代码之家  ›  专栏  ›  技术社区  ›  Greg

(编译器)else if(true)vs else场景

  •  22
  • Greg  · 技术社区  · 9 年前

    获取以下Java代码片段:

    ....
        else if (true){ //hard-coded as true
         ///launch methodA
        }
        else {
         ///launch methodA (same code as in the ` else if ` statement)
        }
    ....
    

    我想知道的是编译器是如何处理这个问题的。编译器删除 else if(true) 语句,以便不必执行检查,即使它被硬编码为true。特别是在Eclipse中,上面的代码是如何解释的?

    或者在以下场景中:

    ....
        else if (true){ //hard-coded as true
         ///launch methodA
        }
        else {
         ///launch methodBB
        }
    ....
    

    在这种情况下,编译器删除 else 陈述因为在跑步时 其他的 语句无法访问。

    8 回复  |  直到 9 年前
        1
  •  21
  •   dotvav    9 年前

    无法访问的语句在Java中被禁止,并且必须触发编译错误。JLS定义了什么是无法访问的语句: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21

    这里太长了,不能完全引用,但这里有一个摘录( 强调 我的):

    if (false) { x=3; }
    

    不会导致编译时错误。优化编译器 也许 认识到陈述x=3;将永远不会被执行,并且 也许 选择 从生成的类文件中省略该语句的代码,但是 语句x=3;在技术上不被视为“无法达到” 此处指定的意义。

    这种不同处理方法的基本原理是允许程序员 定义“标志变量”,例如:

    static final boolean DEBUG = false;
    

    然后编写代码,例如:

    if (DEBUG) { x=3; }
    

    其思想是,应该可以将DEBUG的值从false更改为true或从true更改为false,然后正确编译代码,而不需要对程序文本进行其他更改。

    因此,答案将取决于您使用的编译器及其优化选项。

        2
  •  10
  •   Jean Logeart    9 年前

    编译器在编译时对其进行优化:

    public class Test {
        public static void main(String[] args) {
        if(true) {
            System.out.println("Hello");
        } else {
            System.out.println("Boom");
        }
    }
    

    给我(和我的 Java 1.8.0_45 ):

    Compiled from "Test.java"
    public class Test {
      publicTest();
        Code:
           0: aload_0
           1: invokespecial #1        // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: getstatic     #2        // Field java/lang/System.out:Ljava/io/PrintStream;
           3: ldc           #3        // String Hello
           5: invokevirtual #4        // Method java/io/PrintStream.println:(Ljava/lang/String;)V
           8: return
    }
    

    代码只是打印 Hello . Boom 甚至没有考虑。

    所有最新的Java编译器都在编译时消除了死代码。

        3
  •  3
  •   M. Reif    9 年前

    这个问题没有特别的答案。这取决于Java编译器。 大多数编译器忽略死代码,因为它不会改变代码的语义,即使它会导致更大的类文件。

    如果你对这样的分析感兴趣,有很多关于消除死代码的文献。

        4
  •  3
  •   uoyilmaz    9 年前

    您可以尝试编写代码并反编译类文件。我的编译器优化了

    else if (true){ //hard-coded as true
     ///launch methodA
    }
    else {
     ///launch methodA (same code as in the else if statement)
    }
    

    else {
     ///launch methodA
    }
    

    else if (true){ //hard-coded as true
     ///launch methodA
    }
    else {
     ///launch methodBB
    }
    

    其他{
    ///启动方法A
    }
    

    我认为所有编译器版本都会以这种方式优化它。

        5
  •  2
  •   dtortola    9 年前

    特别是关于Eclipse,它将警告您最后一个else块是不可访问的,但是编译被委托给您的jdk,所以可能是编译器警告Eclipse。

        6
  •  2
  •   Roshana Pitigala Laxmansinghsodhanohdiyala    6 年前

    现在我在eclipse中编写代码,我的方法是

    public static void aa(String b) {
      if (true) {
    
      } else if (true) {
        System.out.println("asas");
      } else {
      }
    }
    

    在我编译了代码之后,我用JD-GUI反编译了代码。我的反编译代码是:

    public static void aa(String b) {}
    

    结果很好!

        7
  •  1
  •   user207421    9 年前

    编译器完全删除else-if(true)语句,以便不必执行检查,即使它被硬编码为true,这难道不符合逻辑吗。

    不,它不会,除非两个块都有相同的内容,为什么要检查它?这在语义上是不正确的。编译器删除最后一个不可访问的 else ,这就是它的作用。

        8
  •  0
  •   Community CDub    8 年前

    相关答案: Java If(false) Compile

    请参阅有关使用javap-c诊断字节码以查看是否实际上消除了死代码的特别说明。 https://stackoverflow.com/a/6240017/679457