Optional 详细用法
Optional 详细用法
文章共4,634字 · 阅读需要大约16分钟
一键AI生成摘要,助你高效阅读
问答
·
1:Optional 是一个对象容器,具有以下两个特点
-
提示用户要注意该对象有可能为null
-
简化if else代码
Optional.empty(): 创建一个空的 Optional 实例
Optional.of(T t):创建一个 Optional 实例,当 t为null时抛出异常
//调用工厂方法创建Optional实例
Optional<String> name = Optional.of("Sanaulla");
//控制台打印输出Sanaulla
System.out.println(name.get());
//传入参数为null,抛出NullPointerException.
Optional<String> someNull = Optional.of(null);
Optional.ofNullable(T t):创建一个 Optional 实例,但当 t为null时不会抛出异常,而是返回一个空的实例
//ofNullable与of方法相似,唯一的区别是可以接受参数为null的情况,如果指定的值为null,则返回一个空的Optional
//下面创建了一个不包含任何值的Optional实例
//例如,值为'null'
Optional empty = Optional.ofNullable(null);
//通过isPresent()方法返回false为空,true非空
if (empty.isPresent()) {
System.out.println(empty.get());
} else {
System.out.println("值为空");
}
2. 获取:
get():获取optional实例中的对象,当optional 容器为空时报错
3. 判断:
- isPresent():判断optional是否为空,如果空则返回false,否则返回true
//isPresent方法用来检查Optional实例中是否包含值
if (name.isPresent()) {
//在Optional实例内调用get()返回已存在的值
System.out.println(name.get());//输出Sanaulla
}
- ifPresent(Consumer c):如果optional不为空,则将optional中的对象传给Comsumer函数
//ifPresent方法接受lambda表达式作为参数。
//lambda表达式对Optional的值调用consumer进行处理。
Optional<String> optional = Optional.of("Hello");
optional.ifPresent(s -> {
s = s + "world";
//打印Helloworld
System.out.println(s);
});
//打印Hello
System.out.println(optional.get());
//通过ifPresent修改的值,再次通过get获取的时候不会改变
- 设置(获取)默认值,有时候,我们在创建(获取) Optional 对象的时候,需要一个默认值,orElse() 和 orElseGet() 方法就派上用场了(类似三目运算符)
- orElse() 方法用于返回包裹在 Optional 对象中的值,如果该值不为 null,则返回;否则返回默认值。该方法的参数类型和值得类型一致(类似三目运算符)
String nullName = null;
String name = Optional.ofNullable(nullName).orElse("沉默王二");
System.out.println(name); // 输出:沉默王二
String nullName = "小王";
String name = Optional.ofNullable(nullName).orElse("沉默王二");
System.out.println(name); // 输出:小王
- orElseGet() 方法与 orElse() 方法类似,但参数类型不同。如果 Optional 对象中的值为 null,则执行参数中的函数
String nullName = null;
String name = Optional.ofNullable(nullName).orElseGet(()->"沉默王二");
System.out.println(name); // 输出:沉默王二
- 从输出结果以及代码的形式上来看,这两个方法极其相似,这不免引起我们的怀疑,Java 类库的设计者有必要这样做吗?
- 假设现在有这样一个获取默认值的方法,很传统的方式
public static String getDefaultValue() {
System.out.println("getDefaultValue");
return "沉默王二";
}
- 然后,通过 orElse() 方法和 orElseGet() 方法分别调用 getDefaultValue() 方法返回默认值
public static void main(String[] args) {
String name = null;
System.out.println("orElse");
String name2 = Optional.ofNullable(name).orElse(getDefaultValue());
System.out.println("orElseGet");
String name3 = Optional.ofNullable(name).orElseGet(Demo::getDefaultValue);
}
- 注:类名 :: 方法名是 Java 8 引入的语法,方法名后面是没有 () 的,表明该方法并不一定会被调用
- 输出结果如下所示:
orElse
getDefaultValue
orElseGet
getDefaultValue
- 输出结果是相似的,没什么太大的不同,这是在 Optional 对象的值为 null 的情况下。假如 Optional 对象的值不为 null 呢?
public static void main(String[] args) {
String name = "沉默王三";
System.out.println("orElse");
String name2 = Optional.ofNullable(name).orElse(getDefaultValue());
System.out.println("orElseGet");
String name3 = Optional.ofNullable(name).orElseGet(OrElseOptionalDemo::getDefaultValue);
}
- 输出结果如下所示:
orElse
getDefaultValue
orElseGet
- orElseGet() 没有去调用 getDefaultValue()。orElseGet方法的性能更佳
- orElseGet() 直观从语义上来看,get() 方法才是最正宗的获取 Optional 对象值的方法,但很遗憾,该方法是有缺陷的,因为假如 Optional 对象的值为 null,该方法会抛出 NoSuchElementException 异常。这完全与我们使用 Optional 类的初衷相悖
public class GetOptionalDemo {
public static void main(String[] args) {
String name = null;
Optional<String> optOrNull = Optional.ofNullable(name);
System.out.println(optOrNull.get());
}
}
- 这段程序在运行时会抛出异常:
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:141)
at com.cmower.dzone.optional.GetOptionalDemo.main(GetOptionalDemo.java:9)
- 尽管抛出的异常是 NoSuchElementException 而不是 NPE,但在我们看来,显然是在“五十步笑百步”。建议 orElseGet() 方法获取 Optional 对象的值
- orElse(T other):如果optional不为空,则返回optional中的对象;如果为null,则返回 other 这个默认值
//如果值不为null,orElse方法返回Optional实例的值。
//如果为null,返回传入的消息。
//输出:There is no value present!
System.out.println(empty.orElse("There is no value present!"));
//输出:Sanaulla
System.out.println(name.orElse("There is some value!"));
-
orElseGet(Supplier other):如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other
-
orElseThrow(Supplier exception):如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常
4. 过滤:
filter(Predicate p):如果optional不为空,则执行断言函数p,如果p的结果为true,则返回原本的optional,否则返回空的optional
//filter方法检查给定的Option值是否满足某些条件。
//如果满足则返回同一个Option实例,否则返回空Optional。
Optional<String> longName = name.filter((value) -> value.length() > 6);
System.out.println(longName.orElse("The name is less than 6 characters"));//输出Sanaulla
//另一个例子是Optional值不满足filter指定的条件。
Optional<String> anotherName = Optional.of("Sana");
Optional<String> shortName = anotherName.filter((value) -> value.length() > 6);
//输出:name长度不足6字符
System.out.println(shortName.orElse("The name is less than 6 characters"));
5. 映射:
- map(Function<T, U> mapper):如果optional不为空,则将optional中的对象 t 映射成另外一个对象 u,并将 u 存放到一个新的optional容器中。
//map方法执行传入的lambda表达式参数对Optional实例的值进行修改。
//为lambda表达式的返回值创建新的Optional实例作为map方法的返回值。
Optional<String> upperName = name.map((value) -> value.toUpperCase());
System.out.println(upperName.orElse("No value found"));
-
flatMap(Function< T,Optional< U >> mapper):跟上面一样,在optional不为空的情况下,将对象t映射成另外一个optional
-
区别:map会自动将u放到optional中,而flatMap则需要手动给u创建一个optional
//flatMap与map(Function)非常类似,区别在于传入方法的lambda表达式的返回类型。
//map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。
//但flatMap方法中的lambda表达式返回值必须是Optionl实例。
upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));
System.out.println(upperName.orElse("No value found"));//输出SANAULLA
6:实例演示- Optional 的三种构造方式: Optional.of(obj), Optional.ofNullable(obj) 和明确的 Optional.empty(),生成user
- 存在即返回, 无则提供默认值
Optional<String> optional = Optional.of("Hello");
//打印Hello
System.out.println(user.orElse(null);
//而不是
return user.isPresent() ? user.get() : null;
- 存在即返回, 无则由函数来产生
return user.orElseGet(() -> fetchAUserFromDatabase());
//而不要
return user.isPresent() ? user: fetchAUserFromDatabase();
- 存在才对它做点什么
user.ifPresent(System.out::println);
//而不要下边那样
if (user.isPresent()) {
System.out.println(user.get());
}
- map 函数隆重登场
return user.map(u -> u.getOrders()).orElse(Collections.emptyList())
//上面避免了我们类似 Java 8 之前的做法
if(user.isPresent()) {
return user.get().getOrders();
} else {
return Collections.emptyList();
}
使用 Optional 时尽量不直接调用 Optional.get() 方法, Optional.isPresent() 更应该被视为一个私有方法, 应依赖于其他像 Optional.orElse(), Optional.orElseGet(), Optional.map() 等这样的方法.
更多推荐
已为社区贡献9条内容
所有评论(0)