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();
        }
    }

  • 相关阅读:
    remove white space from read
    optimize the access speed of django website
    dowload image from requests
    run jupyter from command
    crawl wechat page
    python version 2.7 required which was not found in the registry windows 7
    health
    alternate rows shading using conditional formatting
    word
    【JAVA基础】static 关键字
  • 原文地址:https://www.cnblogs.com/zhangmingda/p/14782441.html
Copyright © 2011-2022 走看看