Java基础系列:注解

1 简介

注解:元数据。方便后续使用这些数据。
(1)提供描述程序所需的额外信息。
(2)提高代码易读性和简洁性。
(3)编译期类型检查,可由编译器进行测试和验证注解的正确性,如标准注解@Override、@Deprecated、@SuppressWarngings。

元注解:注解其他注解,修饰自定义的注解,使其按照既定的轨迹运行。

序号元注解描述
1@Target注解标注的位置,如类、方法、参数等。标识值有10种:
(1)TYPE:类、接口(包括注解类型)或者enum
(2)FIELD:域
(3)METHOD:方法
(4)PARAMETER:常规参数
(5)CONSTRUCTOR:构造器
(6)LOCAL_VARIABLE:局部变量
(7)ANNOTATION_TYPE:注解类型
(8)PACKAGE:包
(9)TYPE_PARAMETER:类型参数
(10)TYPE_USE:类型检查
2@Retention注解存活的阶段。标识有3种:
(1)SOURCE:不使用,直接被编译器丢弃
(2)CLASS:class文件中可用,运行时无法获取,被VM丢弃
(3)RUNTIME:运行时可用,可通过反射获取注解信息
3@Documented注解包含在JavaDoc中
4@Inherited允许子类继承父类中的注解

2 类注解

这里讲解类注解类型:ElementType.TYPE

2.1 自定义注解

package com.monkey.java_study.annotation.clazz;

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

/**
 * 类注解.
 *
 * @author xindaqi
 * @date 2022-03-17 15:19
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyClassAnnotation {

    /**
     * id.
     *
     * @return id
     */
    public int id();

    /**
     * 注解描述.
     *
     * @return 描述信息
     */
    public String description() default "自定义类注解";
}

2.2 注解应用

在不同的类中标注类注解。

  • 类1
package com.monkey.java_study.annotation.clazz;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 类注解:应用.
 *
 * @author xindaqi
 * @date 2022-03-17 15:21
 */
@MyClassAnnotation(id = 1)
public class Class1AnnotationUsing {

    private static final Logger logger = LoggerFactory.getLogger(Class1AnnotationUsing.class);

    public void test() {
        logger.info(">>>>>>>>Class 1");
    }
}
  • 类2
package com.monkey.java_study.annotation.clazz;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 类注解:应用.
 *
 * @author xindaqi
 * @date 2022-03-17 15:22
 */
@MyClassAnnotation(id = 2)
public class Class2AnnotationUsing {

    private static final Logger logger = LoggerFactory.getLogger(Class2AnnotationUsing.class);

    public void test() {
        logger.info(">>>>>>>>Class 1");
    }
}

2.3 测试

获取类注解直接通过getAnnotations获取注解数组,一个类可以被多个注解标识。
不同的注解可以自定义不同的处理方式,使用instanceof判断注解类型,做相应处理。
获取注解后,通过类型强转,提取注解的方法,获取对应的值。

package com.monkey.java_study.annotation.clazz;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.reflect.annotation.AnnotationType;

import java.lang.annotation.Annotation;

/**
 * 类注解测试.
 *
 * @author xindaqi
 * @date 2022-03-17 15:28
 */
public class ClassAnnotationTest {

    private static final Logger logger = LoggerFactory.getLogger(ClassAnnotationTest.class);

    private static void processAnnotation(Class<?> clzz) {
        Annotation[] annotations = clzz.getAnnotations();
        for(Annotation annotation : annotations) {
            if(annotation instanceof MyClassAnnotation) {
                logger.info(">>>>>>>>MyClassAnnotation id:{},description:{}", ((MyClassAnnotation) annotation).id(), ((MyClassAnnotation) annotation).description());
            }
        }
    }

    public static void main(String[] args) {
        processAnnotation(Class1AnnotationUsing.class);
        processAnnotation(Class2AnnotationUsing.class);
    }
}

2.4 测试结果

在这里插入图片描述

3 方法级注解

这里讲解方法注解类型:ElementType.METHOD

3.1 自定义注解

package com.monkey.java_study.annotation;

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

/**
 * 方法级注解.
 *
 * @author xindaqi
 * @date 2022-03-16 15:44
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {

    /**
     * id
     *
     * @return id
     */
    public int id();

    /**
     * 描述信息.
     *
     * @return 描述信息
     */
    public String description() default "自定义注解";
}

3.2 注解应用

package com.monkey.java_study.annotation;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 方法注解测试.
 *
 * @author xindaqi
 * @date 2022-03-17 9:58
 */
public class AnnotationUsing {

    private static final Logger logger = LoggerFactory.getLogger(AnnotationUsing.class);

    @MyAnnotation(id = 1)
    public void myMethod1() {
        logger.info(">>>>>>>My method1");
    }

    @MyAnnotation(id = 2)
    public void myMethod2() {
        logger.info(">>>>>>>My method2");
    }
}

3.3 注解测试

获取方法的注解:两步
(1)通过反射方式获取方法getDeclaredMethods();
(2)通过getAnnotation(MyAnnotation.class)获取方法的注解。

package com.monkey.java_study.annotation;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;

/**
 * 处理方法级注解.
 *
 * @author xindaqi
 * @date 2022-03-17 10:01
 */
public class AnnotationTest {

    private static final Logger logger = LoggerFactory.getLogger(AnnotationTest.class);

    private static void processAnnotation(Class<?> cl) {
        for(Method m : cl.getDeclaredMethods()) {
            MyAnnotation myAnnotation = m.getAnnotation(MyAnnotation.class);
            if(null != myAnnotation) {
                logger.info(">>>>>>>Id: {}", myAnnotation.id());
            }
        }
    }

    public static void main(String[] args) {
        processAnnotation(AnnotationUsing.class);
    }
}

3.4 测试结果

在这里插入图片描述

4 参数注解

这里讲解参数检查注解类型:TYPE_USE。

4.1 自定义注解

package com.monkey.java_study.annotation.type_checker;

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

/**
 * 类型检查注解.
 *
 * @author xindaqi
 * @date 2022-03-18 14:56
 */
@Target(ElementType.TYPE_USE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTypeCheckerAnnotation {
    String value();
}

4.2 注解应用

package com.monkey.java_study.annotation.type_checker;

/**
 * 类型检查应用.
 *
 * @author xindaqi
 * @date 2022-03-18 15:04
 */
@MyTypeCheckerAnnotation(value = "class")
public class TypeCheckerAnnotationUsing {

    @MyTypeCheckerAnnotation(value = "name")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "TypeCheckerAnnotationUsing{" +
                "name='" + name + '\'' +
                '}';
    }
}

4.3 测试

获取属性注解:两步
(1)通过反射获取属性getDeclaredFields();
(2)获取属性注解field.getAnnotatedType().getAnnotation(MyTypeCheckerAnnotation.class)。
这里,使用TYPE_USE标识,需要使用getAnnotatedType()。

package com.monkey.java_study.annotation.type_checker;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 类型检查测试.
 *
 * @author xindaqi
 * @date 2022-03-18 15:06
 */
public class TypeCheckerTest {

    private static final Logger logger = LoggerFactory.getLogger(TypeCheckerTest.class);

    private static void annotationProcess(Class<?> clzz, Object obj) throws Exception {
        Annotation[] annotations = clzz.getAnnotations();
        for (Annotation annotation : annotations) {
            if (annotation instanceof MyTypeCheckerAnnotation) {
                logger.info(">>>>>>>>>>Class annotation value:{}", ((MyTypeCheckerAnnotation) annotation).value());
            }
        }
        for (Field field : clzz.getDeclaredFields()) {
            if (null != field.getAnnotatedType().getAnnotation(MyTypeCheckerAnnotation.class)) {
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), clzz);
                Method readMethod = propertyDescriptor.getReadMethod();
                if (null == readMethod.invoke(obj)) {
                    logger.info(">>>>>>>>>>属性值为null");
                }
            }
            MyTypeCheckerAnnotation myTypeCheckerAnnotation = field.getAnnotatedType().getAnnotation(MyTypeCheckerAnnotation.class);
            logger.info(">>>>>>>>>>Field annotation value:{}", myTypeCheckerAnnotation.value());
        }
    }

    public static void main(String[] args) throws Exception {
        TypeCheckerAnnotationUsing typeCheckerAnnotationUsing = new TypeCheckerAnnotationUsing();
        annotationProcess(typeCheckerAnnotationUsing.getClass(), typeCheckerAnnotationUsing);
    }
}

4.4 测试结果

在这里插入图片描述

5 小结

  • 注解:元信息。提供代码额外信息。
  • 注解分为元注解和自定义注解。
  • 元注解即注解的注解,用于标识自定义注解,使自定义注解按照既定的轨迹运行。
  • 自定义注解即按照开发者需求定义的元信息,如类型检查、数据校验等。
  • 自定义注解需要明确注解的作用位置(如类、方法、参数等)、生命周期(如RUNTIME、CLASS等)。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值