(来自于B站韩老师Java反射专题整理相关笔记,链接:https://www.bilibili.com/video/BV1g84y1F7df)
ps:好像从博客园不能直接跳转,可以复制到浏览器打开
需求:根据配置文件(xx.properties)创建对象并调用方法
这种需求通过外部文件配置,在不修改源码的情况下,控制程序,符合设计模式的opc原则(开闭原则:不修改源码的情况下,扩展功能)
传统方法难以解决,引出反射机制
// 1.加载类,返回Class类型的对象 Class clazz = Class.forName("全类名"); // 2.通过class获得加载类的对象实例 Object o = clazz.newInstance(); // 3.通过class获得加载类的方法对象 // 在反射中,可以将方法视为对象 Method method = clazz.getMethod("方法名"); // 4.通过方法对象来实现方法调用 方法.invoke(对象) method.invoke(o);
反射机制就是程序在运行期间借助Reflection API取得任何类的内部信息(成员变量,构造器,成员方法等),并且能够操作对象的属性和方法
类加载完以后,在堆中产生了一个Class类型的对象(一个类只有一个Class对象),该对象包含类的完整结构信息,通过这个对象得到类的结构,这个对象就像一面镜子,透过镜子可以看到类的结构,所以形象的称之为反射
Java程序执行有三个阶段:
优点:动态创建和使用对象,使用灵活
缺点:解释执行,对执行速度有影响
通过Class.forName()获取:已知类的全类名,且该类在类路径下,多用于配置文件,编译阶段
类名.class:多用于参数传递 String.class,加载阶段
对象.getClass():有对象实例,运行阶段
通过类加载器获取:
ClassLoader classloader = 对象.getClass().getClassLoader(); Class cls = classloader.loadClass("全类名");
基本数据类型.class:输出基本类型 int
包装类.TYPE:输出基本类型
java.lang.Class:代表一个类 java.lang.reflect.Method:代表类的方法 java.lang.reflect.Field:代表类的成员变量 java.lang.reflect.Constructor:代表类的构造方法
clazz.getField("")方法不能得到私有属性
Class.getConstructor(形参类的class对象)
测试反射调用性能和优化方案:
对同样的类调用90000000次,采用传统方法和反射调用相差数百倍
优化:关闭访问检查
Method、Field、Constructor对象都有setAccessible()方法,可以开启关闭访问安全检查,参数值为true表示反射的对象在使用时取消访问检查,提高性能(优化一点点)
Class cls = Class.forName("") System.out.println(cls);//com.xxx.xx 显示cls对象 System.out.println(cls.getClass());//java.lang.Class 运行类型 System.out.println(cls.getPackage().getName());//获取包名 cls.getName();//获取全类名 cls.newInstance();//创建对象实例 Field field = cls.getField("");//获取属性 field.set();//给属性赋值 Field[] fields = cls.getFields();//获取所有属性