简介
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;简单说就是,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息。
原理
Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象(Class反射对象),通过该元信息对象可以获知Class的结构信息。
Class反射对象:描述类语义结构,可以从Class对象中获取构造函数、成员变量、方法类等类元素的反射对象,并以编程的方式通过这些反射对象对目标类对象进行操作。
demo
一个简单的例子
public class Car {
private String brand;
private String color;
private int maxSpeed;
private String owner;//私有成员,没有对应的get和set方法;
//①默认构造函数
public Car(){}
//②带参构造函数
public Car(String brand,String color,int maxSpeed){
this.brand = brand;
this.color = color;
this.maxSpeed = maxSpeed;
}
//③未带参的方法
public void introduce() {
System.out.println("brand:"+brand+"; color:"+color+"; maxSpeed:" +maxSpeed);
}
//私有方法
private void whoHasIt(){
System.out.println("The owner of this car is:" + this.owner );
}
//参数的getter/Setter方法
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(int maxSpeed) {
this.maxSpeed = maxSpeed;
}
}
public class ReflectCall {
public static Car initByDefaultConst() throws Throwable {
/**
* ①通过类装载器获取Car类对象
* 1.获取当前线程的ClassLoader
* 2.通过指定的全限定类“reflect.Car”装载Car类对应的反射实例
*/
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class class_car = loader.loadClass("reflect.Car");
/**
* ②获取类的默认构造器对象并通过它实例化Car
* 1.通过Car的反射类对象获取Car的构造函数对象cons
* 2.通过构造函数对象的newInstrance()方法实例化Car对象,其效果等同于new Car()
*/
Constructor cons = class_car.getDeclaredConstructor((Class[])null);
Car car = (Car)cons.newInstance();
/**
* ③获取类的成员变量(包含私有成员),并对成员变量赋值
*/
Field ownerFld = class_car.getDeclaredField("owner");
//取消Java语言访问检查以访问private变量
ownerFld.setAccessible(true);
ownerFld.set(car,"小明");
/**
* ④通过反射方法设置属性
* 通过Car的反射类对象的getMethod(String methodName,Class paramClass)获取属性的Setter方法对象,
* 第一个参数是目标Class的方法名;第二个参数是方法入参的对象类型。
*/
Method setBrand = class_car.getMethod("setBrand",String.class);
/**
* 通过invoke(Object obj,Object param)方法调用目标类的方法,
* 该方法的第一个参数是操作的目标类对象实例;第二个参数是目标方法的入参。
*/
setBrand.invoke(car,"红旗CA72");
Method setColor = class_car.getMethod("setColor", String.class);
setColor.invoke(car, "黑色");
Method setMaxSpeed = class_car.getMethod("setMaxSpeed",int.class);
setMaxSpeed.invoke(car, 200);
/**
* ⑤获取类的私有方法,并调用它
*/
Method whoHasItMtd = class_car.getDeclaredMethod("whoHasIt",(Class[])null);
//取消Java语言访问检查以访问private方法
whoHasItMtd.setAccessible(true);
whoHasItMtd.invoke(car,(Object[])null);
return car;
}
public static void main(String[] args) throws Throwable {
Car car = initByDefaultConst();
car.introduce();
}
}
获取Class类的方法
Class<?> cl1 = ReflectMethod.class;
Class<?> cl2 = new ReflectMethod().getClass();
Class<?> cl3 = Class.forName("test.ReflectMethod");
Class<?> cl4 = cl2.getSuperclass();
Class<?> cl5 = Double.TYPE;
获取所有信息
package testReflect;
import java.lang.reflect.*;
public class PrintClassInfo {
private PrintClassInfo(){}
public static void printClassInfo(String name){
try{
Class cl = Class.forName(name);
String pack = cl.getPackage().getName();
System.out.println("package " + pack);
Class supercl = cl.getSuperclass();
String modifiers = Modifier.toString(cl.getModifiers());
if (modifiers.length() > 0) {
System.out.print(modifiers+" ");
}
System.out.print("class "+name);
if (supercl != null && supercl != Object.class) {
System.out.print(" extends " + supercl.getName());
}
Class []inters = cl.getInterfaces();
if (inters != null && inters.length > 0) {
System.out.print(" implements ");
for (int i=0; i<inters.length; ++i) {
if (i!=0) {
System.out.print(", ");
}
System.out.print(inters[i].getName());
}
}
System.out.print("\n{\nConstructors:\n");
printConstructors(cl);
System.out.println("Methods:");
printMethods(cl);
System.out.println("Fields:");
printFields(cl);
System.out.println("}");
} catch (ClassNotFoundException e){
e.printStackTrace();
}
System.exit(0);
}
public static void printConstructors(Class cl){
Constructor[] cons = cl.getConstructors();
for(Constructor c:cons){
String name = c.getName();
System.out.print(" ");
String modifiers = Modifier.toString(c.getModifiers());
if(modifiers.length() > 0) {
System.out.print(modifiers+" ");
}
System.out.print(name+"(");
Class[] paramTypes = c.getParameterTypes();
for(int i=0; i<paramTypes.length; i++) {
if(i>0)System.out.print(", ");
System.out.print(paramTypes[i].getName());
}
System.out.println(");");
}
}
public static void printMethods(Class cl){
Method[] methods = cl.getDeclaredMethods();
for(Method m:methods){
Class retType = m.getReturnType();
String name = m.getName();
System.out.print(" ");
String modifiers = Modifier.toString(m.getModifiers());
if(modifiers.length() > 0) {
System.out.print(modifiers + " ");
}
System.out.print(retType.getName() + " " + name + "(");
Class[] paramTypes = m.getParameterTypes();
for(int i=0; i<paramTypes.length; i++){
if(i>0) {
System.out.print(", ");
}
System.out.print(paramTypes[i].getName());
}
System.out.println(");");
}
}
public static void printFields(Class cl){
Field[] fields = cl.getDeclaredFields();
for(Field f:fields){
Class type = f.getType();
String name = f.getName();
System.out.print(" ");
String modifiers = Modifier.toString(f.getModifiers());
if(modifiers.length()>0) {
System.out.print(modifiers + " ");
}
System.out.println(type.getName() + " " + name + ";");
}
}
}
常见应用
- Spring IOC机制
- 动态代理
注意性能问题,请勿滥用反射