Static variables are initialized in the order that they are encountered in the source. So, if you try to use a static variable to initialize another static variable, and that variable is later in source, then you will get the default value.
Final variables that are initialized during declaration, to a compile time constant, are themselves, compile time constants. And since the compiler knows their value are compile time, it is always correct.
The order is important. If you omit final in the first example, the instance is created before a is given its value of 5. That's why it prints 0 - before the main method is even executed. By making the field final you're turning it into a compile time constant, and compile time constants get substituted by the compiler. In the compiled code with the final keyword in place, field "a" no longer exists. Instead line 8 says "System.out.println(5);".