写点什么

天真,居然还有人认为 java 的参数传递方式是引用传递 (1)

用户头像
极客good
关注
发布于: 刚刚

public static void main(String[] args) {


int a = 1;


dosomthing(a);


System.out.println("主函数 a 的值 = "+a);


}


private static void dosomthing(int a) {


a = a-1;


System.out.println("修改过后,a = "+a);


}


}


这是一个很简单的一个方法,在主函数 main 中对变量进行了初始化 a=1,然后将 a 传递给 dosomthing(),然后再 dosomthing 中输出了修改之后的值,最后在主函数中打印 a 的值,你们觉得这几句输出中 a 的值分别是多少呢?


第一种:


修改过后,a = 0


主函数 a 的值 = 1


第二种:


修改过后,a = 0


主函数 a 的值 = 0


第三种:


修改过后,a = 1


主函数 a 的值 = 1


想要得到答案的话就得先明白参数传递的两个类型:值传递和引用传递。


什么是引用传递?


在 C++中,函数参数的传递方式有引用传递。所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。


什么是值传递?


值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。


我们再回过头来看上面的例子,如果是引用传递的话打印结果应该是第二种情况,如果是值传递,打印结果应该是第一种情况,所以到底打印的结果是什么呢?


我们一起看一看控制台输出


Connected to the target VM, address: '127.0.0.1:59333', transport: 'socket'


修改过后,a = 0


主函数 a 的值 = 1


Disconnected from the target VM, address: '127.0.0.1:59333', transport: 'socket'


Process finished with exit code 0


这就是第一种情况,很明显,在 dosomthing 函数中修改了 a 的值,但是主函数中的 a 并没有受到影响,所以肯定不会是引用传递,如果是引用传递,主函数的 a 应该会变成 0,只有在参数传递的时候将主函数的中参数复制一份给 dosomthing,才能在 dosomthing 中修改 a 不会对主函数造成影响,所以从基本数据类型来看,java 的参数传递方式为:值传递


这个时候你可能会有疑问了,这只是基本数据类型的传递方式,其他的参数类型呢?下面我们一起来看看引用类型和对象类型的传递方式。


follow me !!!!!


[](


)引用类型传递


=====================================================================


我们都知道 java 中的 String 类型不属于基本数据类型,它是一个引用类型,也可以说是一个对象,那么它的传递方式是什么呢?


我们还是先来看例子


package com.ymy.param;


/**


  • @ProjectName: demo

  • @Package: com.ymy.param

  • @ClassName: StringTypeTest

  • @Author: 流星 007

  • @Description: String 类型传递

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/7/5 14:22

  • @Version: 1.0


*/


public class StringTypeTest {


public static void main(String[] args) {


String a = "hello";


dosomthing(a);


System.out.println("主函数 a 的值 = "+a);


}


private static void dosomthing(String a) {


a = a+" bug";


System.out.println("修改过后,a = "+a);


}


}


打印结果


修改过后,a = hello bug


主函数 a 的值 = hello


Process finished with exit code 0


我们发现主函数的 a 并没有受到 dosomthing 函数的影响,所以这并不是引用传递,这个时候你说是因为


a = a+" bug";这行代码生成了新的对象,所以才会导致数据不一致,我们先来看看 a 的赋值情况吧


// class version 52.0 (52)


// access flags 0x21


public class com/ymy/param/StringTypeTest {


// compiled from: StringTypeTest.java


// access flags 0x1


public <init>()V


L0


LINENUMBER 14 L0


ALOAD 0


INVOKESPECIAL java/lang/Object.<init> ()V


RETURN


L1


LOCALVARIABLE this Lcom/ymy/param/StringTypeTest; L0 L1 0


MAXSTACK = 1


MAXLOCALS = 1


// access flags 0x9


public static main([Ljava/lang/String;)V


// parameter args


L0


LINENUMBER 17 L0


LDC "hello"


ASTORE 1


L1


LINENUMBER 18 L1


ALOAD 1


INVOKESTATIC com/ymy/param/StringTypeTest.dosomthing (Ljava/lang/String;)V


L2


LINENUMBER 19 L2


GETSTATIC java/lang/System.out : Ljava/io/PrintStream;


NEW java/lang/StringBuilder


DUP


INVOKESPECIAL java/lang/StringBuilder.<init> ()V


LDC "\u4e3b\u51fd\u6570a\u7684\u503c = "


INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;


ALOAD 1


INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;


INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;


INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V


L3


LINENUMBER 21 L3


RETURN


L4


LOCALVARIABLE args [Ljava/lang/String; L0 L4 0


LOCALVARIABLE a Ljava/lang/String; L1 L4 1


MAXSTACK = 3


MAXLOCALS = 2


// access flags 0xA


private static dosomthing(Ljava/lang/String;)V


// parameter a


L0


LINENUMBER 24 L0


NEW java/lang/StringBuilder


DUP


INVOKESPECIAL java/lang/StringBuilder.<init> ()V


ALOAD 0


INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;


LDC " bug"


INVOKEVIRTUAL ja


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


va/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;


INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;


ASTORE 0


L1


LINENUMBER 25 L1


GETSTATIC java/lang/System.out : Ljava/io/PrintStream;


NEW java/lang/StringBuilder


DUP


INVOKESPECIAL java/lang/StringBuilder.<init> ()V


LDC "\u4fee\u6539\u8fc7\u540e\uff0ca = "


INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;


ALOAD 0


INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;


INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;


INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V


L2


LINENUMBER 27 L2


RETURN


L3


LOCALVARIABLE a Ljava/lang/String; L0 L3 0


MAXSTACK = 3


MAXLOCALS = 1


}


这是上面代码的字节码代码,我们可以清楚的看到 a 在赋值的时候都调用了 StringBuilder 的同 String 方法,现在我们来看看这个神奇的同 String 方法。


@Override


public String toString() {


// Create a copy, don't share the array


return new String(value, 0, count);


}


这是 StringBuilder 中的 toString 方法,确实是 new 了一个新的对象,就算是 a 变成了一个新的对象,如果是引用传递,主函数的 a 就不会受影响吗?这点我会讲完对象类型传递之后在进行讲解,请继续往下看。


[](


)对象类型传递


=====================================================================


其实上面的两种其实很好区分,很多人都知道是值传递,很多人说 java 的传递方式是引用传递的原因就是出自这里:传递的参数为对象


有些人看到对象传递的时候会改变主函数的值,就认为 java 的参数传递是引用传递,有些人又因为基本数据类型不会队主函数的值造成修改,所以他们的结论是:基本数据类型为值传递;对象类型为引用传递,想法很好,那我们现在一起来解开对象传递的神秘面纱,它到底是引用传递还是值传递呢?


go go go !!!!


还是老规矩,我们一起来看一个例子


package com.ymy.param.vo;


/**


  • @ProjectName: demo

  • @Package: com.ymy.param.vo

  • @ClassName: LolVo

  • @Author: 流星 007

  • @Description: lol 英雄属性

  • csdn:https://blog.csdn.net/qq_33220089

  • 今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523

  • @Date: 2020/7/5 15:11

  • @Version: 1.0


*/


public class LolVo {


/**


  • 姓名


*/


private String name;


/**


  • 职业


*/


private String profession;


public String getName() {


return name;


}


public void setName(String name) {


this.name = name;


}


public String getProfession() {


return profession;


}


public void setProfession(String profession) {


this.profession = profession;


}


@Override


public String toString() {


return "LolVo{" +

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
天真,居然还有人认为java的参数传递方式是引用传递(1)