如何检查多个对象是否无效?
How to check multiple objects for nullity?
通常,我可以看到如下代码结构:
if(a == null || b == null || c == null){
//...
}
我想知道是否有任何广泛使用的库(Google、Apache 等)可以同时检查多个对象的无效性,例如:
if(anyIsNull(a, b, c)){
//...
}
或
if(allAreNulls(a, b, c)){
//...
}
更新:
- 我完全可以自己写
- 我知道这可能是程序结构不佳的结果,但这里不是这种情况
让我们让它更具挑战性,并用这样的东西替换原来的例子:
if(a != null && a.getFoo() != null && a.getFoo().getBar() != null){
//...
}
更新 2:
我已经为 Apache Commons Lang 库创建了一个拉取请求来解决这个问题:
- 问题:https://issues.apache.org/jira/browse/LANG-781
- 公关:https://github.com/apache/commons-lang/pull/108
这些将合并到 commons-lang 版本 3.5 中:
anyNotNull (Object... values)
allNotNull (Object... values)
在Java 8 中,您可以使用Stream.allMatch
来检查是否所有值都符合特定条件,例如null
。不会短很多,但可能更容易阅读。
if (Stream.of(a, b, c).allMatch(x -> x == null)) {
...
}
与 anyMatch
和 noneMatch
类似。
关于你的“更具挑战性的例子”:在这种情况下,我认为没有办法绕过写一个惰性评估的空检查联合,就像你有的那样:
if (a != null && a.getFoo() != null && a.getFoo().getBar() != null) {
...
}
使用流、列表或 var-arg 方法的任何其他方法都会在 a
被测试为不是 null
之前尝试评估 a.getFoo()
。您可以将 Optional
与 map
和方法指针一起使用,它们将被一个接一个地延迟求值,但这是否使它更具可读性是值得商榷的,并且可能因情况而异(特别是对于更长的 class 名字):
if (Optional.ofNullable(a).map(A::getFoo).map(B::getBar).isPresent()) {
...
}
Bar bar = Optional.ofNullable(a).map(A::getFoo).map(B::getBar).orElse(null);
另一种选择可能是 try
访问最里面的项目,但我觉得这也不是好的做法:
try {
Bar bar = a.getFoo().getBar();
...
catch (NullPointerException e) {
...
}
特别是,在 访问该元素后,这还将捕获任何其他 NPE ——要么,要么您只需要将 Bar bar = ...
放入 [=24] =] 以及 try
之后的另一个 if
块中的所有其他内容,使可读性或简洁性方面的任何(有问题的)收益无效。
有些语言有 Safe Navigation Operator,但 Java 似乎不是其中之一。这样,您可以使用像 a?.getFoo()?.getBar() != null
这样的符号,其中如果 a
是 null
,a?.getFoo()
将只求值为 null
。不过,您可以使用自定义函数和 lambda
模拟这样的行为,返回 Optional
或仅返回一个值或 null
,如果您愿意:
public static <T> Optional<T> tryGet(Supplier<T> f) {
try {
return Optional.of(f.get());
} catch (NullPointerException e) {
return Optional.empty();
}
}
Optional<Bar> bar = tryGet(() -> a.getFoo().getBar(););
2018 年编辑: 从 Apache Commons lang 3.5 开始,已经有 ObjectUtils.allNotNull()
and ObjectUtils.anyNotNull()
.
没有
None of Apache Commons Lang (3.4), Google Guava (18) and Spring (4.1.7) 提供了这样一个实用方法。
如果你真的非常需要它,你需要自己写。不过,在现代 Java 代码中,我可能会认为需要这样的构造是一种代码味道。
您也可以使用类似下面的方法。它允许您传递任意数量的参数:
public static boolean isAnyObjectNull(Object... objects) {
for (Object o: objects) {
if (o == null) {
return true;
}
}
return false;
}
您可以使用任意多的参数来调用它:
isAnyObjectNull(a, b, c, d, e, f);
您可以为 areAllNull
做类似的事情。
public static boolean areAllObjectsNull(Object... objects) {
for (Object o: objects) {
if (o != null) {
return false;
}
}
return true;
}
注意:您也可以使用三元运算符代替if (o == null)
。此处显示的两种方法没有错误处理。根据您的需要进行调整。
您可以创建一个对象列表并在其中使用 yourList.contains(null)
。
List < Object > obList = new ArrayList < Object > ();
String a = null;
Integer b = 2;
Character c = '9';
obList.add(a);
obList.add(b);
obList.add(c);
System.out.println("List is " + obList);
if (obList.contains(null)) {
System.out.println("contains null");
} else {
System.out.println("does not contains null");
}
Objects.requireNonNull
借助 Objects
class and its requireNonNull
方法是可能的。
public static void requireNonNull(Object... objects) {
for (Object object : objects) {
Objects.requireNonNull(object);
}
}
Apache commons-lang3 自版本 3.11 以来具有方法 ObjectUtils.allNull(Object... values)
ObjectUtils.allNull(obj1, obj2, obj3);
我一直在寻找解决方案,但我还没有将 apache 作为依赖项,我觉得只为 allNonNull 方法添加它很愚蠢。这是我使用 Predicate#and() / Predicate#or() 的普通 java 解决方案,如下所示:
private static boolean allNonNull(A a) {
Predicate<A> isNotNull = Objects::nonNull;
Predicate<A> hasFoo = someA -> someA.foo != null;
Predicate<A> hasBar = someA -> someA.foo.bar != null;
return Optional.ofNullable(a)
.filter(isNotNull.and(hasFoo.and(hasBar)))
.isPresent();
}
注意:对于 anyNonNull,只需使用 or() 方法而不是 and()。
调用时,将给出以下输出:
System.out.println(isValid(new A(new Foo(new Bar())))); // true
System.out.println(isValid(new A(new Foo(null)))); // false
System.out.println(isValid(new A(null))); // false
System.out.println(isValid(null)); // false
Class 使用的定义:
public static class A {
public A(Foo foo) {
this.foo = foo;
}
Foo foo;
}
public static class Foo {
public Foo(Bar bar) {
this.bar = bar;
}
Bar bar;
}
public static class Bar { }
通常,我可以看到如下代码结构:
if(a == null || b == null || c == null){
//...
}
我想知道是否有任何广泛使用的库(Google、Apache 等)可以同时检查多个对象的无效性,例如:
if(anyIsNull(a, b, c)){
//...
}
或
if(allAreNulls(a, b, c)){
//...
}
更新:
- 我完全可以自己写
- 我知道这可能是程序结构不佳的结果,但这里不是这种情况
让我们让它更具挑战性,并用这样的东西替换原来的例子:
if(a != null && a.getFoo() != null && a.getFoo().getBar() != null){ //... }
更新 2:
我已经为 Apache Commons Lang 库创建了一个拉取请求来解决这个问题:
- 问题:https://issues.apache.org/jira/browse/LANG-781
- 公关:https://github.com/apache/commons-lang/pull/108
这些将合并到 commons-lang 版本 3.5 中:
anyNotNull (Object... values)
allNotNull (Object... values)
在Java 8 中,您可以使用Stream.allMatch
来检查是否所有值都符合特定条件,例如null
。不会短很多,但可能更容易阅读。
if (Stream.of(a, b, c).allMatch(x -> x == null)) {
...
}
与 anyMatch
和 noneMatch
类似。
关于你的“更具挑战性的例子”:在这种情况下,我认为没有办法绕过写一个惰性评估的空检查联合,就像你有的那样:
if (a != null && a.getFoo() != null && a.getFoo().getBar() != null) {
...
}
使用流、列表或 var-arg 方法的任何其他方法都会在 a
被测试为不是 null
之前尝试评估 a.getFoo()
。您可以将 Optional
与 map
和方法指针一起使用,它们将被一个接一个地延迟求值,但这是否使它更具可读性是值得商榷的,并且可能因情况而异(特别是对于更长的 class 名字):
if (Optional.ofNullable(a).map(A::getFoo).map(B::getBar).isPresent()) {
...
}
Bar bar = Optional.ofNullable(a).map(A::getFoo).map(B::getBar).orElse(null);
另一种选择可能是 try
访问最里面的项目,但我觉得这也不是好的做法:
try {
Bar bar = a.getFoo().getBar();
...
catch (NullPointerException e) {
...
}
特别是,在 访问该元素后,这还将捕获任何其他 NPE ——要么,要么您只需要将 Bar bar = ...
放入 [=24] =] 以及 try
之后的另一个 if
块中的所有其他内容,使可读性或简洁性方面的任何(有问题的)收益无效。
有些语言有 Safe Navigation Operator,但 Java 似乎不是其中之一。这样,您可以使用像 a?.getFoo()?.getBar() != null
这样的符号,其中如果 a
是 null
,a?.getFoo()
将只求值为 null
。不过,您可以使用自定义函数和 lambda
模拟这样的行为,返回 Optional
或仅返回一个值或 null
,如果您愿意:
public static <T> Optional<T> tryGet(Supplier<T> f) {
try {
return Optional.of(f.get());
} catch (NullPointerException e) {
return Optional.empty();
}
}
Optional<Bar> bar = tryGet(() -> a.getFoo().getBar(););
2018 年编辑: 从 Apache Commons lang 3.5 开始,已经有 ObjectUtils.allNotNull()
and ObjectUtils.anyNotNull()
.
没有
None of Apache Commons Lang (3.4), Google Guava (18) and Spring (4.1.7) 提供了这样一个实用方法。
如果你真的非常需要它,你需要自己写。不过,在现代 Java 代码中,我可能会认为需要这样的构造是一种代码味道。
您也可以使用类似下面的方法。它允许您传递任意数量的参数:
public static boolean isAnyObjectNull(Object... objects) {
for (Object o: objects) {
if (o == null) {
return true;
}
}
return false;
}
您可以使用任意多的参数来调用它:
isAnyObjectNull(a, b, c, d, e, f);
您可以为 areAllNull
做类似的事情。
public static boolean areAllObjectsNull(Object... objects) {
for (Object o: objects) {
if (o != null) {
return false;
}
}
return true;
}
注意:您也可以使用三元运算符代替if (o == null)
。此处显示的两种方法没有错误处理。根据您的需要进行调整。
您可以创建一个对象列表并在其中使用 yourList.contains(null)
。
List < Object > obList = new ArrayList < Object > ();
String a = null;
Integer b = 2;
Character c = '9';
obList.add(a);
obList.add(b);
obList.add(c);
System.out.println("List is " + obList);
if (obList.contains(null)) {
System.out.println("contains null");
} else {
System.out.println("does not contains null");
}
Objects.requireNonNull
借助 Objects
class and its requireNonNull
方法是可能的。
public static void requireNonNull(Object... objects) {
for (Object object : objects) {
Objects.requireNonNull(object);
}
}
Apache commons-lang3 自版本 3.11 以来具有方法 ObjectUtils.allNull(Object... values)
ObjectUtils.allNull(obj1, obj2, obj3);
我一直在寻找解决方案,但我还没有将 apache 作为依赖项,我觉得只为 allNonNull 方法添加它很愚蠢。这是我使用 Predicate#and() / Predicate#or() 的普通 java 解决方案,如下所示:
private static boolean allNonNull(A a) {
Predicate<A> isNotNull = Objects::nonNull;
Predicate<A> hasFoo = someA -> someA.foo != null;
Predicate<A> hasBar = someA -> someA.foo.bar != null;
return Optional.ofNullable(a)
.filter(isNotNull.and(hasFoo.and(hasBar)))
.isPresent();
}
注意:对于 anyNonNull,只需使用 or() 方法而不是 and()。
调用时,将给出以下输出:
System.out.println(isValid(new A(new Foo(new Bar())))); // true
System.out.println(isValid(new A(new Foo(null)))); // false
System.out.println(isValid(new A(null))); // false
System.out.println(isValid(null)); // false
Class 使用的定义:
public static class A {
public A(Foo foo) {
this.foo = foo;
}
Foo foo;
}
public static class Foo {
public Foo(Bar bar) {
this.bar = bar;
}
Bar bar;
}
public static class Bar { }