如何让泛型类IntArrayList仅接受Integer类型?
首先得说清楚:你用T instanceof Integer报错,核心原因是Java的泛型类型擦除机制——编译后所有泛型参数T都会被擦除成它的上界(这里因为NewArrayList继承的ArrayList没指定上界,所以T会变成Object),所以运行时JVM根本不知道T原本是什么类型,而且编译器也不允许你用类型变量和instanceof做比较,这语法本身就不合法。
那怎么实现IntArrayList仅接受Integer类型呢?给你两个方案,按推荐程度排序:
方案一:直接去掉泛型,指定父类的类型参数(最优解)
既然你明确只需要Integer类型,那完全没必要给IntArrayList加泛型T,直接让它继承NewArrayList<Integer>就行。这样编译时就会强制检查所有操作的类型,根本不需要运行时判断,安全又高效:
public class IntArrayList extends NewArrayList<Integer> { // 这里写仅Integer可用的方法,比如求和之类的 public int sum() { int total = 0; for (Integer num : this) { total += num; } return total; } }
用这个方案的话,别人如果想往IntArrayList里加非Integer的元素,编译器直接就报错了,从根源上杜绝了错误。
方案二:保留泛型,但通过Class对象绑定类型(适合特殊场景)
如果你因为某些特殊原因必须保留泛型T,那可以通过在构造时传入Class<T>对象来保留类型信息,同时在构造和添加元素时做检查:
public class IntArrayList<T> extends NewArrayList<T> { private final Class<T> elementType; // 构造时必须传入类型Class对象,强制检查是否为Integer public IntArrayList(Class<T> elementType) { if (!Integer.class.equals(elementType)) { throw new IllegalArgumentException("IntArrayList only accepts Integer type"); } this.elementType = elementType; } // 重写add方法,再次检查元素类型(防止通过原始类型或强制转换绕过构造检查) @Override public boolean add(T element) { if (!(element instanceof Integer)) { throw new ClassCastException("Only Integer elements are allowed"); } return super.add(element); } // 仅Integer可用的方法示例 public int sum() { int total = 0; for (T num : this) { total += (Integer) num; // 这里可以安全强转,因为已经做过检查 } return total; } }
使用时必须这样创建实例:
IntArrayList<Integer> list = new IntArrayList<>(Integer.class);
如果传入其他类型的Class对象,比如String.class,构造时直接抛出异常。
为什么不能用T instanceof Integer?
再强调一遍:Java泛型是编译期特性,运行时泛型参数会被擦除。比如你写IntArrayList<String>,编译后T会变成Object,JVM完全不知道原来的T是String还是Integer。而且编译器也不允许你用类型变量T和instanceof一起使用,这属于语法错误,因为instanceof要求右边是具体的引用类型,而不是一个类型变量。
内容的提问来源于stack exchange,提问作者Samplasion

