天天看點

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

可以将一個類的定義放在另一個類的定義内部,這就是内部類。

       内部類是一個非常有用的特性但又比較難了解使用的特性(鄙人到現在都沒有怎麼使用過内部類,對内部類也隻是略知一二)。

       内部類我們從外面看是非常容易了解的,無非就是在一個類的内部在定義一個類。

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

public class OuterClass {  

    private String name ;  

    private int age;  

    public String getName() {  

        return name;  

    }  

    public void setName(String name) {  

        this.name = name;  

    public int getAge() {  

        return age;  

    public void setAge(int age) {  

        this.age = age;  

    class InnerClass{  

        public InnerClass(){  

            name = "chenssy";  

            age = 23;  

        }  

}  

       在 這裡InnerClass就是内部類,對于初學者來說内部類實在是使用的不多,鄙人菜鳥一個同樣沒有怎麼使用過(貌似僅僅隻在做swing 注冊事件中使用過),但是随着程式設計能力的提高,我們會領悟到它的魅力所在,它可以使用能夠更加優雅的設計我們的程式結構。在使用内部類之間我們需要明白為 什麼要使用内部類,内部類能夠為我們帶來什麼樣的好處。

       為什麼要使用内部類?在《Think in java》中有這樣一句話:使用内部類最吸引人的原因是:每個内部類都能獨立地繼承一個(接口的)實作,是以無論外圍類是否已經繼承了某個(接口的)實作,對于内部類都沒有影響。

      在我們程式設計中有時候會存在一些使用接口很難解決的問題,這個時候我們可以利用内部類提供的、可以繼承多個具體的或者抽象的類的能力來解決這些程式設計問題。可以這樣說,接口隻是解決了部分問題,而内部類使得多重繼承的解決方案變得更加完整。

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

public interface Father {  

public interface Mother {  

public class Son implements Father, Mother {  

public class Daughter implements Father{  

    class Mother_ implements Mother{  

      其實對于這個執行個體我們确實是看不出來使用内部類存在何種優點,但是如果Father、Mother不是接口,而是抽象類或者具體類呢?這個時候我們就隻能使用内部類才能實作多重繼承了。

      其實使用内部類最大的優點就在于它能夠非常好的解決多重繼承的問題,但是如果我們不需要解決多重繼承問題,那麼我們自然可以使用其他的編碼方式,但是使用内部類還能夠為我們帶來如下特性(摘自《Think in java》):

      1、内部類可以用多個執行個體,每個執行個體都有自己的狀态資訊,并且與其他外圍對象的資訊互相獨立。

      2、在單個外圍類中,可以讓多個内部類以不同的方式實作同一個接口,或者繼承同一個類。

      3、建立内部類對象的時刻并不依賴于外圍類對象的建立。

      4、内部類并沒有令人迷惑的“is-a”關系,他就是一個獨立的實體。

      5、内部類提供了更好的封裝,除了該外圍類,其他類都不能通路。

       在這個部分主要介紹内部類如何使用外部類的屬性和方法,以及使用.this與.new。

       當我們在建立一個内部類的時候,它無形中就與外圍類有了一種聯系,依賴于這種聯系,它可以無限制地通路外圍類的元素。

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

    /**省略getter和setter方法**/  

    public class InnerClass{  

        public void display(){  

            System.out.println("name:" + getName() +"   ;age:" + getAge());  

    public static void main(String[] args) {  

        OuterClass outerClass = new OuterClass();  

        OuterClass.InnerClass innerClass = outerClass.new InnerClass();  

        innerClass.display();  

--------------  

Output:  

name:chenssy   ;age:23  

       在

這個應用程式中,我們可以看到内部了InnerClass可以對外圍類OuterClass的屬性進行無縫的通路,盡管它是private修飾的。這是因

為當我們在建立某個外圍類的内部類對象時,此時内部類對象必定會捕獲一個指向那個外圍類對象的引用,隻要我們在通路外圍類的成員時,就會用這個引用來選擇

外圍類的成員。

       其實在這個應用程式中我們還看到了如何來引用内部類:引用内部類我們需要指明這個對象的類型:OuterClasName.InnerClassName。同時如果我們需要建立某個内部類對象,必須要利用外部類的對象通過.new來建立内部類:OuterClass.InnerClass innerClass

= outerClass.new InnerClass();。

       同時如果我們需要生成對外部類對象的引用,可以使用OuterClassName.this,這樣就能夠産生一個正确引用外部類的引用了。當然這點實在編譯期就知曉了,沒有任何運作時的成本。

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

    public void display(){  

        System.out.println("OuterClass...");  

        public OuterClass getOuterClass(){  

            return OuterClass.this;  

        innerClass.getOuterClass().display();  

-------------  

Output:  

OuterClass...  

       到

這裡了我們需要明确一點,内部類是個編譯時的概念,一旦編譯成功後,它就與外圍類屬于兩個完全不同的類(當然他們之間還是有聯系的)。對于一個名為

OuterClass的外圍類和一個名為InnerClass的内部類,在編譯成功後,會出現這樣兩個class檔案:OuterClass.class

和OuterClass$InnerClass.class。

       在Java中内部類主要分為成員内部類、局部内部類、匿名内部類、靜态内部類。

       成員内部類也是最普通的内部類,它是外圍類的一個成員,是以他是可以無限制的通路外圍類的所有 成員屬性和方法,盡管是private的,但是外圍類要通路内部類的成員屬性和方法則需要通過内部類執行個體來通路。

       在成員内部類中要注意兩點,第一:成員内部類中不能存在任何static的變量和方法;第二:成員内部類是依附于外圍類的,是以隻有先建立了外圍類才能夠建立内部類。

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

    private String str;  

    public void outerDisplay(){  

        System.out.println("outerClass...");  

        public void innerDisplay(){  

            //使用外圍内的屬性  

            str = "chenssy...";  

            System.out.println(str);  

            //使用外圍内的方法  

            outerDisplay();  

    /*推薦使用getxxx()來擷取成員内部類,尤其是該内部類的構造函數無參數時 */  

    public InnerClass getInnerClass(){  

        return new InnerClass();  

        OuterClass outer = new OuterClass();  

        OuterClass.InnerClass inner = outer.getInnerClass();  

        inner.innerDisplay();  

--------------------  

chenssy...  

outerClass...  

推薦使用getxxx()來擷取成員内部類,尤其是該内部類的構造函數無參數時 。

       有

這樣一種内部類,它是嵌套在方法和作用于内的,對于這個類的使用主要是應用與解決比較複雜的問題,想建立一個類來輔助我們的解決方案,到那時又不希望這個

類是公共可用的,是以就産生了局部内部類,局部内部類和成員内部類一樣被編譯,隻是它的作用域發生了改變,它隻能在該方法和屬性中被使用,出了該方法和屬

性就會失效。

       對于局部内部類實在是想不出什麼好例子,是以就引用《Think in java》中的經典例子了。

       定義在方法裡:

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

public class Parcel5 {  

    public Destionation destionation(String str){  

        class PDestionation implements Destionation{  

            private String label;  

            private PDestionation(String whereTo){  

                label = whereTo;  

            }  

            public String readLabel(){  

                return label;  

        return new PDestionation(str);  

        Parcel5 parcel5 = new Parcel5();  

        Destionation d = parcel5.destionation("chenssy");  

       定義在作用域内:

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

public class Parcel6 {  

    private void internalTracking(boolean b){  

        if(b){  

            class TrackingSlip{  

                private String id;  

                TrackingSlip(String s) {  

                    id = s;  

                }  

                String getSlip(){  

                    return id;  

            TrackingSlip ts = new TrackingSlip("chenssy");  

            String string = ts.getSlip();  

    public void track(){  

        internalTracking(true);  

        Parcel6 parcel6 = new Parcel6();  

        parcel6.track();  

       在做Swing程式設計中,我們經常使用這種方式來綁定事件

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

button2.addActionListener(    

                new ActionListener(){    

                    public void actionPerformed(ActionEvent e) {    

                        System.out.println("你按了按鈕二");    

                    }    

                });  

        我們咋一看可能覺得非常奇怪,因為這個内部類是沒有名字的,在看如下這個例子:

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

    public InnerClass getInnerClass(final int num,String str2){  

        return new InnerClass(){  

            int number = num + 3;  

            public int getNumber(){  

                return number;  

        };        /* 注意:分号不能省 */  

        OuterClass out = new OuterClass();  

        InnerClass inner = out.getInnerClass(2, "chenssy");  

        System.out.println(inner.getNumber());  

interface InnerClass {  

    int getNumber();  

----------------  

5  

       這裡我們就需要看清幾個地方

      1、 匿名内部類是沒有通路修飾符的。

      2、 new 匿名内部類,這個類首先是要存在的。如果我們将那個InnerClass接口注釋掉,就會出現編譯出錯。

      3、 注意getInnerClass()方法的形參,第一個形參是用final修飾的,而第二個卻沒有。同時我們也發現第二個形參在匿名内部類中沒有使用過,是以當所在方法的形參需要被匿名内部類使用,那麼這個形參就必須為final。

      4、 匿名内部類是沒有構造方法的。因為它連名字都沒有何來構造方法。

PS:由于篇幅有限,對匿名内部類就介紹到這裡,有關更多關于匿名内部類的知識,我就會在下篇部落格(java提高篇-----詳解匿名内部類)做詳細的介紹,包括為何形參要定義成final,怎麼對匿名内部類進行初始化等等,敬請期待……

java提高篇-----關鍵字static中提到Static可以修飾成員變量、方法、代碼塊,其他它還可以修飾内部類,使用static修飾的内部類

我們稱之為靜态内部類,不過我們更喜歡稱之為嵌套内部類。靜态内部類與非靜态内部類之間存在一個最大的差別,我們知道非靜态内部類在編譯完成之後會隐含地

儲存着一個引用,該引用是指向建立它的外圍内,但是靜态内部類卻沒有。沒有這個引用就意味着:

      1、 它的建立是不需要依賴于外圍類的。

      2、 它不能使用任何外圍類的非static成員變量和方法。

java基礎之:詳解内部類(轉載)        第一次見面        一、為什麼要使用内部類        二、内部類基礎        三、成員内部類        四、局部内部類        五、匿名内部類        六、靜态内部類

    private String sex;  

    public static String name = "chenssy";  

    /** 

     *靜态内部類 

     */  

    static class InnerClass1{  

        /* 在靜态内部類中可以存在靜态成員 */  

        public static String _name1 = "chenssy_static";  

            /*  

             * 靜态内部類隻能通路外圍類的靜态成員變量和方法 

             * 不能通路外圍類的非靜态成員變量和方法 

             */  

            System.out.println("OutClass name :" + name);  

     * 非靜态内部類 

    class InnerClass2{  

        /* 非靜态内部類中不能存在靜态成員 */  

        public String _name2 = "chenssy_inner";  

        /* 非靜态内部類中可以調用外圍類的任何成員,不管是靜态的還是非靜态的 */  

            System.out.println("OuterClass name:" + name);  

     * @desc 外圍類方法 

     * @author chenssy 

     * @data 2013-10-25 

     * @return void 

        /* 外圍類通路靜态内部類:内部類. */  

        System.out.println(InnerClass1._name1);  

        /* 靜态内部類 可以直接建立執行個體不需要依賴于外圍類 */  

        new InnerClass1().display();  

        /* 非靜态内部的建立需要依賴于外圍類 */  

        OuterClass.InnerClass2 inner2 = new OuterClass().new InnerClass2();  

        /* 方位非靜态内部類的成員需要使用非靜态内部類的執行個體 */  

        System.out.println(inner2._name2);  

        inner2.display();  

        outer.display();  

chenssy_static  

OutClass name :chenssy  

chenssy_inner  

OuterClass name:chenssy  

       上面這個例子充分展現了靜态内部類和非靜态内部類的差別。

       到這裡内部類的介紹就基本結束了!對于内部類其實本人認識也隻是皮毛,逼近菜鳥一枚,認知有限!我會利用這幾天時間好好研究内部類!

鞏固基礎,提高技術,不懼困難,攀登高峰!!!!!!