Java:没有包访问的子类访问

时间:2010-11-21 05:18:12

标签: java access-modifiers

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

这不是完全倒退吗?假设我在某个包中有一个类ControlledInstantiation。如果我有另一个类AlsoControlledInstantiation扩展ControlledInstantiation,我无法调用ControlledInstantiation的构造函数,除非我将其设置为protected或public。如果我将它设置为protected,那么包中的任何其他类都可以根据需要经常实例化它。因此,对于其超类(和语法,是)必须替代的东西获得与超类相同或更少的访问权限,而不是服务于不同但相关的函数的东西。这就像告诉你的孩子他不能玩你的钱包,因为你不会让你的邻居这样做,然后让你的邻居睡在你的房子,因为你的孩子。

所以我想我在问这个决定的动机是什么,我怎么能绕过它呢?

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:0)

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