3.值传递
值传递(Pass By Value)指的是方法传参时,传递的是原内容的副本,因此对副本进行如何修改都不会影响原内容。
实现代码如下:
public class PassTest { public static void main(String[] args) { int age = 18; System.out.println("调用方法前:" + age); intTest(age); System.out.println("调用方法后:" + age); } private static void intTest(int age) { age = 30; System.out.println("方法中修改为:" + age); } }
程序的执行结果为:
调用方法前:18
方法中修改为:30
调用方法后:18
从上述结果可以看出,在方法中修改参数并未影响原内容,我们把这种传参方式称之为值传递。
4.引用传递
引用传递(Pass By Reference)指的是方法传参时,传递的是参数本身,因此对参数进行任意修改都会影响原内容。
模拟“引用传递”的实现代码如下:
public class PassTest { public static void main(String[] args) { char[] name = {'磊', '哥'}; System.out.println("调用方法前:" + new String(name)); paramTest(name); System.out.println("调用方法后:" + new String(name)); } private static void paramTest(char[] n) { n[1] = '神'; System.out.println("方法中修改为:" + new String(n)); } }
程序的执行结果为:
调用方法前:磊哥
方法中修改为:磊神
调用方法后:磊神
从上述的结果可以看出在 paramTest
方法中修改了参数之后,在 main
方法中再打印参数时,发现参数的值也跟着发生了改变,那么似乎我们可以得出结论,Java 中貌似也有“引用传递”,然而实事并如此,我们接着看。
5.真假“引用传递”
我们给上面的代码添加一行,如下所示:
public class PassByValue { public static void main(String[] args) { char[] name = {'磊', '哥'}; System.out.println("调用方法前:" + new String(name)); paramTest(name); System.out.println("调用方法后:" + new String(name)); } private static void paramTest(char[] n) { n = new char[2]; // 添加此行代码 n[1] = '神'; System.out.println("方法中修改为:" + new String(n)); } }
程序的执行结果为:
调用方法前:磊哥
方法中修改为:神
调用方法后:磊哥
从上述结果可以看出,当我们在 paramTest
方法中添加 new char[]
之后,“引用传递”就突然变值传递了?为什么?
这是因为,在 Java 语言中本质上只有值传递,也就说 Java 的传参只会传递它的副本,并不会传递参数本身。
前面那个带引号的“引用传递”其实只是传递了它的引用副本,如下图所示:
PS:《Java虚拟机规范》中对 Java 堆的描述是:“所有的对象实例以及数组都应当在堆上分配”。
所以我们在调用 new char[]
之后,可以看出 n
对象有了新地址,而原内容并未被修改,如果按照引用传递的思路来看的话,不管执行任何方式的修改都会改变原内容,因此我们可以更加确认 Java 语言中只有值传递,如下图所示:
总结
通过本文的内容,我们可以得出:在 Java 语言中只有值传递,方法传参时只会传递副本信息而非原内容。我们还知道了基础数据类型会直接生成到栈上,而对象或数组则会在栈和堆上都生成信息,并将栈上生成的引用,直接指向堆中生成的数据,如下图所示: