尽可能地使每个类或者成员不能被外界访问。
公有类的实例域绝不能是公有的。
包含公有可变域的类通常并不是线程安全的。
让类具有公有的静态 final 数组域,或者这种域的访问方法是错误的。
公有类永远都不要暴露可变的的域
不可变类是指实例不可以被修改的类
17.1 不可变类要遵循的五条原则:
17.2 不可变对象的优缺点:
如果类不能做成不可变的,仍然应尽可能地限制它的可变性
除非有令人信服地理由要使域变成是非 final 的,否则要使每个域都是 private final 的
构造器应该创建完全初始化对象,并建立所有约束关系
越包继承是非常危险的。
与方法调用不同的是,继承打破了封装性。
复合:不扩展现有的类,而是在新的类中增加一个私有域,它引用现有类的一个实例。
该类必须有文档说明它可覆盖的方法和自用性
可覆盖的方法:非 final 的,公有的或者受保护的。
对于为了继承而设计的类,唯一的测试方法是编写子类,发布之前必须对子类就那些测试。
构造器绝不能调用可被覆盖的方法。
无论是 clone 还是 readObject,都不可以调用可覆盖的方法。
为了继承而设计类,对这个类会有一些实质性的限制。
现有的类可以很容易被更新,以实现新的接口。
接口是定义mixin(混合类型)的理想选择,而抽象类不行。
接口允许构造非层次结构的类型框架。
接口使得更安全地增强类功能成为了可能。
通过对接口实现一个抽象的骨架实现类可以把接口和抽象类地优点结合起来(好的文档是非常必要i的!)
接口负责定义类型,或许还提供一些缺省方法(default method),而骨架实现类负责实现 基本类型的方法和非基本类型接口方法。拓展骨架实现占了实现接之外的大部分工作。这就是模板方法模式。
骨架实现类被称为 AbstractInterface,例如集合框架中的 AbstractSet,AbstractList,AbstractMap。
JDK8 之后:缺省方法(default method)
常量接口是对接口的不良使用。
接口只用来定义类型,不应该被用来导出常量。
类层次:通过继承连接起来做类似的事情。
标签类:两种甚至更多风格的实例的类,并包含表示实例风格的标签域。
标签类过于冗长,容易出错,且效率低下。
嵌套类:内部类。
外围类:内部类的外围的类。
嵌套类有4种:
静态成员类
非静态成员类
匿名类
局部类
如果声明成员类不要求访问外围实例,就要始终把修饰符static放在它的声明种。
顶级类:最外层,没有继承的类。
如果一个源文件中定义多个顶级类,可能会导致给一个类提供多个定义。哪一个定义会被用到,取决于源文件传输给编译器的顺序。
如果一定要把多个顶级类放入一个源文件,就要考虑使用静态成员类,以此代替将这两个类分到独立的源文件中去。
结论:
永远不要把多个顶级类或者接口放入一个源文件中。遵循这个原则可以确保编译时一个类不会有多个定义。这么做反过来也能确保编译产生的类文件,以及程序结果行为都不会受到源文件传给编译器的顺序的影响。