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

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

来自Java语言规范 :

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

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

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

根据我对该问题的新理解,完全重写了这个答案。 以下是我的第一个答案,留给后人。

来自Java语言规范 :

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

这表明无论静态如何,编译器都需要隐藏父变量。

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

根据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 

看下面的代码。 如果你想从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 */