public static void f(Integer i){
i = 2;
//或者 i = new Integer(2)
//这里虽然涉及常量池,但是不考虑这个先,跟这个没关系;
}
public static void main(String[] args) {
Integer i = 1;
f(i);
System.out.println(i);
}
这段代码输出什么,很多人可能想,Integer是引用类型, 传递过去改变了值为2,因此输出为2,然而结果确是1
然后有人说是因为Integer中的值无法改变,因为它里面的value是final类型的,改变它的值会重新生成一个对象,这个是对应下面这种情况的
//输出1,2,因为Integer不可变,++b重新生成了一个对象,跟原来无关
Integer a = 1;
Integer b = a;
++b;
System.out.println(a);
System.out.println(b);
那么我们再来看看下面这个。
class Person{
public int age;
}
public static void f2(Person src){
Person dst = new Person();
dst.age = 2;
src = dst;
}
public static void main(String[] args) {
Person p = new Person();
p.age = 1;
f2(p);
System.out.println(p.age);
}
这次Person是可变的了吧。
结果输出: 1
所以这跟Integer是否可变没有关系,不是因为Integer值不可变所以结果没有改变,而是因为Integer的值不可变,导致生成了新的对象并赋值,以下为个人的理解,如有错误,还请指正
虽然是说叫引用传递,可以改值,但是这个改值的意思是
例如刚刚的Person类,你可以写 p.age = 2;这样改值,而不是直接改变p = new Person()
就比如c语言,这里的引用好像是c语言的一级指针 Person *t = &p; (ps,声明指针的时候写成*t,实际上是t是指针,而不是*t是指针)
你把t当作参数进行传递,实际上是传递了p的内存地址,然后,你在函数里面 ,可以改变 *t,但是你却无法改变t。
用c语言递归构建一棵树,如果不用返回值的形式的话,那么传进函数就是(**t)而不是(*t),因为只有这样才能真正改变t的值
public static void swap(List<Integer> list, int i, int j){
Integer src = list.get(i);
Integer dst = list.get(j);
Integer temp = src;
src = dst;
dst = temp;
}
这段代码可以交换list中2个成员的值吗,不可以
个人理解:
在使用get方法之后,相当于又建立了一个对对象的引用,你在这里对它进行赋值,是改变的你本身的指向,也就是你不引用这个对象了,去引用另一个对象,这样对原对象没有任何改变,自然也无法交换他们的值了;
还是用c语言指针的例子
在这里 list也就是装了一个个的指针,指针中是内存地址
比如你要获取list中的一个指针, *p,那么这里的get方法也就相当于
XXX * q = p;
然后你再对q进行赋值(q = ),是改变了q的指向,跟p是没有任何关系的,
除非你写 *q = 1; 那么这样*p的值也跟着改变了,因为他们指向同一块内存空间
其实如果list里面不是Integer,是其他对象,你要改对象的属性,可以这样写
int temp = p.age;
temp = p.age;
p.age = q.age;
q.age = temp;
这样是可以的。