将对象引用传递给java混淆中的方法[重复]

Posted

技术标签:

【中文标题】将对象引用传递给java混淆中的方法[重复]【英文标题】:passing object reference to a method in java confusions [duplicate] 【发布时间】:2021-09-20 06:24:12 【问题描述】:

我很困惑为什么在第一个代码(代码 1)中,myCounter 指向的对象在传递给方法“print”后被更新为值 2。 但是在第二个代码(代码 2)中,str 指向的对象仍然是同一个字面量“This is a string literal”。我认为 str(str 是一个对象引用,就像我认为的 myCounter 一样)经历相同的机制,因为它也被传递给一个方法,所以它不应该像 myCounter 一样更新吗?

这是代码 1:

public class PrimitiveVsReference

private static class Counter 
    private int count;

    public void advance(int number) 
        count += number;
    

    public int getCount() 
        return count;
    


public static void main(String args[])         
    int i = 30;
    System.out.println("value of i before passing to method : " + i);
    print(30);
    System.out.println("value of i after passing to method : " + i);
    
    Counter myCounter = new Counter();
    System.out.println("counter before passing to method : " + myCounter.getCount());// this gives 0
    print(myCounter); 
    System.out.println("counter after passing to method : " + myCounter.getCount());// now this gives 2 after passing into the method "print"


/*
 * print given reference variable's value
 */
public static void print(Counter ctr) 
    ctr.advance(2);


/**
 * print given primitive value
 */
public static void print(int value) 
    value++;


代码 2:

String str = "This is a string literal.";

public static void tryString(String s)

    s = "a different string";


tryString(str); // isn't this here doing the samething as when myCounter is passed to print in Code 1?
System.out.println("str = " + str); // But this here output the original literal "This is a string literal."

有人可以解释发生了什么吗?

【问题讨论】:

这是修改对象内容(代码1)和创建新对象(代码2)的区别。 @MarkRotteveel 所以根据你所说的,user16320675 的第二个答案(没有得到任何投票的解释)是正确的推理。第一个答案(有 2 个赞成票的那个)给出的推理不是正确的答案(即它与不可变或可变无关,对吧?)。这是正确的吗?因为我想了解正确的解决方案。 是的,没错。事实字符串是不可变的与此无关(如果您在代码 1 中的 print 中使用了 ctr = new Counter(),并且 Counter 是一个可变对象,也会发生同样的情况)。 @MarkRotteveel 哦,感谢您指出正确的解决方案。 【参考方案1】:

由于字符串是不可变的(“一旦创建了 String 实例,就永远不会更改 String 实例的内容”),该赋值创建了一个新的字符串对象,该对象是引用的副本现在指向。原始引用仍然指向“这是一个字符串文字。”

您可以尝试使用StringBufferStringBuilder 并看到不同的结果。

【讨论】:

但是 myCounter 怎么样,您能解释一下为什么要更新 myCounter 吗? 你能解释一下“那个赋值创建一个新的字符串对象”是什么意思吗?是哪个任务?还有“引用的副本现在指向”的含义?谢谢 @user16320675 所以它与 str 是否可变无关? str 在这里是一个字符串。但是如果 str 是其他一些类型,说是 A 类型的对象,我们将这个对象 A 传递给方法 tryString(A str) s = str; (所以假设 tryString 接受 A 类型的参数),这是否意味着现在 s在赋值s = str 发生后存储对象str 的地址(即堆内存中的地址)?有人可以解释更多。所以它与可变或不可变无关?对吗? @user16320675 那么你能解释一下为什么在第二个代码中,str 没有得到更新吗?但在第一个代码(代码 1)中,对象 myCounter 得到更新?【参考方案2】:

我将尝试使用 StringBuilder - 一个可变对象 - 基于相关代码发布的 cmets 来说明我的意思。

代码 1

public static void main(String[] args) 
    StringBuilder builder = new StringBuilder("abc");
    System.out.println("before passing to method: " + builder);
    method(builder);
    System.out.println("after passing to method: " + builder);


private static void method(StringBuilder bld) 
  bld.append("def");

应该输出:

before passing to method: abc
after passing to method: abcdef

上面的代码中只有一个StringBuider的实例,正在改变和显示的那个


代码 2

private static final StringBuilder ANOTHER_ONE = new StringBuilder("a different string");

public static void main(String[] args) 
    StringBuilder builder = new StringBuilder("abc");
    System.out.println("before passing to method: " + builder);
    method(builder);
    System.out.println("after passing to method: " + builder);


private static void method(StringBuilder bld) 
  bld = ANOTHER_ONE;  // or bld = new StringBuilder("a different string")

应该输出:

before passing to method: abc
after passing to method: abc

以上代码中有两个StringBuider实例;一个正在显示,另一个被分配到method


可以看出,即使对象是可变的,对参数的赋值也不会体现在调用方法时使用的变量中。实际上它是一个表达式,产生一个值,用于初始化方法的参数——在这个具体的例子中,表达式恰好只是一个变量。

你可以想到s = "a different string"相似1s = new String(new char[] 'a', ' ', 'd', 'i', 'f', 'f', 'e', 'r', 'e', 'n', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g')

1 - 缺少对 intern() 的调用,因此它也被作为所有文字(也更难阅读和输入)进行了实习

【讨论】:

哦,谢谢。我会尝试理解您的代码,因为有时我需要理解。但是,如果那里的解释不正确,为什么人们会赞成 Veke 的第一个答案。 所以我不相信真正的原因是“因为字符串是不可变的”。所以这不是正确的推理。所以我会把你的作为正确的推理。但只是困惑为什么人们现在支持不正确的答案。 这让我更加困惑。

以上是关于将对象引用传递给java混淆中的方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

作为函数参数传递的Java对象[重复]

java 值传递 数组传递

Java Object 引用传递和值传递

Java方法中传递数组与改变数组值的问题

Java方法中传递数组与改变数组值的问题

通过 Java 中的套接字传递对包含在“数据包”对象中的对象的引用