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 在公有類中使用訪問方法而非公有域