国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java基礎(chǔ)-內(nèi)部類詳解

graf / 1181人閱讀

摘要:序內(nèi)部類是定義在另一個(gè)類內(nèi)部的類。之所以定義在內(nèi)部是因?yàn)閮?nèi)部類有一些普通類沒有的特權(quán),可以方便實(shí)現(xiàn)一些需求。還有明確的使用內(nèi)部類的構(gòu)建函數(shù)。在以后,使用表達(dá)式會(huì)比匿名內(nèi)部類更加方便。

我的博客   轉(zhuǎn)載請(qǐng)注明原創(chuàng)出處。

內(nèi)部類(inner class)是定義在另一個(gè)類內(nèi)部的類。之所以定義在內(nèi)部是因?yàn)閮?nèi)部類有一些普通類沒有的“特權(quán)”,可以方便實(shí)現(xiàn)一些需求。

內(nèi)部類

先來(lái)看一個(gè)簡(jiǎn)單的例子:

public class Apple {

    private int size = 16;

    private class Book {
        public void print() {
            System.out.println(size);
        }
    }

}

Book類就是定義在Apple類中的一個(gè)內(nèi)部類,Book類引用了Apple類的私有域size卻沒有報(bào)錯(cuò),這就是上文提到的特權(quán)了,內(nèi)部類可以引用外圍類的所有域和方法包括私有的。那么為什么內(nèi)部類可以做到這樣神奇的事情呢?原來(lái)是編譯器在背后偷偷干的好事!

把上文的例子編譯后可以看到編譯器會(huì)額外生成一個(gè)Apple$Book.class文件:

class Apple$Book {
    private Apple$Book(Apple var1) {
        this.this$0 = var1;
    }

    public void print() {
        System.out.println(Apple.access$000(this.this$0));
    }
}

可以看到這個(gè)類的名稱是用外圍類名稱加內(nèi)部類名稱用$符號(hào)分割,而且編譯器在內(nèi)部類的構(gòu)造函數(shù)里自動(dòng)添加了一個(gè)外圍類的參數(shù),這樣內(nèi)部類就能引用到外圍類的域和參數(shù)了。

不過這樣還有一個(gè)問題,我們完全可以按普通的方式自己寫一個(gè)構(gòu)建方式來(lái)接收Apple類而不用內(nèi)部類的方式,不過這樣的類卻無(wú)法引用Apple類的私有域和私有方法。

眼尖的同學(xué)可能已經(jīng)發(fā)現(xiàn)奧秘了,Apple.access$000(this.this$0)這一條語(yǔ)句就是關(guān)鍵了。內(nèi)部類在引用外圍類的私有域和方法時(shí)編譯器會(huì)在外圍類內(nèi)部生成一個(gè)靜態(tài)方法access$XXX,這個(gè)方法會(huì)返回外圍類的私有域或調(diào)用私有方法,方法的第一個(gè)參數(shù)是外圍類的引用。

不過這樣就有了安全風(fēng)險(xiǎn),任何人都可以通過調(diào)用Apple.access$000方法很容易地讀取到私有域size。當(dāng)然,access$000不是Java的合法方法名。但熟悉類文件結(jié)構(gòu)的黑客可以使用十六進(jìn)制編輯器輕松地創(chuàng)建一個(gè)用虛擬機(jī)指令調(diào)用那個(gè)方法的類文件。由于隱秘地訪問方法需要擁有包可見性,所以攻擊代碼需要與被攻擊類放在同一個(gè)包中。

特殊的語(yǔ)法

內(nèi)部類有一些特殊的語(yǔ)法,比如獲取傳入的外圍類引用的語(yǔ)法是OuterClass.this,外圍類的類名加上this關(guān)鍵字。還有明確的使用內(nèi)部類的構(gòu)建函數(shù)outerObject.new InnerClass {construction parameters)。在內(nèi)部類中聲明的靜態(tài)域必須是不可變的,即必須用final修飾符修飾,且不能有靜態(tài)方法。例子:

public class Apple {

    private int size = 16;

    private class Book {
        public void print() {
            System.out.println(Apple.this.size);
        }
    }

    public static void main(String[] args) {
        Apple apple = new Apple();
        Apple.Book book = apple.new Book();
    }

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

內(nèi)部類也可以在一個(gè)方法內(nèi)聲明,這樣定義的內(nèi)部類就是局部?jī)?nèi)部類。局部?jī)?nèi)部類和內(nèi)部類的區(qū)別在于局部?jī)?nèi)部類的作用域局限于定義它的方法塊內(nèi),除了這個(gè)方法內(nèi)部局部?jī)?nèi)部類都是不可見的。

public class Apple {

    private int size = 16;

    private void print() {
        class Book {
            public void print() {
                System.out.println(size);
            }
        }
        Book book = new Book();
        book.print();
    }

}
匿名內(nèi)部類

顧名思義,匿名內(nèi)部類是一種沒有類名的類。因?yàn)橛袝r(shí)候我們只需要有一個(gè)一次性使用的類的對(duì)象,匿名內(nèi)部類可以方便我們實(shí)現(xiàn)。通常的語(yǔ)法格式為:

SuperType superType = new SuperType(construction parameters) {
    inner class methods and data
}

如果SuperType是一個(gè)接口,那么就需要在大括號(hào)里實(shí)現(xiàn)接口定義的抽象方法。如果SuperType是一個(gè)類,可以在大括號(hào)里擴(kuò)展這個(gè)類。因?yàn)槟涿麅?nèi)部類沒有類名,所以是不能定義構(gòu)建函數(shù)的。在Java8以后,使用lambda表達(dá)式會(huì)比匿名內(nèi)部類更加方便。

雙括號(hào)初始化

利用匿名內(nèi)部類的特殊語(yǔ)法的特殊初始化技巧,比如初始化一個(gè)數(shù)組:

List arrayList = new ArrayList() {{
    add("test");
    add("test2");
}};

不過就這個(gè)例子來(lái)說這樣更好:List arrayList = Arrays.asList("test", "test2");

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

上文說到內(nèi)部類都會(huì)有一個(gè)外圍類的引用,不過有時(shí)我們只是想把類放在另一個(gè)類內(nèi)部并不需要引用它,這時(shí)就可以用到靜態(tài)內(nèi)部類。例子:

public class Apple {

    private int size;

    private int price;

    public Apple(int size, int price) {
        this.size = size;
        this.price = price;
    }

    public static void main(String[] args) {
        Apple apple = AppleBuilder.builder().setPrice(20).setSize(16).build();
    }

    static class AppleBuilder {

        private int size;

        private int price;

        static AppleBuilder builder() {
            return new AppleBuilder();
        }

        Apple build() {
            return new Apple(size, price);
        }

        AppleBuilder setSize(int size) {
            this.size = size;
            return this;
        }

        AppleBuilder setPrice(int price) {
            this.price = price;
            return this;
        }

    }

}
后記

一周一篇的第八篇了,接下來(lái)再?gòu)?fù)習(xí)一下并發(fā)相關(guān)的內(nèi)容就準(zhǔn)備去看看JVM相關(guān)的內(nèi)容了。知識(shí)學(xué)是學(xué)不完的,只希望自己能堅(jiān)持學(xué)到老,不要待在舒適區(qū)變成一個(gè)曾經(jīng)討厭的老頑固。這次同樣是參考《Java核心技術(shù) 卷1》,這可真是一本好書,建議Java新手都去看看。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/71790.html

相關(guān)文章

  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    spacewander 評(píng)論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    xfee 評(píng)論0 收藏0
  • 后臺(tái)開發(fā)常問面試題集錦(問題搬運(yùn)工,附鏈接)

    摘要:基礎(chǔ)問題的的性能及原理之區(qū)別詳解備忘筆記深入理解流水線抽象關(guān)鍵字修飾符知識(shí)點(diǎn)總結(jié)必看篇中的關(guān)鍵字解析回調(diào)機(jī)制解讀抽象類與三大特征時(shí)間和時(shí)間戳的相互轉(zhuǎn)換為什么要使用內(nèi)部類對(duì)象鎖和類鎖的區(qū)別,,優(yōu)缺點(diǎn)及比較提高篇八詳解內(nèi)部類單例模式和 Java基礎(chǔ)問題 String的+的性能及原理 java之yield(),sleep(),wait()區(qū)別詳解-備忘筆記 深入理解Java Stream流水...

    makeFoxPlay 評(píng)論0 收藏0
  • java源碼

    摘要:集合源碼解析回歸基礎(chǔ),集合源碼解析系列,持續(xù)更新和源碼分析與是兩個(gè)常用的操作字符串的類。這里我們從源碼看下不同狀態(tài)都是怎么處理的。 Java 集合深入理解:ArrayList 回歸基礎(chǔ),Java 集合深入理解系列,持續(xù)更新~ JVM 源碼分析之 System.currentTimeMillis 及 nanoTime 原理詳解 JVM 源碼分析之 System.currentTimeMi...

    Freeman 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<