答案:没有正确的答案,笔者认为引用传递和值传递针是对 java 参数传递的现象进行的一种定义,先来几段代码演示一下 java 传参
基本数据类型传参
public static void main(String[] args) {
int a = 1;
basicTypeTest(a);
System.out.println(a);
}
private static void basicTypeTest(int a) {
a++;
}
输出:1
这里,basicTypeTest 对 a 的值进行了自增,但是没有影响到 main 方法的 a 值,这种定义为值传递; 在 jvm 可以这样对这种现象进行分析,在栈空间中,每个方法对应一个栈帧,栈帧中又包含方法的局部变量表、返回地址、动态链接、操作数栈等信息,在main方法中,a 的值就存在于局部变量表中,在basicTypeTest方法中,通过加法之后又存在于局部变量表中。栈帧中的局部变量表做了隔离,所以 basicTypeTest 中的 a 的值自然不影响 main 方法中的 a 的值。
对象传递
public static void main(String[] args) {
People people = new People();
pojoTest(people);
System.out.println(people.getName());
}
private static void pojoTest(People people) {
people.setName("张三");
}
输出: 张三
这里的定义为引用传递,这个的对象传递在平时的开发过程中就比较常见了,我们经常传入一个对象进入一个方法,把对对象的属性进行各种操作封装在方法中;分析:在 main 方法进行调用的时候,在 main 方法的操作数栈中保存了对堆空间中 people 的引用,在 pojoTest 方法中对对象中的 name 进行了赋值,所以 main 方法中获得了 people 的 name 值。
字符串传递
public static void main(String[] args) {
String a = "hello";
stringTest(a);
System.out.println(a);
}
private static void stringTest(String a) {
a = "world";
System.out.println("test中a的值" + a);
}
输出:test中a的值world
hello
字符串传递比较特殊,这个 stringTest 的调用并没有改变 a 的值,笔者看过许多解释,认为都挺有道理,这里列举一个比较好的解释:
string类型是 final 不可变的,jdk6 以后为了 string 的效率,设计了字符串常量池,字符串常量池的初衷是为了能够复用常量池中的字符串,提高效率,所以将 string 设计成了不可变的;反过来想如果引用 a 指向了字符串 "test", 引用 b 复用字符串也指向了 "test",这时 a 神不知鬼不觉得将 "test" 改为了 "test1", 那 b 不得爆炸?
废话不多说,画张图来看下 解释:首先 main 方法在常量池中创建了 hello 这个字符串并指向了 a, stringTest 在创建 world 时,发现常量池中没有 world 字段,进行了a = new String("world")操作。
2021年9月10日晚。