Java 两次强制转换或创建新实例是否更有效

Java 两次强制转换或创建新实例是否更有效,java,casting,Java,Casting,考虑这两段代码(您可以假设execeptionObj属于Object类型,但我们知道它是Throwable的一个实例): (一) (二) 在我正在进行的一个项目的代码评审中,一位评审员说第一种方法不如第二种方法有效,因为它涉及两个类型转换。我只是想知道你是怎么想的。创建一个新实例似乎也会涉及一些开销。考虑到一个异常的成本以及仅仅打印出内容的成本,我认为这场辩论有点似是而非 考虑到一个例外和仅仅打印内容的成本,我认为这场辩论有点似是而非 这两段代码做不同的事情。在第二种情况下,您不再传递excep

考虑这两段代码(您可以假设
execeptionObj
属于
Object
类型,但我们知道它是
Throwable
的一个实例):

(一)

(二)


在我正在进行的一个项目的代码评审中,一位评审员说第一种方法不如第二种方法有效,因为它涉及两个类型转换。我只是想知道你是怎么想的。创建一个新实例似乎也会涉及一些开销。

考虑到一个异常的成本以及仅仅打印出内容的成本,我认为这场辩论有点似是而非

考虑到一个例外和仅仅打印内容的成本,我认为这场辩论有点似是而非

这两段代码做不同的事情。在第二种情况下,您不再传递exceptionObj,而是“由exceptionObj引起的未指定的丢弃”。我认为那不是你想要的

你是说第二行的第一行是:

Throwable t = (Throwable) exceptionObj;
我想它的效率会稍微高一些,但不会让它决定问题。哪个更具可读性是关键,我认为(修改后的)第二个更具可读性


你真的要把箱子扔掉吗?当然,记录器已经可以丢弃了吗?

这两段代码做了不同的事情。在第二种情况下,您不再传递exceptionObj,而是“由exceptionObj引起的未指定的丢弃”。我认为那不是你想要的

你是说第二行的第一行是:

Throwable t = (Throwable) exceptionObj;
我想它的效率会稍微高一些,但不会让它决定问题。哪个更具可读性是关键,我认为(修改后的)第二个更具可读性

你真的要把箱子扔掉吗?那伐木工人肯定已经被抛弃了

  • 您将注意到这两者之间几乎没有性能差异。特别是因为异常处理代码很可能不会在紧密循环中运行
  • 示例2仅在
    exceptionObj
    字符串或
    可丢弃的
    时编译。如果是
    字符串
    ,则第一个示例根本无法编译,如果是
    可丢弃的
    ,则在第一个示例中不需要强制转换
  • 创建一个新的
    Throwable
    以避免强制转换是一件可怕的事情,因为它改变了代码的实际功能
  • 您将注意到这两者之间几乎没有性能差异。特别是因为异常处理代码很可能不会在紧密循环中运行
  • 示例2仅在
    exceptionObj
    字符串或
    可丢弃的
    时编译。如果是
    字符串
    ,则第一个示例根本无法编译,如果是
    可丢弃的
    ,则在第一个示例中不需要强制转换
  • 创建一个新的
    Throwable
    以避免强制转换是一件可怕的事情,因为它改变了代码的实际功能
  • 可丢弃t=(可丢弃)例外bj; logger.log(Level.ERROR,t,t.getMessage()); 可丢弃t=(可丢弃)例外bj; logger.log(Level.ERROR,t,t.getMessage());
    为什么不施放一次并使用两次呢

    Throwable t = (Throwable) exceptionObj;
    

    如果不分析并使用重载,就很难说出实际答案。

    为什么不施放一次并使用两次呢

    Throwable t = (Throwable) exceptionObj;
    
    logger.log(Level.ERROR, (Throwable) exceptionObj,
        ((Throwable) exceptionObj).getMessage());
    
    如果不分析和使用重载,就很难说出实际答案

    logger.log(Level.ERROR, (Throwable) exceptionObj,
        ((Throwable) exceptionObj).getMessage());
    
    从理论上讲,这将导致两种类型铸件的成本。实际上,JIT编译器可能会将其优化为只执行一次类型转换的本机代码

    Throwable t = new Throwable((Throwable)exceptionObj);
    logger.log(Level.ERROR, t, t.getMessage());
    
    这里我们用一个类型转换和一个对象创建替换两个类型转换。但是,创建的对象是可丢弃的,如果您查看Throwable的构造函数,您会注意到它调用
    fillInStackTrace()
    。此方法创建一组其他对象来记录有关堆栈的信息,这可能比执行(成功的)类型转换要昂贵得多。此外,这个类型转换很有可能已经被优化掉了

    显然,彻底的调查需要分析两个版本的代码,并检查JIT编译器生成的本机代码

    (正如其他人所指出的,这两段代码的效果是不同的。第一段记录原始异常,第二段记录新的Throwable,原始异常作为嵌套异常。)

    从理论上讲,这将导致两种类型铸件的成本。实际上,JIT编译器可能会将其优化为只执行一次类型转换的本机代码

    Throwable t = new Throwable((Throwable)exceptionObj);
    logger.log(Level.ERROR, t, t.getMessage());
    
    这里我们用一个类型转换和一个对象创建替换两个类型转换。但是,创建的对象是一个Throwable,如果查看Throwable的构造函数,您会注意到它调用
    fillInStackTrace()
    。此方法创建一组其他对象来记录有关堆栈的信息,这可能比执行(成功的)类型转换要昂贵得多。此外,这个类型转换很有可能已经被优化掉了

    显然,彻底的调查需要分析两个版本的代码,并检查JIT编译器生成的本机代码


    (正如其他人所指出的,这两段代码的效果是不同的。第一段记录原始异常,第二段记录新的Throwable,原始异常作为嵌套异常。)

    不,我是说我写的。下面是评论员的原话:“你最好创建一个实例,使用2个casting是没有效率的”。强制转换是必要的,因为我正在为日志调用使用以下签名:Log.Log(Level,Throwable,String)@dcp:casting两次总是比创建对象快得多。此外,“创建实例”代码也无法编译。@dcp By usi