不能转换为非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重命名为someMsg
。 Value
不能只是任何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不变的
- 有从
Integer
到Number
的转换,但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参数)。 你的情况T
是Value<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; }