【问题标题】:Java: Subclass access without package accessJava:没有包访问的子类访问
【发布时间】:2011-05-13 07:14:03
【问题描述】:

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

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

所以我想我在问,这个决定的动机是什么,我该如何绕过它?

【问题讨论】:

  • 但是您正在为ControlledInstantiation 编写代码,因此可能是它包中代码的所有者..您是说您不信任自己吗?
  • 任何人都可以在任何包中创建新类,类加载器保护的类除外。除非我在所有记录的接口中隐藏内部使用的类的包名称(我认为这是不可能的,因为即使是工厂也必须导入它创建的类,并且在某些时候必须引用工厂本身,等等.),任何人都可以将一个类放入该包中。人们几乎肯定不会,除非他们想做不该做的事,但他们可以。

标签: java access-modifiers


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

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

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

      if(!getClass().isAssignableFrom(
          Class.forName(new Throwable().getStackTrace()[1].getClassName()))) {
              throw new IllegalAccessException(
                  "This method can be accessed by subclass only");
      }
      

    【讨论】:

    • 你的答案很好,但请学会正确格式化代码示例:stackoverflow.com/editing-help
    • 抱歉格式错误。我通常会这样做,但这次我尝试了几次格式化,但它不起作用!
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2011-04-03
      • 1970-01-01
      • 2014-06-23
      • 1970-01-01
      • 1970-01-01
      • 2015-05-06
      • 1970-01-01
      • 1970-01-01
      • 2016-06-15
      相关资源
      最近更新 更多