@target(elementtype.type_parameter)专用于泛型类型参数声明处,如类、接口或方法的、位置,不可用于实际类型使用场景;需显式声明,不被其他elementtype覆盖,配合annotatedtype反射获取。

@Target(ElementType.TYPE_PARAMETER) 是 Java 8 引入的元注解配置,专门用于将自定义注解标注在泛型类型参数声明处,比如类、接口或方法的 <t></t>、<k v></k> 这类位置。它不能作用于泛型的实际使用位置(如 List<string></string> 中的 String),那是 TYPE_USE 的职责。
为什么必须显式声明 TYPE_PARAMETER?
Java 不会自动把 @Target(ElementType.TYPE) 或 @Target(ElementType.METHOD) 推广到泛型形参上。TYPE_PARAMETER 是独立且明确的靶点,不被其他 ElementType 覆盖。
正确配置方式
@Target(ElementType.TYPE_PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface NonNullType {
}
这个注解现在只能写在泛型声明的尖括号里,例如:
// ✅ 合法:用在类的泛型参数上
public class Box {
private T value;
}
// ✅ 合法:用在接口的泛型参数上
public interface Processor {
O process(I input);
}
// ✅ 合法:用在泛型方法的类型参数上
public T getOrDefault(T defaultValue) {
return defaultValue;
}
⚠️ 注意这些非法用法会直接编译失败:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
Box<string></string>中给String加@NonNullType→ 错,这是类型使用,该用TYPE_USE -
private @NonNullType String name;→ 错,字段上要用FIELD或TYPE_USE -
public void foo(@NonNullType String s)→ 错,参数上要用PARAMETER或TYPE_USE
和 TYPE_USE 的关键区别
| 场景 | TYPE_PARAMETER |
TYPE_USE |
|---|---|---|
class Result<t></t> 中的 T
|
✅ 支持 | ❌ 不匹配(这不是“使用”,是“声明”) |
List 中的 String
|
❌ 不支持 | ✅ 支持 |
new ArrayList() |
❌ | ✅ |
T parse(...) 中的 T
|
✅ | ❌(此处是声明,不是使用) |
简单记:声明泛型变量用 TYPE_PARAMETER;使用(实例化、转型、强制泛型上下文)用 TYPE_USE。
实际用途举例
这类注解常配合编译期检查工具(如 Error Prone、Checker Framework)做静态分析:
- 标记
@KeyFor("map") T表示该类型参数必须是某 map 的合法 key 类型 - 标记
@NullableType T表示泛型可为空,影响类型推导 - 框架通过反射读取时,需确保
AnnotatedType(而非Type)才能拿到TYPE_PARAMETER注解信息
反射获取示例:
AnnotatedType annotatedSuper = Box.class.getAnnotatedSuperclass();
if (annotatedSuper instanceof AnnotatedParameterizedType apType) {
AnnotatedType[] typeArgs = apType.getAnnotatedActualTypeArguments();
// typeArgs[0] 对应 <t>,其上的注解可通过 getAnnotations() 获取
}</t>
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










