String类的不可变性是指什么?
首先,String类内部用于存储字符串的字符数组char[] value
前加了final
关键字,这意味着一旦初始化完成后就无法对该数组进行扩容。
private final char value[];
其次,纵观String类所有方法的设计,凡是涉及字符串修改的方法,只要修改了字符串的内容,都会将结果用一个新的String类对象返回,这意味着仅通过String类对外提供的接口对其进行访问和操作能够保证字符串的内容永远保持不变。
最后,String 类本身被声明为 final,这意味着它不能被继承。这防止了子类可能通过添加修改方法来改变字符串内容的可能性。
String类为什么要设计成不可变的?这样做有什么好处?
- 因为 String 对象的内容不会改变,所以它的哈希值也就固定不变。这使得 String 对象特别适合作为 HashMap 或 HashSet 等集合的键。而且因为 String 对象的哈希值是固定不变的,可以在第一次计算过哈希值之后就缓存起来(存到 String 类的成员变量
int hash
中),之后需要用到哈希值时就不用重复计算了,提高了效率。 - 由于 String 对象的内容不会改变,所以当代码中出现相同的字符串字面量时,可以使用同一个字符串对象来表示它们(存在字符串常量池中),不用对重复出现的字符串字面量每个都创建一个字符串对象,从而节约了内存。
- 不可变性使得 String 对象在使用中更加安全。因为字符串经常用作参数传递给其他 Java 方法,例如网络连接、打开文件等。如果 String 是可变的,这些方法调用的参数值就可能在不知不觉中被改变,从而导致网络连接被篡改、文件被莫名其妙地修改等问题。
哪些字符串对象是放在常量池中的?
(1)直接"…"得到的字符串对象放在常量池。
(2)直接"…"+"…"拼接的字符串对象放在常量池。
(3)两个指向"…"的final常量拼接结果放在常量池。
(4)所有字符串对象.intern( )方法得到的结果放在常量池。
除以上四种方式,其他方式得到的字符串结果都在堆中。
String s = new String("hello");
创建了几个字符串对象?
字符串对象内存分析面试题
String类设计成不可变的有什么坏处?
如果在程序中频繁使用字符串变量拼接或修改字符串,那么每次都会得到新的字符串对象,就会导致系统效率低下。因此Java另外提供了两个可变字符序列StringBuffer(线程安全)和StringBuilder供系统使用。
字符串拼接是如何实现的?
使用“+”拼接字符串,底层是通过SpringBuilder实现的。
String a = "hello ";
String b = "world!";
String ab = a + b;
等价于:
String a = "hello ";
String b = "world!";
StringBuilder sb = new StringBuilder();
sb.append(a);
sb.append(b);
String ab = sb.toString();