一、概念说明
java的反射机制,是在运行状态下,可以动态获取任意一个类的属性和方法;可以动态调用一个对象任意方法;
二、反射相关类
java.lang.Class; //类
java.lang.reflect.Constructor;//构造方法
java.lang.reflect.Field; //类的成员变量
java.lang.reflect.Method;//类的方法
java.lang.reflect.Modifier;//访问权限
三、应用场景
1.获取对象及成员变量
package com.reflect.dto
public class RequestDTO{
private String userId;
private String userName;
}
调用:
Class classz=Class.forName("com.reflect.dto.RequestDTO");
Object obj=classz.newInstance();
if(classz instance of RequestDTO){
RequestDTO requestDTO=(RequestDTO )obj;
}
Field field=classz.getField("userName");
field.set(requestDTO,"ZHANGSAN");
2.通过反射运行配置文件内容
(1)resource.properties
className=com.reflect.dto.RequestDTO
methodName=getUserId
(2)解析配置文件
public static String getValue(String key){
Properties pro=new Properties();
FileReader in=new FileReader("resource.properties");
pro.load(in);
in.close();
return pro.getProperty(key);
}
(3)调用
Class classz =Class.forName(getValue("className"));//获取类
Object obj=classz.getConstructor().newInstance();//实例化对象
Method method=classz.getMethod(getValue("methodName"));//获取方法
method.invoke(obj);//调用方法
3.通过反射跳过泛型检查(在一个String的ArrayList中存储一个Integer的值方法)
ArrayList arrayList=new ArrayList<>();
arrayList.add("张三");
Class classz=arrayList.getClass();
Method m=classz.getMethod("add",Object.class);
m.invoke(arrayList,100);
遍历打印出来,后就是:
张三
100
4.通过反射获取对象中注解
package com.annotation
@MyClassAnnotation(desc = "The class", uri = "com.test.annotation.Test")
public class TestAnnotation{
@MyMethodAnnotation(desc = "The class method", uri = "com.test.annotation.Test#setId")
public void setId(String id) {
System.out.println(" method info: "+id);
this.id = id;
}
}
Class classz =Class.forName("com.annotation.TestAnnotation");
MyClassAnnotation myClassAnnotation=classz.getAnnotation(MyClassAnnotation.class);
myClassAnnotation.desc();
Method m=classz.getMethod("setId",new Class[]{int.class});
MyMethodAnnotation myMethodAnnotation=m..getAnnotation(MyMethodAnnotation .class);
myMethodAnnotation.desc();
5.spring ioc反射机制原理
下面是Spring通过配置进行实例化对象,并放到容器中的伪代码:
//解析元素的id属性得到该字符串值为“courseDao”
String idStr = "courseDao";
//解析元素的class属性得到该字符串值为“com.qcjy.learning.Dao.impl.CourseDaoImpl”
String classStr = "com.qcjy.learning.Dao.impl.CourseDaoImpl";
//利用反射知识,通过classStr获取Class类对象
Class> cls = Class.forName(classStr);
//实例化对象
Object obj = cls.newInstance();
//container表示Spring容器
container.put(idStr, obj);
四、缺点
性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。