JAVA之注解
JAVA之注解
注解(Annotation)详细介绍
注解 是 Java 编程语言中的一种元数据机制,用于在源码中添加附加信息。注解可以用于类、方法、字段、参数等位置,为编译器、工具或运行时环境提供额外的指示。注解不会直接影响代码的执行逻辑,但可以在编译时、类加载时或运行时被处理,提供一些额外的功能或约束。
注解的作用
- 编译器使用的注解:
@Override
:用于表示一个方法是从父类重写过来的。编译器会检查这个方法是否真的覆写了父类的方法。如果没有,编译器将会报错。@SuppressWarnings
:告诉编译器在指定的代码部分忽略某些警告。例如,@SuppressWarnings("unchecked")
可以用来忽略类型安全的警告。- 这些注解在编译器处理后不会被保留到
.class
文件中,它们仅用于编译时的检查。
- 工具处理的注解:
- 一些工具在处理
.class
文件时可能会使用注解,例如字节码修改工具、代码生成工具等。这类注解会被编译到.class
文件中,但在程序运行时通常不会被访问。 - 示例:某些框架(如
Hibernate、Spring)使用注解来配置类的行为,工具会在加载
.class
文件时读取这些注解来生成所需的配置。
- 一些工具在处理
- 运行时读取的注解:
- 这些注解在程序运行时可以被反射机制读取。例如,使用
@PostConstruct
注解的方法会在对象创建后自动被调用。这类注解会被保留在.class
文件中,并可以在运行时通过反射获取。 - 常见的运行时注解:
@Entity
、@Transactional
、@Autowired
。
- 这些注解在程序运行时可以被反射机制读取。例如,使用
注解的定义
注解的定义语法如下:
1 | import java.lang.annotation.ElementType; |
@Retention
:指定注解的保留策略。RetentionPolicy.SOURCE
:注解只保留在源码中,编译后不保留。RetentionPolicy.CLASS
:注解保留在.class
文件中,但运行时不可见。RetentionPolicy.RUNTIME
:注解保留在.class
文件中,且在运行时可见。
@Target
:指定注解的应用位置。例如:ElementType.FIELD
:注解可以用于字段。ElementType.METHOD
:注解可以用于方法。
注解的配置参数
注解的参数可以是以下类型:
- 基本类型:
int
、float
、boolean
等。 String
类型。- 枚举类型。
Class
类型。- 上述类型的数组。
注解的参数可以有默认值,未指定参数时将使用默认值。常用的参数名为
value
,当注解只有一个参数时,可以省略参数名:
1 | public Check { |
注解的使用示例
1 | public class Hello { |
@Check(min = 0, max = 100, value = 55)
:为字段n
定义了min
、max
和value
参数。@Check(value = 99)
:仅定义了value
参数,等同于@Check(99)
。@Check(99)
:省略了value
参数名,等同于@Check(value = 99)
。@Check
:使用默认值,没有显式指定参数。
- 注解 是一种为代码提供元数据的机制,不直接影响代码逻辑。
- 注解可用于编译时检查、工具处理、运行时读取等多种场景。
- 可以定义注解,并为其设置参数,参数可以有默认值。
- 注解的配置参数类型有限制,必须是常量。
定义注解
在Java中,定义注解(Annotation)是一种创建可用于代码的元数据的方式。注解本身不会直接影响程序的运行,但它们可以被编译器、开发工具或运行时环境读取和处理。
1. 定义注解
使用@interface
关键字定义注解。注解定义的格式如下:
1 | public Report { |
@interface
关键字用于定义注解类型。- 注解定义通常是空的,除非需要添加配置参数。
2. 添加参数和默认值
在注解中,可以定义参数和默认值。注解的参数类似于方法参数,可以使用default
关键字设置默认值。推荐使用value
作为最常用的参数名。示例如下:
1 | public Report { |
- 参数定义遵循普通方法的语法规则,但它们是常量,并且必须有默认值。
3. 使用元注解
元注解(Meta-Annotations)是用于修饰其他注解的注解。Java标准库提供了几个常用的元注解:
@Target
定义注解可以应用于代码中的哪些元素(如类、方法、字段等)。例如:
1 |
|
ElementType
指定了注解的目标位置,如TYPE
(类或接口)、FIELD
(字段)、METHOD
(方法)等。
这段代码定义了一个名为
Report
的自定义注解(Annotation)。1. 注解定义
1
2
3
4
5
6
public Report {
int type() default 0;
String level() default "info";
String value() default "";
}
@Target(ElementType.METHOD)
@Target
是一个元注解,用于指定注解可以应用的目标元素类型。ElementType.METHOD
表示该注解只能用于方法上。也就是说,@Report
只能应用于方法,而不能应用于字段、类等其他元素上。
public @interface Report
public
:这是注解的访问修饰符,意味着它可以在任何地方被使用。@interface
:用于定义一个注解类型。@interface
是Java语言中定义注解的关键字。
int type() default 0;
- 这是一个名为
type
的注解参数。int
表示该参数的类型是整数。default 0
表示如果在使用@Report
注解时没有提供type
参数的值,则默认值为0
。
String level() default "info";
- 这是一个名为
level
的注解参数。String
表示该参数的类型是字符串。default "info"
表示如果在使用@Report
注解时没有提供level
参数的值,则默认值为"info"
。
String value() default "";
- 这是一个名为
value
的注解参数。String
表示该参数的类型是字符串。default ""
表示如果在使用@Report
注解时没有提供value
参数的值,则默认值为空字符串""
。- 在许多注解中,
value
是一个常用的默认参数名。如果注解只有一个参数,通常可以省略参数名直接指定值。总结
这段代码定义了一个名为
Report
的注解,该注解可以用于方法上。它包含三个参数:
type
:一个整数类型的参数,默认值为0
。level
:一个字符串类型的参数,默认值为"info"
。value
:一个字符串类型的参数,默认值为空字符串""
。你可以在代码中使用这个注解来标记方法,并通过这些参数提供额外的信息或配置。比如:
1
2
3
4
public void init() {
// method implementation
}在这个例子中,
init
方法被标记为@Report
注解,并且为type
、level
和value
参数提供了具体的值。这些值可以在运行时通过反射读取,以实现动态处理或配置。
@Retention
定义注解的生命周期,即注解的存活时间。它有三个值:
RetentionPolicy.SOURCE
:注解仅在源代码中存在,编译后丢弃。RetentionPolicy.CLASS
:注解保留在.class文件中,但在运行时不可用。RetentionPolicy.RUNTIME
:注解保留在运行时,可以通过反射读取。
例如:
1 |
|
RetentionPolicy.RUNTIME
允许在程序运行时通过反射读取注解。
@Repeatable
定义一个注解是否可以重复使用。通常,注解只能在一个目标上出现一次,但使用@Repeatable
可以允许注解重复。示例如下:
1 |
|
@Repeatable
允许在一个目标上应用多个相同的注解。
这段代码定义了一个可以重复使用的注解
@Report
和一个用于容纳多个@Report
注解的注解@Reports
。1.
@Repeatable
注解
1
2
3
4
5
6
7
public Report {
int type() default 0;
String level() default "info";
String value() default "";
}
@Repeatable(Reports.class)
:这是一个元注解,用于标记@Report
注解可以被重复使用。@Repeatable
指定了一个容器注解类Reports
,该类用于存放多个@Report
注解实例。@Target(ElementType.TYPE)
:表示@Report
注解可以应用于类型(类、接口等)上。@interface Report
:定义了一个注解类型Report
。- 注解参数:
type
、level
和value
,分别有默认值0
、"info"
和""
。2.
@Reports
注解
1
2
3
4
public Reports {
Report[] value();
}
@Target(ElementType.TYPE)
:表示@Reports
注解可以应用于类型(类、接口等)上。@interface Reports
:定义了一个容器注解类型Reports
。Report[] value()
:@Reports
注解包含一个Report
数组,存储多个@Report
注解实例。总结
@Report
是一个可重复使用的注解,可以应用于类、接口等类型上。它可以存储三个参数:type
、level
和value
。@Reports
是一个容器注解,用于存放多个@Report
注解实例。它包含一个Report
数组value
。通过使用
@Repeatable
和@Reports
,你可以在一个类上使用多个@Report
注解实例,而不需要为每个注解定义一个新的容器。
@Inherited
定义子类是否可以继承父类的注解。@Inherited
仅适用于类(ElementType.TYPE
),并且仅针对类的继承有效。
1 |
|
@Inherited
确保子类可以继承父类的注解。
代码解释
1
2
3
4
5
6
7
public Report {
int type() default 0;
String level() default "info";
String value() default "";
}1.
@Inherited
- 定义:
@Inherited
是一个元注解,用于指示注解是否可以被子类继承。- 作用: 当一个注解类(例如
@Report
)被@Inherited
修饰时,子类会自动继承该注解。- 适用范围:
@Inherited
仅适用于类(即@Target(ElementType.TYPE)
)的继承关系,而不适用于接口或方法等其他元素的继承。2.
@Target(ElementType.TYPE)
- 定义:
@Target
是一个元注解,用于指定注解可以应用于代码的哪些部分。- ElementType.TYPE: 表示
@Report
注解可以应用于类和接口(即类型上)。3.
public @interface Report
@interface
: 这是 Java 中定义注解的关键字。Report
: 这是自定义的注解类型名。它可以被应用于类、接口等类型上。4. 注解参数
int type() default 0
:type
是一个参数,类型为int
,默认值为0
。String level() default "info"
:level
是一个参数,类型为String
,默认值为"info"
。String value() default ""
:value
是一个参数,类型为String
,默认值为空字符串""
。使用示例
假设我们有一个父类使用了
@Report
注解:
1
2
3
public class Parent {
}如果我们定义一个子类
Child
继承自Parent
:
1
2 public class Child extends Parent {
}由于
Parent
类使用了@Inherited
注解,Child
类会自动继承@Report
注解。即使Child
类没有显式地声明@Report
注解,它也会继承Parent
类的@Report
注解,Child
类的行为等同于Parent
类的@Report
注解。总结
@Inherited
使得注解可以被子类继承。@Target(ElementType.TYPE)
表明注解可以应用于类和接口。- 注解
Report
包含三个参数,type
、level
和value
,它们都有默认值。这个机制对于需要在类继承层次结构中共享元数据(如配置、标记等)非常有用。
定义注解的步骤包括:
- 使用
@interface
关键字定义注解。 - 添加参数并设置默认值,常用参数名为
value
。 - 使用元注解配置注解的行为,包括目标位置
(
@Target
)、生命周期 (@Retention
)、是否可重复 (@Repeatable
)、是否可继承 (@Inherited
)。
大多数自定义注解通常需要配置 @Target
和
@Retention
,其中
@Retention(RetentionPolicy.RUNTIME)
是最常用的设置。根据实际需求,可以选择使用其他元注解来增强注解的功能。
处理注解
Java注解(Annotation)本身不直接影响代码逻辑。其主要作用是提供元数据,如何使用这些元数据完全由程序或工具决定。根据
@Retention
的配置,注解的生命周期分为三种类型:
- SOURCE: 注解在编译时丢弃,不会保留在
.class
文件中。 - CLASS: 注解保留在
.class
文件中,但不会被加载到 JVM 中。 - RUNTIME: 注解在运行时保留,并可通过反射 API 读取。
使用反射 API 读取 RUNTIME 注解
判断注解是否存在
1
2// 判断Person类是否有@Report注解
boolean hasReport = Person.class.isAnnotationPresent(Report.class);解释
Person.class
:- 这表示
Person
类的Class
对象。在 Java 中,Class
对象用于获取有关类的信息,例如其字段、方法和注解。
- 这表示
isAnnotationPresent(Class<Annotation> annotationClass)
:- 这是
Class
类中的一个方法,用于检查指定的注解是否存在于该类上。 - 参数
annotationClass
是要检查的注解的Class
对象,例如Report.class
。
- 这是
Report.class
:- 这是
Report
注解的Class
对象。Report.class
表示Report
注解类型的Class
对象,用于在isAnnotationPresent
方法中传递。
- 这是
- 返回值
boolean
:- 这个方法返回一个布尔值,指示
Person
类上是否存在@Report
注解。 - 如果
Person
类上存在@Report
注解,isAnnotationPresent
返回true
;如果不存在,返回false
。
- 这个方法返回一个布尔值,指示
这段代码的目的是检查
Person
类上是否应用了@Report
注解。它使用Class.isAnnotationPresent
方法来确定注解是否存在,并将结果存储在hasReport
变量中。这样可以在程序中动态决定是否处理类的特定注解。读取注解
1
2
3
4// 获取Person类上的@Report注解
Report report = Person.class.getAnnotation(Report.class);
int type = report.type();
String level = report.level();这段代码用于获取
Person
类上的@Report
注解,并从中提取注解的值。解释
Person.class.getAnnotation(Report.class)
:Person.class
是Person
类的Class
对象。这表示Person
类的元数据,可以用来检索关于Person
类的各种信息。getAnnotation(Class<T> annotationClass)
是Class
类中的一个方法,用于获取指定的注解类型。如果该注解存在于该类上,方法将返回该注解的实例;否则,返回null
。Report.class
是Report
注解的Class
对象。它被传递给getAnnotation
方法以指定要查找的注解类型。
Report report
:- 这行代码从
Person
类中获取@Report
注解的实例。如果Person
类上存在@Report
注解,getAnnotation(Report.class)
将返回该注解实例,并将其赋值给report
变量。 - 如果
Person
类上没有@Report
注解,report
将为null
。
- 这行代码从
int type = report.type()
:- 从
report
对象中调用type()
方法,获取注解@Report
的type
属性值。 type()
方法是@Report
注解中定义的一个方法,用于获取type
参数的值。它返回一个int
类型的值,这个值是在定义@Report
注解时指定的。
- 从
String level = report.level()
:- 从
report
对象中调用level()
方法,获取注解@Report
的level
属性值。 level()
方法是@Report
注解中定义的一个方法,用于获取level
参数的值。它返回一个String
类型的值,这个值是在定义@Report
注解时指定的。
- 从
示例
假设
@Report
注解定义如下:1
2
3
4
5
6
7
public Report {
int type() default 0;
String level() default "info";
String value() default "";
}并且
Person
类上有如下注解:1
2
3
public class Person {
}执行上述代码后:
Report report = Person.class.getAnnotation(Report.class);
将获得@Report
注解的实例。int type = report.type();
将返回1
,因为type
被设置为1
。String level = report.level();
将返回"debug"
,因为level
被设置为"debug"
。
方法、字段和构造方法
方法
1
2Method method = Person.class.getMethod("someMethod");
Report report = method.getAnnotation(Report.class);这段代码用于获取
Person
类中的someMethod
方法上的@Report
注解,并将其存储在report
变量中。1
2Method method = Person.class.getMethod("someMethod");
Report report = method.getAnnotation(Report.class);解释
Method method = Person.class.getMethod("someMethod");
:Person.class
是Person
类的Class
对象,表示该类的元数据。getMethod(String name, Class<?>... parameterTypes)
是Class
类中的一个方法,用于获取Class
对象中指定名称和参数类型的方法的Method
对象。"someMethod"
是要获取的方法的名称。getMethod("someMethod")
会返回Person
类中名为someMethod
的Method
对象。如果该方法存在于Person
类中,它将返回一个Method
实例;如果方法不存在或方法参数不匹配,将抛出NoSuchMethodException
。
Report report = method.getAnnotation(Report.class);
:method.getAnnotation(Class<T> annotationClass)
是Method
类中的一个方法,用于获取指定的注解类型。如果该方法上存在指定的注解,方法将返回该注解的实例;否则,返回null
。Report.class
是Report
注解的Class
对象。它被传递给getAnnotation
方法以指定要查找的注解类型。
Report report
:- 这行代码将
method.getAnnotation(Report.class)
的返回值赋给report
变量。如果someMethod
方法上存在@Report
注解,report
将是@Report
注解的实例;如果没有@Report
注解,report
将为null
。
- 这行代码将
示例
假设
@Report
注解定义如下:1
2
3
4
5
6
7
public Report {
int type() default 0;
String level() default "info";
String value() default "";
}并且
Person
类中有一个方法someMethod
,如下所示:1
2
3
4
5public class Person {
public void someMethod() {
}
}执行上述代码后:
Method method = Person.class.getMethod("someMethod");
将返回Person
类中someMethod
方法的Method
对象。Report report = method.getAnnotation(Report.class);
将获取someMethod
方法上的@Report
注解实例。
someMethod
方法上的@Report
注解存在,report
将包含注解的属性值,例如:report.type()
将返回1
。report.level()
将返回"debug"
。
如果
someMethod
方法上没有@Report
注解,则report
将为null
。这段代码用于检查并获取
Person
类中指定方法(someMethod
)上的注解@Report
。如果该方法上存在@Report
注解,通过method.getAnnotation(Report.class)
方法可以访问该注解的属性值。字段
1
2Field field = Person.class.getField("someField");
Report report = field.getAnnotation(Report.class);这段代码用于获取
Person
类中的someField
字段上的@Report
注解,并将其存储在report
变量中。1
2Field field = Person.class.getField("someField");
Report report = field.getAnnotation(Report.class);解释
Field field = Person.class.getField("someField");
:Person.class
是Person
类的Class
对象,表示该类的元数据。getField(String name)
是Class
类中的一个方法,用于获取Class
对象中指定名称的Field
对象。它返回Class
对象中名为name
的字段的Field
对象。"someField"
是要获取的字段的名称。getField("someField")
会返回Person
类中名为someField
的Field
对象。如果该字段存在于Person
类中,它将返回一个Field
实例;如果字段不存在或名称不匹配,将抛出NoSuchFieldException
。
Report report = field.getAnnotation(Report.class);
:field.getAnnotation(Class<T> annotationClass)
是Field
类中的一个方法,用于获取指定的注解类型。如果该字段上存在指定的注解,方法将返回该注解的实例;否则,返回null
。Report.class
是Report
注解的Class
对象。它被传递给getAnnotation
方法以指定要查找的注解类型。
Report report
:- 这行代码将
field.getAnnotation(Report.class)
的返回值赋给report
变量。如果someField
字段上存在@Report
注解,report
将是@Report
注解的实例;如果没有@Report
注解,report
将为null
。
- 这行代码将
示例
假设
@Report
注解定义如下:1
2
3
4
5
6
7
public Report {
int type() default 0;
String level() default "info";
String value() default "";
}并且
Person
类中有一个字段someField
,如下所示:1
2
3
4public class Person {
public String someField;
}执行上述代码后:
Field field = Person.class.getField("someField");
将返回Person
类中someField
字段的Field
对象。Report report = field.getAnnotation(Report.class);
将获取someField
字段上的@Report
注解实例。
someField
字段上的@Report
注解存在,report
将包含注解的属性值,例如:report.type()
将返回1
。report.level()
将返回"debug"
。
如果
someField
字段上没有@Report
注解,则report
将为null
。这段代码用于检查并获取
Person
类中指定字段(someField
)上的注解@Report
。如果该字段上存在@Report
注解,通过field.getAnnotation(Report.class)
方法可以访问该注解的属性值。构造方法
1
2Constructor<?> constructor = Person.class.getConstructor();
Report report = constructor.getAnnotation(Report.class);这段代码用于获取
Person
类中无参数构造函数上的@Report
注解,并将其存储在report
变量中。1
2Constructor<?> constructor = Person.class.getConstructor();
Report report = constructor.getAnnotation(Report.class);解释
Constructor<?> constructor = Person.class.getConstructor();
:Person.class
是Person
类的Class
对象,表示该类的元数据。getConstructor(Class<?>... parameterTypes)
是Class
类中的一个方法,用于获取该类中指定参数类型的构造函数。此方法返回一个Constructor
对象。- 当没有传递参数类型时,
getConstructor()
方法将返回无参数构造函数的Constructor
对象。如果Person
类中存在一个无参数构造函数,返回的将是该构造函数的Constructor
实例;如果没有无参数构造函数,将抛出NoSuchMethodException
。 Constructor<?>
是一个泛型类的实例,表示构造函数的元数据。
Report report = constructor.getAnnotation(Report.class);
:getAnnotation(Class<T> annotationClass)
是Constructor
类中的一个方法,用于获取构造函数上指定类型的注解。如果构造函数上存在该注解,方法将返回注解实例;否则,返回null
。Report.class
是Report
注解的Class
对象。它作为参数传递给getAnnotation
方法以指定要查找的注解类型。
Report report
:- 这行代码将
constructor.getAnnotation(Report.class)
的返回值赋给report
变量。如果Person
类中的无参数构造函数上存在@Report
注解,report
将是@Report
注解的实例;如果构造函数上没有@Report
注解,report
将为null
。
- 这行代码将
示例
假设
@Report
注解定义如下:1
2
3
4
5
6
7
public Report {
int type() default 0;
String level() default "info";
String value() default "";
}并且
Person
类中定义了一个无参数构造函数,并且该构造函数上有@Report
注解:1
2
3
4
5
6public class Person {
public Person() {
// 构造函数逻辑
}
}执行上述代码后:
Constructor<?> constructor = Person.class.getConstructor();
将返回Person
类中无参数构造函数的Constructor
对象。Report report = constructor.getAnnotation(Report.class);
将获取无参数构造函数上的@Report
注解实例。
@Report
注解存在,report
将包含注解的属性值,例如:report.type()
将返回1
。report.level()
将返回"debug"
。
如果构造函数上没有
@Report
注解,则report
将为null
。这段代码用于获取
Person
类中无参数构造函数上的注解@Report
。如果该构造函数上存在@Report
注解,通过constructor.getAnnotation(Report.class)
方法可以访问该注解的属性值。如果注解不存在,则report
为null
。
方法参数的注解
1
2
3
4
5
6
7
8Annotation[][] paramAnnotations = method.getParameterAnnotations();
Annotation[] param1Annotations = paramAnnotations[0];
for (Annotation anno : param1Annotations) {
if (anno instanceof Range) {
Range range = (Range) anno;
int max = range.max();
}
}这段代码用于获取方法参数上的所有注解,并检查这些注解的具体类型,然后提取某些注解的属性值。
1
2
3
4
5
6
7
8Annotation[][] paramAnnotations = method.getParameterAnnotations();
Annotation[] param1Annotations = paramAnnotations[0];
for (Annotation anno : param1Annotations) {
if (anno instanceof Range) {
Range range = (Range) anno;
int max = range.max();
}
}详细解释
Annotation[][] paramAnnotations = method.getParameterAnnotations();
:method.getParameterAnnotations()
是Method
类中的一个方法,用于获取方法参数上的所有注解。返回值是一个二维数组Annotation[][]
。- 每个一维数组
Annotation[]
对应方法的一个参数,包含了该参数上的所有注解。二维数组的索引与参数的索引一致,例如paramAnnotations[0]
是第一个参数上的所有注解。
Annotation[] param1Annotations = paramAnnotations[0];
:- 从
paramAnnotations
数组中获取第一个参数(索引为0
)的所有注解。param1Annotations
是一个Annotation[]
数组,包含了第一个参数上的所有注解。 - 如果方法有多个参数,
paramAnnotations
数组的长度与方法参数的个数相同,每个Annotation[]
数组包含了对应参数上的注解。
- 从
for (Annotation anno : param1Annotations)
:- 遍历
param1Annotations
数组中的每个注解anno
。 - 对于
param1Annotations
数组中的每个元素,执行for
循环中的代码块。
- 遍历
if (anno instanceof Range)
:- 检查当前注解
anno
是否是Range
注解的实例。 Range
是一个自定义的注解(假设它是定义的注解,例如:@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER)
)。
- 检查当前注解
Range range = (Range) anno;
:- 如果
anno
是Range
的实例,则将其强制转换为Range
类型,以便访问Range
注解定义的方法。
- 如果
int max = range.max();
:- 获取
Range
注解的max
属性值。 max
是Range
注解定义的一个属性,表示该注解的某种最大值限制。
- 获取
示例说明
假设我们有一个方法
someMethod
,其参数上使用了@Range
注解:1
2
3public void someMethod(int value) {
// 方法逻辑
}然后,我们通过反射来获取该方法参数上的注解信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 获取Method实例
Method method = Person.class.getMethod("someMethod", int.class);
// 获取所有参数的注解
Annotation[][] paramAnnotations = method.getParameterAnnotations();
// 获取第一个参数(索引为0)的所有注解
Annotation[] param1Annotations = paramAnnotations[0];
// 遍历第一个参数的所有注解
for (Annotation anno : param1Annotations) {
// 检查注解是否为@Range
if (anno instanceof Range) {
// 强制转换为@Range注解
Range range = (Range) anno;
// 获取@Range注解的max属性值
int max = range.max();
System.out.println("Max value: " + max);
}
}在这个例子中,
method.getParameterAnnotations()
返回了一个二维数组,包含了someMethod
方法所有参数的注解信息。paramAnnotations[0]
提取了第一个参数(value
)的注解数组。我们检查这些注解是否是Range
类型,若是,则读取Range
注解的max
属性值。这段代码主要用于读取和处理方法参数上的注解。首先,通过
method.getParameterAnnotations()
方法获取参数的注解信息,然后通过遍历检查每个注解的类型,获取注解的属性值。这样做允许程序在运行时动态地处理和检查方法参数上的注解。
使用注解的实例
注解定义: 1
2
3
4
5
6
public Range {
int min() default 0;
int max() default 255;
}
在类中使用注解: 1
2
3
4
5
6public class Person {
public String name;
public String city;
}
检查方法: 1
2
3
4
5
6
7
8
9
10
11
12
13void check(Person person) throws IllegalArgumentException, ReflectiveOperationException {
for (Field field : person.getClass().getFields()) {
Range range = field.getAnnotation(Range.class);
if (range != null) {
Object value = field.get(person);
if (value instanceof String s) {
if (s.length() < range.min() || s.length() > range.max()) {
throw new IllegalArgumentException("Invalid field: " + field.getName());
}
}
}
}
}
通过注解和检查方法,我们可以在运行时验证 Person
实例的字段值是否满足注解定义的约束。