为了加深对Java语言的理解,加深对Java各种特性的理解与掌握,平常会自己归纳一些专题的分析和总结。基于自己的理解,感觉哪些部分适合在一起进行总结,就归纳为一个专题了。可能一个专题里面的东西也不属于一个类别,或者也比较杂乱,请见谅。
本文是在总结不可变对象与String的不可变中,涉及到的String的字符串常量池。感觉这个部分比较重要,面试也经常考到这些,就单独拿出来作为一个专题。(此篇总结大部分是借鉴了CSDN的一篇文章,然后加上了一些自己的理解)
字符串常量池:
- 为了减少在jvm中创建的字符串的数量,字符串类维护了一个字符串常量池,字符串常量池(String pool)是Java堆内存中一个特殊的存储区域;
- 当创建String对象时,jvm会先检查字符串常量池,如果这个字符串的常量值已经存在在池中了,就直接返回池中对象的引用,如果不在池中,就会实例化一个字符串并放入池中;
- 常量池:用于保存java在编译期就已经确定的,已经编译的class文件中的一份数据。包括了类、方法、接口中的常量,也包括字符串常量,如String s = "a"这种声明方式;
String s1 = "aaa";
String s2 = "aaa";
从日常的面试题展开:
String s = new String("abc"); //创建了几个对象
两个;
第一个对象是"abc"字符串存储在常量池中;
第二个对象是创建在Heap中的String对象;这里的s是放在栈里面的指向了Heap堆中的String对象。
String s1 = new String("s1") ;
String s2 = new String("s1") ; //创建了几个对象
三个;
第一个是编译期就已经创建在常量池中创建的"s1",因为创建一个之后常量池中就会有,不再创建,直接指向;
后面两个是运行期使用new创建在堆上的s1和s2;
示例1:
String s0 = "111"; //pool
String s1 = new String("111"); //heap
final String s2 = "111"; //pool
String s3 = "sss111"; //pool
String s4 = "sss" + "111"; //pool
String s5 = "sss" + s0; //heap
String s6 = "sss" + s1; //heap
String s7 = "sss" + s2; //pool
String s8 = "sss" + s0; //heap
System.out.println(s3 == s4); //true
System.out.println(s3 == s5); //false
System.out.println(s3 == s6); //false
System.out.println(s3 == s7); //true
System.out.println(s5 == s6); //false
System.out.println(s5 == s8); //false
示例2:
String str1 = "abc";
String str2 = "abc";
String str3 = "abc";
String str4 = new String("abc");
String str5 = new String("abc");
String str6 = new String("abc");
结论:
- 单独使用""引号创建的字符串都是常量,编译器就已经存储到常量池中了;
- 使用new String()创建的是对象会存储到heap中,是运行期创建的;
- 使用只包含常量的字符串连接符如"a"+"a"创建的也是常量,编译器就能确定,并存储到常量池"aa",但不会有"a"存在;
- 使用包含变量的字符串连接符如"a"+s1创建的对象会存储在堆中,运行时期才创建;只要s1是变量,不论s1指向池常量池中的字符串对象还是堆中的字符串对象,运行期"a"+s1操作实际上是编译器创建了StringBuilder对象进行了append操作后通过toString()返回了一个字符串对象存在heap上。
- 对于final String s2 = "111",是一个用final修饰的变量,在编译期就已知了,在包含变量的字符串连接符"a"+s2时直接用常量"111"来代替s2,等效于"a"+"111",在编译期就已经生产了字符串对象"a111"对象在常量池中。
目前全部文章列表:
idea整合restful风格的ssm框架(一)
idea整合restful风格的ssm框架(二)
idea整合spring boot+spring mvc+mybatis框架
idea整合springboot+redis
JVM学习之—Java内存区域
JVM学习之—垃圾回收与内存分配策略
专题整理之—不可变对象与String的不可变
专题整理之—String的字符串常量池