JWh*_*hiz 14 java inheritance packages protected
我想了解下面示例中发生的情况(通过子类从包外部访问受保护的成员).
我知道对于包外的类,子类只能通过继承来查看受保护的成员.
有两个包:package1和package2.
package1: ProtectedClass.java
package org.test.package1;
public class ProtectedClass {
protected void foo () {
System.out.println("foo");
}
}
Run Code Online (Sandbox Code Playgroud)package2: ExtendsprotectedClass.java
package org.test.package2;
import org.test.package1.ProtectedClass;
public class ExtendsprotectedClass extends ProtectedClass {
public void boo() {
foo(); // This works,
// since protected method is visible through inheritance
}
public static void main(String[] args) {
ExtendsprotectedClass epc = new ExtendsprotectedClass();
epc.foo(); // Why is this working?
// Since it is accessed through a reference,
// foo() should not be visible, right?
}
}
Run Code Online (Sandbox Code Playgroud)package2: UsesExtendedClass.java
package org.test.package2;
public class UsesExtendedClass {
public static void main(String[] args) {
ExtendsprotectedClass epc = new ExtendsprotectedClass();
epc.foo(); // CompilationError:
// The method foo() from the type ProtectedClass
// is not visible
}
}
Run Code Online (Sandbox Code Playgroud)可以理解,该boo()方法ExtendsprotectedClass可以访问foo(),因为受保护的成员只能通过继承访问.
我的问题是,为什么foo()方法在通过main()方法中的引用访问时工作正常ExtendsprotectedClass 但在通过引用访问时不起作用?epcUsesExtendedClass
Jon*_*eet 12
ExtendsprotectedClass允许类中的代码ProtectedClass通过类型引用访问受保护的成员ExtendsprotectedClass.从JLS部分6.6.2:
受保护的成员或对象的构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它.
和
设C是声明受保护成员m的类.仅允许在C的子类S的主体内进行访问.此外,如果Id表示实例字段或实例方法,则:
- 如果访问是通过限定名称Q.Id,其中Q是ExpressionName,则当且仅当表达式Q的类型是S或S的子类时才允许访问.[...]
UsesExtendedClass对于执行来说不是负责任的ExtendsprotectedClass,因此最终的调用失败了.
编辑:这背后的原因是protected访问旨在帮助子类实现他们需要的功能,从而提供比通常可用的超类内部更多的访问权限.如果所有代码都可以使用它,那么将该方法公之于众.基本上,子类被信任不破坏封装; 他们在自己类型的对象中获得了更多的能力.公共API不应公开这些细节,但受保护的API只能用于为子类提供更多机会.