泛型类型参数命名无强制规定但需统一:E多用于集合元素,T更通用;泛型方法必须声明<T>前缀;不可new T()或T[],需用Class<T>反射创建实例或Object[]转型。

泛型类定义时用 E 还是 T?其实没强制规定,但得统一
Java 里泛型类型参数命名是约定俗成的,不是语法要求。E 通常代表 Element(集合元素),多见于 ArrayList<E>;T 代表 Type,更通用,比如工具类中常见 Result<T>。
真正要小心的是别在一个类里混用:class Box<T, E> 看起来像两个不同含义,但如果都表示“装的东西”,反而让人困惑。选一个、用到底。
-
E更适合容器类、集合类,强调“被存取的元素” -
T更适合通用包装、转换、返回值场景,比如<T> T parse(String s) - 别用
A、B或中文拼音首字母——IDE 不会报错,但别人读代码时真会卡住
泛型方法声明必须带 <T> 前缀,漏了就编译不过
这是新手最常栽的地方:写了个方法想用泛型,却忘了在返回类型前加类型参数声明。比如想写一个通用交换方法:
public static <T> void swap(T[] arr, int i, int j) { ... }
如果写成 public static void swap(T[] arr, int i, int j),编译器根本不知道 T 是啥,直接报错:cannot resolve symbol T。
立即学习“Java免费学习笔记(深入)”;
- 泛型方法的
<T>必须紧挨着访问修饰符,不能丢、不能放后面 - 泛型方法可以独立于类的泛型存在——类没泛型,方法照样能用
<T> - 如果方法参数类型依赖泛型(如
List<T>),而你又没声明<T>,IDE 可能只提示“raw type”,但实际运行时类型擦除后逻辑可能出错
泛型类实例化不能用 new T(),反射才是正解
想在泛型类里构造 T 的实例?直接写 new T() 会编译失败:Cannot instantiate the type T。因为泛型在运行时已被擦除,JVM 不知道 T 具体是什么类。
常见替代方案是传入 Class<T> 对象:
public class Container<T> {
private final Class<T> type;
public Container(Class<T> type) { this.type = type; }
public T create() throws Exception { return type.getDeclaredConstructor().newInstance(); }
}
- 别试图绕过——
new Object()强转成T看似能编译,但会触发 unchecked warning,且运行时可能ClassCastException - 如果
T是接口或抽象类,getDeclaredConstructor().newInstance()会抛InstantiationException - Java 9+ 推荐用
type.getConstructor().newInstance()替代已弃用的getDeclaredConstructor()
泛型数组创建受限,new T[10] 是非法语法
Java 明确禁止直接创建泛型数组:T[] arr = new T[10]; 编译不过,报错:generic array creation。原因还是类型擦除——JVM 在运行时无法确保数组元素类型安全。
常用解法是先建原始类型数组,再强制转型(需配合 @SuppressWarnings("unchecked")):
T[] arr = (T[]) new Object[10];
- 这种转型只在内部使用安全(比如
ArrayList源码就这么干),对外暴露的 API 别这么写 - 如果用了
ArrayList<T>,就别硬造数组——它底层就是Object[],封装好了 - 用
Arrays.asList()或Stream.generate()构造泛型集合,比折腾数组更自然
? extends T,什么时候必须用 T,以及 Class<T> 传参时怎么避免类型丢失。这些不靠编译器提醒,全靠对擦除机制的理解是否到位。









