考虑这两段代码(您可以假设execeptionObj
属于Object
类型,但我们知道它是Throwable
的一个实例:
1)
logger.log(Level.ERROR, (Throwable) exceptionObj,
((Throwable) exceptionObj).getMessage());
2)
Throwable t = new Throwable((Throwable)exceptionObj);
logger.log(Level.ERROR, t, t.getMessage());
在我正在进行的项目的代码审查期间,一位评论者说第一种方式不如第二种方式有效,因为它涉及2个演员。我只是想知道你的想法。似乎创建一个新实例也会涉及一些开销。
答案 0 :(得分:12)
这两段代码做了不同的事情。在第二个中,您不再传递exceptionObj,而是“由exceptionObj引起的未指定的Throwable”。我认为这不是你想要的。
你的意思是第二行的第一行:
Throwable t = (Throwable) exceptionObj;
我猜,它的效率非常高,但不会让它决定这个问题。哪个更易读是关键,我认为(修改过的)第二个更具可读性。
你真的要向Throwable提起诉讼吗?当然记录器已经使用了Throwable吗?
答案 1 :(得分:6)
考虑到例外的成本而仅打印出内容,我建议这场辩论有点似是而非。
答案 2 :(得分:4)
为什么不施放一次并使用两次?
Throwable t = (Throwable) exceptionObj;
如果没有分析和使用重载,很难说出实际答案。
答案 3 :(得分:2)
Throwable t = (Throwable) exceptionObj; logger.log(Level.ERROR, t, t.getMessage());
答案 4 :(得分:1)
exceptionObj
为String
或Throwable
时进行编译。如果它是String
,那么第一个例子根本不会编译,如果它是Throwable
,那么在第一个例子中你的演员阵容是不必要的Throwable
只是为了避免强制转换,这是一件非常糟糕的事情,因为它会改变你的代码实际所做的事情。答案 5 :(得分:1)
logger.log(Level.ERROR, (Throwable) exceptionObj,
((Throwable) exceptionObj).getMessage());
理论上这将导致两种类型演员的成本。在实践中,JIT编译器可以很好地将其优化为仅执行一次类型转换的本机代码。
Throwable t = new Throwable((Throwable)exceptionObj);
logger.log(Level.ERROR, t, t.getMessage());
这里我们用一个类型转换和一个对象创建替换两个类型转换。但是,创建的对象是Throwable,如果您查看Throwable的构造函数,您会注意到它调用fillInStackTrace()
。此方法创建了一堆其他对象来记录有关堆栈的信息,这可能比执行(成功)类型转换更加更多。此外,这种类型转换很可能已被优化掉了。
显然,彻底调查需要分析两个版本的代码并检查JIT编译器生成的本机代码......
(正如其他人所说,两段代码的效果不同。第一段记录原始异常,第二段记录一个新的Throwable,原始异常作为嵌套异常。)