反射
-
- 1、概述
- [2、TypeToken\<T> 与 TypeParameter\<T>(泛型解析与动态替换)](#2、TypeToken<T> 与 TypeParameter<T>(泛型解析与动态替换))
- [3、Invokable<A, R> 与 Parameter(统一方法与构造器)](#3、Invokable<A, R> 与 Parameter(统一方法与构造器))
- [4、Reflection 与 AbstractInvocationHandler(代理与工具)](#4、Reflection 与 AbstractInvocationHandler(代理与工具))
- 5、ClassPath(类路径高效率扫描)
- 6、TypeResolver(底层类型解算器)
1、概述
com.google.common.reflect 包提供了增强版的 Java 反射工具,解决了原生反射 API 在泛型擦除、方法与构造器抽象不统一、动态代理模板代码冗余以及类路径扫描等方面的局限。
包核心类一览
| 类名 | 核心职责 | 解决的原生反射痛点 |
|---|---|---|
TypeToken<T> |
运行时捕获、解析与操作完整泛型类型 | 突破泛型擦除限制,准确判断带泛型的继承关系 |
TypeParameter<T> |
配合 TypeToken.where() 进行动态泛型变量替换 |
可以在运行时动态绑定未知的泛型参数类型 |
Invokable<A, R> |
统一抽象 Method 与 Constructor |
解决方法/构造器无法统一处理及泛型返回值正确解析的问题 |
Parameter |
封装 Invokable 的参数信息 |
提供优雅的参数类型、注解及修饰符访问 API |
Reflection |
反射工具方法(创建代理、强制类初始化) | 简化 Proxy.newProxyInstance 的繁琐调用 |
AbstractInvocationHandler |
动态代理处理器的抽象基类 | 自动处理 equals()、hashCode()、toString(),防止代理失效 |
ClassPath |
类路径资源与 Class 扫描 | 在无需提前加载 Class(不触发 static 块)的前提下扫描类 |
TypeResolver |
独立的类型映射与求解器 | 可以在任意 Type 对象树结构中替换与求解类型变量 |
2、TypeToken<T> 与 TypeParameter<T>(泛型解析与动态替换)
2.1、核心API
| 方法名 | 说明 |
|---|---|
TypeToken.of(Class<T>) / TypeToken.of(Type) |
工厂方法,创建 TypeToken 实例 |
getType() / getRawType() |
获取底层 java.lang.reflect.Type / 擦除后的 Class |
isSubtypeOf(...) / isSupertypeOf(...) |
准确判断当前包含泛型的类型是否是目标类型的子类/父类 |
resolveType(Type) |
解析指定类型(如方法返回值)在当前 context 下的具体泛型 |
where(TypeParameter<P>, TypeToken<P> / Class<P>) |
将泛型占位符替换为具体类型,构建新的 TypeToken |
getTypes() |
返回 TypeSet,可遍历当前类型的所有超类与实现的接口 |
2.2、使用示例
java
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;
import java.util.List;
import java.util.Map;
public class TypeTokenAdvancedExample {
// 辅助泛型类,用于泛型变量替换
abstract static class MapType<K, V> extends TypeToken<Map<K, List<V>>> {}
public static void main(String[] args) {
// 1. 动态构造 Map<String, List<Integer>> 的 TypeToken
TypeToken<Map<String, List<Integer>>> dynamicToken = new MapType<String, Integer>() {}
.where(new TypeParameter<K>() {}, TypeToken.of(String.class))
.where(new TypeParameter<V>() {}, TypeToken.of(Integer.class));
System.out.println("动态生成的泛型类型: " + dynamicToken.getType());
// 输出: java.util.Map<java.lang.String, java.util.List<java.lang.Integer>>
// 2. 类型关系校验
TypeToken<List<String>> stringListToken = new TypeToken<List<String>>() {};
TypeToken<Iterable<String>> iterableToken = new TypeToken<Iterable<String>>() {};
System.out.println("List<String> 是否继承 Iterable<String>: "
+ stringListToken.isSubtypeOf(iterableToken)); // true
}
}
3、Invokable<A, R> 与 Parameter(统一方法与构造器)
Invokable 是 Method 和 Constructor 的统一抽象,A 表示定义该方法的类类型,R 表示返回值类型。
3.1、核心API
| 方法名 | 说明 |
|---|---|
Invokable.from(Method) / from(Constructor) |
静态工厂,将原生反射对象转为 Invokable |
getDeclaringClass() / getReturnType() |
获取声明类 / 解析后的真实返回值类型 |
getParameters() |
返回包含参数名称、类型、注解的 ImmutableList<Parameter> |
isOverridable() |
判断该方法是否可被子类重写 |
isPublic() / isPackagePrivate() / isFinal() |
简洁的权限修饰符判断 |
invoke(Object receiver, Object... args) |
安全调用方法,自动把受检异常包装抛出 |
3.2、使用示例
java
import com.google.common.reflect.Invokable;
import com.google.common.reflect.Parameter;
import java.lang.reflect.Method;
import java.util.List;
public class InvokableExample {
public List<String> processData(String input, int count) {
return List.of(input.repeat(count));
}
public static void main(String[] args) throws Exception {
Method method = InvokableExample.class.getMethod("processData", String.class, int.class);
Invokable<InvokableExample, Object> invokable = Invokable.from(method);
// 1. 修饰符与可重写状态判断
System.out.println("是否公开: " + invokable.isPublic()); // true
System.out.println("是否可重写: " + invokable.isOverridable()); // true
// 2. 参数信息读取
for (Parameter param : invokable.getParameters()) {
System.out.println("参数类型: " + param.getType() + ", 对应 Invokable: " + param.getDeclaringInvokable().getName());
}
// 3. 执行调用
InvokableExample instance = new InvokableExample();
Object result = invokable.invoke(instance, "A", 3);
System.out.println("执行结果: " + result); // [AAA]
}
}
4、Reflection 与 AbstractInvocationHandler(代理与工具)
Reflection 简化了 Java 动态代理创建流程;AbstractInvocationHandler 避免了重写 equals()、hashCode()、toString() 导致的潜在 Bug。
4.1、核心API
| 方法名 | 说明 |
|---|---|
Reflection.newProxy(Class<T>, InvocationHandler) |
快捷创建动态代理实例,无需显式传入 ClassLoader |
Reflection.initialize(Class<?>... classes) |
强制触发类的初始化(执行 static 代码块) |
handleInvocation(proxy, method, args) |
AbstractInvocationHandler 的抽象方法,专心编写业务代理逻辑 |
4.2、使用示例
java
import com.google.common.reflect.AbstractInvocationHandler;
import com.google.common.reflect.Reflection;
import java.lang.reflect.Method;
interface UserService {
String findName(long id);
}
public class ProxyExample {
public static void main(String[] args) {
// 使用 Reflection + AbstractInvocationHandler 创建代理
UserService userService = Reflection.newProxy(UserService.class, new AbstractInvocationHandler() {
@Override
protected Object handleInvocation(Object proxy, Method method, Object[] args) {
// 只处理自定义接口方法
if ("findName".equals(method.getName())) {
return "User_" + args[0];
}
return null;
}
});
System.out.println(userService.findName(1001L)); // 输出: User_1001
// toString/equals/hashCode 已被 AbstractInvocationHandler 规范处理
System.out.println(userService.toString()); // 输出类似: UserService default toString
}
}
5、ClassPath(类路径高效率扫描)
ClassPath 允许在运行时扫描 JVM 中的 Class 资源,适合做注解扫描或插件加载。
5.1、核心API
| 方法名 | 说明 |
|---|---|
ClassPath.from(ClassLoader) |
根据 ClassLoader 获取 ClassPath 实例 |
getTopLevelClasses(String packageName) |
扫描指定包名下的顶级类(不深入子包) |
getTopLevelClassesRecursive(String packageName) |
递归扫描指定包及其子包下的所有顶级类 |
ClassInfo.getName() / ClassInfo.load() |
获取类全限定名 / 延迟加载对应的 Class 对象 |
5.2、使用示例
java
import com.google.common.reflect.ClassPath;
public class ClassPathScanExample {
public static void main(String[] args) throws Exception {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
ClassPath classPath = ClassPath.from(classLoader);
// 递归扫描 com.google.common.base 包下的所有类
for (ClassPath.ClassInfo classInfo : classPath.getTopLevelClassesRecursive("com.google.common.base")) {
// 仅打印包含 "Char" 的类名
if (classInfo.getSimpleName().contains("Char")) {
System.out.println("扫描到目标类: " + classInfo.getName());
// 按需真正加载 Class
Class<?> clazz = classInfo.load();
System.out.println("类装载成功: " + clazz.getCanonicalName());
}
}
}
}
6、TypeResolver(底层类型解算器)
TypeResolver 是 Guava 内部用于求解复杂的 Type 变量绑定的独立工具,支持将带有类型占位符(如 T、K)的 Type 绑定为真正的实际类型。
java
import com.google.common.reflect.TypeResolver;
import java.lang.reflect.Type;
import java.util.List;
public class TypeResolverExample {
public static void main(String[] args) throws Exception {
// 1. 假设有一个泛型接口 List<E> 的 get(int) 方法,返回值类型为 E (TypeVariable)
Type eType = List.class.getMethod("get", int.class).getGenericReturnType();
System.out.println("原始返回值类型: " + eType); // E
// 2. 创建 TypeResolver,设定绑定关系:将 List.class 中的 E 替换为 String.class
TypeResolver resolver = new TypeResolver()
.where(List.class.getTypeParameters()[0], String.class);
// 3. 求解绑定后的类型
Type resolvedType = resolver.resolveType(eType);
System.out.println("求解后的返回值类型: " + resolvedType); // class java.lang.String
}
}