String对象的创建方式
String str1 = "abc";
String str2 = "abc"; // 此时str1 == str2,因为他们都是常量池中的abc
String str3 = new String("abc") // 这会在堆中创建一个abc新对象,此时str1≠str3
- 第一种:直接赋值,若字符串存在于常量池中,会直接引用常量池中字符串;若不存在,会在常量池中创建并返回引用
- 第二种:new创建(先检测常量池中是否存在该字符串),若字符串存在于常量池中,则直接在堆中创建字符串对象;若常量池中不存在,会现在常量池中创建字,再从堆中创建字符串
- 下面思考一下
String str = new String("abc")
到底创建了几个对象?答案一个或两个,当常量池中存在abc时,只在堆中创建对象abc,当常量池中不存在abc时,先在在常量池中创建abc,然后从堆中创建对象abc
String常量池的使用
- 双引号赋值,使用常量池
- String类的intern方法,如果常量池中有等于此String的字符串,返回常量池中该字符串引用。如果没有,在常量池中创建与此String内容相等字符串并返回常量池中字符串的引用(此处说法笼统:具体可以看这篇博客)
8种基本类型的包装类和常量池
除了Float和Double外,其他几种基本类型的包装类(Byte,Short,Integer,Long,Character,Boolean)都实现了常量池技术,包装类默认创建数值 [-128,127] 的相应类型的缓存数据,超出此范围仍然会去堆中创建对象,
以Integer缓存为例
// 缓存[-128,127]之间的数值否则堆中创建对象
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
应用场景
- Integer i1 = 40; 编译时将代码封装成Integer i1 = Integer.valueOf(40);
- Integer i2 = new Integer(40); 创建新对象