Reputation: 21
I'm learning Enum concept in java and I faced a problem while practicing.
Here is the code snippet,
public class MyClass {
private String cardColor = CARDS.SPADE.cardColor; #Causes Null Pointer #Default Value
private MyClass(CARDS card){
this.cardColor = card.cardColor;
}
public static enum CARDS{
SPADE("Black"),
CLUB("Black"),
DIAMOND("Red"),
HEART("Red");
private String cardColor = null;
private MyClass obj = null;
CARDS(String color){
this.cardColor = color;
obj = new MyClass(this); #Trying to create object for MyClass
}
public String getCardColor(){
return this.cardColor;
}
}
public static void main(String args[]) {
System.out.println(CARDS.SPADE);
}
}
I'm trying to create a MyClass object private to the enum in it's constructor. Here the value CARDS.SPADE is null and I end up with Null Pointer Exception.
If I don't create an object in enum constructor everything works perfect,
obj = new MyClass(this);
I'm not understanding why the static enum is not initialized and I'm confused with the control flow here. Can someone explain me what's wrong here?
Upvotes: 1
Views: 2847
Reputation: 131336
You have a circular dependency : the initialization of the CARDS
enum and the MyClass
instance depend on each other.
CARDS
constructor instantiates MyClass
but MyClass
constructor relies itself on the CARDS.SPADE
state that is not still fully initialized as in the pending enum constructor.
Either break this cycle or do things in two times. Init the enum without the bidirectional relationship and after the constructor invocations, set the enum value to the MyClass
instance via a setter.
Note that the "real" cause of the NullPointerException
is that you don't refer to the currently instance created in the enum constructor (this
) but you refer the enum value from the enum class itself : MyClass.CARD.SPADE
.
The first has a state but the second not yet since the enum constructor has not returned yet.
By passing the enum instance into the constructor of MyClass
it will "work" :
CARDS(String color){
this.cardColor = color;
obj = new MyClass(this);
}
}
// ...
public MyClass(CARDS cards){
cardColor = cards.cardColor;
}
But in a general way, passing this
during constructor body to another object/class not a good idea. This may leak to an inconsistent state if the object states changes between this time and the end of the constructor invocation.
Upvotes: 4