Java“技巧”,重新定义了儿童类成员 [英] Java "trick", redefining daughter class member

查看:88
本文介绍了Java“技巧”,重新定义了儿童类成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在接受Java考试的培训,而且在去年的课程中我遇到了一些我不理解的东西。这是代码

I'm training for a Java exam, and I've come across something I don't understand in last year subject. Here is the code

class Mother {
    int var = 2;

    int getVar() {
        return var;
    }
}

class Daughter extends Mother {
    int var = 1;

    int getVar() { 
        return var;
    }

    public static void main(String[] args) {
        Mother m = new Mother();
        System.out.println(m.var);
        System.out.println(m.getVar());
        m = new Daughter();
        System.out.println(m.var);
        System.out.println(m.getVar());
    }
}

问题是这个程序的输出是什么?。我会选择2 2 1 1,但在编译和运行这段代码时,我得到2 2 2 1.

The question is "what is the output of this program?". I would have go with 2 2 1 1, but when compiling and running this piece of code, I get 2 2 2 1.

任何人都可以解释我为什么?

Anyone can explain me why ?

感谢阅读!

推荐答案

方法调用 m.getVar()是一个虚方法调用。第二次调用它时,会动态调度到派生的 Daughter.getVar(),它可以达到预期效果(访问 Daugther.var 并返回)。

The method call m.getVar() is a virtual method call. The second time you call it, it's dynamically dispatched to the derived Daughter.getVar(), which does what you expect (accesses Daugther.var and returns that).

成员字段没有这种虚拟调度机制。所以 m.var 总是引用 Mother.var ,即基类的变量版本。

There is no such virtual dispatch mechanism for member fields. So m.var always refers to Mother.var, i.e. the base class's version of that variable.

Daughter 类可以看作有两个不同的 var 成员:来自母亲的那个和它自己的。它自己的成员隐藏 Mother 中的那个,但是可以使用<$从 Daughter 类中访问它c $ c> super.var 。

The Daughter class can be seen as having two different var member: the one from Mother and its own. Its own member "hides" the one in Mother, but can be accessed from within the Daughter class by using super.var.

此官方规格见 8.3字段声明 JLS / second_edition / HTML / jTOC.doc.html> JLS 。
引用:

The official spec for this is in section 8.3 Field Declarations of the JLS. Quote:


如果类声明了具有特定名称的字段,则该字段的声明称为隐藏任何和所有可访问的超类中具有相同名称的字段的声明,以及该类的超接口。字段声明还对封闭类或接口中的任何可访问字段以及任何封闭块中具有相同名称的任何局部变量,形式方法参数和异常处理程序参数进行阴影(§6.3.1)声明。

If the class declares a field with a certain name, then the declaration of that field is said to hide any and all accessible declarations of fields with the same name in superclasses, and superinterfaces of the class. The field declaration also shadows (§6.3.1) declarations of any accessible fields in enclosing classes or interfaces, and any local variables, formal method parameters, and exception handler parameters with the same name in any enclosing blocks.

请注意,它可以变得非常有趣(强调添加):

Note that it can get pretty interesting (emphasis added):


如果字段声明隐藏了另一个字段的声明,则两个字段不必具有相同类型

And:


可能有几条路径可以从接口继承相同的字段声明 。在这种情况下,该字段被认为仅被继承一次,并且可以通过其简单名称来引用而没有歧义。

There might be several paths by which the same field declaration might be inherited from an interface. In such a situation, the field is considered to be inherited only once, and it may be referred to by its simple name without ambiguity.

因此该段值得阅读: - )

So that paragraph is well worth reading :-)

这篇关于Java“技巧”,重新定义了儿童类成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆