在日常中经常就会碰到String类型的对象,自己再总结一下
1.String对象的存储
1.1.编译时可以确定的String数据通过新建对象放入字符串常量池或者引用常量池里已存在的值相等的对象, 此时有两种情况:
A:通过“=”运算符将“xxxxx”字符串直接赋值给引用
B:"="号右边发生字符串的直接拼接[a=“c”+“d”,a在常量池]
1.2.编译时不能确定的String数据在运行时在堆中创建String对象存储,此时也有两种情况:
A: "new"的字符串
B: "="号右边有String类型的变量[a=“sf”,b=a+“fgh”,b在堆中]
如下的例子:
String a="a";//编译器先去常量池里寻找是否有"a"字符串存在,若有,则将a指向其地址值,若无,则在常量池新建对象"a",并将其地址给a;
String c="a" //c和a具有相同的地址值
String b=new String("b");//jvm先在常量池寻找是否有"b"字符串存在,若有,则在堆中新建一个String对象,该对象内容复制自常量池的"b",如无,jvm会在堆中直接新建一个对象"b",并同时在常量池里新建"b"字符串对象。方便以后调用。
2.String类型数据的修改
先看一下String类的源码:
/** The value is used for character storage. */
private final char value[]; //String类存储字符串的属性是final修饰的
发现String对象数据是final的,即一旦赋值完成,其值将不再可变,相当于常量,因此,可以得出若程序修改了某个String变量指向的字符串,其实本质上并没有修改该字符串本身,而是将该变量指向了另外的String对象。因此在将String对象作为参数进行传递时,尽管传递的是地址值,调用方法中改变String的值,原方法中字符串不受影响。题外话,在jdk1.8之后,常量池移到了堆中。例子如下:
String a="a";
a="L";//a指向常量池中某个String对象
String b=new String("b");
b=new String("b");//b指向堆中的某个String新对象
b="L";//b指向常量池中某个String对象