Java:跨包的受保护访问

时间:2010-08-22 07:53:55

标签: java inheritance packages protected

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

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

有两个包:package1package2

  1. package1ProtectedClass.java

    package org.test.package1;
    
    public class ProtectedClass {
    
        protected void foo () {
            System.out.println("foo");
        }
    }
    
  2. 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?
        }
    }
    
  3. 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
        }
    }
    
  4. 据了解,boo()中的ExtendsprotectedClass方法可以访问foo(),因为受保护的成员只能通过继承访问。

    我的问题是,为什么foo()方法在main()的{​​{1}}方法中通过引用访问时工作正常,但在访问时无效通过ExtendsprotectedClass中的epc引用?

4 个答案:

答案 0 :(得分:12)

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

  

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

  

设C是声明受保护成员m的类。仅允许在C的子类S的主体内进行访问。此外,如果Id表示实例字段或实例方法,则:

     
      
  • 如果访问是通过限定名称Q.Id,其中Q是ExpressionName,则当且仅当表达式Q的类型为S或S的子类时才允许访问。[...] < / LI>   

UsesExtendedClassExtendsprotectedClass的实施不负责任,因此最终的调用失败。

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

看一下这张照片

enter image description here

明确表示可以通过子类访问类的受保护成员。