场景:mongodb库,表增加新字段,旧数据对应的字段为空。当需要调用对象中的字段时,字段为空时导致空指针报错。当对象存在大量字段,就需要先做大量非空判断了。
简单demo:
public class Entity {
private BigDecimal money;
private Integer base;
// 省略getter/setting/toString
}
public static void main(String[] args) {
List<Entity> list = new ArrayList<>();
Entity entity1 = new Entity(new BigDecimal(12), 10);
list.add(entity1);
// 模拟mongodb库中数据,存在缺少字段的情况
// Entity entity2 = new Entity(null, 20);
Entity entity2 = new Entity(new BigDecimal(13), null);
list.add(entity2);
Optional<Entity> reduce = list.stream().reduce(
(x, y) -> new Entity(
x.getMoney().add(y.getMoney()),
x.getBase() + y.getBase()
)
);
System.out.println(reduce.get());
}
很明显上面会报空指针:
###解决方法
增加初始化空字段校验,当字段为空时,根据字段类型进行初始化
public static void main(String[] args) {
List<Entity> list = new ArrayList<>();
Entity entity1 = new Entity(new BigDecimal(12), 10);
list.add(entity1);
// Entity entity2 = new Entity(null, 20);
Entity entity2 = new Entity(new BigDecimal(13), null);
list.add(entity2);
try {
initNullField(list, Entity.class);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("######初始化空字段异常");
}
Optional<Entity> reduce = list.stream().reduce(
(x, y) -> new Entity(
x.getMoney().add(y.getMoney()),
x.getBase() + y.getBase()
)
);
System.out.println(reduce.get());
}
/**
* 初始化空字段
*
* @param ts
* @param cls
* @param <T>
* @throws Exception
*/
private static <T> void initNullField(List<T> ts, Class<T> cls) throws Exception {
// 获取实体类的所有属性,返回Field数组
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
// 设置获取权限
field.setAccessible(true);
String name = field.getName();
for (T t : ts) {
Object objectValue = field.get(t);
if (objectValue == null) {
// 获取到字段的类型
Type type = field.getGenericType();
String setterMethodName = "set" + StringUtils.capitalize(name);
// 根据类型的不同执行不同的初始化操作
if (type.equals(BigDecimal.class)) {
Method method = cls.getMethod(setterMethodName, BigDecimal.class);
method.invoke(t, BigDecimal.ZERO);
} else if (type.equals(Integer.class)) {
Method method = cls.getMethod(setterMethodName, Integer.class);
method.invoke(t, 0);
}
}
}
}
}
代码执行正常: