【发布时间】:2019-08-06 11:52:32
【问题描述】:
这是我试图理解的编译器行为的过度简化版本:
class Scratch {
public static void main(String[] args) {
HouseCat<? extends Mammal> hcat = new Tabby();
//HouseCat<Mammal> won't work, compiler catches incorrect type parameter bound
HouseCat<CrazyHouseCat> crazyCat = new Tabby();
}
}
interface Mammal<T extends Mammal> extends Comparable<T>{
T cloneInstance();
}
interface Feline<T extends Feline> extends Mammal<T>{}
interface HouseCat <T extends HouseCat> extends Feline<T>{}
interface CrazyHouseCat<T extends CrazyHouseCat> extends HouseCat<T>{
void pushStuffOverTvStand();
}
class Tabby implements CrazyHouseCat<CrazyHouseCat>{
@Override
public CrazyHouseCat cloneInstance() {
return null;
}
@Override
public void pushStuffOverTvStand() {
}
@Override
public int compareTo(CrazyHouseCat o) {
return 0;
}
}
在上面的 sn-p 中,HouseCat<? extends Mammal> 是一个比 HouseCat 接口允许的类型范围更广的引用,即:HouseCat<T extends HouseCat>
如果我尝试做类似HouseCat<Long> 的事情,编译器会告诉我Long 不满足类型参数的约束。好吧,<? extends Mammal> 不是这样,至少可能是这样。
编译器不允许我创建一个违反类型参数T 约束的实例,但我对它关于使用Mammal 作为引用上限的行为感到困惑。 (HouseCat,Mammal] 之间的类型范围无效,为什么编译器不会拒绝这个引用定义?
说明:
我的问题不是关于通配符? 的含义。我在问为什么编译器允许使用比参数化类型定义所允许的更广泛的类型来定义对参数化类型实例的引用。提到的问题并未解决这种特定情况,它们与通配符的含义有关。我的问题是关于通配符的有效范围,编译器似乎没有强制执行。
【问题讨论】:
-
我不确定您要做什么,但是您发布的代码中有很多原始类型,这不是一个好主意。
-
@SharonBenAsher 我不这么认为。请参阅我的说明。
-
` //HouseCat
不起作用,编译器捕获不正确的类型参数绑定` - 因为 Mammal 没有扩展 Mammal -
@ACV 不,它不会起作用,因为 Mammal 是 HouseCat 类型参数(再次是 HouseCat)允许类型的超类型。扩展自身的类型是 Java 泛型中的有效类型参数