4

I have a Class called Color in which there are three static Objects (instantiating with the same class itself) and a int type (called i) variable. When I Run the Class, the 'i' variable is increments in the Constructor, but it is not persisting in memory , please explain this below code

package test;
public class Color
{
     public static  Color RED = new Color();
     public static final Color BLUE = new Color();
     public static final Color GREEN = new Color();
     static int i=0;

     Color(){
         System.out.println("Incrementing 'i'  here  "+(++i));
     }

     public static void main(String[] args) {
         System.out.println("The 'i' variable is not incremented here, it still shows '0' ,  'i' is: "+ Color.i );  // line 14 
        Color x = new Color();
        System.out.println(x.i);
    }
}

The out is as follow:

Incrementing 'i'  here  1
Incrementing 'i'  here  2
Incrementing 'i'  here  3
The 'i' variable is not incremented here, it still shows '0' ,  'i' is: 0
Incrementing 'i'  here  1
1

2 Answers 2

8

When a class is loaded and linked, its static fields are all initialized to their default values. Once that is done, the static field initializers are executed in the order they appear in the file, thus completing the initialization of the class. All this happens before any code defined in that class executes. So what's happening here is:

  1. RED, GREEN, BLUE, and i are initialized to their default values (null for the Color fields and 0 for i). Note that this is independent of any initializers.
  2. The initializer for field RED (RED = new Color()) executes. As a side effect, i is incremented to 1.
  3. The initializer for field BLUE executes and i is incremented to 2.
  4. The initializer for field GREEN executes and i is incremented to 3.
  5. The initializer for the static field i executes and i is assigned the value 0.
  6. The main() method executes and produces the results consistent with i being 0 when main() begins execution.

You can read the gory details of all this in Chapter 12 of the Java Language Specification (JLS) and Chapter 5 of the Java Virtual Machine Specification.

You can get the output you expected simply by move the declaration of i to be ahead of the Color fields:

 static int i=0;
 public static  Color RED = new Color();
 public static final Color BLUE = new Color();
 public static final Color GREEN = new Color();

Then the output will be:

Incrementing 'i' here 1
Incrementing 'i' here 2
Incrementing 'i' here 3
The 'i' variable is not incremented here, it still shows '0' , 'i' is: 3
Incrementing 'i' here 4
4

Note that the final modifiers have no effect on the order of initialization here because GREEN and BLUE are not "constant variables" according to the definition of that term in the JLS. A constant variable (an unfortunate pairing of words) is a primitive or String variable that is both declared final and initialized to a constant expression. In this case, new Color() is not a constant expression and Color is not an appropriate type for a constant variable. See, for instance, §4.12.4 of the JLS.

Sign up to request clarification or add additional context in comments.

10 Comments

Speaking of chapter 12 of the JLS, if I'm reading 12.4.1 correctly, won't BLUE and GREEN be initialized before RED because they're final?
@Powerlord no, final doesn't make a constant. Only Strings and primitives can be constants, and there are rules to be respected for that. Besides, constants are initialized like all other fields, it's just that their value can be used before they were initialized, because it was already known at compile time so the compiler replaced the variable access with its known value.
@Powerlord - You're right. I hadn't noticed the final modifier on those two fields. I'll update my answer to reflect that.
@kumesana - That analysis is wrong. When the class is first loaded, all static fields (including final fields) are initialized to their default values. The compiler doesn't know the address of the object that will be returned by new Color(); that is determined when the initializer executes, which happens at run time, later in the initialization process for the class (but still before main() begins execution).
@TedHopp final or non-final doesn't matter and doesn't change the order of initialization. Now that your answer pretends it does, your answer has become incorrect. You could just simply give it a try, by the way. I don't know where that idea started from, but I supposed that it came from the existence of constants, which is an overlapping, but different, subject.
|
0

Class Initialization proceeds top to bottom .When we initialize Color we create a new Color .In order to create a new Color we also have to initialize Color. That's called recursive initialization and what the system does is simply ignores the recursive initialization and executes new Color(). This class initializer executes by the below sequence top to bottom

  1. public static Color RED = new Color(); this sets static variable i to 1.

  2. public static final Color BLUE = new Color(); this increments static variable i to 2

  3. public static final Color GREEN = new Color(); this increments static variable i to 3

  4. static int i=0; this sets static variable i back to zero.

Now when the main thread runs.It sees the static variable to 0 and increments to 1.

As a counter example try replacing static int i=0 to static Integer i=new Integer(0). . This will throw a NullPointerException . This is because at class initialization time when public static Color RED = new Color(); executes it sees the i as null , because i has not been initialized by then, resulting in NullPointerException

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.