Java自定义注解

简介: 如果Java SE提供的11内置注解不能满足你的需求,可以自定义注解,注解本质是一种接口,它 是java.lang.annotation.Annotation接口的子接口,是引用数据类型。

一、声明注解

声明自定义注解可以使用@interface关键字实现,最简单形式的注解示例代码如下:

public @interface Marker{
}

上述代码声明一个Marker注解,@interface声明一个注解类型,它前面的访问限定修饰符与类一样有两 种:公有访问权限和默认访问权限。

Marker注解中不包含任何的成员,这种注解称为标记注解(Marked Annotation),基本注解中的 @Override就属于标记注解。根据需要注解中可以包含一些成员,示例代码如下:

//单值注解 
@interface MyAnnotation { 
  String value(); 
}

代码中声明MyAnnotation 注解,它有一个成员value,注意value后面是有一对小括号,value前面的是 数据类型。成员也可以有访问权限修饰符,但是只能是公有权限和默认权限。

注解中的成员也可以有默认值,示例代码如下:

//带有默认值注解 
@interface MyAnnotation1 {
String value() default "注解信息";
int count() default 0;
}

通过关键字default指定默认值。使用这些注解示例代码如下:

@Marker
public class HelloWorld {
  @MyAnnotation(value = "Annotation") 
  private String info = "";
  @MyAnnotation1(count = 10) 
  public static void main(String[] args) {
  }
}

默认情况下注解可以修饰任意的程序元素(类、接口、成员变量、成员方法和数据类型等)。


二、使用元注解案例


上面声明注解只是最基本形式的注解,对于复杂的注解可以在声明注解时使用元注解。下面通过一 个案例介绍一下在自定义注解中使用元注解,在本案例中定义了两个注解。


先看看第一个注解MyAnnotation,它用来修饰类或接口,MyAnnotation代码如下:

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Documented; 
import java.lang.annotation.Target;
@Documented 
@Target({ ElementType.TYPE }) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MyAnnotation { 
  String description(); 
}

第二个注解MemberAnnotation,它用来类中成员变量和成员方法,MemberAnnotation代码如下:

import java.lang.annotation.Documented; 
import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 
@Documented 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ ElementType.FIELD, ElementType.METHOD }) 
public @interface MemberAnnotation {
  Class<?> type() default void.class;
  String description(); 
}

使用了MyAnnotation和MemberAnnotation注解是Person类,Person类代码如下:

@MyAnnotation(description = "这是一个测试类") 
public class Person {
  @MemberAnnotation(type = String.class, description = "名字") 
  private String name;
  @MemberAnnotation(type = int.class, description = "年龄") 
  private int age;
  @MemberAnnotation(type = String.class, description = "获得名字") 
  public String getName() { 
    return name; 
  }
  @MemberAnnotation(type = int.class, description = "获得年龄") 
  public int getAge() { 
    return age; 
  }
  @MemberAnnotation(description = "设置姓名和年龄") 
  public void setNameAndAge(String name, int age) {
    this.name = name;
    this.age = age; 
  }
  @Override 
  public String toString() { 
    return "Person [name=" + name + ", age=" + age + "]"; 
  }
}

使用注解时如果当前类与注解不在同一个包中,则需要将注解引入。


三、读取运行时注解信息案例


注解是为工具读取信息而准备的。有些工具可以读取源代码文件中的注解信息;有的可以读取字节码 文件中的注解信息;有的可以在运行时读取注解信息。但是读取这些注解信息的代码都是一样的,区 别只在于自定义注解中@Retention的保留策略不同。

读取注解信息需要反射相关API,Class类如下方法:


A getAnnotation(Class annotationClass):如果此元素存在 annotationClass类型的注解,则返回注解,否则返回null。

Annotation[] getAnnotations():返回此元素上存在的所有注解。

Annotation[] getDeclaredAnnotations():返回直接存在于此元素上的所有注解。与getAnnotations() 区别在于该方法将不返回继承的注释。

boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):如果此元素上存在 annotationClass类型的注解,则返回true,否则返回false。

boolean isAnnotation():如果此Class对象表示一个注解类型则返回true。

在运行时Person类中注解信息代码如下:

import java.lang.reflect.Field; 
import java.lang.reflect.Method;
public class HelloWorld {
  public static void main(String[] args) {
    try { 
      Class<?> clz = Class.forName("xxx.Person");
      // 读取类注解 
      if (clz.isAnnotationPresent(MyAnnotation.class)) { 
        MyAnnotation ann = (MyAnnotation)clz.getAnnotation(MyAnnotation.class);
        System.out.printf("类%s,读取注解描述: %s \n", clz.getName(), ann.description()); 
      }
      // 读取成员方法的注解信息 
      Method[] methods = clz.getDeclaredMethods(); 
      for (Method method : methods) {
        if (method.isAnnotationPresent(MemberAnnotation.class)) { 
          MemberAnnotation ann = method.getAnnotation(MemberAnnotation.class);
          System.out.printf("方法%s,读取注解描述: %s \n", method.getName(), ann.description()); 
        } 
      }
      // 读取成员变量的注解信息 
      Field[] fields = clz.getDeclaredFields(); 
      for (Field field : fields) {
        if (field.isAnnotationPresent(MemberAnnotation.class)) {
          MemberAnnotation ann = field.getAnnotation(MemberAnnotation.class);
            System.out.printf("成员变量%s,读取注解描述: %s \n", field.getName(), ann.description()); 
          }
      } 
    } catch (Exception e) {
      e.printStackTrace(); 
    }
  }
}

运行结果如下:

类com.a51work6.Person,读取注解描述: 这是一个测试类 
方法getName,读取注解描述: 获得名字 
方法getAge,读取注解描述: 获得年龄 
方法setNameAndAge,读取注解描述: 设置姓名和年龄 
成员变量name,读取注解描述: 名字 
成员变量age,读取注解描述: 年龄



相关文章
|
10月前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
303 1
|
2月前
|
XML 人工智能 Java
java通过自定义TraceId实现简单的链路追踪
本文介绍了如何在Spring Boot项目中通过SLF4J的MDC实现日志上下文traceId追踪。内容涵盖依赖配置、拦截器实现、网关与服务间调用的traceId传递、多线程环境下的上下文同步,以及logback日志格式配置。适用于小型微服务架构的链路追踪,便于排查复杂调用场景中的问题。
112 0
|
9月前
|
XML Java 编译器
Java注解的底层源码剖析与技术认识
Java注解(Annotation)是Java 5引入的一种新特性,它提供了一种在代码中添加元数据(Metadata)的方式。注解本身并不是代码的一部分,它们不会直接影响代码的执行,但可以在编译、类加载和运行时被读取和处理。注解为开发者提供了一种以非侵入性的方式为代码提供额外信息的手段,这些信息可以用于生成文档、编译时检查、运行时处理等。
197 7
|
10月前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
171 1
|
11月前
|
Java
让星星⭐月亮告诉你,自定义定时器和Java自带原生定时器
定时器是一种可以设置多个具有不同执行时间和间隔的任务的工具。本文介绍了定时器的基本概念、如何自定义实现一个定时器,以及Java原生定时器的使用方法,包括定义定时任务接口、实现任务、定义任务处理线程和使用Java的`Timer`与`TimerTask`类来管理和执行定时任务。
346 3
|
6月前
|
Java 编译器 开发者
注解的艺术:Java编程的高级定制
注解是Java编程中的高级特性,通过内置注解、自定义注解及注解处理器,可以实现代码的高度定制和扩展。通过理解和掌握注解的使用方法,开发者可以提高代码的可读性、可维护性和开发效率。在实际应用中,注解广泛用于框架开发、代码生成和配置管理等方面,展示了其强大的功能和灵活性。
146 25
|
11月前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
225 43
Java学习十六—掌握注解:让编程更简单
|
9月前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
264 34
|
9月前
|
Java 编译器 数据库
Java 中的注解(Annotations):代码中的 “元数据” 魔法
Java注解是代码中的“元数据”标签,不直接参与业务逻辑,但在编译或运行时提供重要信息。本文介绍了注解的基础语法、内置注解的应用场景,以及如何自定义注解和结合AOP技术实现方法执行日志记录,展示了注解在提升代码质量、简化开发流程和增强程序功能方面的强大作用。
338 5
|
11月前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
149 2
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下