为什么在这个例子中String helloWorld没有改变?

时间:2016-04-09 02:12:49

标签: java string

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

这让我感到困惑,因为如果我没记错的话:

  • 对象,当传递给方法传递引用时,因此即使不返回,也可以更改对象本身
  • 这就是我可以将ArrayList传递给方法并对其进行操作而不必返回相同的ArrayList并将其分配给main中的前一个ArrayList的原因。
  • String是一个Object。

为什么String helloWorld没有改变?

3 个答案:

答案 0 :(得分:2)

您似乎在问这个问题:

public static void mutate(String toMutate) {
    toMutate = toMutate.substring(toMutate.length()/2);
}

toMutate变量是一个局部变量,包含对字符串对象的引用。分配给它更改局部变量。它不会更改引用来自的调用方法中的变量。

技术答案是Java参数传递是“按值传递”而不是“通过引用传递”。传递字符串时,您将按值传递字符串引用。您没有传递对在调用者中保存字符串引用的变量的引用。你不能用Java做到这一点。

简而言之,使用您似乎想要的语义在Java中实现void mutate(String)是不可能的。方法签名需要不同,语义和用法也不同。

  

对象,当传入方法时传递引用,因此即使不返回,也可以更改对象本身。

你的错误。如果对象可以更改,则可以对其进行更改。 String对象是不可变的。它经过专门设计,因此您无法对其进行更改。

如果您希望Java中的“类似字符串”对象可以更改,则可以使用StringBuilderStringBuffer对象。 (有关详细信息及其之间的差异,请参阅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对象。你的原始字符串仍然存在。