Java:跨包的受保护访问

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

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

有两个软件包: 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() ,因为受保护的成员只能通过继承来访问。

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


    允许ExtendsprotectedClass类中的代码通过类型为ExtendsprotectedClass的引用访问ProtectedClass保护成员。 从JLS部分6.6.2:

    对象的受保护成员或构造函数可以从仅在负责实现该对象的代码声明的包中进行访问。

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

  • 如果访问是通过限定名Q.Id访问的,其中Q是一个表达式名,那么当且仅当表达式Q的类型是S或S的一个子类时才允许访问。[...]
  • UsesExtendedClass不负责执行ExtendsprotectedClass ,因此最终调用失败。

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


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


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

    链接地址: http://www.djcxy.com/p/24107.html

    上一篇: Java: protected access across packages

    下一篇: Why the protected modifier behave differently here in Java subclass?