As discussed here, javac and other Java compilers may provide code elimination capabilities for if
-statements where the condition is a "Constant Expression".
How is this affected if my code uses a constant expression that depends on other constant expressions defined in different packages?
For example, let's say I have the following classes in the respective specified packages:
package foo;
public class Foo {
public static final boolean CONDITION = false;
}
and
package bar;
import foo.Foo;
public class Bar {
public void test() {
if (Foo.CONDITION) {
System.out.println("This line of code could be eliminated.");
} else {
System.out.println("This line of code will be executed.");
}
}
}
Clearly, if the foo
-package is loaded at run-time from an external jar-file, the compiler can't technically just assume that Foo.CONDITION
will be false and should not eliminate the true
-branch of the if
-statement.
Whereas, if Foo
and Bar
were actually in the same package, the true
-branch should definitely be eliminated (if the compiler supports code elimination at all).
Not quite sure how to best phrase this question, but: How "close" does Foo
need to be to Bar
for a constant expression in Foo
to also be considered constant in Bar
? Would they need to be in the same file? the same package? the same jar-file? or does it not matter at all (i.e. would the compiler always consider Foo.CONDITION
as constant and use the value found in the build-path during compile time)?
A constant expression is an expression that yields a primitive type or a String, and whose value can be evaluated at compile time to a literal. The expression must evaluate without throwing an exception, and it must be composed of only the following: Primitive and String literals.
Eclipse compiler for Java (ECJ) is open source incremented compiler. We reform features of ECJ, related to optimization technique called as dead code detection and elimination. ECJ identifies the dead code. We are extending this compiler to eliminate the dead code.
public static final variables are also known as a compile-time constant, the public is optional there. They are replaced with actual values at compile time because compiler know their value up-front and also knows that it cannot be changed during run-time.
Compile Time Errors are those errors which prevent the code from running because of an incorrect syntax such as a missing semicolon at the end of a statement or a missing bracket, class not found, etc. These errors are detected by the java compiler and an error message is displayed on the screen while compiling.
Since it's part of the public "signature" of the referenced class, it is assumed to be constant. Essentially the idea is that final
means final, and if you change it, it's your fault.
This is similar to actual method signatures of referenced classes, also taken as-is at compile time. Which is why if you compile your code against one version of a library and run it against another, you might get a NoSuchMethodError
.
Update: Actually the JLS gives an even stronger guarantee:
If a field is a constant variable (§4.12.4), then deleting the keyword final or changing its value will not break compatibility with pre-existing binaries by causing them not to run, but they will not see any new value for the usage of the field unless they are recompiled. This is true even if the usage itself is not a compile-time constant expression (§15.28).
This result is a side-effect of the decision to support conditional compilation, as discussed at the end of §14.21.
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