无法使用泛型转换为非特定嵌套类型

时间:2010-08-26 13:46:15

标签: java generics casting

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

类型不匹配:无法从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;
    }
}

5 个答案:

答案 0 :(得分:17)

使用以下内容:

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

问题是?中的Msg<Value<?>> objMsg NOT 能够捕获转化。它不是Msg 某种类型的Value。它是“{{1>} ANY 类型的Msg

这也解释了为什么随着声明的变化,我还将变量重命名为ValuesomeMsg不能只是Value。它必须属于某些类型(在此示例中为Object)。


更通用的例子

让我们考虑String的更通用的例子。类似于原始方案,List<List<?>>可以 NOT 捕获转换List<List<?>>

List<List<Integer>>

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

  • Java泛型是类型不变的
  • 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>

相关问题

另见

答案 1 :(得分:3)

虽然您的泛型类型参数包含通配符,但它本身不是通配符。在使用非通配符泛型类型Msg<T>分配变量(T)时,所分配的对象必须具有与其通用类型完全相同的T(包括{{的所有泛型类型参数) 1}},通配符和非通配符)。在您的情况下,TT,与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;
}