欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

浅谈Java反射与Annotation

程序员文章站 2024-01-20 17:29:28
...
通过Java反射机制,编程人员可以更加深入的控制程序的运行过程。从JDK1.5开始新增了Annotation功能,本文主要讲述Java反射的相关内容,包括定义Annotation类型的方法和在程序运行时访问Annotation信息的方法。通过学习本文,你能构了解到:通过反射访问构造方法的的方法、访问成员变量的方法、访问方法的方法、定义Annotation类型的方法、访问Annotation信息的方法。
  • Class类与Java反射
通过Java反射机制,可以在程序中访问已经装载到JVM中的Java对象的描述,实现访问、监测和修改Java对象本身信息的功能。Java中所有的类均继承自Object,在Object类中定义了getClass()方法,该方法返回一个Class的对象,通过该Class对象可以返回其所有的信息。
package annotation.blog;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class BlogDemoReflect {
	public static void main(String[] args) {
		BlogDemo bd = new BlogDemo("test");
		Class bdC = bd.getClass();
		// 包路径
		Package packageUrl = bdC.getPackage();
		System.out.println(packageUrl);
		// 类名称
		String className = bdC.getName();
		System.out.println(className);
		// 继承类
		Class classObj = bdC.getSuperclass();
		System.out.println(classObj);
		// 实现接口
		Class[] interfaceObjs = bdC.getInterfaces();
		
		// 权限为public构造方法
		Constructor[] constructors = bdC.getConstructors();
		// 所有构造方法
		Constructor[] allConstructors = bdC.getDeclaredConstructors();
		
		// 权限为public方法
		Method[] methods = bdC.getMethods();
		// 所有方法
		Method[] allMethods = bdC.getDeclaredMethods();
		
		// 权限为public的成员变量
		Field[] fields = bdC.getFields();
		// 所有成员变量
		Field[] allFields = bdC.getDeclaredFields(); 		
	}	
}
注意:getFields()和getMethod()获得权限为public的成员变量和方法,包含从超类中继承得到的成员变量和方法;通过getDeclaredFields()和getDeclaredMethods()只是获得本类中的所有成员和方法。执行具有可变数量的参数的构造方法时,需要将入口参数定义为二维数组。

  • 使用Annotation功能
定义Annotation:
package annotation.blog;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationDemo {
	String value() default "test";
}
定义一个Annotation需要使用接口的关键字interface,需要在其前方加上@符号,该关键字的隐含意思为继承了java.lang.annotation.Annotation接口。@Target用来设置Annotation类型适用的程序元素种类,未设置默认是所有程序元素。枚举类ElementType中的枚举常量用来设置@Target:
ANNOTATION_TYPE:表示用于Annotation类型;
TYPE:表示用于类、接口和枚举,以及Annotation类型;
CONSTRUCTOR:用于构造方法;
FIELD:用于成员变量和枚举常量;
METHOD:用于方法;
PARAMETER:用于参数;
LOCAL_VARIABLE:用于局部变量;
PACKAGE:用于包;
@Retention可以设置Annotation的有效范围。枚举类RetentionPolicy中的枚举常量设置@Retention:
SOURCE:不编译Annotation到类文件中,有效范围小;
CLASS:编译Annotation到类文件中,但运行时不加载Annotation到JVM中;
RUNTIME:表示运行时加载Annotation到JVM中,有效范围最大。

访问Annotation信息:
如果在定义Annotation类型时将@Retention设置为RetentionPolicy.RUNTIME,运行程序时通过反射就可以获取到相关的Annotation信息,如构造方法、字段、方法的Annotation信息。以Retry注解为实例进行分析:
注解类:
package annotation.retry;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Retry {
	int interval() default 3;
	int time() default 4000;
}
注解处理器类:
package annotation.retry;

import java.lang.reflect.Method;

class MyRunnable implements Runnable{
	private int interval;
	private int time;
	private Method method;
	public MyRunnable(int interval, int time, Method method){
		this.interval = interval;
		this.time = time;
		this.method = method;
	}
	@Override
	public void run() {
		for(int i = 0; i < interval; i++){
			try {
				method.invoke(new Object(), "Hello World");
				Thread.sleep(time);
			}catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
}
public class RetryProcessor {
	public void parseMethod(Class<?> clazz) throws Exception{
		Method[] methods = clazz.getDeclaredMethods();
		for(Method method : methods){
			Retry retry = method.getAnnotation(Retry.class);
			if(retry != null){
				int interval = retry.interval();
				int time = retry.time();
				System.out.println(interval);
				System.out.println(time);
				Thread t = new Thread(new MyRunnable(interval, time, method));
				t.start();
			}
		}
	}
}
注解测试类:
package annotation.retry;

public class RetryTest {
	@Retry
	public static void sayHello(String name){
		System.out.println("say hello1 " + name);
	}
	@Retry(interval = 9, time = 9000)
	public static void sayHello2(String name){
		System.out.println("say hello2 " + name);
	}
	public static void main(String[] args) throws Exception {
		RetryProcessor retry = new RetryProcessor();
		retry.parseMethod(RetryTest.class);
	}
}

  • 总结
通过本文对Java反射和Annotation的浅谈介绍,相信读者能够掌握Java反射机制的使用方法。利用反射机制可以在程序运行时访问类的所有描述信息(构造方法、成员变量、方法),实现逆向控制控制程序的执行过程。从JDK1.5开始增加了Annotation功能,可以对类、构造方法、成员变量、方法、参数等进行注释,在程序运行时通过反射可以读取这些信息,根据读取的信息可以实现逆向控制程序的执行过程


上一篇: DOM事件-调用函数

下一篇: