天天看点

浅析Effective Java 书中提到重要的规则-1

1. 考虑用静态工厂方法代替构造器

分析:

   优势一:静态工厂方法有表达特殊意义的名字,可以进行需要的表述,更容易使用更容易于别人对你代码的阅读理解;

   优势二:不需要在每次使用这个方法的使用创建新的对象。如果程序经常创建这个对象,而且创建一个对象花费的性能成本很高,那么采用这种的方式可以极大提高性能;

   优势三:静态工厂方法可以返回原类型任何子类型的对象;一些基于接口一的框架就使用了这个特点;

   优势四: 创建参数化类型实例的时候,使得代码更加的简洁;

对比如下:

调用参数化构造器时:需要两次提供参数类型

实例化代码:

   Map <String ,List<String>> m = new HashMap<String,List<String>>();

采用静态工厂方法后: 由编译器匹配类型参数,又叫:类型推导

可以编写静态工厂方法:

   public static Map<K,V> HashMap<K,V> newInstance()

   {

       return new HashMap<K,V>();

   }

实例化代码如下:

Map <String,List<String>> m = HashMap.newInstance();

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

   当一个类实例化时需要指定初始化多个参数时,考虑采用构建器完成初始化工作;推荐builder模式;

有很多参数时,通常的处理是编写很多个构造器,虚拟机根据匹配选择合适的构造器完成初始化。或者是采用java bean的模式,给每个成员变量定义 set方法完成初始化赋值;这里推荐一种更好的方式,Builder模式进行初始化工作;示例代码见附件:Builder模式示例代码;

好处:一旦赋予的参数值不匹配时就会提示错误,不允许实例化。使用Builder构建器的代码易于阅读编写,比Java bean的模型更加安全;

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

分析:    

   Singleton指的是仅仅被实例化一次的类。常常用来代表那些本质上唯一的组件。

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

分析:

   很多的类我们不需要进行实例化,我们只是使用它提供的静态方法。我们可以使用private关键字修饰的构造器,使得类不能被实例化,不能被子类化;

因为在实例化或实例化一个类的子类的时候必须调用该类的构造器完成实例化。当它被private修饰了,就不能从外部调用,就不能完成实例化工作。

5. 避免创建不必要的对象

   这个主要体现在使用那些不可变对象身上比如String类型对象,在需要多次创建String对象时,例如:String str = new String("我是一个字符窜");这里会创建2个对象,中加入在一个循环中调用这行代码,可想而知会有多少个不必要的对象产生。

对于这种情况可以有以下几种处理方式:

   第一: 单是对于String对象,我们可以利用虚拟机中的字符串常量池来重用对象;String str = "我是一个字符串" ;这里会产生1个对象,之后有新的代码: String str2 = "我是一个字符串" ; 那么也不会再次产生新的对象了,str、str2 指向同样的一个对象;

   第二: 尽量使用静态工厂方法,避免新的对象产生;

   第三: 对于知道的不会改变的可变的对象,我们也尽量重用它。使用静态代码块保证内存中只有一个对象;

例如:

class   Student{

   private final Date birthday ;

   private static final Date boom_start;

   private static final Date boom_end;

   static {

       Calendar = gmtCal = Calender.getInstance(TimeZone.getTimeZone("GMT"));

       gmtCal.set(1946,Calendar.JANUARY,1,0,0,0);

       boom_start = gmtCal.getTime();

       boom_end = gmtCal.getTime();            

}

 说明:Student 类是一个可变的对象,但是计算每一个学生的生日的方式是不变的,每一个学生的生日是不变的,final保证之后不会发生改变;静态代码块里,Calender对象只会被生产一次。

6. 消除过期的对象引用

   java虚拟机有垃圾回收器会定期清除过期的对象,但是当一个对象被无意识的保留下来了,垃圾回收器就不会回收了他,就可能造成内存泄露。比如Stack类自己管理着内存,垃圾回收器并比想人一样知道哪些是可以回收的,所以当出栈时应该手动清空这些数组元素;

7. 避免使用终结方法

   终结方法(finalizer )是不可预测的,是一个危险的方法,使用这个方法可能会导致系统行为不稳定,性能下降,以及可移植性降低等;当然也有它的用处,不推荐重写;

   值得引起重视的: 终结方法里创建销毁对象会比不使用终结方法创建销毁对象速度慢几百倍;

                   不应该利用终结方法来更新重要对象的持久状态,因为这个方法的执行优先级较低,不能保证及时被执行;

                   也有显示终结方法运用的地方,InputStream,OutputStream 等 IO流处理中会显示的调用close()方法关闭流;

   使用情况: 作为安全网 或者用于终止本地非关键的资源文件;子类重写了父类的终结方法,应该确保调用父类的终结方法(super.finalizal方法)

继续阅读