Can't cast to to unspecific nested type with generics
我有两个具有嵌套泛型的类。有没有办法摆脱
类型不匹配:无法从
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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; } } |
使用以下内容:
1 | Msg<? extends Value<?>> someMsg = strMsg; |
问题是
这也解释了为什么在声明更改的同时,我还将变量重命名为
让我们考虑一个更通用的>
>
>
1 2 3 4 5 6 7 | 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" |
另一种方法是:
- Java泛型是类型不变量。
- 有一个从
Integer 到Number 的转换,但是List< Integer > 不是List< Number > 的转换。- 类似地,
List 可以被List> 转换,但List< List > 不是List< List> > 的。
- 类似地,
- 使用有界通配符,
List extends? Number > 可以捕获转换List< Integer > 的EDOCX1。- 同样,一个
List extends? List> > 可以捕获一个List< List > 的转换。
- 同样,一个
一些
1 2 3 4 | List<List<?>> lolAnything = new ArrayList<List<?>>(); // compiles fine! List<?> listSomething = new ArrayList<?>(); // DOES NOT COMPILE!!! // cannot instantiate wildcard type with new! |
相关问题
- 泛型方法上的多个通配符使Java编译器(和ME!)非常困惑
- 对这个问题进行了很长很详细的探讨
- Java通用EDCOX1〔42〕
- 有什么简单的方法来解释为什么我不能做
List ?animals = new ArrayList () 和 有什么区别?
也见
- Java泛型教程
- 泛型和子类型通配符使用通配符更有趣
- Angelika Langer的Java泛型常见问题解答
- 什么是有界通配符?
- 在泛型类型的实例化之间存在哪些超级子类型关系?
我的回答和另一个类似,但希望更清楚。
1 2 3 | List<List<?>> is a list of (lists of anything). List<List<String>> is a list of (lists of strings). |
后者无法转换为前者,因为这样做将允许您向列表中添加一个列表>,该列表显然会被破坏。
请注意,如果用没有的类型替换列表,则此规则不会更改。添加。Java将需要声明站点协方差和/或逆反(例如C语言的iQuestaby < Ext T>或斯卡拉的列表[+A])。Java只有使用站点协方差和逆变(?)扩展X,?超级X)。
尽管泛型类型参数包含通配符,但它本身不是通配符。当分配给具有非通配符泛型类型
由于
1 | Msg<? extends Value<?>> a = new Msg<Value<String>>(); |
不是一个直接的答案,但我强烈建议您阅读:http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf以更好地理解泛型。
ilmtitan有一个很好的解决方案,如果您不想使类特定于值,那么此时您也可以使用基类型而不是泛型,因为您将关闭一个安全功能,但有一种方法。您甚至可以传递一个参数来使这个方法更通用,但关键是"@suppresswarnings"。
1 2 3 4 5 | @SuppressWarnings("unchecked") Msg<Value<?>> convert() { return (Msg<Value<?>>) this; } |