14
class abc {
    int a = 0;
    static int b;
    static abc h = new abc(); //line 4

    public abc() {
        System.out.println("cons");
    }

    {
        System.out.println("ini");
    }

    static {
        System.out.println("stat");
    }
}

public class ques {
    public static void main(String[] args) {
        System.out.println(new abc().a);
    }
}

When i wrote this code I am getting output in order like this:

ini
cons
stat
ini
cons
0

Here when I created a new object in main(), class abc got loaded and static variables and blocks are executed in order they are written. When control came to line 4 static abc h = new abc(); Instance Initialization block is called. Why? why is static block not called when a new object is created at line 4 and till that time static block was also not called even once, so according to convention static block should have been called. Why is this unexpected output coming?

Konstantin V. Salikhov
  • 4,554
  • 2
  • 35
  • 48
Shashank Agarwal
  • 1,122
  • 1
  • 8
  • 24
  • 1
    possible duplicate of [Java static class initialization](http://stackoverflow.com/questions/3499214/java-static-class-initialization) – DavidPostill Jul 24 '14 at 07:28
  • Static code is run only once so when the second object is created (inside the first one) it is not executed. I am surprised that `ini` is executed at this point though. – Eypros Jul 24 '14 at 07:37
  • 2
    @DavidPostill- Tagged post clears the concept that how static initialization normally happens. But my main ques is that why static block is not called at line 4 and instead Instance Initialization block was called. – Shashank Agarwal Jul 24 '14 at 07:37
  • 1
    As I debug your code, I can see that at line 4 static block is called and that is only place it will be called due to static initialization. If you remove the static member static block is called first. – Maas Jul 24 '14 at 07:41
  • @Duncan I just wanted to make the instance initializer easier to see, but I will not argue if you say so. In retrospect, you are actually right, I should have added 1 newline not 2. – EpicPandaForce Jul 24 '14 at 07:45
  • @ShashankAgarwal when class abc called it first check it's static and your static block is after your static object so first it create the static object and due to this object creation the `ini` and then `cons` is executed and then the next static i.e your static block. – amit bhardwaj Jul 24 '14 at 07:46
  • @ShashankAgarwal Konstantin V. Salikhov answer explain this very well take a look at it – amit bhardwaj Jul 24 '14 at 07:49
  • @amitbhardwaj- Thanks! Dont you think Didier L answer is more accurate.? – Shashank Agarwal Jul 24 '14 at 07:53
  • You keep asking almost exact duplicates of your own previous questions. If you actually understood the answers you wouldn't need to. – Boann Jul 24 '14 at 12:52
  • @Boann - Firstly, I am new to java so need to build my basics. Secondly if you think that my ques are useless then you ignore these posts. – Shashank Agarwal Jul 24 '14 at 13:12

2 Answers2

7

JLS says:

The static initializers and class variable initializers are executed in textual order, and may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope (§8.3.2.3). This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.

Which is exactly your case.

Here is your original example: http://ideone.com/pIevbX - static initializer of abc goes after static instance of abc is assigned - so static initializer can't be executed - it's textually after static variable initialization

Let's move line 4 after static initialization block - http://ideone.com/Em7nC1 :

class abc{
int a = 0;
static int b;
public abc() {
    System.out.println("cons");
}
{
    System.out.println("ini");
}
static {
    System.out.println("stat");
}
static abc h = new abc();//former line 4

}

Now you can see the following output:

stat
ini
cons
ini
cons
0

Now initialization order is more like you expected - first called static initializer and then static instance of abc is initialized in common manner.

Konstantin V. Salikhov
  • 4,554
  • 2
  • 35
  • 48
6

Static fields initialization and static blocks are executed in the order they are declared. In your case, the code is equivalent to this after separating declaration and initialization:

class abc{
    int a;
    static int b;
    static abc h;//line 4

    static {
        h = new abc();//line 4 (split)
        System.out.println("stat");
    }

    public abc() {
        a = 0;
        System.out.println("ini");
        System.out.println("cons");
    }
}

public class ques{
    public static void main(String[] args) {
        System.out.println(new abc().a);
    }
}

So when you reach line 4 from your code, the static initialization is actually being executed and not finished yet. Hence your constructor is called before stat can be printed.

Didier L
  • 18,905
  • 10
  • 61
  • 103