Java:无包访问的子类访问

Java:无包访问的子类访问,java,access-modifiers,Java,Access Modifiers,对Java来说相当陌生,但我想知道为什么包访问被认为比子类访问“更严格”。也就是说,每个提供子类访问成员的访问修饰符也提供整个包的访问权限,并且有一些修饰符提供包访问权限,但不提供子类访问权限 这不是完全倒退了吗?假设我在某个包中有一个类ControlledInstantiation。如果我有另一个类AlsoControlledInstantiation扩展了ControlledInstantiation,我将无法调用ControlledInstantiation的构造函数,除非我将其设置为pr

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

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


因此,我想我是在问,是什么促使了这个决定,我该如何避免它?

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


事实上,Java曾经有一个私有保护的修饰符,它可以实现您所追求的目标,但我想它被删除了,因为它让人困惑。我真的不知道如何在不将每个类/子类对降级到自己的包的情况下实现这一点。但这是一个凌乱的解决方案,它违背了Java的原则,而且它对超过两个类的继承层次结构也不起作用。

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

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

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


  • 你可以封一个包裹。请参阅JAR文件规范。

    但是您正在为
    ControlledInstantiation
    编写代码,因此可能是其包中代码的所有者。。你是说你不信任自己吗?任何人都可以在任何包中创建一个新类,除了类装入器保护的类。除非我在所有文档化的接口中隐藏内部使用的类的包名(我认为这是不可能的,因为即使是工厂也必须导入它创建的类,并且在某个时候必须引用工厂本身,等等),否则任何人都可以将类放入该包中。人们几乎肯定不会这样做,除非他们想做一些他们不应该做的事情,但他们可以。你的答案很好,但请学会正确设置代码示例的格式:对不起,格式不好。我通常会这样做,但这次我尝试格式化了好几次,但都没有成功!
    if(!getClass().isAssignableFrom(
        Class.forName(new Throwable().getStackTrace()[1].getClassName()))) {
            throw new IllegalAccessException(
                "This method can be accessed by subclass only");
    }