从Java中的toString方法捕获异常

时间:2019-03-19 09:31:22

标签: java exception tostring throwable

最近我在GitHub上看到了以下代码:

private static String safeToString(Object obj) {
    if (obj == null) return null;
    try {
        return obj.toString();
    } catch (Throwable t) {
        return "Error occured";
    }
}

我从未在toString()块中放置过try-catch方法调用。但是现在,当我考虑它时,这可能是有道理的。例如,有人可能会在类中覆盖toString()方法,而该方法可能会抛出运行时异常,例如NullPointerException。因此,我们可以尝试捕获Exception。但是为什么Throwable呢?您认为这有意义吗?

4 个答案:

答案 0 :(得分:2)

几乎没有充分的理由这样做。 contract of toString()并未表示允许从该方法引发异常。任何引发异常的代码都是残破的代码,这种异常需要公开和修复,而不是抑制。

在将某些“不良”对象从您无法控制的库转换为字符串的情况下,写catch (RuntimeExcepton e)可能是适当的,但是这样的捕获应该伴随注释,详细说明为什么有必要,因为在通常情况下不需要。

撇开Rogue异常抛出toString方法,请注意Java已经至少有两种“安全”方式将可能为null的值转换为String:

  • Objects.toString(obj, null)
  • String.valueOf(obj)

...所以我会质疑safeToString方法是否应该存在。

答案 1 :(得分:1)

ThrowableExceptionError的父类。 尝试捕获Error通常是一个坏主意,因为它被设计为不会被捕获。

捕获Throwable只是捕获Exception的过度实现和适得其反的版本。尽管如此,如果出于某种原因您创建了另一种Throwable并希望与Exception一起使用,那可能是一次尝试/捕获的方法块。并不是说这样做是一种干净的方法,但是它会起作用。

编辑TL; DR:在大多数情况下,捕获Exception而不是Throwable

答案 2 :(得分:1)

在极少数情况下,您可能想捕获这样的错误。一般来说,这是一个坏主意,在这种情况下,这可能是有道理的,因为这通常是出于日志记录/调试的目的,而不是由应用程序直接使用。

我希望提供更多信息,例如

private static String safeToString(Object obj) {
    if (obj == null) return null;
    try {
        return obj.toString();
    } catch (Throwable t) {
        return obj.getClass() + ".toString() threw " + t;
    }
}

例如

class Element {
    Object data;
    Element e;

    public String toString() {
        return data + (e == null ? "" : e.toString());
    }
}

Element e = new Element();
e.data = "hi";
e.e = e; // oops

System.out.println("e: " + safeToString(e)); // doesn't kill the thread or JVM.

答案 3 :(得分:0)

捕获任何Throwable然后继续执行是不正确的,因为它包含Error,这注定是致命的:

来自Javadocs

  

ErrorThrowable的子类,表示合理的应用程序不应尝试捕获的严重问题。大多数此类错误是异常情况。尽管ThreadDeath错误是“正常”情况,但它也是Error的子类,因为大多数应用程序都不应尝试捕获它。

也就是说,一些 Error可以恢复(例如LinkageError),而其他恢复得不是很多。

但是捕获 Exception 可能是一个有效的用例,例如在记录代码中,您不希望仅仅因为对toString()的调用失败而导致执行中断:

private static String safeToString(Object obj) {
    try {
        return obj == null ? "null" : obj.toString();
    } catch (Exception e) {
        return "<exception: " + e + ">";
    }
}