effective解读-第六条 避免创建不必要对象
-
-
对于重量级对象(例如数据库连接对象)、大量创建的对象、不必要的对象(已存在对象已经能完成功能了但是又去创建了对象,而且对1中清晰性、简洁性和功能性没有任何帮助)要有限考虑避免创建重复对象
反例1:使用
String s=new String("bikini");
在一个使用频繁的方法中或者循环中会创建很多没必要的对象。改进版本:String s="bikini";
反例2:
Boolean(String)
,同时提供构造器和静态工厂方法的不可变类,优先使用静态工厂方法以避免创建不必要的对象。改进:Boolean.valueOf(String)`替代,该构造器在java9中废弃。反例3:使用正则判断字符串是否匹配罗马字符,如果多次调用该方法就会降低程序性能,因为创建Pattern的成本很高
static boolean isRomanNumeral(String str){
return s.matches("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$")
}改进版本:
private static final Pattern ROMAN=Pattern.compile("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
static boolean isRomanNumeral(String s){
return ROMAN.matcher(s).matches();
}书中还提到上面的代码可以编程懒加载模式,但是不建议这么做,因为它增加了代码的复杂性但是不能显著的提高到已有的性能水平。我们在编译器中写入下面的代码,代码检测工具也会提示我们这个问题(提示:在使用正则表达式时,利用好其预先编译功能,可以有效的加快正则匹配速度)。
//不建议代码
private final Pattern ROMAN;
static boolean isRomanNumeral(String s){
if(ROMAN==NULL){
ROMAN=Pattern.compile("^(?=.)M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$");
}
return ROMAN.matcher(s).matches();
}反例4:要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱,这里给出了创建多余实例的例子
private static long sum(){
//由于这里使用Long而没使用long 导致创建了2的31次方个Long实例
Long sun=0L;
for(long i=0;i<=Integer.MAX_VALUE;i++){
sum+=i;
}
return sum;
}正例1:不可变对象可以被安全的重用,这里提到了适配器模式中用来代替原功能对象的后备对象,由于它设计出来就是完成特定功能的,所以把它设计成可重用对象。
正例2:Map保存key存储的例子,Map集合保存key的Set集合keySet,创建多个实例并无害处,但是没有必要,所以Map实例中keySet使用的是单例。
HashMap map = new HashMap<>();
map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
map.put(4, 4);
Set set1= map.keySet();
System.out.println(set1);
map.put(5, 5);
Set set2 = map.keySet();
System.out.println(set1);
System.out.println(set2);
//true
System.out.println(set1==set2);
//源码如下
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
-------------------------------------------
个性签名:独学而无友,则孤陋而寡闻。做一个灵魂有趣的人!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!