定义


String

String是一种不可变的字符串类型。

intern()


  • 若字符串常量池中不存在该字符串,则:
    • Java6(JDK6)及之前:复制一份字符串到永久代中的字符串常量池中,并返回该字符串的引用
    • Java7(JDK7)及之后:复制当前字符串到堆中的字符串常量池中,并返回该字符串的引用
  • 若字符串常量池中存在该字符串,则返回该字符串的引用

字符串常量池


字符串常量池用于缓存字符串对象,里面保存了字符串对象的引用。
使用字符串字面量创建字符串时:

String s = "abc";

JVM先在字符串常量池中查找是否存在"abc"

  • 若存在,则直接返回该字符串的引用
  • 若不存在,则在字符串常量池中创建字符串"abc",然后返回该字符串的引用

问题


String为什么设计为不可变

  1. 安全性:Java中类名、文件路径、URL、数据库连接信息等都用String来表示,如果String是可变的,这些字符串在被系统检查后可能会被修改,这样就会产生安全漏洞。
  2. 线程安全:不可变对象天然就是线程安全的,可以在不同的线程间进行传递,同时进行读取。
  3. 字符串常量池:字符串常量池依赖于String的不可变性,如果String是可变的,在一处对字符串进行修改,其他引用也会被修改,字符串常量池就失效了。
  4. 哈希集合:String常常用来作为哈希集合的Key,如果String可变,String的hashCode计算结果就不能被缓存,原有hashCode对应的值也会无法找到,造成数据丢失和内存泄露。

new String()创建的对象数量

String s = new String("abc");

这行代码可能创建1~2个对象:

  1. 若字符串字面量"abc"不存在于字符串常量池中,将在字符串常量池中创建一个String对象。
  2. 在堆上创建一个内容为"abc"的新的String对象。