簡體   English   中英

為什么內部類不能使用靜態初始化器?

[英]Why can't an inner class use static initializer?

Quoth JLS#8.1.3

內部類可能不會聲明靜態初始化器 (第8.7節 )......

這表現如下:

class A {
    class B {
        static { // Compile-time Error: Cannot define static initializer in inner type A.B
            System.out.println("Class is initializing...");
        }
    }
}

既然Java的內部(非靜態)類是由類加載器加載的 ,就像其他類一樣,為什么我們不能為它們安裝靜態初始化器?

這種限制背后的原因是什么?

我認為這是因為Inner類本身不是靜態的。 從Java的角度來看 它是一個實例變量,我想是的 (1)類加載器不是設計用於爬入內部非靜態類來查找和初始化potentiel靜態對象。

但它不是不可能的問題,請看下面的例子:

public class Outer {
    public static class Inner {
        Outer owner;
        static String constant;

        {
            constant = "foo";
        }

        private Inner(Outer owner) {
            if (owner == null) {
                throw new NullPointerException();
            }
            this.owner = owner;
        }
    }

    public Inner newInner() {
        return new Inner(this);
    }
}

甚至沒有警告,因為Inner聲明為靜態。

但乍一看,它有一個指向封閉Outer實例的指針,只能通過Outer創建,因為它只有一個私有構造函數,並且它的所有者不能為null。 從程序員的角度來看,它具有非靜態內部類的所有約束,並且可以像一個一樣使用(除了像Outer.this這樣的特殊習語),但從編譯器的角度來看它是靜態的,靜態字段將是靜態的在第一次Outer初始化時正確初始化。

(1):Pacerier在下面解釋了為什么這是不正確的。

無有效使用

只是我提出的意見,贊成爭論/辯論

請閱讀以下主題。

這解釋了為什么Java禁止內部類中的靜態字段

IMO同樣的原因也適用於static initializer 畢竟,創建問題的關鍵是static

除了在上面的線程中解釋的原因,我可以給出另一個蹩腳的理由
static initializer的名稱為我們提供了何時以及為何使用此塊的提示。 一個不是簡單地使用靜態初始化塊來打印hello world [ 在這里插入meme ]。
使用此塊的主要原因顯然是初始化靜態變量。

現在作為內部類/非靜態嵌套類不允許靜態變量,允許靜態初始化器有什么意義?

根據定義存在矛盾:

來自JLS§8.1.3

當且僅當包含語句或表達式的最內層方法,構造函數,實例初始化程序,靜態初始化程序,字段初始值設定項或顯式構造函數調用語句是靜態方法,靜態初始化程序,變量初始化程序時,語句或表達式才出現在靜態上下文中靜態變量或顯式構造函數調用語句(第8.8.7節)。

...

當內部類(其聲明不在靜態上下文中出現)引用作為詞法封閉類的成員的實例變量時,將使用相應的詞法封閉實例的變量。

暫無
暫無

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

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