(编译器)否则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