当前位置: 首页 > 科技观察

多图证明,Java是按值传递还是按引用传递?

时间:2023-03-22 00:16:30 科技观察

本文转载自微信公众号“Java中文社区”,作者雷哥。转载本文请联系Java中文社区公众号。开篇,揭晓答案。在Java语言中,只有值传递,没有引用传递。解释和证明见正文。说到值传递和引用传递,就不得不提到两个概念:值类型和引用类型。1、值类型通俗的理解,所谓值类型是指Java中的8种基本数据类型:整型:byte、int、short、long浮点型:float、double字符型:char布尔型:boolean从JVM层面来说:所谓值类型是指在赋值时直接在栈(Java虚拟机栈)上产生值的类型,如下图所示:2.引用类型引用类型是指typevaluetype以外的数据类型,如:classinterfacearraystringwrapperclass(Integer,Double...)从JVM层面来说,所谓引用类型就是在初始化时在栈上产生引用,而值是在堆上生成的这些数据类型,如下图所示:3.按值传递(PassByValue)是指方法传递参数时,传递的是原始内容的副本,所以任何文案修改不会影响原内容。实现代码如下:publicclassPassTest{publicstaticvoidmain(String[]args){intage=18;System.out.println("调用方法前:"+age);intTest(age);System.out.println("调用方法后:"+age);}privatestaticvoidintTest(intage){age=30;System.out.println("方法修改为:"+age);}}程序执行结果为:调用前方法:18方法修改为:30调用方法后:18从上面的结果可以看出,修改方法中的参数并没有影响原来的内容。我们称这种传递参数的方式为值传递。4.引用传递引用传递是指方法传递参数时传递的是参数本身,因此对参数的任何修改都会影响原来的内容。模拟“引用传递”的实现代码如下:publicclassPassTest{publicstaticvoidmain(String[]args){char[]name={'雷','兄弟'};System.out.println("调用方法前:"+newString(name));paramTest(name);System.out.println("调用方法后:"+newString(name));}privatestaticvoidparamTest(char[]n){n[1]='上帝';System.out。println("方法修改为:"+newString(n));}}程序执行结果为:调用方法前:雷格方法修改为:雷神调用方法后:雷神由以上结果可知,我们可以看到修改了paramTest方法中的参数后,在main方法中打印参数的时候,发现参数的值也发生了变化,所以好像可以断定好像是“引用传递”在Java中,但事实并非如此。让我们继续。5.判断真假“按引用传递”我们在上面的代码中加一行,如下:.println("调用方法前:"+newString(name));paramTest(name);System.out.println("调用方法后:"+newString(name));}privatestaticvoidparamTest(char[]n){n=newchar[2];//加入这行代码n[1]='God';System.out.println("方法修改为:"+newString(n));}}程序执行结果为:调用方法前:雷哥方法中,修改为:神调用后method:雷哥从上面的结果我们可以看出,当我们在paramTest方法中添加newchar[]的时候,“按引用传递”突然变成按值传递了?为什么?这是因为,在Java语言中,本质上只有值传递,也就是说Java的参数传递只会传递它的副本,而不会传递参数本身。前面引用的“passbyreference”其实只是传递了它的引用副本,如下图:PS:《Java虚拟机规范》中对Java堆的描述是:“所有的对象实例和数组都应该分配在堆上”。所以我们调用newchar[]之后,可以看到n对象有了新的地址,但是原来的内容并没有被修改。如果我们按照引用传递的思路来看的话,无论进行什么样的修改,都会改变原来的内容,所以我们可以更加确定Java语言中只有值传递,如如下图所示:总结通过本文的内容,我们可以得出结论,在Java语言中,只有值的传递,方法传递参数时,传递的只是复制信息,而不传递原始内容。我们也知道基本数据类型会直接在栈上生成,而对象或者数组会在栈和堆上同时生成信息,而在栈上生成的引用会直接指向堆上生成的数据,如图在下图中: