将对象引用传递给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 实例的内容”),该赋值创建了一个新的字符串对象,该对象是引用的副本现在指向。原始引用仍然指向“这是一个字符串文字。”
您可以尝试使用StringBuffer
或StringBuilder
并看到不同的结果。
【讨论】:
但是 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"
相似1与s = new String(new char[] 'a', ' ', 'd', 'i', 'f', 'f', 'e', 'r', 'e', 'n', 't', ' ', 'S', 't', 'r', 'i', 'n', 'g')
。
1 - 缺少对 intern()
的调用,因此它也被作为所有文字(也更难阅读和输入)进行了实习
【讨论】:
哦,谢谢。我会尝试理解您的代码,因为有时我需要理解。但是,如果那里的解释不正确,为什么人们会赞成 Veke 的第一个答案。 所以我不相信真正的原因是“因为字符串是不可变的”。所以这不是正确的推理。所以我会把你的作为正确的推理。但只是困惑为什么人们现在支持不正确的答案。 这让我更加困惑。以上是关于将对象引用传递给java混淆中的方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章