在讨论这个问题之前,首先需要看一段代码:
Mode类:
package com.ragentek;
public class Mode {
public static int m1 = 4;
public static int getM1() {
return m1;
}
public static void setM1(int m1) {
Mode.m1 = m1;
}
}
Test类:
package com.ragentek;
import com.ragentek.Mode;
public class Test {
private static int a = 4;
public static void main(String[] args) {
Test test = new Test();
Mode mode = new Mode();
test.changeTest(4);
System.out.println("传基本类型a,a="+a);
test.changeTest(mode.m1);
System.out.println("传引用类型mode.ml,mode.m1="+mode.m1);
test.changeTest(mode);
System.out.println("传对象mode,mode.m1="+mode.m1);
}
private void changeTest(int a){
a = 5;
}
private void changeTest(Mode mode){
mode.m1 = 5;
}
}
运行结果如下:
传基本类型a,a=4
传引用类型mode.ml,mode.m1=4
传对象mode,mode.m1=5
由以上现象可以分析,java是分值传递和引用传递的。对于基本类型和引用类型,是值传递的,而对于对象,是引用传递。
当基本类型的变量被当作参数传递给方法时,JAVA虚拟机所做的工作是把这个值拷贝了一份,然后把拷贝后的值传递到了方法的内部。我们可以看上面的方法:
private void changeTest(int a){
a = 5;
}
在这个方法中的a和private static int a = 4;此处的全局变量a具有相同的值4,他们却是两个不同的变量,changeTest(int a)方法中的变量a是由JAVA虚拟机创建的作用域在change(int a)方法内的局部变量,在这个方法执行完毕后,它的生命周期就结束了。
那么对于引用类型,java虚拟机又是怎样处理的呢?同样,它会拷贝一份这个变量所持有的引用,然后把它传递给JAVA虚拟机为方法创建的局部变量,从而这两个变量指向了同一个对象。
有一种说法是当一个对象或引用类型变量被当作参数传递时,也是值传递,这个值就是对象的引用,因此JAVA中只有值传递,没有引用传递。我个人很认同这种说法。当一个对象被当作参数传递时,其实传递的是这个对象的首地址。我们对这个对象中一些属性的操作,其实就是基于这个首地址执行的。