欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java內(nèi)部類(lèi)深入解析

 更新時(shí)間:2023年12月29日 09:59:52   作者:理想萬(wàn)歲萬(wàn)萬(wàn)歲  
這篇文章主要介紹了Java內(nèi)部類(lèi)深入解析,在java中,我們被允許在編寫(xiě)一個(gè)類(lèi)(外部類(lèi)OuterClass)時(shí),在其內(nèi)部再嵌套一個(gè)類(lèi)(嵌套類(lèi)NestedClass),java將嵌套類(lèi)分為兩種,非靜態(tài)內(nèi)部類(lèi)(簡(jiǎn)稱內(nèi)部類(lèi))和 靜態(tài)內(nèi)部,需要的朋友可以參考下

一、介紹

在java中,我們被允許在編寫(xiě)一個(gè)類(lèi)(外部類(lèi)OuterClass)時(shí),在其內(nèi)部再嵌套一個(gè)類(lèi)(嵌套類(lèi)NestedClass),java將嵌套類(lèi)分為兩種:非靜態(tài)內(nèi)部類(lèi)(簡(jiǎn)稱內(nèi)部類(lèi)) 和 靜態(tài)內(nèi)部類(lèi),如下所示

public class OuterClass {
    class InnerClass {
    }
    static class StaticInnerClass {
    }
}

嵌套類(lèi)作為外部類(lèi)的一個(gè)成員,無(wú)論其是否為靜態(tài)內(nèi)部類(lèi),我們都可以對(duì)其添加任何的訪問(wèn)修飾符(public、protected、private、default),如下所示

public class OuterClass {
    public class InnerClass {
    }
    protected static class StaticInnerClass {
    }
}

非靜態(tài)內(nèi)部類(lèi)對(duì)其外部類(lèi)中的所有成員變量和方法都具有訪問(wèn)權(quán),即便它被private修飾也可以。但是靜態(tài)內(nèi)部類(lèi)對(duì)外部類(lèi)中的成員變量和方法沒(méi)有訪問(wèn)權(quán)。

二、為什么要使用內(nèi)部類(lèi)

內(nèi)部類(lèi)為我們提供了以下便利:

  • 它對(duì)只在一個(gè)地方使用的類(lèi)進(jìn)行邏輯分組

如果一個(gè)類(lèi)A.java只對(duì)另一個(gè)類(lèi)B.java有用,那么將它嵌入到那個(gè)類(lèi)中并把兩個(gè)類(lèi)放在一起豈不合理?即把A.java作為內(nèi)部類(lèi),而將B.java作為外部類(lèi)。

  • 它增加了封裝性

考慮兩個(gè)類(lèi)A.java 和 B.java,其中B.java需要訪問(wèn)A.java的被聲明為private的成員變量或方法。通過(guò)將類(lèi)B.java隱藏在類(lèi)A.java中,A.java的成員變量或方法可以被聲明為private,B.java也可以訪問(wèn)它們。另外,B.java本身也可以對(duì)外界隱藏。

  • 它使代碼更加可讀和可維護(hù)

將內(nèi)部類(lèi)嵌套在外部類(lèi)中使代碼更接近使用它的地方。

三、非靜態(tài)內(nèi)部類(lèi)

非靜態(tài)內(nèi)部類(lèi)有以下特點(diǎn):

  • 對(duì)其外部類(lèi)中的所有成員變量和方法都具有訪問(wèn)權(quán),即便它被private修飾也可以。
  • 不允許定義任何static修飾的成員變量和方法。
  • 外部類(lèi)必須通過(guò)非靜態(tài)內(nèi)部類(lèi)的實(shí)例對(duì)象訪問(wèn)其內(nèi)部的屬性和方法。
  • 編譯后生成兩個(gè)class文件:外部類(lèi).class 和 外部類(lèi)$內(nèi)部類(lèi).class。

當(dāng)我們實(shí)例化一個(gè)非靜態(tài)內(nèi)部類(lèi)的對(duì)象時(shí),使用以下方法

  • 在外部類(lèi)中實(shí)例化內(nèi)部類(lèi)
public class OuterClass {
    public void initInnerClass() {
        InnerClass innerClass = new InnerClass();
        innerClass.innerClassMethod_1();
    }
    class InnerClass {
        public void innerClassMethod_1() {
            System.out.println("調(diào)用內(nèi)部類(lèi)方法");
        }
    }
}
  • 在其他類(lèi)中實(shí)例化內(nèi)部類(lèi)
class InnerClassTest {
    public static void main(String[] args) {
        // 方式一:創(chuàng)建內(nèi)部類(lèi)innerClass實(shí)例
        OuterClass outerClass = new OuterClass();
        OuterClass.InnerClass innerClass1 = outerClass.new InnerClass();
        innerClass1.innerClassMethod_1();
        // 方式二:創(chuàng)建內(nèi)部類(lèi)innerClass實(shí)例
        OuterClass.InnerClass innerClass2 = new OuterClass().new InnerClass();
        innerClass2.innerClassMethod_1();
    }
}

非靜態(tài)內(nèi)部類(lèi)還有兩種特殊的類(lèi)型:局部?jī)?nèi)部類(lèi) 和 匿名內(nèi)部類(lèi)。后面細(xì)說(shuō)。

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

靜態(tài)內(nèi)部類(lèi)在行為上與其他類(lèi)相似

  • 對(duì)外部類(lèi)成員的訪問(wèn)只能通過(guò)外部類(lèi)的實(shí)例對(duì)象。
  • 編譯后生成兩個(gè)class文件:外部類(lèi).class 和 外部類(lèi)$內(nèi)部類(lèi).class。

當(dāng)我們實(shí)例化一個(gè)靜態(tài)內(nèi)部類(lèi)的對(duì)象時(shí),使用以下方法

在外部類(lèi)中實(shí)例化內(nèi)部類(lèi)

public class OuterClass {
    public void initStaticInnerClass() {
        StaticInnerClass staticInnerClass = new StaticInnerClass();
        staticInnerClass.staticInnerClassMethod_1();
    }
    static class StaticInnerClass {
        public void staticInnerClassMethod_1() {
            System.out.println("調(diào)用靜態(tài)內(nèi)部類(lèi)方法");
        }
    }
}

在其他類(lèi)中實(shí)例化內(nèi)部類(lèi)

class InnerClassTest {
    public static void main(String[] args) {
        OuterClass.StaticInnerClass staticInnerClass = new OuterClass.StaticInnerClass();
        staticInnerClass.staticInnerClassMethod_1();
    }
}

五、局部?jī)?nèi)部類(lèi)

在一個(gè)代碼塊聲明的類(lèi)叫局部?jī)?nèi)部類(lèi)。

此處的代碼塊指任何{}內(nèi)部(如靜態(tài)代碼塊、方法、for循環(huán)、if塊)

  • 局部?jī)?nèi)部類(lèi)可聲明在任何代碼塊中
  • 局部?jī)?nèi)部類(lèi)內(nèi)部可以訪問(wèn)其外部的成員變量,但該成員變量的值不允許被修改,因此我們需要使用final修飾。
  • 不允許定義任何static靜態(tài)成員變量或方法
  • 靜態(tài)方法中的局部?jī)?nèi)部類(lèi),只允許訪問(wèn)外部類(lèi)中的static靜態(tài)成員變量和方法。
  • 不允許被static修飾
  • 在{}代碼塊中不可以聲明接口interface。因?yàn)閕nterface接口天生就是靜態(tài)的。
  • 局部?jī)?nèi)部類(lèi)中僅允許在常量變量聲明中使用static。從java16開(kāi)始允許不被final修飾
  • 編譯后生成外部類(lèi).class 和 外部類(lèi)+$+編號(hào)+內(nèi)部類(lèi).class。

創(chuàng)建局部?jī)?nèi)部類(lèi)的方式如下:

public class OuterClass {
    public void localClassMethod() {
        for (int i=0; i<10; i++) {
            // for循環(huán)中的局部?jī)?nèi)部類(lèi)
            class LocalClassInFor {
            }
        }
        if (true) {
            // if代碼塊中的局部?jī)?nèi)部類(lèi)
            class LocalClassInIf {
            }
        }
        // 方法中的局部?jī)?nèi)部類(lèi)
        class LocalClass {
        }
    }
}

六、匿名內(nèi)部類(lèi)

在一個(gè)方法內(nèi)部聲明的類(lèi)但沒(méi)有命名該類(lèi)的名稱叫局部?jī)?nèi)部類(lèi)。匿名類(lèi)使您的代碼更加簡(jiǎn)潔。允許我們能夠同時(shí)聲明和實(shí)例化一個(gè)類(lèi)。除了沒(méi)有名字之外,它們類(lèi)似于局部?jī)?nèi)部類(lèi)。如果只需要使用一次局部?jī)?nèi)部類(lèi),就使用它們。

  • 本質(zhì)上是一個(gè)表達(dá)式。
  • 實(shí)例化匿名內(nèi)部類(lèi)需要借助一個(gè)父類(lèi) 或 接口。
  • 可以訪問(wèn)外部類(lèi)的成員變量和方法。與局部?jī)?nèi)部類(lèi)相同。
  • 不可以修改外部變量,但該變量的值不允許被修改,因此我們需要使用final修飾。與局部?jī)?nèi)部類(lèi)相同。
  • 與外部變量或方法重名時(shí),默認(rèn)采用就近原則訪問(wèn)。與非靜態(tài)內(nèi)部類(lèi)相同。
  • 不可以聲明static靜態(tài)變量或方法。但可以聲明final static常量。
  • 編譯后生成外部類(lèi).class 和 外部類(lèi)+$+編號(hào).class。

使用匿名內(nèi)部類(lèi)需要借助父類(lèi) 或 接口實(shí)現(xiàn),其本質(zhì)相同,都是對(duì)方法的重寫(xiě)。如下所示

使用父類(lèi)

public class AnonymousOuterClass {

    class InnerClass {
        private String innerField = "field in InnerClass";
        public void getField() {
            System.out.println(innerField);
        }
    }

    public void anonymousInnerMethod() {
        // 聲明并實(shí)例化匿名內(nèi)部類(lèi)
        InnerClass innerClass = new InnerClass() {
            private String innerField = "a";
            @Override
            public void getField() {
                // 輸出匿名內(nèi)部類(lèi)中的成員變量innerField
                System.out.println(innerField);
                // 輸出父類(lèi)類(lèi)中的成員變量innerField
                super.getField();
            }
        };

        innerClass.getField();
    }
}

class AnonymousOuterClassTest {
    public static void main(String[] args) {
        AnonymousOuterClass anonymousOuterClass = new AnonymousOuterClass();
        anonymousOuterClass.anonymousInnerMethod();
    }
}

使用接口

public class AnonymousOuterClass {
    interface InnerInterface {
        void getField();
    }
    public void anonymousInnerInterfaceMethod() {
        InnerInterface innerInterface = new InnerInterface() {
            private String innerField = "field in inner interface";
            @Override
            public void getField() {
                // 輸出匿名內(nèi)部類(lèi)中的成員變量innerField
                System.out.println(innerField);
            }
        };
        innerInterface.getField();
    }
}
class AnonymousOuterClassTest {
    public static void main(String[] args) {
        AnonymousOuterClass anonymousOuterClass = new AnonymousOuterClass();
        anonymousOuterClass.anonymousInnerInterfaceMethod();
    }
}

七、lambda表達(dá)式內(nèi)部類(lèi)

使用lambda表達(dá)式內(nèi)部類(lèi)的理由很簡(jiǎn)單:當(dāng)匿名內(nèi)部類(lèi)的父類(lèi)或接口中只有一個(gè)方法時(shí),其實(shí)現(xiàn)代碼最少也得五六行,為了使代碼簡(jiǎn)化,所以使用lambda表達(dá)式內(nèi)部類(lèi)。

  • 編譯后生成外部類(lèi).class。lambda表達(dá)式內(nèi)部類(lèi)不會(huì)生成單獨(dú)的class文件。
  • 其余特性與匿名內(nèi)部類(lèi)相同。

除了實(shí)例化方式不同,lambda表達(dá)式內(nèi)部類(lèi)和匿名內(nèi)部類(lèi)其余使用限制完全一致。

public class LambdaOuterClass {
    interface InnerInterface {
        void sayHello();
    }
    public void sayHello() {
        // lambda表達(dá)式內(nèi)部類(lèi)
        InnerInterface innerInterface = () -> System.out.println("hello world");
        innerInterface.sayHello();
    }
}
class LambdaOuterClassTest {
    public static void main(String[] args) {
        LambdaOuterClass lambdaOuterClass = new LambdaOuterClass();
        lambdaOuterClass.sayHello();
    }
}

八、成員重名

無(wú)論是靜態(tài)內(nèi)部類(lèi)還是非靜態(tài)內(nèi)部類(lèi),當(dāng)內(nèi)部類(lèi)中與外部類(lèi)具有相同名稱的成員變量的情況下,當(dāng)我們?cè)趦?nèi)部類(lèi)中使用該變量時(shí),默認(rèn)采用就近原則的方式訪問(wèn)該變量。如果需要訪問(wèn)外部類(lèi)中的重名變量時(shí),則需要通過(guò)OuterClass.this.field訪問(wèn),如下所示

public class OuterClass {
    private String sameNameField = "the same name field in OuterClass";
    class InnerClass {
        private String sameNameField = "the same name field in InnerClass";
        public void testSameNameField() {
            // 訪問(wèn)內(nèi)部類(lèi)的重名變量
            System.out.println(sameNameField);
            // 訪問(wèn)外部類(lèi)的重名變量
            System.out.println(OuterClass.this.sameNameField);
        }
    }
}

九、序列化

java強(qiáng)烈建議不要序列化內(nèi)部類(lèi),包括局部?jī)?nèi)部類(lèi)和匿名類(lèi)。當(dāng)Java編譯器編譯某些結(jié)構(gòu)時(shí),比如內(nèi)部類(lèi),它創(chuàng)建合成結(jié)構(gòu),這些是在源代碼中沒(méi)有相應(yīng)構(gòu)造的類(lèi)、方法、字段和其他構(gòu)造。合成結(jié)構(gòu)使Java編譯器能夠在不改變JVM的情況下實(shí)現(xiàn)新的Java語(yǔ)言特性。然而,合成構(gòu)造在不同的Java編譯器實(shí)現(xiàn)中可能有所不同,這意味著在不同的實(shí)現(xiàn)中,類(lèi)文件也可能不同。因此,如果我們序列化一個(gè)內(nèi)部類(lèi),然后用不同的JRE實(shí)現(xiàn)反序列化它,可能會(huì)有兼容性問(wèn)題。

十、如何選擇內(nèi)部類(lèi)

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

當(dāng)需要訪問(wèn)外部類(lèi)實(shí)例的非public修飾的成員變量和方法時(shí)。

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

當(dāng)不需要訪問(wèn)外部類(lèi)實(shí)例的成員變量和方法時(shí)。

局部?jī)?nèi)部類(lèi)

當(dāng)我們需要?jiǎng)?chuàng)建一個(gè)類(lèi)的多個(gè)實(shí)例,請(qǐng)?jiān)L問(wèn)其構(gòu)造函數(shù),或者引入一個(gè)新的命名類(lèi)型(例如,因?yàn)槟院笮枰{(diào)用其他方法)。

匿名內(nèi)部類(lèi)

當(dāng)我們需要同時(shí)聲明和實(shí)例化一個(gè)類(lèi),并且只需要使用一次局部?jī)?nèi)部類(lèi)時(shí)。

lambda表達(dá)式內(nèi)部類(lèi)

到此這篇關(guān)于Java內(nèi)部類(lèi)深入解析的文章就介紹到這了,更多相關(guān)Java內(nèi)部類(lèi)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實(shí)現(xiàn)byte[]轉(zhuǎn)List的示例代碼

    Java實(shí)現(xiàn)byte[]轉(zhuǎn)List的示例代碼

    byte,即字節(jié),由8位的二進(jìn)制組成。在Java中,byte類(lèi)型的數(shù)據(jù)是8位帶符號(hào)的二進(jìn)制數(shù)。List?是一個(gè)接口,它繼承于Collection的接口。它代表著有序的隊(duì)列。本文將介紹如何通過(guò)java實(shí)現(xiàn)byte[]轉(zhuǎn)List,需要的可以參考一下
    2022-01-01
  • Spring中@Repository注解的作用和用法以及和@Mapper的區(qū)別詳析

    Spring中@Repository注解的作用和用法以及和@Mapper的區(qū)別詳析

    這篇文章主要給大家介紹了關(guān)于Spring中@Repository注解的作用和用法以及和@Mapper的區(qū)別的相關(guān)資料,注解的作用是標(biāo)識(shí)一個(gè)類(lèi)為數(shù)據(jù)訪問(wèn)對(duì)象,并由Spring框架進(jìn)行實(shí)例化和管理,需要的朋友可以參考下
    2023-09-09
  • 新手學(xué)習(xí)java反射基礎(chǔ)

    新手學(xué)習(xí)java反射基礎(chǔ)

    Java反射就是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類(lèi),都能夠知道這個(gè)類(lèi)的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;并且能改變它的屬性。下面我們來(lái)一起學(xué)習(xí)一下吧
    2019-06-06
  • springboot整合 xxl-job的項(xiàng)目實(shí)踐

    springboot整合 xxl-job的項(xiàng)目實(shí)踐

    XL-JOB是一個(gè)分布式任務(wù)調(diào)度平臺(tái),用于解決分布式系統(tǒng)中的任務(wù)調(diào)度和管理問(wèn)題,它包括調(diào)度中心、執(zhí)行器和Web管理控制臺(tái),本文就來(lái)介紹一下springboot整合 xxl-job的項(xiàng)目實(shí)踐,感興趣的可以了解一下
    2024-09-09
  • 使用Java判定一個(gè)數(shù)值是否在指定的開(kāi)閉區(qū)間范圍內(nèi)

    使用Java判定一個(gè)數(shù)值是否在指定的開(kāi)閉區(qū)間范圍內(nèi)

    這篇文章主要給大家介紹了關(guān)于使用Java判定一個(gè)數(shù)值是否在指定的開(kāi)閉區(qū)間范圍內(nèi)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-09-09
  • Java微信二次開(kāi)發(fā)(一) Java微信請(qǐng)求驗(yàn)證功能

    Java微信二次開(kāi)發(fā)(一) Java微信請(qǐng)求驗(yàn)證功能

    這篇文章主要為大家詳細(xì)介紹了Java微信二次開(kāi)發(fā)第一篇,Java微信請(qǐng)求驗(yàn)證功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 有關(guān)tomcat內(nèi)存溢出的完美解決方法

    有關(guān)tomcat內(nèi)存溢出的完美解決方法

    下面小編就為大家?guī)?lái)一篇有關(guān)tomcat內(nèi)存溢出的完美解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-05-05
  • Java8 Lambda表達(dá)式詳解及實(shí)例

    Java8 Lambda表達(dá)式詳解及實(shí)例

    這篇文章主要介紹了Java8 Lambda表達(dá)式詳解的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • java實(shí)現(xiàn)快速排序圖文詳解

    java實(shí)現(xiàn)快速排序圖文詳解

    網(wǎng)上關(guān)于快速排序的算法原理和算法實(shí)現(xiàn)都比較多,不過(guò)java是實(shí)現(xiàn)并不多,而且部分實(shí)現(xiàn)很難理解,和思路有點(diǎn)不搭調(diào)。所以整理了這篇文章。如果有不妥之處還請(qǐng)建議
    2021-08-08
  • java實(shí)現(xiàn)dijkstra最短路徑尋路算法

    java實(shí)現(xiàn)dijkstra最短路徑尋路算法

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)dijkstra最短路徑尋路算法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01

最新評(píng)論