Effective Java 2.0_Java中的靜態(tài)內(nèi)部類_Item 2知識(shí)點(diǎn)

文章作者:Tyan
博客:noahsnail.com

1. 什么是靜態(tài)內(nèi)部類

在Java中有靜態(tài)代碼塊、靜態(tài)變量、靜態(tài)方法,當(dāng)然也有靜態(tài)類,但Java中的靜態(tài)類只能是Java的內(nèi)部類,也稱為靜態(tài)嵌套類。靜態(tài)內(nèi)部類的定義如下:

public class OuterClass {
    
    static class StaticInnerClass {
        ...
    }
}

在介紹靜態(tài)內(nèi)部類之前,首先要弄清楚靜態(tài)內(nèi)部類與Java其它內(nèi)部類的區(qū)別。

2. 內(nèi)部類

什么是內(nèi)部類?將一個(gè)類的定義放在另一個(gè)類的內(nèi)部,就是內(nèi)部類。Java的內(nèi)部類主要分為成員內(nèi)部類、局部?jī)?nèi)部類、匿名內(nèi)部類、靜態(tài)內(nèi)部類。

2.1 成員內(nèi)部類

成員內(nèi)部類是最普通的內(nèi)部類,就是一個(gè)普通的類定義在另一個(gè)類的內(nèi)部,形式如下:

public class OuterClass {
    
    class InnerClass {
        ...
    }
}

注:

  • 在成員內(nèi)部類中,可以直接訪問(wèn)外部類的屬性、方法,即使是private類型也可以訪問(wèn),這是因?yàn)閮?nèi)部類持有一個(gè)外部類的引用,可以自由訪問(wèn)。

  • 成員內(nèi)部類中不能存在任何靜態(tài)變量和靜態(tài)方法。

  • 成員內(nèi)部類是依附于外部類的,只有先創(chuàng)建了外部類才能夠創(chuàng)建內(nèi)部類。

成員內(nèi)部類的創(chuàng)建形式如下:

//定義成員內(nèi)部類的方式一
OuterClass test = new OuterClass();
InnerClass innerA = test.new InnerClass();

//定義成員內(nèi)部類的方式二
OuterClass.InnerClass  innerB = new OuterClass().new InnerClass();

2.2 局部?jī)?nèi)部類

局部?jī)?nèi)部類是定義在一個(gè)方法或者一個(gè)作用域里面的類,形式如下:

public void methodInnerClass() {
    class InnerClass {
        ...
    }
    InnerClass A = new InnerClass();
}

注:

  • 局部?jī)?nèi)部類就像是方法里面的一個(gè)局部變量一樣,不能有public、protected、private以及static修飾符。

  • 可以直接訪問(wèn)外部類的屬性、方法,即使是private類型也可以訪問(wèn)。

2.3 匿名內(nèi)部類

用過(guò)Swing的人應(yīng)該對(duì)匿名內(nèi)部類非常熟悉,Swing中使用了大量的匿名內(nèi)部類。匿名內(nèi)部類的形式如下:

Button button = new Button();
button.addActionListener(new ActionListener() {

    @Override
    public void actionPerformed(ActionEvent e) {
        ...             
    }
            
});

注:

  • 匿名內(nèi)部類沒(méi)有名字,沒(méi)有構(gòu)造方法。

  • 匿名內(nèi)部類用于繼承其他類或是實(shí)現(xiàn)接口,并不需要增加額外的方法,只是對(duì)繼承方法的實(shí)現(xiàn)或是重寫(xiě)。

2.4 靜態(tài)內(nèi)部類

靜態(tài)內(nèi)部類也是定義在另一個(gè)類里面的類,只不過(guò)在類的前面多了一個(gè)關(guān)鍵字static。其定義形式如下:

public class OuterClass {
    
    static class StaticInnerClass {
        ...
    }
}

注:

  • 靜態(tài)內(nèi)部類的創(chuàng)建不依賴外部類。

  • 靜態(tài)內(nèi)部類不能訪問(wèn)外部類的非靜態(tài)成員和非靜態(tài)方法。

2.5 靜態(tài)內(nèi)部類與其它內(nèi)部類的區(qū)別

靜態(tài)內(nèi)部類與其它內(nèi)部類最大的區(qū)別在于非靜態(tài)內(nèi)部類在編譯完成之后會(huì)隱含地保存一個(gè)引用,該引用是指向創(chuàng)建它的外部類,但是靜態(tài)內(nèi)部類卻沒(méi)有。靜態(tài)內(nèi)部類只是嵌套在外部類中,因此也被稱為嵌套內(nèi)部類。

2.6 為什么要使用內(nèi)部類

  • 方便將存在一定邏輯關(guān)系的類組織在一起,又可以對(duì)外界隱藏。

  • 典型的情況是,內(nèi)部類繼承自某個(gè)類或?qū)崿F(xiàn)某個(gè)接口,內(nèi)部類的代碼操作創(chuàng)建外部類的對(duì)象。典型的情況是Effective Java 2.0中Item 2講述的構(gòu)建器模式。

  • 使用內(nèi)部類最吸引人的原因是:每個(gè)內(nèi)部類都能獨(dú)立地繼承自一個(gè)(接口的)實(shí)現(xiàn),所以無(wú)論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對(duì)于內(nèi)部類都沒(méi)有影響。如果沒(méi)有內(nèi)部類提供的可以繼承多個(gè)具體的或抽象的類的能力,一些設(shè)計(jì)與編程問(wèn)題就很難解決。從這個(gè)角度看,內(nèi)部類使得多重繼承的解決方案變得完整。接口解決了部分問(wèn)題,而內(nèi)部類有效地實(shí)現(xiàn)了“多重繼承”。

3. 為什么要使用靜態(tài)內(nèi)部類

使用靜態(tài)內(nèi)部類主要是因?yàn)殪o態(tài)內(nèi)部類的兩個(gè)優(yōu)點(diǎn):

  • 增強(qiáng)了類的封裝性

  • 提高了代碼的可讀性

以下面的例子為例:將Builder放在NutritionFacts的內(nèi)部,說(shuō)明二者之間有一定的關(guān)系,比起將兩個(gè)類分開(kāi)要好很多,因此增強(qiáng)了類的封裝性。其次,二者放在一起,能很明顯的看出Builder類是用來(lái)創(chuàng)建NutritionFacts類的,提高了代碼的可讀性。

4. 靜態(tài)內(nèi)部類的例子

靜態(tài)內(nèi)部類的創(chuàng)建:

//Builder Pattern
public class NutritionFacts {
    private final int servingSize;
    private final int servings;
    private final int calories;
    private final int fat;
    private final int sodium;
    private final int carbohydrate;

    public static class Builder {
        // Required parameters
        private final int servingSize;
        private final int servings;
        // Optional parameters - initialized to default values
        private int calories = 0;
        private int fat = 0;
        private int carbohydrate = 0;
        private int sodium = 0;

        public Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }

        public Builder calories(int val) {
            calories = val;
            return this;
        }

        public Builder fat(int val) {
            fat = val;
            return this;
        }

        public Builder carbohydrate(int val) {
            carbohydrate = val;
            return this;
        }

        public Builder sodium(int val) {
            sodium = val;
            return this;
        }

        public NutritionFacts build() {
            return new NutritionFacts(this);
        }
    }

    private NutritionFacts(Builder builder) {
        servingSize = builder.servingSize;
        servings = builder.servings;
        calories = builder.calories;
        fat = builder.fat;
        sodium = builder.sodium;
        carbohydrate = builder.carbohydrate;
    }
}

靜態(tài)內(nèi)部類的使用:

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();

參考資料

1、Effective Java 2.0

2、http://www.cnblogs.com/chenssy/p/3388487.html

3、http://www.cnblogs.com/dolphin0520/p/3811445.html

4、http://book.51cto.com/art/201202/317517.htm

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

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 34,679評(píng)論 18 399
  • 一:java概述:1,JDK:Java Development Kit,java的開(kāi)發(fā)和運(yùn)行環(huán)境,java的開(kāi)發(fā)工...
    ZaneInTheSun閱讀 2,812評(píng)論 0 11
  • Java 內(nèi)部類 分四種:成員內(nèi)部類、局部?jī)?nèi)部類、靜態(tài)內(nèi)部類和匿名內(nèi)部類。 1、成員內(nèi)部類: 即作為外部類的一個(gè)成...
    ikaroskun閱讀 1,355評(píng)論 0 13
  • 假期陪母親看了一部劇,看哭了她,觸動(dòng)了我。有些情節(jié),至今還記得。我覺(jué)得其中幾個(gè)人講述了幾個(gè)道理,值得借鑒。 程紫月...
    遇琳閱讀 1,808評(píng)論 4 4
  • 1、群友Y先生開(kāi)始了高質(zhì)量的微信公眾號(hào)寫(xiě)作,一起加入堅(jiān)持寫(xiě)作陣營(yíng)。我半死不活的堅(jiān)持著,群友們?nèi)〉弥卮筮M(jìn)步,我既興奮...
    陌白Carl閱讀 96評(píng)論 0 0

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