Java:子类访问而无需包访问

发布于 2024-10-03 09:34:42 字数 489 浏览 3 评论 0原文

对于 Java 来说相当陌生,但我想知道为什么包访问被认为比子类访问“更具限制性”。也就是说,每个为子类提供对成员的访问权限的访问修饰符也为整个包提供访问权限,并且存在提供包访问权限但不提供子类访问权限的修饰符。

这不是完全倒退了吗?假设我在某个包中有一个 ControlledInstantiation 类。如果我有另一个类 AlsoControlledInstantiation 扩展 ControlledInstantiation,我无法调用 ControlledInstantiation 的构造函数,除非我将其设置为 protected 或 public。如果我将它设置为 protected,那么现在包中的任何其他类都可以随意实例化它。因此,那些必须替代其超类的东西(从语法上来说,是)与提供不同但相关功能的东西相比,对超类的访问权限相同或更少。这就像告诉你的孩子他不能玩你的钱包,因为你不会让你的邻居这样做,然后让你的邻居睡在你的房子里,因为你的孩子这样做。

所以我想我在问,是什么促使我做出这个决定,我该如何绕过它?

Fairly new to Java, but I'm wondering why package access is considered "more restrictive" than subclass access. That is, every access modifier which provides subclasses with access to a member also provides the whole package with access, and there are modifiers whic provide package access but not subclass access.

Isn't this totally backwards? Let's say I have a class ControlledInstantiation in some package. If I have another class AlsoControlledInstantiation extends ControlledInstantiation, I am unable to call the constructor of ControlledInstantiation unless I set it to protected or public. And if I set it to protected, now any other class in the package can instantiate it as often as it likes. So something which is obliged to be substitutable for its superclass (and, syntactically, is) gets the same or less access to the superclass than something which serves a distinct but related function. It's like telling your child he can't play with your wallet because you wouldn't let your neighbours do it and then letting your neighbours sleep in your house because your kid does.

So I guess I'm asking, what motivated this decision, and how can I get around it?

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

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

发布评论

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

评论(3

遮云壑 2024-10-10 09:34:42

乍一看似乎有些倒退,但其思想是 Java 包应该包含一组在语义上相关的相对内聚的类,这反映在默认的包修饰符中。那么逻辑是,如果您想更进一步并允许任何包中的子类查看您的成员,您可以将它们声明为受保护的。来自外部包的子类应该比来自您自己的包的任何类(无论是否是子类)更不受信任,这对您来说有意义吗?

事实上,Java 曾经有一个 private protected 修饰符,它可以实现你所追求的目标,但我想它被删除了,因为它让人们感到困惑。我不太确定如何在不将每个类/子类对归入其自己的包的情况下实现这一目标。但这是一个混乱的解决方案,违背了 Java 的原则,而且它不适用于两个以上类的继承层次结构。

It may seem backwards at first, but the idea is that a Java package should contain a set of comparatively cohesive classes which are semantically related, and this is reflected in the default package modifier. Then the logic is that if you want to go one step further and allow subclasses from any package to view your members, you can declare them protected. Does it make sense to you that subclasses from foreign packages should be less trusted than any class (whether a subclass or not) from your own package?

Java did in fact once have a private protected modifier which would achieve what you're after, but it was removed, I imagine, because it confused people. I'm not really sure how you could achieve this without relegating each class/subclass pair to its own package. But that's a messy solution which goes against Java's principles and it wouldn't work for inheritance hierarchies of more than two classes anyway.

禾厶谷欠 2024-10-10 09:34:42

你是对的,这个事实有点令人困惑。
以下是我可以建议的解决方法。

  1. 您的受保护构造函数的示例与方法更相关。在某些情况下,如果将类标记为抽象,则可以避免不是当前类的子类的包成员访问受保护构造函数。

  2. 如果您确实希望避免包成员访问受保护的方法,您至少可以在运行时使用 Throwable.getStacktrace() 解决此问题:

    if(!getClass().isAssignableFrom(
        Class.forName(new Throwable().getStackTrace()[1].getClassName()))) {
            抛出新的 IllegalAccessException(
                “该方法只能由子类访问”);
    }
    

You are right, this fact is a little bit confusing.
Here are the workarounds I can suggest.

  1. Your example with protected constructor is more relevant for methods. In some cases you can avoid access to protected constructor by package member that are not the subclasses of current class if you mark class as abstract.

  2. If you really wish to avoid access to protected method by package members you can solve this problem at least at runtime using Throwable.getStacktrace():

    if(!getClass().isAssignableFrom(
        Class.forName(new Throwable().getStackTrace()[1].getClassName()))) {
            throw new IllegalAccessException(
                "This method can be accessed by subclass only");
    }
    
吻泪 2024-10-10 09:34:42

您可以密封包裹。请参阅 JAR 文件规范。

You can seal a package. See the JAR File Specification.

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