前言
网上看的这篇博文把Java的参数传递已经讲得很清楚了。我用一道比较绕的题来理解一下String的参数传递。
public class Demo {
String str = new String("hello");
char[] ch = {'a', 'b', 'c'};
public void fun(String str, char ch[]) {
str = "world";
ch[0] = 'd';
}
public static void main(String[] args) {
Demo test = new Demo();
test.fun(test.str, test.ch);
System.out.print(test.str + " and ");
System.out.print(test.ch);
}
}
这道题的结果输出“hello and dbc".
分析与解答
对象test调用fun方法,将实参test.str(全局变量str存放对象"hello"的内存地址)和test.ch(全局变量ch存放字符数组对象的内存地址),传给fun方法的形参str引用和ch[]引用。
参数传递相当于
String str = "hello"
,局部变量str存放对象"hello"的内存地址。我们知道String是final类型。所以语句str = "world"
;的含义:将在堆中重新分配一个内存空间存放"world",局部变量str指向"world"。局部变量str的生命周期和方法相同,只是名称和全局变量str相同。注意!即使此处局部变量即使不是String类型,而是基本数据类型,局部变量也不会影响同名的全局变量。
以上两步操作在JVM中如下图所示,内存地址为假设。
- char ch[]与char[] ch等价。语句
ch[0] = 'd';
将替换字符数组对象中下标为0的字符,即改变了对象的内容。test.str没有改变,还是"hello",test.ch从"abc"改为"dbc"。
IDEA调试图如下:
拓展
Book a == new Book();//对象1
Book b == new Book();//对象2
b = a;
问:那个对象会被回收?
答:对象2,因为将引用a中存放对象1的地址赋值给了引用b,所以引用b将“指向”对象1,对象2将被回收。
总结
从String的参数传递可以看出,String的参数传递是对象地址值传递,所以String的参数传递是值传递。