Java 8 引入了 Optional 类来简化代码中空指针异常的处理。当代码中调用空对象的方法或属性时,可能会出现空指针异常。考虑到代码中出现空指针异常的可能性非常高,开发者通常会尝试处理每一个可能出现空值的情况,但由于这是一个运行时异常,程序仍然容易出错,并且遗漏空检查的机会仍然很高。
Optional 实例是一个容器对象,用于包含非空对象/值。Optional 对象用于表示空值的存在与否。此类提供各种实用方法,帮助代码处理值为“可用”或“不可用”的情况,而不是检查空值。它在 Java 8 中引入,并且类似于 Guava 中的 Optional。
Optional 类提供了类型检查解决方案,而不是直接检查空值。此类充当值的包装器。除了处理空值外,Optional 类还提供了许多实用方法,如在空值情况下获取默认值、在底层值为空的情况下抛出异常等。
Optional 类声明
以下是 java.util.Optional<T> 类的声明:
public final class Optional<T> extends Object
Optional 类方法
方法与描述
-
static <T> Optional<T> empty() 返回一个空的 Optional 实例。
-
boolean equals(Object obj) 表明另一个对象是否与此 Optional “相等”。
-
Optional<T> filter(Predicate<? super <T> predicate>) 如果存在一个值并且该值匹配给定的谓词,则返回一个描述该值的 Optional,否则返回一个空的 Optional。
-
<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper) 如果存在一个值,则应用提供的带有 Optional 的映射函数,并返回该结果,否则返回一个空的 Optional。
-
T get() 如果此 Optional 中存在值,则返回该值,否则抛出 NoSuchElementException。
-
int hashCode() 返回存在的值的哈希码值,如果没有值则返回 0。
-
void ifPresent(Consumer<? super T> consumer) 如果存在一个值,则使用该值调用指定的消费者,否则不做任何事情。
-
boolean isPresent() 如果存在一个值则返回 true,否则返回 false。
-
<U>Optional<U> map(Function<? super T,? extends U> mapper) 如果存在一个值,则应用提供的映射函数,并如果结果非空,则返回一个描述结果的 Optional。
-
static <T> Optional<T> of(T value) 返回具有指定非空值的 Optional。
-
static <T> Optional<T> ofNullable(T value) 返回描述指定值的 Optional,如果指定的值为 null 则返回一个空的 Optional。
-
T orElse(T other) 如果存在一个值,则返回该值,否则返回 other。
-
T orElseGet(Supplier<? extends T> other) 如果存在一个值,则返回该值,否则调用 other 并返回调用的结果。
-
<X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) 如果存在一个值,则返回包含的值,否则根据提供的供应商抛出异常。
-
String toString() 返回此 Optional 的非空字符串表示形式,适用于调试。
-
boolean isEmpty() 如果存在一个值则返回 false,否则返回 true。此方法是在 Java 11 中添加到 Optional API 中的。
此类继承了来自 java.lang.Object 的方法。
创建 Optional 类实例
Optional 类提供了多种方法来为提供的值/对象创建 Optional 实例。以下是一些对应的方法及其语法,后跟一个示例:
Optional.empty() 方法
此方法返回一个空值的 Optional 实例。它可以用来表示不存在的值而不是 null。
Optional emptyOptional = Optional.empty();
Optional.of() 方法
此方法返回一个具有给定非空值的 Optional 实例。如果提供的值为 null,则会抛出 NullPointerException。
String name = "John";
Optional valueOptional = Optional.of(name);
Optional.ofNullable() 方法
此方法返回一个具有给定值的 Optional 实例。如果提供的值为 null,则返回一个空的 Optional 实例。
Optional emptyOptional = Optional.empty();
示例:创建 Optional 实例
以下示例展示了如何使用上述方法创建 Optional 对象以及何时应使用它们。
package com.tutorialspoint;
import java.util.Optional;
public class OptionalTester {
public static void main(String[] args) {
Integer value1 = null;
Integer value2 = Integer.valueOf(10);
Optional<Integer> empty = Optional.empty();
Optional<Integer> a = Optional.ofNullable(value1);
Optional<Integer> b = Optional.of(value2);
System.out.println("value of a: " + (a.isPresent() ? a.get(): "0"));
System.out.println("value of b: " + (b.isPresent() ? b.get(): "0"));
System.out.println("value of empty: " + (empty.isPresent() ? empty.get(): "0"));
}
}
编译并运行上述程序,将会产生以下结果:
value of a: 0
value of b: 10
value of empty: 0
检查 Optional 类实例值
Optional 类提供了以下方法来检查 Optional 实例是否有值。这些方法应在使用 get() 方法获取 Optional 实例的值之前使用,因为 get() 方法会在底层值为空时抛出空指针异常。
Optional.isPresent() 方法
此方法检查当前的 Optional 实例,并基于是否存在值返回 true 或 false。
Optional emptyOptional = Optional.empty();
boolean isValuePresent = emptyOptional.isPresent();
Optional.isEmpty() 方法
此方法检查当前的 Optional 实例,并基于是否存在值返回 true 或 false。此方法是在 Java 11 中添加到 Optional API 中的。
Optional emptyOptional = Optional.empty();
boolean isValuePresent = emptyOptional.isEmpty();
示例:检查 Optional 实例
以下示例展示了如何使用上述方法创建 Optional 对象以及何时应使用它们。
package com.tutorialspoint;
import java.util.Optional;
public class OptionalTester {
public static void main(String[] args) {
Integer value1 = null;
Integer value2 = Integer.valueOf(10);
Optional<Integer> empty = Optional.empty();
Optional<Integer> a = Optional.ofNullable(value1);
Optional<Integer> b = Optional.of(value2);
System.out.println("value of a: " + (a.isEmpty() ? a.get(): "0"));
System.out.println("value of b: " + (b.isPresent() ? b.get(): "0"));
System.out.println("value of empty: " + (empty.isPresent() ? empty.get(): "0"));
}
}
编译并运行上述程序,将会产生以下结果:
value of a: 0
value of b: 10
value of empty: 0
使用 Optional 类方法的默认值
Optional 类提供了以下方法来从 Optional 实例中获取默认值,如果值不存在的话。
Optional.orElse() 方法
此方法检查当前的 Optional 实例,并如果存在值则返回其值,否则返回提供的默认值。
Optional<Integer> valueOptional = Optional.ofNullable(null);
Integer value = valueOptional.orElse(Integer.valueOf(-1));
Optional.orElseGet(Supplier) 方法
此方法检查当前的 Optional 实例,并如果存在值则返回其值,否则调用传递给函数的供应商来生成默认值并返回相同的值。
Optional<Integer> valueOptional = Optional.ofNullable(null);
Integer value = valueOptional.orElseGet(()-> (int)(Math.random() * 10));
使用 Optional 类方法获取默认值的示例
以下示例展示了如何使用上述方法通过 Optional 对象获取默认值。
package com.tutorialspoint;
import java.util.Optional;
public class OptionalTester {
public static void main(String[] args) {
Optional<Integer> valueOptional = Optional.ofNullable(null);
Integer value = valueOptional.orElse(Integer.valueOf(-1));
System.out.println(value);
Optional<Integer> valueOptional1 = Optional.ofNullable(Integer.valueOf(10));
Integer value1 = valueOptional1.orElse(Integer.valueOf(-1));
System.out.println(value1);
Optional<Integer> valueOptional2 = Optional.ofNullable(null);
Integer value2 = valueOptional2.orElseGet(() -> (int)(Math.random() * 10));
System.out.println(value2);
Optional<Integer> valueOptional3 = Optional.ofNullable(Integer.valueOf(10));
Integer value3 = valueOptional3.orElseGet(() -> (int)(Math.random() * 10));
System.out.println(value3);
}
}
编译并运行上述程序,将会产生以下结果:
-1
10
3
10
Optional 类用于抛出异常的方法
Optional 类提供了以下方法,在值不存在的情况下抛出异常。
Optional.orElseThrow() 方法
我们可以在必要字段未传递的情况下优雅地处理这种情况,使用 orElseThrow() 方法抛出自定义异常。
Optional<Integer> emptyOptional = Optional.empty();
Integer value = emptyOptional.orElseThrow();
Optional.orElseThrow(Supplier) 方法
我们可以在必要字段未传递的情况下优雅地处理这种情况,使用 orElseThrow(supplier) 方法调用抛出自定义异常。
Optional<Integer> emptyOptional = Optional.empty();
Integer value = emptyOptional.orElseThrow(() -> {throw new RuntimeException("value not present");});
使用 Optional 类抛出异常的示例
以下示例展示了如何使用上述方法在缺少必要参数时抛出和处理异常。
package com.tutorialspoint;
import java.util.Optional;
public class OptionalTester {
public static void main(String[] args) {
Optional<Integer> valueOptional1 = Optional.ofNullable(null);
Optional<Integer> valueOptional2 = Optional.ofNullable(10);
try {
sum(valueOptional1, valueOptional2);
} catch (Exception e) {
e.printStackTrace();
}
try {
sum(valueOptional2, valueOptional1);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Integer sum(Optional<Integer> value1, Optional<Integer> value2) {
Integer val1 = value1.orElseThrow();
Integer val2 = value2.orElseThrow(() -> {throw new RuntimeException("value not present");});
return val1 + val2;
}
}
编译并运行上述程序,将会产生以下结果:
java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.orElseThrow(Optional.java:377)
at com.tutorialspoint.OptionalTester.sum(OptionalTester.java:27)
at com.tutorialspoint.OptionalTester.main(OptionalTester.java:12)
java.lang.RuntimeException: value not present
at com.tutorialspoint.OptionalTester.lambda$0(OptionalTester.java:29)
at java.base/java.util.Optional.orElseThrow(Optional.java:403)
at com.tutorialspoint.OptionalTester.sum(OptionalTester.java:29)
at com.tutorialspoint.OptionalTester.main(OptionalTester.java:19)