Java是值传递还是引用传递?


首先,我们要知道值传递和引用传递的区别; 然后要了解Java中基本类型和引用类型的区别,以及Java中"="的作用; 最后我们再来判断Java到底是值传递还是引用传递。

一、值传递和引用传递

    值传递:是指在调用函数时将实际参数复制一份到函数中,在函数中对参数修改的话,不会影响到实际参数。 引用传递:是指在调用函数时将实际参数的地址传递到函数中,在函数中对参数进行修改的话,将影响到实际参数。
值传递 引用传递 区别 创建副本 不创建副本 结果 函数中无法改变原始对象 函数中可以改变原始对象

二、基本类型和引用类型

    基本类型:对于基本数据类型,值就直接保存在变量里面。例如图中的num,10直接保存在变量中。 引用类型:对于引用数据类型,变量保存的不是对象,而是对象的地址值(地址值是int / long类型的)。一般也称这个为“引用”,对象中保存着实际的内容,而引用则指向这个对象。

三、赋值运算符"="的作用

    基本类型:对于基本类型,赋值运算符会直接改变变量的值。 引用类型:对于引用类型,赋值运算符会直接改变变量中的地址值。 但是原来的对象并不会被改变 。

若执行如下语句:

num = 20;
str = "world";
    当执行 num = 20 时,赋值运算符会直接改变变量 num 的值,将其改为 20 ; 当执行 str = "world" 时,赋值运算符会直接改变变量 str 中的地址,地址从 0x10 变为了 0x20 ,但是原来的对象 "Hello" 并没有被改变。(由于没有任何引用指向这个对象,所以在GC时会被JVM当作垃圾回收掉)

四、调用方法时发生了什么

1、基本类型

我们先给 num 赋值为10,然后调用方法 fun(int value) 在fun方法中,将 value 改为20 最后我们在最初的方法中输出num,发现它的值还是10

原因:因为调用fun()方法后,num 和value的值都是10,但valule是num的副本,所以在方法fun()中改变value的值后,原方法中num的值不会受到任何影响。

2、引用类型:提供了改变自身值的方法

  1. 我们先创建StringBuilder对象sb,并初始化它的值为 "Hello"
  2. 然后调用fun(StringBuilder builder)方法
  3. 在方法fun()中,我们使用对象本身的方法append来修改builder的值
  4. 回到最初的方法中,打印sb输出"Hello world"。我们发现sb的值被改变了

原因:调用fun()方法后,sb和builder其实都指向了同一个对象(如下图),此时builder使用方法改变值,其实就是对这个对象本身做了修改。由于sb也指向了这个对象,所以打印出的sb并不是"Hello",而是"Hello world"。

3、引用类型:提供了改变自身值的方法,但是不使用这个方法,而是使用了赋值运算符(=)

  1. 我们先创建StringBuilder对象sb,并初始化它的值为 "Hello"
  2. 然后调用fun(StringBuilder builder)方法
  3. 在方法fun()中,我们创建一个新的StringBuilder对象并初始化为" world",并使用赋值运算符
  4. 回到最初的方法中,打印sb输出"Hello",sb的值并没有被改变

原因:调用fun()方法后,sb和builder都指向了同一个对象。但是在fun()方法中创建了一个新对象,并使用赋值运算符(=),导致builder的地址被替换掉了。此时sb和builder指向的是不同的对象。 打印sb时,由于原对象"Hello"并没有被修改,所以sb的值并没有改变。


五、总结

在Java中:

    如果参数是基本类型,传递的是基本类型的 字面量值 的拷贝; 如果参数是引用类型,传递的是该变量所引用的对象在堆中 地址值 的拷贝。

所以,Java中只有值传递。


参考文章

经验分享 程序员 微信小程序 职场和发展