方法隐藏和字段隐藏的继承帮助

时间:2016-04-15 08:42:14

标签: java inheritance

public class Test
{
    static int i = 1;

    static void m1()
    {
    }
}

class Test1 extends Test
{
    int i = 1;    //allowed 

    void m1()     // not allowed; Both are instance level, so why this difference? Both can be accessed with super keyword
    {
    }
}

为什么不能使用相同的签名隐藏静态方法,但允许静态字段执行此操作?两者都是实例级别,那么为什么只允许静态字段?

1 个答案:

答案 0 :(得分:8)

m1()中的

Teststatic方法,而m1()中的Test1是非静态方法。现在想象一下,如果允许这样做,那么当您执行以下语句时,运行时将选择哪个实现:

new Test1().m1();

由于子类的实例(在您的情况下为Test1)可以访问,也可以从父类(来自Test)访问静态方法。这就是不允许的原因。

下一个问题为什么Test1 中允许具有相同名称的变量:无法从子类实例访问父类'静态变量。换句话说,父类的静态状态是从子级隐藏的。那是

Test1.i;   // compilation error, can't access parent's static variable

将导致编译错误。如果你试试

new Test1().i; // will access Test1's i variable

它将指向子类'状态而不是父类。这就是为什么子类可以具有相同名称的变量。

注意:如果i中的Test是非静态的,即使在这种情况下,Test1也可以包含名为i的变量。在这种情况下,i中的Test1会在i中隐藏Test

修改

来自Shahaan Syed的comment

  

new Test1().i;为什么这是我所关心的

用另一个词来表达Shahaan Syed的困惑:为什么

  • 在变量的情况下,子类可以有一个非静态变量 parent类有一个名称相同的静态变量
  • 另一方面,
  • ,子类不能有非静态方法 parent类有一个同名的静态方法吗?

作为Kevin Esche commented,我还认为Java通过允许从子类实例访问父类的static方法而搞砸了。虽然这不是一个好习惯,编译器也会生成警告。

以下是(JLS §8.3)的引用:

  

在这方面,隐藏字段不同于隐藏方法   (§8.4.8.3),因为静态和静态之间没有区别   字段隐藏中的非静态字段,而绘制了区别   方法隐藏中的静态和非静态方法之间。

但我在JLS中找不到任何理由。

我认为不应该生成警告而应该有编译时错误。那就是从子类实例访问父类的static字段和static方法,应该是编译器错误。在这方面,事情将是一致的,易于理解。但这又是我的想法。

同一行上另一个有趣的问题:Why isn't calling a static method by way of an instance an error for the Java compiler?