【Java 入门 Day29】 反射 + 设计模式(上篇):反射框架底层核心,打破封装的 “代码透视挂”

家人们谁懂啊!平时写new 类名()是明着造对象,反射相当于开了透视外挂,不用提前硬编码,运行时扒出类所有隐藏信息、偷偷创建对象、调用私有方法,Spring、Mybatis 所有底层框架全靠它撑起来!今天用大白话拆解反射全套知识点,告别晦涩课本!

一、先分清两个极易混淆概念

1. 类的对象(普通实例)

咱们平时Student s = new Student()造出来的s,就是类的对象,存着成员变量真实数据,一个类能 new 出成千上万个。

2. 类对象(Class 模板对象)

类第一次被加载进 JVM 时,会自动生成唯一一份Class对象,像这个类的身份证档案,里面封装完整信息:包名、类名、父类、接口、所有属性、构造、全部方法。 一个类全程只会生成 1 个 Class 对象,无论 new 多少实例,共用同一份档案。

3. 反射到底是什么?

反射就是拿到这个 Class 档案对象,不依赖编译期硬编码,在运行时动态解析类、创建对象、读写私有属性、调用私有方法。 框架万能的根源:配置文件写类全限定名,运行时靠反射自动创建对象,不用改代码重新编译。

二、三种获取 Class 类对象的方式(面试必背)

方式 1:通过普通实例调用 getClass ()

java运行

复制代码
Student s = new Student();
Class c1 = s.getClass();

适用场景:手里已经有实例对象,临时拿类档案。

方式 2:类名.class 静态字面量

java运行

复制代码
Class c2 = Student.class;

优势:代码编译阶段就能拿到 Class,不会触发类加载,性能最好,适合静态工具类。

方式 3:Class.forName ("包名。类名") (框架核心用法)

java运行

复制代码
Class c3 = Class.forName("test_reflect.Student");

重点踩坑:必须传完整权限名(包 + 类名) ,只写类名直接抛ClassNotFoundException类找不到异常。 框架标配:配置文件写字符串全类名,运行时通过这条语句加载类,Spring 容器实例化 Bean 底层全是它。

补充:四类会触发类加载、生成 Class 对象的时机

  1. 第一次 new 这个类的实例;
  2. 第一次调用类静态变量 / 静态方法;
  3. 子类加载时,会优先加载父类;
  4. 使用Class.forName()反射获取类对象。

三、Class 类高频实用 API

  1. getName():获取完整带包类名;
  2. getMethods():拿本类 + 父类所有 public 公开方法,私有方法看不见;
  3. getDeclaredMethods():只拿当前类自己的全部方法,包含 private 私有方法,父类方法不获取;

四、反射全套实操:造对象、调用构造、执行方法

1. 无参构造创建对象 newInstance ()

java运行

复制代码
Class c = Class.forName("test_reflect.Student");
Object obj = c.newInstance();

硬性规则:默认调用无参构造 ,实体类没写无参构造直接抛InstantiationException实例化异常,开发实体规范必须预留无参构造。

2. 有参构造创建对象

先根据参数类型拿到指定构造器,再传参实例化:

java运行

复制代码
Class c = Class.forName("test_reflect.Student");
// 获取 String+Integer 参数的构造方法
Constructor con = c.getConstructor(String.class, Integer.class);
// 传入实参创建对象
Object stu = con.newInstance("万青", 48);

3. 反射调用私有方法(暴力破封装)

setAccessible(true)相当于关闭 Java 权限校验,无视 private 私有限制:

java运行

复制代码
// 获取本类私有test方法
Method m = c.getDeclaredMethod("test");
// 暴力开启访问权限
m.setAccessible(true);
// 执行方法,obj为类实例
m.invoke(obj);

五、反射优缺点客观总结

✅ 优点

代码极度通用灵活,底层框架、中间件核心基石。框架读配置动态创建对象,不用硬编码耦合业务类。

❌ 缺点

  1. 可读性极差,代码繁琐冗长,普通业务代码尽量少用;
  2. 破坏面向对象封装,能强行操作私有属性、私有方法,违背封装设计思想;
  3. 运行性能偏低,绕开编译期校验,大量反射会拖慢程序速度。

本篇小结

上篇吃透反射底层逻辑、三种获取 Class 对象写法、反射实例化对象 + 调用方法完整代码。 下一篇讲解三大经典设计模式:单例(饿汉 / 懒汉 / 静态内部类完美版)、工厂模式,还有配套 Properties 配置文件读取实操,面试八股高频考点全覆盖!