hisham hm

Java: if you have trouble declaring a static hashmap…

Java (as of version 6, aka 1.6) does not allow you to declare a static HashMap as conveniently as an array. Still, you have the alternative of using a static block in your class to add fields. Take this example:

import java.util.HashMap;

public class StaticHashMapTest {
	private final static HashMap constants = new HashMap();
	static
	{
		constants.put("A", "The Letter A");
		constants.put("B", "The Letter B");
		constants.put("C", "The Letter C");
	}
	/* Rest of your class that needs to know the consts */
}

This works fine. But then you want to map something a little more complex than a string to another string. And I don't mean something very complex... just, say, a string to a string and an integer (yes, you'd like to use some kind of "pair object", but it looks like Java does not have it).

So you go and try to do things The Java Way (tm) and create a tiny class just to hold your two values:

import java.util.HashMap;

public class StaticHashMapTest {

	private class Pair {
		final String name;
		final int number;
		public Pair(String name, int number) {
			this.name = name;
			this.number = number;
		}
	}

	private final static HashMap constants = new HashMap();
	static
	{
		constants.put("A", new Pair("The Letter A", 123));
		constants.put("B", new Pair("The Letter B", 456));
		constants.put("C", new Pair("The Letter C", 789));
	}
	/* Rest of your class that needs to know the consts */
}

This should suffice, right? I even made the Pair class private to my class, to ensure good information hiding (that's what Java is all about, right?). Turns out this fails to compile:

StaticHashMapTest.java:18: non-static variable this cannot be referenced from a static context
      constants.put("A", new Pair("The Letter A", 123));
                         ^
StaticHashMapTest.java:19: non-static variable this cannot be referenced from a static context
      constants.put("B", new Pair("The Letter B", 456));
                         ^
StaticHashMapTest.java:20: non-static variable this cannot be referenced from a static context
      constants.put("C", new Pair("The Letter C", 789));
                         ^
3 errors

The error messages say that my "new" operators are failing due to the use of the "this" variable, which is not there at all! But hey, we can call "new" from a static context, can't we? We just did that when declaring the HashMap itself.

It turns out that the problem is that we're using an inner class. Objects from inner classes hold a "this" reference to their parent object (yes, as in myInnerObject.this.myParentAttribute... go figure), hence the trouble with the implicit "this" reference.

You have to make it a static inner class, which means it doesn't know anything about the enclosing class. Yes, that's yet another meaning for the word "static" in programming. Due to this peculiar meaning, inner classes are the only context where you can use the "static" qualifier to a class declaration in Java.

This, therefore, works:

import java.util.HashMap;

public class StaticHashMapTest {

	private static class Pair {
		final String name;
		final int number;
		public Pair(String name, int number) {
			this.name = name;
			this.number = number;
		}
	}
	private final static HashMap constants = new HashMap();
	static
	{
		constants.put("A", new Pair("The Letter A", 123));
		constants.put("B", new Pair("The Letter B", 456));
		constants.put("C", new Pair("The Letter C", 789));
	}
	/* Rest of your class that needs to know the consts */
}

And that's Java for you.