Java 如何摆脱Exception.getMessage()输出带类名

问题

如下所示,exception.getMessage() 输出的信息带上了Class name。这样就会一直携带,看着不太舒服。

com.xxx.api.RealTimeException: com.xxx.api.RealTimeException: scp: SNAPHOT.jar: Permission denied

分析

这个类名应该来自于exception的转换 嵌套
这里日志打印出来是 java.util.concurrent.ExecutionException 异常携带的信息。
那么java.util.concurrent.ExecutionException 这个异常是来自于Future。

可以看到 Future.get 调用了report,这里会处理异常。

private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }

再顺着 new ExecutionException构造器,一直找到 Throwable的构造器

    public Throwable(Throwable cause) {
        fillInStackTrace();
        detailMessage = (cause==null ? null : cause.toString());
        this.cause = cause;
    }

这里就很显然,如果Exception子类使用 这个构造器,那么detailMessage 会取上一个 exception的.toString。而不是getMessage:

//Throwable
    public String toString() {
        String s = getClass().getName();
        String message = getLocalizedMessage();
        return (message != null) ? (s + ": " + message) : s;
    }

解决

如果是ExecutionException异常,则取cause的Message,就不会有类名。这里假设cause 类是一个没有再包裹其他exception的直接异常。
一般Exception的 message本身就不会带有类名,子类也不会有。

  try {
     future.get();
  } catch (Exception e) {
      if (e instanceof ExecutionException) {
        e = (Exception) e.getCause();
      }
      throw new RealTimeException(-1, e.getMessage());
    }
posted @ 2020-04-15 19:03  一杯半盏  阅读(2554)  评论(0编辑  收藏  举报