簡體   English   中英

靜態嵌套類和普通類的區別

[英]Difference between static nested class and regular class

我知道這是一個有點重復的問題,但我想以非常具體的方式提出這個問題,以澄清一個非常重要的觀點。 主要問題是:除了訪問包含類中的私有靜態字段之外,當一個是靜態嵌套類而另一個是常規的頂級類時,其他相同的類之間是否有任何區別?

// ContainingClass.java
public class ContainingClass {
    private static String privateStaticField = "";

    static class ContainedStaticClass {
        public static void main(String[] args) {
            ContainingClass.privateStaticField = "new value";
        }
    }
}

// OutsideClass.java
public class OutsideClass {
    public static void main(String[] args) {
        ContainingClass.privateStaticField = "new value";  // DOES NOT COMPILE!!
    }
}

換句話說:是ContainedStaticClass可以訪問或執行的操作與OutsideClass可以訪問或執行的操作之間的唯一區別,即OutsideClass不能直接訪問ContainingClass.privateStaticField嗎? 或者還有其他不常被討論或遇到的細微差別嗎?

您的說法是正確的:靜態類和外部類之間的唯一區別是對類和封閉類的成員的訪問。 static關鍵字聲明該類不是內部類:它實際上是封閉類范圍內的外部類。

請參閱https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.5.1

ContainedStaticClass 具有包私有(即默認)可見性,而OutsideClass 具有公共可見性。

您可以選擇將 ContainedStaticClass 設為 protected 或 private,而這不是 OutsideClass 的選項。

一個微妙的不同之處在於一個嵌套類具有的能力陰影包封類型的成員:

class ContainingClass {
    public static String privateStaticField = "a";

    static class ContainedStaticClass {
        public static String privateStaticField = "b";
        public static void main(String[] args) {
            System.out.println(privateStaticField);  // prints b
        }
    }
}

但這也與類的范圍有關。

有幾個細微的差別。

可能最重要的一個是嵌套的靜態類可以設置為privateprotected 頂級類只能是 package-private 或public

我能想到的其他差異是技術細節,您可能不應該在這些細節重要的地方編寫代碼:

  • 嵌套的靜態類可以“隱藏”或“隱藏”同名的其他類。 當嵌套靜態類與外部類同名且都在作用域內時,嵌套靜態類會隱藏外部類。

  • 嵌套靜態類由其外部類的子類繼承,因此它在這些子類的范圍內,無需完全限定名稱或靜態導入即可引用。

  • 同一個包中的兩個外層類不能共享同名,但一個類可以繼承多個嵌套的同名靜態類(例如從兩個接口)。 這不會導致編譯錯誤,除非嵌套類的名稱使用不明確

  • 由於繼承的原因,嵌套的靜態類可以有多個不同的完全限定名稱,例如在class A { static class B extends A {} } ,類AB可以稱為ABBABBB等。 一個外部類只能有一個完全限定的名稱。

  • 外部類的規范名稱等於其二進制名稱,但嵌套靜態類的規范名稱不等於其二進制名稱。 嵌套靜態類的二進制名稱使用符號$將外部類的二進制名稱與嵌套靜態類的簡單名稱分隔開。

另一個微妙的區別發生在反射用例中。 使用Class.forName加載類所需的類名有點時髦。

Class.forName("com.acme.OuterClass.Innerclass");  // not found
Class.forName("com.acme.OuterClass$Innerclass");  // correct

另請參閱: 使用 Class.forName 實例化嵌套靜態類

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM