我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
当前回答
如果不允许空值
如果从外部调用方法,请从以下内容开始:
public void method(Object object) {
if (object == null) {
throw new IllegalArgumentException("...");
}
然后,在该方法的其余部分中,您将知道该对象不为空。
如果它是一个内部方法(不是API的一部分),只需记录它不能为空,就可以了。
例子:
public String getFirst3Chars(String text) {
return text.subString(0, 3);
}
但是,如果您的方法只是传递值,而下一个方法传递值等,则可能会出现问题。在这种情况下,您可能需要检查上述参数。
如果允许为空
这真的取决于。如果发现我经常这样做:
if (object == null) {
// something
} else {
// something else
}
所以我分支,做两件完全不同的事情。没有难看的代码片段,因为我确实需要根据数据做两件不同的事情。例如,我应该处理输入,还是应该计算一个好的默认值?
实际上,我很少使用“if(object!=null&&…”这个成语。
如果你展示了你通常使用这个习语的例子,那么给你举例可能会更容易。
其他回答
我可以更笼统地回答吗!
当方法以我们不期望的方式获取参数时,我们通常会遇到这个问题(错误的方法调用是程序员的错误)。例如:您希望得到一个对象,而得到一个null。您希望得到一个至少包含一个字符的字符串,而得到一个空字符串。。。
因此:
if(object == null){
//you called my method badly!
}
or
if(str.length() == 0){
//you called my method badly again!
}
他们都希望在执行任何其他函数之前确保我们收到了有效的参数。
如其他一些答案中所述,为了避免上述问题,您可以遵循契约设计模式。请参见http://en.wikipedia.org/wiki/Design_by_contract.
要在java中实现这种模式,可以使用javax.annotation.NotNull等核心java注释,或者使用Hibernate Validator等更复杂的库。
只是一个示例:
getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)
现在,您可以安全地开发方法的核心函数,而无需检查输入参数,它们可以保护您的方法不受意外参数的影响。
您可以更进一步,确保在应用程序中只能创建有效的pojo。(来自hibernate验证器站点的示例)
public class Car {
@NotNull
private String manufacturer;
@NotNull
@Size(min = 2, max = 14)
private String licensePlate;
@Min(2)
private int seatCount;
// ...
}
Java8现在有一个可选类,该类包装考虑中的对象,如果存在值,isPresent()将返回true,而get()则返回值。
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Java8在Java.util包中引入了一个新的类Optional。
Java 8的优点可选:
1.)不需要空检查。2.)运行时不再出现NullPointerException。3.)我们可以开发干净整洁的API。
可选-可以包含或不包含非空值的容器对象。如果存在值,isPresent()将返回true,而get()则返回该值。
有关更多详细信息,请在此处找到oracle文档:-https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html
Java8带来了新的Java.util.Optional类,它可以解决一些问题。至少可以说,它提高了代码的可读性,并且在公共API的情况下,使API的契约对客户端开发人员更加清晰。
它们是这样工作的:
给定类型(Fruit)的可选对象被创建为方法的返回类型。它可以是空的或包含Fruit对象:
public static Optional<Fruit> find(String name, List<Fruit> fruits) {
for (Fruit fruit : fruits) {
if (fruit.getName().equals(name)) {
return Optional.of(fruit);
}
}
return Optional.empty();
}
现在看看这段代码,我们在其中搜索给定Fruit实例的Fruit(水果)列表:
Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
Fruit fruit = found.get();
String name = fruit.getName();
}
您可以使用map()运算符对可选对象执行计算,或从中提取值。orElse()允许您为缺少的值提供回退。
String nameOrNull = find("lemon", fruits)
.map(f -> f.getName())
.orElse("empty-name");
当然,检查空/空值仍然是必要的,但至少开发人员意识到该值可能是空的,忘记检查的风险是有限的。
在从头开始使用Optional构建的API中,只要返回值可能为空,并且仅在不能为空时返回纯对象(惯例),客户端代码可能会放弃对简单对象返回值的空检查。。。
当然,Optional也可以用作方法参数,在某些情况下,可能比5或10个重载方法更好地指示可选参数。
可选提供了其他方便的方法,例如允许使用默认值的orElse,以及与lambda表达式一起使用的ifPresent。
我邀请您阅读这篇文章(我撰写这个答案的主要来源),其中很好地解释了NullPointerException(以及一般的空指针)问题以及Optional带来的(部分)解决方案:Java Optional Objects。
总而言之,避免声明
if (object != null) {
....
}
由于java7,您可以使用Objects方法:Objects.isNull(对象)Objects.nonNull(对象)Objects.requireOnNull(对象)Objects.equals(object1,object2)从java8开始,您可以使用Optional类(何时使用)
object.ifPresent(obj->…);java 8
object.ifPresentOrElse(对象->…,()->…);java 9
依靠方法契约(JSR305)并使用FindBugs。用annotations@javax.annotation.Nullable和@javax.annotation.Nonnnual标记代码。还提供了前提条件。前提条件.checkNotNull(对象);在特殊情况下(例如字符串和集合),可以使用apachecommons(或Google guava)实用程序方法:
公共静态布尔isEmpty(CharSequence cs)//apache CollectionUtils公共静态布尔isEmpty(集合coll)//apacheStringUtils公共静态布尔isEmpty(Map Map)//apache MapUtils公共静态布尔isNullOrEmpty(@Nullable String字符串)//Guava字符串
当您需要在null时分配默认值时,请使用apachecommons-lang
公共静态对象defaultIfNull(对象对象,对象defaultValue)