2016-05-17 67 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