字符串作为参考类型

时间:2018-12-07 11:40:05

标签: java string reference-type

我刚开始学习Java,但是我才刚刚开始了解值类型与引用类型。据我了解,字符串是引用类型。但是,与其他引用类型不同,我可以打印String而不用打印字母和数字的某种奇怪组合。这是为什么?而且,说我有代码

String s1 = "x";
String s2 = s1;
s1 = "xyz";
System.out.println(s2);

它将打印“ x”,而不是“ xyz”,即使我更改了s2所指的对象。当我更改一个数组时,这不会发生。为什么字符串很特殊?

2 个答案:

答案 0 :(得分:5)

  

但是,与其他引用类型不同,我可以打印String而不用打印字母和数字的某些奇怪组合。为什么会这样?

因为与其他许多类型一样,字符串会覆盖Object.toString(),并返回另一个字符串,而不是默认实现返回的字符串(当然,它会返回自身)。

  

当我更改一个数组时,不会发生这种情况。

您将“为变量分配新值”与“更改对象的状态”混为一谈。如果您执行的操作与使用数组执行的操作相同,则将具有相同的行为:

char[] s1 = new char[] {'x'};
char[] s2 = s1;
s1 = new char[] {'x', 'y', 'z'};
System.out.println(Arrays.toString(s2));

将不同的数组分配给s1时,不会改变变量s2指向的内容。

当然,如果s1和s2指向同一数组,而您修改了该数组,则它们都将始终指向同一修改后的数组:

char[] s1 = new char[] {'x'};
char[] s2 = s1;
s1[0] = 'y';
System.out.println(Arrays.toString(s2));

答案 1 :(得分:1)

看看Object#toString的实现:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

现在,这是String#toString的实现:

public String toString() {
    return this;
}

调用System.out.println(String s)直接打印内部char数组表示形式,而System.out.println(Object o)的实现如下:

public void println(Object x) {
    String s = String.valueOf(x);
    synchronized (this) {
        print(s);
        newLine();
    }
}

最后,实现String#valueOf

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

由于此,在未覆盖System.out.println方法的对象上调用toString导致调用Object#toString,该方法返回由hashCode附加的类的名称。

关于第二个问题,请参见Java String variable setting - reference or value?