class OtherObject {
String innerString;
OtherObject(String x) {innerString = x;}
}
class Playground {
public static void mutate(OtherObject toMutate) {
toMutate.innerString = toMutate.innerString.substring(toMutate.innerString.length()/2);
}
public static void mutate(String toMutate) {
toMutate = toMutate.substring(toMutate.length()/2);
}
public static void main(String[] args) {
String helloWorld = new String("Hello, World!");
OtherObject helloWorld2 = new OtherObject("Hello, World!");
mutate(helloWorld);
mutate(helloWorld2);
System.out.println(helloWorld);
System.out.println(helloWorld2.innerString);
}
}
在这个例子中,我通过方法mutate
设置了两个对象,只有一个对象发生了变化,如下所示:
Hello, World!
World!
Process finished with exit code 0
这让我感到困惑,因为如果我没记错的话:
main
中的前一个ArrayList的原因。为什么String helloWorld没有改变?
答案 0 :(得分:2)
您似乎在问这个问题:
public static void mutate(String toMutate) {
toMutate = toMutate.substring(toMutate.length()/2);
}
toMutate
变量是一个局部变量,包含对字符串对象的引用。分配给它仅更改局部变量。它不会更改引用来自的调用方法中的变量。
技术答案是Java参数传递是“按值传递”而不是“通过引用传递”。传递字符串时,您将按值传递字符串引用。您没有传递对在调用者中保存字符串引用的变量的引用。你不能用Java做到这一点。
简而言之,使用您似乎想要的语义在Java中实现void mutate(String)
是不可能的。方法签名需要不同,语义和用法也不同。
对象,当传入方法时传递引用,因此即使不返回,也可以更改对象本身。
你的错误。如果对象可以更改,则可以对其进行更改。 String对象是不可变的。它经过专门设计,因此您无法对其进行更改。
如果您希望Java中的“类似字符串”对象可以更改,则可以使用StringBuilder
或StringBuffer
对象。 (有关详细信息及其之间的差异,请参阅javadoc。)
答案 1 :(得分:0)
您需要仔细考虑这些示例中的更改内容。
写作时
toMutate.innerString = toMutate.innerString.substring(toMutate.innerString.length()/2)
您要更改innerString
实例的字段OtherObject
。这就是改变一个对象的意思;改变它的领域。
另一方面,当你写
toMutate = toMutate.substring(toMutate.length()/2);
您没有更改任何对象的字段。您所做的只是重新分配变量。因为Java总是按值传递,即使它是传递的对象引用,该行也没有任何效果。
答案 2 :(得分:-1)
因为字符串在Java中是不可变的。也就是说,一旦创建,就不能改变相同的String对象。在内部,Java使用java.lang.StringBuffer
来更改字符串,而不是在String对象本身中进行更改。
这是因为,一旦用Java创建的字符串,就无法自行更改。在mutate(String)
方法中创建单独的String对象。你的原始字符串仍然存在。