先容
每个类都有一个 Class 对象,包含了与类有关的信息。当编译一个新类时,会产生一个同名的 .class 文件,该文件内容保存着 Class 对象。
类加载相当于 Class 对象的加载。类在第一次使用时才动态加载到 JVM 中,可以使用 Class.forName("com.mysql.jdbc.Driver") 这种方式来控制类的加载,该方法会返回一个 Class 对象。
反射可以提供运行时的类信息,并且这个类可以在运行时才加载进来,甚至在编译时期该类的 .class 不存在也可以加载进来。
Class 和 java.lang.reflect 一起对反射提供了支持,java.lang.reflect 类库紧张包含了以下三个类:
Java反射机制是指在运行时动态地获取一个类的信息并能够操纵该类的属性和方法的能力。Java反射机制使得程序能够在运行时借助Class类的API来操纵自身的属性和方法,从而大大增强了Java的灵活性和可扩展性。
优缺点
优点:
- 提高了程序的灵活性:可以在运行时获取和操纵类的信息,使程序具有更好的灵活性和扩展性。
- 减少了代码的重复性:可以动态地获取和操纵类的信息,减少了代码的重复性。
- 提高了程序的可维护性:可以使程序的结构更加清晰明白,提高了程序的可维护性。
缺点:
- 性能较低:Java反射机制是通过运行时动态获取和操纵类的信息,性能较低。
- 安全性题目:Java反射机制可以访问和操纵类的所有信息,存在安全性题目。
- public void test2() {
- long start = System.currentTimeMillis();
- for (int i = 0; i < 10000000; i++) {
- getAuthor(); //运行时间15
- // getAuthorByReflect();//运行时间4378
- }
- long end = System.currentTimeMillis();
- System.out.println("运行时间:" + (end - start));
- }
复制代码 如何获取
- //1. 通过类名.class获取
- class s = SubjectService.class;
-
- //2.通过Class.forName名获取
- class s = Class.forName(SubjectService);
-
- //3.通过对象.getclass获取
- class s = data.getClass();
-
- //4.通过类加载器获取
- ClassLoader classLoader = Practice0.class.getClassLoader();
- Class s = classLoader.loadClass("全类名");
复制代码 比较四种获取方式的区别?通过类加载器获取的方式不常用,在此不做比较。
- 类名.class:JVM将使用类装载器,将类装入内存(前提是:类还没有装入内存),不做类的初始化工作,返回Class的对象。
- Class.forName(“类名字符串”):装入类,并做类的静态初始化,返回Class的对象。
- 实例对象.getClass():对类进行静态初始化、非静态初始化;返回引用运行时真正所指的对象(子对象的引用会赋给父对象的引用变量中)所属的类的Class的对象。
应用场景
- 框架设计:在框架设计中,通常必要使用反射技术来解耦,使框架可扩展和灵活。
- 单位测试:在单位测试中,我们可以使用反射技术来访问私有或受保护的类成员,使测试更加全面。
- 动态代理:使用反射技术可以创建动态代理对象,从而可以在运行时期代理任意一个实现了接口的对象,实现AOP等功能。
- 序列化和反序列化:许多Java序列化和反序列化工具都是基于Java反射机制实现的,例如Java的ObjectInputStream和ObjectOutputStream。
Java反射技术可以在很多场景中应用,尤其是在框架设计和组件化开发中,反射技术可以提高代码的灵活性和可扩展性,减少代码耦合性,简化代码的编写。但是,反射机制也增加了程序的复杂度,因此必须审慎使用。
执行流程
- public class HelloReflect {
- public static void main(String[] args) {
- try {
- // 1. 使用外部配置的实现,进行动态加载类
- TempFunctionTest test = (TempFunctionTest)Class.forName("com.tester.HelloReflect").newInstance();
- test.sayHello("call directly");
- // 2. 根据配置的函数名,进行方法调用(不需要通用的接口抽象)
- Object t2 = new TempFunctionTest();
- Method method = t2.getClass().getDeclaredMethod("sayHello", String.class);
- method.invoke(test, "method invoke");
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e ) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
-
- public void sayHello(String word) {
- System.out.println("hello," + word);
- }
- }
复制代码
反射获取类实例
获取类信息
首先调用了 java.lang.Class 的静态方法,获取类信息。
[code]@CallerSensitivepublic static Class |