不能转换为非generics的非特定嵌套types

我有两个嵌套的generics类。 有没有办法摆脱的

types不匹配:不能从Msg<Value<String>>转换为Msg<Value<?>>错误? 在最后的任务

 public class Value<V> { V val; public Value(V val) { this.val = val; } @Override public String toString() { return "" + val; } } public class Msg<T> { T holder; public Msg( T holder) { this.holder = holder ; } public String toString() { return "" + holder; } public static void main(String[] args) { Msg<Value<String>>strMsg = new Msg(new Value<String>("abc")); // This is OK Msg<?>objMsg = strMsg; // Type mismatch: cannot convert from Msg<Value<String>> to Msg<Value<?>> Msg<Value<?>>objMsg = strMsg; } } 

使用以下内容:

 Msg<? extends Value<?>> someMsg = strMsg; 

问题是, 在Msg<Value<?>> objMsg不能捕捉转换。 它不是“ 某种types的Value Msg ,而是“ 任何types的Value Msg ”。

这也解释了为什么随着声明的变化,我也把variables重命名为someMsgValue不能只是任何Object 。 它必须属于某种types(在这个例子中是String )。


一个更通用的例子

我们来看一个List<List<?>>的更通用的例子。 与原始场景类似, List<List<?>> 不能捕获 – 转换List<List<Integer>>

  List<List<Integer>> lolInt = null; List<List<?>> lolAnything = lolInt; // DOES NOT COMPILE!!! // a list of "lists of anything" List<? extends List<?>> lolSomething = lolInt; // compiles fine! // a list of "lists of something" 

这是另一种看待它的方法:

  • Javagenerics是types不变的
  • 有从IntegerNumber的转换,但List< Integer >不是List< Number >
    • 类似地, List<Integer>可以被List<?>捕获转换,但是List< List<Integer>不是List< List<?> >
  • 使用有界通配符, List<? extends List<? extends Number >可以捕获 – 转换List< Integer >
    • 同样,一个List<? extends List<? extends List<?>可以捕获 – 转换List< List<Integer> >

有些事实? 可以捕捉和别人也不能解释以下片段:

  List<List<?>> lolAnything = new ArrayList<List<?>>(); // compiles fine! List<?> listSomething = new ArrayList<?>(); // DOES NOT COMPILE!!! // cannot instantiate wildcard type with new! 

相关问题

  • generics方法上的多个通配符使Java编译器(和我!)非常困惑
    • 非常漫长而详细的探索这个问题
  • Java通用List<List<? extends Number>> List<List<? extends Number>>
  • 任何简单的方法来解释为什么我不能做的List<Animal> animals = new ArrayList<Dog>()
  • <E extends Number><Number>之间有什么区别?

也可以看看

  • Javagenerics教程
    • generics和子types | 通配符 | 通配符更有趣
  • Angelika Langer的Javagenerics常见问题
    • 什么是有界通配符?
    • 哪些超types关系存在于genericstypes的实例之间?

虽然您的genericstypes参数包含通配符,但它本身不是通配符。 使用非通配typesT指定variables( Msg<T> )时,被分配的对象必须具有T作为generics(包括T ,通配符和非通配符的所有genericstypes参数)。 你的情况TValue<String> ,它与Value<?>不是同一个types。

你可以做什么,因为Value<String>可赋值给Value<?> ,使用通配符types:

 Msg<? extends Value<?>> a = new Msg<Value<String>>(); 

我的答案与另一个类似,但希望更清楚。

 List<List<?>> is a list of (lists of anything). List<List<String>> is a list of (lists of strings). 

后者不能转换为前者,因为这样做可以让你添加一个List <Number>到你的List <List <String>中,这将明显被打破。

请注意,如果将Listreplace为某些没有.add的types,则此规则不会更改。 Java将需要声明站点的协方差和/或反对(如C#的IEnumerable <out T>或Scala的列表[+ A])。 Java只有use-site协方差和逆变(?extends X,?super X)。

不是一个直接的答案,但我强烈build议阅读: http : //java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf更好地理解generics。

ILMTitan有一个很好的解决scheme,如果你不想让这个类特定于Value,那么你可以在这个时候使用基types而不是generics,因为你会closures一个安全特性,但是有一个方法。 你甚至可以传递一个参数来使这个方法更通用,但关键是“@SuppressWarnings”。

 @SuppressWarnings("unchecked") Msg<Value<?>> convert() { return (Msg<Value<?>>) this; }