我需要验证班级中的必填字段
例如,9
字段不得为null
。
我需要检查它们是否都为空,但是我现在正在使用多个if语句,如下所示:
StringBuilder mandatoryExcessFields = new StringBuilder(MANDATORY_EXCESS_FIELDS.length);
if(Objects.isNull(excess.getAsOfDate())){
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[0]);
}
if(StringUtils.isEmpty(excess.getStatus())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[1]);
}
if(Objects.isNull(excess.getLimit())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[2]);
}
if(!Objects.isNull(excess.getLimit()) && Objects.isNull(excess.getLimit().getId())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[3]);
}
if(!Objects.isNull(excess.getLimit()) && Objects.isNull(excess.getLimit().getAsOfDate())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[4]);
}
if(Objects.isNull(excess.getExposure())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[5]);
}
if(!Objects.isNull(excess.getExposure()) && Objects.isNull(excess.getExposure().getCoordinates())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[6]);
}
if(!Objects.isNull(excess.getExposure()) && Objects.isNull(excess.getExposure().getValue())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[7]);
}
if(StringUtils.isEmpty(excess.getLimitValue())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[8]);
}
我们是否有更好的方法来减少这种样板代码,我可以利用的Java-8的任何设计模式或任何新功能?
答案 0 :(得分:3)
所有Object.isNull
都可以替换为Optional
对象及其方法。让我们以以下行为例:
if (!Objects.isNull(excess.getLimit()) && Objects.isNull(excess.getLimit().getId())) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[3]);
}
将简化为(并压缩在1行以保持可读性):
Optional.ofNullable(excess.getLimit()) // check the Limit
.map(limit -> limit.getId()) // if not null, getId
.ifPresent(i -> builder.append(MANDATORY_EXCESS_FIELDS[3])); // Append if present
对于String.isEmpty(s)
检查,您必须以这种方式创建Optional
:
Optional.ofNullable(excess.getStatus()).filter(s -> !StringUtils.isEmpty(s))
一种简短的方法是将那些Optional
对象传递到地图中,并使用索引来遍历它们并执行操作。 int count
是许多检查项:
Map<Integer, Optional<?>> map = new HashMap<>();
map.put(...);
map.put(1, Optional.ofNullable(excess.getStatus()).filter(s -> !StringUtils.isEmpty(s)));
map.put(...);
map.put(3, Optional.ofNullable(excess.getLimit()).map(limit -> limit.getId()));
map.put(...);
for (int index=0; index<count; index++) {
map.get(index).ifPresent(any -> mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[index]));
}
for循环也可以简化:
IntStream.range(0, count).forEach(index ->
map.get(index)
.ifPresent(any -> mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[index])));
答案 1 :(得分:2)
基本上,这里有两种方法:
我强烈建议您研究bean验证:
定义将信息作为bean承载的类。然后使用各种注释标记相应的字段。然后使用一些现有框架为您进行验证。您甚至可以在那里定义自己的自己批注,这些批注运行您自己的自己的代码。
答案 2 :(得分:2)
您可以在javax.validator
POJO类的每个字段(或所需的任何字段)上使用带有hibernate.validator
批注的@NotNull
和excess
。这种组合还提供了广泛的模式检查。
通过这种方法,您不必显式地执行所有if检查。您不仅可以使用null检查,还可以使用模式匹配检查,这些检查可能分散在您的所有代码中。
答案 3 :(得分:1)
基本上,初始化和赋值不应将任何字段设置为null。
如果这是不合时宜的(一个字段在逻辑上实际上是可选的),则该字段可能应该是一个Optional<...>
,并分配了一个Optional.ofNullable(...)
。这样可以确保在使用时可以安全地处理该字段,但是当然会导致编辑工作。
现在看代码,这里似乎没有简单的重构。
代码可以重构;在某些地方缺少功能映射。
Predicate<Excess>[] parts = {
exc -> Objects.isNull(exc.getAsOfDate()),
exc -> StringUtils.isEmpty(exc.getStatus()),
...
};
for (int i = 0; i < parts.length; ++i) {
if (parts[i].test(excess)) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[i]);
}
}
等等。
答案 4 :(得分:1)
为方便重构,您可以引入两种帮助方法:
private String createErrorMsgIfObjectNull(Object o, String errorMessage) {
return Objects.isNull(o) ? errorMessage : "";
}
private String createErrorMsgIfStringEmpty(String s, String errorMessage) {
return StringUtils.isEmpty(s) ? errorMessage : "";
}
并以这种方式使用它们:
StringBuilder mandatoryExcessFields = new StringBuilder(MANDATORY_EXCESS_FIELDS.length);
mandatoryExcessFields.append(createErrorMsgIfObjectNull(excess.getAsOfDate(), MANDATORY_EXCESS_FIELDS[0]))
.append(createErrorMsgIfStringEmpty(excess.getStatus(), MANDATORY_EXCESS_FIELDS[1]))
.append(createErrorMsgIfObjectNull(excess.getLimit(), MANDATORY_EXCESS_FIELDS[2]))
// ...
通过检查要测试的对象的类型,您仍然可以走得更远。您将只有一个帮助程序方法,该方法将根据参数类型进行处理:
private String createErrorMsgIfNullOrEmptyString(Object o, String errorMessage) {
if (o instanceof String) {
return StringUtils.isEmpty((String)o) ? errorMessage : "";
}
return Objects.isNull(o) ? errorMessage : "";
}
Java 8流方法将在filter
和map()
操作中内联帮助程序,并会收集String
结果:
List<SimpleImmutableEntry<Object, String>> objectAndErrorMessageList = new ArrayList<>();
int i = 0;
objectAndErrorMessageList.add(new SimpleImmutableEntry<>(excess.getAsOfDate(), MANDATORY_EXCESS_FIELDS[i++]));
objectAndErrorMessageList.add(new SimpleImmutableEntry<>(excess.getStatus(), MANDATORY_EXCESS_FIELDS[i++]));
// and so for
String globalErrorMsg =
objectAndErrorMessageList.stream()
.filter(e -> {
Object objectToValid = e.getKey();
if (objectToValid == null) {
return true;
}
if (objectToValid instanceof String && StringUtils.isEmpty(objectToValid)) {
return true;
}
return false;
})
.map(SimpleImmutableEntry::getValue)
.collect(Collectors.joining(""));
答案 5 :(得分:0)
其他解决方案如下:与@Nikolas答案相同。
Map<Integer, Predicate<Excess>> map = new HashMap<>();
Predicate<Excess> checkStatus = excess -> excess.getStatus().isEmpty();
Predicate<Excess> checkLimit = excess -> Objects.isNull(excess.getLimit());
Predicate<Excess> checkLimitId = excess -> Objects.isNull(excess.getLimit().getId());
Predicate<Excess> checkLimitAndId = checkLimit.and(checkLimitId);
// other predicates
map.put(1,checkStatus);
map.put(2,checkLimit);
map.put(3,checkLimitAndId);
// put other predicates ...
for (Map.Entry<Integer, Predicate<Excess>> m : map.entrySet()) {
if (m.getValue().test(excess)) {
mandatoryExcessFields.append(MANDATORY_EXCESS_FIELDS[m.getKey()]);
}
}
答案 6 :(得分:0)
有点复杂,但是我有一个很好的解决方案,因为它是通用的,可以与任何对象一起使用:
Excess excess = new Excess(new Limit());
Checker<Excess, Excess> checker = new Checker<>(
identity(),
List.of(
new CheckerValue<>("excess date is null", Excess::getAsOfDate),
new CheckerValue<>("limit is null", Excess::getLimit)
),
List.of(new Checker<>(Excess::getLimit, List.of(new CheckerValue<>("limit id is null", Limit::getId))))
);
System.out.println(checker.validate(excess));
此代码将打印:
excess date is null
limit id is null
第一堂课Checker
包含:
孩子-Checker
class Checker<S, T> {
Function<S, T> sourceFunction;
List<CheckerValue<T>> values;
List<Checker<T, ?>> children = emptyList();
/*All args constructor; 2 args constructor*/
public String validate(S object) {
T value = sourceFunction.apply(object);
if(value != null) {
String valueString = values.stream().map(v -> v.validate(value)).filter(Optional::isPresent).map(Optional::get).collect(joining("\n"));
valueString += "\n\t";
valueString += children.stream().map(c -> c.validate(value)).collect(Collectors.joining("\n"));
return valueString;
}
return "";
}
}
和CheckerValue
类:
class CheckerValue<T> {
String validationString;
Function<T, Object> fun;
/*all args constructor*/
public Optional<String> validate(T object) {
return fun.apply(object) != null ? Optional.empty() : Optional.of(validationString);
}
}