第一章 引言
1.Java语言支持四种类型:接口/类/数组和基本类型。前三种通常被称为引用类型。
2.类的成员由它的域。方法。成员类和成员接口组成。方法的签名由它的名称和所有参数类型组成,签名不包括它的返回类型。
第二章 创建和销毁对象
1.第1条:考虑用静态工厂方法代替构造器
优势:(1)有名称
(2)不必每次调用都创建一个新对象
(3)可以返回原返回类型的任何子类型的对象
(4)在创建参数化类型实例的时候,使代码更简洁
缺点:(1)类如果不含公有的或者受保护的构造器,就不能被子类化
(2)与其他静态方法实际上没有任何区别
2.服务提供者框架:多个服务提供者实现了一个服务,系统为服务提供者的客户端提供多个实现,并把他们从多个实现中解耦出来。
该框架的三个重要组件:(1)服务接口,提供者实现的;
(2)提供者注册API,这是系统用来注册实现,让客户端访问它们的;
(3)服务访问API,客户端用来获取服务的实例的。
(4)服务提供者接口,这些提供者负责创建其服务实现的实例。(可选)
3.第2条:遇到多个构造器参数时要考虑用构建器
重叠构造器模式
JavaBeans模式
Builder模式
4.第3条:用私有构造器或者枚举类型强化Singleton属性
//单例模式实现序列化需要添加ReadResolve方法
public class Singleton implements Serializable{
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
private Object readResolve() {
return singleton;
}
}
<span style="color:#000000">public enum Elvis{
INSTANCE;
public void leaveTheBuilding(){...}
}</span>
注:这种方法在功能上与公有域方法相近,但是它更加简洁,无偿地提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击的时候。虽然还未广泛采用,但单元素的枚举类型已经成为实现Singleton的最佳方法。
第四章 类和接口
1.第15条:使可变性最小化
使类成为不可变,遵循以下五条规则:
(1)不要提供任何会修改对象状态的方法;
(2)保证类不会被扩展;
(3)使所有的域都是final的;
(4)使所有的域都成为私有的;
(5)确保对任何可变组件的互斥访问。
//确保类不可变性,类不允许自身被子类化。两种方法:
//1.使类成为final的
//2.让类的所有构造器都变成私有的或者包级私有的,并添加共有的静态工厂来代替公有构造器。
public class Complex{
private final double re;
private final double im;
private Complex(double re,double im){
this.re = re;
this.im = im;
}
public static Complex valueOf(double re,double im){
return new Complex(re,im);
}
}
2.第16条:复合优先于继承
3.第17条:要么为继承而设计,并提供文档说明,要么就禁止继承
4.第18条:接口优于抽象类
现有的类可以很容易被更新,以实现新的接口。
接口是定义mixin(混合类型)的理想选择。
接口允许我们构造非层次结构的类型框架。
5.第19条:接口只用于定义类型
6.第20条:类层次优于标签类
7.第21条:用函数对象表示策略
函数对象:一个类仅导出通过对象引用实现的方法,她的实例实际上就等同于一个指向该方法的指针。
函数指针的主要用途是实现策略模式。
8.第22条:优先考虑静态成员类
嵌套类:静态成员类,非静态成员类,匿名类和局部类
内部类:非静态成员类,匿名类和局部类
第五章 泛型
1.第23条:请不要在新代码中使用原生态类型
原生态类型:不带任何实际类型参数的泛型名称。
如果使用原生态类型,就失掉了泛型在安全性和表述性方面的所有优势。
虽然你可以将List<String>传递给类型List的参数,但是不能将它传给类型List<Object>的参数。泛型有子类型化的规则,LIst<String>是原生态类型List的一个子类型,而不是参数化类型LIst<Object>的子类型。因此,如果使用像List这样的原生态类型,就会失掉类型安全性,但是如果使用像List<Object>这样的参数化类型,则不会。
无限制的通配符类型:要使用泛型,但不确定或者不关心实际的类型参数,可以使用一个问号代替。
该规则的两个例外:(源于“泛型信息可以在运行中被擦除”)
(1)在类文字中必须使用原生态类型。规范不允许使用参数化类型(虽然允许数组类型和基本类型):List.class,String[].class和int.class都合法,但List<String>.class和List<?>.class则不合法。
(2)在参数化类型而非无限制通配符类型上使用instanceof操作符是非法的。用无限制通配符类型代替原生态类型,对instanceof操作符的行为不会产生任何影响。在这种情况下,尖括号(<>)和问号(?)就显得多余了。
if(o instanceof Set){
Set<?> m = (Set<?>)o;
}
2.第24条:消除非受检警告
编译器警告:非受检强制转化警告(unchecked cast warnings),非受检方法调用警告,非受检普通数组创建警告,以及非受检转换警告(unchecked conversion warnings)。
如果无法消除警告,同时可以证明引起警告的代码是类型安全的,只有在这种情况下才可以用一个@SuppressWarnings("unchecked")注解来禁止这条警告。但应始终在尽可能小的范围中使用该注解。
每当使用SuppressWarnings("unchecked")注解时,都要添加一条注解,说明为什么这么做是安全的。
3.第25条:列表优先于注解
数组与泛型相比,两个不同点:(1)数组是协变的,泛型是不可变的(2)数组是具体化的,数组在运行时才知道并检查它们的元素类型约束,泛型是通过擦除实现的,所以泛型只在编译时强化它们的类型信息。
4.第26条:优先考虑泛型
将类泛型化的第一个步骤是给它的声明添加一个或者多个类型参数。
5.第27条:优先考虑泛型方法
泛型方法的一个显著特性是,无需明确指定类型参数的值,不像调用泛型构造器的时候是必须指定的。编译器通过检查方法参数的类型来计算类型参数的值。
6.第28条:利用有限制通配符来提升API灵活性
producer-extends,consumer-super(PECS)
7.第29条:优先考虑类型安全的异构容器