java泛型类与接口的类型参数必须声明在类/接口名后、花括号前,用尖括号包裹,多个参数逗号分隔;命名推荐t、e、k/v等单字母;可独立用于字段、方法参数及返回值,但不可用于静态上下文、new t()或基本类型;实例化时须传入具体类型实参以启用类型检查。

Java 中定义和使用泛型接口与泛型类的类型参数,核心在于明确“声明位置”“命名规范”“使用范围”和“实例化约束”。不是写上
泛型类中类型参数的正确定义与使用
类型参数必须声明在类名后、花括号前,用尖括号包裹,多个参数用逗号分隔。每个参数可独立用于字段、方法参数、返回值、局部变量类型,但不能用于静态上下文或构造器签名(构造器本身不声明泛型,但可使用已声明的类型参数)。
- 命名推荐使用语义化单字母:T(Type)、E(Element)、K/V(Key/Value)、S/T(Source/Target),避免用 Object 或具体类名作形参
- 字段和方法中直接使用,如 private T data;、public void set(T value)、public T get()
- 不能用类型参数创建实例:new T() 编译失败;也不能作为异常类型或数组元素类型(T[] arr = new T[10] 非法,需用 (T[]) new Object[10] 并加 @SuppressWarnings("unchecked")
- 带边界的写法示例:class Box
> ,表示 T 必须是 Number 子类且可比较
泛型接口中类型参数的正确定义与使用
接口的泛型声明方式与类一致,放在接口名后。多参数常见于数据转换、映射、事件处理等契约场景,强调“能力抽象”,而非具体实现。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 典型双参数接口:interface Mapper
{ T map(S source); },S 是输入源类型,T 是目标类型,二者完全解耦 - 可带约束:interface Pair
, V> ,限定 K 可自然排序,V 无限制 - 函数式接口也支持多泛型,如 JDK 自带的 BiConsumer
,其 accept(T t, U u) 方法天然适配两种输入类型 - 实现该接口时,要么传入具体类型(如 class UserMapper implements Mapper
),要么延续泛型(class GenericMapper implements Mapper)
继承与实现时的类型参数传递规则
子类或实现类必须对父类/接口声明的每个类型参数给出明确交代——不能遗漏、不能错位、不能擅自增减数量。
- 正确示例:class SafeList
extends ArrayList ,父类需一个参数,子类提供一个对应参数 E - 错误示例:class Bad extends ArrayList
虽可编译,但丧失泛型灵活性,属于“泛型退化”,应避免 - 若父类有多个参数,子类必须一一匹配:class Three extends Two 合法;而 class Three
extends Two 会报错,因为 A、B 在当前作用域未声明 - 实现接口时若指定实参,所有方法签名将按实参展开;若保持泛型,则子类仍需承担类型参数声明责任
注意类型擦除带来的实际限制
泛型只在编译期存在,运行时所有类型参数都被擦除为边界上限(无界则为 Object)。这意味着:
- 无法在运行时获取泛型实际类型,obj.getClass().getTypeParameters() 返回的是形参声明,不是实参
- 不能用基本类型作为类型参数,List
非法,必须用包装类 List - 不能基于泛型类型做重载区分,void handle(List
) 和 void handle(List) 编译不通过(擦除后都是 List) - 反射中获取泛型信息需通过 Method.getGenericReturnType() 或 Field.getGenericType(),而非 getClass()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










