我有一个抽象类定义为:
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();
eclipse出错:
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 {
}
答案 0 :(得分:4)
主要问题是因为您无法将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<BlackCat>
投入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>>
嗯,这两个通配符肯定没问题,它是关于数学归纳的......
答案 1 :(得分:2)
这里的问题是你有两个不同的通用定义可能是相同的:
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();
}
答案 2 :(得分:0)
泛型系统无法理解两行中指示的泛型类型(当应用于具体实现时)实际上在编译器执行其业务时引用相同的具体类型。
TCV<? extends MF> o = new TCVConcrete();
Map<String, MVR< ? extends MF>> map = o.operation();
在Serializable
的简单情况下,有许多类实现Serializable
,因此一个语句可能意味着一个类,另一个语句可能意味着另一个,因此这将无法编译。您需要在文件的顶部创建一个类型范围,然后对两个行使用相同的类型,或者实现MF的子类并将其用于两个行,而不是将其保留为浮动泛型类型。
答案 3 :(得分:0)
问题是你用的是两个?通配符,基本上说“MF或MF的一些未指定的子类”。但这可能意味着MF的两个不同的子类;这就是分配类型不匹配的原因。
你可能想要的是根本不使用通配符。这应该有效:
TCV<MF> o = new TCVConcrete();
Map<String, MVR<MF>> map = o.operation();