Will Java Final variables have default values?

http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html, chapter "Initializing Instance Members":

The Java compiler copies initializer blocks into every constructor.

That is to say:

{
    printX();
}

Test() {
    System.out.println("const called");
}

behaves exactly like:

Test() {
    printX();
    System.out.println("const called");
}

As you can thus see, once an instance has been created, the final field has not been definitely assigned, while (from http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.2):

A blank final instance variable must be definitely assigned at the end of every constructor of the class in which it is declared; otherwise a compile-time error occurs.

While it does not seem to be stated explitely in the docs (at least I have not been able to find it), a final field must temporary take its default value before the end of the constructor, so that it has a predictable value if you read it before its assignment.

Default values: http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5

On your second snippet, x is initialized on instance creation, so the compiler does not complain:

Test() {
    printX();
    x = 7;
    printX();
    System.out.println("const called");
}

Also note that the following approach doesn't work. Using default value of final variable is only allowed through a method.

Test() {
    System.out.println("Here x is " + x); // Compile time error : variable 'x' might not be initialized
    x = 7;
    System.out.println("Here x is " + x);
    System.out.println("const called");
}

JLS is saying that you must assign the default value to blank final instance variable in constructor (or in initialization block which is pretty the same). That is why you get the error in the first case. However it doesn't say that you can not access it in constructor before. Looks weird a little bit, but you can access it before assignment and see default value for int - 0.

UPD. As mentioned by @I4mpi, JLS defines the rule that each value should be definitely assigned before any access:

Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.

However, it also has an interesting rule in regards to constructors and fields:

If C has at least one instance initializer or instance variable initializer then V is [un]assigned after an explicit or implicit superclass constructor invocation if V is [un]assigned after the rightmost instance initializer or instance variable initializer of C.

So in second case the value x is definitely assigned at the beginning of the constructor, because it contains the assignment at the end of it.


If you don't initialize x you'll get a compile-time error since x is never initialized.

Declaring x as final means that it can be initialized only in the constructor or in initializer-block (since this block will be copied by the compiler into every constructor).

The reason that you get 0 printed out before the variable is initialized is due to the behavior defined in the manual (see: "Default Values" section):

Default Values

It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.

The following chart summarizes the default values for the above data types.

Data Type   Default Value (for fields)
--------------------------------------
byte        0
short       0
int         0
long        0L
float       0.0f
double      0.0d
char        '\u0000'
String (or any object)      null
boolean     false