Java源码赏析(四)Java常见注解

元注解

@Target :标识注解的目标,默认为所有

  • ElementType.TYPE(用于类)
  • ElementType.FIELD(用于域,包括enum)
  • ElementType.METHOD(用于方法)
  • ElementType.PARAMETER(用于正式参数)
  • ElementType.CONSTRUCTOR(类型构造方法)
  • ElementType.LOCAL_VARIABLE(用于本地变量)
  • ElementType.ANNOTATION_TYPE(用于注解)
  • ElementType.PACKAGE(用于包)
  • ElementType.TYPE_PARAMETER(java8,用于输入参数)
  • ElementType.TYPE_USE (java8,用于类型)

@Retention:注解保留到哪

  • RetentionPolicy.SOURCE (只保留到源码,编译为.class文件时忽略)
  • RetentionPolicy.CLASS (只保留到.class文件,运行时忽略,default默认)
  • RetentionPolicy.RUNTIME (运行时保留,可以通过反射机制读取注解的信息。)

@Documented:将此注解保存在 Javadoc 中

@Inherited:允许子类继承父类的注解

@Repeatable:用于重复使用注解(Java8新增)

常用注解

一、@Override

 常用于重写父类的方法,或实现接口的方法,若不满足则报错。

package java.lang;

import java.lang.annotation.*;

/**
 * 使用在方法上,只存在在源码上
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

二、@Deprecated

 常用于标注一个方法被弃用。

package java.lang;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

/**
 * 记录JavaDoc,保留至运行时,可使用在构造方法,属性(包括枚举),本地变量,方法,包,公共参数和类
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

三、@SuppressWarnings

常用于忽略特定警告,@SuppressWarnings("unchecked", "deprecation")可以同时忽略多个警告。

package java.lang;

import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

/**
 * 在类型、域、方法、正是参数、构造方法、本地变量上使用,只存在于源码
 */
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    /**
     * 一般取 unchecked/deprecation,表示忽略 unchecked/deprecation 警告信息
     */
    String[] value();
}

 

 四、@SafeVarargs (Java7)

常用于抑制varargs相关的未检查警告,一般只能用于static、final方法

package java.lang;

import java.lang.annotation.*;

/**
 * 能记录JavaDoc,保留至运行时,使用在构造方法和方法上
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface SafeVarargs {}

 

五、@FunctionalInterface (Java8)

 编译器检测接口是否符合函数式接口定义

package java.lang;

import java.lang.annotation.*;

/**
 * 能记录JavaDoc,存在于运行时,只能使用在类上
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FunctionalInterface {}

 

自定义注解

首先定义一个注解

package com.example.demo.util.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
@Inherited
public @interface MyAnnotation {
    String value() default "001";
}

可以看到,在Student的sNo属性上使用了该注解

package com.example.demo.util.annotation;

import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    @MyAnnotation
    private String sNo;

    private String sName;
}

处理注解

package com.example.demo.util.annotation;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

public class AnnotationTest {

    public static void main(String[] args) {
        //创建一个学号为 002 的学生 kw
        Student student = new Student("002", "kw");

        //获取学生对象对应的类
        Class<? extends Student> clazz = student.getClass();
        //获取学生类的属性
        Field[] declaredFields = clazz.getDeclaredFields();
        /** 循环判断是否存在注解@MyAnnotation
         * 若存在则获取该属性的set方法
         * 并使用该方法将值改为@MyAnnotation的value值
         */
@MyAnnotation的value
        for (Field field: declaredFields) {
            if (field.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);
                if (Objects.nonNull(annotation)) {
                    String name = field.getName();
                    try {
                        Method setMethod = clazz.getDeclaredMethod(
"set" + name.substring(0, 1).toUpperCase() + name.substring(1), String.class);
                        String annotationValue = annotation.value();
                        setMethod.invoke(student, annotationValue);
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }

            }
        }
        //打印
        System.out.println(student);
    }
}

/** 输出
Student(sNo=001, sName=kw)
*/

 

posted @ 2020-09-14 19:57  Kwanwooo  阅读(283)  评论(0编辑  收藏  举报