当前位置: 首页 > 面试题库 >

Java:跨包的受保护的访问

贺彬
2023-03-14
问题内容

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

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

有两个包:package1package2

  1. package1ProtectedClass.java
        package org.test.package1;

    public class ProtectedClass {

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

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

我的问题是,为什么是foo()方法,通过在基准访问时,工作正常main()的方法ExtendsprotectedClass ,但
将无法正常工作 通过访问时epc的参考UsesExtendedClass


问题答案:

ExtendsprotectedClass该类中的代码被允许ProtectedClass通过type的引用访问受保护的成员ExtendsprotectedClass。从JLS第6.6.2节中:

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

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

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

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

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



 类似资料:
  • 问题内容: 我在理解Java(或其背后的设计)中的受保护的访问修饰符时遇到了一些麻烦。我认为这意味着程序包访问和通过继承包含抽象成员的类的对象的访问。 我编写了以下示例代码。我看到,如果未注释,注释掉的行会产生编译错误。为什么我可以通过Second中的Second对象而不是Second中的First对象访问pro? 问题答案: 该网页链接@MadProgrammer给出了一个体面的解释: “ pr

  • 问题内容: 在下面的代码中,Consumer类可以访问Parent类的受保护方法。由于Parent和Consumer类之间没有关系,这怎么可能。 谢谢 问题答案: 表示:相同的包或通过继承。由于您的课程都在(实际上不建议使用),因此可以进行访问。顺便说一句:如果您尝试测试Java访问控制,则会忘记(= no修饰符= )。 另一方面,访问是指:从该特定类(以及仍然是主机类成员的非静态内部类)之外的任

  • 问题内容: 我有两节课。 类具有受保护的方法,是的实例。 Class 与class在同一包中。 我正在尝试访问,但正在获取… 怎么了? 问题答案: 编译器应该捕获这样的错误。当您显然在运行时得到此消息时,发生了一些奇怪的事情。可能您已更改了源代码,但已完全重新编译。 另一个潜在但晦涩的问题是通过不同的类加载器加载类。即使包名称相同,从不同的类加载器加载的类也将位于不同的包中(以与由不同的类加载器加

  • 通过向资源服务器出示访问令牌,客户端访问受保护资源。资源服务器必须验证访问令牌,并确保它没有过期且其范围涵盖了请求的资源。资源服务器用于验证访问令牌的方法(以及任何错误响应)超出了本规范的范围,但一般包括资源服务器和授权服务器之间的互动或协调。 客户端使用访问令牌与资源服务器进行证认的方法依赖于授权服务器颁发的访问令牌的类型。通常,它涉及到使用具有所采用的访问令牌类型的规范定义的身份验证方案(如R

  • 问题内容: 为什么定义中的所有方法都是隐式的?为什么不允许使用方法? 问题答案: 因为接口应该表示“您可以在课堂外看到的东西”。添加非公共方法是没有意义的。

  • 问题内容: 我正在研究使用SQL LocalDB作为客户端数据库,它将替代.net 4中开发的内部应用程序中的当前SQL CE 3.5数据库。 我遇到了一个不确定的问题,那就是LocalDB实例的安全设置。 如果我在.net中设置了一个脚本来创建一个私有LocalDB实例,例如(localdb)\ T1,然后在该实例中创建了一个新数据库,并添加了一个SQL用户帐户+密码(非域帐户),如何停止本地使