最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

一、介紹

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

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

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

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

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

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

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

  • 它對只在一個地方使用的類進行邏輯分組

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

  • 它增加了封裝性

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

  • 它使代碼更加可讀和可維護

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

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

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

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

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

  • 在外部類中實例化內(nè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)部類方法");
        }
    }
}
  • 在其他類中實例化內(nèi)部類
class InnerClassTest {
    public static void main(String[] args) {
        // 方式一:創(chuàng)建內(nèi)部類innerClass實例
        OuterClass outerClass = new OuterClass();
        OuterClass.InnerClass innerClass1 = outerClass.new InnerClass();
        innerClass1.innerClassMethod_1();
        // 方式二:創(chuàng)建內(nèi)部類innerClass實例
        OuterClass.InnerClass innerClass2 = new OuterClass().new InnerClass();
        innerClass2.innerClassMethod_1();
    }
}

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

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

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

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

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

在外部類中實例化內(nè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)部類方法");
        }
    }
}

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

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

五、局部內(nèi)部類

在一個代碼塊聲明的類叫局部內(nèi)部類。

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

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

創(chuàng)建局部內(nèi)部類的方式如下:

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

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

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

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

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

使用父類

public class AnonymousOuterClass {

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

    public void anonymousInnerMethod() {
        // 聲明并實例化匿名內(nèi)部類
        InnerClass innerClass = new InnerClass() {
            private String innerField = "a";
            @Override
            public void getField() {
                // 輸出匿名內(nèi)部類中的成員變量innerField
                System.out.println(innerField);
                // 輸出父類類中的成員變量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)部類中的成員變量innerField
                System.out.println(innerField);
            }
        };
        innerInterface.getField();
    }
}
class AnonymousOuterClassTest {
    public static void main(String[] args) {
        AnonymousOuterClass anonymousOuterClass = new AnonymousOuterClass();
        anonymousOuterClass.anonymousInnerInterfaceMethod();
    }
}

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

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

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

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

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

八、成員重名

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

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() {
            // 訪問內(nèi)部類的重名變量
            System.out.println(sameNameField);
            // 訪問外部類的重名變量
            System.out.println(OuterClass.this.sameNameField);
        }
    }
}

九、序列化

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

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

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

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

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

當(dāng)不需要訪問外部類實例的成員變量和方法時。

局部內(nèi)部類

當(dāng)我們需要創(chuàng)建一個類的多個實例,請訪問其構(gòu)造函數(shù),或者引入一個新的命名類型(例如,因為您稍后需要調(diào)用其他方法)。

匿名內(nèi)部類

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

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

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

相關(guān)文章

  • mybatis如何設(shè)置useGeneratedKeys=true

    mybatis如何設(shè)置useGeneratedKeys=true

    這篇文章主要介紹了mybatis如何設(shè)置useGeneratedKeys=true,具有很好的參考價值,希望對大家有所幫助。
    2022-01-01
  • 在同一個類中調(diào)用帶有@Transactional注解的方法示例

    在同一個類中調(diào)用帶有@Transactional注解的方法示例

    這篇文章主要為大家介紹了在同一個類中調(diào)用帶有@Transactional注解的方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-04-04
  • SpringBoot?Http遠(yuǎn)程調(diào)用的方法

    SpringBoot?Http遠(yuǎn)程調(diào)用的方法

    這篇文章主要為大家詳細(xì)介紹了SpringBoot?Http遠(yuǎn)程調(diào)用的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • Java中監(jiān)聽器Listener詳解

    Java中監(jiān)聽器Listener詳解

    Listener是由Java編寫的WEB組件,主要完成對內(nèi)置對象狀態(tài)的變化 (創(chuàng)建、銷毀)和屬性的變化進行監(jiān)聽,做進一步的處理,主要對session和application內(nèi)置對象監(jiān)聽,這篇文章主要介紹了Java中監(jiān)聽器Listener,需要的朋友可以參考下
    2023-08-08
  • java實現(xiàn)分布式鎖的常用三種方式

    java實現(xiàn)分布式鎖的常用三種方式

    本文主要介紹了java實現(xiàn)分布式鎖,一般有這3種方式,基于數(shù)據(jù)庫實現(xiàn)的分布式鎖、基于Redis實現(xiàn)的分布式鎖和基于Zookeeper實現(xiàn)的分布式鎖,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • Java單例模式下的MongoDB數(shù)據(jù)庫操作工具類

    Java單例模式下的MongoDB數(shù)據(jù)庫操作工具類

    這篇文章主要介紹了Java單例模式下的MongoDB數(shù)據(jù)庫操作工具類,結(jié)合實例形式分析了java基于單例模式下操作MongoDB數(shù)據(jù)庫相關(guān)連接、查詢、插入、刪除等操作封裝技巧,需要的朋友可以參考下
    2018-01-01
  • java 中 MD5加密的實例

    java 中 MD5加密的實例

    這篇文章主要介紹了java 中 MD5加密的實例的相關(guān)資料,通過本文希望能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • 詳解hbase與hive數(shù)據(jù)同步

    詳解hbase與hive數(shù)據(jù)同步

    這篇文章主要介紹了詳解hbase與hive數(shù)據(jù)同步的相關(guān)資料,需要的朋友可以參考下
    2017-09-09
  • java實現(xiàn)樹形菜單對象

    java實現(xiàn)樹形菜單對象

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)樹形菜單對象,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • springboot中使用FastJson解決long類型在js中失去精度的問題

    springboot中使用FastJson解決long類型在js中失去精度的問題

    這篇文章主要介紹了springboot中使用FastJson解決long類型在js中失去精度的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06

最新評論

江门市| 岑溪市| 大埔县| 黑山县| 宝丰县| 海丰县| 北碚区| 天津市| 伽师县| 化隆| 两当县| 棋牌| 福泉市| 五家渠市| 古浪县| 黄冈市| 灵宝市| 吉安县| 梨树县| 平武县| 太和县| 房山区| 韶山市| 富阳市| 桑日县| 来安县| 府谷县| 山丹县| 宝应县| 中江县| 麦盖提县| 咸宁市| 宁陕县| 南皮县| 萍乡市| 绥德县| 湖州市| 丽江市| 天气| 孟津县| 美姑县|