Q:

Initialization of static final fields in Java

public class Main {
 static final int alex=getc();
 static final int alex1=Integer.parseInt("10");
 static final int alex2=getc();

public static int getc(){
    return alex1;
}

public static void main(String[] args) {
    final Main m = new Main();
    System.out.println(alex+" "+alex1 +" "+alex2);
  } 
}

Can someone tell me why this prints: 0 10 10? I understand that it's a static final variable and its value shouldn't change but it`s a little difficult to understand how the compiler initializes the fields.

A:

It's an ordering problem.  Static fields are initialized in the order that they are encountered, so when you call getc() to inititalize the alex variable, alex1 hasn't been set yet.  You need to put initialization of alex1 first, then you'll get the expected result.

A:

This situation is covered by JLS 8.3.2.3 "Restrictions on the use of Fields during Initialization".
The JLS rules allows the usage in your Question, and state that the first call to getc() will return default (uninitialized) value of alex.
However, the rules disallow some uses of uninitialized variables; e.g.
int i = j + 1;
int j = i + 1;

is disallowed.

Re some of the other answers.  This is not a case where the Java compiler "can't figure it out".  The compiler is strictly implementing what the Java Language Specification specifies.  (Or to put it another way, a compiler could be written to detect the circularity in your example and call it a compilation error.  However, if it did this, it would be rejecting valid Java programs, and therefore wouldn't be a conformant Java compiler.)

In a comment you state this:

... final fields always must be initialized at compile or at runtime before the object creation.

This is not correct.
There are actually two kinds of final fields:

A so-called "constant variable" is indeed evaluated at compile time.  (A constant variable is a variable "of primitive type or type String, that is final and initialized with a compile-time constant expression" - see JLS 4.12.4.).  Such a field will always have been initialized by the time you access it ... modulo certain complications that are not relevant here.
Other final fields are initialized in the order specified by the JLS, and it is possible to see the field's value before it has been initialized.  The restriction on final variables is that they must be initialized once and only once during class initialization (for a static) or during object initialization.

Finally, this stuff is very much "corner case" behavior.  A typical well-written class won't need to
access a final field before it has been initialized.

A:

Static final fields whose values are not compile-time constant expressions are initialized in order of declaration. Thus when alex in being initialized, alex1 is not initialized yet, so that getc() returns default values of alex1 (0).
Note that result will be different (10 10 10) in the following case:
static final int alex1 = 10;

In this case alex1 is initialized by a compile-time constant expression, therefore it's initialized from the very beginning.

