zoukankan      html  css  js  c++  java
  • java 编程基础:【注解】 提取注解信息,利用自定义注解编写测试类,注解绑定事件

    提取注解信息

    使用注解修饰了类、方法、成员变量等成员之后,这些注解不会自己生效,必须由开发者提供相应工具来提取并处理注解信息。
     
    Java使用java.lang.annotation.Annotation接口代表程序元素前面的注解,该接口是所有注解的父接口。Java5在java.lang.reflect包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解程序元素(就是哪些类可以被注解修饰)。该接口主要有如下几个实现类。
    • Class: 类定义
    • Constructor: 构造器定义
    • Field: 类的成员变量定义
    • Method: 类的方法定义
    • Packag: 的包定义
     
    对于AnnotatedElement的实现类,Java提供了如下几个方法来获取修饰其的注解的信息:
     
    package com.zmd.myAnnotation;
    import java.lang.annotation.*;
    
    @Retention(RetentionPolicy.RUNTIME) //配置生命周期运行时可以获取到
    @Inherited //配置注解的继承性,用了注解的父类,子类默认被修饰
    public @interface MyAnnotation {
        String name() default "zmd";
        int age() default 22;
    }

    定义一个父类使用注解

    package com.zmd.myAnnotation;
    
    import java.lang.annotation.Annotation;
    
    @MyAnnotation(name = "hehe",age = 1)
    public class MyClass {
        public static void main(String[] args) {
            //判断是否有MyAnnotation注解修饰
            System.out.println(MyClass.class.isAnnotationPresent(MyAnnotation.class)); //true
            //获取包括继承父类的注解。
            Annotation annotation = MyClass.class.getAnnotation(MyAnnotation.class);
            if (annotation instanceof MyAnnotation){
                MyAnnotation myAnnotation = (MyAnnotation) annotation;
                System.out.println("tag is:" + annotation);  //tag is:@com.zmd.myAnnotation.MyAnnotation(name="hehe", age=1)
                System.out.println("name is:" + myAnnotation.name()); //name is:hehe
                System.out.println("age is:" + myAnnotation.age()); //age is:1
            }
        }
    }

    定义子类继承父类获取注解信息

    package com.zmd.myAnnotation;
    import java.lang.annotation.Annotation;
    
    public class MySubClass extends MyClass {
        public static void main(String[] args) {
            //是不是有MyAnnotation注解修饰
            System.out.println(MySubClass.class.isAnnotationPresent(MyAnnotation.class)); //true
            //获取指定类型的Annotation
    //        Annotation annotation = SubClass.class.getAnnotation(MyAnnotation.class);//用这行代码,可以获取到MyAnnotation,因为MyAnnotation是获取所有包括继承性的
            Annotation annotation = MySubClass.class.getDeclaredAnnotation(MyAnnotation.class);//用这行代码无法获取到MyAnnotation,因为我们getDeclaredAnnotation方法只能获取到直接修饰该类的注解,不能获取到从父类继承过来的注解
            System.out.println(annotation); //null
            if (annotation instanceof MyAnnotation) { //false 啥也没输出
                System.out.println("tag is " + annotation);
                System.out.println("name is " + ((MyAnnotation) annotation).name());
                System.out.println("age is " + ((MyAnnotation) annotation).age());
            }
        }
    }

    编写测试工具

    利用自定义注解标识可测试的方法,编写测试工具类,用于测试那些只标识了可以测试的方法

    1、编写自定义注解

    package com.zmd.autotestTools;
    
    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 {
    }

    2、编写使用注解的类

    package com.zmd.autotestTools;
    
    public class MyClass {
        @Testable
        public static void m1() {};
    
        public static void m2() {};
    
        @Testable
        public static void m3() {throw new RuntimeException();};
    
        public static void m4() {};
    
        @Testable
        public static void m5() {throw new IllegalArgumentException();};
    
        public static void m6() {};
    
        @Testable
        public static void m7() {};
    
        public static void m8() {};
    }

    3、编写工具类测试 使用注解的类中的方法

    package com.zmd.autotestTools;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    /**
     * @ClassName TestMethod
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/5/18.
     */
    public class TestMethod {
        public static void test(Class<?> cls) throws IllegalAccessException, InstantiationException {
            //获取所有的方法
            Method[] methods = cls.getMethods();
            //创建一个实例
            MyClass myClass = (MyClass) cls.newInstance();
            for (Method method : methods){
                //如果方法被修饰,意思是可以测试
                if (method.isAnnotationPresent(Testable.class)){
                    //那就测试
                    try {
                        //如果是静态方法
                        if (Modifier.isStatic(method.getModifiers())){
                            method.invoke(null);
                        }else {
                            method.invoke(MyClass.class);
                        }
                        System.out.println(method.getName() + "测试成功");
                    }catch (InvocationTargetException e) {
    //                    e.printStackTrace();
                        System.err.println(method.getName() + "测试失败");
                    }
    
                }
            }
        }
    
        public static void main(String[] args) throws InstantiationException, IllegalAccessException {
            test(MyClass.class);
        }
    }

     注解绑定事件

    开发思路:

    • 1、定义单独一个处理注解的类,使用此类的静态方法处理给定对象中的所有实例变量。
    • 2、自定义注解中定义属性,用于使用注解时传入对应的事件类型。
    • 3、窗口Button使用注解,再调用处理注解的类处理窗口中所有实例变量。

    1、编写自定义注解

    package com.zmd.annotationbindAction;
    
    import java.awt.event.ActionListener;
    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.FIELD) //只能修饰类变量实例变量
    public @interface ActionListenFor {
        Class<? extends ActionListener>  value();
    }

    2、编写绑定事件方法类

    package com.zmd.annotationbindAction;
    
    import javax.swing.*;
    import java.awt.event.ActionListener;
    import java.lang.reflect.Field;
    import java.lang.reflect.Type;
    
    /**
     * @ClassName ProcessesAnnotation
     * @projectName: object1
     * @author: Zhangmingda
     * @description: 处理
     * date: 2021/5/18.
     */
    public class ProcessesAnnotation {
        public static void processes(Object object) throws IllegalAccessException, InstantiationException {
            Class<?> cls = object.getClass();
            //获取所有属性
            Field[] allField = cls.getDeclaredFields();
            for (Field field : allField) {
                //如果属性被注解修饰
                if (field.isAnnotationPresent(ActionListenFor.class)){
                    //设置可访问
                    field.setAccessible(true);
                    //获取对应的注解
                    ActionListenFor actionListenFor = field.getAnnotation(ActionListenFor.class);
                    //获取要绑定的事件的Class,创建事件监听器
                    Class<? extends ActionListener> actionClass = actionListenFor.value();
                    ActionListener actionListener = actionClass.newInstance();
                    //将属性转换为button对象绑定事件
                    AbstractButton button = (AbstractButton) field.get(object);
                    button.addActionListener(actionListener);
                }
            }
        }
    }

    2、编写图形化窗口

    package com.zmd.annotationbindAction;
    
    import javax.swing.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    /**
     * @ClassName TestAnnotationBindAction
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/5/18.
     */
    public class TestAnnotationBindAction {
    
        //定义窗口需要的基础属性
        private JFrame jFrame = new JFrame("测试注解绑定事件");
    
        @ActionListenFor(okAction.class)
        private JButton confirmbutton = new JButton("确定");
    
        @ActionListenFor(cancleAction.class)
        private JButton canclebutton = new JButton("取消");
    
        private JPanel jPanel = new JPanel();
    
        /**
         * 组装窗口
         */
        private void  start() throws InstantiationException, IllegalAccessException {
            jPanel.add(confirmbutton);
            jPanel.add(canclebutton);
            jFrame.add(jPanel);
            jFrame.setLocation(400,300);
            jFrame.pack();
            jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            jFrame.setVisible(true);
            //使用处理类处理本类所有属性
            ProcessesAnnotation.processes(this);
        }
    
        public static class okAction implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("点击了确认按钮");
            }
        }
        public static class cancleAction implements ActionListener {
            @Override
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("点击了取消按钮");
            }
        }
        public static void main(String[] args) throws IllegalAccessException, InstantiationException {
            new TestAnnotationBindAction().start();
        }
    }

  • 相关阅读:
    压缩流GZipStream
    委托和事件
    .NET垃圾回收机制
    程序集相关知识
    生活
    poj 3767 I Wanna Go Home
    fw:Python GUI的设计工具
    How to configure an NTP client and server on CentOS/RedHat
    FW:Tripwire
    Bash if 判断 集合
  • 原文地址:https://www.cnblogs.com/zhangmingda/p/14782441.html
Copyright © 2011-2022 走看看