java - 编译器如何处理选择语句变体

标签 java compiler-construction jvm javac bytecode

下面的所有三种方法在功能上都是相同的 - 但是它们都有我认为的风格差异。当这些被编译时,编译器是否会区别对待它们? (我缺乏检查和理解反编译字节码的知识)

// Method 1
private boolean isAcceptableRange(final int a, final int b) {       
    if ((Math.abs(a - b)) <= range) {
        return true;
    } else {
        return false;
    }
}

// Method 2
private boolean isAcceptableRange(final int a, final int b) {       
    if ((Math.abs(a - b)) <= range) {
        return true;
    }
    return false;
}

// Method 3
private boolean isAcceptableRange(final int a, final int b) {
    if ((Math.abs(a - b)) <= range)
        return true;
    return false;
}

我最初的想法是,由于额外的 else 子句,#1 将是唯一的,其中 #2 和 #3 最终将是相同的。这意味着在优化磁盘/ROM 空间效率和可能的指令效率(考虑嵌入式)时,请使用选项 #2 或 #3。

或者编译器是否知道最终结果并“优化”它?

最佳答案

Or does the compiler know the end result and "optimize" it away?

是的,确实如此。让我们看看生成的字节码:

javap -c -private MyClass.class
  • javap:是一个工具(除其他外)可以让您查看 java 类的字节码,它随 JDK 一起提供。
  • -c:将代码反汇编为字节码
  • -private:显示类中的私有(private)成员和方法。
  • MyClass.class:编译后的类
<小时/>
private boolean isAcceptableRange1(int, int);
    Code:
       0: iload_1       
       1: iload_2       
       2: isub          
       3: invokestatic  #1                  // Method java/lang/Math.abs:(I)I
       6: aload_0       
       7: getfield      #2                  // Field range:I
      10: if_icmpgt     15
      13: iconst_1      
      14: ireturn       
      15: iconst_0      
      16: ireturn       

  private boolean isAcceptableRange2(int, int);
    Code:
       0: iload_1       
       1: iload_2       
       2: isub          
       3: invokestatic  #1                  // Method java/lang/Math.abs:(I)I
       6: aload_0       
       7: getfield      #2                  // Field range:I
      10: if_icmpgt     15
      13: iconst_1      
      14: ireturn       
      15: iconst_0      
      16: ireturn       

  private boolean isAcceptableRange3(int, int);
    Code:
       0: iload_1       
       1: iload_2       
       2: isub          
       3: invokestatic  #1                  // Method java/lang/Math.abs:(I)I
       6: aload_0       
       7: getfield      #2                  // Field range:I
      10: if_icmpgt     15
      13: iconst_1      
      14: ireturn       
      15: iconst_0      
      16: ireturn  

我调用了方法isAcceptableRange1isAcceptableRange2isAcceptableRange3。正如您所看到的,所有方法都具有完全相同的字节码。

关于java - 编译器如何处理选择语句变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25146628/

相关文章:

java - 编译 Java 类时禁用编译时依赖性检查

java.net.UnknownHostException 在将日期更改为 future 之后发生

java - 使用 Java 高效地对数据库中的数据进行排序?

java - "Java HotSpot(TM) 64-Bit Server VM warning: Failed to reserve shared memory. (errno=12)"

compiler-construction - Visual Studio Code 到底是什么?

java - 使用用户定义的注释生成编译器警告

java - 动态编译依赖于特定类加载器加载的类的java代码

java - 更改字符串 xml hiperlink 的颜色而不覆盖样式

java - aws.accessKeyId 和 aws.secretKey 未被读取

c# - Roslyn 中的代理缓存行为更改