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
{
}
}
Run Code Online (Sandbox Code Playgroud)
为什么静态方法不能用相同的签名隐藏,但允许静态字段执行此操作?两者都是实例级别,那么为什么只允许静态字段?
m1()在类中Test是一个static方法,而m1()in Test1是非静态的.现在想象一下,如果允许这样做,那么当你执行下面的语句时,运行时会选择哪个实现:
new Test1().m1();
Run Code Online (Sandbox Code Playgroud)
由于子类的实例(Test1在您的情况下)可以访问也从父类(从Test)访问静态方法.这就是为什么不允许这样做的原因.
对于下一个问题,为什么允许具有相同名称的变量Test1:父类'静态变量无法从子类实例访问.换句话说,父类的静态状态是从子级隐藏的.那是
Test1.i; // compilation error, can't access parent's static variable
Run Code Online (Sandbox Code Playgroud)
将导致编译错误.如果你试试
new Test1().i; // will access Test1's i variable
Run Code Online (Sandbox Code Playgroud)
它将指向子类的状态而不是父类.这就是为什么子类可以具有相同名称的变量.
注意:如果iin Test是非静态的,即使在这种情况下,Test1也可以包含名称变量i.在这种情况下,i在Test1将阴影i中Test.
编辑
来自Shahaan Syed的评论:
new Test1().i;为什么允许这是我所关心的
将Shahaan Syed的混淆换成另一个词:为什么
正如Kevin Esche 评论的那样,我也认为Java通过允许static从子类实例访问父类的方法而搞砸了.虽然这不是一个好习惯,编译器也会生成警告.
这是(JLS§8.3)的引用:
在这方面,隐藏字段不同于隐藏方法(第8.4.8.3节),因为在字段隐藏中静态和非静态字段之间没有区别,而在方法隐藏中区分静态和非静态方法.
但我在JLS中找不到任何理由.
我认为不应该产生警告而应该有编译时错误.即从子类实例访问父类的static字段和static方法,应该是编译器错误.在这方面,事情将是一致的,易于理解.但这又是我的想法.
同一行上另一个有趣的问题:为什么不通过实例调用静态方法是Java编译器的错误?
| 归档时间: |
|
| 查看次数: |
99 次 |
| 最近记录: |