10

I have problem understanding the order in which initialization happens. this is the order I assumed:

*Once per 
    1. Static variable declaration
    2. Static block
*Once per object
    3. variable declaration
    4. initialization block
    5. constructor

but according to this code I am obviously wrong:

    class SomethingWrongWithMe
    {
        {
            b=0;         //no. no error here.
            int a = b;   //Error: Cannot reference a field before it is defined.
        }
        int b = 0;
    }

And the error would disappear if I do this:

    class SomethingWrongWithMe
    {
        int b = 0;
        {
            b=0;
            int a = b;   //The error is gone.
        }
    }

I can't figure out why isn't there an error on

    b=0;
Untitled
  • 781
  • 1
  • 6
  • 24

3 Answers3

4

The Java Language Specification (section 8.3.2.3) says you can use a variable on the left hand side of an expression, i.e. assign to it, before it is declared, but you cannot use it on the right hand side.

All variables are initialized to their default values, then explicit initializers and anonymous blocks are run in the order they are found in the source file. Finally the constructor is called.

Statics are only run once on the first use of a class.

The compile error appears to be a rule of Java rather than something that necessarily makes sense in every case.

Simon G.
  • 6,587
  • 25
  • 30
  • follow-up question: ok. I now understand the the situation here. just can't understand why is there such a feature. I can't imagine a use for it. why would someone want to assign to a variable in the initialization block before its declaration? why not just declare it first? – Untitled Mar 13 '12 at 04:36
  • 1
    I agree, and why can we assign a value to it, but not read from it? The JLS says all variables are created and initialised to default values before any explicit code is run, so the variable exists and has a value, we just can't read from it. That just seems strange to me. – Simon G. Mar 13 '12 at 09:10
  • It's done to avoid circular references. E.g. int a = b + 1; int b = a + 2; – ekaerovets Mar 06 '15 at 10:41
3

Variable definitions are not done "before" blocks. They are both done at the same time, in the order that they are defined

class SomethingWrongWithMe {
    {
        b = debug("block 1");
    }
    int b = debug("define");
    {
        b = debug("block 2");
    }
    private int debug(String str) {
        System.out.println(str);
        return 0;
    }
}

Output

block 1
define
block 2
Adam
  • 35,919
  • 9
  • 100
  • 137
  • 1
    Right, but the question why he may write to a variable declared below the line but not read from the same variable is not answered. – aioobe Mar 12 '12 at 10:42
1

First of all, your assumptions are more or less correct, except for the fact that declarations (with initialization, such as int b = 0) and instance initializer blocks are executed in the order they are written.

int b = 0;   // executed first

{
    b = 1;   // executed second
}

int a = b;   // executed third

Also note that the declaration i.e. int b is not executed. The declaration just declares the existence of the variable.

As for the error you got (or, rather the error you didn't get) I agree that it looks strange. I assume that the compiler deals with referencing a variable in an expression and assigning a value to it in different ways. When writing to a variable in an instance initializer, it just checks that the variable is there, while when reading from it, it requires it to be declared above the instance initializer block. I'll see if I can find a reference for that in the JLS.

aioobe
  • 413,195
  • 112
  • 811
  • 826