再來說說Java嵌套類(nested class)

2021-01-07 IT168

  【IT168 文檔】有時候開發時為了方便,在代碼中使用了不少嵌套類(nested class),但是使用過程中如果不了解嵌套類的特性,可能會造成意想不到的情況。

  Java對象想要通過網絡傳輸,必須實現序列化接口,於是我們在Service中定義了了一個實現了序列化接口的內部類,然後調用遠程接口將其傳輸到網絡上。

  一運行報異常:不能將沒有實現序列化接口的Object序列化。

  怎麼回事,這是一個很簡單的內部類,的確已經實現了序列化接口了,其定義的成員都是可序列化的String類型;將其換成普通類沒有問題。難道不能使用序列化的內部類?

  其實我們使用的內部類是嵌套類(nested class)的一種,而nested class 共有四種:

static nested class 靜態嵌套類inner class 內部類(非靜態)local class 本地類(定義在方法內部)anonymous class 匿名類

  靜態嵌套類的行為更接近普通的類,另外三個是真正的內部類。區別在於作用域的不同。

  以下是對他們的性質描述:

  以下還有一段程序說明它們的區別和使用方式:

  Java代碼 

/**  
*  
* 普通內部類持有對外部類的一個引用, 靜態內部類卻沒有  
*  
* @author howard  
*/  
public class OutterClass {  
  
    /*  
     * this is static nested class  
     */  
    private static class StaticNestedClass {  
        private void yell() {  
            System.out.println(this.toString());  
            // OutterClass.this.yell();//靜態內部類實例沒有外部類實例的引用  
        }  
    }  
  
    /*  
     * this is inner class  
     */  
    private class InnerClass {  
        private void yell() {  
            System.out.println(this.toString());  
            OutterClass.this.yell();//內部類實例顯式使用外部類實例的方式  
        }  
    }  
  
    private void yell() {  
        System.out.println( this.toString());  
    }  
  
    private void run() {  
        /*  
         * this is local class  
         */  
        class LocalClass {  
            public void yell(){  
                System.out.println(this.toString());  
            }  
        }  
        /*  
         * this is anonymous class  
         */  
        new Object() {  
            public void yell(){  
                System.out.println(this.toString());  
            }  
        }.yell();  
        LocalClass lc=new LocalClass();  
        InnerClass ic = new InnerClass();  
        StaticNestedClass sc=new StaticNestedClass();  
        lc.yell();  
        ic.yell();  
        sc.yell();  
    }  
  
    public static void main(String[] args) {  
        OutterClass oc = new OutterClass();  
        oc.run();  
    }  
}  

  仔細分析如上代碼,可以得出一個結論,所有的內部類,Local內部類,匿名內部類都可以直接訪問外面的封裝類的實例變量和方法。而靜態嵌套類則不能。

  調試代碼可以發現,內部類,Local內部類,匿名內部類的實例都持有一個外部封裝類實例的隱式引用;

  而java對象序列化要求對象裡所有的對象成員都實現序列化接口。

  所以,如果只有內部類實現序列化,而外部封裝類沒有實現序列化接口,就會在對內部類進行序列化的時候報出異常。

相關焦點

  • Java內部類新解,你沒有見過的船新版本
    基礎Java支持類中嵌套類,稱之為nested class。嵌套的層數沒有限制,但實際中一般最多用兩層。根據內部類是否有static修飾,分為 static nested class和 non-static nested class。
  • 你的if else 嵌套讓我來優化
    下面將會談談我在工作中如何減少if else嵌套的。正文在談我的方法之前,不妨先用個例子來說明if else嵌套過多的弊端。想像下一個簡單分享的業務需求:支持分享連結、圖片、文本和圖文,分享結果回調給用戶(為了不跑題,這裡簡略了業務,實際複雜得多)。
  • 跟我學java編程—深入理解while嵌套
    就像if語句可以嵌套一樣,一個循環也可以嵌套在另一個循環中,一個循環中含有另一個循環就稱為嵌套循環。在D盤Java目錄下,新建「AngleSample.java」文件。用記事本打開「AngleSample.java」文件,輸入以下代碼:代碼結構分析程序功能主要是演示while嵌套循環語句的使用。
  • 跟我學java編程—Java嵌套if
    除了使用簡單if和多重if之外,還可以將整個if塊插入另一個if塊中,這種結構稱為嵌套if。嵌套if主要用於只有當前提條件滿足時,才判斷後續條件是否滿足。如果我們真的需要寫出具有第二種意義的嵌套條件語句,那麼,就應該採用下面的寫法:示例1:編寫一個程序,要求用戶輸入兩個數值,通過嵌套if結構判斷兩個數值的大小,並輸出相應信息。在D盤Java目錄下,新建「EmbedSample.java」文件。
  • java class loader
    當你需要用java語言進行開發時,了解java類加載如何工作是很有幫助的。對類加載過程有基本的理解可以幫助Java程式設計師處理多種ClassLoader相關的異常。類加載器委派模型 java類的加載由類加載器(CL)來執行,CL負責將類載入到JVM中。簡單的應用程式可以利用java平臺自帶的類加載工具來進行載入,而更複雜的應用傾向於定義自己的CL。java中所有的CL被組織成樹結構。
  • 關於Java中Runtime.class.getClass()的細節分析
    和getClass()由此可知,new Object().getClass()得到的應該是名稱為『java.lang.Object』的Class,記作class java.lang.Object(以下類似) ,而Runtime.class拿到的Class作為Object的子類,調用getClass()得到的卻是class java.lang.Class。
  • 徹底消滅if-else嵌套
    但if-else一般不建議嵌套超過三層,如果一段代碼存在過多的if-else嵌套,代碼的可讀性就會急速下降,後期維護難度也大大提高。2.2 親歷的重構前陣子重構了服務費收費規則,重構前的if-else嵌套如下。
  • 如何用Bull轉換任意類型的Java Bean
    例如,給定源和目標類:public class FromBean { public class ToBean { private final String name
  • 夯實Java基礎系列9:深入理解Class類和Object類
    :Test.javapackage synchronization.demo;import java.util.Date;public class Test {public static void main(String[] args) {BottomService
  • 一文讀懂JAVA類文件結構
    數據類型: 無符號數和表通過以上定義,我們可知,其實我們編寫的java文件,經過javac編譯之後的class文件會以一種二進位流的方式存在,這樣就方便java虛擬機來讀取我們編寫的java文件。    也就是說class文件只是一種中介,但是這種中介的格式或者順序都是被嚴格限定的,那麼,我們的java文件變成class文件之後,會變成一種什麼樣的數據結構呢?下面我們通過一張圖來看看。通過這張圖,我們可以從宏觀的意義上了解了一個class文件具體是怎樣組成的,那麼,下面我們分別看看,每一個組成的部分又代表了什麼?
  • JVM之用Java解析class文件
    java之所以能夠實現跨平臺,便在於其編譯階段不是將代碼直接編譯為平臺相關的機器語言,而是先編譯成二進位形式的java字節碼,放在Class文件之中,虛擬機再加載Class文件,解析出程序運行所需的內容。每個類都會被編譯成一個單獨的class文件,內部類也會作為一個獨立的類,生成自己的class。
  • 跟我學java編程—深入理解for語句的嵌套循環
    用記事本打開「ForSample1.java」文件,輸入以下代碼:代碼結構分析程序功能主要是演示for嵌套循環的使用方法。編譯「ForSample1.java」文件,在命令行窗口輸入「javac ForSample1.java」並執行命令,編譯通過後,在命令行窗口輸入「java ForSample1」運行Java程序,命令行窗口顯示如下信息:
  • Java中內部類到底有什麼用?
    內部類嵌套內部類局部內部類接口內部類匿名內部類本篇文章只對實際項目開發中用的較多的,普通內部類與匿名內部類做一定介紹。其他三種若有興趣請自行通過谷歌或書籍進行了解。在這裡我再自作主張的為大家概括一下普通內部類持有一個指向外部類的引用。要創建普通內部類,一定要先創建外部類。普通內部類就像人體的心臟一樣,能夠隨意訪問外部類的任意成員變量。
  • Java提高篇——詳解內部類
    這是因為當我們在創建某個外圍類的內部類對象時,此時內部類對象必定會捕獲一個指向那個外圍類對象的引用,只要我們在訪問外圍類的成員時,就會用這個引用來選擇外圍類的成員。其實在這個應用程式中我們還看到了如何來引用內部類:引用內部類我們需要指明這個對象的類型:OuterClasName.InnerClassName。
  • Visual Studio Code 10 月 Java 擴展更新
    具體如下:Code NavigationGo to super implementation此更新中,可以在懸停時單擊「Go to Super Implementation」連結來跳轉到類實現和重寫方法。
  • 我是一個Java class
    "唉,果然沒有被裝載過, 你是個class 文件,當然要報文件開頭的那幾個數了, 就是Java 他爸James Gosling 在jdk 1.0時確定的那個數啊""奧, 我看看, 0xCAFEBABE""不錯, 是個java 類, 把你後邊的兩個數也報一下", 小個子繼續問"50 , 0" "看來版本不高啊, 是jdk 1.6編譯出來的啊
  • Java之 Scanner類
    Scanner 類java.util.Scanner 是 Java5 的新特徵,我們可以通過 Scanner 類來獲取用戶的輸入,並通過 Scanner 類的 next() 與 nextLine() 方法獲取輸入的字符串,在讀取前我們一般需要 使用 hasNext 與 hasNextLine 判斷是否還有輸入的數據。
  • 程序汪幫公司面試3年1萬8的Java程式設計師,基礎的問題沒回答好啊
    =expectedModCount的情況,就會報並發修改異常java.util.ConcurrentModificationException總結記住5個單詞這個就是對Java集合工具熟悉的考察,當然你能說清楚下面這些更佳java集合的工具類Collections中提供了兩種排序的方法,分別是:
  • Java基礎知識中的類
    源程序代碼如下://程序文件名為SetApple.javapublic class SetApple{        public static void main(String[] args)        {                apple a=new apple();//創建apple類
  • java類加載的過程概述
    當Java程序首次通過下面6種方式使用某個類或接口時,系統會初始化該類或接口。1. 創建類的實例。2. 訪問類的靜態變量,或者為靜態變量賦值。5. 直接使用java.exe命令來運行某個主類。6. 使用反射方式來強制創建某個類或接口對應的java.lang.Class對象。