我有一个关于java.util.logging.Handler的问题:
是否允许此抽象方法的实现抛出运行时异常,还是应始终向错误管理器报告?
文档没有指定,但类中的其他方法明确说明了它们可以抛出的内容:
公共摘要无效发布(日志记录记录) 发布日志记录。 日志记录请求最初是向 Logger 对象发出的,该对象 初始化日志记录并将其转发到此处。
处理程序负责格式化消息,何时以及是否 必要。格式应包括本地化。
参数:记录 - 日志事件的描述。空记录是 静默忽略且未发布
[链接: https://docs.oracle.com/javase/7/docs/api/java/util/logging/Handler.html#publish(java.util.logging.LogRecord)]
在这种情况下,API 规范并不总是与实现匹配。 源代码中不成文的规则似乎是:
- 对空记录的处理可以是恶意的或忽略的。 StreamHandler 的子类忽略 null,并且 MemoryHandler 是 null 敌对的。 记录器从不传递 null 进行发布,JDK-8216363:java.util.logging.Handler#isLoggable 中的 NullPointerException 使其将空记录视为忽略。
- 从 isLoggable 引发的任何运行时异常都将转义处理程序。 这意味着从筛选器引发的任何异常都会转义发布方法,并且不会被错误管理器捕获。 请注意,没有枚举ErrorManager.FILTER_FAILURE,这意味着该行为是有意的。
- 发布不应引发的异常在错误管理器文档中枚举。 大多数情况是格式和写入错误。
真正的发布应该委托给错误管理器,以确定发布是否引发异常。 来自 Handler.setErrorManager 文档:
如果在使用此处理程序时发生任何错误,将调用错误管理器的"错误"方法。
这意味着发布应该服从错误管理器的行为,默认情况下不会抛出错误管理器。
如果你想通过Handler.reportError获得异常,你必须使用偷偷摸摸的抛出。
public class HostileErrorManager extends ErrorManager {
public HostileErrorManager() {
}
@Override
protected void reportError(String msg, Exception ex, int code) {
sneakyThrow(new Throwable(msg + ": " + code, ex));
}
@SuppressWarnings("unchecked")
private <T extends RuntimeException> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
}