【发布时间】:2012-06-02 19:44:05
【问题描述】:
我们如何才能将任何受保护方法的访问权限限制为只能访问任何包中的子类,而不是同一包中的类。
如果任何不是子类并且在同一个包中的类也必须抛出“受保护的方法”之类的异常。
编辑:有什么方法可以检查调用类名实例,然后我们可以使用 instanceof 进行验证。
【问题讨论】:
标签: java
我们如何才能将任何受保护方法的访问权限限制为只能访问任何包中的子类,而不是同一包中的类。
如果任何不是子类并且在同一个包中的类也必须抛出“受保护的方法”之类的异常。
编辑:有什么方法可以检查调用类名实例,然后我们可以使用 instanceof 进行验证。
【问题讨论】:
标签: java
这是不可能的。您可以在 protected 修饰符(同一个包中的子类 + 类)和默认修饰符(同一个包中的类)之间进行选择。没有第三种选择。
您也不能在运行时轻易地强制执行,因为找到调用代码的类名和包并不容易。见:How do I find the caller of a method using stacktrace or reflection?
一个选项是使用aspectj。它甚至可以在编译时拒绝尝试从同一包访问protected 方法而不是子类的代码(借助declare warning 和declare error 指令)。您可能想要包含一些编译时注释,例如@SubclassesOnly。请参阅:Compile-time architecture enforcement revisited: AspectJ, Maven and Eclipse 和 Compile-time checks with AspectJ。
【讨论】:
简单:从包中删除所有其他类,只留下你的基类。
这意味着可以访问您的类的唯一类来自另一个包。
如果另一个库复制了您的包名,您可以轻松检查调用者的包并断言它与您的不同:
if (getClass().getPackage().equals(MyBaseClass.class.getPackage())
throw new IllegalAccessError(); // or similar
仅供参考getClass() 为您提供this 的类,这将是子类的类。
要查找调用者的类,请使用以下代码:
Class<?> callerClass = Class.forName(Thread.currentThread().getStackTrace()[2].getClassName());
【讨论】:
Thread.currentThread().getStackTrace() 来获取调用者的类。查看编辑后的答案