中文字幕精品亚洲无线码二区,国产黄a三级三级三级看三级,亚洲七七久久桃花影院,丰满少妇被猛烈进入,国产小视频在线观看网站

深(shen)入理解Java:內(nei)部類

一、什么是內部類?

  內部類是指在一個外部類的內部再定義一個類。內部類作為外部類的一個成員,并且依附于外部類而存在的。內部類可為靜態,可用protected和private修飾(而外部類只能使用public和缺省的包訪問權限)。內部類主要有以下幾類:內部、局部內部、靜內部、匿名內部

二、內部類的共性

(1)、內(nei)部類仍然是一個獨(du)立的類,在(zai)編譯之后內(nei)部類會(hui)被(bei)編譯成獨(du)立的.class文件,但是前面冠以外(wai)部類的類名和$符號(hao) 。

(2)、內部類(lei)不能(neng)用普(pu)通的方式訪問。

(3)、內(nei)部(bu)類聲(sheng)明(ming)成靜態(tai)的,就(jiu)不能隨便的訪問外部(bu)類的成員變量了,此時內(nei)部(bu)類只能訪問外部(bu)類的靜態(tai)成員變量 。

(4)、外部類不能直接訪(fang)問(wen)內(nei)部類的的成(cheng)員,但可以(yi)通過內(nei)部類對象來(lai)訪(fang)問(wen)

 

  內部(bu)(bu)類(lei)是外(wai)(wai)部(bu)(bu)類(lei)的(de)(de)一個成員,因此內部(bu)(bu)類(lei)可(ke)以(yi)自由地訪問(wen)外(wai)(wai)部(bu)(bu)類(lei)的(de)(de)成員變量,無論是否是private的(de)(de)。

  因為當(dang)某個外圍類(lei)(lei)(lei)的對(dui)象(xiang)創建內(nei)部類(lei)(lei)(lei)的對(dui)象(xiang)時,此內(nei)部類(lei)(lei)(lei)會(hui)捕(bu)獲一個隱(yin)式引用(yong),它引用(yong)了實(shi)例化該內(nei)部對(dui)象(xiang)的外圍類(lei)(lei)(lei)對(dui)象(xiang)。通(tong)過這個指針,可(ke)以訪問外圍類(lei)(lei)(lei)對(dui)象(xiang)的全(quan)部狀態。

通(tong)(tong)過(guo)反編譯內部類的字節碼,分析(xi)之后主要(yao)是通(tong)(tong)過(guo)以(yi)下(xia)幾步做(zuo)到的: 
  1 編譯器自(zi)動(dong)為內(nei)部類(lei)添加一個成(cheng)員(yuan)變量(liang), 這個成(cheng)員(yuan)變量(liang)的類(lei)型和外部類(lei)的類(lei)型相同, 這個成(cheng)員(yuan)變量(liang)就是指(zhi)向外部類(lei)對象(xiang)的引(yin)用; 
  2 編譯器自(zi)動為內部類(lei)(lei)的(de)構造方法添加一個(ge)參數, 參數的(de)類(lei)(lei)型(xing)(xing)是(shi)外(wai)部類(lei)(lei)的(de)類(lei)(lei)型(xing)(xing), 在構造方法內部使(shi)用這(zhe)個(ge)參數為1中添加的(de)成員變量賦值; 
  3 在(zai)調(diao)用(yong)內部(bu)類(lei)的構造函(han)數初始化內部(bu)類(lei)對象時, 會默認傳入外部(bu)類(lei)的引用(yong)。

三、為什么需要內部類?

其主要原因有以下幾點:

  • 內(nei)部類(lei)方(fang)法可以訪問(wen)該類(lei)定(ding)義所在的(de)作用域的(de)數據,包括私有(you)的(de)數據

  • 內部(bu)類可以對(dui)同一個包中的(de)其他類隱藏(zang)起來,一般的(de)非內部(bu)類,是不允(yun)許(xu)有 private 與protected權限的(de),但(dan)內部(bu)類可以

  • 可以(yi)實現多重繼(ji)承

  • 當(dang)想(xiang)要(yao)定(ding)義一個回(hui)調函(han)數且(qie)不想(xiang)編寫大量代碼時,使用匿名(ming)內部(bu)類比較便捷

使用內部類最吸引人的(de)原因是:

  每個(ge)(ge)內部(bu)類(lei)(lei)(lei)都能獨立地繼(ji)承(cheng)(cheng)(cheng)自一(yi)個(ge)(ge)(接口的(de)(de)(de)(de))實現(xian),所(suo)以(yi)無論外(wai)圍類(lei)(lei)(lei)是(shi)否已(yi)經繼(ji)承(cheng)(cheng)(cheng)了某個(ge)(ge)(接口的(de)(de)(de)(de))實現(xian),對于(yu)內部(bu)類(lei)(lei)(lei)都沒有影響(xiang)。大家(jia)都知(zhi)道Java只能繼(ji)承(cheng)(cheng)(cheng)一(yi)個(ge)(ge)類(lei)(lei)(lei),它的(de)(de)(de)(de)多重繼(ji)承(cheng)(cheng)(cheng)在我們(men)(men)沒有學習內部(bu)類(lei)(lei)(lei)之前是(shi)用(yong)接口來實現(xian)的(de)(de)(de)(de)。但使用(yong)接口有時候有很多不(bu)方(fang)(fang)便的(de)(de)(de)(de)地方(fang)(fang)。比(bi)如我們(men)(men)實現(xian)一(yi)個(ge)(ge)接口就必須(xu)實現(xian)它里面的(de)(de)(de)(de)所(suo)有方(fang)(fang)法(fa)。而(er)有了內部(bu)類(lei)(lei)(lei)就不(bu)一(yi)樣了。它可(ke)以(yi)使我們(men)(men)的(de)(de)(de)(de)類(lei)(lei)(lei)繼(ji)承(cheng)(cheng)(cheng)多個(ge)(ge)具體(ti)類(lei)(lei)(lei)或抽象類(lei)(lei)(lei)。

大家(jia)看下(xia)面的例子:

public class Example1 {
    public String name(){
       return "liutao";
   }
}

public class Example2 {
    public int age(){
        return 25;
    }
}

public class MainExample {

   private class test1 extends Example1{
        public String name(){
          return super.name();
        }
    }

    private class test2 extends Example2 {
       public int age(){
         return super.age();
       }
    }

   public String name(){
    return new test1().name(); 
   }

   public int age(){
       return new test2().age();
   }

   public static void main(String args[]){
       MainExample mi=new MainExample();
       System.out.println("姓名:"+mi.name());
       System.out.println("年齡:"+mi.age());
   }
}

四、成員內部類:

  即在一個類中直接定義的內部類, 成員內部類與普通的成員沒什么區別,可以與普通成員一樣進行修飾和限制。成員內部類不能含有static的變量和方法。

public class Outer {
    private static int i = 1;
    private int j = 10;
    private int k = 20;

    public static void outer_f1() {}

    public void outer_f2() {}

    // 成員內部類中,不(bu)能定義靜態(tai)成員
    // 成(cheng)員內部類(lei)中,可以(yi)訪問外部類(lei)的所(suo)有成(cheng)員
    class Inner {
        // static int inner_i = 100;//內(nei)部類中不(bu)允許定義靜態變量
        int j = 100; // 內部類和外部類的實例變量可以(yi)共存
        int inner_i = 1;

        void inner_f1() {
            System.out.println(i);
            // 在內部類中(zhong)訪問內部類自己的變量(liang)直接用變量(liang)名
            System.out.println(j);
            // 在內(nei)部(bu)類中訪問內(nei)部(bu)類自己(ji)的變量也可以用this.變量名
            System.out.println(this.j);
            // 在內(nei)部(bu)(bu)類中(zhong)訪問外部(bu)(bu)類中(zhong)與內(nei)部(bu)(bu)類同名(ming)的實例變量用外部(bu)(bu)類名(ming).this.變量名(ming)
            System.out.println(Outer.this.j);
            // 如果內部類(lei)中沒有與外部類(lei)同(tong)名的變(bian)量,則可以直接(jie)用變(bian)量名訪問外部類(lei)變(bian)量
            System.out.println(k);
            outer_f1();
            outer_f2();
        }
    }

    // 外部(bu)類(lei)的(de)非靜態方(fang)法訪問成員內部(bu)類(lei)
    public void outer_f3() {
        Inner inner = new Inner();
        inner.inner_f1();
    }

    // 外(wai)部(bu)類(lei)(lei)的(de)靜態(tai)方法(fa)訪(fang)問(wen)成員(yuan)內(nei)部(bu)類(lei)(lei),與在外(wai)部(bu)類(lei)(lei)外(wai)部(bu)訪(fang)問(wen)成員(yuan)內(nei)部(bu)類(lei)(lei)一樣
    public static void outer_f4() {
        // step1 建立外部類對象
        Outer out = new Outer();
        // step2 根據外部類對(dui)象建立(li)內部類對(dui)象
        Inner inner = out.new Inner();
        // step3 訪問內(nei)部類(lei)的(de)方法(fa)
        inner.inner_f1();
    }

    public static void main(String[] args) {
        //outer_f4();//該(gai)語句的輸出(chu)(chu)結果和下面三條語句的輸出(chu)(chu)結果一樣(yang)
        // 如果(guo)要直接創(chuang)建內部類的對(dui)象,不能想當然地(di)認為(wei)只需加上外圍類Outer的名字,
        // 就可以按照通常的(de)樣子生成內部類的(de)對象,而(er)是必須(xu)使(shi)用此外圍類的(de)一個對象來
        // 創建其內部類的一個對象:
        // Outer.Inner outin = out.new Inner()
        // 因此,除非你(ni)已經(jing)有了外(wai)圍(wei)類(lei)(lei)的一個對象,否則不可能生成內(nei)部類(lei)(lei)的對象。因為此
        // 內部(bu)(bu)類的(de)(de)對(dui)象會(hui)悄(qiao)(qiao)悄(qiao)(qiao)地鏈接(jie)到創建它(ta)的(de)(de)外圍類的(de)(de)對(dui)象。如果你用的(de)(de)是(shi)靜態的(de)(de)內部(bu)(bu)類,
        // 那就不需要對其外圍類對象的(de)引用。
        Outer out = new Outer();
        Outer.Inner outin = out.new Inner();
        outin.inner_f1();
    }
}

六、局部內部類:

  在方法中定義的(de)內(nei)(nei)部類稱為局部內(nei)(nei)部類。與局部變量類似,局部內(nei)(nei)部類不能有(you)(you)訪(fang)問說(shuo)明符(fu),因(yin)為它不是外圍類的(de)一部分,但是它可以訪(fang)問當前代碼塊內(nei)(nei)的(de)常量,和此外圍類所有(you)(you)的(de)成員。

需要注意的是:

  (1)、局(ju)部內部類(lei)只能在定(ding)義該(gai)內部類(lei)的方(fang)法內實例化,不(bu)可以在此(ci)方(fang)法外對其實例化。

  (2)、局部(bu)內部(bu)類(lei)對象(xiang)不能使用該(gai)內部(bu)類(lei)所在方法的非final局部(bu)變量。

具體原因等下再說(shuo)

public class Outer {
    private int s = 100;
    private int out_i = 1;

    public void f(final int k) {
        final int s = 200;
        int i = 1;
        final int j = 10;

        // 定(ding)義在方法內部
        class Inner {
            int s = 300;// 可以定義與外(wai)部(bu)類同名(ming)的(de)變量

            // static int m = 20;//不可以定義靜態變量
            Inner(int k) {
                inner_f(k);
            }

            int inner_i = 100;

            void inner_f(int k) {
                // 如果內(nei)部(bu)類(lei)沒有與(yu)外部(bu)類(lei)同名的變量(liang),在(zai)內(nei)部(bu)類(lei)中(zhong)可以直接訪問外部(bu)類(lei)的實例(li)變量(liang)
                System.out.println(out_i);
                // 可以訪問外(wai)部(bu)(bu)類的局部(bu)(bu)變(bian)(bian)量(liang)(即方法內的變(bian)(bian)量(liang)),但(dan)是變(bian)(bian)量(liang)必須是final的
                System.out.println(j);
                // System.out.println(i);
                // 如果內(nei)部(bu)(bu)(bu)類(lei)(lei)中(zhong)有與(yu)外部(bu)(bu)(bu)類(lei)(lei)同名(ming)的(de)變量,直接(jie)用變量名(ming)訪(fang)問的(de)是內(nei)部(bu)(bu)(bu)類(lei)(lei)的(de)變量
                System.out.println(s);
                // 用this.變量名訪問(wen)的也(ye)是內部類變量
                System.out.println(this.s);
                // 用外部(bu)類(lei)名(ming).this.內部(bu)類(lei)變量(liang)名(ming)訪問的(de)是外部(bu)類(lei)變量(liang)
                System.out.println(Outer.this.s);
            }
        }
        new Inner(k);
    }

    public static void main(String[] args) {
        // 訪(fang)問局部(bu)內部(bu)類必須先有外部(bu)類對象
        Outer out = new Outer();
        out.f(3);
    }
}

 

七、靜態內部類(嵌套類):

  如果你(ni)不需要(yao)內部(bu)類對(dui)象(xiang)與其(qi)外圍(wei)類對(dui)象(xiang)之間有(you)聯系,那你(ni)可(ke)以(yi)將內部(bu)類聲明為static。這(zhe)通常稱(cheng)為嵌(qian)套類(nested class)。想要(yao)理(li)解static應(ying)用(yong)于內部(bu)類時的(de)含(han)義,你(ni)就(jiu)(jiu)必須記住,普通的(de)內部(bu)類對(dui)象(xiang)隱含(han)地保(bao)存了一個引用(yong),指(zhi)向創建它的(de)外圍(wei)類對(dui)象(xiang)。然而,當內部(bu)類是static的(de)時,就(jiu)(jiu)不是這(zhe)樣了。嵌(qian)套類意味著:

  1. 要創建(jian)嵌套類的對(dui)(dui)象,并不(bu)需要其外圍類的對(dui)(dui)象。

  2. 不能(neng)從嵌套(tao)類的(de)(de)對(dui)象(xiang)中訪問(wen)非(fei)靜態(tai)的(de)(de)外(wai)圍類對(dui)象(xiang)。

public class Outer {
    private static int i = 1;
    private int j = 10;

    public static void outer_f1() {}

    public void outer_f2() {}

    // 靜態內部類可以用public,protected,private修飾
    // 靜(jing)態內部類(lei)中可以定(ding)義(yi)靜(jing)態或者(zhe)非(fei)靜(jing)態的成員
    private static class Inner {
        static int inner_i = 100;
        int inner_j = 200;

        static void inner_f1() {
            // 靜(jing)態(tai)內部類只能訪問外部類的靜(jing)態(tai)成員(yuan)(包(bao)括靜(jing)態(tai)變量和靜(jing)態(tai)方(fang)法)
            System.out.println("Outer.i" + i);
            outer_f1();
        }

        void inner_f2() {
            // 靜(jing)(jing)態內部類不(bu)能訪問外部類的非(fei)(fei)靜(jing)(jing)態成(cheng)員(包括非(fei)(fei)靜(jing)(jing)態變量和非(fei)(fei)靜(jing)(jing)態方法)
            // System.out.println("Outer.i"+j);
            // outer_f2();
        }
    }

    public void outer_f3() {
        // 外部(bu)類(lei)訪問(wen)內(nei)部(bu)類(lei)的(de)靜態(tai)(tai)成(cheng)員(yuan):內(nei)部(bu)類(lei).靜態(tai)(tai)成(cheng)員(yuan)
        System.out.println(Inner.inner_i);
        Inner.inner_f1();
        // 外部類訪問內部類的非靜態(tai)成(cheng)員:實例化內部類即(ji)可
        Inner inner = new Inner();
        inner.inner_f2();
    }

    public static void main(String[] args) {
        new Outer().outer_f3();
    }
}

生成(cheng)一個靜態內(nei)部(bu)類(lei)不(bu)(bu)(bu)需(xu)要外部(bu)類(lei)成(cheng)員:這(zhe)是(shi)(shi)靜態內(nei)部(bu)類(lei)和成(cheng)員內(nei)部(bu)類(lei)的(de)(de)區別。靜態內(nei)部(bu)類(lei)的(de)(de)對象可以直接(jie)(jie)生成(cheng):Outer.Inner in = new Outer.Inner();而不(bu)(bu)(bu)需(xu)要通(tong)過生成(cheng)外部(bu)類(lei)對象來(lai)生成(cheng)。這(zhe)樣實際上使(shi)靜態內(nei)部(bu)類(lei)成(cheng)為(wei)了一個頂級(ji)類(lei)(正常情(qing)況下,你不(bu)(bu)(bu)能在接(jie)(jie)口(kou)(kou)內(nei)部(bu)放置(zhi)任(ren)何代碼,但嵌套類(lei)可以作為(wei)接(jie)(jie)口(kou)(kou)的(de)(de)一部(bu)分,因為(wei)它是(shi)(shi)static 的(de)(de)。只是(shi)(shi)將嵌套類(lei)置(zhi)于接(jie)(jie)口(kou)(kou)的(de)(de)命名空(kong)間內(nei),這(zhe)并不(bu)(bu)(bu)違反接(jie)(jie)口(kou)(kou)的(de)(de)規則)

 

八、匿名內部類:

簡單地(di)說:匿名(ming)(ming)內部(bu)類(lei)就是沒有名(ming)(ming)字(zi)的內部(bu)類(lei)。什么情況下需(xu)要(yao)使用(yong)匿名(ming)(ming)內部(bu)類(lei)?如果滿足下面的一些(xie)條件,使用(yong)匿名(ming)(ming)內部(bu)類(lei)是比較合適的:
  • 只用到類的一個實例。
  • 類(lei)在定義(yi)后馬上用(yong)到。
  • 類非常小(SUN推薦是在4行代碼以下(xia))
  • 給類命(ming)名并不會導(dao)致你的代碼更容(rong)易被理解。
在使(shi)用匿名內部類時,要(yao)記住以下幾個原(yuan)則(ze):
  •   匿名內部類不(bu)能有構造方法(fa)。

  •   匿名(ming)內(nei)部類(lei)不(bu)能定義任何靜態成員、方法和類(lei)。

  •   匿名內部類(lei)不能是public,protected,private,static。

  •   只能創建匿名(ming)內部(bu)類的一個實例。

  •    一個匿名內部類(lei)一定是在new的(de)后面,用其隱含實現(xian)一個接口或實現(xian)一個類(lei)。

  •   因(yin)匿(ni)名內部(bu)類為局(ju)部(bu)內部(bu)類,所以局(ju)部(bu)內部(bu)類的所有限制都對其(qi)生(sheng)效(xiao)。

 

下(xia)面(mian)的(de)代碼展示(shi)的(de)是,如果你的(de)基類需要一(yi)個有參數(shu)的(de)構造器,應(ying)該怎么辦:
public class Parcel7 {
    public Wrapping wrap(int x) {
        // Base constructor call:
        return new Wrapping(x) { // Pass constructor argument.
            public int value() {
                return super.value() * 47;
            }
        }; // Semicolon required
    }
    public static void main(String[] args) {
        Parcel7 p = new Parcel7();
        Wrapping w = p.wrap(10);
    }
}
只需簡(jian)單地(di)傳遞合適的(de)(de)參數給基(ji)類的(de)(de)構造(zao)器即可,這里(li)是將x 傳進new Wrapping(x)。在匿名內(nei)部(bu)類末尾(wei)的(de)(de)分(fen)號(hao),并不是用(yong)來標記此內(nei)部(bu)類結束(shu)(C++中是那樣)。實際上,它標記的(de)(de)是表達式的(de)(de)結束(shu),只不過這個表達式正巧(qiao)包含(han)了(le)內(nei)部(bu)類罷(ba)了(le)。因此,這與別的(de)(de)地(di)方(fang)使(shi)用(yong)的(de)(de)分(fen)號(hao)是一致(zhi)的(de)(de)。
 
如果在匿名類中定義成(cheng)員變量或者(zhe)使用帶參(can)數的構造函數,你同樣能夠對(dui)其(qi)執行初始化操作(zuo):
public class Parcel8 {
    // Argument must be final to use inside
    // anonymous inner class:
    public Destination dest(final String name, String city) {
        return new Destination(name, city) {
            private String label = name;

            public String getName() {
                return label;
            }
        };
    }

    public static void main(String[] args) {
        Parcel8 p = new Parcel8();
        Destination d = p.dest("Tanzania", "gz");
    }

    abstract class Destination {
        Destination(String name, String city) {
            System.out.println(city);
        }

        abstract String getName();
    }
}
注意這(zhe)里的形(xing)參city,由(you)于它沒(mei)有被(bei)匿(ni)名內(nei)部類(lei)直接(jie)使(shi)用,而(er)是(shi)被(bei)抽象類(lei)Inner的構造(zao)函數所使(shi)用,所以不(bu)必定義為final。
 
 

九、內部類的重載問題

 
  如果(guo)你創建(jian)了一個內(nei)(nei)部(bu)(bu)類(lei),然后繼承其外圍類(lei)并(bing)重新定(ding)義此內(nei)(nei)部(bu)(bu)類(lei)時,會發生什(shen)么呢?也就(jiu)是說,內(nei)(nei)部(bu)(bu)類(lei)可(ke)以被重載(zai)嗎?這看起(qi)來似(si)乎是個很有用的(de)點子,但是“重載(zai)”內(nei)(nei)部(bu)(bu)類(lei)就(jiu)好(hao)像(xiang)它是外圍類(lei)的(de)一個方法,其實并(bing)不起(qi)什(shen)么作用:
 
class Egg {
       private Yolk y;
 
       protected class Yolk {
              public Yolk() {
                     System.out.println("Egg.Yolk()");
              }
       }
 
       public Egg() {
              System.out.println("New Egg()");
              y = new Yolk();
       }
}
 
public class BigEgg extends Egg {
       public class Yolk {
              public Yolk() {
                     System.out.println("BigEgg.Yolk()");
              }
       }
 
       public static void main(String[] args) {
              new BigEgg();
       }
}
輸出(chu)結果(guo)為:
New Egg()
Egg.Yolk()
 
缺省的(de)(de)構(gou)造器是(shi)編譯器自動生成的(de)(de),這里是(shi)調用基類的(de)(de)缺省構(gou)造器。你可(ke)能(neng)認為既然創建了BigEgg 的(de)(de)對象(xiang),那么所使用的(de)(de)應該是(shi)被“重載”過(guo)的(de)(de)Yolk,但你可(ke)以(yi)從輸出中看到(dao)實際情況并不是(shi)這樣的(de)(de)。
這個(ge)例子說明,當你繼承了某(mou)個(ge)外(wai)圍類(lei)的(de)(de)時(shi)候,內部(bu)(bu)類(lei)并(bing)沒有發生什么(me)特別神奇(qi)的(de)(de)變化。這兩個(ge)內部(bu)(bu)類(lei)是(shi)完全獨立(li)的(de)(de)兩個(ge)實體,各自在自己的(de)(de)命名空(kong)間內。當然,明確(que)地繼承某(mou)個(ge)內部(bu)(bu)類(lei)也是(shi)可以(yi)的(de)(de):
class Egg2 {
       protected class Yolk {
              public Yolk() {
                     System.out.println("Egg2.Yolk()");
              }
 
              public void f() {
                     System.out.println("Egg2.Yolk.f()");
              }
       }
 
       private Yolk y = new Yolk();
 
       public Egg2() {
              System.out.println("New Egg2()");
       }
 
       public void insertYolk(Yolk yy) {
              y = yy;
       }
 
       public void g() {
              y.f();
       }
}
 
public class BigEgg2 extends Egg2 {
       public class Yolk extends Egg2.Yolk {
              public Yolk() {
                     System.out.println("BigEgg2.Yolk()");
              }
 
              public void f() {
                     System.out.println("BigEgg2.Yolk.f()");
              }
       }
 
       public BigEgg2() {
              insertYolk(new Yolk());
       }
 
       public static void main(String[] args) {
              Egg2 e2 = new BigEgg2();
              e2.g();
       }
}
輸出結果為(wei):
Egg2.Yolk()
New Egg2()
Egg2.Yolk()
BigEgg2.Yolk()
BigEgg2.Yolk.f()
 
現在BigEgg2.Yolk 通過(guo)extends Egg2.Yolk 明確(que)地繼承了此內(nei)部類,并且重載了其中的(de)方(fang)法(fa)。Egg2 的(de)insertYolk()方(fang)法(fa)使得(de)BigEgg2 將它自己的(de)Yolk 對象向(xiang)上轉(zhuan)型,然(ran)后傳遞(di)給引用y。所(suo)以當g()調(diao)用y.f()時(shi),重載后的(de)新版的(de)f()被執行。第二次調(diao)用Egg2.Yolk()是BigEgg2.Yolk 的(de)構造(zao)器調(diao)用了其基(ji)類的(de)構造(zao)器。可以看到(dao)在調(diao)用g()的(de)時(shi)候,新版的(de)f()被調(diao)用了。
 

十、內部類的繼承問題

  因為內部類(lei)(lei)的(de)(de)(de)構造器(qi)要(yao)用(yong)(yong)到其外圍類(lei)(lei)對(dui)象(xiang)的(de)(de)(de)引(yin)用(yong)(yong),所(suo)以在(zai)你繼承一個(ge)內部類(lei)(lei)的(de)(de)(de)時候,事情變得有點復雜。問(wen)題在(zai)于,那個(ge)“秘密的(de)(de)(de)”外圍類(lei)(lei)對(dui)象(xiang)的(de)(de)(de)引(yin)用(yong)(yong)必須被初始化(hua),而在(zai)被繼承的(de)(de)(de)類(lei)(lei)中并(bing)不存在(zai)要(yao)聯(lian)接的(de)(de)(de)缺省對(dui)象(xiang)。要(yao)解決這個(ge)問(wen)題,需(xu)使用(yong)(yong)專(zhuan)門(men)的(de)(de)(de)語法來(lai)明確(que)說清(qing)它(ta)們(men)之間(jian)的(de)(de)(de)關聯(lian):
class WithInner {
        class Inner {
                Inner(){
                        System.out.println("this is a constructor in WithInner.Inner");
                };
        }
}
 
public class InheritInner extends WithInner.Inner {
        // ! InheritInner() {} // Won't compile
        InheritInner(WithInner wi) {
                wi.super();
                System.out.println("this is a constructor in InheritInner");
        }
 
        public static void main(String[] args) {
                WithInner wi = new WithInner();
                InheritInner ii = new InheritInner(wi);
        }
}
輸出結果為:
this is a constructor in WithInner.Inner
this is a constructor in InheritInner
 
可以看到,InheritInner 只繼承自內(nei)部類,而(er)不是外(wai)圍類。但是當要生成一個構(gou)造器時,缺省的(de)構(gou)造器并(bing)不算(suan)好,而(er)且(qie)你不能(neng)只是傳遞一個指(zhi)向外(wai)圍類對(dui)象的(de)引用(yong)。此(ci)外(wai),你必(bi)須在(zai)構(gou)造器內(nei)使(shi)用(yong)如下語法:
enclosingClassReference.super();
這樣才提(ti)供了必要的引用,然后程序才能編譯通(tong)過。
 

為什么非靜態內部類中不能有static修飾的屬性,但卻可以有常量?

如:

public class InnerClassDemo{
    int x;
    class A{
        static  int a = 0;//這樣寫是(shi)不合(he)法的.
        static final int b=0;//這樣寫是合法的

     }
}

定(ding)義一個靜(jing)態(tai)(tai)(tai)的域(yu)或者(zhe)方法,要求(qiu)在靜(jing)態(tai)(tai)(tai)環境(jing)或者(zhe)頂層環境(jing),即(ji)如果加(jia)上 static class A變成靜(jing)態(tai)(tai)(tai)內部(bu)(bu)類(lei)就ok非靜(jing)態(tai)(tai)(tai)內部(bu)(bu)類(lei) 依(yi)賴于一個外部(bu)(bu)類(lei)對(dui)象(xiang),而靜(jing)態(tai)(tai)(tai)域(yu)/方法是不(bu)(bu)依(yi)賴與對(dui)象(xiang)——僅與類(lei)相(xiang)關(guan)(細說(shuo)了,就是加(jia)載靜(jing)態(tai)(tai)(tai)域(yu)時,根本(ben)沒有外部(bu)(bu)類(lei)對(dui)象(xiang))因此,非靜(jing)態(tai)(tai)(tai)內部(bu)(bu)類(lei)中不(bu)(bu)能定(ding)義靜(jing)態(tai)(tai)(tai)域(yu)/方法,編譯過不(bu)(bu)了。


而常(chang)(chang)量之所(suo)以可以(不論有無static),因為java在(zai)編譯(yi)期(qi)就(jiu)確(que)定所(suo)有常(chang)(chang)量,放到所(suo)謂的(de)常(chang)(chang)量池當中。常(chang)(chang)量的(de)機制和(he)普通變量不一樣

為什么匿名內部類和局部內部類只能訪問final變量

參(can)考:

posted @ 2014-09-19 00:10  ^_TONY_^  閱讀(14935)  評論(4)    收藏  舉報