天真,居然还有人认为 java 的参数传递方式是引用传递,互联网 java 工程师面试突击训练网盘
[](
)引用类型传递
=====================================================================
我们都知道 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 java/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{" +
"name='" + name + ''' +
", profession='" + profession + ''' +
'}';
}
}
package com.ymy.param;
import com.ymy.param.vo.LolVo;
/**
@ProjectName: demo
@Package: com.ymy.param
@ClassName: ObjectTypeTest
@Author: 流星 007
@Description: 对象类型传递
csdn:https://blog.csdn.net/qq_33220089
今日头条:https://www.toutiao.com/c/user/5372182357/#mid=1637641735275523
@Date: 2020/7/5 15:16
@Version: 1.0
*/
public class ObjectTypeTest {
public static void main(String[] args) {
LolVo lolVo = new LolVo();
lolVo.setName("无极剑圣");
lolVo.setProfession("刺客");
dosomthing(lolVo);
System.out.println("主函数 lolVo = "+lolVo);
}
private static void dosomthing(LolVo lolVo) {
lolVo.setProfession("战士");
System.out.println("dosomthing lolVo = "+lolVo);
}
}
结果如下:
dosomthing lolVo = LolVo{name='无极剑圣', profession='战士'}
主函数 lolVo = LolVo{name='无极剑圣', profession='战士'}
Process finished with exit code 0
评论