《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对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- Debian 7.x 安装Oracle JAVA
- springmvc实现url路由功能
- spring boot 配置 druid/** * 配置druid * Created by adam on 4/11/16. */ @Configuration public class D
- api接口rsa加密