首页 文章

Java:跨包的受保护访问

提问于
浏览
14

我想了解下面示例中发生的情况(通过子类从包外部访问受保护的成员) .

我知道对于包外的类,子类只能通过继承来查看受保护的成员 .

有两个包: package1package2 .

  • package1ProtectedClass.java
package org.test.package1;

public class ProtectedClass {

    protected void foo () {
        System.out.println("foo");
    }
}
  • package2ExtendsprotectedClass.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?
    }
}
  • package2UsesExtendedClass.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
    }
}

据了解, ExtendsprotectedClass 中的 boo() 方法可以访问 foo() ,因为受保护的成员只能通过继承访问 .

我的问题是,为什么 foo() 方法在 ExtendsprotectedClassmain() 方法中通过引用访问时工作正常,但在通过 UsesExtendedClass 中的 epc 引用访问时不起作用?

4 回答

  • 1

    允许 ExtendsprotectedClass 类中的代码通过 ExtendsprotectedClass 类型的引用访问 ProtectedClass 的受保护成员 . 来自JLS section 6.6.2

    可以从包外部访问对象的受保护成员或构造函数,只能通过负责实现该对象的代码来声明它 .

    设C为声明受保护成员m的类 . 仅允许在C的子类S的主体内进行访问 . 此外,如果Id表示实例字段或实例方法,则:如果访问是通过限定名称Q.Id,其中Q是ExpressionName,则访问当且仅当表达式Q的类型为S或S的子类时才被允许[...]

    UsesExtendedClass 对于 ExtendsprotectedClass 的实现不负责任,因此最终调用失败 .

    编辑:这背后的原因是 protected 访问旨在帮助子类实现他们需要的功能,从而提供比通常可用的超类内部更多的访问权限 . 如果所有代码都可以使用它,那么将该方法公之于众 . 基本上,子类被信任不破坏封装;他们公开了这些细节,但受保护的API只能用于为子类提供更多机会 .

  • 2

    它在第一种情况下工作,因为它是从同一个类调用的,即使通过引用访问该方法也是如此 . 您甚至可以通过同一主方法中的引用调用 ExtendsprotectedClassprivate 方法 .

  • 12

    我相信你已经回答了自己的问题; UsesExtendedClass不从ProtectedClass继承,并且 - 根据定义 - “protected”成员只能在声明/定义它们的类中或在继承自声明或定义它们的类中访问 .

  • 0

    看看这张照片来自:http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

    enter image description here

    很明显,类的受保护成员可以通过子类访问 .

相关问题