Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,如果一个子类用一个实例子变量来隐藏一个静态父变量,那么继承的方法将使用哪个变量?_Java_Inheritance_Shadowing - Fatal编程技术网

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

在Java中,如果一个子类用一个实例子变量来隐藏一个静态父变量,那么继承的方法将使用哪个变量?,java,inheritance,shadowing,Java,Inheritance,Shadowing,如中所述,这可能是一件坏事。(如果父变量名被更改了怎么办?那么它将不再被隐藏。)然而,我仍然很好奇静态/非静态不同的变量是否会相互隐藏。一方面,我希望它们是相同的变量名,因此会被隐藏,但另一方面,编译器似乎可以根据静态性区分这两个变量。查看下面的代码。如果要从子类访问字段,它将使用自己的成员变量。如果要从超类访问静态字段,必须使用超类.field显式调用它。“STATIC_字段”可以直接访问,因为编译器没有歧义 public class SuperClass{ static Stri

如中所述,这可能是一件坏事。(如果父变量名被更改了怎么办?那么它将不再被隐藏。)然而,我仍然很好奇静态/非静态不同的变量是否会相互隐藏。一方面,我希望它们是相同的变量名,因此会被隐藏,但另一方面,编译器似乎可以根据静态性区分这两个变量。

查看下面的代码。如果要从
子类
访问
字段
,它将使用自己的成员变量。如果要从
超类
访问静态
字段
,必须使用
超类.field
显式调用它。“STATIC_字段”可以直接访问,因为编译器没有歧义

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

根据Java语言规范,另请参见中的15.11.1和15.11.2以及中的8.3:

如果类声明一个具有特定名称的字段,则该字段的声明称为隐藏该类的超类和超接口中具有相同名称的任何和所有可访问的字段声明

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

您可以参考“字段声明”部分。

它们将:

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
发件人:

如果表达式名称由单个标识符组成,则 必须正好是一个表示本地 变量、参数或字段位于 标识符出现。否则,将发生编译时错误

如果声明声明了最后一个字段,则名称的含义为 该字段的值。否则,表达式名称的含义 是由声明声明的变量

如果超类中的方法引用该类的特定字段(静态或其他),则此时只有该类的字段声明才在范围内;子类的任何字段(静态或其他)都不在范围内。因此,该方法将始终使用超类字段,即使子类继承它并对该字段进行阴影处理

基于我对这个问题的新理解,这个答案被完全改写了。下面是我的第一个答案,留给子孙后代

发件人:

字段、局部变量、方法参数的声明d, 名为n的构造函数参数或异常处理程序参数 任何其他字段、局部变量、方法的声明 参数、构造函数参数或异常处理程序参数 命名为n,在整个 d的范围

这表明编译器需要对父变量进行阴影处理,而与静态无关


请注意,这些都与继承的方法无关,继承的方法总是使用原始变量,而不管子类是否对其进行阴影处理。我怀疑这不是您想要问的。

对于Eclipse的编译器,父类中的方法仍将使用超类中的成员变量,而不是子类中的阴影变量,如下所示。这只是ThinkStiple答案的一个稍加修改的版本

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

我觉得这是很重要的事情,可以帮助其他人,所以这个问题是有用的,但是:你试过了吗?尝试它是一件事,但这可能是编译器依赖的。我想知道在语言规范中是否有一个明确的规则。也发布输出,这样人们可以了解它的功能,无论是作为在线注释还是粘贴在belowI中的输出。我理解阴影的概念,但我的问题的重要部分是“继承的方法将使用哪个变量?”。非常好。这个答案和@ThinkStiple的答案相结合会更好,再加上对语言规范的引用,其中明确指出这是正确的行为,这将是理想的选择。(ThinkStiple的答案有点像这样,但没有特别提到继承方法。)然而,我会接受这个答案,直到其他答案有任何重大改进。嗯,我在这里看到的问题是,我们调用的是子方法,而不是父方法,来测试它们是什么。我会这样做的,请稍候……父方法将只访问父方法中的内容,无论它是父方法还是子方法。这实际上是对我试图问的问题的回答:“所有这些都与继承的方法无关,继承的方法总是使用原始变量,而不管子类是否隐藏它们”.语言规范有这样的规定吗?如果是,在哪里?我正在努力找到它。谢谢,答案现在已经很完整了。我理解隐藏的概念,但我的问题的重要部分是“继承的方法将使用哪个变量?”。我理解隐藏的概念,但我的问题的重要部分是“继承的方法将使用哪个变量?”。继承的方法将使用父级的静态变量。因此,如果我们向测试类添加方法:public int doSomething(){return MYNUMBER;}doSomething将始终返回5。我不会删除任何信息,但规范中是否有任何其他内容表明继承的方法也使用子字段?似乎您从Taymon获得了答案。这个答案+1,因为它提到您仍然可以通过完全限定名访问字段。
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
*/