之前看这本《Effective Java(第二版)》都是非常早曾经了。这本书确实是本好书。须要细嚼慢咽,每次看都有不同的体验。
在此写博客巩固一下。
第一章.创建和销毁对象
考虑用静态工厂方法取代构造器
通常我们获取类的实例,较为经常使用的方法是使用构造器。而这里要讲的是使用公有的静态工厂方法(注意:静态工厂方法和设计模式中的工厂方法模式是不允许思)
- 静态工厂方法与构造器的不同,第一优势是它们有名称。假设构造器的參数本身没有确切的描写叙述正被返回的对象,那么具有名称的静态工厂会更easy使用,代码也将更易理解。一个类仅仅能有一个带有指定签名的构造器,当然我们能够通过不同參数去制作多个构造器,只是这带来的麻烦是让代码更加复杂,或者是记不住。而静态方法有名称。所以不受限制。
- 静态工厂方法不必在每次被调用的时候创建一个新的对象。静态工厂方法能够为反复的调用返回同样的对象。这样有助于类总能严格控制在某个时刻哪些实例应该存在,这种类被称作实例受控的类。
- 静态工厂方法能够返回原返回类型的不论什么子类型的对象。
公有的静态工厂方法所返回的对象的类不仅能够是非公有的,并且该类还能够随着每次调用而发生变化,这取决与静态工厂的參数值。仅仅要是已声明的返回类型的子类型,都是同意的。
静态工厂方法返回的对象所属的类,在编写包括该静态工厂方法的类能够不必存在。这中灵活的静态工厂方法构成了服务提供者框架的基础。服务提供者框架:多个服务提供者实现一个服务,系统为服务提供者的client提供多个实现。并把他们从多个实现中解耦出来。服务提供者框架中有三个重要的主键:服务接口,这个是提供者实习的。提供者注冊API。这是系统用来实现注冊,为了让client訪问它们的,服务訪问API。是client用来获取服务的实例的。服务訪问API一般同意可是不要求client指定某种提供者的条件。假设没有这种规定,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里的方法,当中的调用就是如此。
避免创建不必要的对象
通常最好能重用对象而不是在每次须要的时候就创建一个同样功能的新对象,对于同一时候提供了静态工厂方法和构造器的不可变类,通常能够使用静态工厂方法而不是构造器,以避免创建不必要的对象。通过维护对象池来避免创建对象并非一种好的做法,除非池中的对象是非重量级的。
真正正确使用对象池的典型是数据库链接池,建立数据库链接的代价输非常昂贵的,所以重用这些对象就非常有必要了。
消除过期的对象引用
消除过期的引用最好的办法是让包括该引用的变量结束其生命周期。假设是在最紧凑的作用域范围内定义每个变量,这样的就会发生。一般来说,仅仅要是自己管理内存的,我们就应当警惕内存泄漏问题,一旦元素被释放掉,则该元素中包括的不论什么对象引用都应该被清空。
内存泄漏的一个常见来源缓存。一旦你把对象的引用放到缓存中,就非常easy被遗忘掉。
内存泄漏的还有一个来源监听器和其它回调,假设你实现了一个API,client在这个API中注冊回调。却没有显示地取消注冊,那么除非你採取某些动作。否则就会累积。解决方式是仅仅保存它们的弱引用。