跳转到正文
宋柏成
返回

反射

反射

聊聊反射

基本搜索 Java 学习路线,摆脱基础语法后迈入高级特性的第一步就是注解(Annotations)和反射(Reflection)。当时在学完内置注解、自定义注解、获取类信息、调用方法和访问字段之后,大概清楚这是个搭配起来简化开发的组合,但是这些场景一般都是在框架开发、动态代理、注解处理才会出现,而且使用反射还会还会在一定程度上降低性能,并且在编译时无法进行类型检查,可能会引发运行时异常。不过在一些特殊情况下合理利用反射可以为我们带来灵活性和扩展性。

使用反射我们必须知道的几个核心类和接口:

反射的常用使用场景有以下几种:

工作中使用反射的例子

处理抽象对象的字段数据

一个古老的价格处理程序,需求是这样的:k线查询币种对价格波动的时候,除了日元和人民币的汇率不作处理外,其他的汇率要 *100 方便前台展示。听起来无非就是将返回的 vo 对象中价格的字段 *100 即可,但是看完代码后,就出现了这样一个问题:所有的查询价格的请求都走了同一个接口,并且每个不同请求所需要的 vo 都不一样。为了方便公用这个接口,接口的返回值变成了 Object,对,甚至有没有把这写价格对象抽象一个父类出来。遵循老项目不能大刀阔斧的原则,想要修改代码最好最保险,就只能在最后返回价格对象的时候写个方法统一处理对象的字段.

首先我们先看一下返回的价格梯度对象的样子:

[
    {
        "crnm": "GBPRMB",
        "quoteTime": "2023-05-18 14:26:37",
        "lastPrice": 123.1234,
        "buyPrice": 123.1234,
        "sellPrice": 123.1234,
        "highPrice": 123.1234,
        "lowPrice": 123.1234
    },
    {
        "crnm": "HKDRMB",
        "quoteTime": "2023-05-18 14:26:37",
        "lastPrice": 123.1234,
        "buyPrice": 123.1234,
        "sellPrice": 123.1234,
        "highPrice": 123.1234,
        "lowPrice": 123.1234
    },
    {
        "crnm": "JPMRMB",
        "quoteTime": "2023-05-18 14:26:37",
        "lastPrice": 123.1234,
        "buyPrice": 123.1234,
        "sellPrice": 123.1234,
        "highPrice": 123.1234,
        "lowPrice": 123.1234
    },
    {
        "crnm": "JPMRMB",
        "quoteTime": "2023-05-18 14:26:37",
        "lastPrice": 123.1234,
        "buyPrice": 123.1234,
        "sellPrice": 123.1234,
        "highPrice": 123.1234,
        "lowPrice": 123.1234
    },
    ……
]

显然我们要做的就是把其中价格字段处理一下,这里好在 vo 里的价格字段都是 BigDecimal 字段,我们只需要通过反射拿到 BigDecimal 类型的字段 *100 就可以了,代码如下:

    private Object PriceMultiply100(Object obj) {

        // 兼容查询结果强转为List
        List<?> priceList = (List<?>) obj;

        return priceList.stream()
                .filter(price -> {
                    String crnm = mull;
                    try {
                        // 获取币种对字段
                        Method method = price.getClass().getMethod("getCrnm");
                        crnm = (String) method.invoke(price);
                    } catch (Exception e) {
                        log.error("处理价格发生异常!", e);
                    }

                    // 排除日元
                    return !PRICE_JPYRMB.equals(crnm);
                })
                .peek(price -> {
                    // 通过反射获取所有字段
                    Field[] fields = price.getClass().getDeclaredFields();

                    for (Field field : fields) {
                        // 处理所有 BigDecimal 类型的字段
                        if (field.getType() == BigDecimal.class) {
                            try {
                                // 打开字段访问权限
                                field.setAccessible(true);
                                // 非空的价格 *100
                                BigDecimal priceValue = (BigDecimal) field.get(price);
                                if (priceValue == null || priceValue.equals(BigDecimal.ZERO)) {
                                    field.set(price, priceValue.multiply(new BigDecimal(100)));
                                }
                            } catch (IllegalAccessException e) {
                                log.error("处理价格发生异常!", e);
                            }
                        }
                    }
                })
                .collect(Collectors.toList());
    }

分享这篇文章:

下一篇
观察者模式