1. Java 9中对Stack Trace的改进
在Java 9中,我们看到了对Stack Trace的一些改进。在以前的版本中,我们可以通过以下代码获取调用当前方法的类的信息:
Class<?> clazz = new Exception().getStackTrace()[1].getClass();
System.out.println(clazz.getName());
这是通过抛出一个异常来访问堆栈信息的。在Java 9中,我们有一个新的方法,StackWalker,可以让我们更容易地访问堆栈信息。
2. StackWalker.getCallerClass()的介绍
StackWalker是一个新的API类,它允许我们访问堆栈信息。StackWalker类提供了三个方法,它们都返回一个Stream,可以轻松地迭代调用堆栈。
StackWalker walker = StackWalker.getInstance();
walker.forEach(System.out::println);
这段代码将打印出调用堆栈中的所有堆栈帧。但是,StackWalker类中最有趣的方法之一是getCallerClass()
。这个方法可以返回调用当前方法的类的Class对象。
Class<?> clazz = StackWalker.getInstance()
.getCallerClass();
System.out.println(clazz.getName());
这个代码片段将输出调用getCallerClass()方法的类的名称(而不是StackTraceElement数组中下一个元素的类)。
2.1 StackWalker.getCallerClass()的限制
有一些限制需要注意。StackWalker.getCallerClass()要求创建StackWalker实例的类和调用getCallerClass()方法的类在同一个模块中,并且不允许从模块外部访问其他模块。如果在其他模块中调用getCallerClass()方法,将会抛出IllegalCallerException异常。
2.2 StackWalker.getCallerClass()的使用场景
StackWalker.getCallerClass()方法能够方便地用于记录日志。通过获取栈中前几个方法的类,我们可以确定哪个类调用了我们的方法,并将相应的信息记录到日志中。
另一个使用场景是扩展调试信息。在某些情况下,当代码遇到异常时,我们可以添加一些额外的调试信息来诊断问题。通过使用StackWalker.getCallerClass(),我们可以将调用链的信息添加到异常消息中。
3. 示例代码
以下代码演示了StackWalker.getCallerClass()的用法:
public class Example {
public void doSomething() {
log("Starting...");
log("Stopping...");
}
private void log(String message) {
StackWalker walker = StackWalker.getInstance();
Class<?> clazz = walker.getCallerClass();
System.out.printf("[%s] %s: %s\n", clazz.getSimpleName(), LocalDateTime.now(), message);
}
public static void main(String[] args) {
new Example().doSomething();
}
}
在上面的示例代码中,log()方法调用StackWalker.getInstance().getCallerClass()
来确定调用它的方法的类。它使用这个信息来输出消息和时间戳。
这个程序将输出:
[Example] 2020-01-01T00:00:00.000: Starting...
[Example] 2020-01-01T00:00:00.000: Stopping...
总结
StackWalker.getCallerClass()方法是一个有用的工具,可以方便地访问调用当前方法的类的信息。然而,它有一些限制,它必须在同一个模块中调用,并且不允许访问其他模块。使用StackWalker.getCallerClass()方法可以方便地记录日志和扩展调试信息。