哪有什么引用传递,所有都是值传递
经常看到有人说什么值传递、引用传递,其实都是值传递,区别不过是传的值的类型罢了。
传值方式
java传值有且只有一种方式,将参数的“值”复制后传入,这个“值”是指变量名所对应的地址中存放的值,对于值类型和对象类型,由于地址中存放的东西不同,因此表现有所不同:
- 对于8种值类型,其存放的就是本身的值,因此表现为将值传递到函数中,修改后的值对原值无影响。
- 对于对象来说,其存放的是对象头,里面包含了对象的类型、首地址等。将对象头的值传递到函数中,其仍然能正确指向对象本身。
传递的是值的拷贝,而非其本身
值类型
对于值类型来说
7++;
这种无疑是错误的,因为不能对常量进行修改。任何一个IDE都会报错。

但如果将其作为参数传入
public class ObjTest {
public static void main(String[] args) {
inc(7);
}
private static void inc(int a) {
a++;
System.out.println(a);
}
}
那么就不会报错,并且输出8。这是因为在传递到函数里面的并不是常量7,而是一个拷贝int a = 7,而a是一个int类型的变量,因此可以自增。
对象
而对于对象来说,同样如此。
public class ObjTest {
public static void main(String[] args) {
inc(7);
Node n1 = new Node();
f1(n1);
System.out.println("n1 = " + n1);
}
private static void f1(Node node) {
node.a++;
node.b += 2;
node.c += 3;
node.d = new int[]{1, 5};
// 在此设置断点2
node = new Node();
node.a = -1;
node.b = -2;
node.d[0] = 3;
System.out.println("node = " + node);
}
private static void inc(int a) {
a++;
System.out.println(a);
}
}
public class Node {
public int a;
public int b;
public int c;
public int[] d = new int[2];
}
在执行到断点1的时候,如下图所示,可以看到,n1的所有值都为默认值,地址为0x704

在执行到断点2(此行未执行)时,如下图所示,可以看到,node指向的地址仍为@704,值已经进行了对应的修改

继续执行到函数结束,可以看到node指向了@708,属性的值变为了新的值。

结束子函数,回到主函数中,可以看到n1的所有属性都与node指向@704时相同

可见,同值类型的变量相同,传入子函数的对象头node并不是主函数中的对象头n1本身,而是它的一个拷贝,他们指向同一个对象@704,无论是通过n1,还是初始的node,都可以对@704进行操作(调用方法,修改属性),因而好像和值类型的传递有所不同。但如果修改node本身的值,令其指向@708,这对n1没有任何影响,n1依然指向@704。此后通过node修改对象的值,修改的是@708的值,与@704没有任何关系,因此也对主函数中的n1没有任何影响。
因此,所谓引用传递,不过是值是引用(或者说指针)的值传递。

浙公网安备 33010602011771号