溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java基礎(chǔ)8:深入理解內(nèi)部類

發(fā)布時(shí)間:2020-08-11 15:53:23 來源:ITPUB博客 閱讀:159 作者:a724888 欄目:編程語言

更多內(nèi)容請(qǐng)關(guān)注微信公眾號(hào)【Java技術(shù)江湖】

這是一位阿里 Java 工程師的技術(shù)小站,作者黃小斜,專注 Java 相關(guān)技術(shù):SSM、SpringBoot、MySQL、分布式、中間件、集群、Linux、網(wǎng)絡(luò)、多線程,偶爾講點(diǎn)Docker、ELK,同時(shí)也分享技術(shù)干貨和學(xué)習(xí)經(jīng)驗(yàn),致力于Java全棧開發(fā)!(關(guān)注公眾號(hào)后回復(fù)”資料“即可領(lǐng)取 3T 免費(fèi)技術(shù)學(xué)習(xí)資源以及我我原創(chuàng)的程序員校招指南、Java學(xué)習(xí)指南等資源)

** Java基礎(chǔ)8:深入理解內(nèi)部類
本文主要介紹了Java內(nèi)部類的基本原理,使用方法和各種細(xì)節(jié)。

有關(guān)內(nèi)部類實(shí)現(xiàn)回調(diào),事件驅(qū)動(dòng)和委托機(jī)制的文章將在后面發(fā)布。

具體代碼在我的GitHub中可以找到

https://github.com/h3pl/MyTech

文章首發(fā)于我的個(gè)人博客:

https://h3pl.github.io/2018/04/25/javase8

內(nèi)部類初探

一、什么是內(nèi)部類?

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

二、內(nèi)部類的共性

(1)內(nèi)部類仍然是一個(gè)獨(dú)立的類,在編譯之后內(nèi)部類會(huì)被編譯成獨(dú)立的.class文件,但是前面冠以外部類的類名和$符號(hào) 。

(2)內(nèi)部類不能用普通的方式訪問。

(3)內(nèi)部類聲明成靜態(tài)的,就不能隨便的訪問外部類的成員變量了,此時(shí)內(nèi)部類只能訪問外部類的靜態(tài)成員變量 。

(4)外部類不能直接訪問內(nèi)部類的的成員,但可以通過內(nèi)部類對(duì)象來訪問

  內(nèi)部類是外部類的一個(gè)成員,因此內(nèi)部類可以自由地訪問外部類的成員變量,無論是否是private的。

  因?yàn)楫?dāng)某個(gè)外圍類的對(duì)象創(chuàng)建內(nèi)部類的對(duì)象時(shí),此內(nèi)部類會(huì)捕獲一個(gè)隱式引用,它引用了實(shí)例化該內(nèi)部對(duì)象的外圍類對(duì)象。通過這個(gè)指針,可以訪問外圍類對(duì)象的全部狀態(tài)。

通過反編譯內(nèi)部類的字節(jié)碼,分析之后主要是通過以下幾步做到的:

  1 編譯器自動(dòng)為內(nèi)部類添加一個(gè)成員變量, 這個(gè)成員變量的類型和外部類的類型相同, 這個(gè)成員變量就是指向外部類對(duì)象的引用;

  2 編譯器自動(dòng)為內(nèi)部類的構(gòu)造方法添加一個(gè)參數(shù), 參數(shù)的類型是外部類的類型, 在構(gòu)造方法內(nèi)部使用這個(gè)參數(shù)為1中添加的成員變量賦值;

  3 在調(diào)用內(nèi)部類的構(gòu)造函數(shù)初始化內(nèi)部類對(duì)象時(shí), 會(huì)默認(rèn)傳入外部類的引用。

二、使用內(nèi)部類的好處:

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

1 只是為了降低包的深度,方便類的使用,靜態(tài)內(nèi)部類適用于包含類當(dāng)中,但又不依賴與外在的類。

2 由于Java規(guī)定靜態(tài)內(nèi)部類不能用使用外在類的非靜態(tài)屬性和方法,所以只是為了方便管理類結(jié)構(gòu)而定義。于是我們?cè)趧?chuàng)建靜態(tài)內(nèi)部類的時(shí)候,不需要外部類對(duì)象的引用。

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

1 內(nèi)部類繼承自某個(gè)類或?qū)崿F(xiàn)某個(gè)接口,內(nèi)部類的代碼操作創(chuàng)建其他外圍類的對(duì)象。所以你可以認(rèn)為內(nèi)部類提供了某種進(jìn)入其外圍類的窗口。

2 使用內(nèi)部類最吸引人的原因是:每個(gè)內(nèi)部類都能獨(dú)立地繼承自一個(gè)(接口的)實(shí)現(xiàn),所以無論外圍類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對(duì)于內(nèi)部類都沒有影響

3 如果沒有內(nèi)部類提供的可以繼承多個(gè)具體的或抽象的類的能力,一些設(shè)計(jì)與編程問題就很難解決。
從這個(gè)角度看,內(nèi)部類使得多重繼承的解決方案變得完整。接口解決了部分問題,而內(nèi)部類有效地實(shí)現(xiàn)了"多重繼承"。

三、
那靜態(tài)內(nèi)部類與普通內(nèi)部類有什么區(qū)別呢?問得好,區(qū)別如下:

(1)靜態(tài)內(nèi)部類不持有外部類的引用
在普通內(nèi)部類中,我們可以直接訪問外部類的屬性、方法,即使是private類型也可以訪問,這是因?yàn)閮?nèi)部類持有一個(gè)外部類的引用,可以自由訪問。而靜態(tài)內(nèi)部類,則只可以訪問外部類的靜態(tài)方法和靜態(tài)屬性(如果是private權(quán)限也能訪問,這是由其代碼位置所決定的),其他則不能訪問。

(2)靜態(tài)內(nèi)部類不依賴外部類
普通內(nèi)部類與外部類之間是相互依賴的關(guān)系,內(nèi)部類實(shí)例不能脫離外部類實(shí)例,也就是說它們會(huì)同生同死,一起聲明,一起被垃圾回收器回收。而靜態(tài)內(nèi)部類是可以獨(dú)立存在的,即使外部類消亡了,靜態(tài)內(nèi)部類還是可以存在的。

(3)普通內(nèi)部類不能聲明static的方法和變量
普通內(nèi)部類不能聲明static的方法和變量,注意這里說的是變量,常量(也就是final static修飾的屬性)還是可以的,而靜態(tài)內(nèi)部類形似外部類,沒有任何限制。

==為什么普通內(nèi)部類不能有靜態(tài)變量呢?==

1 成員內(nèi)部類 之所以叫做成員 就是說他是類實(shí)例的一部分 而不是類的一部分

2 結(jié)構(gòu)上來說 他和你聲明的成員變量是一樣的地位 一個(gè)特殊的成員變量 而靜態(tài)的變量是類的一部分和實(shí)例無關(guān)

3 你若聲明一個(gè)成員內(nèi)部類 讓他成為主類的實(shí)例一部分 然后又想在內(nèi)部類聲明和實(shí)例無關(guān)的靜態(tài)的東西 你讓JVM情何以堪啊

4 若想在內(nèi)部類內(nèi)聲明靜態(tài)字段 就必須將其內(nèi)部類本身聲明為靜態(tài)

非靜態(tài)內(nèi)部類有一個(gè)很大的優(yōu)點(diǎn):可以自由使用外部類的所有變量和方法

下面的例子大概地介紹了

1 非靜態(tài)內(nèi)部類和靜態(tài)內(nèi)部類的區(qū)別。

2 不同訪問權(quán)限的內(nèi)部類的使用。

3 外部類和它的內(nèi)部類之間的關(guān)系

//本節(jié)討論內(nèi)部類以及不同訪問權(quán)限的控制//內(nèi)部類只有在使用時(shí)才會(huì)被加載。//外部類Bpublic class B{    int i = 1;    int j = 1;    static int s = 1;    static int ss = 1;    A a;    AA aa;    AAA aaa;    //內(nèi)部類A    public class A {//        static void go () {////        }//        static {////        }//      static int b = 1;//非靜態(tài)內(nèi)部類不能有靜態(tài)成員變量和靜態(tài)代碼塊和靜態(tài)方法,        // 因?yàn)閮?nèi)部類在外部類加載時(shí)并不會(huì)被加載和初始化。        //所以不會(huì)進(jìn)行靜態(tài)代碼的調(diào)用        int i = 2;//外部類無法讀取內(nèi)部類的成員,而內(nèi)部類可以直接訪問外部類成員        public void test() {            System.out.println(j);            j = 2;            System.out.println(j);            System.out.println(s);//可以訪問類的靜態(tài)成員變量        }        public void test2() {            AA aa = new AA();            AAA aaa = new AAA();        }    }    //靜態(tài)內(nèi)部類S,可以被外部訪問    public static class S {        int i = 1;//訪問不到非靜態(tài)變量。        static int s = 0;//可以有靜態(tài)變量        public static void main(String[] args) {            System.out.println(s);        }        @Test        public void test () {//            System.out.println(j);//報(bào)錯(cuò),靜態(tài)內(nèi)部類不能讀取外部類的非靜態(tài)變量            System.out.println(s);            System.out.println(ss);            s = 2;            ss = 2;            System.out.println(s);            System.out.println(ss);        }    }    //內(nèi)部類AA,其實(shí)這里加protected相當(dāng)于default    //因?yàn)橥獠款愐{(diào)用內(nèi)部類只能通過B。并且無法直接繼承AA,所以必須在同包    //的類中才能調(diào)用到(這里不考慮靜態(tài)內(nèi)部類),那么就和default一樣了。    protected class AA{        int i = 2;//內(nèi)部類之間不共享變量        public void test (){            A a = new A();            AAA aaa = new AAA();            //內(nèi)部類之間可以互相訪問。        }    }    //包外部依然無法訪問,因?yàn)榘鼪]有繼承關(guān)系,所以找不到這個(gè)類    protected static class SS{        int i = 2;//內(nèi)部類之間不共享變量        public void test (){            //內(nèi)部類之間可以互相訪問。        }    }    //私有內(nèi)部類A,對(duì)外不可見,但對(duì)內(nèi)部類和父類可見    private class AAA {        int i = 2;//內(nèi)部類之間不共享變量        public void test() {            A a = new A();            AA aa = new AA();            //內(nèi)部類之間可以互相訪問。        }    }    @Test    public void test(){        A a = new A();        a.test();        //內(nèi)部類可以修改外部類的成員變量        //打印出 1 2        B b = new B();    }}//另一個(gè)外部類class C {    @Test    public void test() {        //首先,其他類內(nèi)部類只能通過外部類來獲取其實(shí)例。        B.S s = new B.S();        //靜態(tài)內(nèi)部類可以直接通過B類直接獲取,不需要B的實(shí)例,和靜態(tài)成員變量類似。        //B.A a = new B.A();        //當(dāng)A不是靜態(tài)類時(shí)這行代碼會(huì)報(bào)錯(cuò)。        //需要使用B的實(shí)例來獲取A的實(shí)例        B b = new B();        B.A a = b.new A();        B.AA aa = b.new AA();//B和C同包,所以可以訪問到AA//      B.AAA aaa = b.new AAA();AAA為私有內(nèi)部類,外部類不可見        //當(dāng)A使用private修飾時(shí),使用B的實(shí)例也無法獲取A的實(shí)例,這一點(diǎn)和私有變量是一樣的。        //所有普通的內(nèi)部類與類中的一個(gè)變量是類似的。靜態(tài)內(nèi)部類則與靜態(tài)成員類似。    }}

內(nèi)部類的加載

可能剛才的例子中沒辦法直觀地看到內(nèi)部類是如何加載的,接下來用例子展示一下內(nèi)部類加載的過程。

1 內(nèi)部類是延時(shí)加載的,也就是說只會(huì)在第一次使用時(shí)加載。不使用就不加載,所以可以很好的實(shí)現(xiàn)單例模式。

2 不論是靜態(tài)內(nèi)部類還是非靜態(tài)內(nèi)部類都是在第一次使用時(shí)才會(huì)被加載。

3 對(duì)于非靜態(tài)內(nèi)部類是不能出現(xiàn)靜態(tài)模塊(包含靜態(tài)塊,靜態(tài)屬性,靜態(tài)方法等)

4 非靜態(tài)類的使用需要依賴于外部類的對(duì)象,詳見上述對(duì)象innerClass 的初始化。

簡(jiǎn)單來說,類的加載都是發(fā)生在類要被用到的時(shí)候。內(nèi)部類也是一樣

1 普通內(nèi)部類在第一次用到時(shí)加載,并且每次實(shí)例化時(shí)都會(huì)執(zhí)行內(nèi)部成員變量的初始化,以及代碼塊和構(gòu)造方法。

2 靜態(tài)內(nèi)部類也是在第一次用到時(shí)被加載。但是當(dāng)它加載完以后就會(huì)將靜態(tài)成員變量初始化,運(yùn)行靜態(tài)代碼塊,并且只執(zhí)行一次。當(dāng)然,非靜態(tài)成員和代碼塊每次實(shí)例化時(shí)也會(huì)執(zhí)行。

總結(jié)一下Java類代碼加載的順序,萬變不離其宗。

規(guī)律一、初始化構(gòu)造時(shí),先父后子;只有在父類所有都構(gòu)造完后子類才被初始化

規(guī)律二、類加載先是靜態(tài)、后非靜態(tài)、最后是構(gòu)造函數(shù)。

靜態(tài)構(gòu)造塊、靜態(tài)類屬性按出現(xiàn)在類定義里面的先后順序初始化,同理非靜態(tài)的也是一樣的,只是靜態(tài)的只在加載字節(jié)碼時(shí)執(zhí)行一次,不管你new多少次,非靜態(tài)會(huì)在new多少次就執(zhí)行多少次

規(guī)律三、java中的類只有在被用到的時(shí)候才會(huì)被加載

規(guī)律四、java類只有在類字節(jié)碼被加載后才可以被構(gòu)造成對(duì)象實(shí)例

成員內(nèi)部類

在方法中定義的內(nèi)部類稱為局部?jī)?nèi)部類。與局部變量類似,局部?jī)?nèi)部類不能有訪問說明符,因?yàn)樗皇峭鈬惖囊徊糠?,但是它可以訪問當(dāng)前代碼塊內(nèi)的常量,和此外圍類所有的成員。

需要注意的是:
局部?jī)?nèi)部類只能在定義該內(nèi)部類的方法內(nèi)實(shí)例化,不可以在此方法外對(duì)其實(shí)例化。

public class 局部?jī)?nèi)部類 {    class A {//局部?jī)?nèi)部類就是寫在方法里的類,只在方法執(zhí)行時(shí)加載,一次性使用。        public void test() {            class B {                public void test () {                    class C {                    }                }            }        }    }    @Test    public void test () {        int i = 1;        final int j = 2;        class A {            @Test            public void test () {                System.out.println(i);                System.out.println(j);            }        }        A a = new A();        System.out.println(a);    }    static class B {        public static void test () {            //static class A報(bào)錯(cuò),方法里不能定義靜態(tài)內(nèi)部類。            //因?yàn)橹挥性诜椒ㄕ{(diào)用時(shí)才能進(jìn)行類加載和初始化。        }    }}

匿名內(nèi)部類

簡(jiǎn)單地說:匿名內(nèi)部類就是沒有名字的內(nèi)部類,并且,匿名內(nèi)部類是局部?jī)?nèi)部類的一種特殊形式。什么情況下需要使用匿名內(nèi)部類?如果滿足下面的一些條件,使用匿名內(nèi)部類是比較合適的:
只用到類的一個(gè)實(shí)例。
類在定義后馬上用到。
類非常?。⊿UN推薦是在4行代碼以下)
給類命名并不會(huì)導(dǎo)致你的代碼更容易被理解。
在使用匿名內(nèi)部類時(shí),要記住以下幾個(gè)原則:

1  匿名內(nèi)部類不能有構(gòu)造方法。

2  匿名內(nèi)部類不能定義任何靜態(tài)成員、方法和類。

3  匿名內(nèi)部類不能是public,protected,private,static。

4  只能創(chuàng)建匿名內(nèi)部類的一個(gè)實(shí)例。

5 一個(gè)匿名內(nèi)部類一定是在new的后面,用其隱含實(shí)現(xiàn)一個(gè)接口或?qū)崿F(xiàn)一個(gè)類。

6  因匿名內(nèi)部類為局部?jī)?nèi)部類,所以局部?jī)?nèi)部類的所有限制都對(duì)其生效。

一個(gè)匿名內(nèi)部類的例子:

    public class 匿名內(nèi)部類 {}interface D{    void run ();}abstract class E{    E (){    }    abstract void work();}class A {        @Test        public void test (int k) {            //利用接口寫出一個(gè)實(shí)現(xiàn)該接口的類的實(shí)例。            //有且僅有一個(gè)實(shí)例,這個(gè)類無法重用。            new Runnable() {                @Override                public void run() {//                    k = 1;報(bào)錯(cuò),當(dāng)外部方法中的局部變量在內(nèi)部類使用中必須改為final類型。                    //因?yàn)榉酵獠糠ㄖ屑词垢淖兞诉@個(gè)變量也不會(huì)反映到內(nèi)部類中。                    //所以對(duì)于內(nèi)部類來講這只是一個(gè)常量。                    System.out.println(100);                    System.out.println(k);                }            };            new D(){                //實(shí)現(xiàn)接口的匿名類                int i =1;                @Override                public void run() {                    System.out.println("run");                    System.out.println(i);                    System.out.println(k);                }            }.run();            new E(){                //繼承抽象類的匿名類                int i = 1;                void run (int j) {                    j = 1;                }                @Override                void work() {                }            };        }}

匿名內(nèi)部類里的final

使用的形參為何要為final

參考文件: http://android.blog.51cto.com/268543/384844

我們給匿名內(nèi)部類傳遞參數(shù)的時(shí)候,若該形參在內(nèi)部類中需要被使用,那么該形參必須要為final。也就是說:當(dāng)所在的方法的形參需要被內(nèi)部類里面使用時(shí),該形參必須為final。

為什么必須要為final呢?

首先我們知道在內(nèi)部類編譯成功后,它會(huì)產(chǎn)生一個(gè)class文件,該class文件與外部類并不是同一class文件,僅僅只保留對(duì)外部類的引用。當(dāng)外部類傳入的參數(shù)需要被內(nèi)部類調(diào)用時(shí),從java程序的角度來看是直接被調(diào)用:

public class OuterClass {    public void display(final String name,String age){        class InnerClass{            void display(){                System.out.println(name);            }        }    }}

從上面代碼中看好像name參數(shù)應(yīng)該是被內(nèi)部類直接調(diào)用?其實(shí)不然,在java編譯之后實(shí)際的操作如下:

public class OuterClass$InnerClass {    public InnerClass(String name,String age){        this.InnerClass$name = name;        this.InnerClass$age = age;    }            public void display(){        System.out.println(this.InnerClass$name + "----" + this.InnerClass$age );    }}

所以從上面代碼來看,內(nèi)部類并不是直接調(diào)用方法傳遞的參數(shù),而是利用自身的構(gòu)造器對(duì)傳入的參數(shù)進(jìn)行備份,自己內(nèi)部方法調(diào)用的實(shí)際上時(shí)自己的屬性而不是外部方法傳遞進(jìn)來的參數(shù)。

直到這里還沒有解釋為什么是final

在內(nèi)部類中的屬性和外部方法的參數(shù)兩者從外表上看是同一個(gè)東西,但實(shí)際上卻不是,所以他們兩者是可以任意變化的,也就是說在內(nèi)部類中我對(duì)屬性的改變并不會(huì)影響到外部的形參,而然這從程序員的角度來看這是不可行的。

畢竟站在程序的角度來看這兩個(gè)根本就是同一個(gè),如果內(nèi)部類該變了,而外部方法的形參卻沒有改變這是難以理解和不可接受的,所以為了保持參數(shù)的一致性,就規(guī)定使用final來避免形參的不改變。

簡(jiǎn)單理解就是,拷貝引用,為了避免引用值發(fā)生改變,例如被外部類的方法修改等,而導(dǎo)致內(nèi)部類得到的值不一致,于是用final來讓該引用不可改變。

故如果定義了一個(gè)匿名內(nèi)部類,并且希望它使用一個(gè)其外部定義的參數(shù),那么編譯器會(huì)要求該參數(shù)引用是final的。

內(nèi)部類初始化

我們一般都是利用構(gòu)造器來完成某個(gè)實(shí)例的初始化工作的,但是匿名內(nèi)部類是沒有構(gòu)造器的!那怎么來初始化匿名內(nèi)部類呢?使用構(gòu)造代碼塊!利用構(gòu)造代碼塊能夠達(dá)到為匿名內(nèi)部類創(chuàng)建一個(gè)構(gòu)造器的效果。

public class OutClass {    public InnerClass getInnerClass(final int age,final String name){        return new InnerClass() {            int age_ ;            String name_;            //構(gòu)造代碼塊完成初始化工作            {                if(0 < age && age < 200){                    age_ = age;                    name_ = name;                }            }            public String getName() {                return name_;            }                        public int getAge() {                return age_;            }        };    }

內(nèi)部類的重載

  如果你創(chuàng)建了一個(gè)內(nèi)部類,然后繼承其外圍類并重新定義此內(nèi)部類時(shí),會(huì)發(fā)生什么呢?也就是說,內(nèi)部類可以被重載嗎?這看起來似乎是個(gè)很有用的點(diǎn)子,但是“重載”內(nèi)部類就好像它是外圍類的一個(gè)方法,其實(shí)并不起什么作用:

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();       }}復(fù)制代碼輸出結(jié)果為:New Egg()Egg.Yolk()

缺省的構(gòu)造器是編譯器自動(dòng)生成的,這里是調(diào)用基類的缺省構(gòu)造器。你可能認(rèn)為既然創(chuàng)建了BigEgg 的對(duì)象,那么所使用的應(yīng)該是被“重載”過的Yolk,但你可以從輸出中看到實(shí)際情況并不是這樣的。
這個(gè)例子說明,當(dāng)你繼承了某個(gè)外圍類的時(shí)候,內(nèi)部類并沒有發(fā)生什么特別神奇的變化。這兩個(gè)內(nèi)部類是完全獨(dú)立的兩個(gè)實(shí)體,各自在自己的命名空間內(nèi)。

內(nèi)部類的繼承

因?yàn)閮?nèi)部類的構(gòu)造器要用到其外圍類對(duì)象的引用,所以在你繼承一個(gè)內(nèi)部類的時(shí)候,事情變得有點(diǎn)復(fù)雜。問題在于,那個(gè)“秘密的”外圍類對(duì)象的引用必須被初始化,而在被繼承的類中并不存在要聯(lián)接的缺省對(duì)象。要解決這個(gè)問題,需使用專門的語法來明確說清它們之間的關(guān)聯(lián):

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);        }}

復(fù)制代碼
輸出結(jié)果為:
this is a constructor in WithInner.Inner
this is a constructor in InheritInner

可以看到,InheritInner 只繼承自內(nèi)部類,而不是外圍類。但是當(dāng)要生成一個(gè)構(gòu)造器時(shí),缺省的構(gòu)造器并不算好,而且你不能只是傳遞一個(gè)指向外圍類對(duì)象的引用。此外,你必須在構(gòu)造器內(nèi)使用如下語法:
enclosingClassReference.super();
這樣才提供了必要的引用,然后程序才能編譯通過。

有關(guān)匿名內(nèi)部類實(shí)現(xiàn)回調(diào),事件驅(qū)動(dòng),委托等機(jī)制的文章將在下一節(jié)講述。


向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI