字符串常量池
概念
- 字符串常量池是一个大小固定的
HashTable
,默认长度是1009。 - java6存放在永久代,java7和java8存放到java堆中。
常见面试题
- 用双引号定义的字符串是直接存储到常量池,用
new String
创建的是存放在堆中。
String s1 = "123";//存储到字符串常量池
String s2 = new String("123");
System.out.println(s1 == s2); //false
System.out.println(s1.equals(s2)); // true
- 常量的拼接存放到常量池,s4也是直接从常量池中获取,是同一个对象。
String s3 = "a" + "b" + "c"; // 常量的拼接会存储到常量池
String s4 = "abc";
System.out.println(s3 == s4);
- 变量拼接常量,等价于StringBuilder的append,所以s3的对象存放在堆中。
String s1 = "abc";
String s2 = "def";
String s3 = s1 + "def"; // 变量拼接常量,不会存储到常量池。带有字符串变量的拼接,等价于StringBuilder的append
String s4 = "abcdef";
System.out.println(s3==s4); // false
String s5= s3.intern();
System.out.println(s4==s5); //true
- 如果s1和s2都是final类型的,那么s1和
def
的拼接,都是常量。
final String s1 = "abc";
final String s2 = "def";
String s3 = s1 + "def";
String s4 = "abcdef";
System.out.println(s3==s4);
-
new String("ab")
创建了几个对象?两个。一个存放在堆中,一个存放在常量池中。 -
new String("a")+new String("b")
创建了几个对象?字符串a,b都在堆和常量池中,字符串变量拼接用的是StringBuilder
。生成字符串,会生成字符串ab
到堆中,所以总共是6个。 -
s3是堆空间创造的变量,s4是常量池中对象,但是两个对象是相等的,属于同一个对象。该原理是因为String.intern()方法在1.8之后会将对象的引用地址放到串池,即串池中的对象和引用对象是同一份。
String s3 = new String("a") + new String("b");
s3.intern();
String s4 = "ab";
System.out.println(s3 == s4); // true
System.out.println(s3.equals(s4));
包装类和对象池
Integer i1 = 127; //这种调用底层实际是执行的Integer.valueOf(127),里面用到了IntegerCache对象池
Integer i2 = 127;
System.out.println(i1 == i2);//输出true
//值大于127时,不会从对象池中取对象
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4);//输出false
//用new关键词新生成对象不会使用对象池
Integer i5 = new Integer(127);
Integer i6 = new Integer(127);
System.out.println(i5 == i6);//输出false