您的位置:首页 > Web前端

《Effective java》笔记(第二版) --第二章(1-3)

2016-12-28 17:28 225 查看

个人笔记

第二章 ——

第一条: 考虑用静态工厂方法代替构造器

静态工厂方法与构造器不同的第一大优势在于,它们有名字

new Integer(…)

返回一个Integer类型的实体,但是只是一个实体去构造,如果我想要Integer的最大值,就不那么清晰了,所有有了

public static final int MAX_VALUE;

用Integer.MAX_VALUE来使用,可以告诉别人这是一个Integer的成员,并且更直观

静态工厂方法与构造器不同的第二大优势在于,不必在每次调用它们的时候都创建一个新的对象

/这个static确保了加载的时候只初始化了一次(具体的搜索JVM的初始化顺序),防止了多次的构造/

静态工厂方法与构造器不同的第三大优势在于,它们可以返回原类型的任何子类对象

多态

静态工厂方法与构造器不同的第四大优势在于,在创建参数化实例的时候,它们使代码变得更简洁

/比如说我会联想到这样的东西/

Map

静态工厂方法的主要缺点在于,类如果不含public的或者对应的构造函数,就不能被子类化

//一开始大家相安无事

class Money{}

class Rmb extends Money{}

//后来

class Money{

private Money(){}

public static Money getInstance(){return new Money();}

}

/Rmb就不能继承了(每个子类都有一个父类的引用,static class除外),只有把这个构造改成public,protected的话,那么会导致工厂的方法和构造的方法共存,后面的子类就不能很好的继承了/

静态工厂方法的第二个缺点在于,它们与其他的静态方法实际没有任何区别

//API文档中构造方法都跑到了一起,但是你的工厂却混在普通的static方法里//面,别人去找只会恶心到别人,所以大家都用比较固定的名字,比如

newInstance, getInstance,of,valueOf,getType,Type

//之类的好记的名字来命名

第二条: 遇到多个构造器参数时要考虑用构建器

//设计模式的Builder模式,也就是,通过一个一个返回this的方法,实现对于构造的链式的构建方式,是不是想起了什么,好像c++中的参数化列表,比如

new MyClass(1,2,3,4,5,6,7)…

//可读性差,谁知道你修改了那个参数,修改起来很难受,但是

new MyClass().Builder(xx,xx).first(1),second(2)…build();

//相对就会非常顺眼和舒适,而first的声明也很简单

public MyClass first(int first){this.first = first;}

//build则是,对于之前所做的操作的this对象,调用构造方法

public MyClass build(){return MyClass(this);}

//很少的参数就没必要多此一举,以免增加没必要的API

//Builder模式,先获取Builder器,需要创建一个Builder对象,多余的数据域,导致额外的开销,最好一开始就用它

//其他的,比如说做web开发经常看到的javaBean是这个样子的

public class User {

private int psw;

private int account;

public int getPsw() {
return psw;
}

public void setPsw(int psw) {
this.psw = psw;
}

public int getAccount() {
return account;
}

public void setAccount(int account) {
this.account = account;
}


}

//规规矩矩的方法命名,其实这只是用来做反射然后那参数拼接的,一种约定

User u;

u.setAccount(233);

u.setPsw(233);

…//如果参数越来越多,对应的setter和getter方法越来越多,仅仅搞程序员的自觉是不能保证这些数据域都被正确初始化的

//再思考一个问题,既然有这么多的set和get方法,意味着用户(使用这个class的人)能够对其中的数据域随意进行修改

//如果是恶意的用户,他可能会开一个Thread对数据域进行各种修改,那么会导致我们读到的数据不再可靠,用户需要用同步,付出额外的努力来实现这个类的可靠和线程的安全

//幸运的是,你只要使用上面的Builder模式就能够避免暴露这些接口

//懂得使用反射的用户会知道Class.newInstance可以调用默认构造,那么,这个方法本身是抛出

InstantiationException,IllegalAccessException

/这样的异常,但是,在你外围对这个newInstance的try catch块中,却不能检测出这个Class.newInstance所调用的构造方法如果抛出异常,用户将会失去catch掉这个异常的权利,而吧这个异常传播到外面去,通常会导致你的应用瞬间爆炸/

第三条: 用私有的构造器或者枚举类型强化Singleton属性

//Singleton属性指的是唯一的,不能多个实例化的属性,比如windows只有一个资源管理器,文件系统

实现方法有几种 1.5之前

//构造函数私有化,声明一个调用私有构造的公共静态数据域构造自身,来访问,但是java的反射能够通过Class.setAccessible改变权限来调用构造方法,为了防止别人这样做,加一个flag,并且在第二次构造的时候throw一个异常

//静态工厂方法 ,和上面步骤↑一样,但是这个静态的数据域改为私有,暴露工厂方法来返回这个静态的数据域,但是缺点还是需要throw来避免
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java