javac treating static final differently based on a

2020-06-18 09:20发布

问题:

When I compile:

public static final boolean FOO = false;
public static final void fooTest() {
    if (FOO) {
        System.out.println("gg");
    }
}

I get an empty method fooTest() {}. However when I compile:

static boolean isBar = false;
public static final boolean BAR = isBar;
public static final void fooTest() {
    if (BAR) {
        System.out.println("gg");
    }
}

the if statement is included in the compiled class file. Does this mean there are two different "types" of static final in java, or is this just a compiler optimization?

回答1:

In the first case, the compiler does an optimization. It knows Foo will always be false and kill the code than will never be reached.

In the second case, you are assigning the value of the non-final variable isBar to BAR. The compiler can't tell if the variable isBar has been modified somewhere else, especially if it is not private. Therefore it is not sure of the value of BAR. Therefore he can not do the optimization.



回答2:

It is purely a case of compiler optimization where it ignores a direct assignment and does consider indirect assignment of literals.



回答3:

In the first case static final fields are constants which are known at compile time. So the compiler optimizes and inlines the constant.

In the second case the field is non-final variable and cannot be inlined by the compiler as it can change.

class Test{
   public static final boolean BOOL = true; //CONSTANT KNOWN AT COMPILE TIME


   public void someMethod(){
         while(BOOL){
             //some code
         }
   }


   //OPTIMIZED VERSION DONE BY COMPILER
   public void someMethod(){
        while(true){   //There is no need for accessing BOOL if it is not going to change and compiler understands that so inlines the value of constant


        }
   }

}

You can look at the compiled code using some de-compiler tools and you will find the optimized method that I have written in the class file.



回答4:

There could be only one existing static value within the memory. In the first block, the static final variable FOO is set false value which in known to the compiler and hence it optimizes the if statement in it. But in second statement, the BAR final static variable is assigned isBar static variable value, which in turn makes the compiler not to optimize the if statement (since isBar could be any Boolean value and it cannot be determined because java supports polymorphism and values are assigned to variables dynamically during run time.), hence static variables memory position in the second block is important to the compiler to determine its value, where as in the first block the value false is known without any assignment between different variables and it is optimized.