17
public class Main {

    public static void main(String[] args) {
        System.out.println(B.x);
    }

}
class A {
    public static String x = "x";
}
class B extends A {
    static {
        System.out.print("Inside B.");
    }
}

質問: 出力が次のようになる理由: x. だがしかし:Inside B.x

4

5 に答える 5

10

への参照はB.x、次のバイトコードを発行します。

getstatic       #3   <Field int B.x>

Java 仮想マシンの仕様によると

Java 仮想マシン命令 anewarray、checkcast、getfield、 getstatic、instanceof、invokedynamic、invokeinterface、invokespecial、invokestatic、invokevirtual、ldc、ldc_w、multianewarray、new、putfield、および putstatic は、ランタイム定数プールへのシンボリック参照を作成します。これらの命令を実行するには 、そのシンボリック参照を解決する必要があります。

したがって、JVM は へのシンボリック参照をB.x解決する必要があります。フィールド解像度は次のように指定されます

D からクラスまたはインターフェイス C のフィールドへの未解決のシンボリック参照を解決するには、フィールド参照によって指定された C へのシンボリック参照を最初に解決する必要があります (§5.4.3.1)。

...

フィールド参照を解決するとき、フィールド解決は最初に C とそのスーパークラスで参照されたフィールドを検索しようとします:

C がフィールド参照で指定された名前と記述子でフィールドを宣言すると、フィールド ルックアップは成功します。宣言されたフィールドは、フィールド ルックアップの結果です。

それ以外の場合、フィールド ルックアップは、指定されたクラスまたはインターフェイス C の直接のスーパーインターフェイスに再帰的に適用されます。

それ以外の場合、C がスーパークラス S を持っている場合、フィールド ルックアップが再帰的に S に適用されます。

それ以外の場合、フィールド ルックアップは失敗します。

つまり、JVM は に解決B.xされA.xます。Aこれが、クラスのみをロードする必要がある理由です。

于 2012-11-20T14:27:15.903 に答える
7

B.x実際にはそうであるため、ロードする必要があるA.xのはクラスだけです。A

于 2012-11-20T14:22:40.043 に答える
4

Java 言語仕様、Java SE 7 Editionの §12.4「クラスとインターフェースの初期化」では、次のように指定されています。

クラスの初期化staticは、その初期化子と、クラスで宣言された静的フィールド (クラス変数) の初期化子の実行で構成されます。

[…]

フィールドへの参照static( §8.3.1.1 ) は、サブクラス、サブインターフェース、またはインターフェースを実装するクラスの名前を通じて参照される可能性がある場合でも、実際にそれを宣言するクラスまたはインターフェースのみを初期化します。

したがって、上記の回答のいくつかの主張に反して、クラスをロードBする必要がありますが、で宣言されていることを判断するために、より具体的な何かを行うまで、クラスは初期化されません(つまり、そのイニシャライザは実際には実行されません)。 .B.xABstaticB

于 2012-11-20T16:45:51.603 に答える
2

Class Bあなたが呼び出すときにあなたがアクセスしているものAを持っている拡張public static variable xB.x

出力として期待する場合Inside B.は、そのクラスのオブジェクトを作成する必要があります。すべての静的コードブロックが実行されます。または、その静的コードブロックをクラスに移動しますA:-)

JVMがクラスをロードすると、すべての静的ブロックがグループ化され、宣言された順序で実行されます。

編集ソース):簡単な答えは、統計はJavaでは継承されないということです。むしろ、クラスで宣言された静的メンバーは、派生クラスの宣言によって「隠された」場合を除いて、派生クラスの名前空間に直接表示されます(「アクセス」制限の対象となります)。

では、Staticがクラスに属している場合、なぜそれが派生クラスに細流化するのでしょうか。それが定義されたクラスにとどまるだけではいけませんか?

于 2012-11-20T14:21:51.007 に答える
2

Bの静的メンバーにB直接アクセスするまで、実際にロードする必要はありません。このコードは次の点に注意してください。

public class TestMain {
    public static void main(String[] args) {
        System.out.println(B.x);
        System.out.println(B.y);
    }

    static class A {
        public static String x = "x";
    }

    static class B extends A {
        public static String y = "y";
        static {
            System.out.print("Inside B.");
        }
    }
}

出力します:

x
Inside B.y

B何かにBアクセスするまでロードする必要がないからです。

これは、この件に関する良いリンクです。記事から、「忘れないでください。このコードは、JVM がクラスをロードするときに実行されます。JVM は、これらすべてのブロックを 1 つの静的ブロックに結合してから実行します。ここで、私が言及したいいくつかのポイントを示します。」

于 2012-11-20T14:33:36.683 に答える