Java Generics Question
In my quest to develop a generic singleton class, I encountered this problem:
[weiqi@gao] $ cat Singleton.java
public class Singleton<T> {
private static T instance;
public static T getInstance() {
if (instance == null) {
instance = new T();
}
return instance;
}
}
[weiqi@gao] $ javac Singleton.java
Singleton.java:2: non-static class T cannot be referenced from a static context
private static T instance;
^
Singleton.java:3: non-static class T cannot be referenced from a static context
public static T getInstance() {
^
Singleton.java:5: non-static class T cannot be referenced from a static context
instance = new T();
^
3 errors
Why? (Both C++ and C# allow similar constructs.)
Re: Java Generics Question
Java 5.0 generics differ in concept from those in C# version 2. In Java there is only one class per class no matter how many parameters it has. Therefore static members are not affected by generic parameters of their class. So you would need to do something like this (not tested):
import java.util.Map;
public class Singleton<T> {
private static Map<Class<?>,Object> instanceMap =
new java.util.HashMap<Class<?>,Object>();
public static synchronized <T> T getInstance(
Class<T> clazz
) throws InstantiationException,
IllegalAccessException
{
T instance = clazz.cast(instanceMap.get(clazz));
if (instance != null) {
return instance;
}
try {
instance = clazz.cast(clazz.newInstance());
} catch (InstantiationException exc) {
throw new IllegalArgumentException(exc);
} catch (IllegalAccessException exc) {
throw new IllegalArgumentException(exc);
} catch (ClassCastException exc) {
throw new IllegalArgumentException(exc);
}
instanceMap.put(clazz, instance);
return instance;
}
}
But we all know singletons are evil. If there's no state in the class, then you can simply cast a single instance, as Collections.emptySet does.