68

Could anyone explain how Java executes this code? I mean the order of executing each statement.

public class Foo
{
    boolean flag = sFlag;
    static Foo foo = new Foo();
    static boolean sFlag = true;

    public static void main(String[] args)
    {
        System.out.println(foo.flag);
    }
}

OUTPUT:

false
Eng.Fouad
  • 115,165
  • 71
  • 313
  • 417
  • 4
    We are human, not computer. Should we try to make code more straightforward rather than using these sort of tricks or traps or whatever... – Don Li May 17 '12 at 07:31
  • 1
    +1 because it's not a difficult but good question, which I'm sure will help others in understanding the language and especially the static modifier better. Very useful answer given by @JonSkeet on a somewhat important - but often underestimated - topic. – jorey May 19 '12 at 02:09
  • 1
    I dislike it when people use 'Foo'. Use real terms :/ – contactmatt May 22 '12 at 19:57

5 Answers5

104
  • Class initialization starts. Initially, foo is null and sFlag is false
  • The first static variable initializer (foo) runs:
    • A new instance of Foo is created
    • The instance variable initializer for flag executes - currently sFlag is false, so the value of flag is false
  • The second static variable initializer (sFlag) executes, setting the value to true
  • Class initialization completes
  • main runs, printing out foo.flag, which is false

Note that if sFlag were declared to be final it would be treated as a compile-time constant, at which point all references to it would basically be inlined to true, so foo.flag would be true too.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Does it matter the order in which the variables are defined in the class ? i.e. if `flag` was defined after `sflag`? – Naveen May 16 '12 at 07:36
  • @Naveen IMHO, I don't think so. static variables will be initialized first. – Eng.Fouad May 16 '12 at 07:38
  • 1
    @Naveen: The order matters in that if `sFlag` were declared before `foo`, that would matter - but `sFlag` and `flag` order doesn't matter. – Jon Skeet May 16 '12 at 07:42
  • 5
    static members are initialised in the order they are declared. If you declare sFlag before the instance is created then the output would be true. – Drona May 16 '12 at 07:44
  • @Jon, could you give a bit more info on why the value of ***foo.flag*** would have been true if ***sFlag*** was declared final? seems confusing to me since the assignment to ***flag*** always happens before the initilization of ***Sflag*** Thanks – Cong Hui May 22 '12 at 18:32
  • 1
    @ClintHui: Compile-time constants have their constant values used wherever the constant field is referred to, rather than actually accessing the field... so it wouldn't matter that the field wasn't actually set to its value yet. – Jon Skeet May 22 '12 at 18:33
12

foo is instantiated during the static initialization of the class, and before sFlag was initialized, and the default value of a boolean is false.

  1. The class is loaded
  2. Foo is initialized to the instance

    2.a The instance member flag is initialized to the value of sFlag (false by default)

  3. sFlag is initialized to true

Please refer to JLS §12.4 for more details.

MByD
  • 135,866
  • 28
  • 264
  • 277
5

When class is loaded, sFlag and foo fields are initialized but foo is initialized first!
fields flag and sFlag are boolean and can't be null so by default there're false and sFlag is still false when foo is being initialized. flag = sFlag after this flag is false.That's it

shift66
  • 11,760
  • 13
  • 50
  • 83
2

The general order of initialization operations is (after the class is loaded and before first use):

  1. Static (class) code blocks in order it appears in the code,
  2. Object code blocks in order it appears in the code (initialization blocks and assignments).
  3. Constructors

Certainly I don't refer constructors and functions body as a code block above .

I don't know how about final static fields. It looks like they follow the rules of static fields and they cannot be referenced before declaration despite previous comments that they are initialized at compilation step. If they are referenced before there is a compilation error:

Example.java:8: illegal forward reference
        System.err.println("1st static block j=" + j);

Maybe final static fields can be initialized and compiled into the class file but this is not a general rule and they still cannot be referenced before declaration.

Example code to check initialization order:

class Example {    

    final static int j = 5;

    {
        System.err.println("1st initializer j=" + j);
    }

    static {
        System.err.println("1st static block j=" + j);
    }

    static {
        System.err.println("2nd static block j=" + j);
    }

    final static java.math.BigInteger i = new java.math.BigInteger("1") {    
        {
            System.err.println("final static anonymous class initializer");
        }
    };

    Example() {
        System.err.println("Constructor");
    }

    static {
        System.err.println("3nd static block j=" + j);
    }

    {
        System.err.println("2nd initializer");
    }

    public static void main(String[] args) {
        System.err.println("The main beginning.");
        Example ex = new Example();
        System.err.println("The main end.");
    } 
}

The above code snipset prints:

1st static block j=5
2nd static block j=5
final static anonymous class initializer
3nd static block j=5
The main beginning.
1st initializer j=5
2nd initializer
Constructor
The main end.
digital_infinity
  • 534
  • 6
  • 20
1

at first static fields should run and at first inline! so at first line 4 and then 5 will run so foo is initialized first and as we know boolean variables are initialized to false by default so at first so as the foo is initialized the field of flag is sflag that's false and then sfalsg becomes true that won't change flag( there's no relation) then at last main runs and print falg that is false!!! I hope to be useful! Be successful

F M
  • 35
  • 4