2016-05-17 94 views
0

我遇到了一個問題,我無法找到解決方案。泛型通配符不能轉換爲泛型

我經常使用一個映射,其中鍵和值是具有匹配泛型類型的對象。對於每一對泛型應匹配。雖然條目之間的泛型可能不一樣。 (爲了清楚起見,包括一個例子)。 這可以通過使用通配符來輕鬆完成。雖然正因爲如此,你不能將鑰匙或價值與海誓山盟結合使用。

請考慮底部包含的示例。沒有(簡單的)方法來修改映射以運行到Cast異常。雖然我仍然無法使用地圖,就像我在useEntries()內嘗試的那樣。所以我的問題是,有沒有解決這個問題的方法?提前致謝!

@SuppressWarnings("unchecked") 
public static void useEntries() { 
    for (Map.Entry<GenericObject<?>, Function<?, ?>> currentEntry : map.entrySet()) { 
     GenericObject key = currentEntry.getKey(); 
     Function value = currentEntry.getValue(); 
     key.set(value.apply(key.get())); 
    } 
} 

去除方法中GenericObjectFunction仿製藥將讓你做出純Object實例調用:

public class GenericWildcardTest 
{ 
    static Map<GenericObject<?>, Function<?, ?>> map = new HashMap<>(); 

    public static <S> void put(GenericObject<S> genericObject, Function<S, S> function) 
    { 
     map.put(genericObject, function); 
    } 

    public static void useEntries() 
    { 
     for(Entry<GenericObject<?>, Function<?, ?>> currentEntry : map.entrySet()) 
      //The #apply(); part simply wont compile because of cast errors. 
      currentEntry.getKey().set(currentEntry.getValue().apply(currentEntry.getKey().get())); 
    } 



    // Simple Object with generic. 
    static class GenericObject<T> 
    { 
     private T object; 

     public GenericObject(T object) 
     { 
      this.object = object; 
     } 

     public void set(T object) 
     { 
      this.object = object; 
     } 

     public T get() 
     { 
      return this.object; 
     } 
    } 
} 
+0

鑄造是一個明顯的解決方法。 – shmosel

+0

我很困惑你的帖子和你的要求。您正在使用泛型和通配符。我建議您完整閱讀本教程,其中涵蓋了泛型和通配符,並將闡明您的問題。 [Java™教程:泛型(更新)](http://docs.oracle.com/javase/tutorial/java/generics/index.html) – Underbalanced

+0

@shmosel你明智地沒有嘗試使用它?因爲它不會工作。我甚至試圖用自己的通用實現來製作私有方法。但其相當簡單。泛型可以轉換爲通配符,但不是vicaversa – n247s

回答

2

這裏是你如何可以用鑄造做到這一點:

@SuppressWarnings("unchecked") 
public static <S> void useEntries() { 
    for(Entry<GenericObject<?>, Function<?, ?>> currentEntry : map.entrySet()) { 
     GenericObject<S> key = (GenericObject<S>)currentEntry.getKey(); 
     Function<S, S> value = (Function<S, S>)currentEntry.getValue(); 
     key.set(value.apply(key.get())); 
    } 
} 

這個答案假定您的地圖確實包含Function<S, S>,不Function<GenericObject<S>, S>

+0

我寧願單獨對每個演員施加壓制(例如,'@SuppressWarnings(...)GenericObject key = ...'),而不是整個方法,以免您不小心添加更多未經檢查的演員陣容如果以後改變方法。但一般來說,這是一種比原始類型更好的方法。 –

+1

@AndyTurner,同意。我會更進一步,並創建一個私有方法來避免暴露'T'(因此它實際上代表了一種類型),但我決定在這裏以簡單的方式。 – shmosel

0

可以按如下方式重寫useEntries方法。這是你的責任,以確保正確的打字。註釋SuppressWarning將刪除將以其他方式打印的編譯警告。

+0

沒想到那個。愚蠢簡單。謝謝 – n247s

+2

不要使用原始類型:使用轉換。 –

+1

我會建議在原始類型之前投射。由於原始類型,這個代碼中實際存在一個被忽略的錯誤。 – shmosel