我使用 x != null
来避免 NullPointerException
。有其他的替代方法吗?
if (x != null) {
// ...
}
我使用 x != null
来避免 NullPointerException
。有其他的替代方法吗?
if (x != null) {
// ...
}
无论何时传递数组或向量,请将它们初始化为空,而不是为null。这样你就可以避免大量检查null并且一切都很好 :)
public class NonNullThing {
Vector vectorField = new Vector();
int[] arrayField = new int[0];
public NonNullThing() {
// etc
}
}
null
(且不检查null
),则可以使用类型T
。如果它可能为null
,则可以使用类型Optional<T>
。然后,使用方法map
来处理T ->
,使用方法flatMap
来处理T -> Optional<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;}
}
解决“!= null”检查的另一种方法是(如果从设计上无法摆脱):
Optional.ofNullable(someobject).ifPresent(someobject -> someobject.doCalc());
或者
Optional.ofNullable(someobject).ifPresent(SomeClass::doCalc);
假设SomeClass是someobject的类型。
然而,你无法从doCalc()中获得返回值,因此仅适用于void方法。
map
结合 get
或者其他获取 Optional 值的方法来获取值,而不是使用 ifPresent
。 - ThisIsNoZaku在Java 8中,你可以像下面这样将供应商传递给一个辅助方法:
if(CommonUtil.resolve(()-> a.b().c()).isPresent()) {
}
if(a!=null && a.b()!=null && a.b().c()!=null) {
}
//CommonUtil.java
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
} catch (NullPointerException var2) {
return Optional.empty();
}
}
Java 8现在有一个Optional类,它包装了需要考虑的对象。如果存在值,则isPresent()将返回true,并且get()将返回该值。
http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
您也可以使用Checker Framework(适用于JDK 7及以上版本)静态检查空值。这可能会解决很多问题,但需要运行一个额外的工具,目前只能在OpenJDK上使用。
https://checkerframework.org/好的,我知道这个问题已经被技术上回答了无数次,但我必须说一下,因为这是与Java程序员讨论不休的问题。
抱歉,但我几乎不同意以上所有观点。我们在Java中必须测试null的原因是因为大多数Java程序员不知道如何处理内存。
我之所以这么说是因为我在C++中有很长时间的编程经验,我们不这样做。换句话说,你不需要这样做。请注意,在Java中,如果你遇到悬空指针,你会得到一个普通的异常;而在C++中,这个异常通常不会被捕获并终止程序。
不想这样做?那么就按照C / C ++的一些简单规则进行操作。
不要轻易实例化东西,考虑每个“new”可能会给你带来很多麻烦,并遵循这些简单的规则。
一个类只能以3种方式访问内存 ->
它可以“拥有”类成员,它们将遵循以下规则:
这意味着您需要像Java一样记住谁是每个资源的所有者或父级,并尊重该所有权。只有创建它的类才能删除对象。 另外 ->
某些成员将被“使用”但不拥有或“拥有”。这些是由另一个类“拥有”的,并作为参数传递给构造函数。由于这些属于另一个类,因此我们永远不会删除或关闭它们,只有父项可以这样做。
类中的方法还可以实例化用于内部使用的本地对象,这些对象永远不会超出类的范围,否则它们应该是正常的“拥有”对象。
最后,为了使所有这些工作,您需要具有分层形式的有纪律的设计,并且不进行循环。
在这种设计下,并遵循上述规则,分层设计中的子类将永远不会访问已销毁的指针,因为这意味着父类在子类之前被销毁,而分层非循环设计将不允许这种情况发生。
最后,还要记住,在启动系统时,您应该从层次结构的顶部向下构建,并从底部向上销毁。你永远不会在任何地方遇到null指针,否则有人正在违反规则。
有一种好的方法可以从JDK中检查空值。 它是Optional.java,有许多方法来解决这些问题。比如下面:
/**
* Returns an {@code Optional} describing the specified value, if non-null,
* otherwise returns an empty {@code Optional}.
*
* @param <T> the class of the value
* @param value the possibly-null value to describe
* @return an {@code Optional} with a present value if the specified value
* is non-null, otherwise an empty {@code Optional}
*/
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
/**
* Return {@code true} if there is a value present, otherwise {@code false}.
*
* @return {@code true} if there is a value present, otherwise {@code false}
*/
public boolean isPresent() {
return value != null;
}
/**
* If a value is present, invoke the specified consumer with the value,
* otherwise do nothing.
*
* @param consumer block to be executed if a value is present
* @throws NullPointerException if value is present and {@code consumer} is
* null
*/
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
这对于帮助Javer非常有用。
public class Null {
public static void main(String[] args) {
String str1 = null;
String str2 = "";
if(isNullOrEmpty(str1))
System.out.println("First string is null or empty.");
else
System.out.println("First string is not null or empty.");
if(isNullOrEmpty(str2))
System.out.println("Second string is null or empty.");
else
System.out.println("Second string is not null or empty.");
}
public static boolean isNullOrEmpty(String str) {
if(str != null && !str.isEmpty())
return false;
return true;
}
}
输出
str1 is null or empty.
str2 is null or empty.