java泛型通配符和类型参数的范围
泛型里如果不限制类型参数,它可以接受任意已定义的类型。很多时候我们只需要其中一部分,用户传入其他类型会在运行期出错。本节先限制类型参数的范围,再讲通配符 ?。
例如编写一个泛型方法,返回 Integer、Double 等数组中的最大值:元素得能取数值,就不能让 T 是任意类型。
| 写法 | 用在哪 | 含义 |
|---|---|---|
| <T extends Number> | 声明泛型类 / 方法的类型参数 | T 只能是 Number 或其子类 |
| Point<?, ?> | 使用已经声明好的泛型类型 | 实参类型任意,避免擦成 Object |
| ? extends Number | 通配符上界 | Number 及其子类;适合取出 |
| ? super Number | 通配符下界 | Number 及其父类;适合放入 |
一、限制类型参数的范围
下面这段会编译失败:doubleValue() 是 Number 及其子类的方法,不是所有 T 都有。
用 extends 限制上限,让 T 只接受 Number 及其子类(Integer、Double、Long 等;Character 不是 Number 的子类)。这里的 extends 不再只表示继承:T 是某类的子类型,或 T 实现了某接口。上界若是类只能写一个;接口可以有多个,用 & 分隔,例如 T extends Number & Comparable<T>。
max 不能从 null 起步再调 doubleValue(),否则空数组或第一轮比较会空指针;应从第一个元素开始比。
二、通配符 ?
上一节用泛型类表示坐标,坐标可以是整数、小数或字符串:
若在类外定义 printPoint(Point p),没有写出类型实参时会发生类型擦除,相当于 Point<Object, Object>,和不用泛型差不多。要用通配符表示“任意类型的 Point”:
运行结果:This point is: 10, 20;This point is: 东京180度, 北纬210度。
三、通配符的上界和下界
数字坐标和字符串坐标含义不同:数字表示 x/y 轴,字符串表示经纬度。可以再限制通配符范围,让一个方法只接受数字坐标,另一个只接受字符串坐标。
运行结果:x: 10, y: 20;GPS: 东京180度,北纬210度。? extends Number 表示只能是 Number 及其子类。String 是 final 类,没有子类,因此 ? extends String 实际上只能是 String 本身。
通配符不但能限制上限,也能限制下限:? super Number 表示 Number 及其父类。一般项目里很少自己设计泛型,这里主要是学会怎么读、怎么用,给后面的集合教程铺路。
一句话总结:声明时用 T extends 卡住类型参数;使用时用 ?、? extends、? super 描述“未知但有范围”的实参,避免擦成裸 Object。
转载请注明来源:java泛型通配符和类型参数的范围







