static initializer not being called ...

Hi there ... :-)

I'm trying an odd variation on the enumeration class, which seems to be showing some odd behaviour which I don't understand.

publicclass ForecastingEnum{

publicstaticfinal ForecastingEnum NORMAL =new ForecastingEnum("NORMAL","normal string");

publicstaticfinal ForecastingEnum HISMOOTH =new ForecastingEnum("HISMOOTH","High Smooth Value");

publicstaticfinal ForecastingEnum LOWVAL =new ForecastingEnum("LOVAL","Low Value");

privatestatic Map map =new HashMap();

private String shortName;

private String longName;

static{

map =new HashMap();

}

public ForecastingEnum(String shortName, String longName){

this.setShortName(shortName);

this.setLongName(longName);

map.put(longName,this);

}

}

It seems that the static initializer is not being called, and at a guess, I think it may be because I'm supplying my own constructor.

But I always thought that statics were initialized when the class was loaded, so I'm not really sure why the map is null when the constructor is called.

I mean the easy way out is to just test the map in the constructor, and initialize it if it is null, but I'm really curious why this doesn't work.

Thanks in advance.

Ray

[2415 byte] By [raze66a] at [2007-11-27 5:24:01]
# 1

Well, right now you're doing a double initialization of your map. You should use either

private static Map map = new HashMap();

or

private static Map map;

static {

map = new HashMap();

}

Maybe that will solve your problem.

Dalzhima at 2007-7-12 11:50:10 > top of Java-index,Java Essentials,Java Programming...
# 2
Declare and initialize the Map before declaring those static instances of the class. Initializers are run in the order they're declared, if I recall correctly
georgemca at 2007-7-12 11:50:10 > top of Java-index,Java Essentials,Java Programming...
# 3

Ah, yes ... sorry about that. But I've tried it with either and both, and oddly enough, the map shows that the static block is never called, and even though map is defined with

private static Map map = new HashMap();

the value of map is still null when the constructor is called. I'm sure it is something I am doing, but I'm baffled as to what it is.

raze66a at 2007-7-12 11:50:10 > top of Java-index,Java Essentials,Java Programming...
# 4

> Ah, yes ... sorry about that. But I've tried it with

> either and both, and oddly enough, the map shows

> that the static block is never called, and even

> though map is defined with

>

> > private static Map map = new HashMap();

>

>

> the value of map is still null when the constructor

> is called. I'm sure it is something I am doing, but

> I'm baffled as to what it is.

That doesn't show the initializer wasn't called at all. Merely that it hadn't been called by that point. It's because of the order in which things are being initialized

georgemca at 2007-7-12 11:50:10 > top of Java-index,Java Essentials,Java Programming...
# 5

>>> Declare and initialize the Map before declaring those static instances of the class. Initializers are run in the order they're declared, if I recall correctly <<

Gaaaahhh!!!!! ... :-D

Dammit, yes of course!

A thousand 'thank yous' sir!

I even was reading about the ordering of static initialization and it still didn't click!

Sorry for wasting your time folks!

raze66a at 2007-7-12 11:50:10 > top of Java-index,Java Essentials,Java Programming...
# 6

> >>> Declare and initialize the Map before declaring

> those static instances of the class. Initializers are

> run in the order they're declared, if I recall

> correctly <<

>

> Gaaaahhh!!!!! ... :-D

>

> Dammit, yes of course!

>

> A thousand 'thank yous' sir!

>

> I even was reading about the ordering of static

> initialization and it still didn't click!

>

> Sorry for wasting your time folks!

Heh heh write out a hundred times "I must not expect to use something before it exists" and we'll say no more about it. I'll even let you off with writing a script to write it 100 times, if it's clever enough :-)

georgemca at 2007-7-12 11:50:10 > top of Java-index,Java Essentials,Java Programming...
# 7

The problem is likely to be the declaration order. When the you reference the first enum contact static initialization is triggered, and the first thing it does it to try to initialise your first constant. This invokes the constructor. But when it comes to referring to map, intialization is already in progress, so it doesn't restart. map won't be initialized until all textutally preceding static fields have been initialized (including calling the constructor).

Try simply putting the static {} stuff at the top of the class definition.

malcolmmca at 2007-7-12 11:50:10 > top of Java-index,Java Essentials,Java Programming...
# 8

Try this out

import java.io.*;

import java.util.*;

public class ForecastingEnum {

public static final ForecastingEnum NORMAL = new ForecastingEnum("NORMAL", "normal string");

public static final ForecastingEnum HISMOOTH = new ForecastingEnum("HISMOOTH", "High Smooth Value");

public static final ForecastingEnum LOWVAL = new ForecastingEnum("LOVAL", "Low Value");

private static Map map = new HashMap();

private String shortName;

private String longName;

public ForecastingEnum(String shortName, String longName) {

if(map==null)

map=new HashMap();

this.setShortName(shortName);

this.setLongName(longName);

map.put(longName, this);

}

private void setShortName(String s){shortName=s;}

private void setLongName(String s){longName=longName;}

}

gaurav_k1a at 2007-7-12 11:50:11 > top of Java-index,Java Essentials,Java Programming...
# 9

> Try this out

>

> import java.io.*;

> import java.util.*;

> public class ForecastingEnum {

>

> public static final ForecastingEnum NORMAL = new

> ForecastingEnum("NORMAL", "normal string");

> public static final ForecastingEnum HISMOOTH = new

> ForecastingEnum("HISMOOTH", "High Smooth Value");

> public static final ForecastingEnum LOWVAL = new

> ForecastingEnum("LOVAL", "Low Value");

>

>private static Map map = new HashMap();

>private String shortName;

> private String longName;

>

>

> public ForecastingEnum(String shortName, String

> longName) {

> if(map==null)

> map=new HashMap();

> this.setShortName(shortName);

> this.setLongName(longName);

> map.put(longName, this);

>

>private void setShortName(String s){shortName=s;}

> private void setLongName(String

> s){longName=longName;}

>

> }

Ok, while that might get the code working, it's really just hiding the problem rather than fixing it

georgemca at 2007-7-12 11:50:11 > top of Java-index,Java Essentials,Java Programming...
# 10

No, that wouldn't work either. The constructor calls precede the "map = new HashMap()" so, the first constructor would create a HashMap the static intializer would then replace it with an empty one.

What you need to understand is that the compiler accumulates a secret static method (called <clinit>) by concatenating static initializers (e.g. NORMAL = new ForecastingEnum("NORMAL", "normal string"); plus anything in static{} blocks. This code is simply added in the order it appears. <clinit> is called once, the first time you use the class. Further use of static or constructors during <clinit> won't cause it to start again.

malcolmmca at 2007-7-12 11:50:11 > top of Java-index,Java Essentials,Java Programming...