java核心学习(十) 注解Annotation----上

一、java的五个自带的注解

  @Override,方法重写的限定

  @Deprecated,标记已过时

  @SuppressWarnings,抑制编译器警告

  @SafeVararges,抑制堆污染警告

  @FunctionalInterface,标记函数式接口

二、JDK的元Annotation

  元Annotation指 Annotation的Annotation,最根本的注解。在java8里共有六个元注解,其中五个·用于修饰其他注解的定义,另外一个用于定义java8新增的重复注解。

  1、 @Retention 用于指定被修饰的Annotation可以保留多长时间,有且仅有一个名为value的成员变量,value的值仅能为如下三种

    RetentionPolicy.CLASS 编译器把Annotation记录在class文件中,当运行java程序时,JVM不可以获取Annotation信息,不可以通过反射来获取Annotation信息,这也是value的默认值。

    RetentionPolicy.RUNTIME 编译器把Annotation记录在class文件中,可利用反射在运行时获取Annotation信息,JVM也可以获取反射信息。

    RetentionPolicy.SOURCE 只保留在java源代码中,在编译为class文件中丢弃之。

  2、 @Target 用于指定被修饰的Annotation能用于修饰哪些程序单元,也仅含有一个value成员变量,其允许的值如下

    ElementType.ANNOTATION_TYPE 指定该annotation只能用于修饰 Annotation

    ElementType.CONSTRUCTOR 指定该注解只能用于修饰构造器

    ElementType.FIELD 指定该注解只能修饰成员变量

    ElementType.LOCAL_VARIABLE 指定该注解只能修饰局部变量

    ElementType.METHOD 指定该注解只能修饰方法定义

    ElementType.PACKAGE 指定该注解只能修饰包定义

    ElementType.PARAMETER 指定该注解可以修饰参数

    ElementType.TYPE 指定该注解可以修饰类、接口(包括注解类型)或枚举定义。

  3、 @Documented 用于使用javadoc工具生成文档时加入注解,不赘述

  4、 @inherited 指定被该注解修饰的类具有继承性

三、定义注解并使注解达到一定功能的实例

  实例一、定义一个Testable来标记哪些方法是可以测试的

    首先需要定义注解 @Testable ,定义注解就是定义注解的名字和上述的几个性质还有注解的内容(成员变量),注解本身只是对源代码添加一些特殊标记,注解本身并不会影响源代码,这些特殊标记可以被反射获取来编写注解的处理类。

    定义注解的代码:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//定义注解的持续时间为Runtime,定义注解的目标为Method
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Testable {
    //该注解的功能为标记方法时候可被测试,不需要成员变量,仅仅只需要通过注解的有无来判断即可。
}

    编写使用该注解的类

public class MyTest {
    @Testable
    public static void m1(){

    }

    public static void m2(){

    }
    @Testable
    public static void m3(){
        throw new IllegalArgumentException("参数出错");
    }
    public static void m4(){}
    @Testable
    public static void m5(){

    }

    public static void m6(){

    }
    @Testable
    public static void m7(){
        throw new RuntimeException("程序业务出现异常");
    }
    public static void m8(){}

}

    要想让上面MyTest类中的注解发挥作用,必须要编写注解的处理工具类,通过反射的方式来处理注解,这里用函数式接口来代替,真正处理注解的代码放在了main方法里

public interface ProcessorTest {
void process(String clazz) throws ClassNotFoundException;
}

    main方法如下:

import java.lang.reflect.Method;

public class RunTests {
    public static void process(String clazz,ProcessorTest processorTest) throws ClassNotFoundException{
        processorTest.process(clazz);
    }
    public static void main(String[] args) throws ClassNotFoundException{
        process("MyTest", new ProcessorTest() {
            @Override
            public void process(String clazz) throws ClassNotFoundException{
                int passed = 0;
                int failed = 0;
                for (Method m:Class.forName("MyTest").getMethods()
                     ) {
                    //判断方法是否使用了@Testable来修饰
                    if(m.isAnnotationPresent(Testable.class)){
                        try {
                            m.invoke(null);
                            passed++;
                        }
                        catch (Exception e){
                            System.out.println("方法"+ m + "运行失败,异常:"+e.getCause());
                            failed++;
                        }
                    }
                }
                System.out.println("共运行了:"+(passed+failed)+"个方法,其中:\n失败了:"+failed+"个,\n成功了:"+passed+"个");
            }
        });
    }
}

    由于上面代码编译使用java7,所以无法使用lambda表达式。

    运行结果如下

方法public static void MyTest.m3()运行失败,异常:java.lang.IllegalArgumentException: 参数出错
方法public static void MyTest.m7()运行失败,异常:java.lang.RuntimeException: 程序业务出现异常
共运行了:4个方法,其中:
失败了:2个,
成功了:2个

Process finished with exit code 0

 

posted @ 2017-09-11 16:50  The_shy  阅读(215)  评论(0编辑  收藏  举报