在 Java 中从 toString 方法捕获异常
Catch exception from toString method in Java
最近我在 GitHub 上看到了以下代码:
private static String safeToString(Object obj) {
if (obj == null) return null;
try {
return obj.toString();
} catch (Throwable t) {
return "Error occured";
}
}
我从未在 try-catch
块中放置 toString()
方法调用。但现在想想,这可能是有道理的。例如,有人可以在 class 中覆盖 toString()
方法,这可能会引发运行时异常,例如 NullPointerException
。所以我们可以尝试捕捉Exception
。但为什么 Throwable
?你觉得有道理吗?
Throwable
是 Exception
和 Error
的父 class。
尝试捕获 Error
通常不是一个好主意,因为它被设计为不被捕获。
赶上 Throwable
只是赶上 Exception
的超预期和适得其反的版本。尽管如此,如果 出于某种原因 你创建了另一种 Throwable
你想要与 Exception
一起使用,这可能是一种在单个try/catch 块。并不是说这样做是一种干净的方法,但它会起作用。
编辑 TL;DR :在大多数情况下,捕获 Exception
而不是 Throwable
。
在极少数情况下,您可能想要捕获这样的错误。然而,总的来说这是一个坏主意,在这种情况下它可能有意义,因为这通常用于 logging/debugging 目的而不是直接由应用程序使用。
我希望能提供更多信息,例如
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.
捕获任何 Throwable
然后继续执行是不正确的,因为它包含 Error
,这意味着是致命的:
来自Javadocs:
An Error
is a subclass of Throwable
that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath
error, though a "normal" condition, is also a subclass of Error
because most applications should not try to catch it.
也就是一些Error
可以恢复(比如LinkageError
),其他的就没那么多了
但是捕捉 Exception
可能是一个有效的用例,例如在您不希望执行仅仅因为调用 toString()
失败:
private static String safeToString(Object obj) {
try {
return obj == null ? "null" : obj.toString();
} catch (Exception e) {
return "<exception: " + e + ">";
}
}
几乎没有理由这样做。 contract of toString() 并没有说允许从该方法中抛出异常。任何抛出异常的代码都是损坏的代码,这种异常需要暴露和修复,而不是压制。
如果您要将一些不受您控制的库中的“坏”对象转换为字符串,那么写 catch (RuntimeExcepton e)
可能是合适的,但是这样的捕获应该伴随详细说明为什么需要的评论,因为一般情况下不需要。
抛开流氓异常抛出 toString 方法,请注意 Java 已经有至少两种“安全”方法将可能为 null 的值转换为字符串:
Objects.toString(obj, null)
String.valueOf(obj)
...所以我会质疑 safeToString 方法是否应该存在。
最近我在 GitHub 上看到了以下代码:
private static String safeToString(Object obj) {
if (obj == null) return null;
try {
return obj.toString();
} catch (Throwable t) {
return "Error occured";
}
}
我从未在 try-catch
块中放置 toString()
方法调用。但现在想想,这可能是有道理的。例如,有人可以在 class 中覆盖 toString()
方法,这可能会引发运行时异常,例如 NullPointerException
。所以我们可以尝试捕捉Exception
。但为什么 Throwable
?你觉得有道理吗?
Throwable
是 Exception
和 Error
的父 class。
尝试捕获 Error
通常不是一个好主意,因为它被设计为不被捕获。
赶上 Throwable
只是赶上 Exception
的超预期和适得其反的版本。尽管如此,如果 出于某种原因 你创建了另一种 Throwable
你想要与 Exception
一起使用,这可能是一种在单个try/catch 块。并不是说这样做是一种干净的方法,但它会起作用。
编辑 TL;DR :在大多数情况下,捕获 Exception
而不是 Throwable
。
在极少数情况下,您可能想要捕获这样的错误。然而,总的来说这是一个坏主意,在这种情况下它可能有意义,因为这通常用于 logging/debugging 目的而不是直接由应用程序使用。
我希望能提供更多信息,例如
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.
捕获任何 Throwable
然后继续执行是不正确的,因为它包含 Error
,这意味着是致命的:
来自Javadocs:
An
Error
is a subclass ofThrowable
that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. TheThreadDeath
error, though a "normal" condition, is also a subclass ofError
because most applications should not try to catch it.
也就是一些Error
可以恢复(比如LinkageError
),其他的就没那么多了
但是捕捉 Exception
可能是一个有效的用例,例如在您不希望执行仅仅因为调用 toString()
失败:
private static String safeToString(Object obj) {
try {
return obj == null ? "null" : obj.toString();
} catch (Exception e) {
return "<exception: " + e + ">";
}
}
几乎没有理由这样做。 contract of toString() 并没有说允许从该方法中抛出异常。任何抛出异常的代码都是损坏的代码,这种异常需要暴露和修复,而不是压制。
如果您要将一些不受您控制的库中的“坏”对象转换为字符串,那么写 catch (RuntimeExcepton e)
可能是合适的,但是这样的捕获应该伴随详细说明为什么需要的评论,因为一般情况下不需要。
抛开流氓异常抛出 toString 方法,请注意 Java 已经有至少两种“安全”方法将可能为 null 的值转换为字符串:
Objects.toString(obj, null)
String.valueOf(obj)
...所以我会质疑 safeToString 方法是否应该存在。