of()与ofNullable()的区别
从方法名上对比理解,就是
ofNullable()
可以支持null值,那of()
就不支持null值。
下面看下源码:
java.util.Optional.java
/**
* Returns an {@code Optional} with the specified present non-null value.
*
* @param <T> the class of the value
* @param value the value to be present, which must be non-null
* @return an {@code Optional} with the value present
* @throws NullPointerException if value is null
*/
public static <T> Optional<T> of(T value) {
return new Optional<>(value);
}
/**
* Constructs an instance with the value present.
*
* @param value the non-null value to be present
* @throws NullPointerException if value is null
*/
private Optional(T value) {
this.value = Objects.requireNonNull(value);
}
java.util.Objects.java
/**
* Checks that the specified object reference is not {@code null}. This
* method is designed primarily for doing parameter validation in methods
* and constructors, as demonstrated below:
* <blockquote><pre>
* public Foo(Bar bar) {
* this.bar = Objects.requireNonNull(bar);
* }
* </pre></blockquote>
*
* @param obj the object reference to check for nullity
* @param <T> the type of the reference
* @return {@code obj} if not {@code null}
* @throws NullPointerException if {@code obj} is {@code null}
*/
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
从上面的源码可以看到of()
方法里面做了判空抛出NPE处理,如果不想抛出NPE,则使用ofNullable()
。
ofNullable()的源码
private static final Optional<?> EMPTY = new Optional<>();
/**
* Constructs an empty instance.
*
* @implNote Generally only one empty instance, {@link Optional#EMPTY},
* should exist per VM.
*/
private Optional() {
this.value = null;
}
/**
* 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);
}
/**
* Returns an empty {@code Optional} instance. No value is present for this
* Optional.
*
* @apiNote Though it may be tempting to do so, avoid testing if an object
* is empty by comparing with {@code ==} against instances returned by
* {@code Option.empty()}. There is no guarantee that it is a singleton.
* Instead, use {@link #isPresent()}.
*
* @param <T> Type of the non-existent value
* @return an empty {@code Optional}
*/
public static<T> Optional<T> empty() {
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
建议:Optional的引入就是为了解决空指针的问题,所有我们在大多数情况下 使用的是 ofNullable()
方法。
orElse()与orElseGet()的区别
下面是源码
/**
* Return the value if present, otherwise return {@code other}.
*
* @param other the value to be returned if there is no value present, may
* be null
* @return the value, if present, otherwise {@code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
/**
* Return the value if present, otherwise invoke {@code other} and return
* the result of that invocation.
*
* @param other a {@code Supplier} whose result is returned if no value
* is present
* @return the value if present otherwise the result of {@code other.get()}
* @throws NullPointerException if value is not present and {@code other} is
* null
*/
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
可以看出,方法入参的区别。一个是传一个值,一个是传入一个函数。(传入函数的情况,就意味则需要的时候才会调用函数,不需要时就不会调用。出入值得话 就是在调用方法之前,这个值已经是确定的了,也就说这个值已经是经过运算了),下面举例。
举例
public class MTest {
public static void main(String[] args) {
System.out.println("1. 三目运算===========================");
boolean one = (Boolean.TRUE) ? a():b();
System.out.println(one);
//输出:
//--a--
//true
//说明:根据条件的真假,只会执行a或b方法的某一个。
System.out.println("2. orElse()===========================");
System.out.println(Optional.ofNullable(Boolean.FALSE).orElse(b()));
//--b--
//false
//说明:b()方法被执行了,将b方法的返回值true作为参数传给了orElse(true)方法,但实际并未使用true。其实按正常来说,就不应该执行b(), 那下面的orElseGet() 方法就是解决这个问题的。
System.out.println("3. orElseGet()===========================");
System.out.println(Optional.ofNullable(Boolean.FALSE).orElseGet(() -> b()));
//false
//说明:不为null时,直接打印了 Boolean.FALSE的值,根本没有去调用b()方法
System.out.println("4. of()===========================");
System.out.println(Optional.of(null).orElseGet(() -> b()));
//抛出异常
}
public static boolean a() {
System.out.println("--a--");
return true;
}
public static boolean b() {
System.out.println("--b--");
return true;
}
}
上面的输出结果是:
1. 三目运算===========================
--a--
true
2. orElse()===========================
--b--
false
3. orElseGet()===========================
false
4. of()===========================
Exception in thread "main" java.lang.NullPointerException
at java.util.Objects.requireNonNull(Objects.java:203)
at java.util.Optional.<init>(Optional.java:96)
at java.util.Optional.of(Optional.java:108)
at com.iccboy.data.test.core.credit.service.MTest.main(MTest.java:15)
Process finished with exit code 1
从上面的例子中,建议:使用ofNullable()
避免空指针, orElse()
与orElseGet()
根据出入的值来判断,如果是传入的一个已知的值(变量)则可用orElse()
,如果传入的是一个方法则使用orElseGet()