引言
这个问题比较基础,但是也有必要一提,全当再复习一下吧。java里到底是值传递还是引用传递呢?如果是引用传递,好像也能解释清楚"一个对象被传入方法,方法中对对象属性的修改会影响外层对象的值"。如果是值传递也有点说不过去,如果在方法内对这个对象重新初始化,却对外层对象没有任何影响。带着这几个疑问来看一看吧!
测试一下
public static void main(String[] args) {
int index = 1;
change(index);
System.out.println(index);
}
private static void change(int index) {
index = 3;
}
结果是1
,因为传入的是基本类型变量,方法内的index=3
赋值操作不影响外层的输出。那么换成引用类型呢?
public static void main(String[] args) {
Inner inner = new Inner();
inner.setId(32);
inner.setUserName("jerrik");
printDetail(inner);
System.out.println(inner);
}
private static void printDetail(Inner inner) {
inner.setId(27);
}
结果是27 - jerrik
,无论是值传递还是引用传递都可以解释。再来一个测试程序验证一下:
public static void main(String[] args) {
Inner inner = new Inner();
inner.setId(32);
inner.setUserName("jerrik");
change(inner);
System.out.println(inner);
}
private static void change(Inner inner) {
inner = new Inner();
}
这里输出:32 - jerrik
。这下可以解释清楚了,如果inner对象作为值传递的参数,方法内将该inner置空,则应该输出空值
才对,所以可以得出结论:java并不是使用对象的值作为传递的
。如果是引用传递,则是将外层引用重新指向了一个新地址,也应该输出空值
。那到底传递是什么呢?
权威依据
《JAVA核心技术》中讲到"java程序设计语言总是采用值调用。也就是说,方法得到的是所有参数值的一个拷贝,方法不能修改传递给它的任何参数变量的内容。"
说明传递的并不是对象的值,而是重新创建了一份拷贝进行传入,那到底是对象的拷贝还是引用的拷贝呢?如果是对象的拷贝,在堆中则会存在两个Inner对象,那么对拷贝出来的对象进行设值不会影响外层,但是和事实刚好相反,所以排除是对象的拷贝。那么就只能是栈内存地址的拷贝,使它们同时指向堆内的同一个地址,所以可以通过set
来修改外层对象的值,即使通过inner = new Inner();
也只会使这份拷贝出来的新地址指向这个新对象,而不会影响原来的对象。
结论
当发生方法调用的时候,传入的是外层对象栈内存地址的一份拷贝,也是一个数值,指向的还是同一块堆内存,所以java采用的不是引用传递而是值传递。最后,本文是根据个人理解整理的,如有勘误请多谅解!