为了账号安全,请及时绑定邮箱和手机立即绑定

在 JAVA 中检查对象的空字段

在 JAVA 中检查对象的空字段

暮色呼如 2021-09-12 16:28:21
假设我有一个包含 x 个字段的对象。允许两个为非空,其余的必须为空。我不想逐个字段做空检查,所以我想知道是否有一种聪明的方法可以用最新的java版本的一些功能来做这个空检查。
查看完整描述

3 回答

?
阿晨1998

TA贡献2037条经验 获得超6个赞

您可以stream为 POJO 中的所有字段创建并可以检查 null

return Stream.of(id, name).anyMatch(Objects::isNull);

或者

return Stream.of(id, name).allMatch(Objects::isNull);


查看完整回答
反对 回复 2021-09-12
?
人到中年有点甜

TA贡献1895条经验 获得超7个赞

我不想逐个字段做空检查

您可以避免自己编写支票,但您需要“标记”字段上的约束。

并使用 Validator 显式验证实例。
请注意,带注释的字段null在某个上下文中可能是强制性的,而null在另一个上下文中则不一定。并且它与这种方式兼容,因为验证器将仅在请求时验证对象:即按需。


根据您的评论:

我正在开发代码库,而您的解决方案具有侵入性。我将不得不接触创建该 pojo 的低级 json 解析器。我不想那样做

在这种情况下,您可以使用要验证的当前类外部的 Map。
它将允许维护您验证的字段的名称并在错误消息中使用它(对调试很有用)。

例如 :

Foo foo = new Foo();

// set foo fields...


// expected null but was not null

Map<String, Object> hasToBeNullMap = new HashMap<>();

hasToBeNullMap.put("x", foo.getX());

hasToBeNullMap.put("y", foo.getY());

hasToBeNullMap.put("z", foo.getZ());

String errrorMessageForNullExpected = getErrorFieldNames(hasToBeNullMap, Objects::nonNull);


// expected not null but was null

Map<String, Object> hasToBeNotNullMap = new HashMap<>();

hasToBeNotNullMap.put("z", foo.getZ());

String errrorMessageForNotNullExpected = getErrorFieldNames(hasToBeNotNullMap, o -> o == null);


private static String getErrorFieldNames(Map<String, Object> hasToBeNullMap, Predicate<Object> validationPred) {

    return hasToBeNullMap.entrySet()

                         .stream()

                         .filter(validationPred::test)

                         .map(Entry::getKey)

                         .collect(joining(","));

}


查看完整回答
反对 回复 2021-09-12
?
哆啦的时光机

TA贡献1779条经验 获得超6个赞

如果对象中只有几个字段,并且您知道它不会经常更改,则可以Stream.of按照 Deadpool 的回答将它们列为参数。缺点是违反了 DRY 原则:您重复字段名称:一次在 POJO 定义中,再次在参数列表中。


如果您有很多字段(或不想重复自己),您可以使用反射:


boolean valid = Stream.of(YourPojoClass.class.getDeclaredFields())

    .filter(f -> !(f.getName().equals("fieldname allowed to be null") || f.getName.equals("the other field name")))

    .allMatch(f -> {

        f.setAccessible(true);

        try {

            return f.get(o) == null;

        } catch (IllegalAccessException e) {

            throw new RuntimeException(e);

        }

    });

请注意,使用反射可能会产生很小的性能损失,与解析从 Web 服务获得的 JSON 字符串相比可能微不足道。


如果您有原始字段(例如int, boolean, char)并且您希望将它们包含在检查中,将它们限制为默认值(0, false, '\0'),则使用以下代码:


    .allMatch(f -> {

        f.setAccessible(true);

        try {

            return (f.getType() == boolean.class && f.getBoolean(o) == false)

                    || (f.getType().isPrimitive() && f.getDouble(o) == 0)

                    || f.get(o) == null;

        } catch (IllegalAccessException e) {

            throw new RuntimeException(e);

        }

    });


查看完整回答
反对 回复 2021-09-12
  • 3 回答
  • 0 关注
  • 191 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信