Java 字符串常量池 String Pool 的理解

Updated on in Java with 443 views

Java 中 String 是一个非常特殊的数据类型,在学习 JVM 虚拟机的时候,才真正意识到为了让 String 类型在运行过程中速度更快、更节省内存,才提供了字符串常量池的概念。

概念

字符串常量池(String Pool)保存所欲字符串字面量(literal strings),这些字面量在编译时期就确定,不仅如此,还可以使用 String 的 intern() 方法在运行时添加到常量池中。

常量池的使用主要有两种方法:

  • 直接使用双引号声明出来的 String 对象会直接存储到常量池中。
  • 使用 String 提供的 intern() 方法时,会查询字符串常量池中是否存在当前字符,如果不存在则将当前字符串放入常量池中。

String、StringBuffer、StringBuilder

这是 String 的另一个知识点,这里只是提一下一笔带过。

  1. 可变性
  • String 不可变
  • StringBuffer 和 StringBuilder 可变
  1. 线程安全性
  • String 不可变,因此是线程安全的
  • StringBuilder 不是线程安全的
  • StringBuffer 是线程安全的,内部使用 synchronized 进行同步

String Pool 示例(JDK1.8)

这里要特别注意,此处以 JDK1.8 为例,因为在 JDK1.7 之前常量池在 Perm 区,而在 JDK1.7 之后常量池在 Java Heap 区,所以所看到的运行结果会有所不同。

String s1 = "ss";		// 在常量池上创建常量s1
String s2 = "ss";		// 直接放回已存在的常量
System.out.println(s1 == s2);	// true
String s1 = new String("ss");	// 在堆上创建对象
String s2 = new String("ss");	// 在堆上创建对象
System.out.println(s1 == s2);	// false
String s1 = "ss1" + "ss2"	// 在常量池上创建常量 ss1、ss2、ss1ss2
String s2 = "ss1ss2";
String s3 = "ss1" + "ss2";
System.out.println(s2 == s3);  // true
String s1 = new String("ss1") + new String("ss2");	// 在堆上创建对象 ss1、ss2 和 ss1ss2,在常量池上创建常量 ss1 和 ss2
s1.intern();
String s2 = "ss1" + "ss2";
System.out.println(s1 == s2);	// true
String s1 = new String("ss") + new String("ss1");	// 常量 ss 不存在,所以第一步在常量池中创建了常量 ss
String s2 = new String("s") + new String("s");	// 创建对象 ss
System.out.println(s2 == s2.intern());		// false
System.out.println(s1 == s1.intern());		// true
String s1 = "ss1ss2";
String s2 = "ss1" + new String("ss2");
System.out.println(s1 == s2.intern());		// true
String s1 = "ss1ss2";
String s2 = "ss1" + new String("ss2");
System.out.println(s1 == s2.intern());		// true
System.out.println(s2 == s2.intern());		// false

规律:
1.new String 在堆上创建字符串对象。
2.通过字面量赋值创建字符串(如:String str="1")时,会先在常量池中查找是否存在相同的字符串,若存在,则将栈中的引用直接指向该字符串;若不存在,则在常量池中生成一个字符串,再将栈中的引用指向该字符串。
3.常量字符串的 + "" 操作,编译阶段直接会合成为一个字符串。如 String str="JA"+"VA",在编译阶段会直接合并成语句 String str="JAVA",于是会去常量池中查找是否存在 "JAVA",从而进行创建或引用。


标题:Java 字符串常量池 String Pool 的理解
作者:Jeffrey

Responses
取消