Guava——反射

反射

1、概述

com.google.common.reflect 包提供了增强版的 Java 反射工具,解决了原生反射 API 在泛型擦除、方法与构造器抽象不统一、动态代理模板代码冗余以及类路径扫描等方面的局限。

包核心类一览

类名 核心职责 解决的原生反射痛点
TypeToken<T> 运行时捕获、解析与操作完整泛型类型 突破泛型擦除限制,准确判断带泛型的继承关系
TypeParameter<T> 配合 TypeToken.where() 进行动态泛型变量替换 可以在运行时动态绑定未知的泛型参数类型
Invokable<A, R> 统一抽象 MethodConstructor 解决方法/构造器无法统一处理及泛型返回值正确解析的问题
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
    }
}
相关推荐
lingran__1 小时前
Git 完全指南(三):远程仓库与标签管理
开发语言·git·gitee·ssh·团队协作·远程仓库·分布式版本控制
for_ever_love__1 小时前
python爬虫: 数据解析
开发语言·爬虫·python·xpath
学习星球1 小时前
AI 一句话生成 3D 游戏世界:腾讯 HY-World 2.0 开源深度解析与本地实战
开发语言·人工智能·游戏·3d·ai·课程设计·ai编程
名字还没想好☜1 小时前
Go 用 -race 抓数据竞争:一个偶发崩溃的排查、原理与修复
开发语言·后端·golang·go
小灰灰搞电子1 小时前
Rust std::vec::Vec<T>动态数组:所有相关 API 全面介绍
开发语言·rust
X1A0RAN1 小时前
Jenkins 流水线跨阶段的数据共享:让变量“动态更新“成为可能
java·servlet·jenkins
学习星球1 小时前
CodeWhale 深度剖析:从 DeepSeek-TUI 到 40.9K Star 的 Rust 终端编程 Agent
开发语言·后端·rust
Rain的Java大神之路2 小时前
高并发下的热点账户余额扣减:Redis+Lua脚本实现无锁记账
java·spring boot·redis·后端·spring cloud·缓存·lua
随遇而安zx2 小时前
【地基篇】---JVM 类加载 源码解析(基于 Java 8)
java·jvm·python