日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++ 私有内部类_Java内部类新解,你没有见过的船新版本

發(fā)布時(shí)間:2023/12/19 c/c++ 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++ 私有内部类_Java内部类新解,你没有见过的船新版本 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基礎(chǔ)

Java支持類中嵌套類,稱之為nested class。嵌套的層數(shù)沒有限制,但實(shí)際中一般最多用兩層。根據(jù)內(nèi)部類是否有static修飾,分為 static nested class 和 non-static nested class 。non-static nested class又被稱為 inner class 。inner class里面又有兩個(gè)特殊一點(diǎn)的類:local class 和 anonymous class 。特殊之處主要在于語法使用上,實(shí)質(zhì)功能是差不多的。 官方 是這樣解釋的:

Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are called static nested classes. Non-static nested classes are called inner classes.

用圖表示分類及關(guān)系如下:

上面是按照官方的說法來分的,實(shí)際中很多人習(xí)慣把所有的嵌套類都稱為inner class(內(nèi)部類),這只是個(gè)稱謂,不影響溝通就好。后文用nested class來統(tǒng)稱static nested class和non-static nested class。各個(gè)類的主要特性和限制已經(jīng)在圖中說明了(適用于JDK 8及以后)。

那為什么需要內(nèi)部類呢?內(nèi)部類是在Java 1.1中引入的,當(dāng)時(shí)很多人質(zhì)疑該設(shè)計(jì)增加了Java的復(fù)雜性,但實(shí)用性不強(qiáng),當(dāng)然這種問題仁者見仁智者見智。官方的解釋是這樣的:

Why Use Nested Classes?

Compellingreasons for using nested classes include the following:

  • It is a way of logically grouping classes that are only used in one place : If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.**
  • It increases encapsulation : Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
  • It can lead to more readable and maintainable code : Nesting small classes within top-level classes places the code closer to where it is used.

總的來說,嵌套類最大的目的是改善代碼的組織,并不是必不可少的功能。嵌套類能實(shí)現(xiàn)的功能,通過正常的類都可以實(shí)現(xiàn),只不過可能要多寫點(diǎn)代碼,且不是很優(yōu)雅而已。

為什么inner class可以訪問外層類的非靜態(tài)成員

要說明的是: 嵌套類是對于編譯器而言的,對虛擬機(jī)來說沒有什么嵌套類,只有正常的類 。也就是說嵌套類經(jīng)過編譯器編譯之后要轉(zhuǎn)化成一個(gè)個(gè)正常的類,比如A類里面嵌套了B類。那經(jīng)過編譯器之后會變成兩個(gè)獨(dú)立的類: A 和 A$B 。這樣問題就很簡單了,B類要訪問A類的非靜態(tài)成員,要滿足兩個(gè)條件:

  • 要有A類的實(shí)例。
  • 且要有訪問成員的權(quán)限或者方式。
  • 而編譯器在編譯期間就幫我們干了這兩件事,下面驗(yàn)證一下。

    定義一個(gè)嵌套類:

    public class OuterClass {/*** 定義一個(gè)公有成員變量*/public Object publicVariable = "public member variable";private Object privateVariable = "private member variable";/*** 定義兩個(gè)私有成員變量*/ private Object privateVariable2 = "private member variable2";/*** 定義一個(gè)私有成員方法* @param parameter*/private void privateMethod(String parameter) {System.out.println(parameter);}/*** 調(diào)用inner class*/public void show() {InnerClass innerClass = new InnerClass();innerClass.print();}/*** inner class*/class InnerClass {void print() {// inner class里面直接調(diào)用了外部類的私有成員變量和成員方法System.out.println(privateVariable);privateMethod("invoke outer class private method.");// 調(diào)用外層類的公有變量System.out.println(publicVariable);}}public static void main(String[] args) {new OuterClass().show();} }

    上面代碼定義了外層類是 OuterClass ,內(nèi)部類是 InnerClass 。外層類定義了1個(gè)公有變量、2個(gè)私有變量和1個(gè)私有方法。然后在InnerClass里面直接使用了OuterClass的所有成員。程序運(yùn)行結(jié)果如下:

    private member variable invoke outer class private method. public member variable

    反編譯一下上面的兩個(gè)類:

    # javap -p OuterClass.class Compiled from "OuterClass.java" public class OuterClass {public java.lang.Object publicVariable;private java.lang.Object privateVariable;private java.lang.Object privateVariable2;public OuterClass();private void privateMethod(java.lang.String);public void show();public static void main(java.lang.String[]);# 注意這兩個(gè)靜態(tài)方法static java.lang.Object access$000(OuterClass);static void access$100(OuterClass, java.lang.String); }# javap -p OuterClass$InnerClass.class Compiled from "OuterClass.java" class OuterClass$InnerClass {# 注意這個(gè)final的成員變量和下面的構(gòu)造函數(shù)final OuterClass this$0;OuterClass$InnerClass(OuterClass);void print(); }

    結(jié)論就是:

  • 編譯器修改了內(nèi)部類:增加了一個(gè)final的外層類實(shí)例作為內(nèi)部類的成員變量;修改了內(nèi)部類的構(gòu)造函數(shù),將外部類實(shí)例通過內(nèi)部類的構(gòu)造函數(shù)傳遞給內(nèi)部類。這樣內(nèi)部類就有了外部類的實(shí)例,上面的第1個(gè)條件就達(dá)成了。
  • 編譯器在外部類中增加了幾個(gè)非private的靜態(tài)方法。對于內(nèi)部類訪問外部類的每一個(gè)私有成員,都會有這么一個(gè)方法。這樣內(nèi)部類就可以通過這些靜態(tài)方法去訪問外部類的私有成員了。非私有的成員直接通過1中的外層類實(shí)例即可訪問,所以就無需生成這些靜態(tài)方法了。
  • 再進(jìn)一步驗(yàn)證一下上面的結(jié)論1,當(dāng)執(zhí)行 InnerClass innerClass = new InnerClass(); 語句創(chuàng)建一個(gè)內(nèi)部類實(shí)例之后,可以觀測到下面的結(jié)果:

    可以看到,內(nèi)部類實(shí)例( OuterClass$InnerClass@470 )自動引用了外層類實(shí)例( OuterClass@464 )。所以, inner class之所以能訪問外層類的成員是因?yàn)樗趯?shí)例化的時(shí)候就已經(jīng)和一個(gè)外層類的實(shí)例關(guān)聯(lián)了 ,實(shí)際是通過這個(gè)外層類實(shí)例去訪問外層類的成員。對于私有成員,還生成了一些輔助的靜態(tài)方法。這也說明,要實(shí)例化inner class,必須先實(shí)例化它的外層類。

    另外有個(gè)限制就是inner class里面不能定義靜態(tài)變量和靜態(tài)方法,一個(gè)例外是可以定義基礎(chǔ)類型和String類型的靜態(tài)常量。比如:

    static final String s = “s”; // OK static final int i = 5; // OK static final Integer ii = 5; // 錯(cuò)誤

    local class和anonymous class都屬于特殊的inner class,所以上面講述的所有東西對他們也適用。

    為什么static nested class不能訪問外層類的非靜態(tài)成員

    原因很簡單,static nested class除了被定義到某個(gè)類里面以外,幾乎和普通的類沒有什么區(qū)別。 它不會和外層類的某個(gè)實(shí)例關(guān)聯(lián) ,比如我們在上面的OuterClass里面再定義一個(gè)StaticNestedClass :

    static class StaticNestedClass {private int a;void foo() {} }

    反編譯以后:

    # javap -p OuterClass$StaticNestedClass.class Compiled from "OuterClass.java" class OuterClass$StaticNestedClass {private int a;OuterClass$StaticNestedClass();void foo(); }

    除了類名被改寫了以外,和原來定義的類沒有任何區(qū)別。所以如果沒有被定義為private的話,static nested class完全可以獨(dú)立于外層類使用。

    所有nested class都可以訪問外層類的靜態(tài)成員

    上面討論的都是nested class能不能訪問外層類的非靜態(tài)成員,那如果是靜態(tài)成員呢?結(jié)論就是所有nested class都可以訪問的靜態(tài)成員,不管是不是私有。原理的話和inner class訪問外層類非static成員是一樣的,如果是private的,編譯器會在外層中生成一個(gè)輔助訪問的static方法,如果是非私有的,那通過類就可以直接訪問。

    ## 如果nested class是private的?

    我們知道正常的類是不能使用private和protected的(只能是public或者不加訪問修飾符),但nested class卻可以,因?yàn)閚ested class其實(shí)就是外層類的一個(gè)特殊成員,就像成員變量、成員方法一樣。比如,如果我們不想讓外部的其它類看到nested class的類,就可以將它設(shè)置成private的,但對于外層類是沒有影響的,照樣可以操作這個(gè)類。這個(gè)怎么做到的呢?

    我們將上面的StaticNestedClass改為private的:

    private static class StaticNestedClass {void foo() {System.out.println(a);} }

    反編譯看下:

    # javap -p OuterClass$StaticNestedClass.class Compiled from "OuterClass.java" class OuterClass$StaticNestedClass {private OuterClass$StaticNestedClass();void foo();OuterClass$StaticNestedClass(OuterClass$1); }

    可以看到,如果nested class被設(shè)置成private,它原來的構(gòu)造函數(shù)就會被設(shè)置為private的,同時(shí)編譯器又新增了一個(gè)外部可見的構(gòu)造函數(shù)OuterClass$StaticNestedClass(OuterClass$1) ,這個(gè)構(gòu)造函數(shù)的一個(gè)入?yún)⒕褪峭獠款惖膶?shí)例。這樣,外部類實(shí)例化nested class的時(shí)候會先調(diào)用這個(gè)構(gòu)造函數(shù),這個(gè)構(gòu)造函數(shù)內(nèi)部又調(diào)用了原始的private的構(gòu)造函數(shù)。inner class也是這樣的。

    ## 總結(jié)

    嵌套類的實(shí)質(zhì)就是外層類的成員,就像成員變量、成員方法一樣,初衷是提高代碼結(jié)構(gòu)的緊湊和可維護(hù)性。 使用嵌套類的幾乎唯一的場景就是這個(gè)內(nèi)部類僅供外層類(或者包含它的代碼塊)使用,其它場景都應(yīng)該使用正常的一級類 。按這個(gè)思路使用即可,不要濫用,更不要搞騷操作。

    Reference

    • Core Java Volume I
    • Orace The Java? Tutorials
    原文鏈接:https://niyanchun.com/java-nested-class.html

    如果覺得本文對你有幫助,可以點(diǎn)進(jìn)我主頁關(guān)注我公眾號,上面有更多技術(shù)干貨文章以及相關(guān)資料共享,大家一起學(xué)習(xí)進(jìn)步!

    總結(jié)

    以上是生活随笔為你收集整理的c++ 私有内部类_Java内部类新解,你没有见过的船新版本的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。