Effective Java 读书笔记(一)

ForCleanCode 为笔者读书总结,出于自身理解目的总结!

Effective Java 读书笔记(一)_第1张图片
JoshBloch.jpg

一丶对象的创建和销毁
(一) 静态工厂方法替代构造器

1.静态工厂方法的几大优势:

(1) 静态工厂方法与传统构造器方法不同的第一大优势 ,他们有名称:

sample:返回一个素数

public static int BigInteger.probablePrime(int, int, Random){}

(2)不必再每次调用它的时候都创建一个新的对象:

sample:重复利用 预先创建好的实例,如布尔b

 /**
     * 1 确保他是一个Singleton
     * 2 可用 == 替代 equals,判断相等 提升性能
     * @param b
     * @return
     */
 public static Boolean valueOf(boolean b){
        return b ? Boolean.TRUE:Boolean.FALSE;
    }

(3)可以返回原返回类型的任何子类型的对象,提高灵活性

sample: java.util.EnumSet 为例子

/**
     * 1 如果他的元素<=64 return RegularEnumSet
     * 2 否则 return JumboEnumSet
     * 3 class RegularEnumSet> extends EnumSet 都是他的子类
     * 4 对客户端不可见 根据参数返回适配类型  更加灵活
     * @param elementType
     * @param 
     * @return
     */
    public static > EnumSet noneOf(Class elementType) {
        Enum[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);
    }

(4) 在创建参数化类型实例的时候,使代码变得更加简洁:

sample:已实例化单个HashMap为例子:

 /**
     * 传统写法
     *   缺点:如果HashMap参数 很多 特别冗长 ,实例化起来写长参数 会很麻烦
     */
    Map> mMap = new HashMap>();

    /**
     * 静态工厂方法
     *      省下了手写实例化后的参数
     */
    Map> mStaticMap = newInstance();

    /**
     *  J神说 目前HashMap 并没有工厂方法(可以放自己的工具类中)
     *      在以后java版本中可能会看到
     *      
     * @param 
     * @param 
     * @return
     */
    public static  HashMap newInstance(){
        return new HashMap();
    }

2丶静态工厂方法的缺点

(1)类如果不含有公有的或者受保护的构造器,就不能被子类化

sample: 比如 Collections 和 Framework, 构造方法私有化 肯定就不能被实例化了。。。。

(2)静态工厂与其他静态方法实际没有任何区别。

sample:
比如你实例化一个TextView 他是通过构造器 实例化的,你找到对应的对象通过Ctrl+左键和容易定位
到 该对象所实例化的构造方法。
但是通过静态工厂 返回给你的实例化对象,是如何实例化的很难找到。

    但是J神又说了  Javadoc总有一天会注意到这些静态工厂方法的(但是目前 java8 还没实现 嘻嘻嘻)

(二)遇到多个构造器参数时要考虑用构造器

静态工厂和构造器有个共同的局限性:不能很好的扩展到大量的参数。

(1)从迭代构造器角度考虑:

sample:迭代构造器我们遇到了太多了,比如常见的自定义View


/**
 *  根据传入参数的数量挨个迭代,直到三个参数的构造器为止
 * Created by zhaoyuanchao on 2018/4/21.
 */

public class SampleView extends View {
    public SampleView(Context context) {
        this(context, null);
    }

    public SampleView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SampleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    
}

缺点:
构造器调用通常需要许多你根本不想设置的参数,但是由于构造器限制 不得不为他传值, 如果有10个参数那种构造器,就会很快失去控制 相当的不灵活。

(2)JavaBean模式考虑:
sample:可以很好的处理每个必要的可选参数,创建实例容易


/**
 * Created by zhaoyuanchao on 2018/4/21.
 */

public class SampleBean {
    private String a;
    private String b;

    public SampleBean() {
    }

    public void setA(String a) {
        this.a = a;
    }

    public void setB(String b) {
        this.b = b;
    }
}

缺点:
JavaBean 由于构造过程被分调到了 几个方法中,所以无法通过构造器的有效参数 来保证该类的一致性。
线程不安全。

(3)Builder模式:
sample: 既能保证像构造器那样的安全性,也能保证像JavaBean那样的可读性。


public class NutritionFacts {
    private final int a;
    private final int b;
    private final int c ;
    private final int d;
    private final int e;
    private final int f;

    public static class Builder{
        // 如 a b 为必须传入的值
        private final int a;
        private final int b;
        // c d e f为非必须传入的值
        private  int c = 0;
        private  int d = 0;
        private  int e = 0;
        private  int f = 0;

        public Builder(int a , int b) {
            this.a = a;
            this.b = b;
        }

        public Builder setC(int val){
            c = val;
            //这里面为什么要为什么要return 自身呢? 为了方便链式调用复制 c d e f
            return this;
        }
        public Builder setD(int val){
            d = val;
            return this;
        }
        public Builder setE(int val){
            e = val;
            return this;
        }
        public Builder setF(int val){
            f = val;
            return this;
        }

        public NutritionFacts build(){
            return new NutritionFacts(this);
        }
    }

    private NutritionFacts(Builder builder){
        a = builder.a;
        b = builder.b;
        c = builder.c;
        d = builder.d;
        e = builder.e;
        f = builder.f;
    }
}

调用方法:

 /**
   * 很常见一种实例化方法吧,我见过很多
   */
  NutritionFacts nutritionFacts = new NutritionFacts.Builder(10, 8).setC(1).
                setD(2).setE(3).setF(4).build();

缺点:
(1)为了创建对象,必须先创建Builder的构造器。
(2)Builder模式比重叠构造器更加冗长,只有在多参的时候才会用到(书上推荐>=4个参数)。

Builder模式的应用场景:
如果类的构造器或者静态工厂中有多个参数,Builder模式就是中不错的选择!

你可能感兴趣的:(Effective Java 读书笔记(一))