自定义注解

在JDK的元注解一章,虽然没有正式介绍,但是相各位已经知道,声明一个注解很简单,就是使用@interface关键字即可。接下来,我们学习如何给自己创建的注解增加一些实际的功能。

自定义注解

 

我们首先来看一下自定义注解的注意事项 :

 

  1. 定义注解需要使用@interface关键字,定义格式 : public @interface 注解名称,其中public是权限修饰符。

示例代码

pbulic @interface Test {}

 

  1. 使用注解很简单,只需要将注解像public,final等修饰符一样,放在程序元素的前面或者上面即可。一般会选择放在程序元素的上面。默认情况下,注解可以修饰程序中的任何元素

示例代码

@Test

public class TestAnnotation {

    @Test

    private String name;

    @Test

    public void test1() {

        System.out.println("test1");

    }

}

 

  1. 定义注解可以为注解声明成员变量,格式 :数据类型 成员变量名称(); 注意,跟声明方法形式很像,但这是注解的成员变量,不是方法。
  2. 注解中的成员变量只能是八种基本数据类型,以及String,Class,Enum等

示例代码

@interface Test {

    //声明注解的成员变量 数据类型 成员变量名称();

    String name();

    int value();

    String[] names();

}

  1. 使用注解的时候必须为注解中所有的成员变量赋值,否则编译报错。

示例代码

@Test(name = "小钻风", value = 300,names= {"避尘大王","避暑大王","避寒大王"})

public class TestAnnotation {

   @Test(name = "小钻风", value = 300,names= {"避尘大王","避暑大王","避寒大王"})

   private String name;

 

   @Test(name = "小钻风", value = 300,names= {"避尘大王","避暑大王","避寒大王"})

   public void test1() {

       System.out.println("test1");

   }

}

  1. 可以为注解的成员变量声明默认值,格式 defalut value

示例代码

@interface Test {

   String name();

   int value();

   String[] names() default {"避尘大王","避暑大王","避寒大王"};

}

  1. 使用注解的时候,带默认值的成员变量可以不赋值,这个时候使用的是注解中成员变量的默认值

示例代码

@Test(name = "小钻风", value = 300)

public class TestAnnotation {

   @Test(name = "小钻风", value = 300)

   private String name;

   @Test(name = "小钻风", value = 300)

   public void test1() {

       System.out.println("test1");

   }

}

  1. 使用注解的时候,如果只需要给注解的value成员变量赋值,则成员变量名称可以省略,只赋值即可

示例代码

@Test(name = "小钻风", value = 300) //value不能省略

public class TestAnnotation {

      @Test(name="小钻风",value = 300) //value不能省略

   private String name;

      @Test(300) //value可以省略

   public void test1() {

       System.out.println("test1");

   }

}

@interface Test {

   String name() default "小钻风";

   int value();

   String[] names() default { "避尘大王", "避暑大王", "避寒大王" };

}

  1. Java.lang.Annotation接口是所有注解的父接口,所以,注解一旦声明创建,便自动继承java.lang.Annotation接口

 

总结 : 根据注解是否包含成员变量,可以把注解分为两类

  1. 标记注解

没有定义成员变量的注解被称为标记。这种注解仅利用自身的存在与否来提供信息,例如@Override。

  1. 元数据注解

包含成员变量的注解可以接受更多的元数据,所以也被称为元数据注解。这种注解,其本身,其成员变量都可以用来提供信息

获取注解信息

使用注解修饰了程序元素以后,这些注解不会自己生效,必须由相应的工具类来提取并处理才能生效。这些工具类都在java.lang.reflect包中。从Java 5开始,java.lang.reflect包所提供的反射AIP增加了读取运行时注解的能力。只有当定义注解的时候使用了@Retention(RetentionPolicy.RUNTIME)修饰,该注解才会在运行时可见,JVM才会在装载.class文件时读取保存在.class文件中的注解。

 

示例代码

 

一:声明注解

@Retention(RetentionPolicy.RUNTIME)

@interface Test {

    String name() default "小钻风";

    int value();

    String[] names() default { "避尘大王", "避暑大王", "避寒大王" };

}

二:创建测试类

@Test(name = "小钻风", value = 300) // value不能省略

public class TestAnnotation {

       @Test(name = "小钻风", value = 300) // value不能省略

       private String name;

       @Test(300) // value可以省略

       public void test1() {System.out.println("test1");}

       public static void main(String[] args)  throw Exception{

                     Class<TestAnnotation> classT = null;

classT = (Class<TestAnnotation>) Class.forName("com.annotation.TestAnnotation");

                     Method method = classT.getMethod("test1");

                     System.out.println(method);

                     //获取指定方法的所有注解

                     Annotation[] annotations = classT.getMethod("test1").getAnnotations();

                     for (Annotation annotation : annotations) {

                            System.out.println(annotation);

                            //将注解强转成所需要的注解类型

                            if (annotation instanceof Test) {

                                   Test temp = (Test) annotation;

                                   //通过注解对象的抽象方法来访问注解中的元数据

                                   System.out.println("name  :" + temp.name());

                                   System.out.println("value :"+temp.value());

                                   String[] names = temp.names();

                                   for (String tempName : names) {

                                          System.out.println("names :"+tempName);

                                   }

                            }

              }

}

小结

Class 、Constructor、 Method、 Field等程序元素均是AnnotatedElement接口的子类。当通过反射获取到某个程序元素以后,就可以通过其父接口AnnotatedElement提供的方法来获取该程序元素上的注解信息。

AnnotatedElement接口提供了如下几个方法帮助开发者获取注解信息

<T extends Annotation> T getAnnotation(Class<T> annotationClass);--返回程序元素上指定类型注解

default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)

-- java8新增方法,返回直接修饰该程序元素,指定类型的注解

Annotation[] getAnnotations();-- 返回程序元素上所有的注解

Annotation[] getDeclaredAnnotations();-- 返回直接修饰该程序元素的所有注解

default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)

--- java8新增方法,与重复注解有关,获取指定类型的多个注解

default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)

--- java8新增方法,与重复注解有关,获取直接修饰该程序元素,指定类型的多个注解

default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

-- 判断该程序元素上是否存在指定类型的注解

 

示例代码 : 获取重复注解

 

    public static void main(String[] args) throws ClassNotFoundException {

        Class<People> clazz = (Class<People>) Class.forName("com.annotation.People");

        // java 8 以前获取重复注解的方式

        Roles roles = clazz.getDeclaredAnnotation(Roles.class);

        Role[] rolesArray = roles.value();

        for (Role role : rolesArray) {

            System.out.println(role.value());

        }

        // java 8新增获取重复注解的方式

        Role[] roleArray = clazz.getDeclaredAnnotationsByType(Role.class);

        for (Role role : roleArray) {

            System.out.println(role.value());

        }

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

会飞的王小卡

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值