String
String 类是 final 型,固 String 类不能被继承,它的成员方法也都默认为final 方法。
String对象一旦创建就固定不变了,对 String 对象的任何改变都不影响到原对象,相关的任何改变操作都会生成新的 String 对象。
String 类是通过 char 数组来保存字符串的,String 对 equals 方法进行了重定,比较的是值相等。
String a = "test"; String b = "test"; String c = new String("test");
a、b 和字面上的 test 都是指向 JVM 字符串常量池中的"test"对象,他们指向同一个对象。而new 关键字一定会产生一个对象 test,该对象存储在堆中。所以 new String("test")产生了两个对象,保存在栈中的 c 和保存在堆中的 test。而在 java 中根本就不存在两个完全一模一样的字符串对象,故在堆中的 test 应该是引用字符串常量池中的 test。
例: 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对象。System.out.println(str3 == "abcdef");//返回 false 因为 str3 指向堆中的"abcdef"对象,而"abcdef"是字符池中的对象,所以结果为false。JVM对 String str="abc"对象放在常量池是在编译时做的,而 String str3=str1+str2 是在运行时才知道的,new对象也是在运行时才做的。
String 为什么要设计成不可变的?
1)字符串常量池需要 String 不可变。因为 String 设计成不可变,当创建一个String 对象时,若此字符串值已经存在于常量池中,则不会创建一个新的对象,而是引用已经存在的对象。如果字符串变量允许必变,会导致各种逻辑错误,如改变一个对象会影响到另一个独立对象。
2)String 对象可以缓存 hashCode。字符串的不可变性保证了 hash 码的唯一性,因此可以缓存 String 的 hashCode,这样不用每次去重新计算哈希码。在进行字符串比较时,可以直接 比较 hashCode,提高了比较性能;
3)安全性。String 被许多 java 类用来当作参数,如 url 地址,文件 path 路径,反射机制所需的 Strign 参数等,若 String 可变,将会引起各种安全隐患。

浙公网安备 33010602011771号