这个item提到,能重用的时候最好不要创建新的对象。
String自动装箱的例子
首先举了String
的例子。创建String
的时候,不要new一个String,而是直接用Java的自动装箱方法。
String s = new String("stringette"); // DON'T DO THIS!
要这样:
String s = "stringette";
这是一个single String instance. 只要在虚拟中有相同的字符串字面常量,这个对象就会被重用。
我们知道基本数据类型用==判断相等,包装后的数据类型用Objects.equals判断相等。String又有==又有equals方法,因为String的primitive type和wrapper class都是String。
这问题之前也思考过,循环里面的变量声明问题。编译器会优化的。否则就会创建很多对象了。
还有个String自动装箱的有趣的例子,new两个同样的字符串,equals判断是true,但是==判断就是false。
String str1 ="abc";
String str2 ="abc";
System.out.println(str2==str1); //输出为 true
System.out.println(str2.equals(str1)); //输出为 true
String str3 =new String("abc");
String str4 =new String("abc");
System.out.println(str3==str4); //输出为 false
System.out.println(str3.equals(str4)); //输出为 true
这是因为equals判断的是String里面的值,而==判断的是原始数据类型-->比对的是对象Object。
str1和str2引用了同一个对象,而str3和str4引用了不同的对象。
第二个例子
举了isBabyBoomer的例子,主要思想就是把能重用的两个常量定义成static final的而不是每次调用都新建对象。
后面还举了一些Map的例子,没怎么看懂。
第三个例子,Long的自动装箱
package com.czgo.effective;
public class TestLonglong {
public static void main(String[] args) {
Long sum = 0L;
for(long i = 0; i < Integer.MAX_VALUE; i++){
sum += i;
}
System.out.println(sum);
}
}
这段程序算出的结果是正确的,但是比实际情况要慢的多,只因为打错了一个字符。变量sum被声明成Long而不是long,意味着程序构造了大约2的31次方个多余的Long实例(大约每次往Long sum中增加long时构造一个实例)。将sum的声明从Long改成long,速度快了不是一点半点。结论很明显:要优先使用基本类型而不是引用类型,要当心无意识的自动装箱。