------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。我在前面的博客中已经总结了通过类名和对象获取类中所有属性和方法的方式。所以在此处,主要介绍反射的一些应用场景。
读取配置文件获取类名,并调用其方法
在实际开发中,经常会因为业务拓展或变更需求,需要对类进行增加或修改,直接修改源码显然是不现实的。所以,通常会将一些信息写入配置文件中,有需要的时候,只需要修改配置文件就可以完成需求。例如下面这个类:
class DemoClass{
public void run(){
System.out.println("run方法");
}
}
我们可以将DemoClass的类名存入配置文件run.properties中,在另一个地方,通过读取配置文件中的信息来调用run方法。
class DemoClass1{
public static void main(String[] args)throws Exception{
BufferedReader br = new BufferedReader(new FileReader("run.properties"));//创建输入流,读取文件
Class clazz = Class.forName(br.readLine()); //获取类名,并生成字节码对象
DemoClass d = (DemoClass)clazz.newInstance(); //创建该类对象
Method m = clazz.getMethod("run"); //调用run方法
m.invoke(d);
}
}
通过反射越过泛型检查
import java.lang.reflect.Method;
import java.util.ArrayList;
public class Test1 {
/**
* ArrayList<Integer>的一个对象,在这个集合中添加一个字符串数据,如何实现呢?
*/
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<>();
list.add(111);
list.add(222);
Class clazz = Class.forName("java.util.ArrayList"); //获取字节码对象
Method m = clazz.getMethod("add", Object.class); //获取add方法
m.invoke(list, "abc"); //向集合中添加字符串“abc”
System.out.println(list);
}
}
因为泛型是在编译时期进行检查,而反射是在运行时对对象的方法进行调用,所以,通过反射可以越过泛型的检查,向容器中添加需要的元素。
通过反射修改某个对象中的属性值
//此方法可将obj对象中名为propertyName的属性的值设置为value。
public void setProperty(Object obj, String propertyName, Object value) throws Exception {
Class clazz = obj.getClass(); //获取字节码对象
Field f = clazz.getDeclaredField(propertyName); //暴力反射获取字段
f.setAccessible(true); //去除权限
f.set(obj, value);
}
判断对象是否属于反射得到的类
import java.lang.reflect.*;
class Test1{
}
//利用Class类中的isInstance()方法判断对象是否为此类的实例
public class Test {
public static void main(String args[]) {
try {
Class cls = Class.forName("Test1"); //获取Test1类的字节码对象
boolean b1 = cls.isInstance(new Integer(37)); // 传入一个整型对象
System.out.println(b1); //false
boolean b2 = cls.isInstance(new Test1()); //传入一个Test1对象
System.out.println(b2); //true
}
catch (Throwable e) {
System.err.println(e);
}
}
}