zoukankan      html  css  js  c++  java
  • Effective Java 创建和销毁对象

    《Effective Java》阅读笔记,用适合自己理解的方式提炼该书内容。《Effective Java》是一本很实用的书,阅读方法应该是快速的领会,总结,然后应用。而非,一个字一个字去推敲,研究。所以,书呆子们一般都很xx,在我眼里。

    2016.07.24作

    1,用静态方法替代构造器,下面是很好的例子:

    public static final Boolean TRUE = new Boolean(true);
    
    public static final Boolean FALSE = new Boolean(false);
    
    public static Boolean valueOf(boolean b){
              return b ? Boolean.TRUE : Boolean.FALSE;
    }

    结合代码来谈,valueOf比构造函数更能体现其意义;其次,valueOf返回的是final static成员,这种情况避免了创建不必要的对象。

    2,构建器Builder。这个太棒了,使用了java的内部类。

    package cn.j;
    
    public class NutritionFacts {
        private final int servingSize;
        private final int servings;
        private final int calories;
        private final int fat;
        private final int sodium;
        private final int carbonhydrate;
     
        public static class Builder {
            private final int servingSize;
            private final int servings;
     
            private int calories = 0;
            private int fat = 0;
            private int sodium = 0;
            private int carbonhydrate = 0;
             
            public Builder(int servingSize,int serving){
                this.servingSize = servingSize;
                this.servings = serving;
            }
             
            public Builder calories(int val){
                this.calories = val;
                return this;
            }
             
            public Builder fat(int val){
                this.fat = val;
                return this;
            }
             
            public Builder carbonhyate(int val){
                this.carbonhydrate = val;
                return this;
            }
             
            public Builder sodium(int val){
                this.sodium = val;
                return this;
            }
             
            public NutritionFacts build(){
                return new NutritionFacts(this);
            }
        }
         
        private NutritionFacts(Builder builder){
            servingSize = builder.servingSize;
            servings = builder.servings;
            calories = builder.calories;
            fat = builder.fat;
            sodium = builder.sodium;
            carbonhydrate = builder.carbonhydrate;
        }
         
        public static void main(String[] args) {
            NutritionFacts cocacola = new NutritionFacts.Builder(240,80).calories(100).sodium(35).carbonhyate(27).build();
        }
    }

    结合代码来看,如果单纯用构造函数来初始化那些参数的话,会比较麻烦,而难以阅读,使用易于出错。

    例如new Test(1,2,3,4,5,6,7,8,9);这种写法。

    上述代码的形式,NutritionFacts cocacola = new NutritionFacts.Builder(240,80).calories(100).sodium(35).carbonhyate(27).build();可读性非常强。builder模式模拟了具名的可选参数。

    我隐约记得,目前工作中的项目看到过这种Builder的写法。

    3,通过私有构造器强化不可实例化的能力,这也是非常非常实用!因为项目中工具类太常用,都需要这种强化不可实例化的能力。下面代码是我自己SonnBlog的代码:

    /**
    * @ClassName: StringUtil 
    * @Description: 字符串处理工具类
    * @author 无名
    * @date 2016-4-30 下午10:26:48 
    * @version 1.0
     */
    public final class StringUtill
    {
        private StringUtill()
        {
        }
        
        public static boolean isStringEmpty(String str)
        {
            if(null == str|| "".equals(str))
            {
                return true;
            }
            return false;
        }
        
        public static boolean isTheSameStr(String str1,String str2)
        {
            if(isStringEmpty(str1) || isStringEmpty(str2)||!str1.equals(str2))
            {
                return false;
            }
            return true;
        }
    }

    4,用私有构造函数强化Singleton属性

    第一种方式:

    public class Elvis{
             private static final Elvis INSTANCE = new Elvis();
             private Elvis(){}
             public static Elvis getInstance(){return INSTANCE;}
    }

    像之前说的那样,private构造函数使得该类不可实例化,同时public static的getInstance方法返回private static final的Elvis成员,而这个成员被final保证了只能实例化一次。

    第二种方式:

    public enum Elvis{
              INSTANCE;
    public void leaveTheBuilding(){……} }

    5,避免创建不必要的对象

    // Creates lots of unnecessary duplicate objects - page 20-21  
      
    import java.util.*;  
      
    public class Person {  
        private final Date birthDate;  
      
        public Person(Date birthDate) {  
            // Defensive copy - see Item 39  
            this.birthDate = new Date(birthDate.getTime());  
        }  
      
        // Other fields, methods omitted  
      
        // DON'T DO THIS!  
        public boolean isBabyBoomer() {  
            // Unnecessary allocation of expensive object  
            Calendar gmtCal =  
                Calendar.getInstance(TimeZone.getTimeZone("GMT"));  
            gmtCal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);  
            Date boomStart = gmtCal.getTime();  
            gmtCal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);  
            Date boomEnd = gmtCal.getTime();  
            return birthDate.compareTo(boomStart) >= 0 &&  
                   birthDate.compareTo(boomEnd)   <  0;  
        }  
    }  

    改进为:

    public class Person{  
        private Date birthDate;  
        private static final Date BOOM_START;  
        private static final Date BOOM_END;  
        static{  
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(“GMT”));  
        //婴儿潮开始时间  
        cal.set(1946, Calendar.JANUARY, 1, 0, 0, 0);  
    BOOM_START = cal.getTime();  
    //婴儿潮结束时间  
        cal.set(1965, Calendar.JANUARY, 1, 0, 0, 0);  
    BOOM_END = cal.getTime();  
        }  
        //判断是否是婴儿潮出生的人  
        public boolean isBabyBoomer(){  
             return birthDate.compareTo(BOOM_START) >= 0 && birthDate.compareTo(BOOM_END) < 0;  
       }  
    }  

    可以看出,第一个Person类的isBabyBoomer方法会导致很多对象的创建,改进后使用static代码块,并将BOOM_START和BOOM_END设置为静态方法。这两个对象便只需对象new的时候创建一次。

    6,消除过期的对象引用

    一般而言,只要类是自己管理内存,程序员就应该警惕内存泄漏问题。一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。

    这一条,还是需要结合具体应用场景和实例来谈才有意义。以后遇到类似问题再来补充。

    书中的那个例子感觉挺蠢的,那个pop方法,正常人思维都是会释放其引用:

    import java.util.*;  
      
    public class Stack {  
        private Object[] elements;  
        private int size = 0;  
        private static final int DEFAULT_INITIAL_CAPACITY = 16;  
      
        public Stack() {  
            elements = new Object[DEFAULT_INITIAL_CAPACITY];  
        }  
      
        public void push(Object e) {  
            ensureCapacity();  
            elements[size++] = e;  
        }  
      
        public Object pop() {  
            if (size == 0)  
                throw new EmptyStackException();  
            return elements[--size];  
        }  
      
        /** 
         * Ensure space for at least one more element, roughly 
         * doubling the capacity each time the array needs to grow. 
         */  
        private void ensureCapacity() {  
            if (elements.length == size)  
                elements = Arrays.copyOf(elements, 2 * size + 1);  
        }  
    }  
    public Object pop() {    
        if (size == 0)     
            throw new EmptyStackException();    
        Object result = elements[--size];    
        elements[size] = null;  
        return result;    
    }  
  • 相关阅读:
    实体类调用泛型父类中的静态方法中执行CRUD——第一版
    Windows10 磁盘100%解决办法
    Torchvision 源码安装[Ubuntu]
    Pycharm调试:进入调用函数后返回
    Windows 10 家庭版/专业版 彻底关闭windows update自动更新
    Windows10 家庭版 关闭Windows defender
    Windows 10 更改系统文字大小
    Ubuntu 使用命令行连接无线网
    支持向量机(SVM)
    Ubuntu系统实现将Jupyter notebook项目发布到GitHub
  • 原文地址:https://www.cnblogs.com/rixiang/p/5701398.html
Copyright © 2011-2022 走看看