How to force instantiation of static fields
I was quite surprised of the output of the following code:
Country class
public class Country {
private static Map<String, Country> countries = new HashMap<String, Country>();
private final String name;
@SuppressWarnings("LeakingThisInConstructor")
protected Country(String name) {
this.name = name;
register(this);
}
/** Get country by name */
public static Country getCountry(String name) {
return countries.get(name);
}
/** Register country into map */
public static void register(Country country) {
countries.put(country.name, country);
开发者_JAVA技巧 }
@Override
public String toString() {
return name;
}
/** Countries in Europe */
public static class EuropeCountry extends Country {
public static final EuropeCountry SPAIN = new EuropeCountry("Spain");
public static final EuropeCountry FRANCE = new EuropeCountry("France");
protected EuropeCountry(String name) {
super(name);
}
}
}
Main method
System.out.println(Country.getCountry("Spain"));
Output
null
Is there any clean way of forcing the class that extend Country to be loaded so the countries map contains all the Country instances?
Yes, use static initializer block:
public class Country {
private static Map<String, Country> countries = new HashMap<String, Country>();
static {
countries.put("Spain", new EuroCountry("Spain"));
}
...
Your class EuropeCountry
was not loaded at the time you called Country.getCountry("Spain")
. The correct solution would be
private static Map<String, Country> countries = new HashMap<String, Country>();
static {
// Do something to load the subclass
try {
Class.forName(EuropeCountry.class.getName());
} catch (Exception ignore) {}
}
This is just an example... There are other ways to achieve the same (see also Peter's answer)
You need to load the EuropeCountry
class. Any reference to it before calling Country will enough.
精彩评论