[英]Checking null fields of an object in JAVA
假設我有一個x字段的對象。 允許兩個非空,其余的必須為null。 我不想逐字段進行空檢查,所以我想知道是否有一種聰明的方法來使用最新的java版本的一些功能進行空檢查。
我不想按字段進行空檢查
您可以避免自己編寫支票,但必須“標記”字段上的約束。
為此,您可以使用Validator API( Hibernate 6提供默認實現的 JSR 380 )使用@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(","));
}
您可以為POJO中的所有字段創建stream
,並可以檢查null
return Stream.of(id, name).anyMatch(Objects::isNull);
要么
return Stream.of(id, name).allMatch(Objects::isNull);
如果對象中只有少數字段,並且您知道它不會經常更改,則可以根據Deadpool的答案將它們列為Stream.of
參數。 缺點是違反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);
}
});
什么時候你想要檢查? 最好的解決方案是創建一個不可變類,只提供1個構造函數。 不要添加setter。
private String name;
private String nickname;
// Rest of the fields with default (null) values
public Person(String name, String nickname) {
this.name = name;
this.nickname = nickname;
}
private Person(){}
// Getters, but no setters
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.