Java generics, singletones and static methods

So, I have several "Manager" classes, for example GroupManager. All these managers are singlets.

Using this method for instancing:

private static GroupManager groupManager = null; private GroupManager() { } public static GroupManager Instance() { if (groupManager == null) { groupManager = new GroupManager(); } return groupManager; } 

I think I should start using some inheritance, since they have many copied methods.

Instance () methods are the same for each Manager.

So, for inheritance, I can do this (obviously):

 GroupManager extends Manager 

Is it possible to use generics to use the same Instance method for all managers, for example:

 public class Manager<E> { private static E instance = null; public static E Instance() { if (instance == null) { instance = new E(); } return instance; } } 

I think that makes sense :)

So, you would do GroupManager.Instance () as usual.

+7
source share
5 answers

You do not understand how generics and statics work. If you have a static field or method (such as an โ€œinstanceโ€ or an instance ()) that can be called without creating an instance of the class manager, how do you expect the JVM (and even the compiler) to know what type E is supposed to be?

Here is an example, as suggested by G_H:

GeneralManager and AreaManager expand the capabilities of the Manager

The Manager class is the only one that has a static getInstance () method:

  public class Manager { private static Map<Class<? extends Manager>,Manager> INSTANCES_MAP = new java.util.HashMap<Class<? extends Manager>, Manager>(); //Also, you will want to make this method synchronized if your application is multithreaded, //otherwise you mihgt have a race condition in which multiple threads will trick it into //creating multiple instances public static <E extends Manager> E getInstance(Class<E> instanceClass) throws InstantiationException, IllegalAccessException { if(INSTANCES_MAP.containsKey(instanceClass)) { return (E) INSTANCES_MAP.get(instanceClass); } else { E instance = instanceClass.newInstance(); INSTANCES_MAP.put(instanceClass, instance); return instance; } } } 
+9
source

No, that will not work. Java uses compile-time generalizations to check types, but does not generate additional classes or store information about type parameters at run time.

When you declare Manager<E> with a parameter of this type E , this is what will only play a role in the actual instance. You may have a subclass of type GroupManager extends Manager<String> or something else, but this will not magically produce many static methods.

Static methods and members belong to a class, not an instance. Therefore, attempts to use generics there, which are designed to enter instances, are not going to fly.

+2
source

If you create the group manager class as follows, you can call your instance method.

 public class GroupManager extends Manager<GroupManager>{} 

And in your manager class try this ...

 public class Manager<E> { private static E instance = null; public static E Instance() { try { return instance.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } 

Or, if you know an object that needs an instance, just create a generic method

 public static <T> T getInstance(Class<T> t){ try { return t.newInstance(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } 

I have not tried any of this, so I'm not sure if this will work.

0
source

Entering a constructor in a general context. Cash is not thread safe, but is used only in a static context, so its fine if you do not miss its use

 public class Example { public static class MySingletonClass { } public interface Provider<T> { T get(); } static final Provider<MySingletonClass> myClassInstanceProvider = new Cash<MySingletonClass>(new Provider<MySingletonClass>() { @Override public MySingletonClass get() { return new MySingletonClass(); } }); public static class Cash<T> implements Provider<T> { private Provider<T> provider; public Cash(Provider<T> provider) { this.provider = provider; } @Override public T get() { final T t = provider.get(); provider = new Provider<T>() { @Override public T get() { return t; } }; return t; } } } 
0
source

<i>

 public class Manager<E>{ private static Object instance = null; public static E Instance() { if (instance == null) { instance = new E(); } return (E)instance; } } 

0
source

All Articles