Test.java
package a;
import b.B;
public class Test {
public static void main(String[] v) {
new A().test();
new B().test();
}
}
A.java:
package a;
public class A {
protected void test() { }
}
B.java:
package b;
public class B extends a.A {
protected void test() { }
}
为什么new B().test()
会出错?这不会破坏可见性规则吗?
B.test()
在Test
中是不可见的,因为它们位于不同的包中,但却拒绝调用test()
的超类中的B
,这是可见的。< / p>
欢迎链接到JLS的相应部分。
答案 0 :(得分:12)
在这里,您可以使用protected
关键字进行JLS:
JLS protected description和JLS protected example。
基本上protected
修饰符意味着您可以从同一包中的类访问给定类和 2)的子类中的field / method / ... 1)。
因为2)new A().test()
有效。但是new B().test()
不起作用,因为类B
位于不同的包中。
答案 1 :(得分:7)
这不是继承在Java中的工作方式。
如果方法被覆盖,并且重写的方法不可见,则尝试调用它是编译时错误。
您似乎期望Java会自动回退到超类中的方法,但这种情况不会发生。
我稍后会尝试挖掘JLS为什么不这样做......
答案 2 :(得分:7)
问题是,在编译时,您告诉Java,当您没有此类访问权限时,您希望访问类的受保护成员。
如果你这样做了;
A a = new B();
a.test();
然后它将起作用并且重写的方法将运行,因为在编译时Java检查您是否有权访问A.在运行时,提供的对象具有适当的方法,因此执行B test()方法。动态绑定或后期绑定是关键。
答案 3 :(得分:0)
是的,可以覆盖受保护的方法。
class A{
protected void f(){
SOP("A");
}}
class B extends A{
protected void f(){
SOP("B");
}
public static void main(String...args)
{
B b=new B();
b.f();
}
}
输出:B