Java泛型上界疑问:为何<T extends Animal>无法适配子类集合?
问题描述
我希望killAll()方法能够接收任何存储Animal子类(如Dog类)对象的ArrayList,编写的代码如下:
import java.util.ArrayList; public class Animal{...} public class Dog{...} public class TestAnimal{ public static void killAll(ArrayList <T extends Animal> animals){ System.out.println("animals are dead"); } public static void main(String[] args){ ArrayList<Animal> simonAnimal = new ArrayList<>(); ArrayList<Dog> simonDog = new ArrayList<>(); killAll(simonAnimal); killAll(simonDog); } }
报错的代码行:
public static void killAll(ArrayList <T extends Animal> animals){
错误信息:Incorrect number of arguments for type ArrayList; it cannot be parameterized with arguments <T, Animal>
将<T extends Animal>替换为<? extends Animal>后代码可正常运行,想请教为何原写法无法生效?
问题解析
- 你原写法的核心问题是泛型方法的声明格式错误。
<T extends Animal>这种泛型参数的声明,必须放在方法返回值的前面,而不是直接嵌套在ArrayList的尖括号里。编译器会把你当前的写法误解为:给ArrayList传递了两个泛型参数T和Animal,但ArrayList本身只接受一个泛型参数,所以才抛出了“参数数量不正确”的错误。 - 如果想用泛型参数
T来实现需求,正确的写法应该是这样:
public static <T extends Animal> void killAll(ArrayList<T> animals){ System.out.println("animals are dead"); }
这样编译器会把<T extends Animal>识别为方法的泛型参数声明,表示这个方法可以接收任意T类型(T是Animal本身或其子类)的ArrayList实例。
- 而
<? extends Animal>是通配符,它代表一个未知的、继承自Animal的类型,专门用于这种只需要读取集合元素、不需要向集合写入数据的场景。它不需要提前声明泛型参数,直接写在集合的泛型位置即可,所以替换后代码能正常运行。
内容的提问来源于stack exchange,提问作者Simon Zhao
相关产品推荐
相关产品推荐

