2011-11-02 32 views
7

Así que tengo algunas clases de 'Administrador', por ejemplo GroupManager. Todos estos gerentes son solteros.genéricos de Java, singletons y métodos estáticos

El uso de este método para la creación de instancias:

private static GroupManager groupManager = null; 

private GroupManager() 
{ 

} 

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

Estoy pensando que debería empezar a utilizar alguna herencia, ya que tienen una gran cantidad de métodos copiados.

Los métodos de Instance() para cada administrador son los mismos.

Así que para la herencia que pueda hacer esto (obviamente):

GroupManager extends Manager 

¿Es posible el uso de los genéricos para utilizar el mismo método de instancia para todos los gerentes, algo así como:

public class Manager<E> 
{ 
    private static E instance = null; 

    public static E Instance() 
    { 
     if (instance == null) 
     { 
      instance = new E(); 
     } 
     return instance; 
    } 

} 

pienso eso tiene sentido :)

Entonces, usted haría GroupManager.Instance() como normal.

+1

Java genéricos son de ninguna manera la ¡lo mismo que las plantillas de C++! ¡Déjalo ir! Nunca puede asignar un objeto (es decir, llamar nuevo) utilizando un Java Generic. Pruebe una búsqueda en Google de "Java Type Erasure" – DwB

+0

Relacionados: http://stackoverflow.com/questions/1927789/why-should-i-care-that-java-doesnt-have-reified-generics – BalusC

+0

Manager E es un referencia a un tipo genérico No hay una forma simple de configurar una clase para asignar objetos de un tipo que solo se conoce en tiempo de ejecución. La respuesta de Reid Mac es lo que probaría. – DwB

Respuesta

9

No entiende cómo funcionan los genéricos y la estática. Si tiene un campo o método estático (como "instancia" o instancia()), que puede invocarse sin instanciar el administrador de clase, ¿cómo espera que la JVM (y el compilador par) sepan qué tipo E se supone que debe ¿ser?

Aquí está un ejemplo, de acuerdo con la sugerencia de G_H:

Gerente General y AreaManager tanto se extienden Administrador

La clase Manager es el único que tiene la getInstance() método estático:

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; 
      } 
     } 
    } 
+1

Sí, pero eso no funcionará para la idea de implementar singletons. Necesitarías una estructura horriblemente contorsionada como un Mapa de 'Clase'es a instancias. –

+0

+1, eso es muy cierto, estaba pensando si debería agregar esa observación también o no (decidí no causar, creo que primero las nociones básicas de genéricos y estáticos deben ser entendidas antes de ser usadas así). Sin embargo, haces un buen punto. Además, podría restringir el tipo E genérico a una clase base como E extiende RootOfIheritanceChainClass. –

+0

Estoy un poco perdido lol, debería ir con: básicamente necesito un nuevo método Instance() para cada nuevo Manager. – Metalstorm

2

No, no va a funcionar. Java usa genéricos en tiempo de compilación para la verificación de tipos, pero no genera clases adicionales ni retiene información sobre los parámetros de tipo en el tiempo de ejecución.

Cuando declara Manager<E> con ese parámetro de tipo E, eso es algo que solo desempeñará una función en una instancia real. Podrías tener una subclase como GroupManager extends Manager<String> o lo que sea, pero eso no va a generar mágicamente una variedad del método estático.

Los métodos y miembros estáticos pertenecen a una clase, no a una instancia. Así que tratar de usar genéricos allí, que están destinados a tipear instancias, no va a volar.

0

Si hace que su clase de administrador de grupo sea la siguiente, puede llamar a su método de instancia.

public class GroupManager extends Manager<GroupManager>{} 

Y en su clase Gestor de probar este ...

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; 
} 

O si se conoce el objeto que desea una instancia para, simplemente hacer que el método genérico

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 HAVN No intenté nada de esto, así que no estoy seguro de si funcionará.

+1

el primer ejemplo es incorrecto – Fabian

0

Inyectando el constructor en un contexto genérico.Dinero en efectivo no es seguro para subprocesos, pero sólo se utiliza en el contexto estático por lo que su muy bien si usted no se pierda usarlo

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

public class Manager<E>{ 

private static Object instance = null; 

    public static E Instance() { 
     if (instance == null) 
     { 
     instance = new E(); 
     } 
     return (E)instance; 
    } 
} 

+0

La respuesta anterior servirá, ¿no es así? –

+0

eso no va a funcionar – Fabian

+0

que no funciona ... – mahieddine

Cuestiones relacionadas