• 《EffctiveJava》创建和销毁对象


    创建和销毁对象

    用静态工厂方法代替构造器

    相比构造器的优点

    • 有名称:可以更明确方法的功能;
    • 不必在调用时重复创建实例:使不可变类预先创建实例,或将实例缓存起来,避免重复创建对象,提高性能。
    • 返回原返回类型的子类型的对象。
    • 在创建参数化类型实例时,代码更简洁
      Map<String, List<String>> map = new HashMap<String, List<String>>();
      // 用静态工厂方法实现
      Map<String, String> map = HashMap.newInstence();
      

    相比构造器的缺点

    • 类如果不含共有的或者受保护的构造器,将不能被子类化。
    • 与其他的静态方法没任何区别。
      静态工厂方法的一些命名习惯
      – valueOf:类型转换方法
      – of:更简洁的替代,在EnumSet中使用并流行起来
      – getInstance:对于Singleton来说,该方法没有参数,只会返回一个实例。
      – newInstance:与getInstance一样,但newInstance能够确保每个新实例与其他实例不同。
      – getType:像getInstance一样,返回对象类型
      – newType:想newInstance一样,返回对象类型

    综上:构造器和静态工厂方法各有优缺点,优先使用静态工厂方法。

    遇到多个构造器参数时要考虑用构建器

    Builder模式:利用多个builder构建多个对象。推荐在多参数且参数大多数都是可选的的情况下使用。

    • 优点:易于阅读和编写,比JavaBean更安全。
    • 缺点:比重叠构造器冗长。

    Builder模式示例:

    public class NutritionFacts {
    
        private final int servingSize;
    
        private final int servings;
    
        private final int colorings;
    
        private final int fat;
    
        private final int sodium;
    
        private final int carbohydrate;
    
        public static class Builder {
            // 必须的
            private int servingSize = 0;
    
            private int servings = 0;
    
            // 非必须的
            private int colorings = 0;
    
            private int fat = 0;
    
            private int sodium = 0;
    
            private int carbohydrate = 0;
    
            public Builder(int servingSize, int servings) {
                this.servings = servings;
                this.servingSize = servingSize;
            }
    
            public Builder calories(int colorings) {
                this.colorings = colorings;
                return this;
            }
    
            public Builder carbohydrate(int carbohydrate) {
                this.carbohydrate = carbohydrate;
                return this;
            }
    
            public Builder sodium(int sodium) {
                this.sodium = sodium;
                return this;
            }
    
            public Builder fat(int fat) {
                this.fat = fat;
                return this;
            }
    
            public NutritionFacts build() {
                return new NutritionFacts(this);
            }
        }
    
        private NutritionFacts(Builder builder) {
            this.servingSize = builder.servingSize;
            this.servings =  builder.servings;
            this.colorings =  builder.colorings;
            this.fat =  builder.fat;
            this.sodium =  builder.sodium;
            this.carbohydrate =  builder.carbohydrate;
        }
    }
    
    

    调用:

     NutritionFacts nutritionFacts = new NutritionFacts.Builder(1, 2)
     				.calories(3).carbohydrate(4).fat(5).sodium(6)
                    .build();
    

    用私有构造器或枚举类型强化Singleton属性

    Singleton是指仅仅被实例化一次的类。Singleton通常被用来表示那些本质上唯一的系统组件,例如窗口管理器或文件系统。

    方式一:

    public class Elvis {
    
        private Elvis() {
            // 初始化相关操作
        }
    
        public static final Elvis INSTANCE = new Elvis();
    
        public void leaveTheBuilding() {
            // ...
        }
    }
    

    使用:

    Elvis.INSTANCE;
    

    方式二:

    public class Elvis {
    
        private Elvis() {
            // 初始化相关操作
        }
        private static final Elvis INSTANCE = new Elvis();
    
        public static Elvis getInstance() {
            return INSTANCE;
        }
    
    }
    
    

    使用:

    Elvis.getInstance();
    

    通过私有构造器强化不可实例化的能力

    一些工具类不希望被实例化,实例化对它没有任何意义。

    public class UtilityClass {
    
        /**
         * 私有构造方法,保证在任何情况下都不会被实例化
         */
        private UtilityClass() {
            // 防止在当前类调用构造方法
            throw new AssertionError();
        }
    
        public static boolean empty(String message) {
            if (message == null || "".equals(message)) {
                return Boolean.TRUE;
            }
            return Boolean.FALSE;
        }
    }
    

    使用:

     UtilityClass.empty("hello Word");
    

    避免创建不必要的对象

    • 正确使用String
      反例:
    String s  = new String("hello");	// hello本来就是字符串
    

    正确:

    String s = "hello";
    
    • 自动装箱
      优先使用基本类型。

    消除过期的对象引用

    一般而言,只要类是自己管理内存,就应该警惕内存泄漏的问题。

    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) {
    
            }
            Object e = elements[--size];
            elements[size] = null;
            return e;
        }
    
        private void ensureCapacity() {
            if (elements.length == size) {
                elements = Arrays.copyOf(elements, 2 * size+1);
            }
        }
    }
    
    

    避免使用终结方法

    try finally

    有梦为马,游历天涯!
  • 相关阅读:
    Codeforces Round #348 (VK Cup 2016 Round 2, Div. 2 Edition) D. Little Artem and Dance
    HDU 5521 Meeting 最短路
    BZOJ 1051: [HAOI2006]受欢迎的牛 强连通缩点
    P2661 信息传递 强连通分量
    Codeforces Round #343 (Div. 2) C. Famil Door and Brackets
    HDU 4859 海岸线 最小割
    HDU 4162 Shape Number
    Codeforces Round #355 (Div. 2) D. Vanya and Treasure dp+分块
    bzoj 1295: [SCOI2009]最长距离 暴力+bfs最短路
    Codeforces Round #222 (Div. 1) C. Captains Mode 对弈+dp
  • 原文地址:https://www.cnblogs.com/qijianguo/p/10686343.html
Copyright © 2020-2023  润新知