java singleton of parameterized class

1.1k Views Asked by At

I can't get this disentangled.

public class MySingleton<T extends AUsefulClass>{
    Map<String, T> myUsefulRegistry;
    private static MySingleton<T> _instance = null;

    public static instance(){
        if(instance == null)
            _instance = new MySingleton<T>();

        return _instance;
    }
}

public class Test{
    @Test
    public void testThis(){
        MySingleton<SomeClass> mySingleton = MySingleton<SomeClass>().instance();
    }
}

This parametrization is faulty because you cannot make a static reference to a nonstatic T. Still, I would like to build a parameterizable singleton class.

3

There are 3 best solutions below

0
On

Here's a solution:

public class MySingleton {
    private static MySingleton instance;

    private final Map<String, ?> myUsefulRegistry;

    private <T> MySingleton(Class<T> type) {
        myUsefulRegistry = new HashMap<String, T>();
    }

    public static <T> MySingleton getInstance(Class<T> type) {
        if (instance == null) {
            instance = new MySingleton(type);
        }
        return instance;
    }
}

If you are planning on reassigning myUsefulRegistry, you will obviously have to omit the final modifier and also implement state based on the type parameter (by storing it to use again).

Edit: There's an issue if the user passes a different type to the original. You may want to store the type in any case then, so you can check whether any proceeding calls to getInstance(Class<T>) are valid.

0
On

I'd rather look at my design in this case. Also, if you want to create a different singleton due circumstances. You'd probably use a factory to instantiate the singleton at first.

I'm not sure if the singleton pattern is a good approach, it introduces global state via objects, which is the very thing you probably don't want.

0
On

The problem is that in Java (unlike .NET) you've only got one static variable no matter how many different type arguments you provide - so MySingleton<Foo>._instance is equal to MySingleton<Bar>._instance.

I suspect you want a Map<Class<? extends AUsefulClass>, MySingleton>, suppressing the warnings about raw types. Then you'd make your instance method take a Class<T> parameter as well, so it would know what to look up.

Of course, this is assuming you want separate state for different type arguments. If you don't need different state for MySingleton<Foo> and MySingleton<Bar> you can truly have a single instance, and just cast it while suppressing the unchecked conversion warning.