最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

Java对象中转换空值的字段 今日观点

来源:博客园

在后端返回数据给前端时,公司的框架会把值为null的数据去掉,方便前端取值。

如:Person对象为:{name:"浩二", age:24, weight:null, height:114},那返回给前端的就为{name:"浩二", age:24, height:114}。

如果这个时候有个需求:


(资料图片仅供参考)

Integer类型的字段为null给-1

Long类型的字段为null给-1L

String类型的字段为null给""(空字符串)

对象类型的字段为null给new对象,

不能直接动框架,因此需要手动转化。

代码写死转换

这种是最简单的方式,顾名思义,写死代码的方式一个一个字段来转换

示例

转换对象 ConvertNullFiledInfo

@Datapublic class ConvertNullFiledInfo {​    private Integer intNum;​    private Long longNum;​    private String str;​    private ConvertNullFiledInfo info;​}

转换代码

@Servicepublic class ConvertNullFiledService {​    /**     * 写死代码的方式一个一个字段来转换     * @param info     * @return     */    public ConvertNullFiledInfo convertFunction01(ConvertNullFiledInfo info) {        info.setIntNum(info.getIntNum() == null ? -1 : info.getIntNum());        info.setLongNum(info.getLongNum() == null ? -1L : info.getLongNum());        info.setStr(info.getStr() == null ? "" : info.getStr());        info.setInfo(info.getInfo() == null ? new ConvertNullFiledInfo() : info.getInfo());        return info;    }    }

测试代码

import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;​​@SpringBootTest@RunWith(SpringRunner.class)public class ConvertNullFiledServiceTest {​    @Autowired    private ConvertNullFiledService convertNullFiledService;​    @Test    public void convertFunction01() {        // str和info字段给null        ConvertNullFiledInfo info = createConvertNullFiledInfo(1, 1L, null, null);        ConvertNullFiledInfo result = convertNullFiledService.convertFunction01(info);        System.out.println(result);    }​    /**     * 自定义字段创建ConvertNullFiledInfo     * @param intNum     * @param longNum     * @param str     * @param info     * @return     */    private ConvertNullFiledInfo createConvertNullFiledInfo(Integer intNum, Long longNum, String str, ConvertNullFiledInfo info) {        ConvertNullFiledInfo result = new ConvertNullFiledInfo();        result.setIntNum(intNum);        result.setLongNum(longNum);        result.setStr(str);        result.setInfo(info);        return result;    }    }

运行结果

可以看到是正常转换了的

问题点

这样写虽然简单方便,但是如果有非常多的对象需要转换,就会有许多重复代码;

而且如果字段有修改(类型、名称、被删除、新增),就需要在去转换方法中修改,因此可以用更好的方式。

遍历Filed转换

所有对象都有Class类,而Class有getDeclaredFields()方法,能获取到所有字段(filed),

因此可以使用这种方式来转换。

示例

转换代码

/**     * 遍历field的方式一个一个字段来转换     * @param info     * @return     */    public ConvertNullFiledInfo convertByField(ConvertNullFiledInfo info) {        try {            Field[] fields = info.getClass().getDeclaredFields();            for (Field field : fields) {                // 设置可访问私有变量                field.setAccessible(true);                // 获取当前字段值                Object value = field.get(info);                // value不为空就跳过                if (value != null) {                    continue;                }                // 获取当前字段类型                Class type = field.getType();                if (type == Integer.class) {                    // Integer类型就设置为-1                    field.set(info, -1);                } else if (type == Long.class) {                    // Long类型就设置为-1L                    field.set(info, -1L);                } else if (type == String.class) {                    // String类型就设置为“”                    field.set(info, "");                } else if (type == ConvertNullFiledInfo.class) {                    // ConvertNullFiledInfo类型就设置为新对象                    field.set(info, new ConvertNullFiledInfo());                }            }        } catch (Exception e) {            e.printStackTrace();        }        return info;    }

测试代码

@Testpublic void convertByField() {    // str和info字段给null    ConvertNullFiledInfo info = createConvertNullFiledInfo(1, 1L, null, null);    ConvertNullFiledInfo result = convertNullFiledService.convertByField(info);    System.out.println(result);}

运行结果

可以看到也是成功转换了

问题点

这种写法仍然存在问题,可以看到方法的传参和返回值都是固定类型为ConvertNullFiledInfo,

并且在遍历field的时候,也有if判断是写定的ConvertNullFiledInfo,

因此也在一定程度上写死了代码

优化

为了避免写死的情况,可以使用泛型来写

转换代码

@Servicepublic class ConvertNullFiledService {        /**     * 使用泛型,遍历field的方式一个一个字段来转换     * @param object     * @return     */    public T convertByFieldGeneric(T object) {        try {            Field[] fields = object.getClass().getDeclaredFields();            for (Field field : fields) {                // 设置可访问私有变量                field.setAccessible(true);                // 获取当前字段值                Object value = field.get(object);                // value不为空就跳过                if (value != null) {                    continue;                }                // 获取当前字段类型                Class type = field.getType();                if (type == Integer.class) {                    // Integer类型就设置为-1                    field.set(object, -1);                } else if (type == Long.class) {                    // Long类型就设置为-1L                    field.set(object, -1L);                } else if (type == String.class) {                    // String类型就设置为“”                    field.set(object, "");                } else if (type == object.getClass()) {                    // T类型就设置为新对象                    Object newObj = object.getClass().newInstance();                    field.set(object, newObj);                }            }        } catch (Exception e) {            e.printStackTrace();        }        return object;    }}

测试代码

@Testpublic void convertByFieldGeneric() {    // 全部字段给null    ConvertNullFiledInfo info = createConvertNullFiledInfo(null, null, null, null);    ConvertNullFiledInfo result = (ConvertNullFiledInfo) convertNullFiledService.convertByFieldGeneric(info);    System.out.println(result);}

运行结果

成功转换

关键词: