(编译器)否则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语句不是合乎逻辑的吗? 因为在运行时, else语句无法访问。

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,然后正确编译代码而不对程序文本进行其他更改。

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

编译器在编译时选择它:

 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."":()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编译器都在编译时消除了死代码。

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

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

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

 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 } 

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

特别是关于Eclipse,它会警告你最后一个else块无法访问,但编译被委托给你的jdk,所以也许是编译器警告Eclipse。

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

结果非常好!

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

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

相关回答: Java If(false)编译

请特别注意使用javap -c诊断字节码以查看死代码是否实际被消除。 https://stackoverflow.com/a/6240017/679457