Java 中提供了 Anmotation 注解功能,该功能可用于类、构造方法、成员变量、成员方法、参数、字段等的声明中。用来提供额外的信息或配置。
@interface
关键字定义一个注解,这个关键字的隐含意思是继承java.lang.annotation.Annotation
接口。,这样的 Annotation 类型被称为 marker annotation。
public @interface NoMemberAnnotation {
}
public @interface OneMemberAnnotation {
String value();
}
String: 成员类型。可用的成员类型有 String、Class、primitive、enumerated 和 annotation,以及所列类型的数组。
public @interface MoreMemberAnnotation {
String describe();
Class type();
}
public @interface MyAnnotation {
String value() default "";
int count() default 0;
}
枚举常量 说明
----------------------------------------------------------------
ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造方法进行注解
ElementType.FIELD 可以给属性进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法内的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
实例1
@Target()// 用于构造方法、字段、方法和参数
//@Target( {ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
public @interface Constructor_Annotation {
String value() default "默认构造方法"; // 定义一个具有默认值的String型成员
}
枚举常量 说明
SOURCE 表示不编译 Annotation 到类文件中,有效范围最小
CLASS 表示编译 Annotation 到类文件中,但是在运行时不加载 Anmotation 到JVM中
RUNTIME 表示在运行时加载 Annotation 到JVM 中,有效范围最大
实例
@Retention(RetentionPolicy.RUNTIME)// 在运行时加载Annotation到JVM中
public @interface Field_Method_Parameter_Annotation {
String describe(); // 定义一个没有默认值的String型成员
Class type() default void.class; // 定义一个具有默认值的Class型成员
}
Inherited 是继承的意思,但是它并不是说注解本身可以继承,而是说如果一个超类被 @Inherited 注解过的注解进行注解的话,那么如果它的子类没有被任何注解应用的话,那么这个子类就继承了超类的注解。
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface Test {}
@Test
public class A {}
public class B extends A {}
注解 Test 被 @Inherited 修饰,之后类 A 被 Test 注解,类 B 继承 A,类 B 也拥有 Test 这个注解。
顾名思义,这个元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去。
Repeatable 自然是可重复的意思。
举个例子,一个人他既是程序员又是产品经理,同时他还是个画家。
@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
String role default "";
}
@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {
int id();
String msg();
}
@TestAnnotation(id=3,msg="hello annotation")
public class Test {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {
public int id() default -1;
public String msg() default "Hi";
}
//TestAnnotation 中 id 属性默认值为 -1,msg 属性默认值为 Hi。
//它可以这样应用。
@TestAnnotation()//因为有默认值,所以无需要再在 @TestAnnotation 后面的括号里面进行赋值了,这一步可以省略。
public class Test {}
如果一个注解内仅仅只有一个名字为 value 的属性时,应用这个注解时可以直接接属性值填写到括号内。
@interface Check {
String value();
}
@Check("hi")
int a;
这和下面的效果是一样的
@Check(value="hi")
int a;
public @interface Perform {}
//应用这个注解的时候,括号都可以省略。
@Perform
public void testMethod(){}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value() default "";
int count() default 0;
}
@MyAnnotation(value = "example", count = 5)
class TestDemo {
@MyAnnotation(value ="field")
//或 @MyAnnotation("field")
private String name;
@MyAnnotation(value ="method")
//或 @MyAnnotation("method")
public void myMethod() {
// 方法体
System.out.println("myMethod");
}
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
TestDemo obj = new TestDemo();
// 获取类上的注解
MyAnnotation classAnnotation = obj.getClass().getAnnotation(MyAnnotation.class);
System.out.println("====获取类上的注解====");
System.out.println(classAnnotation.value());
System.out.println(classAnnotation.count());
// 获取字段上的注解
Field field = obj.getClass().getDeclaredField("name");
MyAnnotation fieldAnnotation = field.getAnnotation(MyAnnotation.class);
System.out.println("====获取字段上的注解====");
System.out.println(fieldAnnotation.value());
// 获取方法上的注解
Method method = obj.getClass().getMethod("myMethod");
MyAnnotation methodAnnotation = method.getAnnotation(MyAnnotation.class);
System.out.println("====获取方法上的注解====");
System.out.println(methodAnnotation.value());
}
}
//运行结果
====获取类上的注解====
example
5
====获取字段上的注解====
field
====获取方法上的注解====
method