public static void main(String[] args) throws Exception {
String str="aaaaaaaa";
change(str);
System.out.println(str);
}
public static void change(String str){
str="bbbbbbb";
}
结果是aaaaa,而不是改变过的bbbbb.
解释:
对象是传引用(准确说应该是指针,Java 中没有C 意义上的引用),但是如果引用的是个String对象,情况就不同,因为String 一旦创建就不能改变,这才是关键(本质)。
在change 方法中给该方法的局部变量str 重新赋值时,因为str 指向的位置是String 常量池,是不能改变的,所以只能产生一个新的String 对象,change 方法中的str 指向新的对象,而main 方法中的str 变量还是指向之前产生的对象。
这跟一般的传引用是不一样的,因为一般的引用可以改变其指向的地址上的对象值,所以传来传去如果大家还是指向同一个地址,一改全部都改变了。
可以用StringBuffer 试试,结果和你预期的就会一致。如下面的代码
public static void main(String[] args) throws Exception {
StringBuffer str=new StringBuffer("aaaaaaaa");
change(str);
System.out.println(str);
}
public static void change(StringBuffer str){
str=str.replace(0, str.length(), "bbbbbbbb");
}
也就是说,如果修改了引用指向的地址的内容,所有指向该地址的引用都会受到影响,这才是传引用的根本所在。
使用String s="" 的方式产生的String 对象会被放入String 常量池中,而String 常量池中相同的String 对象只会有一个Copy ,故,public static void main(String[] args) throws Exception {
String str1="aaaaaaaa";
String str2="aaaaaaaa";
System.out.println(str1==str2);
}
将输出true. 而使用new String 产生的对象就跟一般的对象一样,会在普通的Heap 中,此对象会同时被加入String常量池(不是很好验证),
public static void main(String[] args) throws Exception {
String str1=new String("aaaaaaaa");
String str2=new String("aaaaaaaa");
System.out.println(str1==str2);
}
将输出false.