(编译器)否则if(true)vs else scenario

Gre*_*reg 22 java compiler-construction if-statement language-lawyer

获取以下Java代码段:

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

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

或者在以下场景中如何:

....
    else if (true){ //hard-coded as true
     ///launch methodA
    }
    else {
     ///launch methodBB
    }
....
Run Code Online (Sandbox Code Playgroud)

在这种情况下编译器删除else语句不是合乎逻辑的吗?因为在运行时,else语句无法访问.

dot*_*vav 21

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

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

if (false) { x=3; }
Run Code Online (Sandbox Code Playgroud)

不会导致编译时错误.优化编译器可以 实现语句x = 3; 将永远不会执行,并可能选择从生成的类文件中省略该语句的代码,但语句x = 3; 在此处指定的技术意义上,不被视为"无法到达".

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

static final boolean DEBUG = false;
Run Code Online (Sandbox Code Playgroud)

然后编写如下代码:

if (DEBUG) { x=3; }
Run Code Online (Sandbox Code Playgroud)

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

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

  • 除此之外,如果程序员有一个像`static boolean enableLogging;`实际上*用作变量*的变量*以后不能将它更改为`static final boolean elableLogging = false;`而不必手动编辑读取它的所有代码. (2认同)

Jea*_*art 10

编译器在编译时优化它:

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

给我(和我一起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
}
Run Code Online (Sandbox Code Playgroud)

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

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