使用super关键字定义泛型的允许参数类型及编译错误解惑
泛型中super关键字的使用疑问解答
一、super关键字定义泛型时允许的参数类型
- 允许指定类型及其所有父类/父接口,涵盖继承体系里的直接父类和间接父类。比如指定
String的话,合法的类型包括String、Object;如果是自定义类继承体系(如Child extends Parent extends GrandParent),那? super Child允许的类型就是Child、Parent、GrandParent、Object。 - 对于接口来说,
? super 子接口允许的类型包括该子接口、所有父接口以及Object。
二、Function<? super String, Integer>编译错误的原因
先看你的代码:
public void method(Function<? super String, Integer> mapper) { mapper.apply(new Object()); // 编译错误 mapper.apply(new String()); // 无错误 }
你搞反了? super String的作用逻辑。Function的第一个泛型参数是输入类型,? super String表示这个输入类型是String的某个父类(包括String自己),但具体是哪一个我们无法确定——它可能是Function<String, Integer>,也可能是Function<Object, Integer>。
编译器要保证类型安全,所以只允许传入所有可能的输入类型都能接受的参数:
- 如果mapper实际是
Function<String, Integer>,它的apply方法只能接受String类型,传Object进去肯定不兼容; - 如果mapper是
Function<Object, Integer>,传Object是可以的,但编译器不能确定mapper到底是哪种情况。
所以唯一安全的参数是String(以及它的子类,但String是final类没有子类),因为不管输入类型是String的哪个父类,String都能向上转型成该类型。而Object不能向下转型成String,所以当mapper实际是Function<String, Integer>时,传Object就会出错,编译器直接禁止这种不确定的操作。
内容的提问来源于stack exchange,提问作者Piotrold
相关产品推荐
相关产品推荐

