3

staticできることとできないことを確認するために、継承をいじっていました。以前に読んだことがありますが、静的メソッドは上書きできず、単に非表示にすることができます。そのため、静的メンバーに適用されるものを確認しようとしました。簡単なテスト コードを次に示します。

public class ParentClass {
    public static String x;
    { x = "In ParentClass"; }
}

public class ChildClass extends ParentClass {
    { x = "In ChildClass"; }
}

オブジェクトから呼び出された x を印刷すると、すべてが期待どおりに進みました。

ParentClass parentClassReference = new ParentClass();
System.out.println(parentClassReference.x); // prints: "In ParentClass"

parentClassReference = new ChildClass();
System.out.println(parentClassReference.x); // prints: "In ChildClass"

子クラス オブジェクトから x への些細な呼び出しでさえ:

ChildClass childClassReference = new ChildClass();
System.out.println(childClassReference.x); // prints: "In ChildClass"

今、私が静的メンバーを呼び出すと、それが行われることになっているように、それは奇妙になります:

System.out.println(ChildClass.x); // prints: "In ChildClass" (Ok, so far.)
System.out.println(ParentClass.x); // prints: "In ChildClass" (This is unexpected.)

この動作については説明がありません。オーバーライドと非表示 (Code Ranch)のコンテキストでは、オブジェクトを介した呼び出しは期待どおりに機能しない可能性が高いように思われましたが、クラス名を介した呼び出しは機能するはずです。

私は混乱しています。誰が助けることができますか?

4

1 に答える 1

4

あなたのコードは非常に奇妙です...しかし、結果はまさに私が期待したとおりです。

次の 3 つのことを理解する必要があります。

  • ここには変数が1 つ しかありません。xとして参照する場合でも、 として参照する場合でもChildClass.xParentClass.x同じ変数です。
  • reference を介してstatic メンバーを参照すると、コンパイラは参照の値をまったく確認せずに、それを静的参照に変換するだけです。SochildClassReference.xは と同等でChildClass.x、実際には としてコンパイルされParentClass.xます。優れた IDE は、この種のことを警告します。つまり、紛らわしいコードが生成されます。
  • の値を設定する作成したコードはx、コンストラクター呼び出しに基づいてのみ実行されます。基本的には以下と同等です:

    public class ParentClass {
        public static String x;
        public ParentClass() {
            x = "In ParentClass";
        }
    }
    
    public class ChildClass extends ParentClass {
        public ChildClass() {
            x = "In ChildClass";
        }
    }
    

基本的に、静的メンバーを通じていかなる種類のポリモーフィズムも達成しようとすべきではありません。それは機能せず、それを偽造しようとしてもうまくいきません。

于 2012-09-07T09:21:38.553 に答える