Java035——Annotation 注解功能

Annotation 注解说明

Java 中提供了 Anmotation 注解功能,该功能可用于类、构造方法、成员变量、成员方法、参数、字段等的声明中。用来提供额外的信息或配置。

注解的定义

  1. 注解的定义:
    使用@interface关键字定义一个注解,这个关键字的隐含意思是继承java.lang.annotation.Annotation 接口。

定义一个没有任何成员的Annotation 类型

,这样的 Annotation 类型被称为 marker annotation。

public @interface NoMemberAnnotation {

}

定义一个只包含一个成员的 Annotation 类型

public @interface OneMemberAnnotation {
	String value();
}

String: 成员类型。可用的成员类型有 String、Class、primitive、enumerated 和 annotation,以及所列类型的数组。

定义一个包含多个成员的 Annotation 类型

public @interface MoreMemberAnnotation {
	String describe();
	Class type();
}

注解可以包含成员变量,也可以有默认值。

 public @interface MyAnnotation {
       String value() default "";
       int count() default 0;
 }

元注解

  1. 元注解是可以注解到注解上的注解
  2. 元标签有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 种。

@Target

  1. Target 是目标的意思,@Target 指定了注解运用的地方。
  2. 在定义 Annotation 类型时,还可以通过 Annotation 类型@Target 来设置 Annotation 类型适用的程序元素种类。如果未设置@Target,则表示适用于所有程序元素。枚举类 ElementType 中的枚举常量用来设置@Targer
	枚举常量								说明
----------------------------------------------------------------
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型成员
}

@Retention

  1. Retention 的英文意为保留期的意思。说明了这个注解的的存活时间。
  2. 通过 Annotation 类型@Retention 可以设置 Annotation 的有效范围。枚举类 RetentionPolicy 中的枚举常量用来设置@Retention。如果未设置@Retention,Amotation 的有效范围为枚举常量CLASS 表示的范围。
枚举常量			说明
SOURCE			表示不编译 Annotation 到类文件中,有效范围最小
CLASS			表示编译 Annotation 到类文件中,但是在运行时不加载 AnmotationJVMRUNTIME		表示在运行时加载 AnnotationJVM 中,有效范围最大

实例

@Retention(RetentionPolicy.RUNTIME)// 在运行时加载Annotation到JVM中
public @interface Field_Method_Parameter_Annotation {
	String describe(); // 定义一个没有默认值的String型成员
	Class type() default void.class; // 定义一个具有默认值的Class型成员
}

@Inherited

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 这个注解。

@Documented

顾名思义,这个元注解肯定是和文档有关。它的作用是能够将注解中的元素包含到 Javadoc 中去。

@Repeatable

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

推荐

你可能感兴趣的:(Java全套学习笔记,java,python,开发语言)