在前面我们已经谈了一些关于Java反射的一些概念,下面我们就写一个小程序来说明一下Java反射的应用。

以下的程序,使用了Java的反射获取类的属性,调用类的方法(包括构造方法),这里要说明的是,在这个例子中也使用到了Java反射中的所谓“暴力反射”的特性,即使用反射调用类的私有方法或属性,不过需要注意的是在使用这一特性时,要先调用setAccessible方法将其设为true,还有一点就是不管是类的Constructor,Method,Field都有两类方法,分别是getXXX,getDeclaredXXX的两类,简单的区别就是私有的(private)和受保护(protected)类型的方法或是属性需要使用getDeclaredXXX方法来获取,而公有的用getXXX即可,特别详细的区别看下图,这个是oracle官网Java教程中给出的:

Java 反射调用 method java 反射调用 protected 方法_Java

这里为了能够相对全面的说明Java的反射特性所以在类的方法或属性上的定义比较多样。

首先我们建立一个普通的Person类:

public class Person {
	
	private String name = "aaaaaaaaaaa";
	public int age = 20;
	protected String addr = "china";
	
	public Person(){}
	
	public Person(String name){
		this.name = name;
	}
	
	private Person(String name, int age){
		this.name = name;
		this.age = age;
	}
	
	public void print(){
		System.out.println("Person's name: "+this.name+",age: "+age);
	}
	
	private void display(String str){
		System.out.println(str);
	}
	
	private static void show(String str){
		System.out.println("调用静态方法测试"+str);
	}
	
}



反射的测试类:ReflectTest

public class ReflectTest {

	public static void main(String[] args) throws Exception {
		
		Class<Person> clazz = Person.class;
		// 通过反射获取Person类的默认的构造方法(无参的构造方法)
		Constructor<Person> constructor1 = clazz.getConstructor();
		// 利用反射调用Person的无参的构造方法,构造Person对象
		Person person1 = constructor1.newInstance();
		person1.print();
		
		// 利用反射调用Person的有参的构造方法
		Constructor<Person> constructor2 = clazz.getConstructor(String.class);
		Person person2 = constructor2.newInstance("constructor2");
		person2.print();
		
		// 利用反射调用Person的私有构造方法(这里就是常说的暴力反射),注意getConstructor,getDeclaredConstructor方法的区别
		Constructor<Person> constructor3 = clazz.getDeclaredConstructor(String.class);
		// 在调用私有方法或属性之前必须要设置此属性为true
		constructor3.setAccessible(true);
		Person person3 = constructor3.newInstance("constructor3");
		person3.print();
		
		// 利用反射获取Person类的属性,注意:getDeclaredField,getField方法的区别
		Field name = clazz.getDeclaredField("name");//获取name属性,私有属性
		Field age = clazz.getField("age");// 获取age属性
		Field addr = clazz.getDeclaredField("addr");// 获取addr属性,受保护类型
		name.setAccessible(true);
		System.out.println("name: "+name.get(person1)+" age: "+age.get(person1)+" addr: "+addr.get(person1));
		
		// 对属性值进行修改
		name.set(person1, "testperson");
		age.setInt(person1, 23);
		addr.set(person1, "Beijing");
		System.out.println("name: "+name.get(person1)+" age: "+age.get(person1)+" addr: "+addr.get(person1));
		
		// 利用反射获取Person类的方法
		Method m1 = clazz.getMethod("print");// 获取print方法
		m1.invoke(person1);
		Method m2 = clazz.getDeclaredMethod("display", String.class);// 获取display方法,私有方法
		m2.setAccessible(true);
		m2.invoke(person1, "display");
		
		Method m3 = clazz.getDeclaredMethod("show", String.class);// 获取show方法,静态私有方法
		m3.setAccessible(true);
		m3.invoke(null, "static show");// 在调用静态方法时,不需要指定对象是谁,直接传null就可
	}
	
}



这里只是就反射的一些常用的方法进行了实践,其实反射的使用是非常的灵活和强大,在Java的很多框架包括大家熟知的Hibernate,Spring等以及一些基础类库都用到了Java的反射特性