Java中怎么创建一个自定义注解?

Java中常见的注解

JDK自带的注解

1.@Override 表示重写了此方法
2.@Deprecated 表示这个方法过时了,不建议使用,Ide会在方法上划横线
3.@SuppressWarnings(“deprecation”) 关闭方法中出现的警告

@SuppressWarnings注解参数常见用法:

1.deprecation:去除不赞成使用类的警告
2.serial:去除当在可序列化的类上缺少 serialVersionUID 定义时的警告
3.finally:去除任何 finally 子句不能正常完成时的警告
4.rawtypes:去除传参数时也要带泛型的警告
5.unchecked:去除执行了未检查的转换时的警告,例如当使用集合时没有用泛型来指定集合保存的类型
6.unused:去除对未使用代码的警告
7.all:去除所有类型的警告

元注解

元注解的作用就是注解其他注解,一般我们使用自定义注解时,就需要用元注解来标注我们自己的注解

@Target:

说明了Annotation被修饰的范围,在Annotation类型的声明中使用了@Target可更加清晰其修饰的目标,声明的范围包括:
1.@Target(ElementType.TYPE):用于类、接口(包括Annotation类型)或枚举
2.@Target(ElementType.FIELD):用于类的成员变量(包括枚举常量)
3.@Target(ElementType.METHOD):用于方法
4.@Target(ElementType.PARAMETER):用于参数
5.@Target(ElementType.CONSTRUCTOR):用于构造器
6.@Target(ElementType.LOCAL_VARIABLE):用于局部变量
7.@Target(ElementType.ANNOTATION_TYPE):用于Annotation类型
8.@Target(ElementType.PACKAGE):用于包
9.@Target(ElementType.TYPE_PARAMETER):1.8新增,Type parameter declaration
10.@Target(ElementType.TYPE_USE):1.8新增,Use of a type

ElementType源码:

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,

    /** Field declaration (includes enum constants) */
    FIELD,

    /** Method declaration */
    METHOD,

    /** Formal parameter declaration */
    PARAMETER,

    /** Constructor declaration */
    CONSTRUCTOR,

    /** Local variable declaration */
    LOCAL_VARIABLE,

    /** Annotation type declaration */
    ANNOTATION_TYPE,

    /** Package declaration */
    PACKAGE,

    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

@Retention:

定义了该Annotation被保留的时间长短,有些只在源码中保留,有时需要在编译成的class中保留,有些需要程序运行时候保留。即描述注解的生命周期。声明类型包括:
1.@Retention(RetentionPolicy.SOURCE) 在源文件保留,例如@Override就是用了@Retention(RetentionPolicy.SOURCE)
2.@Retention(RetentionPolicy.CLASS) 在class中保留,自定义注解默认是在class中保留,对于为什么要使用CLASS不是很明白,这有一篇文章对两者进行了讨论,但我还是不是很明确,希望日后能找到答案
3.@Retention(RetentionPolicy.RUNTIME) 运行时保留,可以通过反射获取,例如@Deprecated使用了@Retention(RetentionPolicy.RUNTIME)

RetentionPolicy源码:

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,

    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}

@Documented:

它表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中,是一个标记注解,没有成员。

@Inherited:

它也是一个标记注解,它的作用是,被它标注的类型是可被继承的,比如一个class被@Inherited标记,那么一个子类继承该class后,则这个annotation将被用于该class的子类。

注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。对于这句话的理解通过如下实例说明:

自定义一个注解类,使用@Inherited,配合使用@Retention(RetentionPolicy.RUNTIME)以通过反射观察注解的继承情况:

package com.lyh.study.annotation;

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Created by liuyunhui on 2020-03-11 16:05.
 * description:
 */
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedDemo {
    String name();
}

新建一个父类:

package com.lyh.study.annotation;

/**
 * Created by liuyunhui on 2020-03-11 16:11.
 * description:
 */
@InheritedDemo(name = "注解可被继承的父类")
public abstract class InheritedParentClass {
    @InheritedDemo(name = "父类中被重写的方法")
    public void override(){
        System.out.println("会被重写的方法");
    }

    @InheritedDemo(name = "父类中没被重写的方法")
    public void notOverride(){
        System.out.println("不被重写的方法");
    }

    @InheritedDemo(name = "父类中的抽象方法")
    public abstract void abstractMethod();
}

新建一个子类,继承上边的父类:

package com.lyh.study.annotation;

/**
 * Created by liuyunhui on 2020-03-11 16:11.
 * description:
 */
public class InheritedChildClass extends InheritedParentClass{

    @Override
    public void abstractMethod() {
        System.out.println("实现父类的抽象方法");
    }

    @Override
    public void override() {
        super.override();
        System.out.println("重写了父类的方法");
    }
}

测试:

package com.lyh.study.annotation;


import org.junit.Test;

public class TestClass {

    @Test
    public void test1() {

        Class<InheritedChildClass> inheritedChildClassClass = InheritedChildClass.class;
        if(inheritedChildClassClass.isAnnotationPresent(InheritedDemo.class)){
            final InheritedDemo annotation = inheritedChildClassClass.getAnnotation(InheritedDemo.class);
            System.out.println("子类获取到父类的注解,name:"+annotation.name());
        }else {
            System.out.println("子类获取不到父类的注解");
        }
    }

}

结果输出:
在这里插入图片描述
注意:如果自定义注解InheritedDemo没有使用注解@Retention(RetentionPolicy.RUNTIME),结果为子类获取不到父类的注解

测试:

//抽象方法的测试
        try {
            final Method abstractMethod = inheritedChildClassClass.getMethod("abstractMethod", new Class[]{});
            if(abstractMethod.isAnnotationPresent(InheritedDemo.class)){
                final InheritedDemo annotation = abstractMethod.getAnnotation(InheritedDemo.class);
                System.out.println("子类实现了父类抽象方法,获取到父类抽象方法的注解,name:"+annotation.name());
            }else{
                System.out.println("子类实现了父类抽象方法,获取不到父类的注解");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

结果输出:
在这里插入图片描述
测试:

//重写方法的测试
        try {
            final Method overrideMethod = inheritedChildClassClass.getMethod("override", new Class[]{});
            if(overrideMethod.isAnnotationPresent(InheritedDemo.class)){
                final InheritedDemo annotation = overrideMethod.getAnnotation(InheritedDemo.class);
                System.out.println("子类重写了父类方法,获取到父类方法的注解,name:"+annotation.name());
            }else{
                System.out.println("子类重写了父类方法,获取不到父类方法的注解");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        System.out.println("----------------------------");
        //未重写方法的测试
        try {
            final Method notOverrideMethod = inheritedChildClassClass.getMethod("notOverride", new Class[]{});
            if(notOverrideMethod.isAnnotationPresent(InheritedDemo.class)){
                final InheritedDemo annotation = notOverrideMethod.getAnnotation(InheritedDemo.class);
                System.out.println("子类未重写父类方法,获取到父类方法的注解,name:"+annotation.name());
            }else{
                System.out.println("子类未重写父类方法,获取不到父类方法的注解");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

结果输出:
在这里插入图片描述
新建一个接口:

package com.lyh.study.annotation;

/**
 * Created by liuyunhui on 2020-03-11 16:11.
 * description:
 */
@InheritedDemo(name = "注解在接口上")
public interface InheritedParentInterface {

    @InheritedDemo(name = "注解在接口的方法上")
    void abstractMethod();
}

接口实现类:

package com.lyh.study.annotation;

/**
 * Created by liuyunhui on 2020-03-11 16:11.
 * description:
 */

public class InheritedParent2Class implements InheritedParentInterface{
    @InheritedDemo(name = "被重写的方法的注解")
    public void override(){
        System.out.println("会被重写的方法");
    }

    @InheritedDemo(name = "未被重写的方法的注解")
    public void notOverride(){
        System.out.println("不被重写的方法");
    }


    @Override
    public void abstractMethod() {
        System.out.println("实现的抽象方法");
    }
}

测试:

Class<InheritedParent2Class> inheritedParent2Class = InheritedParent2Class.class;
        //实现的接口类测试
        if (inheritedParent2Class.isAnnotationPresent(InheritedDemo.class)) {
            final InheritedDemo annotation = inheritedParent2Class.getAnnotation(InheritedDemo.class);
            System.out.println("实现类,获取到实现接口上的注解,name:" + annotation.name());
        } else {
            System.out.println("实现类,未获取到实现接口上的注解");
        }
        System.out.println("----------------------------");
        //实现的接口类方法测试
        try {
            final Method abstractMethod = inheritedParent2Class.getMethod("abstractMethod", new Class[]{});
            if(abstractMethod.isAnnotationPresent(InheritedDemo.class)){
                final InheritedDemo annotation = abstractMethod.getAnnotation(InheritedDemo.class);
                System.out.println("实现类实现的接口类方法,获取到接口类方法的注解,name:"+annotation.name());
            }else{
                System.out.println("实现类实现的接口类方法,未获取到接口类方法的注解");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

结果输出:
在这里插入图片描述
新建一个子类,继承接口实现类InheritedParent2Class :

package com.lyh.study.annotation;

/**
 * Created by liuyunhui on 2020-03-11 16:11.
 * description:
 */
public class InheritedChild2Class extends InheritedParent2Class{

    @Override
    public void abstractMethod() {
        System.out.println("实现父类的抽象方法");
    }

    @Override
    public void override() {
        super.override();
        System.out.println("重写了父类的方法");
    }
}

测试:

System.out.println("----------------------------");
        Class<InheritedChild2Class> inheritedChild2Class = InheritedChild2Class.class;
        //继承实现了接口的类的类测试
        if (inheritedChild2Class.isAnnotationPresent(InheritedDemo.class)) {
            final InheritedDemo annotation = inheritedChild2Class.getAnnotation(InheritedDemo.class);
            System.out.println("子类,父类实现了接口类,获取到实现接口上的注解,name:" + annotation.name());
        } else {
            System.out.println("子类,父类实现了接口类,未获取到实现接口上的注解");
        }

        System.out.println("----------------------------");
        //子类方法测试
        try {
            final Method abstractMethod = inheritedChild2Class.getMethod("abstractMethod", new Class[]{});
            if(abstractMethod.isAnnotationPresent(InheritedDemo.class)){
                final InheritedDemo annotation = abstractMethod.getAnnotation(InheritedDemo.class);
                System.out.println("子类,父类实现了接口类,获取到的注解,name:"+annotation.name());
            }else{
                System.out.println("子类,父类实现了接口类,未获取到注解");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        System.out.println("----------------------------");
        //重写方法的测试
        try {
            final Method overrideMethod = inheritedChild2Class.getMethod("override", new Class[]{});
            if(overrideMethod.isAnnotationPresent(InheritedDemo.class)){
                final InheritedDemo annotation = overrideMethod.getAnnotation(InheritedDemo.class);
                System.out.println("子类,父类实现了接口类,重写父类方法,获取到的注解,name:"+annotation.name());
            }else{
                System.out.println("子类,父类实现了接口类,重写父类方法,未获取到注解");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        System.out.println("----------------------------");
        //未重写方法的测试
        try {
            final Method notOverrideMethod = inheritedChild2Class.getMethod("notOverride", new Class[]{});
            if(notOverrideMethod.isAnnotationPresent(InheritedDemo.class)){
                final InheritedDemo annotation = notOverrideMethod.getAnnotation(InheritedDemo.class);
                System.out.println("子类,父类实现了接口类,未重写父类方法,获取到的注解,name:"+annotation.name());
            }else{
                System.out.println("子类,父类实现了接口类,未重写父类方法,未获取到注解");
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

结果输出:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值