严格来说在Java中不存在所谓的引用传递,只是在方法的传递过程中,传递的是值的副本还是引用地址的副本。
相关总结:
- 参数类型是基本类型,那么会将传过来的参数复制一个副本,传入方法,也就是传递了参数的值。如果在方法中改变了副本的值,不会影响原始的值.
public static void func(int a){
a=20;
System.out.println(a);
}
public static void main(String[] args) {
int a=10;//变量
func(a);
System.out.println(a)
}
结果是:
20
10
- 参数类型是引用类型,那么传过来的同样是参数的副本,只是这个副本存放的是参数的地址。如果在函数中没有改变这个副本的地址,即不对该参数的地址进行改变(不重新new一个对象赋值给参数),而只是改变该地址中的属性值,那么这种改变同样会反馈到原参数中。
public static void func(User user) {
user.setName("ss");
System.out.println(user.getName());
}
public static void main(String[] args) {
User user = new User();
user.setName("ww");
System.out.println(user.getName());
func(user);
System.out.println(user.getName());
}
结果:
ww
ss
ss
如果在函数中改变了副本的地址,如重新new一个,那么副本就指向了一个新的地址,此时传入的参数还是指向原来的地址,所以再改变时就不会影响原来的值。
public static void func(User user) {
//修改副本,指向了一个新的地址
user = new User();
user.setName("ss");
System.out.println(user.getName());
}
public static void main(String[] args) {
User user = new User();
user.setName("ww");
System.out.println(user.getName());
func(user);
System.out.println(user.getName());
}
结果:
ww
ss
ww
此外,对于基本类型的包装类和String类型,这种原来就失效了,这些虽然同样是引用类型,但是在方法中进行改变时同样不会作用在原参数中,因为在这些类均为final修饰的变量。
private final char value[];
private final int value;
一经赋值不可更改,一旦在方法中试图修改该类的属性,就会导致对该类进行重新赋值,即改变了参数的地址,这就导致副本指向了新的地址,因此虽然为引用类型,但修改时仍不会对原值造成影响,造成值传递的现象。
了解这些可以使你的代码变得更加合理,比如当一个集合是一个对象中的属性时,你想去更改集合中的元素,这时只需要从对象中get出来,改变元素,无需再set回去,因为引用传递,而如果是String类型的,你get出来后还需要set回去。比如,当你想要做方法的抽取时,对于引用类型的一些处理,是不需要方法有返回值的,因为引用传递,自然会影响传入的参数的值。