我正在经历这个出色的article Jon Skeet
的 Java 引用语义
,他指出
We assume the presence of a procedure named f that takes a formal parameter s. We call that function giving it an actual parameter g.
The calling code:
f( g )
The function:
procedure f( s ) begin -- body of the procedure end;
All object instances in Java are allocated on the heap and can only be accessed through object references. So if I have the following:
StringBuffer g = new StringBuffer( "Hello" );
The variable g does not contain the string "Hello", it contains a reference (or pointer) to an object instance that contains the string "Hello".
So if I then call f( g ), f is free to modify its formal parameter s to make it point to another StringBuffer or to set it to null. The function f could also modify the StringBuffer by appending " World" for instance. While this changes the value of that StringBuffer, the value of that StringBuffer is NOT the value of the actual parameter g.
我的理解可能是错误的。下面的程序确实更改了传递给该方法的 Stringbuffer
public class MutabilityStringBuffer {
public static void main(String[] args){
StringBuffer sb = new StringBuffer("hello");
System.out.println("String before append: "+ sb.toString());
addString(sb);
System.out.println("Sting after append "+ sb.toString());
String s = "hello";
System.out.println("String before append: "+ s);
addString(s);
System.out.println("Sting after append "+ s);
}
public static void addString(StringBuffer word){
word.append(" world!");
}
public static void addString(String word){
word+=" world!";
}
}
当然,乔恩·斯基特不会错。但我看到 Stringbuffer 可以通过将其传递给方法来更改,因为 stringbuffer 是可变的,这与 Skeet 发布的内容有点矛盾。请在这里澄清我的理解。
谢谢
最佳答案
查看评论
StringBuffer sb = new StringBuffer("hello"); // sb holds reference
System.out.println("String before append: "+ sb.toString()); // you print the value
addString(sb); // you use the reference to append to the StringBuffer
System.out.println("Sting after append "+ sb.toString()); // you print the value
String s = "hello"; // s holds a refernece
System.out.println("String before append: "+ s); // you print its value
addString(s); // // the word variable would hold a new reference inside the method
System.out.println("Sting after append "+ s); // you print its value
在这里
public static void addString(String word){
word+=" world!";
}
传递给 word
的引用的原始值当您重新分配它时会发生变化
word+=" world!";
事情是这样的
String word = [copy of value of the argument's reference];
word = word.toString() /* toString() is unnecessary, but just to make the point */ + " world";
其中字符串连接的结果是一个新的字符串对象,因此是一个新的引用。
如下
public static void addString(StringBuffer word){
word.append(" world!");
}
您访问 word
引用的对象,调用该对象上的方法,该方法在内部修改 char[]
。因此,您更改了对象的值,而不是引用的值。更改引用看起来像
public static void addString(StringBuffer word){
word = new StringBuffer("Answer to the Ultimate Question of Life, the Universe, and Everything: ");
word.append("42");
}
append
在新的 StringBuffer
上执行对象,而不是您作为参数传递的对象,证明对象是按值传递的。
关于java - 重新审视 Jon Skeet 在他的文章中发布的 Java 中的按值传递语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18774339/