Search code examples
javabytecode

Why is method1 and method2 the same at the Bytecode level?


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?


Solution

  • 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).