首先要明白反射是用来干嘛的。“反射就是把JAVA类中的各种成分映射成相应的JAVA类”,照我的理解,正常来说是先有类才能有对象,反射就是先有对象,然后再找到对象对应的类的过程。那如何通过对象找到类呢?就要通过字节码了。Class代表所有JAVA类,而Class类不同的实例对象则对应这不同的JAVA类,这些类也会有不同的实例对象,但都是属于同一个类,而不同的类会有不同的标识特性,这个就是字节码了,只要知道了某个对象对应的类的字节码,也就能知道这个类是什么类了。得到类的字节码的方式一般有三种——1:类名.class;2:对象.getClass();3:Class.forName("类名")。然后通过反射API类可以得到对应类中的成员方法的实例对象,构造方法的实例对象,成员变量的实例对象。

Constructor类:

当得到某个类的字节码后,就能通过这个类的字节码得到此类的构造方法的实例对象,如下所示:

Class clazz = String.class;//得到String类的字节码
		Constructor cons = clazz.getConstructor(StringBuffer.class);//通过字节码得到String类的某个构造方法



因为类中的同名的构造方法可能不止一个,所以getConstructor()方法的参数就对应了不同的构造方法的参数,但必须得是Class类型,即某个类的字节码。

获得类的构造方法后,便能通过这个方法生成实例对象,如下所示:

Class clazz = String.class;//得到String类的字节码
		Constructor cons = clazz.getConstructor(StringBuffer.class);//通过字节码得到String类的某个构造方法



当得到了构造方法的实例cons后,就能通过.newInstance()方法生成类的实例对象,这里需要注意的是newInstance()方法的参数不再是字节码,而是实例变量,和getConstructor()方法中对应的实例变量。因为这样生成的类的对象是Object类型的,如果要将其赋值给某个对象必须进行强制转换

String string = (String)cons.newInstance(new StringBuffer("abc"));

还有一点者的注意的是,Class中也有一个newInstance()方法,能省略中间先获得构造方法的对象,再通过构造方法对象创建实例的过程,直接通过Class调用无参数的构造方法创建实例。如:

clazz.newInstance();



Field类:

除了能得到某个类的构造方法的实例变量外,还能获得获得类的成员变量的实例,如下所示:

public static void main(String[] args) throws Exception{
		
		
		Person2 person = new Person2();
		Field field = person.getClass().getField("age");
		System.out.println(field.get(person));
		field.set(person, 2);
		System.out.println(field.get(person));
	}

}

class Person2{
	public int age;
}



field为Person2这个类的age变量的实例,当获得这个实例后便能对person这个Person2实例中的age变量进行操作。

运行结果为:

0

2

因为field.set()方法对age变量进行了赋值,所以第二次输出的结果为2。

这里需要注意的是,如果类的成员变量为private或default,Field是看不见且不能操作这个变量的,需要进行如下操作:

Person2 person = new Person2();
		Field field = person.getClass().getDeclaredField("age");
		field.setAccessible(true);
		System.out.println(field.get(person));
		field.set(person, 2);
		System.out.println(field.get(person));



运行结果依旧为:

0

2


Method类:

通过geMethod()方法也能获得类的成员方法的对象,如下:

String string = "abc";
		Method method = string.getClass().getMethod("charAt", int.class);
		System.out.println(method.invoke(string, 2));



运行结果为:c

通过getMethod(arg0,arg1)方法获得成员方法的对象,arg0参数为成员方法的方法名,因为可能有许多重名的成员方法,所以arg1为方法的参数,同样也为类,而非类的实例,即应该为类.class。然后便可以通过invoke(arg0,arg1)调用此方法,arg0为调用此方法的对象,如果为null的话即为静态方法,arg1为调用方法时传入的参数,这里应该为类的实例而非类。