全局字符串池(string pool)

字符串池/字符串常量池(String Pool/String Constant Pool):是class常量池中的一部分,存储编译期类中产生的字符串类型数据。
然后将该字符串对象实例引用值存到string pool中。
string pool的底层就是一个StringTable类,它是一个固定大小的Hashtable,默认值大小长度是1009,里面存的是驻留字符串的引用。
也即是说数据存于堆中,StringTable保持引用地址。
在jvm中,StringTable只有一个,被所有类共享。

运行时常量池(runtime constant pool)

运行时常量池(Runtime Constant Pool):方法区的一部分,所有线程共享。虚拟机加载Class后把class常量池中的数据放入到运行时常量池。
运行时常量池是在类加载完成之后,将每个class常量池中的符号引用值 转存 到运行时常量池中,
即,类加载解析之后,将符号引用 替换成 直接引用,与全局常量池中的引用值保持一致。

笔试题1:

  1. /**
  2. * (1)类加载对一个类只会进行一次。”abc”在类加载时就已经创建并驻留在全局字符串池StringTable中
  3. * (2)new String("abc")将常量池中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给s2 持有。
  4. */
  5. @Test
  6. public void test1(){
  7. String s1="abc";
  8. String s2=new String("abc");
  9. System.out.println(s1 == s2);//false
  10. }

笔试题2:

  1. /**
  2. * s2是在运行的时候调用intern()函数,返回常量池StringTable中"abc”的引用值,故s2 s3都是常量池就相同了
  3. */
  4. @Test
  5. public void test2(){
  6. String s1=new String("abc");
  7. String s2=s1.intern();
  8. String s3="abc";
  9. System.out.println(s1 == s2);//false
  10. System.out.println(s2 == s3);//true
  11. }

笔试题3:

  1. /**
  2. * s1 + s2 的执行细节:(变量s是我临时定义的)
  3. * ① StringBuilder s = new StringBuilder();
  4. * ② s.append("a")
  5. * ③ s.append("b")
  6. * ④ s.toString() --> 约等于 new String("ab")
  7. *
  8. * 补充:在jdk5.0之后使用的是StringBuilder,
  9. * 在jdk5.0之前使用的是StringBuffer
  10. *
  11. * s5常量与常量的拼接结果在常量池,原理是编译期就把他处理"ab"存于常量池。
  12. */
  13. @Test
  14. public void test3() {
  15. String s1 = "a";
  16. String s2 = "b";
  17. String s3 = "ab";
  18. String s4 = s1 + s2;
  19. System.out.println(s3 == s4);//false
  20. String s5 = "a"+"b";
  21. System.out.println(s3 == s5);//true
  22. }

笔试题4:

  1. /**
  2. * 如果拼接符号左右两边都是字符串常量或常量引用
  3. 则仍然使用编译期优化,即非StringBuilder的方式。
  4. */
  5. @Test
  6. public void test4(){
  7. final String s1 = "a";
  8. final String s2 = "b";
  9. String s3 = "ab";
  10. String s4 = s1 + s2;
  11. System.out.println(s3 == s4);//true
  12. }