java 编程基础:【注解】 提取注解信息,利用自定义注解编写测试类,注解绑定事件
提取注解信息
使用注解修饰了类、方法、成员变量等成员之后,这些注解不会自己生效,必须由开发者提供相应工具来提取并处理注解信息。
Java使用java.lang.annotation.Annotation接口代表程序元素前面的注解,该接口是所有注解的父接口。Java5在java.lang.reflect包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解程序元素(就是哪些类可以被注解修饰)。该接口主要有如下几个实现类。
- Class: 类定义
- Constructor: 构造器定义
- Field: 类的成员变量定义
- Method: 类的方法定义
- Packag: 的包定义
对于AnnotatedElement的实现类,Java提供了如下几个方法来获取修饰其的注解的信息:
- A getAnnotation(Class annotationClass): 返回该程序元素上存在的、指定类型的注解,如果该类型的注解不存在,则返回null。
- A getDeclaredAnnotation(Class ann tationClass):Java8新增的方法,获取直接修饰元素的指定类型的注解(不会获取到从父类集成来的注解)
- Annotation[] getAnnotations(): 返回元素上的所有注解
- Annotation[] getDeclaredAnnotations(): 返回直接修饰该程序元素的所有注解(不会获取到从父类集成来的注解)
- boolean isAnnotationPresent(Class annotationClass): 判断该程序元素是否存在指定类型的注解,如果存在则返回true 否则返回 false
- Annotation[] getAnnotationsByType(Class annotationClass): 由于Java8增加了重复注解功能,因此需要使用该方法获取对应元素指定类型的可重复的注解
- Annotation[] getDeclaredAnnotationsByType(Class annotationClass): 同上,java8新增了重复注解功能,需要使用该方法获取直接修饰对应元素指定类型的可重复的注解(不会获取到从父类集成来的注解)
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(); } }
posted on 2021-05-18 20:00 zhangmingda 阅读(343) 评论(0) 编辑 收藏 举报