優(yōu)雅編程之這樣編寫方法,你就“正?!绷耍ǘ耍?/h2>

開心一笑

【一大哥去醫(yī)院看病。
醫(yī)生問:你得了什么???
大哥說: 我得了間接性失憶癥。
醫(yī)生問:具體什么癥狀?
大哥說:我一看到漂亮的姑娘就忘記自己已結(jié)婚了。
醫(yī)生說:滾滾滾,這病我自己都沒治好!】

提出問題

項目開發(fā)中,使用方法要注意的一些事項???

解決問題

以下來自《Effective Java》中的讀書筆記:

檢查參數(shù)有效性

應(yīng)該在發(fā)生錯誤之后盡快檢測出錯誤

例如:

public BigInteger mod(BigInteger m){
    //盡快檢查錯誤
    if(m.signum() <= 0){
        throw new ArithmeticException("Modulus <= 0:" + m);
    }
    ....
}

非共有的方法通常應(yīng)該使用斷言來檢查它們的參數(shù),具體做法如下:

private static void sort(long a[],int offset,int length){
    assert a != null;
    assert offset >= 0 && offset <= a.length;
    assert  length >=0 && length <=a.length -offset;
    ....//dosomethiing
}
必要時進行保護性拷貝

對于構(gòu)造器的每個可變參數(shù)進行保護性拷貝是必要的

例如:

public final class Period{
    private final Date start;
    private final Date end;
    
    public Period(Date start,Date end){
        ....
        this.start = start;
        this.end = end;
    }
    
    public Date start(){
        return start;
    }
    
    public Date end(){
        return end;
    }
}

Date start = new Date();
Date end = new Date();
Period p = new Period(start,end);
//注意問題出現(xiàn)在這里
end.setYear(78);

修改后:

public Period(Date start,Date end){
        ....
     this.start = new Date(start.getTime());
     this.end = new Date(end.getTime());
}

注意,保護性拷貝是在檢查參數(shù)有效性之前進行的,并且有效性檢查是針對拷貝之后的對象,而不是針對原始的對象。

雖然替換構(gòu)造器就可以成功避免上述攻擊,但是改變Period實例仍然是有可能的,例如下面例子:

Date start = new Date();
Date end = new Date();
Period p = new Period(start,end);
//注意問題出現(xiàn)在這里
p.end().setYear(78);

進一步修改:

public Date start(){
    return new Date(start.getTime());
}
    
public Date end(){
    return new Date(end.getTime());
}

簡而言之,如果類具有從客戶端得到或者返回到客戶端的可變組件,類就必須保護性的拷貝這些組件。如果拷貝的成本受到限制,并且內(nèi)信任它的客戶端不會不恰當?shù)男薷慕M件,就可以在文檔中指明客戶端的職責是不得修改受到影響的組件,以此來代替保護性拷貝。

謹慎設(shè)計方法簽名
  • 謹慎地選擇方法的名稱。
  • 不要過于追求提供便利的方法。
  • 避免過長的參數(shù)列表。
    有三種方法可以縮短過長的參數(shù)列表,第一種是把方法分解成多個方法,每個方法只需要這些參數(shù)的一個子集。第二種方法是創(chuàng)建輔助類用來保存參數(shù)的分組。第三種是如果方法帶有多個參數(shù),尤其是當它們中有些是可選的時候,最好定一個對象來表示所有參數(shù)。(這些在之前文章都有提過了)
慎用可變參數(shù)

在重視性能的情況下,使用可變參數(shù)需要特別小心,可變參數(shù)方法的每次調(diào)用都會導(dǎo)致進行一次數(shù)組分配和初始化。如果憑經(jīng)驗確定無法承受這一成本,但又需要可變參數(shù)的靈活性,還有一種模式可以讓你如愿以償。假設(shè)確定對某個方法95%的調(diào)用會有3個或者更少的參數(shù),就聲明改方法的5個重載,每個重載方法帶有0至3個普通參數(shù),當參數(shù)的數(shù)目超過3個時,就使用一個可變參數(shù)方法:

例如:

public void foo(){}

public void foo(int a1){}

public void foo(int a1,int a2){}

public void foo(int a1,int a2,int a3){}

public void foo(int a1,int a2,int a3,int ... rest){}

這種方法可能不太恰當,但是一旦需要它時,它可就幫上大忙了。

總之,在定義參數(shù)數(shù)目不定的方法時,可變參數(shù)方法是一種很方便的方式,但是它們不應(yīng)該被過度濫用。如果使用不當,會產(chǎn)生混亂的結(jié)果。

返回零長度的數(shù)組或集合,而不是null

例如:

public Cheese[] getCheeses(int size){

    if(size == 0){
        //這里返回null,是錯誤的,因為調(diào)用改方法,還需要判斷這個null對象
        return null;
    }
}

正確做法:

private final List<Cheese> cheesesInStock = ...;
//定義final型的空數(shù)組
private static final Cheese[] EMPTY_CHEESE_ARRAY = new Cheese[0];

public Cheese[] getCheeses(){
    //返回空數(shù)組而不是null
    return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);
}

同樣的對于集合(Collections.emptySet,emptyList,emptyMap等等)

public List<Cheese> getCheesesList(){
    if(cheesesInStock.isEmpty()){
        //返回不可變的空集合,對于map
        return Collections.emptyList();
    }else{
        return new ArrayList<Cheese>(cheesesInStock);
    }
    
}

有時候會有人認為:null返回值比零長度數(shù)組更好,因為他避免了分配數(shù)組所需要的開銷。

為所有導(dǎo)出的API元素編寫文檔注釋

例如:

/**
 * <p> the method is ...<i>not<i>
 * Returns the element at the specified position in this list.
 *
 * @param  index index of the element to return
 * @return the element at the specified position in this list
 * @throws IndexOutOfBoundsException {@inheritDoc} if the index is out of..
 */
public E get(int index) {
    rangeCheck(index);

    return elementData(index);
}

方法的文檔注釋中每個參數(shù)都有一個@param標簽(后面應(yīng)該是一個名詞),以及一個@return標簽(除非返回為空),以及@throws標簽(后面應(yīng)該是一個名詞),@throws標簽后應(yīng)該包含單詞"if",描述了異常將在什么樣的條件下會被拋出。

文檔注釋還使用了HTML標簽(<p>和<i>).Javadoc工具會把文檔注釋翻譯成HTML

**{@code} **:表示該代碼片段以代碼字體進行呈現(xiàn)

{@literal}:可以把小于號,大于號等包起來,用來輸出這些字符。

更多的文檔注釋,可以看《Effective Java》對它的描述。

讀書感悟

來自亦舒《不易居》

  • 現(xiàn)在還有誰會照顧誰一輩子,那是多沉重的一個包袱。所以非自立不可。
  • 你要改是因為你自己愿意改,不要為任何人,怕只怕那人會令你失望,你又得打回原形。

其他

如果有帶給你一絲絲小快樂,就讓快樂繼續(xù)傳遞下去,歡迎轉(zhuǎn)載,點贊,頂,歡迎留下寶貴的意見,多謝支持!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,569評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,058評論 25 709
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,719評論 18 399
  • 近日讀了一本書《娛樂至死》,雖然這本書初版于1985年,但對當下仍有現(xiàn)實意義。 這本書諷刺了當時美國在電報、電視等...
    平蕪aay閱讀 362評論 0 1
  • 三年級反思。 三年級的課程,是最基礎(chǔ)的入門課程,我保持了講課速度慢,注意前提的,這種策略 在開學(xué)到現(xiàn)在,這十幾星期...
    lygly9閱讀 259評論 0 0

友情鏈接更多精彩內(nèi)容