Effective-java第二三四章

创建和销毁对象

用静态工厂方法代替构造器,公有的静态工厂方法,只是返回类的实例的静态方法

1 有名称,可以确切的描述返回的对象,可以区分多个静态工厂方法之间的区别

2 不必每次都创建一个新对象,避免创建重复对象

3 可以返回原返回类型的任何子类型的对象

4 添加参数,让返回对象的类可以随着调用而变化

5 方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在

6 类如果不含公有的或者受保护的构造器,就不能被子类化

7 如果没有合适的命名,不容易被发现。常见命名规则:

  from:类型转换方法,单个参数,Date d = Date.from(instant)

  of:聚合方法,多个参数,EnumSet.of(jack,queen,king)

  valueOf: Biginteger p = Biginteger .valueOf(123);

  instance或者getInstance

  create或者newInstance:每次调用返回一个新实例

  getType:type表示工厂方法所返回的对象类型

  newType:type表示工厂方法所返回的对象类型

  type:getType 和 newType 的简版

 

遇到多个构造器参数时要考虑使用建造者模式

1 重叠构造器:第一个构造器只有必要参数,第二个构造器多一个可选参数,第三个构造器多两个可选参数,最后一个包含所有可选参数。

2 JavaBeans模式:先调用一个无参数构造器,然后调用set方法设置必须的参数。

3 建造者模式:class.bulider().bulid()。

4 如果有太多参数时,builder模式是一个不错的选择

 

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

1 singleton是指只实例化一次的类

2 私有构造器仅被调用一次,实例化公有的静态final域。容易被反射破解

3 静态工厂方法

3 声明一个包含单个元素的枚举类型

 

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

1 只包含静态方法和静态域的类,可以这样

 

优先考虑依赖注入来引用资源

1 依赖注入:当创建一个新实例时,就将该资源传到构造器中

 

避免创建不必要的对象

1 优先使用基本类型而不是装箱基本类型,小心无意识的自动装箱

 

消除过期的对象引用

1 缓存

2 监听器和回调

 

避免使用终结方法和清除方法

1 终结方法是不可预测的,也是很危险的,一般情况下也是不必要的

2 注重时间的任务不应该由终结方法或者清除方法来完成

3 永远不要依赖终结方法或者清除方法来更新重要的持久状态

4 有严重的性能损失

 

try-with-resources优先于try-finally

1 必须实现AutoCloseable接口

2 代码更简洁,清晰

 

 

对于所有对象都通用的方法

覆盖equals时请遵守通用约定

1 类的每个实例本质上都是唯一的

2 类没有必要提供逻辑相等的功能

3 超类已经覆盖了equals,超类的行为对于这个类也是合适的

4 自反性:对于任何非 null 的引用值 x,x . equals(x)必须返回 true

5 对称性:对于任何非 null 的引用值 x 和 y,y.equals(x)返 回 true 时, x.equals(y)必须返回 true

6 传递性:x.equals(y)true ,并且 y.equals(z )true ,那么 x.equals(z )也必须返回 true 

7 一致性:对象中所用的信息没有被修改,结果一致

8 对于任何非 null 的引用值 x, x.equals (null)必须返回 false

 

覆盖equals时总要覆盖hashcode

1 覆盖了equals的方法的类中,必须覆盖hashcode方法

2 只要对象的equals比较操作所用到的信息没有修改,那么hashcode方法必须始终返回同一个值

3 如果根据equals方法比较是相等的,那么hashcode也必须产生同样的结果

4 如果根据equals方法比较是不相等的,hashcode不一定必须不相等。不过最好不相等

 

始终要覆盖toString

1 好的toString实现可以使类用起来更加舒适,更便于调试

2 tostring应该返回对象中所有值得关注的信息

 

谨慎的覆盖clone

1 实现cloneable接口的类是为了提供一个功能适当的公有的clone方法

2 对象拷贝更好的方法是提供一个拷贝构造器或拷贝工厂

 

考虑实现comparable

 

 

类和接口

使类和成员的可访问性最小化

1 顶层的类和接口,只有两种访问级别:包级私有的(package-private)和公有的(public)

2 公有类的实例域绝不能是公有的

 

要在公有类而非公有域中使用访问方法

1 如果类是在包之外进行访问,就提供访问方法

2 如果类是包级私有,或者是私有的嵌套类,直接暴露它的数据域并没有本质的错误

 

使可变性最小化

1 不可变类,不要提供任何会修改对象状态的方法

2 不可变类,保证类不会被扩展

3 不可变类,所有的域都是final的

4 不可变类,所有的域都是私有的

5 不可变类,确保对于任何可变组件的互斥访问

6 不可变类,本质上是线程安全的,不要求同步,可以自由地共享

7 不可变类,对于每个不同的值都需要一个单独的对象

 

复合优先于继承

1 继承打破了封装性

 

要么设计继承并提供文档说明,要么禁止继承

1 文档说明它可覆盖的方法的自用性

2 类必须以精心挑选的受保护的方法,提供适当的钩子,以便进入其内部工作

3 为了继承而设计的类,唯一的测试方法就是编写子类

4 构造器不能调用可被覆盖的方法

5 为了继承而设计的类,对这个类会有一些实质性的限制

 

接口优于抽象类

 

为后代设计接口

1 java8之后接口允许添加缺省方法

 

接口只用于定义类型

1 常量接口,只包含静态的final域,是对接口的不良使用

 

类层次优于标签类

 

静态成员类优于非静态成员类

 

限制源文件为单个顶级类

 

posted @ 2020-04-11 09:38  褐色键盘  阅读(120)  评论(0)    收藏  举报