自己的理解,如有理解的不对的地方,欢迎指出!
大家都知道的,在Java中,是这样子的:
- 基本数据类型------- 按值传递
- 包装类型------------ 按引用传递
举例:
public static void main(String[] args) {
int a = 1;
StringBuffer s1 = new StringBuffer("hello");
System.out.println("原始的a:"+a+" 原始的s1:"+s1);
change(a,s1);
System.out.println("后来的a:"+a+" 后来的s1:"+s1);
}
private static void change(int a, StringBuffer s1) {
a = 2;
s1.append(" world!");
}
结果:
原始的a:1 原始的s1:hello
后来的a:1 后来的s1:hello world!
完美验证上述观点!
那。。,再看一例
public static void main(String[] args) {
Integer a = 1;
Integer b = a;
System.out.println("原始的a:"+a+",hashcode:"+a.hashCode()+" 原始的b:"+b+",hashcode:"+b.hashCode());
b++;
System.out.println("后来的a:"+a+",hashcode:"+a.hashCode()+" 后来的b:"+b+",hashcode:"+b.hashCode());
String str1 = "lalalala";
System.out.println("原始的str1:"+str1+" , hashcode:"+str1.hashCode());
changeStr(str1);
System.out.println("后来的str1:"+str1+" , hashcode:"+str1.hashCode());
}
private static void changeStr(String str1) {
System.out.println("before changeStr: "+str1+" , hashcode:"+str1.hashCode());
str1 = "xixixixi";
System.out.println("after changeStr: "+str1+" , hashcode:"+str1.hashCode());
}
结果:
原始的a:1,hashcode:1 原始的b:1,hashcode:1
后来的a:1,hashcode:1 后来的b:2,hashcode:2
原始的str1:lalalala , hashcode:-1676657068
before changeStr: lalalala , hashcode:-1676657068
after changeStr: xixixixi , hashcode:918596164
后来的str1:lalalala , hashcode:-1676657068
问题来了: 按引用传递,为什么没有变?
原因:
- 基本类型的包装类型都是不可变量,所以上面的b,在经过b++后,输出来的b的值是2,但是现在的b已经不是原来的b了,可以看得到,hashcode是不一样的【Integer 内部对hashcode进行了重写,hashcode就是它的值】
- String类型是引用类型,同样他也是不可变量,传参的时候传的是引用没有错,但是要明白,引用也是按值传递的。也就是说传过来的str1是引用,它也是一个值,这个值是不可变的。下面的 str1 = “xixixixi”;,改变的不是str1,而是重新开辟了一个地址,然后赋值给str1,所以在这个函数里面,似乎str1变了,但是这个str1已经不是原来的str1了。由于string是不可变量,所以原始的str1并没有发生改变
再看一个例子:
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer("hello");
StringBuffer s2 = new StringBuffer("hello");
System.out.println("原始的s1:"+s1+",hashcode:"+s1.hashCode()+" 原始的s2:"+s2+",hashcode:"+s2.hashCode());
change(s1,s2);
System.out.println("后来的s1:"+s1+",hashcode:"+s1.hashCode()+" 后来的s2:"+s2+",hashcode:"+s2.hashCode());
}
private static void change(StringBuffer ss1, StringBuffer ss2) {
ss1.append(" world!");
ss2 = ss1;
System.out.println("change: ss1: "+ss1+",hashcode:"+ss1.hashCode()+" ss2: "+ss2+",hashcode:"+ss2.hashCode());
}
结果:
原始的s1:hello,hashcode:1163157884
原始的s2:hello,hashcode:1956725890
change: ss1: hello world!,hashcode:1163157884
ss2: hello world!,hashcode:1163157884
后来的s1:hello world!,hashcode:1163157884
后来的s2:hello,hashcode:1956725890
这又是为什么?StringBuffer并不是不可变类啊?为什么s2的值并没有改变?
还是那句话:引用也是按值传递的
解释:传递s1,s2的引用就可以理解为传递了两个地址0X11111111,0X22222222,而且这两个地址是按值传递的(也就是传递了两个值0X11111111,0X22222222)。
在调用ss1.append(" world!");时,会修改ss1所指向的字符串的值,因此会修改s1的值。但是在执行ss2 = ss1;时,只会修改ss2的值而对s2毫无影响。
简单的说:如果时引用类型的化,你是不是改变了我指向的地方(也就是老家),如果直接改变了老家的值,就是变了,如果你改变了是我的值,就和我的老家没有关系,就不会改变老家的值。