I wrote this simple Test class to see how Java evaluates boolean algebra at the Bytecode level:
public class Test { private static boolean a, b; public static boolean method1(){ return !(a || b); } public static boolean method2(){ return !a && !b; } } If you simplify method1() using DeMorgan's Laws, you should get method2(). After looking at the Bytecode (using javap -c Test.class), it looks like:
Compiled from "Test.java" public class Test { public Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>": ()V 4: return public static boolean method1(); Code: 0: getstatic #2 // Field a:Z 3: ifne 16 6: getstatic #3 // Field b:Z 9: ifne 16 12: iconst_1 13: goto 17 16: iconst_0 17: ireturn public static boolean method2(); Code: 0: getstatic #2 // Field a:Z 3: ifne 16 6: getstatic #3 // Field b:Z 9: ifne 16 12: iconst_1 13: goto 17 16: iconst_0 17: ireturn } So my question is, why is method1() and method2() exactly the same at the Bytecode level?
What your seeing is a compiler optimization. When javac encounters method1() it applies an optimization (based on De Morgan's Laws as you pointed out but also short circuiting the && comparison) that allows it to branch early if a is true (thus no need to evaluate b).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With