注解和反射

1、JDK中提供的三个基本的注解
@Deprecated:标注XX过时的。
@SuppressWarnings:抑制警告
    unused:抑制的警告类型
    { "unused", "rawtypes", "unchecked" }:数组,抑制的多个警告类型
    all:抑制所有警告

@Override:保证用户确实是覆盖了父类的某个方法。

2、自定义注解
使用@interface关键字来声明注解:public @interface MyAnn1{}
声明注解的属性字段:类型 字段名() [defalut 默认值];
注解属性的类型只能下面的几种:
String Class 八个基本类型 注解类型 枚举类型 及以上类型的1维数组。

特殊属性:String value;或String[] value();
使用时,直接给定取值,而不用加属性名称
//定义注解
public @interface MyAnn1 {
    String name() default "";
    int age() default -1;
    String city();
    MyAnn2[] ann(); //注解中使用注解类型
}

public @interface MyAnn2 {
    String name() default "";
    String[] value() default ""; //使用是直接使用即可,不需要写属性名
}
public class UserMyAnn1 {
    // @MyAnn1(name="wf",age=98,city="山沟沟")//没有指定属性
    // public void m1(){
    //
    // }
    @MyAnn2("abc")
    // 如果省略属性名,就是给value赋值
    public void m2() {

    }

    @MyAnn2(value = "abc", name = "def")
    public void m3() {

    }

    //数组形式
    @MyAnn2(name = "def", value = { "a", "b", "c" })
    public void m4() {

    }

//注解中使用注解类型
    @MyAnn1(name = "abc", city = "BJ", ann = {
            @MyAnn2(name = "a", value = "b"), @MyAnn2(name = "c", value = "d") })
    public void m5() {

    }
}
3、元注解
服务于注解的注解就是元注解
*@Retention:指定注解的存活范围。默认是CLASS
RetentionPolicy:SOURCE|CLASS|RUNTIME

注解和反射_第1张图片

*@Target:指定注解可以用在什么元素上
ElementType:TYPE|METHOD|。。。

@Documented: 用于指定被该元 Annotation 修饰的 Annotation 类将被 javadoc 工具提取成文档.

@Inherited: 被它修饰的 Annotation 将具有继承性.如果某个类使用了被 
@Inherited 修饰的 Annotation, 则其子类将自动具有该注解
//注解和反射一起使用:

public class MyJunitTest {
    @MyTest(time=100000000)
    public void testAdd(){
        System.out.println("执行了add方法的测试");
    }
    @MyTest
    public void testUpdate(){
        System.out.println("执行了update方法的测试");
    }
}


//反射实现单元测试:

//反射注解:所有注解类型都是Annotation类型的子类
/*
java.lang.reflect.AnnotatedElement:
     getAnnotation(Class annotationType):
        获取指定类型的注解
    Annotation[] getAnnotations():获取所有的注解
    Annotation[] getDeclareAnnotations():返回直接存在于此元素上的所有注释,包含继承
    boolean isAnnotationPresend(Class):有木有指定的注解

    Class, Constructor, Field, Method, Package都实现了该接口
 */
public class MyTestRunner {
    //执行测试:
    /*
     * 获取要测试的java类:MyJunitTest
     * 取到其中的所有方法:Method
     * 看看谁的方法前面有@MyTest的注解,谁有就执行谁
     */
    public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException {
        test2();
    }
    //反射带有属性的注解
    private static void test2() throws IllegalAccessException,
            InvocationTargetException, InstantiationException {
        Class clazz = MyJunitTest.class; //获取要测试的类
        Method ms[] = clazz.getMethods();
        for(Method m:ms){
            MyTest myTest = m.getAnnotation(MyTest.class); //从方法上获取指定类型的注解  @MyTest
            if(myTest!=null){
                //得到注解的属性
                long timeLimit = myTest.time(); //获取指定类型的注解的属性上面的值 @MyTest(time=100000000)
                if(timeLimit>-1){
                    //有性能测试需求
                    long startTime = System.nanoTime();
                    m.invoke(clazz.newInstance(), null); //执行每个方法

                    long useTime = System.nanoTime()-startTime;
                    if(useTime>timeLimit){
                        System.out.println(m.getName()+"执行效率没有测试通过");
                    }
                }else{
                    //没有性能测试需求
                    m.invoke(clazz.newInstance(), null);
                }

            }
        }
    }
    //注解的基本反射
    private static void test1() throws IllegalAccessException,
            InvocationTargetException, InstantiationException {
        Class clazz = MyJunitTest.class;
        Method ms[] = clazz.getMethods();
        for(Method m:ms){
            boolean b = m.isAnnotationPresent(MyTest.class); //判断有木有指定的注解
//          System.out.println(m.getName()+"方法上有木有MyTest注解:"+b);
            if(b){
                m.invoke(clazz.newInstance(), null);//
            }
        }
    }

}

你可能感兴趣的:(javaee)