基本数据类型的包装类型作为参数传递,以及其他引用类型作为参数传递,以及List中值的交换的一些问题

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类型的,改变它的值会重新生成一个对象,这个是对应下面这种情况的

//输出12,因为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是否可变没有关系,以下为个人的理解,如有错误,还请指正

虽然是说叫引用传递,可以改值,但是这个改值的意思是
例如刚刚的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;
这样是可以的。

猜你喜欢

转载自blog.csdn.net/a1065712890/article/details/79735006