[英]Java generics type mismatch
我有一个抽象类定义为:
public abstract class TCV<T extends MF> {
public Map<String, MVR<T>> operation() {
...
}
}
主要代码:
TCV<? extends MF> o = new TCVConcrete();
Map<String, MVR< ? extends MF>> map = o.operation();
日食错误:
Type mismatch: cannot convert from Map<String,MVR<capture#5-of ? extends MF>> to Map<String,MVR<? extends MF>>
编辑
public class TCVConcrete extends TCV<MFV2> {
}
public class MFV2 extends MF {
}
主要问题是因为您无法将Box<Tiger>
为Box<Cat>
,为什么? 你可以这样认为,
Box<Cat>
可以包含猫和老虎,但是Box<Tiger>
只能包含老虎。 如果将Box<Tiger>
投射到Box<Cat>
,然后将BlackCat
扔到Box<Tiger>
:
Box<Cat> catBox = tigerBox;
catBox.throwHere(new BlackCat());
然后,tigerBox被损坏。
让我将您的问题改写为:
public abstract class Company<T extends Cat> {
public Box<T> getFavBox() {
// ...
}
public Set<Box<T>> getBoxes() {
// ...
}
}
Company<? extends Cat> o = new ETCatCompany();
Box<? extends Cat> boxes = o.getFavBox(); // ok
Set<Box<? extends Cat>> boxes = o.getBoxes(); // error
如您所见, o.getFavBox()
可以工作,但o.getBoxes()
不能,为什么?
因为,您不能将任何混凝土猫扔进Box<? extends Cat>
Box<? extends Cat>
,这可能会损坏未知框。 但是,您可以将Box<BlackCat>
放入Set<Box<? extends Cat>>
Set<Box<? extends Cat>>
,这可能反过来破坏Set<Box<Tiger>>
。
或者,您可能认为它是:
Cat ^ Tiger => Cat
Box<Cat> ^ BigBox<Cat> => Box<Cat>
Box<Cat> ^ Box<Tiger> => Box<? extends Cat>
Box<Cat> ^ BigBox<Tiger>
=> (Box<Cat> ^ BigBox<Cat>) ^ (BigBox<Cat> ^ BigBox<Tiger>)
=> Box<Cat> ^ BigBox<? extends Cat>
=> Box<? extends Cat> ^ BigBox<? extends Cat>
=> Box<? extends Cat>
Set<Box<Cat>> ^ Set<BigBox<Cat>> => Set<? extends Box<Cat>>
Set<Box<Cat>> ^ Set<Box<Tiger>> => Set<? extends Box<? extends Cat>>
Set<Box<Cat>> ^ Set<BigBox<Tiger>> => Set<? extends Box<? extends Cat>>
? extends Cat ^ ? extends Tiger => ? extends Cat
Box<? extends Cat> ^ BigBox<? extends Cat> => Box<? extends Cat>
Box<? extends Cat> ^ Box<? extends Tiger>
=> ? extends Box<? extends (? extends Cat)>
=> ? extends Box<? extends Cat>
Set<Box<? extends Cat>> ^ Set<BigBox<? extends Cat>>
=> Set<? extends Box<? extends Cat>>
Set<Box<? extends Cat>> ^ Set<Box<? extends Tiger>> // You are here.
=> Set<? extends Box<? extends Cat>>
Set<Box<? extends Cat>> ^ Set<BigBox<? extends Tiger>>
=> Set<? extends Box<? extends Cat>>
或更可能的是,给出几个operation()调用:
Map<String, MVR<?1 extends MF>> x1 = o.operation();
Map<String, MVR<?2 extends MF>> x2 = o.operation();
...
Map<String, MVR<?n extends MF>> x2 = o.operation();
那么,什么是通用类型?
x1 ^ x2 ^ ... ^ xn
=> Map<String, MVR<?1 extends MF>> ^ Map<String, MVR<?2 extends MF>> ^ ...
=> Map<String, ? extends MVR<? extends MF>> ^ ...
...
=> Map<String, ? extends MVR<? extends MF>>
好吧,两个通配符绝对没错,这是关于数学归纳的...
这里的问题是,您有两个可能相同的通用定义:
TCV<? extends MF> o = new TCVConcrete();
^^^^^^^^^^^^
Map<String, MVR< ? extends MF>> map = o.operation();
^^^^^^^^^^^^^^
虽然这两个可以指向同一类型,但它们也可以指向MF的两个不同子类型。 编译器不喜欢这样。
您可以使用专用方法中的类型变量来解决该问题。
这应该工作:
public void <T extends MF> doSomething(){
TCV<T> o = new TCVConcrete();
Map<String, MVR<T>> map = o.operation();
}
泛型系统无法理解,当编译器进行业务时,两行中指示的泛型类型(当应用于具体实现时)实际上是指相同的具体类型。
TCV<? extends MF> o = new TCVConcrete();
Map<String, MVR< ? extends MF>> map = o.operation();
在Serializable
的简单情况下,有许多类实现Serializable
,因此一个语句可能意味着一个类,而另一条语句可能意味着另一个类,因此将无法编译。 您需要在文件顶部创建类型作用域,然后对两行使用相同的类型,或者实现MF的子类并将其用于两行,而不是将其保留为浮动泛型类型。
问题是您使用的是两个? 通配符,基本上说“ MF或MF的某些未指定子类”。 但这可能意味着MF的两个不同子类。 这就是分配类型不匹配的原因。
您可能想要的是根本不使用通配符。 这应该工作:
TCV<MF> o = new TCVConcrete();
Map<String, MVR<MF>> map = o.operation();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.