繁体   English   中英

在Java中,如果子类使用实例子变量隐藏静态父变量,哪个变量将继承方法使用?

[英]In Java, if a child class shadows a static parent variable with an instance child variable, which variable will inherited methods use?

这可能是一件坏事,如在Java中的父级和子级类中讨论的具有相同的实例变量? (如果父变量名称被更改怎么办?那么它将不再被遮蔽。)但是,我仍然好奇不同的静态/非静态变量是否会相互影响。 一方面,我希望它们是相同的变量名称,因此将被遮蔽,但另一方面,似乎编译器可能基于静态区分这两者。

根据Java语言规范:

如果类声明了具有特定名称的字段,那么该字段的声明将被称为隐藏超类中具有相同名称的字段的任何和所有可访问声明 ,以及该类的超接口。

可以使用限定名称访问隐藏字段(如果它是静态的)

JVM规范

您可以参考“现场声明”部分。

他们会:

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

来自Java语言规范

如果表达式名称由单个标识符组成 ,则必须只有一个可见声明,表示标识符出现点的范围内的局部变量,参数或字段。 否则,发生编译时错误。

如果声明声明了final字段,则name的含义是该字段的值。 否则,表达式名称的含义是声明声明的变量。

如果超类中的方法引用该类的特定字段(静态或其他),那么该字段的该字段声明将在该范围内; 子类的任何字段(静态或其他)都不在范围内。 因此,该方法将始终使用超类字段,即使子类继承它并且阴影该字段。

这个答案完全是基于我对这个问题的新理解而改写的。 以下是我的第一个答案,留给后人。

来自Java语言规范

名为n的字段,局部变量,方法参数,构造函数参数或异常处理程序参数的声明d隐藏了该点范围内的任何其他字段,局部变量,方法参数,构造函数参数或名为n的异常处理程序参数的声明其中d发生在整个d的范围。

这表明编译器需要对父变量进行阴影处理,而不管静态性如何。

请注意,这些都与继承的方法无关,无论子类是否影响它们,它们始终使用原始变量。 我怀疑这不是你要问的问题。

看下面的代码。 如果你想从ChildClass访问field ,它将使用自己的成员变量。 如果要从SuperClass访问静态field ,则必须使用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在这里

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);
    }

}

使用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
*/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM