不能转换为非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<? extendsList<? extendsNumber>可以捕获 – 转换List<Integer>- 同样,一个
List<? extendsList<? extendsList<?>可以捕获 – 转换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; }