Java的自定义注解——Annotation的使用

Annotation——自定义注解

Java中提供了 Annotation 功能,该功能可用于类,构造方法,成员变量,方法。参数等的声明中。该功能不会影响程序的运行,但是会对编译器警告等辅助工具产生影响。

定义 Annotation 类型

在定义 Annotation 类型时,需要用到用来定义接口的 interface 关键字,但需要在 interface 关键字前面加一个 “ @ ” 符号,即定义 Annotation 类型的关键字为@interface 。

public @interface MyAnnotation {
    
    

}

这样就是定义了一个 Annotation 类型。上面定义的 Annotation 类型未包含任何成员,为 Annotation 类型添加成员。

public @interface MyAnnotation {
    
    
	String name();
	Class type();
}

在为 Annotation 类型定义成员时,也可以为成员设置默认值。

public @interface MyAnnotation {
    
    
	String name() default "默认值";
	Class type() default void.class;
}

访问 Annotation 信息

可以通过反射注解,来访问 Annotation 信息,想要反射注解还需要了解一下元注解。元注解就是为其他注解做注解,也就是注解的注解。元注解有四个,常用的有两个 @Target 和 @Retention 。
在这里插入图片描述

@Target

在定义 Annotation 时,可以通过 @Target 来设置 Annotation 适用的程序元素种类,如果为设置 @Target ,则表示适用于所有程序元素。枚举类 ElementType 中的枚举常量用来设置 @Target。
枚举类 ElementType 中的枚举常量

枚举常量 说明
ANNOTATION_TYPE 表示用于 Annotation 类型
TYPE 表示用于类,接口和枚举,以及Annotation 类型
CONSTRUCTOR 表示用于构造方法
FIELD 表示用于成员变量和枚举变量
METHOD 表示用于方法
PARAMETER 表示用于参数
LOCAL_VARIABLE 表示用于局部变量
PACKAGE 表示用于包
@Retention

通过设置 Annotation 类型的 @Retention ,可设置 Annotation 的有效范围。枚举类 RetentionPolicy 中的枚举常量用来设置 @Retention ,如果未设置 @Retention ,Annotation 的有效范围为枚举常量 CLASS 表示的范围。
枚举类 RetentionPolicy 中的枚举常量

枚举常量 说明
SOURCE 表示不编译 Annotation 到类文件中,有效范围最小
CLASS 表示编译 Annotation 到类文件中,但是在运行时不加载 Annotation 到JVM中
RUNTIME 表示在运行时加载 Annotation 到JVM中,有效范围最大

之前反射的三个类 Constructors (构造方法类),Field (成员属性类),Methods (成员方法类)都提供的可以反射注解的方法。
在这里插入图片描述
要想将注解反射出来有个前提,需要将 @Retention 设置成 RUNTIME 。

实例

首先创建一个Dome类,为其添加几个属性。

public class Dome {
    
    

	public String name;// 名称
	public double price;// 价格
	public String produced;// 厂商
}

然后定义一个 Annotation 类型,为这些属性添加注释。

public @interface MyAnnotation {
    
    
	String remkras() default "";//备注
	boolean enable() default true;//属性是否启用,默认true
}

然后回到Dome类中,为属性添加注解。将属性 produced 厂商设置一个过时的注解,不启用。

public class Dome {
    
    

	@MyAnnotation(remkras = "名称")
	public String name;// 名称
	@MyAnnotation(remkras = "价格")
	public double price;// 价格
	@Deprecated
	@MyAnnotation(remkras = "厂商", enable = false)//不启用
	public String produced;// 厂商
}

现在就来反射这些注解,创建一个新的类Study2

public class Study2 {
    
    

	public static void main(String[] args) {
    
    
		Class c = Dome.class;//创建class对象
		Field fl[] = c.getDeclaredFields();//获取所有属性
		for(Field f:fl) {
    
    
			if(f.isAnnotationPresent(MyAnnotation.class)) {
    
    //判断注解是否被MyAnnotation注解过
				System.out.println(f.getName()+"被注解过");
			}
		}
	}
}

在这里插入图片描述
注意:
需要为 MyAnnotation 添加 @Retention 与 @Target 设置,否则运行不出来。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)

完整代码

MyAnnotation:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    
    
	String remkras() default "";//备注
	boolean enable() default true;//属性是否启用,默认true
}

Dome:

public class Dome {
    
    

	@MyAnnotation(remkras = "名称")
	public String name;// 名称
	@MyAnnotation(remkras = "价格")
	public double price;// 价格
	@Deprecated
	@MyAnnotation(remkras = "厂商", enable = false)//不启用
	public String produced;// 厂商
}

Study2:

import java.lang.reflect.Field;

public class Study2 {
    
    

	public static void main(String[] args) {
    
    
		Class c = Dome.class;// 创建class对象
		Field fl[] = c.getDeclaredFields();// 获取所有属性
		for (Field f : fl) {
    
    
			if (f.isAnnotationPresent(MyAnnotation.class)) {
    
    // 判断注解是否被MyAnnotation注解过
				System.out.println(f.getName() + "被注解过");
				MyAnnotation m = f.getAnnotation(MyAnnotation.class);// 创建MyAnnotation对象,获取注解
				System.out.print(f.getName() + "属性的注解内容:");
				System.out.print("备注=" + m.remkras() + " , ");// 获取备注内容
				System.out.println("属性是否启用=" + m.enable());// 获取属性是否启用
			}
		}
	}
}

运行截图:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/javanofa/article/details/104900822