比较两个 throwable 的正确方法是什么?
What is the correct way to compare two throwables?
我正在使用 JUnit 规则立即重新 运行 任何失败的测试。我的额外要求是,如果re-运行也失败了,判断他们是否因为同样的原因而失败。
为此,我修改了 this answer 中的代码以记录失败并进行比较。然而,比较 (.equals) 总是评估为 false,尽管它们出于同样的原因而失败。解决此问题的最佳方法是什么?
private Statement statement(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
for (int i = 0; i < retryCount; i++) {
try {
base.evaluate();
return;
} catch (Throwable t) {
System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed");
// Compare this error with the one before it.
if (errors.size() > 0) {
if (t.equals(errors.get(errors.size() - 1))) {
System.out.println("The error is the same as the previous one!");
} else {
System.out.println("The error is different from the previous one.");
}
}
errors.add(t);
}
}
System.err.println(description.getDisplayName() + ": giving up after " + retryCount
+ " failures");
// Throw most recent error.
throw errors.get(errors.size() - 1);
}
};
}
Equals 没有正确实现异常。您必须自己比较消息 and/or 堆栈跟踪。
你只能比较:
按名字
t.getClass().getName()
或通过 instanceof
t instanceof XXXXXXX
如果只想知道 class 的类型,请使用 instance of
,例如:
if( t instanceof Throwable){
//...
}
Throwable
的相等性定义为 "the same Throwable
"。 (它比较参考文献。)
"Same reason" 是您需要为您的应用程序考虑和定义的内容。
我们可以定义它的一种方式是 "the same type and loosely the same throw
statement":
static boolean sameTypeAndLine(Throwable t1, Throwable t2) {
if (t1.getClass() == t2.getClass()) {
StackTraceElement[] trace1 = t1.getStackTrace();
StackTraceElement[] trace2 = t2.getStackTrace();
return trace1[0].equals(trace2[0]);
} else {
return false;
}
}
但这仍然有歧义:
if (bad1 || bad2) {
// same throw site, different conditions
throw new Exception(...);
}
// throws NullPointerExeption
// (was it foo or the result of bar() that was null?)
Object baz = foo.bar().baz();
因此,您能做的最好的事情就是明确定义例外的原因:
class MyException {
final Reason reason;
MyException(Reason reason) {
this.reason = reason;
}
// or a class, or whatever you need
enum Reason {A, B, C}
}
并检查那些。然后另外,使用防止歧义的编码风格。
我正在使用 JUnit 规则立即重新 运行 任何失败的测试。我的额外要求是,如果re-运行也失败了,判断他们是否因为同样的原因而失败。
为此,我修改了 this answer 中的代码以记录失败并进行比较。然而,比较 (.equals) 总是评估为 false,尽管它们出于同样的原因而失败。解决此问题的最佳方法是什么?
private Statement statement(final Statement base, final Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
for (int i = 0; i < retryCount; i++) {
try {
base.evaluate();
return;
} catch (Throwable t) {
System.err.println(description.getDisplayName() + ": run " + (i + 1) + " failed");
// Compare this error with the one before it.
if (errors.size() > 0) {
if (t.equals(errors.get(errors.size() - 1))) {
System.out.println("The error is the same as the previous one!");
} else {
System.out.println("The error is different from the previous one.");
}
}
errors.add(t);
}
}
System.err.println(description.getDisplayName() + ": giving up after " + retryCount
+ " failures");
// Throw most recent error.
throw errors.get(errors.size() - 1);
}
};
}
Equals 没有正确实现异常。您必须自己比较消息 and/or 堆栈跟踪。
你只能比较:
按名字
t.getClass().getName()
或通过 instanceof
t instanceof XXXXXXX
如果只想知道 class 的类型,请使用 instance of
,例如:
if( t instanceof Throwable){
//...
}
Throwable
的相等性定义为 "the same Throwable
"。 (它比较参考文献。)
"Same reason" 是您需要为您的应用程序考虑和定义的内容。
我们可以定义它的一种方式是 "the same type and loosely the same throw
statement":
static boolean sameTypeAndLine(Throwable t1, Throwable t2) {
if (t1.getClass() == t2.getClass()) {
StackTraceElement[] trace1 = t1.getStackTrace();
StackTraceElement[] trace2 = t2.getStackTrace();
return trace1[0].equals(trace2[0]);
} else {
return false;
}
}
但这仍然有歧义:
if (bad1 || bad2) { // same throw site, different conditions throw new Exception(...); }
// throws NullPointerExeption // (was it foo or the result of bar() that was null?) Object baz = foo.bar().baz();
因此,您能做的最好的事情就是明确定义例外的原因:
class MyException {
final Reason reason;
MyException(Reason reason) {
this.reason = reason;
}
// or a class, or whatever you need
enum Reason {A, B, C}
}
并检查那些。然后另外,使用防止歧义的编码风格。