是否更有效地投射两次或创建新实例

时间:2010-03-04 10:05:48

标签: java casting

考虑这两段代码(您可以假设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个演员。我只是想知道你的想法。似乎创建一个新实例也会涉及一些开销。

6 个答案:

答案 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)

  1. 你会发现两者之间几乎没有性能差异。特别是因为它是异常处理代码,很可能不会在紧密循环中运行
  2. 示例2仅在exceptionObjStringThrowable时进行编译。如果它是String,那么第一个例子根本不会编译,如果它是Throwable,那么在第一个例子中你的演员阵容是不必要的
  3. 创建一个新的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,原始异常作为嵌套异常。)