发现传参问题很有趣,所以总结一下。
package Example;
public class Te {
public String name;
public int age;
}
package Example;
public class A {
public static void main(String[] args) {
Te a = new Te();
Te b = a;
a.name = "123";
a.age = 90;
int num = 100;
Integer NUM = 100;
change0(num);
change0(a);
change0(NUM);
System.out.println(a.name);
System.out.println(a.age);
System.out.println(num);
System.out.println(NUM);
}
public static void change0(Te a1) {
a1.name = "ljm";
a1.age = 99;
}
public static void change0(int a1) {
a1 = 99;
}
public static void change0(Integer a1) {
a1 = 99;
}
}
运行结果:
原理解释:
由实验结果可知,int和Integer类型的值在经过函数调用之后值未被改变,而类的值却被改变,为什么呢?
1.int:
大家都知道,java有八个基本类型,int就是其中的一类;在传参的时候,基本类型的参数都是深复制,也就是说在函数里被改变值的变量不是原来的变量num,而是经过深复制的a1,在函数结束时,a1被释放,从头到尾,原变量num都没有被改变过,所以输出num仍为原值100。
int是保存在栈中的,下面是从栈的角度的示图,有助于大家理解。
2.类:
类为引用类型,引用类型在传参时为浅复制,这种设置可大量的节省存储空间。在函数调用的时候,原变量a和复制后的变量a1指向同一内存地址,所以他们都可以改变该内存地址的值。
类中数据是保存在堆中的,下面是从堆的角度的示图,有助于大家理解。
3.Integer:
Integer也是引用类型,但它的结果却和int一样。因为Integer的源码中对int变量的定义是final类型的,值是不能被改变的,而且在函数调用的装箱过程中,调用的是Integer的ValueOf()函数,在这个函数的源码中,返回值是new的一个新对象,所以Integer在传参的时候也是深复制。
对于类的交换问题,也是值得大家注意的一点:
package Example;
public class A {
public static void main(String[] args) {
Te aa = new Te();
aa.age = 100;
Te bb = new Te();
bb.age = 60;
change(aa,bb);
System.out.println(aa.age);
System.out.println(bb.age);
change2(aa,bb);
System.out.println(aa.age);
System.out.println(bb.age);
}
public static void change(Te a1,Te b1) {
Te temp;
temp = a1;
a1 = b1;
b1 = temp;
}
public static void change2(Te a,Te aa) {
Te temp = new Te();
temp.age = a1.age;
a1.age = b1.age;
b1.age = temp.age;
}
}
在类对象交换时,大家很容易理解成常规的交换,就是change函数的样子,但其实aa和bb并未完成任何交换。如图示:
所以,若要交换应该使用change2的方式。
public static void change2(Te a,Te aa) {
Te temp = new Te();
temp.age = a1.age;
a1.age = b1.age;
b1.age = temp.age;
}