Java:跨包的受保护访问

发布于 2024-09-15 07:01:10 字数 1525 浏览 15 评论 0原文

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

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

有两个包:package1package2

  1. package1ProtectedClass.java

    package org.test.package1;
    
    公共类受保护类{
    
        受保护的无效foo(){
            System.out.println("foo");
        }
    }
    
  2. package2ExtendsprotectedClass.java< /p>

    package org.test.package2;
    
    导入 org.test.package1.ProtectedClass;
    
    公共类 ExtendsprotectedClass 扩展 ProtectedClass {
    
        公共无效嘘(){
            foo(); // 这有效, 
                   // 因为受保护的方法通过继承可见
        }
    
        公共静态无效主(字符串[] args){
            ExtendsprotectedClass epc = new ExtendsprotectedClass();
            epc.foo(); // 为什么这个有效? 
                       // 由于它是通过引用访问的,
                       // foo() 不应该是可见的,对吧?
        }
    }
    
  3. package2UsesExtendedClass.java< /p>

    package org.test.package2;
    
    公共类使用扩展类{
    
        公共静态无效主(字符串[] args){
            ExtendsprotectedClass epc = new ExtendsprotectedClass();
            epc.foo(); // 编译错误: 
                       // ProtectedClass 类型的 foo() 方法
                       // 不可见
        }
    }
    

据了解,是ExtendsprotectedClassboo()方法code> 可以访问 foo(),因为受保护的成员只能通过继承来访问。

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

I would like to understand what's happening in the example below (where a protected member is being accessed from outside the package through a subclass).

I know for classes outside the package, the subclass can see the protected member only through inheritance.

There are two packages: package1 and package2.

  1. package1: ProtectedClass.java

    package org.test.package1;
    
    public class ProtectedClass {
    
        protected void foo () {
            System.out.println("foo");
        }
    }
    
  2. 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?
        }
    }
    
  3. 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
        }
    }
    

It is understood that the boo() method in ExtendsprotectedClass can access foo(), since protected members can be accessed through inheritance only.

My question is, why is the foo() method working fine when accessed through a reference in the main() method of ExtendsprotectedClass but will not work when accessed through the epc reference in UsesExtendedClass?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

策马西风 2024-09-22 07:01:37

看看这张图片:http://docs.oracle。 com/javase/tutorial/java/javaOO/accesscontrol.html

在此处输入图像描述

很明显受保护的成员类的内容可以通过子类来访问。

take a look on this picture from : http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html

enter image description here

its clear that protected member of class can be accessed via subclass.

瞳孔里扚悲伤 2024-09-22 07:01:36

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

I believe you've answered your own question; UsesExtendedClass does not inherit from ProtectedClass, and -- by definition -- "protected" members are accessible only in the class in which they are declared / defined or in a class that inherits from the one in which they are declared or defined.

鹤舞 2024-09-22 07:01:33

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

It is working in the first case because it is being called from the same class even the method is being accessed through a reference. You could even call a private method of ExtendsprotectedClass through a reference in the same main method.

夢归不見 2024-09-22 07:01:32

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

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

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

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

UsesExtendedClass 不负责 ExtendsprotectedClass 的实现,因此最终调用失败。

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

Code within the ExtendsprotectedClass class is allowed to access protected members of ProtectedClass via a reference of type ExtendsprotectedClass. From the JLS section 6.6.2:

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

and

Let C be the class in which a protected member m is declared. Access is permitted only within the body of a subclass S of C. In addition, if Id denotes an instance field or instance method, then:

  • If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S. [...]

UsesExtendedClass isn't reponsible for the implementation of ExtendsprotectedClass, hence the final call fails.

EDIT: The reasoning behind this is that protected access is designed to help subclasses implement the functionality they need, giving more access to the internals of the superclass than would normally be available. If that were available to all code, it would be pretty close to making the method public. Basically, the subclasses are trusted not to break encapsulation; they're given more capabilities within objects of their own type. The public API shouldn't expose those details, but the protected API can just for the purposes of giving subclasses more opportunities.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文