假设我有一个有x个字段的对象。两个被允许为非空,其余的必须为空。我不想逐个字段执行空检查,所以我想知道是否有一种明智的方法可以使用最新java版本的一些特性来完成空检查。
发布于 2018-09-10 17:18:49
如果对象中只有几个字段,并且知道它不会经常更改,您可以根据Deadpool的答案将它们作为Stream.of参数列出。缺点是违反了and原则:重复字段名:一次在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);
}
});发布于 2018-09-10 16:51:00
可以为POJO中的所有字段创建stream,并检查null。
return Stream.of(id, name).anyMatch(Objects::isNull);或
return Stream.of(id, name).allMatch(Objects::isNull);发布于 2018-09-10 16:45:08
我不想逐个字段做空检查
您可以避免自己编写检查,但是您需要“标记”字段上的约束。
为此,可以使用Validator (JSR 380,哪个Hibernate 6提供默认实现。)来用@Null和@NotNull对类字段进行注释。
并使用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(","));
}https://stackoverflow.com/questions/52262121
复制相似问题