Java接口泛型约束通过声明类型参数并限定上界,保障编译期类型安全;支持单/多边界、方法级泛型、有界通配符及Class传递规避类型擦除限制。

Java 接口中使用泛型约束,核心是通过在接口声明时定义类型参数,并结合 extends(或 &)限定其上界,从而在编译期捕获类型不匹配问题,保障类型安全。
接口定义时声明带边界约束的泛型参数
在接口名后用 <t extends sometype></t> 声明类型参数,并指定其必须是某类或某接口的子类型。这样所有实现类和使用者都必须遵守该约束。
-
单边界示例:
interface Repository<t extends entity> { T findById(Long id); }</t>—— 要求所有传入的T必须是Entity或其子类,方法返回值也自动具备Entity的可见成员。 -
多边界示例:
interface Processor<t extends comparable> & Cloneable></t>——T必须同时实现Comparable和Cloneable,否则编译失败。
在方法签名中复用或细化泛型约束
接口中的方法可复用接口级泛型,也可声明独立的、带约束的局部泛型,增强灵活性。
- 复用接口泛型:
<t> List<t> findAll(Class<t> type)</t></t></t>中的T是方法级泛型,与接口泛型无关;若想关联,应写为List<t> findAll()</t>(前提是接口已声明<t extends domainobject></t>)。 - 方法级约束:
<u extends number> double sum(List<u> numbers)</u></u>保证传入列表元素可安全参与数值运算,且调用时由编译器推断U(如Integer、BigDecimal),避免运行时ClassCastException。
配合通配符提升 API 安全性与灵活性
在方法参数中使用有界通配符(? extends / ? super),比裸泛型更严谨,明确读写边界。
立即学习“Java免费学习笔记(深入)”;
-
void saveAll(Collection extends Person> persons):只读取persons,允许传入ArrayList<student></student>或LinkedList<teacher></teacher>,但禁止向其中添加任意对象(因具体子类型未知)。 -
void consume(Consumer super Employee> action):可安全接受Consumer<person></person>(因Employee是Person子类),符合 PECS 原则(Producer Extends, Consumer Super)。
避免常见陷阱:擦除后仍需逻辑校验
泛型在运行时被擦除,所以 instanceof T 或 new T() 不合法。若需运行时类型信息,应显式传递 Class<t></t> 参数。
- 错误写法:
T create() { return new T(); }→ 编译报错。 - 正确写法:
<t> T create(Class<t> clazz) throws Exception { return clazz.getDeclaredConstructor().newInstance(); }</t></t>—— 利用反射+类型参数约束,既保留编译期安全,又支持动态实例化。 - 注意:泛型约束不能防止运行时传入错误的
Class对象,所以实际使用中仍建议配合isAssignableFrom校验,例如if (!Entity.class.isAssignableFrom(clazz)) throw new IllegalArgumentException();


















