你还在写 10 行反射代码只为调一个方法吗?该换个姿势了。
痛点:Java 反射的"丑陋真相"
每个 Java 开发者都经历过这种痛苦------当你需要用反射调用一个方法时,画风是这样的:
ini
Class<?> clazz = Person.class;
Constructor<?> ctor = clazz.getConstructor(String.class, int.class);
Object person = ctor.newInstance("Tom", 25);
Method method = clazz.getMethod("hello");
method.setAccessible(true);
String result = (String) method.invoke(person);
6 行代码,只为创建一个对象并调用一个方法。
这还没完。你还得处理一堆受检异常(NoSuchMethodException、IllegalAccessException、InvocationTargetException......),精确匹配参数类型(传个 Integer 居然匹配不到 int),手动处理基本类型和包装类型的鸿沟...... 写完之后回头看,满屏的 getDeclaredMethod、setAccessible、强转和 try-catch,代码可读性直接归零。
这就是 Java 反射几十年来一直被诟病的原因:强大,但丑陋。
EggG:让反射变成一首诗
EggG(org.noear:eggg)是 Java 类型元数据分析与构建工具,用一个优雅的链式 API 将反射的复杂度彻底隐藏。
上面那段 6 行的代码,用 EggG 只需 1 行:
sql
String result = new Eggg().reflect(Person.class)
.create("Tom", 25)
.call("hello")
.get();
就这么简单。没有 getDeclaredMethod,没有 setAccessible,没有强转,没有受检异常。
四大核心能力,重塑反射体验
1. 链式调用------代码像说话一样流畅
EggG 采用 Builder 模式设计,create()、call()、field()、property() 无缝衔接,一行代码完成从创建到调用到取值的完整操作:
scss
Person person = new Eggg().reflect(Person.class)
.create()
.setField("name", "Tom")
.setField("age", 25)
.call("hello") // 调用方法,返回值自动包装
.get();
void 方法也不怕 ------调用 void 方法后自动返回原对象包装,链式调用永不中断:
scss
eggg.reflect(service)
.call("increment") // void 方法
.call("increment") // 继续链式
.call("increment");
2. 智能匹配------告别类型精确匹配的噩梦
传统反射的 getMethod(name, Class...) 要求参数类型精确匹配 ,传 Integer 不认 int,传 List 不认 Collection。
EggG 内置两级匹配策略:精确匹配 → 模糊匹配自动降级,基本类型与包装类型自动互通:
vbnet
// Integer.valueOf(30) 自动匹配 Person(String, int) 的 int 参数
Person person = eggg.reflect(Person.class)
.create("Bob", Integer.valueOf(30))
.get();
方法重载也不再头疼------同名方法按参数自动选择:
sql
eggg.reflect(dog).call("bark").get(); // "woof"
eggg.reflect(dog).call("bark", 3).get(); // "woof x3"
eggg.reflect(dog).call("bark", "hey").get(); // "hey woof"
3. 透明访问------私有成员无需额外处理
传统反射访问私有成员需要手动 setAccessible(true),而 EggG 做到了完全透明------私有方法、私有字段、私有构造器,统统直接用,框架内部自动处理可见性:
scss
// 私有方法?直接调用
String secret = eggg.reflect(obj).call("getSecret").get();
// 私有字段?直接读写
eggg.reflect(obj).setField("hidden", "revealed");
4. 属性语义------getter/setter 与字段统一抽象
EggG 提供 property() / setProperty() 语义,优先走 getter/setter,找不到时自动降级为字段访问,一个 API 搞定两种场景:
scss
// 优先走 setName(),没有则直接设字段
eggg.reflect(person).setProperty("name", "Alice");
// 优先走 getName(),没有则直接读字段
String name = eggg.reflect(person).property("name").get();
不止优雅,还有性能
流式 API 不等于牺牲性能。EggG 在底层做了多重性能优化:
| 优化点 | 说明 |
|---|---|
| MethodHandle 加速 | 公有方法自动创建 MethodHandle,调用时优先走 MethodHandle 快速路径,避免反射开销 |
| 元数据软缓存 | SoftReference + ConcurrentHashMap 双层缓存,同类只解析一次,内存压力时自动释放 |
| 方法名索引 | ClassEggg 内部预建方法名 HashMap 索引,call() 时 O(1) 定位候选方法 |
| 构造器参数快照 | ConstrEggg 预存参数别名数组,create() 时高性能匹配 |
零依赖,全版本兼容
- 零依赖:不依赖任何第三方库,加一个 Maven 坐标即可使用
- 全 JDK 兼容:基于 Java 8 编译,兼容 JDK 8 ~ JDK 25
- 轻量级:核心代码精简,无侵入性设计
xml
<dependency>
<groupId>org.noear</groupId>
<artifactId>eggg</artifactId>
<version>1.1.0</version>
</dependency>
对比一览:传统反射 vs EggG
| 维度 | 传统反射 | EggG 流式反射 |
|---|---|---|
| 代码量 | 5-10 行/操作 | 1 行链式调用 |
| 类型转换 | 手动强转 | get() 泛型自动转型 |
| 方法匹配 | 精确类型参数 | 按名称 + 参数自动匹配 |
| 基本类型/包装类型 | 不互通 | 自动互通 |
| 私有成员 | 手动 setAccessible |
透明访问 |
| void 方法链式 | 不支持 | 返回 this,持续链式 |
| 异常处理 | 多种受检异常 | 统一 EgggReflectException |
| 性能加速 | 无 | MethodHandle + 缓存 |
快速上手,5 秒入门
dart
// 1. 创建 Eggg 实例
Eggg eggg = new Eggg();
// 2. 从类创建实例 + 调方法
String result = eggg.reflect(String.class)
.create("Hello World")
.call("substring", 6)
.get();
// → "World"
// 3. 从已有实例直接调用
String upper = eggg.reflect("hello")
.call("toUpperCase")
.get();
// → "HELLO"
// 4. 读写字段
Person p = eggg.reflect(Person.class)
.create()
.setField("name", "Tom")
.get();
// 5. 读写属性(走 getter/setter)
eggg.reflect(p).setProperty("age", 30);
int age = eggg.reflect(p).property("age").get();
写在最后
Java 反射是语言层面赋予开发者的强大能力,但其 API 设计几十年来几乎没有进化。EggG 不是要替代反射,而是要在反射之上,提供一层现代化的流式封装------让反射代码从"必须写"变成"愿意写"。
如果你正在开发框架、构建插件系统,或者只是厌倦了冗长的反射样板代码,不妨试试 EggG。
一行链式,胜过十行反射。