String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,String类型的数据一般存储在常量池 中
我们查看一下String类的源码,发现其有两个成员属性:
其中value就是用来存储常量池中String的数据,并将其放置于数组中, hash表示的是String类型的地址信息,默认情况下为0。
我们可以看到:这两个成员变量均是private修饰,并且没有get 和set方法。 这表示我们根本无法改变String类型的信息。
给出如下代码:
public class Example{
//实例化一个String类型
String str = new String("good");
//字符数组
char[ ] ch = { 'a' , 'b' , 'c' };
public static void main(String args[]){
Example ex = new Example();
ex.change(ex.str,ex.ch);
System.out.print(ex.str + " and ");
System.out.print(ex.ch);
}
public void change(String str,char ch[ ]){
str = "test ok";
ch[0] = 'g';
}
}
其输出结果为:
我们可以看到 String类型数据的值未被修改,而字符数组的修改成功
我们要知道,每调用一次方法都会在栈区上开辟一块函数栈帧空间。
所以在main方法调用时,开辟了一块内存空间,并且在该栈帧内部实例化了ex对象,其内部成员有:
1. String str :指向了栈区上的一块空间,并且这块内存空间的值是通过常量池进行赋值的
2.Ch[ ]数组,指向堆区的一块地址空间 里面存放{’a‘,’b‘,’c‘};
注意:栈区上引用变量存放的均是栈区的地址信息
后续调用了change()方法,新开辟一块函数栈帧
注意:在Java中,参数的传递均是传值传递!
由于str是常量池上的内容,需要新建一个String类型的对象,并对其赋值常量池上的字符串“good”,
而栈帧的ch[] , 则是把ex中 ch[ ]所指向的地址 赋值给 函数栈帧中的ch[]
此时开始执行 change方法的方法体
首先让 change的str = 字符串“test ok” 由于字符串的不可变性(前言):首先会在常量池上新存储一个 “test ok” 字符串,并把其值赋值给 change函数在堆区上建立的str
而 ch[0] = ‘g’ ,则是 在原堆区空间上进行修改
总体过程如下图所示: