В Java, если дочерний класс скрывает статическую родительскую переменную с дочерней переменной экземпляра, какую переменную будут использовать унаследованные методы? - PullRequest
7 голосов
/ 30 декабря 2011

Возможно, это плохая вещь, как обсуждалось в Может ли родительский и дочерний класс в Java иметь одну и ту же переменную экземпляра? . (Что если имя родительской переменной будет изменено? Тогда оно больше не будет затенено.) Однако мне все еще интересно, будут ли переменные, которые по-разному статичны / нестатичны, будут затенять друг друга. С одной стороны, я ожидал бы, что это одно и то же имя переменной, поэтому было бы затенено, но с другой стороны кажется, что компилятор может различать два на основе статичности.

Ответы [ 6 ]

6 голосов
/ 30 декабря 2011

Согласно спецификации языка Java:

Если класс объявляет поле с определенным именем, то говорят, что объявление этого поля скрывает все доступные объявления полей с одинаковыми именами в суперклассах и суперинтерфейсах класса.

Доступ к скрытому полю можно получить с помощью квалифицированного имени (если оно статическое)

Спецификация JVM

Вы можете обратиться к разделу «Объявления полей».

4 голосов
/ 30 декабря 2011

С Спецификация языка Java :

Если имя выражения состоит из одного Идентификатора , то должно быть ровно одно видимое объявление, обозначающее либолокальная переменная, параметр или поле в области видимости в точке, в которой встречается идентификатор .В противном случае возникает ошибка времени компиляции.

Если объявление объявляет конечное поле, значение имени является значением этого поля.В противном случае значением имени выражения является переменная, объявленная объявлением.

Если метод в суперклассе ссылается на определенное поле (статическое или иное) этого класса, то только объявление этого классаполе будет в поле зрения в этой точке;любые поля (статические или иные) подклассов не будут находиться в области видимости.Поэтому метод всегда будет использовать поле суперкласса, даже если подкласс наследует его и затеняет это поле.

Этот ответ полностью переписан на основе моего нового понимания вопроса.Ниже мой первый ответ, сохраненный для потомков.

С Спецификация языка Java :

Декларация d изполе, локальная переменная, параметр метода, параметр конструктора или параметр обработчика исключений с именем n затеняет объявления любых других полей, локальных переменных, параметров метода, параметров конструктора или параметров обработчика исключений с именем n которые находятся в области действия в точке, где d встречается во всей области действия d .

Это говорит о том, что компиляторы обязаны скрывать родительские переменные, независимо отстатичности.

Обратите внимание, что все это не относится к наследуемым методам, которые всегда используют исходные переменные независимо от того, скрывает ли их подкласс.Я подозреваю, что это не то, что вы хотели спросить.

4 голосов
/ 30 декабря 2011

они будут:

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
0 голосов
/ 30 декабря 2011

С компилятором Eclipse методы из родительского класса будут по-прежнему использовать переменные-члены из суперкласса, а не теневые переменные из дочернего класса, как показано ниже.Это только слегка измененная версия ответа thinkteep.

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
*/
0 голосов
/ 30 декабря 2011
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);
    }

}
0 голосов
/ 30 декабря 2011

Посмотрите на код ниже. Если вы хотите получить доступ к 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 в здесь

...