我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
我使用x!=null以避免NullPointerException。还有其他选择吗?
if (x != null) {
// ...
}
当前回答
根据所检查的对象类型,您可以使用apachecommons中的一些类,例如:apachecommons-lang和apachecommons集合
例子:
String foo;
...
if( StringUtils.isBlank( foo ) ) {
///do something
}
或(取决于您需要检查的内容):
String foo;
...
if( StringUtils.isEmpty( foo ) ) {
///do something
}
StringUtils类只是众多类中的一个;在commons中有相当多的好类可以进行空安全操作。
下面是一个示例,说明当您包含apache库(commons-lang-2.4.jar)时,如何在JAVA中使用空值验证
public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) {
Validate.notNull(validationEventHandler,"ValidationHandler not Injected");
return read(new StringReader(xml), true, validationEventHandler);
}
如果您使用的是Spring,Spring的包中也有相同的功能,请参见库(Spring-2.46.jar)
关于如何使用spring中的静态类f的示例(org.springframework.util.Assert)
Assert.notNull(validationEventHandler,"ValidationHandler not Injected");
其他回答
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。
您可以使用类似JUnit的框架将类与单元测试相结合。这样,您的代码将是干净的(没有无用的检查),并且您将确保您的实例不会为空。
这是使用单元测试的一个很好的理由。
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中,如果局部变量/字段/方法参数/方法返回类型从未赋值为null(并且不检查null),则可以使用类型T;如果可以为null,则可以键入Optional<T>。然后使用方法map处理T->,使用方法flatMap处理T->可选<R>:
class SomeService {
@Inject
private CompanyDao companyDao;
// return Optional<String>
public Optional<String> selectCeoCityByCompanyId0(int companyId) {
return companyDao.selectById(companyId)
.map(Company::getCeo)
.flatMap(Person::getHomeAddress)
.flatMap(Address::getCity);
}
// return String + default value
public String selectCeoCityByCompanyId1(int companyId) {
return companyDao.selectById(companyId)
.map(Company::getCeo)
.flatMap(Person::getHomeAddress)
.flatMap(Address::getCity)
.orElse("UNKNOWN");
}
// return String + exception
public String selectCeoCityByCompanyId2(int companyId) throws NoSuchElementException {
return companyDao.selectById(companyId)
.map(Company::getCeo)
.flatMap(Person::getHomeAddress)
.flatMap(Address::getCity)
.orElseThrow(NoSuchElementException::new);
}
}
interface CompanyDao {
// real situation: no company for such id -> use Optional<Company>
Optional<Company> selectById(int id);
}
class Company {
// company always has ceo -> use Person
Person ceo;
public Person getCeo() {return ceo;}
}
class Person {
// person always has name -> use String
String firstName;
// person can be without address -> use Optional<Address>
Optional<Address> homeAddress = Optional.empty();
public String getFirstName() {return firstName;}
public Optional<Address> getHomeAddress() {return homeAddress;}
}
class Address {
// address always contains country -> use String
String country;
// city field is optional -> use Optional<String>
Optional<String> city = Optional.empty();
String getCountry() {return country;}
Optional<String> getCity() {return city;}
}
通过遵循问题的大多数其他答案,您可以避免很多事情,以避免NullPointerException。我只想添加Java9中引入的其他一些方法,以优雅地处理这种情况,并展示一些旧的方法也可以使用,从而减少您的工作量。
公共静态布尔值isNull(对象obj)如果提供的引用为null,则返回true,否则返回错误。自Java 1.8以来公共静态布尔值nonNull(对象obj)如果提供的引用为非null,则返回true,否则返回错误。自Java 1.8以来公共静态<T>T requireOnNullElse(T对象,T默认对象)如果第一个参数为非null,则返回第一个参数,否则返回非空的第二个参数。自Java 9以来公共静态<T>T requireOnNullElseGet(T obj,供应商<?扩展T>供应商)如果第一个参数为非空,则返回第一个参数,否则返回supplier.get()的非空值。自Java 9以来公共静态<T>T requireOnNull(T obj,供应商<字符串>消息供应商)检查指定的对象引用是否为空,否则将引发自定义的NullPointerException。自Java 1.8以来
有关上述功能的更多详细信息,请参阅此处。