欢迎来到刘志红的博客

别人说程序员是“搬砖”的码农,但我们知道自己是追求个性的艺术家。也许我们不会过多的在意自己的外表和穿着,但在不羁的外表下,骨子里追求着代码的美、系统的美、设计的美。
扩大
缩小

effective解读-第六条 避免创建不必要对象

  1. 对于轻量级对象,由于现代版本的JVM对该类对象创建和回收十分的廉价,通过创建附加的对象提高程序的清晰性、简洁性和功能性,通常是件好事。

  2. 对于重量级对象(例如数据库连接对象)、大量创建的对象、不必要的对象(已存在对象已经能完成功能了但是又去创建了对象,而且对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;
    }

 

 

posted on 2021-03-27 09:44  MR_程序猿刘  阅读(66)  评论(0编辑  收藏  举报

导航