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

(Compiler) else if(true) vs else scenario

采用以下 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 语句是否合乎逻辑?因为while 运行,else语句是不可达的。

特别是关于 Eclipse,它会警告您最后一个 else 块无法访问,但编译已委托给您 jdk,所以可能是编译器警告了 Eclipse。

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

如果您对此类分析感兴趣,有很多关于消除死代码的文献。

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

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
}

作为

else {
 ///launch methodA
}

我想所有的编译器版本都会这样优化的

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

这里太长了,无法完整引用,但这里是摘录(重点我的):

if (false) { x=3; }

does not result in a compile-time error. An optimizing compiler may realize that the statement x=3; will never be executed and may choose to omit the code for that statement from the generated class file, but the statement x=3; is not regarded as "unreachable" in the technical sense specified here.

The rationale for this differing treatment is to allow programmers to define "flag variables" such as:

static final boolean DEBUG = false;

and then write code such as:

if (DEBUG) { x=3; }

The idea is that it should be possible to change the value of DEBUG from false to true or from true to false and then compile the code correctly with no other changes to the program text.

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

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

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
}

代码只打印 HelloBoom连考虑都没有。

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

现在用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) {}

效果很好!

Wouldn't it be logical for the compiler to remove the else if(true) statement altogether in order to not have to perform a check, even though it is hard-coded as true.

不,它不会,除非两个块具有相同的内容,它为什么要检查那个?这在语义上是不正确的。合乎逻辑的是编译器删除最终无法访问的 else,这就是它所做的。

相关回答:Java If(false) Compile

请参阅有关使用 javap -c 诊断字节码以查看死代码是否实际上已被消除的特别说明。