什么是反射?
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
Java语言能成为动态语言与反射的关系密不可分 。
*项目结构
properties文件中定义了类路径、方法名与变量名,方便后面获取。
Cat实体类 定义了相同的方法,方法名、无参构造和有参构造。
*实体类Cat
public class Cat {
public Cat() {}
public Cat(String name){
this.name = name;
}
public String name = "招财猫猫";
public void hi(){
//System.out.println("hi!" + name);
}
public void cry(){
System.out.println(name + "cry!");
}
}
一、读取配置信息
// 拿到配置文件中的信息 以字符串形式获取
Properties properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
String methodName = properties.get("methodName").toString();
String fieldName = properties.get("fieldName").toString();
二、使用反射机制获取方法、成员变量与构造方法
// 使用反射 得到配置信息中的类对象实例等
Class cls = Class.forName(classfullpath);
// o的含义 -> com.deng.Cat@4554617c
Object o = cls.newInstance();
// 通过cls得到类方法
Method method = cls.getMethod(methodName);
method.invoke(o); //招财猫猫cry!
// 通过cls得到成员变量
Field field = cls.getField(fieldName);
System.out.println(field.get(o)); //招财猫猫
// 通过cls得到构造方法
Constructor constructor1 = cls.getConstructor();
System.out.println(constructor1); //public com.deng.Cat()
Constructor constructor2 = cls.getConstructor(String.class);
System.out.println(constructor2); //public com.deng.Cat(java.lang.String)
三、反射的优化
可以通过反射与传统方式调用方法的时间对比,看看两者的用时。
/** 传统方法调用hi */
public static void m1(){
Cat cat = new Cat();
long start = System.currentTimeMillis();
for (int i = 0; i < 900000000; i++) {
cat.hi();
}
long end = System.currentTimeMillis();
System.out.println("传统方法调用hi用时 -> " + (end-start));
}
/** 反射调用方法hi */
public static void m2() throws Exception {
Class cls = Class.forName("com.deng.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
long start = System.currentTimeMillis();
for (int i = 0; i < 900000000; i++) {
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射机制调用hi用时 -> " + (end-start));
}
打印结果看看
可以看到反射方法比传统调用方法要慢很多,所以我们可以选择方法来对他进行优化
setAccessible(boolean)方法,当参数为true时,可以关闭访问检测。由于JDK的安全检查耗时较多,所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的 。
/** 反射调用方法hi -> 反射优化 -> 关闭访问检测 */
public static void m3() throws Exception {
Class cls = Class.forName("com.deng.Cat");
Object o = cls.newInstance();
Method hi = cls.getMethod("hi");
// 关闭hi的反射访问检测
hi.setAccessible(true);
long start = System.currentTimeMillis();
for (int i = 0; i < 900000000; i++) {
hi.invoke(o);
}
long end = System.currentTimeMillis();
System.out.println("反射机制调优后hi用时 -> " + (end-start));
}
优化后结果对比:
顺利成功