1.一道笔试题
这是一道经典的String面试题,猜猜输出结果是多少?
public class StringTest {
String str = new String("good");
char[] ch = {'t', 'e', 's', 't'};
public void change(String str, char ch[]) {
str = "test ok";
ch[0] = 'b';
}
public static void main(String[] args) {
StringTest ex = new StringTest();
ex.change(ex.str, ex.ch);
System.out.println(ex.str);
System.out.println(ex.ch);
}
}
结果是:
good
best
怎么样,有答对吗。为什么是这个结果呢,就关系到了String的不可变性与Java的求值策略。
2.String的不可变性
有了解过Java底层源码的应该都知道,String的存储变量是带final关键字的,这意味的这个字符串是无法被修改的,在它放入堆中字符串常量池(JDK8以后)中后,内存地址以及内容就会被永久确定下来(除非在池中被回收)。
String底层源代码:
// JDK9之前
private final char value[];
// JDK9及之后
private final byte[] value
3.Java值传递的方式
Java的传递很像引用传递(引用传递就是传递自身变量不会拷贝变量副本),但其实是值传递,因为这个传递的过程并不是把原变量传递出去,而是拷贝了原变量的内存地址。
这样说可能非常难懂,我第一次看也是一脸懵*。但是再结合上面的例子看呢。
由于传递的确实是内存地址,但并不是我原本String字符串自身的内存地址,我依然指向我的内存地址。我把内存地址给你了,能不能修改就看你本事了。而Char[]在堆中是没有不可变这个特性的,所以它就会在change(String str, char ch[])方法中被修改了对象数据。
这么理解是不是非常通俗易懂呢?