8

Javaの親クラスと子クラスが同じインスタンス変数を持つことができるかで説明されているように、これはおそらく悪いことです。。(親変数名が変更された場合はどうなりますか?その後、シャドウされなくなります。)ただし、静的/非静的の変数が互いにシャドウされるかどうかはまだわかりません。一方では、それらは同じ変数名であるため、シャドウされると思いますが、他方では、コンパイラーが静的性に基づいて2つを区別する可能性があるようです。

4

6 に答える 6

7

Java 言語仕様に従って:

クラスが特定の名前のフィールドを宣言する場合、そのフィールドの宣言は、スーパークラスおよびクラスのスーパーインターフェースで同じ名前を持つフィールドのすべてのアクセス可能な宣言を隠すと言われます。

非表示フィールドには、修飾名を使用してアクセスできます (静的な場合)。

JVM仕様

「フィールド宣言」セクションを参照してください。

于 2011-12-29T23:22:59.757 に答える
4

彼らは:

class Parent {
    static String x="static in parent";
    String y="instance in parent";
}
class Child extends Parent {
    static String y="static in child";
    String x="instance in child";
    void foo() {
        System.out.println("x "+x);
        System.out.println("super.x " + super.x); 
        System.out.println("y "+y);
        System.out.println("super.y " + super.y); 
    }
}
public class Main {
    public static void main(String[] args) {
        Parent parent=new Parent();
        Child child=new Child();
        System.out.println("Parent.x "+Parent.x);
        System.out.println("parent.x "+Parent.x); 
        System.out.println("parent.y "+parent.y);
        System.out.println("child.x "+child.x);
        System.out.println("Child.y "+Child.y);
        System.out.println("child.y "+child.y);
        System.out.println("(Parent)child).x "+((Parent)child).x);
        System.out.println("(Parent)child).y "+((Parent)child).y);
        child.foo();
    }
}



Parent.x static in parent
parent.x static in parent
parent.y instance in parent
child.x instance in child
Child.y static in child
child.y static in child
(Parent)child).x static in parent
(Parent)child).y instance in parent
x instance in child
super.x static in parent
y static in child
super.y instance in parent
于 2011-12-29T23:24:32.863 に答える
4

Java言語仕様から:

式名が単一のIdentifierで構成される場合、 Identifierが発生した時点で、スコープ内のローカル変数、パラメーター、またはフィールドのいずれかを示す可視宣言が 1 つだけ存在する必要があります 。そうしないと、コンパイル時エラーが発生します。

宣言が final フィールドを宣言する場合、名前の意味はそのフィールドの値です。それ以外の場合、式名の意味は、宣言によって宣言された変数です。

スーパークラスのメソッドがそのクラスの特定のフィールド (静的またはそれ以外) を参照する場合、そのクラスのフィールドの宣言のみがその時点でスコープ内になります。サブクラスのフィールド (静的またはその他) はスコープ外になります。したがって、サブクラスがそれを継承してそのフィールドを隠している場合でも、メソッドは常にスーパークラス フィールドを使用します。

この回答は、質問に対する私の新しい理解に基づいて完全に書き直されています。以下は私の最初の答えであり、後世のために保管されています。

Java言語仕様から:

nという名前のフィールド、ローカル変数、メソッド パラメータ、コンストラクタ パラメータ、または例外ハンドラ パラメータの宣言dは、その時点でスコープ内にあるnという名前の他のフィールド、ローカル変数、メソッド パラメータ、コンストラクタ パラメータ、または例外ハンドラ パラメータの宣言をシャドウします。ここで、dはdのスコープ全体で発生します。

これは、静的性に関係なく、コンパイラが親変数をシャドウする必要があることを示唆しています。

これは継承されたメソッドには関係ないことに注意してください。継承されたメソッドは、サブクラスがそれらをシャドウするかどうかに関係なく、常に元の変数を使用します。これはあなたが尋ねたかったことではないと思います。

于 2011-12-29T23:26:32.543 に答える
0

以下のコードを見てください。fieldからアクセスする場合ChildClassは、独自のメンバー変数を使用します。fieldから静的にアクセスする場合SuperClassは、を使用して明示的に呼び出す必要がありますSuperClass.field。コンパイラにあいまいさがないため、`STATIC_FIELD``に直接アクセスできます。

  public class SuperClass{
    static String field = "staticField1";
    static String STATIC_FIELD = "staticField2";

    //not possible to have a member field in this class -> compile error
    //String field = "memberField"; is not possible
    public SuperClass() {
      System.out.println( "field = " + field );

    }
  }
  public class ChildClass extends SuperClass{
    String field = "memberField";

    public ChildClass() {
      System.out.println( "field = " + field );//access to member field
      //need to explicitly call SuperClass.field to access the static variable
      System.out.println( "SuperClass.field = " + SuperClass.field );
      //no need to do this when there is no amibiguity
      System.out.println( "STATIC_FIELD = " + STATIC_FIELD );
    }
  }

ここの15.11.1と15.11.2およびここの8.3も参照してください。

于 2011-12-29T23:16:27.207 に答える
0

Eclipse のコンパイラでは、以下に示すように、親クラスのメソッドは引き続き、子クラスのシャドウ変数ではなく、スーパークラスのメンバー変数を使用します。これは、thinksteep の回答をわずかに変更したバージョンです。

class Parent {
    static String x ="static in parent";
    String y="instance in parent";

    void bar() {
        System.out.println("x "+ x);
        System.out.println("y "+ y);
    }
}

class Child extends Parent {
    static String y ="static in child";
    String x="instance in child";

    void foo() {
        System.out.println("x "+x);
        System.out.println("super.x " + super.x); 
        System.out.println("y "+y);
        System.out.println("super.y " + super.y); 
    }
}

public class Main {
    public static void main(String[] args) {
        Parent parent=new Parent();
        Child child=new Child();
        System.out.println("Parent.x "+Parent.x);
        System.out.println("parent.x "+Parent.x); 
        System.out.println("parent.y "+parent.y);
        System.out.println("child.x "+child.x);
        System.out.println("Child.y "+Child.y);
        System.out.println("child.y "+child.y);
        System.out.println("(Parent)child).x "+((Parent)child).x);
        System.out.println("(Parent)child).y "+((Parent)child).y);
        System.out.println("Member variable visibility in parent:");
        parent.bar();
        System.out.println("Member variable visibility in child:");
        child.foo();
        System.out.println("Member variable visibility in inherited methods:");         
        child.bar();

        System.exit(0);
}

/* Output:
Parent.x static in parent
parent.x static in parent
parent.y instance in parent
child.x instance in child
Child.y static in child
child.y static in child
(Parent)child).x static in parent
(Parent)child).y instance in parent
Member variable visibility in parent:
x static in parent
y instance in parent
Member variable visibility in child:
x instance in child
super.x static in parent
y static in child
super.y instance in parent
Member variable visibility in parent methods:
x static in parent
y instance in parent
*/
于 2011-12-30T03:04:51.767 に答える
0
public class Test {

    public static int MYNUMBER = 5;

    public Test() {
    }
}

public class TestChild extends Test {

    public int MYNUMBER = 8;

    public TestChild() {
    }
}

public class Main {

    public static void main(String[] args) {
        TestChild testChild = new TestChild();

        // This would print out 8
        System.out.println("in main test child: " + testChild.MYNUMBER);

        // This won't even compile if the MYNUMBER variable is overshadowed
        // If the MYNUMBER variable is not overshadowed it
        // would compile and
        // print out 5
        // If we make MYNUMBER static also on TestChild,
        // it would compile and print out 8
        System.out.println("in main TestChild.MYNUMBER " + TestChild.MYNUMBER);

        // This would print out 5
        System.out.println(Test.MYNUMBER);
    }

}
于 2011-12-29T23:26:06.263 に答える