【重拾Effective Java】一

之前看这本《Effective Java(第二版)》都是很早以前了,这本书确实是本好书,需要细嚼慢咽,每次看都有不同的体验。在此写博客巩固一下。

第一章.创建和销毁对象

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

   

通常我们获取类的实例,较为常用的方法是使用构造器,而这里要讲的是使用公有的静态工厂方法(注意:静态工厂方法和设计模式中的工厂方法模式是不同意思)

  • 静态工厂方法与构造器的不同,第一优势是它们有名称。如果构造器的参数本身没有确切的描述正被返回的对象,那么具有名称的静态工厂会更容易使用,代码也将更易理解。一个类只能有一个带有指定签名的构造器,当然我们可以通过不同参数去制作多个构造器,不过这带来的麻烦是让代码更加复杂,或者是记不住。而静态方法有名称,所以不受限制。
  • 静态工厂方法不必在每次被调用的时候创建一个新的对象。静态工厂方法能够为重复的调用返回相同的对象,这样有助于类总能严格控制在某个时刻哪些实例应该存在,这种类被称作实例受控的类。
  • 静态工厂方法可以返回原返回类型的任何子类型的对象。公有的静态工厂方法所返回的对象的类不仅可以是非公有的,而且该类还可以随着每次调用而发生变化,这取决与静态工厂的参数值。只要是已声明的返回类型的子类型,都是允许的。静态工厂方法返回的对象所属的类,在编写包含该静态工厂方法的类可以不必存在。这中灵活的静态工厂方法构成了服务提供者框架的基础。服务提供者框架:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。服务提供者框架中有三个重要的主键:服务接口,这个是提供者实习的,提供者注册API,这是系统用来实现注册,为了让客户端访问它们的,服务访问API,是客户端用来获取服务的实例的,服务访问API一般允许但是不要求客户端指定某种提供者的条件,如果没有这样的规定,API就会返回默认实现的一个实例,服务访问API是“灵活的静态工厂”,它构成了服务提供者框架的基础。服务提供者的第四个接口是可选的,服务提供者接口,这些提供者负责创建其服务实现的实例。如果没有服务提供者接口,实现就按照类名称注册,并通过反射方式进行实例化。
  • 静态工厂方法在创建参数化类型实例的时候,代码更加简洁,如下的一段代码:
    Map<String,List<String>>  map=
      new HashMap<String,List<String>>();//这样的写法比较麻烦   <pre name="code" class="java">//假设HashMap 提供了这个静态工厂:
    public static <K,V> HashMap<K,V> newInstance(){
               return new HashMap<K,V>();
    }
    
    //那么我们就可以这么写,如下
    Map<String,List<String>> map=HashMap.neweInstance();
     
  • 静态工厂方法的缺点:类如果不含有公有的或者受保护的构造器,就不能被子类化,对于公有的静态工厂所返回的非公有类,也是这样。
  • 静态工厂方法的缺点:它们与其他静态方法实际上没有任何区别。

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

       静态工厂和构造器都有局限性,不能很好的扩展到大量的可选参数。通常我们习惯采用重叠的构造器

public A(int a,int b){

   this.A(a,b,1);
}
public A(int a,int b,int c){
     ///////
}
我们可以发现,重叠构造器是可行的,不过面对多个参数时,就会异常复杂了。那么我们就要用到JavaBeans模式了。

public int a=0;
public int b=0;
public int c=0;

public A(){
   public void seta(int a){
this.a=a;
}
public void setb(int b){
this.b=b;
}
public void setc(int c){
this.c=c
}
}
这样就弥补了重叠构造器的复杂的不足。不过,JavaBeans本身也是有缺陷的,因为构造过程被分割到几个调用中,在构造过程中JavaBeans可能处于不一致的状态,类无法仅仅通过检验构造器参数的有效性来保持一致性。视图使用处于不一致状态的对象,将会导致失败。


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

singleton指仅仅被实例化一次的类,Singleton往往用来代表那些本质上唯一的系统组件。

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

有时候我们需要编写只包含静态方法和静态域的类,常常我们需要用到java.lang.Math里的方法,其中的调用就是如此。

避免创建不必要的对象

通常最好能重用对象而不是在每次需要的时候就创建一个相同功能的新对象,对于同时提供了静态工厂方法和构造器的不可变类,通常可以使用静态工厂方法而不是构造器,以避免创建不必要的对象。通过维护对象池来避免创建对象并不是一种好的做法,除非池中的对象是非重量级的。真正正确使用对象池的典型是数据库链接池,建立数据库链接的代价输很昂贵的,所以重用这些对象就非常有必要了。

消除过期的对象引用

消除过期的引用最好的办法是让包含该引用的变量结束其生命周期,如果是在最紧凑的作用域范围内定义每一个变量,这种就会发生。一般来说,只要是自己管理内存的,我们就应当警惕内存泄漏问题,一旦元素被释放掉,则该元素中包含的任何对象引用都应该被清空。内存泄漏的一个常见来源缓存,一旦你把对象的引用放到缓存中,就很容易被遗忘掉。内存泄漏的另一个来源监听器和其他回调,如果你实现了一个API,客户端在这个API中注册回调,却没有显示地取消注册,那么除非你采取某些动作,否则就会累积,解决方案是只保存它们的弱引用。

你可能感兴趣的:(java)