Java学习笔记@注解
笔者: unirithe
日期: 11/13/2021
注解概述
- Java 注解 (Annotation) 又称 Java标注,是JDK5.0 引入的一种注释机制
- Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注
注解的作用:对Java中类、方法、成员变量做标记,然后进行特殊处理
自定义注解
代码格式
public @interface 注解名称{
public 属性名称 属性名() default 默认值;
}
范例:自定义注解的使用,可标记各种对象包括类、构造器方法、成员变量
@interface UserInfo{
String id();
String [] hobby() default {"无"};
int age() default 3;
}
@UserInfo(id="123", hobby={"吃饭", "睡觉"}, age = 21)
public class Demo{
@UserInfo(id="456")
public Demo(){}
@UserInfo(id="abc")
public static void main(String[] args) {
@UserInfo(id="123")
int a = 0;
}
}
value特殊属性
- value属性,如果只有一个value属性的情况下,则可忽略value字符串,多个没默认值的属性除外
@interface UserInfo{
String id() default "uni";
String value();
}
@UserInfo("test")
public class Demo{public static void main(String[] args) {}}
元注解
指规范注解的注解
常见元注解:
- @Target : 规定自定义注解适用范围
- @Retention:规定注解的生命周期
范例:规定注解只能针对方法
@Target({ElementType.METHOD})
@interface MyTest{
String value();
}
@Target
该注解可使用的值都在import java.lang.annotation.ElementType 枚举类中
| 变量 | 描述 |
|---|---|
| TYPE | 类,接口 |
| FIELD | 成员变量 |
| METHOD | 成员方法 |
| PARAMETER | 方法参数 |
| CONSTRUCTOR | 构造器 |
| LOCAL_VARIABLE | 局部变量 |
@Retention
该注解可使用的值在java.lang.annotation.RetentionPolicy枚举类中
| 变量 | 描述 |
|---|---|
| SOURCE | 注解只作用在源码阶段,生成的字节码文件中不存在 |
| CLASS | 注解作用在源码阶段和字节码文字阶段,但运行阶段不存在,默认值是CLASS |
| RUNTIME | 注解作用在源码阶段,字节码文件阶段以及运行阶段(开发常用) |
注解解析
注解解析:判断是否存在注解,存在就解析出内容
相关的接口:
- Annotaion : 注解的顶级接口,注解都是Annotation类型的对象
- AnnotatedElement: 该接口定义了与注解解析相关的解析方法
| 返回类型 | 方法名 | 描述 |
|---|---|---|
Annotation[] |
getDeclaredAnnotations() |
获得当前对象上使用的所有注解,返回注解数组 |
T |
getDeclaredAnnotation(Class <T> annotationClass) |
根据注解类型获得对应注解对象 |
boolean |
isAnnotationPresent(Class<Annotation> annotationClass) |
判断当前对象是否使用了指定的注解,若使用了则返回 |
- 所有的类成分Class,Method,Field,Constructor都实现了AnnotatedElement接口,所以它们都有解析注解的作用
解析注解的Tips:
注解在哪个成分就先拿哪个成分对象
比如注解作用是成员方法,则要获得该成员方法对应的Method对象,再拿其注解
比如注解作用在类上,则要该类的Class对象,再拿注解
... 以此类推
范例:获取一个类中所有注解的信息
User.java
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface User{
String id();
String pasword() default "123456";
}
TestAnnotation.java
import org.junit.Test;
@User(id = "uni")
class Demo{
@User(id ="java")
public void test() {}
}
public class TestAnnotation{
@Test
public void parseClass(){
Class userC = Demo.class;
// 判断该类上是否存在注解
if(userC.isAnnotationPresent(User.class)){
User user = (User) userC.getDeclaredAnnotation(User.class);
System.out.println(user.id());
System.out.println(user.pasword());
}
}
}
运行结果
uni
123456
范例:获取类中注解的方法
public void parseMethod() throws NoSuchMethodException {
Class userC = Demo.class;
Method method = userC.getDeclaredMethod("test");
// 判断该类的test方法上是否存在注解
if(method.isAnnotationPresent(User.class)){
User user = (User) method.getDeclaredAnnotation(User.class);
System.out.println(user.id());
System.out.println(user.pasword());
}
}
注解应用场景
案例:模拟 Junit 框架
方法:使用反射机制获取类的所有方法并判断每个方法是否含有指定注解,若有则使用反射调用该方法
MyTest.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}
TestAnnotation.java
import org.junit.Test;
import java.lang.reflect.Method;
public class TestAnnotation{
@MyTest
public void test1(){
System.out.println("test1.");
}
public void test2(){
System.out.println("test2.");
}
@MyTest
public void test3(){
System.out.println("test3.");
}
public static void main(String[] args) throws Exception{
TestAnnotation t = new TestAnnotation();
Class c = TestAnnotation.class;
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
if(method.isAnnotationPresent(MyTest.class)){
method.invoke(t);
}
}
}
}
运行结果
test1.
test3.

浙公网安备 33010602011771号