正如其他人所提到的,使用堆栈跟踪是实现您所寻求功能的一种方法。通常情况下,如果需要“阻止”调用者访问公共方法,则可能表明设计不良。作为一个经验法则,应尽可能使用限制范围的访问修饰符。然而,将方法设置为包级私有或受保护的并不总是可行的。有时,您可能希望将某些类分组在单独的包中。在这种情况下,默认(包级私有)访问权限过于严格,而且通常没有子类化的意义,因此protected也没有帮助。
如果要限制对某些类的调用,则可以创建以下方法:
public static void checkPermission(Class... expectedCallerClasses) {
StackTraceElement callerTrace = Thread.currentThread().getStackTrace()[3];
for (Class expectedClass : expectedCallerClasses) {
if (callerTrace.getClassName().equals(expectedClass.getName())) {
return;
}
}
throw new RuntimeException("Bad caller.");
}
使用它非常简单:只需指定哪个类可以调用该方法。例如,
public void stop() {
checkPermission(ShutdownHandler.class);
running = false;
}
因此,如果除了ShutdownHandler之外的类调用stop方法,checkPermission将抛出IllegalStateException异常。
你可能会想为什么checkPermission硬编码使用堆栈跟踪的第四个元素。这是因为Thread.getStackTrace()使最近调用的方法成为第一个元素。所以,
- getStackTrace()[0] 将是对getStackTrace本身的调用。
- getStackTrace()[1] 将是对checkPermission的调用。
- getStackTrace()[2] 将是对stop的调用。
- getStackTrace()[3] 将是调用stop的方法。这就是我们感兴趣的部分。
你提到想要从特定的类和方法中调用方法,但checkPermission只检查类名。添加检查方法名称的功能只需要进行一些修改,所以我将把它留作练习。