今天开始看Effective Java 2nd,坚持每天抽大概2小时来看,每天30页左右,看完后写读书笔记。
第1条 考虑用静态工厂方法代替构造器
此处静态工厂和设计模式中的工厂模式并不能直接对应,设计模式中的工厂模式在《java与模式》中介绍有三种,简单工厂模式,工厂模式,抽象工厂模式。而此处的静态工厂方法可以看做简单工厂模式中工厂角色和产品角色合并后的结果。
静态工厂方法相对于构造器有3个优势,名称,对实例的控制(单例,多例,或者每次返回新实例),对实例类型的控制(返回子类型)。从名称来说,如果一个类有多个构造器时,有可能我们并不能从参数上来区分开来每个构造器的不同之处,这时带有名称的静态工厂方法就可以明确的说明了。对实例的控制来说,这个也比较容易理解,用构造器实例化对象,每次都是返回的新对象。而静态工厂方法就可以控制返回对象,类似于享元模式。对于返回类型的控制上面来说呢,这个静态工厂方法的返回类型就比较灵活了。说到这里想起在工作当中的一个事情,程序难免会有异常,异常呢一般会在日志中体现出来,但是不可能每天都跑去翻查日志吧。。。所以公司需要将各个应用都吧错误日志发都一个应用上面方便统一查看。其实这个就需要在log4j写日志的时候发一个http请求而已。代码的日志类一般是这样写的:
Private static Log log = LogFactory.getLog(“name”);
也就是用的apache 的 common-logging来实现的,这个就是抽象工厂模式的一个应用了。其实这个就是自定义一个log实现log接口就可以了。然后告诉LogFactory实例化这个log就行了。而这个就体现出静态工厂方法在这方面的一个灵活性了。不用改变接口,就可以实现不同的行为(返回不同的子类型)。
还有一个优势在于使用泛型时。在实例化一个泛型的类时通常需要连续两次提供泛型参数。而有了静态工厂方法,编译器可以替你找到类型参数。
第2条 遇到多个构造器参数时考虑用构建器(builder模式)
对于有多个成员变量的类在实例化的时候需要初始化时,一般还有3种方法,一是采用telescoping constructor模式:
public Constructor(int para1,int para2){
this(para1,para2,default)
}
public Contructor(int para1,int para2,int para3){
…//初始化对象
}
第二种是采用JavaBean模式,实例化类后调用对应的set方法设置值。缺点呢,就是在调用方法时对象可能处于不一致的状态(书中原话,不太懂),还有就是暴露出了一些set方法,不能把类做成不可变了。
第三种就是采用builder模式,另外创建一个builder对象,builder对象中有待build对象的参数,设这好builder对象参数后调用builder对象build方法(当然方法名不一定就是这个)就可以生成一个待build对象。Builder模式的缺点你就是需要额外创建一个builder对象,所以在构造器或者静态方法中有多个参数时可以考虑builder模式。
第3条 使用枚举类型强化Singleton属性
直接上代码吧:
public enum ClassName {
INSTANCE:
public void method(){…}
}
通过调用ClassName.INSTANCE.method() 调用相应方法。
引用书中一句话:单元素的枚举类型已经成为实现Singleton的最佳方法。
第4条 通过私有构造器强化不可实例化类的能力
这一条其实就是在一些只有static方法的类中显示声明私有构造器(无构造器时有一默认无参构造器)。
第5条 避免创建不必要的对象
有一些不可变类,能重用就重用,而没必要每次都去创建。比如不变的时间。
引用书中一句话:要优先使用基本类型而不是装箱基本类型,要当心无意识的自动装箱
当你想用对象池时要仔细想想到底值得否。
第6条 消除过期的对象引用
只要类时自己管理内存的时候,就要警惕内存泄露的问题,当使用缓存的时候也要当心内存泄露。缓存应该要定时清理掉无用的项。这里提到了WeakHashMap,弱引用的hashmap,当某个key还有引用时hashmap中就会一直存在,无引用时,在对WeakHashMap操作时put 或者 get ,无引用的key就会被清除掉。
第7条 避免使用终结方法(finalizer)
finalizer方法是在对象被销毁时触发调用的,但是不同的JVM实现调用的时间点不能保证,很有可能就不会调用。所以需要一般会显示的实现一些终结方法放在try-catch-finally中finally调用。当然有一些非常关键的资源还是需要在finalizer中释放的,比如关闭文件。而且使用了终结方法后记住调用super.finalize(),还有就是防止子类未调用super.finalize()时可考虑使用终结方法守卫者(finalizer guardian).