2011-11-02 130 views
7

所以我有几个'经理'类,例如GroupManager。所有这些经理都是单身人士。Java泛型,单例和静态方法

使用此方法实例化:

private static GroupManager groupManager = null; 

private GroupManager() 
{ 

} 

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

我想我应该开始,因为他们有很多的复制方法来使用一些继承。

每个Manager的Instance()方法是相同的。

所以对于继承我可以做到这一点(显然):

GroupManager extends Manager 

是否有可能使用泛型使用相同的实例方法,所有的管理者,是这样的:

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

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

} 

我想这是有道理的:)

那么你会做GroupManager.Instance()像正常。

+1

Java泛型是没有办法的与C++模板相同!随它吧!您永远不能使用Java Generic分配对象(即调用new)。尝试谷歌搜索“Java类型擦除” – DwB

+0

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

+0

经理 E是一个引用一个泛型类型。没有简单的方法来设置类来分配只在运行时才知道的类型的对象。里德麦克的答案是我会尝试的。 – DwB

回答

9

你不明白仿制药和静力学是如何工作的。如果你有一个静态字段或方法(比如“instance”或者instance()),可以在不实例化类管理器的情况下调用它,那么你如何期望JVM(甚至编译器)知道E应该是什么类型是?

下面是一个例子,按照G_H的建议:

总经理和AreaManager二者延伸经理

Manager类是具有的getInstance()静态方法的只有一个:

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

是的,但是这对于实现单例的想法完全不可行。你需要一些可怕的扭曲结构,比如从Map类到实例的Map。 –

+0

+1,这是非常真实的,我在考虑是否应该添加这个观察结果(我决定不首先让我相信泛型和静态的基本概念在使用之前需要被理解)。不过你说得很好。此外,您可以将泛型E类型限制为基类,如E扩展RootOfIheritanceChainClass。 –

+0

我有点失落大声笑,我应该去:基本上我需要一个新的Instance()方法为每个新的经理。 – Metalstorm

2

不,它不会工作。 Java在编译时使用泛型进行类型检查,但不会在运行时生成额外的类或保留有关类型参数的信息。

当您声明Manager<E>与该类型参数E时,这只会在实际实例中发挥作用。你可以有一个像GroupManager extends Manager<String>之类的子类,但这并不奇怪会产生多种静态方法。

静态方法和成员属于一个类,而不是一个实例。因此,试图在那里使用泛型,这是打算用于输入实例,是不会飞。

0

如果您按如下方式设置组经理类,则可以调用实例方法。

public class GroupManager extends Manager<GroupManager>{} 

而在你Manager类试试这个...

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

或者,如果你知道你想要的实例对象,只是使通用的方法

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

我HAVN没有尝试过这些,所以不知道它是否会起作用。

+1

第一个例子是错误的 – Fabian

0

在通用上下文中注入构造函数。现金是不是线程安全的,但只有在静态的情况下使用,因此它的罚款,如果你不会错过使用它

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

上面的答案会做,不是吗? –

+0

那不会工作 – Fabian

+0

那不工作... – mahieddine