浅谈Java反射与Annotation

通过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功能,可以对类、构造方法、成员变量、方法、参数等进行注释,在程序运行时通过反射可以读取这些信息,根据读取的信息可以实现逆向控制程序的执行过程


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值