https://www.cnblogs.com/yulinfeng/archive/2017/08/03/7282649.html
================================================================================
2.创建和销毁对象
2.1 静态工厂方法代替构造器
2.2 多个构造器参数时用构造器
如下例子:
一个类的构造方法需要多个形参,但是其中某些形参可选可不选:
方案1:重叠构造器:
public class Example {
public final int A;
public final int B;
public final int C;
public final int D;
public Example (int a , int b){
this.Example (a,b,0)
}
public Example (int a , int b , int c){
this.Example (a,b,c,0)
}
public Example (int a , int b , int c , int d ){
A =a;
B =b;
C =c;
D =d;
}
}
缺点:缺少的形参是估计倒数几个,不可有中间缺少形参情形;
方案2:JAVA BEANS:
public class Example {
public final int A;
public final int B;
public final int C;
public final int D;
public Example {}
public void setA(int val) {
A = val;
}
public void setB(int val) { ... }
public void setC(int val) { ... }
public void setD(int val) { ... }
}
缺点: 多线程下,不同线程对同一个实参的实例化可能导致不一致状态出现
方案3:Builder 模式:
public class Example {
// 都是private
private final int A;
private final int B;
private final int C;
private final int D;
public static class Builder {
//Example 类必须的构造参数:
private final int A ;
private final int B ;
//Example 类可选的构造参数:
private final int C = 0 ;
private final int D = 0 ;
public Builder (int a , int b) {
A = a;
B = b;
}
public Builder setC(int c) {
C = c;
return this;
}
public Builder setD(int d) {
D = d;
return this;
}
public Example build() {
return new Example(this);
}
}
public Example (Builder builder) {
A = builder.A;
B = builder.B;
C = builder.C;
D = builder.D;
}
}
初始化的例子:
Example ex = new Example.Builder(100,200).setC(300).setD(400).build();
1.(核心): 在目标类中创建 一个内部静态类---> 通过确保 目标类的初始化完全依赖于其内部静态类,确保多线程安全
2.目标类的成员变量为private 域,内部静态类的成员变量为private 域,但是setC 为public 域---->确保 目标类的初始化完全依赖内部类;
3.内部静态类 的setC() 方法返回不是void 而是目标类 的类型,确保可以连续使用 setC().setD().setE().setD() ,一次性完成成员变量的初始化;
以下方法貌似也可以... ...
没有builder 显的不那么灵活
public static class Example {
private int A ;
private int B ;
private int C = 0;
private int D = 0;
public Example (int a , int b) {
A = a;
B = b;
}
public Example setC (int c) {
C = c;
return this;
}
public Example setD (int d) {
D = d;
return this;
}
}
Example ex = new Example(100,200).setC(300).setD(400);
2.3 用私有构造器或者枚举类型强化Singleton属性
2.4 通过私有构造器强化不可实例化能力
public static class Example {
... ...
private Example (int a , int b) {
... ...
}
}
构造函数为private 域,在初始化Example 是不能通过其构造函数直接初始化,确保此类不可实例化
2.5 避免创建不必要的对象
案例1:
public class Example {
private final int Date;
public Example();
public boolean isBaby {
Calender cal = Calender.getInstance(...);
return cal.isBaby(Date);
}
}
每次调用Example.isBaby 都会new 一个Calender对象
优化:
public class Example {
private final int Date;
private Builder build;
private static class Builder {
public Calender cal;
public Builder () {
cal = Calender.getInstance(...);
}
}
public Example (int val) {
Date = val;
build = new Builder();
}
public boolean isBaby() {
return build.cal.isBaby(Date);
}
}
///或者/
public class Example {
private final int Date;
public static Calender cal;
public Example (int date) {
Date = date;
// cal 是static 修饰的,第一次会初始化,后面的实例中直接共享第一次初始化的内存,不会再运行Calender.getInstance() 方法。
cal = Calender.getInstance(...);
}
public boolean isBaby () {
return cal.isBaby();
}
}
public class Example {
private final int Date;
public Calender cal;
public Example (int date) {
Date = date;
cal = Calender.getInstance(...);
}
public boolean isBaby () {
return cal.isBaby(Date);
}
}
public class Example {
private final int Date;
public Calender cal;
public Example (int date) {
Date = date;
}
public static boolean isBaby () {
cal = Calender.getInstance(...);
return cal.isBaby(Date);
}
}
boolean IsBaby = Example(19900101).isBaby();//???????
2.6 消除过期的对象引用
2.7 避免使用终结方法
3. 对所以对象都通用的方法
3.1 覆盖equals 时请遵守通用约定
equals方法实现了等价关系:
1.自反性: 对于任何非null的引用值x,x.equals(x) 必须返回true;
2.对称性:对于任何非null的引用值x,y 当且仅当 y.equals(x) 返回true时,x.equals(y)必须返回true;
3.传递性:对于任何非null的引用值x,y,z 如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)也为true;
4.一致性:对于任何非null的引用值x,y 只要equals 的笔记操作在对象中所用的信息没有被修改,多次调用x.equals(y) 就会一直返回true/false;
5.对于任何非null引用值,x.equals(null)必须返回false;
以下是高质量使用equals 的诀窍:
1.使用“==” 操作符检查 “参数是否为这个对象的引用”
2.使用instanceof 操作符检查 “参数是否为正确的类型”
3.把参数转换成正确的类型;
4.对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配。
对于 不是float / double 类型的基本类型域, 用“==”比较
对应 对象引用域,可以递归滴调用equals方法;
对于float域,可以使用Float.compare 方法
对于double域,则使用Double.compare
3.2 覆盖equals时总要覆盖hashCode
3.3 始终要覆盖toString
3.4 谨慎覆盖clone
3.5 考虑实现Compareable接口
4.类和接口
4.1 使类和成员的可访问性最小化
4.2 在公有类中使用访问方法而非公有域