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
{
}
}
为什么不能用相同的签名隐藏静态方法,而允许静态字段这样做呢?都是实例级的,为什么只允许静态字段?
最佳答案
类Test
中的
m1()
是一个static
方法,而中的
是非静态的。现在想象一下,如果允许这样做,那么当您执行以下语句时,运行时将选择哪个实现: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
它将指向子类的状态而不是父类的状态。这就是子类可以有同名变量的原因。
注意如果 Test
中的 i
是非静态的,即使在那种情况下 Test1 也可以有名称为 i< 的变量
。在这种情况下,Test1
中的 i
将隐藏 Test
中的 i
。
编辑
来自 Shahaan Syed 的 comment :
new Test1().i;
why is this allowed is my concerned
换句话说 Shahaan Syed 的困惑:为什么
- 在变量的情况下,子类可以有一个非静态变量,同时 父类有一个同名的静态变量,
- 另一方面,子类不能有非静态方法 父类有同名静态方法?
作为凯文·埃舍 commented ,我还认为 Java 通过允许从子类的实例访问父类的 static
方法搞砸了某个地方。尽管这不是一个好的做法,并且编译器也会生成警告。
这是 ( JLS §8.3 ) 的引述:
In this respect, hiding of fields differs from hiding of methods (§8.4.8.3), for there is no distinction drawn between static and non-static fields in field hiding whereas a distinction is drawn between static and non-static methods in method hiding.
但我在 JLS 中找不到这背后的任何原因。
我认为应该是编译时错误而不是生成警告。即从子类实例访问父类的 static
字段和 static
方法,应该是编译器错误。在这方面,事情本来是一致的,也很容易理解。但这只是我的想法。
同一行的另一个有趣问题:Why isn't calling a static method by way of an instance an error for the Java compiler?
关于java - 方法隐藏和字段隐藏的继承辅助,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36642288/