1、通过查看String的源码可以看出String被final关键字修饰,因此String类不能被继承,它的成员方法都默认为final方法,String对象一旦被创建就不可变了。对String类型的任何改变都影响不了原对象,相关的任何改变操作都会产生一个新的对象。
2、String 类是通过char数组来保存字符串的,String对equal方法进行了重写,b比较的是值相等
String a = "123" ; String b = "123"; String c = new String("123");
a 和 b 字面上“123”都指向字符串常量池中的“123”对象,它们都指向同一个对象,而new 关键字会产生一个对象123,该对象储存于堆中,所以new String(“123”);就产生了两个对象,保存在栈中的c和保存在堆中的"123",但是java中不存在两个完全一模一样的对象,故在堆中的“123”应该是引用字符串常量池中的"123";
例如:String str1 = "abc"; //在栈中开辟一块空间用来存放str1,str1指向池中String常量"abc";
String str2 = "def"; //在栈中开辟一块空间用来存放str2,str2指向池中String常量"def";
String str3 = str1 + str2; 栈中开辟一块空间用来存放str3。而str1+str2通过StringBuilder中的最后一步ToString方法返回一个新的String对象,对象“abcdef”会在堆中开辟一块空间用来存放次对象,str3用来存放(str1 + str2)中返回的新String对象。
jvm对String str = “abc”; 对象放在常量池是在编译时做的,而Str3 = str1 + str2是在运行时才知道的,new 对象也是在运行的时候才做的。
3、String为什么设计成不可变的?
(1)字符串常量池需要String不可变,因为String不可变,当创建一个String对象时,若此字符串值已经存在常量池中,则不会创建一个新的对象,而是引用已经存在的对象,如果可变的话回引起各种错误。
(2)出于安全性考虑,String被许多java类用来做参数,如url地址,path路径,文件path路径等,如果String可变,将会引起各种安全问题。
(3)String对象可以缓存hashCode,字符串的不可变性导致hash码的唯一性,因此可以缓存String的hashCode,这样不用每次重新比较hash码,在字符串比较的时候可以直接比较hashCode,提高了性能。



