2

I tried to understand the behavior of initialization order when static fields are initialized with a reference to the same enclosing class object.

public class Test {

        static final Test t=new Test();
        static int a=5;

        Test(){
            System.out.println("a="+a);
        }

        public static void main(String[] args) {
            new Test();
        }

    }

Output of above piece of code is:

a=0
a=5

If I modify variable a to anything else other than plain static:

static final a=5;
a=5;
final a=5;

The output is:

a=5
a=5

Why is this behavior?

Note that the output is a=5 & a=5 even when both t & a are declared as static final in which case t precedes the declaration of a

ernesto
  • 1,899
  • 4
  • 26
  • 39

4 Answers4

4

static final members are initialized before other static members.

non final static members are initialized in order of appearance

Therefore, in your first case :

    static Test t=new Test();
    static int a=5;

The constructor is first called before a is initialized, so a=0 is displayed.

In the second case, static final a is initialized before t, so a=5 is displayed when the first instance of Test is created. When a is not static, it is initialized prior to the execution of the constructor, so again a=5 is displayed.

Regarding the edit in your question.

Looking at section 12.4.2 of the JLS :

  1. Then, initialize the final class variables and fields of interfaces whose values are compile-time constant expressions (§8.3.2.1, §9.3.1, §13.4.9, §15.28).

...

  1. Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.

You see that final class variables (i.e. static final) are initialized before the rest of the static variables only if their values are compile time constant expressions. 5 is a constant expression. new Test() is not. Therefore a is initialized before t even if both are static final.

Community
  • 1
  • 1
Eran
  • 387,369
  • 54
  • 702
  • 768
  • Thanks! But `t` should also be initialized before the execution of constructor? Isn't it looking like a cyclic dependency? Is there any defined behavior when Java encounters circular dependencies...? – ernesto Jan 09 '15 at 11:39
  • @ernesto The initialization of `t` causes a new instance to be created. When a new instance is created, the constructor is executed. The instance variables initialization statements are executed prior to the execution of the constructor. Therefore, when `a` is not static, it is initialized to 5 before the println statement. – Eran Jan 09 '15 at 11:50
  • I updated the question. The output is `a=5 & a-5` even when `t` is declared as `static final` which precedes the declaration of `a` – ernesto Jan 11 '15 at 09:26
1

Static variables are initialized when the class gets loaded by class loader. So when first line “static Test t=new Test();” gets executed, the value of int “a” is not yet initialized, hence it is showing as 0. But other 3 cases (i.e. removing static, adding final or without any modifier) what happens a gets initialized at the time of Object creation of Test class, which is happening in the first line so it is showing the value “5”.

1

Java Language specification is best source to understand all about initialization order. According to that in your scenario, static final field gets initialized before any class level variable gets initialized. When you remove the final, initialization was deferred. It should also be noted if you change

static Test t=new Test();
static int a=5;

to

  static int a=5;
  static Test t=new Test();

it will also print

 a = 5
 a = 5

because of initialization order.

sakthisundar
  • 3,278
  • 3
  • 16
  • 29
  • where in that specification did they tell `static final` will be initialized before anything else? – ernesto Jan 09 '15 at 11:56
  • OK, so point 6 indicates that `final` variables will be initialized before `static`. Let's say I have `static`, `final` and `static final` variables in my class, what's the order? – ernesto Jan 09 '15 at 12:00
  • Pretty sure its static final, then static, then final, then non-final. Within each group order is from top to bottom. – phil_20686 Jan 09 '15 at 12:13
  • final variables with values can not be changed at any point of time because they are compilation time constant expressions. So final variables, no matter class or instance level are initialized at the same level. When it comes to the case of blank finals, your initialization order differs(final variables' initialization can be deferred till the end of the initializer blocks) i.e first static then instance level. As constant expressions, you can not see which happens first because it follows textual order. – sakthisundar Jan 09 '15 at 12:16
  • I updated the question. The output is `a=5 & a-5` even when `t` is declared as `static final` which precedes the declaration of `a` – ernesto Jan 11 '15 at 09:25
0

static final a=5 It is final so it initialize first, before other static members or methods.

In first scenario main() method get executed first and it initializea to its default value 0.

atish shimpi
  • 4,873
  • 2
  • 32
  • 50