Reputation: 131
I am absolute clueless why the following code keeps throwing NullpointerExceptions. I was not able to understand or debug this (its stripped down code from a larger class)...
The code is based on the "Enum Pattern" and I want to keep a List/Map of all "Constants" that are contained in the class (I might be using Reflection for this but using a List/Map is much easier...)
public class Country {
public static final Country SWITZERLAND = new Country("SWITZERLAND");
private static ArrayList<Country> countries = new ArrayList<Country>();
private Country(String constname) {
//constname is currently not used (I will use it for a Key in a Map)
System.out.println(constname);
System.out.println("Ref debug:"+this);
//Ad this to the Countries
Country.countries.add(this);
}
}
Help would be very much appreciated. What am I missing here?
Upvotes: 0
Views: 403
Reputation: 346377
Because I think this deserves more than the cursory mention Jon gave it:
The "typesafe enum pattern" is obsolete!
Unless you are forced to use an ancient Java version (pre 1.5, which isn't even supported anymore by Sun), you should use Java's real Enums, which save you a lot of work and hassles (because old-style typesafe enums are very hard to get right) and are just all around awesome.
Upvotes: 4
Reputation: 12413
'Country' constructor call to initialize SWITZERLAND
static field happens before initialization of countries
list. If you change order of static field definition it will work better.
Upvotes: 1
Reputation: 2572
I think code bellow may work .Constructor of class have to define as public method not private.
Country(String constname) {
//constname is currently not used (I will use it for a Key in a Map)
System.out.println(constname);
System.out.println("Ref debug:"+this);
//Ad this to the Countries
Country.countries.add(this);
}
Upvotes: -1
Reputation: 1502036
To expand on what Konrad said, the static variable initializers are executed in textual order (as specified in JLS section 8.7). If you put the ArrayList
first, it will work:
public class Country {
private static ArrayList<Country> countries = new ArrayList<Country>();
public static final Country SWITZERLAND = new Country("SWITZERLAND");
...
Konrad's suggestion of using a static constructor to keep the order clearly specified is a good one though.
Are you using Java "pre 1.5"? If not, use a straight enum...
Upvotes: 4
Reputation: 545865
SWITZERLAND
, being static, is potentially initialized before countries
, which is also static
. Therefore, countries
is still null
in the constructor call of SWITZERLAND
.
To force a well-defined order of initialization, use a static
block:
public class Country {
public static final Country SWITZERLAND;
private static ArrayList<Country> countries;
static {
countries = new ArrayList<Country>();
SWITZERLAND = new Country("SWITZERLAND");
}
}
Upvotes: 5