Annotation(十一)

        元数据(data about data):定义数据的数据。比如,有一条学生信息记录,里面字段包括姓名(name)、年龄(age)等,那么name、age就是元数据,通过这些元数据就可以描述出一个学生。
        Annotation能够被用来为程序元素(类、方法、成员变量等)设置元数据。Annotation是一个接口,通过反射来获取指定程序元素的Annotation对象,然后通过Annotation对象来取得注释里的元数据。

基本Annotation

在这里插入图片描述

三个基本Annotation
  • @Override
  • @Deprecated
  • @SuppressWarnings

@Override

        @Override就是用来指定方法覆盖的,它们可以强制一个子类必须覆盖父类的方法。
在这里插入图片描述
        作用:告诉编译器检查这个方法,并从父类查找是否包含一个被重写的方法,否则编译错误。Annotation就可以帮助我们避免一些低级错误。
        作用范围:只能作用于方法,不能作用于其他元素。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

@Deprecate

        作用:标志某元素已经过时,不建议使用。若使用过时元素编译器会发出警告。
        作用范围:类和方法

在这里插入图片描述

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}

@SuppressWarnings

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
    String[] value();
}

在这里插入图片描述
        作用:取消显示指定的编译器警告。
        作用范围:类,接口、方法,属性

        例如:如果没有泛型限制的集合会引起编译器警告

//取消单类型的警告
@SuppressWarnings(value = "unchecked")
ArrayList arrayList=new ArrayList();
//取消多类型的警告
@SuppressWarnings(value={"unchecked", "rawtypes"})
public void addItems(String item){
   List items = new ArrayList();
   items.add(item);
}
//取消所有类型的警告
@SuppressWarnings("all")
public void addItems(String item){
   List items = new ArrayList();
   items.add(item);
}



自定义Annotation

定义Annotation

        定义Annotation会使用到关键字@interface(在原来接口定义关键字interface前加@符号)。Annotation类型与接口的定义相似。
        语法

public @interface Annotation{
}

        默认情况下,Annotation可以修饰任何元素,包括类。接口、方法,属性等。

Annotation分类
  1. 标记Annotation:一个没有成员定义的Annotation类型称为标记。这种Annotation仅使用自身的存在与否来为我们提供信息。如@Override、@Test。
  2. 元数据Annotation:包含成员变量的Annotation,因为他们可以接受更多元数据,因此称为元数据Annotation。

例1:标记Annotation:不带成员变量的Annotation

public @interface MyAnnotation {
}
@MyAnnotation
public class TestAnnotation {
}

例2:元数据Annotation:带成员变量

public @interface MyAnnotation {
    int age();
    String name();
}
@MyAnnotation(age = 1,name = "小明")
public class TestAnnotation {

}

提取Annotation信息

        Java使用Annotation接口来代表程序前面的注释,该接口是所有Annotation类型的父接口。在java.lang.reflect包下新增了一个AnnotatedElement接口,该接口代表程序中接受注释的程序元素,该接口的几个实现类:

  • Class:类定义
  • Constructor:构造器定义
  • Field:类的成员变量定义
  • Method:类的方法定义
  • Package:包定义

        java.lang.reflect包下主要包含一些实现反射功能的工具类。



使用例子

//java.lang.annotation.Retention;指定MyAnnotation注释可以保留多久
@Retention(RetentionPolicy.RUNTIME)
//java.lang.annotation.Target;指定MyAnnotation的注释对象(这里只能是方法)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
    int age();
    String name();
}

        仅仅使用注释来标识程序是不会有任何影响的,这也是Java注释的一条重要原则,为了让程序起作用,我必须为这些注释提供一个注释处理工具。



示例1:使用一个测试类的注释

        模拟Junit单元测试@Test注解。

结构:
在这里插入图片描述
package annotation1;


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

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Testable {

}

package annotation1;

/**
 * @author Archer
 * @date 2019-04-04 8:35
 **/
public class MyTest {

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

    @Testable
    public static void test2(){
        System.out.println("test2");
    }

    @Testable
    public static void test3(){
        throw new RuntimeException("test3测试异常");

    }


}

package annotation1;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author Archer
 * @date 2019-04-04 8:38
 **/
public class TestProcessor {
    public static void process(String clazz) throws ClassNotFoundException {
        int passed=0;
        int fialed=0;
        //遍历obj对象的所有方法,通过反射获取
        for (Method m: Class.forName(clazz).getMethods()){
            //如果使用Testable标记注释
            if (m.isAnnotationPresent(Testable.class)){
                //调用m方法
                try {
                    m.invoke(null);
                    //passed加一
                    passed++;
                } catch (IllegalAccessException e) {
                    System.out.println("运行异常"+e.getMessage());
                    fialed++;
                } catch (InvocationTargetException e) {
                    System.out.println("运行异常"+e.getMessage());
                    fialed++;
                }
            }
        }

        //统计结果
        System.out.println("共运行了:"+(passed+fialed)+"个方法\npassed:"+passed+"  fail:"+fialed);
    }

    public static void main(String[] args) throws ClassNotFoundException {
        TestProcessor.process("annotation1.MyTest");
    }
}

运行结果:
在这里插入图片描述

JDK的元Annotion(Meta Annotion)

@Retention

         @Retention只能用于修饰一个Annotation定义,用于指定可以保留多长时间。
@Retention包含一个RetentionPolicy类型的value成员变量,所以使用@Retention是必须为该value成员变量指定值。

value可以为的值:
RetentionPolicy.CLASS:编译器将注释记录在class文件中。当运行Java程序时,JVM不再保留注释。这是默认值。
RetentionPolicy.RUNTIME:编译器将把注释记录在class文件中。当运行Java程序时,JVM也会保留注释。
RetentionPolicy.SOURCE:编译器直接丢弃这种策略的注释。

@Target

        @Target用于修饰一个Annotion定义,用于指定被修饰的Annotion只能用于此时哪些程序元素。
@Tartget Annotion也包含一个名为value的成员变量,

该成员变量的值只能是:
在这里插入图片描述

@Inherited

         @Inherited元Annotion指定被修饰的Annotion将具有继承性。
如果一个父类使用A注释(A注释被@Inherite修饰)修饰,其子类也会自动具有A注释。

APT处理Annotion

         APT(annotation processing tool)是一种处理注释的工具,用于对源代码检测出其中的Annotion后,使用Annotion进行额外处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值