有时候我们做项目的时候不免需要用到大量配置文件,就拿框架举例,通过这些外部文件配置,在不修改的源码的情况下,来控制文件,就要用到我们的反射来解决
假设有一个Cat对象
public class Cat { private String name = "招财猫"; public void hi(){ System.out.println("hi "+name); } }
传统调用方法
public class ReflectionQuestion { public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //传统的方式 new 对象 -》 调用方法 Cat cat = new Cat(); cat.hi(); } }
现在有一个配置文件
classfullpath=Reflection.com.hspedu.Cat method=hi
反射调用
/反射问题的引入 public class ReflectionQuestion { //1.使用Properties类,可以读写配置文件 Properties properties = new Properties(); properties.load(new FileInputStream("src\\Reflection\\re.properties")); String classfullpath = properties.get("classfullpath").toString(); String method = properties.get("method").toString(); //使用反射机制来解决 //(1)加载类,返回Class类型的对象 Class cls = Class.forName(classfullpath); //(2)通过 cls 得到你加载的类 com.hspedu.Cat Object o = cls.newInstance(); System.out.println("o的运行类型="+o.getClass()); //(3)通过 cls 得到你加载的类 Reflection.com.hspedu.Cat 的 methodName 的方法对象 //即: 在反射中,可以把方法视为对象(万物皆对象) Method method1 = cls.getMethod(method); //(4)通过method1 调用方法:即通过方法对象实现调用方法 System.out.println("========================="); method1.invoke(o); } }
运行结果:
反射的强大之处就是可以在外部文件上不修改源码的情况下来控制程序
反射机制
反射机制允许程序在执行的时候借助我们Reflection API取得任何类的内部信息,并且能操作对象的属性及方法。反射在设计模式和框架底层都会用到
(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,形象的称之为:反射
解释
//反射问题的引入 public class ReflectionQuestion { public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { //1.使用Properties类,可以读写配置文件 Properties properties = new Properties(); properties.load(new FileInputStream("src\\Reflection\\re.properties")); String classfullpath = properties.get("classfullpath").toString(); String method = properties.get("method").toString(); //使用反射机制来解决 //(1)加载类,返回Class类型的对象 Class cls = Class.forName(classfullpath); Class cls2 = Class.forName(classfullpath); System.out.println(cls.hashCode()); System.out.println(cls2.hashCode()); } }
运行结果:
可以看出来他们指向同一个对象
java反射机制可以完成
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时得到任意一个类所具有的成员变量和方法
4.在运行时调用任意一个对象的成员变量和方法
5.生成动态代理
反射调用优化
优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就会失去底层支持
缺点:使用反射基本是解释执行,对执行速度有影响
public class Reflection02 { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { m1(); m2(); } //传统方式来调用hi public static void m1(){ Cat cat = new Cat(); long start = System.currentTimeMillis(); for(int i=0;i<90000000;i++){ cat.hi(); } long end = System.currentTimeMillis(); System.out.println("传统方法来调用hi 耗时="+(end-start)); } //反射机制调用方法hi public static void m2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class cls = Class.forName("Reflection.com.hspedu.Cat"); Object o = cls.newInstance(); Method hi = cls.getMethod("hi"); long start = System.currentTimeMillis(); for(int i=0;i<90000000;i++){ hi.invoke(o); } long end = System.currentTimeMillis(); System.out.println("反射方法来调用hi 耗时="+(end-start)); } }
运行结果:
差距这么大有什么方法优化吗
//反射调用优化 + 关闭访问检查 public static void m3() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Class cls = Class.forName("Reflection.com.hspedu.Cat"); Object o = cls.newInstance(); Method hi = cls.getMethod("hi"); hi.setAccessible(true); long start = System.currentTimeMillis(); for(int i=0;i<90000000;i++){ hi.invoke(o); } long end = System.currentTimeMillis(); System.out.println("反射方法来调用hi 耗时="+(end-start)); }