Java基础(八):自定义注解和注解解析

本文深入讲解Java注解的定义、用途、自定义注解的方法、元注解的应用以及如何通过反射解析注解,附带案例演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

注解

1. 概述

定义

注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

作用

  • 编写文档:通过代码里标志的注解生成文档。
  • 编译检查:通过代码里标志的注解让编译器能够实现基本的编译检查【Override】
  • 代码分析:通过代码里标识的注解对代码进行分析【使用反射】

常见注解

  1. @author:用来标识作者名,eclipse开发工具默认的是系统用户名。
  2. @version:用于标识对象的版本号,适用范围:文件、类、方法。
  3. @Override :用来修饰方法声明,告诉编译器该方法是重写父类中的方法,父类不存在该方法,则编译失败。

2. 自定义注解

格式

public @interface 注解名称{
    //属性列表
    属性类型 属性名();
    属性类型 属性名();
    ...
}

注解属性类型

  • 八种基本数据类型
  • String、Class、注解、枚举
  • 以上所有类型的一维数组
public @interface Student {
  String name(); // 姓名
  int age() default 18; // 年龄
  String gender() default "男"; // 性别
}
// 该注解就有了三个属性:name,age,gender

使用: 可以使用在类、成员变量、成员方法、构造方法、局部变量上。

//@Student(name = "张三",age = 19);
public class AnnoTest {
    //@Student(name = "张三",age = 19);
    private String var;
    //@Student(name = "张三",age = 19);
    public static void main(String[] args) {
        //@Student(name = "张三",age = 19);
        String innerVar;
    }
}

3. 元注解(注解的注解)

注解的注解,指定注解的使用位置和生命周期。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
  • @Target元注解

指明注解的使用位置,注解默认可以放在任何地方

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE) // 只有一个属性可以省去'value='
public @interface Target {
    ElementType[] value(); // 枚举数组
}
 TYPE: 用在类,接口上
 FIELD:用在成员变量上
 METHOD: 用在方法上
 PARAMETER:用在参数上
 CONSTRUCTOR:用在构造方法上
 LOCAL_VARIABLE:用在局部变量上
  • @Retention元注解

表示注解的生命周期,注解默认Class阶段

代码的生命周期: .java源代码 -> .class文件 -> 运行时

@Documented
@Retention(RetentionPolicy.RUNTIME) // 只有一个属性可以省去'value='
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value(); // 枚举数组
}
SOURCE:注解只存在于Java源代码中,编译生成的字节码文件中就不存在了。
CLASS:注解存在于Java源代码、编译以后的字节码文件中,运行的时候内存中没有,默认值。
RUNTIME:注解存在于Java源代码中、编译以后的字节码文件中、运行时内存中,程序可以通过反射获取该注解。

4. 注解解析

通过反射获得类中注解的属性, 只有实现AnnotatedElement接口的类才能获得注解。Constructor、Method、Field都实现了AnnotatedElement接口。注解必须活到运行时才能被反射获取。

AnnotatedElement接口中的方法

boolean isAnnotationPresent(Class annotationClass); 判断当前对象是否有指定的注解,有则返回true,否则返回false。
T getAnnotation(Class<T> annotationClass);  获得当前对象上指定的注解对象。
Annotation[] getAnnotations(); 获得当前对象及其从父类上继承的所有的注解对象。
Annotation[] getDeclaredAnnotations();获得当前对象上所有的注解对象,不包括父类的。

获得注解中的属性( 以Method为例 )

Method method = clazz.getMethod(Object obj,Class...args);
Annotation a = method.getAnnotations(String name);
Annotation.属性名();
案例:模拟Junit的@Test注解

@MyTest注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest {
}

AnnoDemo类

public class AnnoDemo {
    @MyTest
    public void actionOne(){
        System.out.println("actionOne");
    }
    public void actionTwo(){
        System.out.println("actionTwo");
    }
    @MyTest
    public void actionThree(){
        System.out.println("actionThree")
    }
}

ParseDemo类

public class ParseDemo {
	public static void main(String[] args) {
        Class clazz = AnnoDemo.class;
       	Object obj = clazz.newInstance();
      	Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            boolean flag = method.isAnnotationPresent(MyTest.class);
            if(flag) method.invoke(obj);
        }
    }
}

结果:

actionOne
actionThree
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值