反射机制
引出反射
我们的猫类
传统的方式
就是new 然后通过对象调用呗
用properties做的话,首先肯定是获取信息
读取配置文件的信息
然后我们需要创建对象是吧
但是这个时候
new classfullpath是不行的,因为我们实际上需要的是
类名
而不是字符串,不能用字符串来代替类名
所以你从配置文件读取的信息,不能用来创建类
那该怎么办呢?
这就该用到反射了
反射快速入门
这样的意义就是通过外部文件配置在不修改源码来控制程序
是我们学习后面Spring全家桶,Mybaits等框架的灵魂
比如你的猫类里面多一个cry方法
你想调用cry不想调用hi就只能修改源码,把cat.hi改为cat.cry
而反射的话
只需要把method=hi改为method=cry就可以了,修改的是配置文件不是源代码
反射原理图
就是本质是通过Class类对象来操作对象
而反射就是
不通过new什么的
直接通过Class类来操作
而且对应的Class类存储的都是对象
可以把方法当做对象,构造器也可以当做对象,变量也是对象
每个对象存储在对应的对象数组里
反射机制中主要类
演示的话
在Cat类多加一个public属性age=10
在加一个构造器
变量获取
获取无参构造
获取有参构造
可以通过对应的
成员变量对象.get(对象)来获取对应的值
这个对象是我们cat的实例对象
方法上面也有例子
方法对象.invoke(对象)
关于方法为什么也要区别化,因为每个对象的属性值可能不一样,方法可能调用属性值,所以对应的方法也可能不一样,具体表现就是每个对象的方法对象不同
还有那个构造器
构造器对应的方法之后讲
无参和有参构造器
有参构造的话,他的参数不是什么String而是String.class就是String类的Class对象
代码
package yuan.hsp.reflection;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
import org.junit.jupiter.api.MethodOrderer.MethodName;
@SuppressWarnings({"all"})
//反射机制的简单介绍
public class introduce {
public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException,
IllegalAccessException, NoSuchMethodException, SecurityException,
IllegalArgumentException, InvocationTargetException, NoSuchFieldException {//这异常有点多,你忍一下
// 1.正常想调用对应的方法
// Cat cat = new Cat();
// cat.hi();
// 2.使用properties类,通过配置文件来进行对应方法的调用,先读取配置文件
Properties properties = new Properties();
// properties.load(new FileInputStream("d:\\eclipseworkspace\\Learn\\src\\re.properties"));
properties.load(new FileInputStream("src\\re.properties"));
String classfullpath = properties.get("classfullpath").toString();
String Method = properties.get("method").toString();
System.out.println(classfullpath);
System.out.println(Method);
// 3.反射机制运用
//1.加载类,返回Class对象cls
Class cls = Class.forName(classfullpath);
//2.通过cls创建对象实例
Object newInstance = cls.newInstance();
System.out.println(newInstance.getClass());
//3.通过对cls来获取到我们对应的对象方法,在反射中万物皆是对象
Method method1 = cls.getMethod(Method);
//4.通过method1调用方法,调用格式:方法对象.invoke(实例对象)
System.out.println("==============================");
method1.invoke(newInstance);
//好处就是可以通过该配置文件来改变调用方法,不用修改源代码
// 一些常用类的方法
//java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量
//得到age字段吧,因为private的name是无法用getField获取
Field field = cls.getField("age");
System.out.println(field.get(newInstance));//成员变量对象.get(实例对象)
Constructor constructor = cls.getConstructor();
System.out.println(constructor);
Constructor constructor2 = cls.getConstructor(String.class);
System.out.println(constructor2);
}
}
反射优化
案列演示
package yuan.hsp.reflection;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@SuppressWarnings({"all"})
//演示类罢了
//还有一个时间对比来进行反射的优化
public class Cat {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException,
IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException,
InvocationTargetException {
Cat cat = new Cat();
cat.m1();
cat.m2();
cat.m3();
}
//这里为了方便我们观察,把hi()输出的内容注释
//m1是普通的对象调用方法
//m2就是用反射机制调用方法,取消访问调查
//m3没有调用setAccessible(true),没有取消访问调查
//可以发现效率差距很大,怎么进行优化呢?
public 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("m1耗时"+(end-start));
}
public void m2() throws ClassNotFoundException, InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
Class cls = Class.forName("yuan.hsp.reflection.Cat");
Object cat = cls.newInstance();
Method method = cls.getMethod("hi");
method.setAccessible(true);//取消访问检查,提高效率
long start = System.currentTimeMillis();
for(int i =0;i<900000000;i++) {
method.invoke(cat);
}
long end = System.currentTimeMillis();
System.out.println("m2=耗时"+(end-start));
}
public void m3() throws ClassNotFoundException, InstantiationException, IllegalAccessException,
NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {
Class cls = Class.forName("yuan.hsp.reflection.Cat");
Object cat = cls.newInstance();
Method method = cls.getMethod("hi");
long start = System.currentTimeMillis();
for(int i =0;i<900000000;i++) {
method.invoke(cat);
}
long end = System.currentTimeMillis();
System.out.println("m3=耗时"+(end-start));
}
private String name="招财猫";
public int age =10;
public Cat() {
super();
}
public Cat(String name) {
super();
this.name = name;
}
public void hi() {
// System.out.println("hi"+name);
}
public void cry() {
System.out.println(name+"喵喵叫...");
}
}
优化方法
可以通过设置为true来跳过访问调查这个步骤提高效率
就是我们之前代码的m2()和m3()对比
多出来那一行代码
method.setAccessible(true);//取消访问检查,提高效率
可以一定程度上提高效率,但是肯定不如传统方式来的快