2011-11-02 132 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