JDK 9:对象类中添加了非空类方法


JDK 9将一些新方法添加到Objects class包括两个static本文重点介绍的方法:requireNonNullElse(T,T)requireNonNullElseGet(T obj,Supplier<? extends T> supplier)。这两种方法都使验证给定对象是否null如果所提供的变量原来是null。因此,这些方法以及引入到Objects在早期JDK版本中[requireNonNull(T),requireNonNull(T,String),和requireNonNull(T,Supplier<String>)]最有可能用于实现guard clauses在方法上。

上一段中提到的添加到Objects在JDK 9之前的版本中,当被测试的对象被确定为null。相反,这三个方法中的每一个都会引发NullPointerException当传递给它们的变量是null。这两个方法添加到Objects在JDK 9中,确实允许指定可以由方法返回的默认值,而不是方法抛出NullPointerException

Objects.requireNonNullElse(T,T)是两个新添加的方法中最直接的方法,用于指定在提供的待测变量为null。下面的代码清单显示了应用此方法的示例。

示例:Objects.requireNonNullElse(T,T)

/**
 * Provide instance of {@code Instant} that corresponds to
 * the provided instance of {@code Date}.
 *
 * @param inputDate Instance of {@code Date} for which
 *    corresponding instance of {@code Instant} is desired;
 *    if this is {@code null}, an {@code Instant} representing
 *    "now" will be returned.
 * @return Instance of {@code Instant} extracted from provided
 *    {@Date} that will instead represent "now" if provided
 *    {@code Date} is {@code null}.
 */
public Instant convertDateToInstantWithNowDefault(final Date inputDate)
{
   final Date dateToConvert
      = Objects.requireNonNullElse(inputDate, new Date());
   return dateToConvert.toInstant();
}


在上面的示例中,如果提供的变量类型为Date存在null,提供的默认值“Now”(基于调用Date constructor that doesn't accept arguments)返回。

JDK 9还添加了该方法Objects.requireNonNullElseGet(T,Supplier<? extends T>)出于类似的目的。此方法与前面讨论的方法的不同之处在于,它接受Supplier用于提供默认值,而不是接受相同类型的另一个对象作为默认值。

在这本极力推荐的书中Modern Java Recipes,Ken Kousen写道,“主要的用例之一是Supplier%s是为了支持延期执行.“在讨论了如何Supplier在JDK中使用,他补充说,“这个延迟执行的过程可以在您自己的代码中使用,以确保从Supplier只有在适当的时候。“我的下一个示例演示了这一点。

下面显示了一个精心设计的代码清单,并演示了如何使用此方法接受Supplier

示例:Objects.requireNonNullElseGet(T,Supplier<? extends T>)

/**
 * Provide instance of {@code Instant} that corresponds to
 * the provided instance of {@code Date}.
 *
 * @param inputDate Instance of {@code Date} for which
 *    corresponding instance of {@code Instant} is desired;
 *    if this is {@code null}, an {@code Instant} based on
 *    a complicated date calculation will be returned.
 * @return Instance of {@code Instant} extracted from provided
 *    {@Date} that will instead represent a calculated date if
 *    provided {@code Date} is {@code null}.
 */
public Instant convertDateToInstantWithCalculatedDefault(final Date inputDate)
{
   final Date dateToConvert
      = Objects.requireNonNullElseGet(inputDate, () -> calculateDate());
   return dateToConvert.toInstant();
}


方法的版本,该方法接受Supplier当预期用于确定默认值的代码长时间运行时可能是有利的。在这种情况下,仅当第一个传入参数为null。当第一个传入的参数是null,则不会调用长时间运行的方法。[顺便说一下,我没有显示calculateDate()在这里,因为它是可笑的人为设计,但只要说,它故意花了非常长的时间来执行。]

这篇文章中介绍的两种方法使得检测特定变量是否null并在出现故障时提供合适的替代方案null。它们很可能最常用于实现“保护子句”,但是它们返回默认值的能力也可能导致额外的用例。