我有两个嵌套泛型的类。有没有办法摆脱
类型不匹配:无法从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;
}
}
答案 0 :(得分:17)
使用以下内容:
Msg<? extends Value<?>> someMsg = strMsg;
问题是?
中的Msg<Value<?>> objMsg
NOT 能够捕获转化。它不是Msg
某种类型的Value
。它是“{{1>} ANY 类型的Msg
”
这也解释了为什么随着声明的变化,我还将变量重命名为Value
。 someMsg
不能只是Value
。它必须属于某些类型(在此示例中为Object
)。
让我们考虑String
的更通用的例子。类似于原始方案,List<List<?>>
可以 NOT 捕获转换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"
转换为 Integer
,但是{ {1}} Number
List<
不是Integer
>
强> List<
Number
可以通过 >
,但List<Integer>
List<?>
List<
不是List<Integer>
{{1 }} 强> >
List<
List<?>
>
可以捕获转换List<? extends
Number
强> >
List<
Integer
>
可以捕获转换List<? extends
List<?>
强> >
某些List<
可以捕获的事实和其他人也无法解释以下代码段:
List<Integer>
List<List<? extends Number>>
List<Animal> animals = new ArrayList<Dog>()
? <E extends Number>
and <Number>
? 答案 1 :(得分:3)
虽然您的泛型类型参数包含通配符,但它本身不是通配符。在使用非通配符泛型类型Msg<T>
分配变量(T
)时,所分配的对象必须具有与其通用类型完全相同的T
(包括{{的所有泛型类型参数) 1}},通配符和非通配符)。在您的情况下,T
为T
,与Value<String>
的类型不同。
您可以执行的操作,因为Value<?>
可分配给Value<String>
,使用通配符类型:
Value<?>
答案 2 :(得分:3)
我的回答与另一回答相似,但希望更清楚。
List<List<?>> is a list of (lists of anything).
List<List<String>> is a list of (lists of strings).
后者无法转换为前者,因为这样做会允许您添加List&lt; Number&gt;到你的列表&lt; List&lt; String&gt;&gt;,这显然会被打破。
请注意,如果使用某些没有.add的类型替换List,则不会更改此规则。 Java需要声明 - 站点协方差和/或逆变(就像C#的IEnumerable&lt; out T&gt;或Scala的列表[+ A])。 Java只有使用站点协方差和逆变(?扩展X,?超级X)。
答案 3 :(得分:1)
不是直接的答案,但我强烈建议阅读:http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf以更好地理解泛型。
答案 4 :(得分:0)
ILMTitan有一个很好的解决方案,如果你不想让这个类特定于Value,你可以在这一点上使用基类型而不是泛型,因为你将关闭一个安全功能,但那里不在。您甚至可以传递参数以使此方法更通用,但关键是“@SuppressWarnings”。
@SuppressWarnings("unchecked")
Msg<Value<?>> convert()
{
return (Msg<Value<?>>) this;
}