Java 內部類

內部類(Nested Class)仍是獨立的類袁辈,只不過被包含于其他類中。編譯之后內部類會被編譯成獨立的.class文件。但是前面冠以外部類的類名和$符號.

成員內部類:

  1. 便于訪問外部類屬性页徐。
  2. 內部類輔助外部類完成某些功能。

如同一個人是由大腦银萍、肢體变勇、器官等身體結果組成,而內部類相當于其中的某個器官之一贴唇,例如心臟:它也有自己的屬性和行為(血液搀绣、跳動)。顯然戳气,此處不能單方面用屬性或者方法表示一個心臟链患,而需要一個類。而心臟又在人體當中瓶您,正如同是內部類在外部內當中麻捻。

實例1:內部類的基本結構

//外部類
class Out {
    private int age = 12;
     
    //內部類
    class In {
        public void print() {
            System.out.println(age);
        }
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out.In in = new Out().new In();
        in.print();
        //或者采用下種方式訪問
        /*
        Out out = new Out();
        Out.In in = out.new In();
        in.print();
        */
    }
}

運行結果:12

從上面的例子不難看出,內部類其實嚴重破壞了良好的代碼結構呀袱,但為什么還要使用內部類呢贸毕?

因為內部類可以隨意使用外部類的成員變量(包括私有)而不用生成外部類的對象,這也是內部類的唯一優(yōu)點

如同心臟可以直接訪問身體的血液夜赵,而不是通過醫(yī)生來抽血

程序編譯過后會產生兩個.class文件明棍,分別是Out.classOut$In.class

其中$代表了上面程序中Out.In中的那個.

Out.In in = new Out().new In()可以用來生成內部類的對象,這種方法存在兩個小知識點需要注意

  • 1.開頭的Out是為了標明需要生成的內部類對象在哪個外部類當中
  • 2.必須先有外部類的對象才能生成內部類的對象寇僧,因為內部類的作用就是為了訪問外部類中的成員變量

實例2:內部類中的變量訪問形式

class Out {
    private int age = 12;
     
    class In {
        private int age = 13;
        public void print() {
            int age = 14;
            System.out.println("局部變量:" + age);
            System.out.println("內部類變量:" + this.age);
            System.out.println("外部類變量:" + Out.this.age);
        }
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out.In in = new Out().new In();
        in.print();
    }
}

運行結果

局部變量:14
內部類變量:13
外部類變量:12

從實例1中可以發(fā)現(xiàn)摊腋,內部類在沒有同名成員變量和局部變量的情況下,內部類會直接訪問外部類的成員變量婉宰,而無需指定Out.this.屬性名

否則歌豺,內部類中的局部變量會覆蓋外部類的成員變量

而訪問內部類本身的成員變量可用this.屬性名,訪問外部類的成員變量需要使用Out.this.屬性名

靜態(tài)內部類

class Out {
    private static int age = 12;
     
    static class In {
        public void print() {
            System.out.println(age);
        }
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out.In in = new Out.In();
        in.print();
    }
}

可以看到心包,如果用static 將內部內靜態(tài)化,那么內部類就只能訪問外部類的靜態(tài)成員變量馒铃,具有局限性

其次蟹腾,因為內部類被靜態(tài)化痕惋,因此Out.In可以當做一個整體看,可以直接new 出內部類的對象(通過類名訪問static娃殖,生不生成外部類對象都沒關系)

實例4:私有內部類

class Out {
    private int age = 12;
     
    private class In {
        public void print() {
            System.out.println(age);
        }
    }
    public void outPrint() {
        new In().print();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        //此方法無效
        /*
        Out.In in = new Out().new In();
        in.print();
        */
        Out out = new Out();
        out.outPrint();
    }
}

如果一個內部類只希望被外部類中的方法操作值戳,那么可以使用private聲明內部類

上面的代碼中,我們必須在Out類里面生成In類的對象進行操作炉爆,而無法再使用Out.In in = new Out().new In() 生成內部類的對象

也就是說堕虹,此時的內部類只有外部類可控制

如同是,我的心臟只能由我的身體控制芬首,其他人無法直接訪問它

實例5:方法內部類

class Out {
    private int age = 12;
 
    public void Print(final int x) {
        class In {
            public void inPrint() {
                System.out.println(x);
                System.out.println(age);
            }
        }
        new In().inPrint();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out out = new Out();
        out.Print(3);
    }
}

在上面的代碼中赴捞,我們將內部類移到了外部類的方法中,然后在外部類的方法中再生成一個內部類對象去調用內部類方法

如果此時我們需要往外部類的方法中傳入?yún)?shù)郁稍,那么外部類的方法形參必須使用final定義

至于final在這里并沒有特殊含義赦政,只是一種表示形式而已

匿名內部類

匿名內部類也就是沒有名字的內部類

正因為沒有名字,所以匿名內部類只能使用一次耀怜,它通常用來簡化代碼編寫

但使用匿名內部類還有個前提條件:必須繼承一個父類或實現(xiàn)一個接口

實例1:不使用匿名內部類來實現(xiàn)抽象方法

abstract class Person {
    public abstract void eat();
}
 
class Child extends Person {
    public void eat() {
        System.out.println("eat something");
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Child();
        p.eat();
    }
}

運行結果eat something

可以看到恢着,我們用Child繼承了Person類,然后實現(xiàn)了Child的一個實例财破,將其向上轉型為Person類的引用

但是掰派,如果此處的Child類只使用一次,那么將其編寫為獨立的一個類豈不是很麻煩左痢?

這個時候就引入了匿名內部類

實例2:匿名內部類的基本實現(xiàn)

abstract class Person {
    public abstract void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

運行結果eat something

可以看到靡羡,我們直接將抽象類Person中的方法在大括號中實現(xiàn)了

這樣便可以省略一個類的書寫

并且,匿名內部類還能用于接口上

實例3:在接口上使用匿名內部類

interface Person {
    public void eat();
}
 
public class Demo {
    public static void main(String[] args) {
        Person p = new Person() {
            public void eat() {
                System.out.println("eat something");
            }
        };
        p.eat();
    }
}

由上面的例子可以看出抖锥,只要一個類是抽象的或是一個接口亿眠,那么其子類中的方法都可以使用匿名內部類來實現(xiàn)

最常用的情況就是在多線程的實現(xiàn)上,因為要實現(xiàn)多線程必須繼承Thread類或是繼承Runnable接口

實例4:Thread類的匿名內部類實現(xiàn)

public class Demo {
    public static void main(String[] args) {
        Thread t = new Thread() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        t.start();
    }
}

實例5:Runnable接口的匿名內部類實現(xiàn)

public class Demo {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    System.out.print(i + " ");
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }
}

實例6:運用內部類調用其他包類中的protected 的方法

當你想使用一個類的protected 方法時磅废,但是又不和這個類在同一個包下纳像,你是沒辦法調用的。
這時候匿名類就派上用場了拯勉,你可以聲明一個匿名類繼承該類竟趾,并定義一個方法,在這個方法內使用super調用你想調用的那個方法(其實你也可以寫個類繼承這個類宫峦,就能調用父類的protected方法了岔帽,但是匿名類更簡潔,因為你只想調用這個方法而已)导绷。例如:

public class Testclass {
    protected void test(){
        System.out.println("test...");
    }
}

這個類有一個protected方法test犀勒,如果你在其他包下想調用這個protected方法是不行的

這時候你可以使用匿名類繼承這個類,定義一個方法callParentTest(),在這個方法體內調用super.test()贾费,最后調用這個callParentTest()即可钦购。

public class UserOthreMethod{
    public static void main(String[] args){
        new Testclass{
            void callParentTest(){
                super.test();
            }
        }.callParentTest();
    }
}

內部類(Nested Class)仍是獨立的類,只不過被包含于其他類中褂萧。編譯之后內部類會被編譯成獨立的.class文件押桃。但是前面冠以外部類的類名和$符號.

成員內部類:

  1. 便于訪問外部類屬性。
  2. 內部類輔助外部類完成某些功能导犹。

如同一個人是由大腦唱凯、肢體、器官等身體結果組成谎痢,而內部類相當于其中的某個器官之一磕昼,例如心臟:它也有自己的屬性和行為(血液、跳動)舶得。顯然掰烟,此處不能單方面用屬性或者方法表示一個心臟,而需要一個類沐批。而心臟又在人體當中纫骑,正如同是內部類在外部內當中。

實例1:內部類的基本結構

//外部類
class Out {
    private int age = 12;
     
    //內部類
    class In {
        public void print() {
            System.out.println(age);
        }
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out.In in = new Out().new In();
        in.print();
        //或者采用下種方式訪問
        /*
        Out out = new Out();
        Out.In in = out.new In();
        in.print();
        */
    }
}

運行結果:12

從上面的例子不難看出九孩,內部類其實嚴重破壞了良好的代碼結構先馆,但為什么還要使用內部類呢?

因為內部類可以隨意使用外部類的成員變量(包括私有)而不用生成外部類的對象躺彬,這也是內部類的唯一優(yōu)點

如同心臟可以直接訪問身體的血液煤墙,而不是通過醫(yī)生來抽血

程序編譯過后會產生兩個.class文件,分別是Out.classOut$In.class

其中$代表了上面程序中Out.In中的那個.

Out.In in = new Out().new In()可以用來生成內部類的對象宪拥,這種方法存在兩個小知識點需要注意

  • 1.開頭的Out是為了標明需要生成的內部類對象在哪個外部類當中
  • 2.必須先有外部類的對象才能生成內部類的對象仿野,因為內部類的作用就是為了訪問外部類中的成員變量

實例2:內部類中的變量訪問形式

class Out {
    private int age = 12;
     
    class In {
        private int age = 13;
        public void print() {
            int age = 14;
            System.out.println("局部變量:" + age);
            System.out.println("內部類變量:" + this.age);
            System.out.println("外部類變量:" + Out.this.age);
        }
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out.In in = new Out().new In();
        in.print();
    }
}

運行結果

局部變量:14
內部類變量:13
外部類變量:12

從實例1中可以發(fā)現(xiàn),內部類在沒有同名成員變量和局部變量的情況下她君,內部類會直接訪問外部類的成員變量脚作,而無需指定Out.this.屬性名

否則,內部類中的局部變量會覆蓋外部類的成員變量

而訪問內部類本身的成員變量可用this.屬性名缔刹,訪問外部類的成員變量需要使用Out.this.屬性名

靜態(tài)內部類

class Out {
    private static int age = 12;
     
    static class In {
        public void print() {
            System.out.println(age);
        }
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out.In in = new Out.In();
        in.print();
    }
}

可以看到球涛,如果用static 將內部內靜態(tài)化,那么內部類就只能訪問外部類的靜態(tài)成員變量校镐,具有局限性

其次亿扁,因為內部類被靜態(tài)化,因此Out.In可以當做一個整體看鸟廓,可以直接new 出內部類的對象(通過類名訪問static从祝,生不生成外部類對象都沒關系)

實例4:私有內部類

class Out {
    private int age = 12;
     
    private class In {
        public void print() {
            System.out.println(age);
        }
    }
    public void outPrint() {
        new In().print();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        //此方法無效
        /*
        Out.In in = new Out().new In();
        in.print();
        */
        Out out = new Out();
        out.outPrint();
    }
}

如果一個內部類只希望被外部類中的方法操作襟己,那么可以使用private聲明內部類

上面的代碼中,我們必須在Out類里面生成In類的對象進行操作哄褒,而無法再使用Out.In in = new Out().new In() 生成內部類的對象

也就是說稀蟋,此時的內部類只有外部類可控制

如同是煌张,我的心臟只能由我的身體控制呐赡,其他人無法直接訪問它

實例5:方法內部類

class Out {
    private int age = 12;
 
    public void Print(final int x) {
        class In {
            public void inPrint() {
                System.out.println(x);
                System.out.println(age);
            }
        }
        new In().inPrint();
    }
}
 
public class Demo {
    public static void main(String[] args) {
        Out out = new Out();
        out.Print(3);
    }
}

在上面的代碼中,我們將內部類移到了外部類的方法中骏融,然后在外部類的方法中再生成一個內部類對象去調用內部類方法

如果此時我們需要往外部類的方法中傳入?yún)?shù)链嘀,那么外部類的方法形參必須使用final定義

至于final在這里并沒有特殊含義,只是一種表示形式而已

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末档玻,一起剝皮案震驚了整個濱河市怀泊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌误趴,老刑警劉巖霹琼,帶你破解...
    沈念sama閱讀 222,865評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異凉当,居然都是意外死亡枣申,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,296評論 3 399
  • 文/潘曉璐 我一進店門看杭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來忠藤,“玉大人,你說我怎么就攤上這事楼雹∧:ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 169,631評論 0 364
  • 文/不壞的土叔 我叫張陵贮缅,是天一觀的道長医增。 經(jīng)常有香客問我诈皿,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,199評論 1 300
  • 正文 為了忘掉前任今膊,我火速辦了婚禮,結果婚禮上吉嚣,老公的妹妹穿的比我還像新娘观话。我一直安慰自己,他們只是感情好轴或,可當我...
    茶點故事閱讀 69,196評論 6 398
  • 文/花漫 我一把揭開白布昌跌。 她就那樣靜靜地躺著,像睡著了一般照雁。 火紅的嫁衣襯著肌膚如雪蚕愤。 梳的紋絲不亂的頭發(fā)上答恶,一...
    開封第一講書人閱讀 52,793評論 1 314
  • 那天,我揣著相機與錄音萍诱,去河邊找鬼悬嗓。 笑死,一個胖子當著我的面吹牛裕坊,可吹牛的內容都是我干的包竹。 我是一名探鬼主播,決...
    沈念sama閱讀 41,221評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼籍凝,長吁一口氣:“原來是場噩夢啊……” “哼周瞎!你這毒婦竟也來了?” 一聲冷哼從身側響起饵蒂,我...
    開封第一講書人閱讀 40,174評論 0 277
  • 序言:老撾萬榮一對情侶失蹤声诸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后退盯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彼乌,經(jīng)...
    沈念sama閱讀 46,699評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,770評論 3 343
  • 正文 我和宋清朗相戀三年渊迁,在試婚紗的時候發(fā)現(xiàn)自己被綠了慰照。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,918評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡宫纬,死狀恐怖焚挠,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情漓骚,我是刑警寧澤蝌衔,帶...
    沈念sama閱讀 36,573評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站蝌蹂,受9級特大地震影響噩斟,放射性物質發(fā)生泄漏。R本人自食惡果不足惜孤个,卻給世界環(huán)境...
    茶點故事閱讀 42,255評論 3 336
  • 文/蒙蒙 一剃允、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧齐鲤,春花似錦斥废、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,749評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至淆九,卻和暖如春统锤,著一層夾襖步出監(jiān)牢的瞬間毛俏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,862評論 1 274
  • 我被黑心中介騙來泰國打工饲窿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留煌寇,地道東北人。 一個月前我還...
    沈念sama閱讀 49,364評論 3 379
  • 正文 我出身青樓逾雄,卻偏偏與公主長得像阀溶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嘲驾,可洞房花燭夜當晚...
    茶點故事閱讀 45,926評論 2 361

推薦閱讀更多精彩內容

  • Java 內部類 分四種:成員內部類淌哟、局部內部類、靜態(tài)內部類和匿名內部類辽故。 1、成員內部類: 即作為外部類的一個成...
    ikaroskun閱讀 1,239評論 0 13
  • 內部類就是定義在一個類中的另外一個類腐碱,是一種從屬關系誊垢。在沒有實際了解內部類之前,我始終困惑症见,為什么要在一個類中定義...
    Single_YAM閱讀 763評論 0 11
  • [toc] 內部類 內部類作為外部類的成員喂走,可以使用人已訪問控制符修飾。 外部類的上一級程序單元是包谋作,所以只有兩個...
    卡路fly閱讀 312評論 0 2
  • Even now there is still hope left 我高考之前遵蚜,去找我當時的愛豆簽名帖池,他就給我寫了...
    Serene小魚閱讀 402評論 1 2
  • 1、 激勵你的原因是什么吭净?從以下19條中選出3個并跟你的朋友談論睡汹。這是課上老師讓我們討論的一個問題。 且不說選擇是...
    Toby馮閱讀 234評論 0 0