Thursday, 26 January 2012

Compile Time Constants in Java

Compile Time Constant means at the time of compilation itself ,the compiler can understands the value of a final variable and acts as 'literal' value.So it will reduce some run-time overhead.General rules for a compile time constants are 
  • They must be declared final
  • They are of primitive data types or String
  • They must be initialized with their declaration.
  • Their value must be constant expression.

Final variables of primitive data types and Strings can be compile time constants. No other type of variables are compile time constants, not even the wrapper classes. They must also be initialized with their declaration, otherwise they’ll not be compile time constants. Lets take a few examples. 

All of the following are compile time constants,

class CompileTimeConstant{
final float PI=3.14f;
final String NATIONALITY="Indian";
final int X=10;
final int Y=20;
final int Z=X+Y;
final int S="Hello"+"World";
}

The following are not compile time constants,

class NotCompileTimeConstant{
final Integer i=10;
final MyClass my=new MyClass();
int X=10;
int Y=20;
final int Z=X+Y;
String s="Hello";
final String str=s+"Welcome";
}
We can also create constants in java whose value can be set at the run-time (blank final in java).They are also not the compile time constants.See the example given below

class RuntimeConstant{
final int X;
final static int Y;
static{
Y=10;
}
RuntimeConstant(int x){
X=x;
}
void int getBalance(final int accno){
}
void display(){
final int X;
X=10;
}
}

What’s So special About Compile Time Constants

1) implicit downcasted (just like literals).
int x=10;

char y=x;
The above statements generates compilation error, Type mismatch: cannot convert from int to char.But compile-time constants support implicit downcast just like literals.
final int x=10;

char y=x;
It will work without any compilation error.

2) compile time constants can be used as switch case values.

int x=10;
switch(10){
case x: //compilation error
        . 
        break;
     }
Here you will get compilation error,case expressions must be constant expressions.If you use compile time constants,it will work correctly.

final int x=10;
switch(10){
case x: //compilation error
        . 
        break;
     }


Both the behaviors that we observed above i.e. implicit downcast and case labels are because of a common reason. Wherever you use a compile time constant, the compiler replaces their use with their actual value. So if I write this code,

final int i = 10;
short j = i;
System.out.println(i);
After compilation it will become,

final int i = 10;
short j = 10;System.out.println(10)
;


As you can see, at both the places where we used i, the compiler replaced it with its value 10. This is the reason why they can be used as case values and that is why they are implicitly downcasted. This replacing of value has serious implications in some cases. Suppose I have two classes in two different files like this,
public class ConstantClass {
    public static final int MY_CONST = 10;
}
public class Main {
    public static void main(String[] args) {
        System.out.println(ConstantClass.MY_CONST);
    }
}
Now if I compile both classes and run Main class, the output will be 10. Since MY_CONST is a compile time constant, so the compiler replaces it with its value in the main method. Now I go and change the value of MY_CONST to 20 and compile only ConstantClass class. Then I run the Main class (without compiling it again), the output will still be 10 i.e. the value of MY_CONST when Main class was compiled. We’ll have to recompile Main class to see the new value of MY_CONST as the output.

No comments:

Post a Comment