Featured image of post Java是值传递还是引用传递

Java是值传递还是引用传递

进入正题之前先简单说说值传递引用传递的区别

按值调用(call by value)表示方法接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可以修改传递引用所对应的变量值,而不能修改传递值调用所对应的变量值。

下面是我用Rust来做的一个简单示范。

可以看到,虽然call_by_value函数和call_by_reference函数都将接收到的参数的值修改为了12450,但是由于call_by_reference函数接收的是by_ref变量的引用,所以在函数内修改by_ref的值会影响到函数外部的by_ref变量,而call_by_value函数接收的是by_val变量的值,所以在函数内修改by_val的值不会影响到函数外部的by_val变量。

对于基本数据类型, Java是值传递还是引用传递?

看下图

可以看到,在函数内的修改并没有影响到函数外部的num,所以对于基本数据类型, Java是值传递

对于基本数据的包装类, 也是值传递

对于引用类型, Java是值传递还是引用传递?

看下图

可以看到,在函数内的修改已经影响到了函数外部的lis,这似乎证明了对于引用类型, Java是引用传递

但是, 我们都知道, 对于引用类型, 变量保存的是指向其堆内存的地址, 也就是说, 如果将引用类型赋值给另一个变量, 修改当前变量的值, 另一个变量也会被改变, 如何理解呢? 请看下图

可以看到, 虽然只是修改了lis而没有去修改copy, 但由于liscopy指向的是同一内存地址, 所以对lis的修改也会体现在copy

回到正题,既然知道了lis变量是对于堆内存中ArrayList的引用, 那么之前的结果就不成立了, 修改changeValue方法再看

可以看到, 在函数中将一个新的ArrayList的引用赋值给了lis变量, 但是函数外的lis变量依然指向的是原来的ArrayList, 所以得出结论, 对于引用类型, Java也是值传递

结论

无论是对于基本数据类型还是引用类型,Java都是值传递,但要注意的是,对于引用类型,变量保存的是其引用,所以通过函数接收的变量去修改其指向的引用类型,也会影响到函数外的变量,而给函数接收的变量赋予新的引用,则不会影响到函数外的变量

Licensed under CC BY-NC-SA 4.0