Java8新特性系列-Optional有什么意义?

首发于:Java8新特性系列-Optional有什么意义? – 微爱博客

Java 8 中有一个称为 Optional 类的新功能,它应该可以解决 NullPointerExceptions。 显然,这些让开发人员感到恼火的程度比我想象的要多。 很明显,一个对象实际上只是一个指针,而指针可以指向任何东西。 也许不再是了? 也许本世纪大多数计算机科学专业的毕业生从未真正了解过指针,因为学校已经被高级编程语言所吸引。 在这一点上我并不批评,这就像问 90 年代计算机科学专业的学生为什么他们不知道 COBOL。

这个新的 Optional 类的亮点当然是“类”这个词。 Optional 只是一个包装器,它包含对其他对象的引用,并且不是 NullPointerExceptions 的灵丹妙药。

让我们从创建一个生成 NullPointerException 的非常简单的示例开始:

import java.util.Optional;

public class OptionalTest{

public String getNullString(){
return (null);
}

public Optional<String> getOptionalNullString(){
return (null);
}

public static void main(String[] args){
OptionalTest optionalTest=new OptionalTest();
String nullString=optionalTest.getNullString();

try{
System.out.println(nullString.toString());
}catch(NullPointerException x){
System.out.println("Oh the humanity, a NullPointerException!");
}
}
}

  


是的,toString() 是多余的,但它保证了 NullPointerException,这是我们试图演示的。 所以这是这个问题的可怕老派解决方案:

if(nullString!=null){
System.out.println(nullString.toString());
}else{
System.out.println("nullString is null, man that check was a lot of work");
}

  


所以这里是可选的救援; 除了 Optional 是一个对象,因此它也可以为空:

Optional<String> optionalString=optionalTest.getOptionalNullString();
try{
if(optionalString.isPresent()){
System.out.println(optionalString.get().toString());
}
}catch(NullPointerException x){
System.out.println("Optional object can be null, sorry dude.");
}

  


好的,所以这可能不是该类的预期用途。 您应该使用像 Optional.of 这样的静态方法来创建实例。 如果传递了一个空值,这将抛出一个,你猜对了,NullPointerException。 因此,如果目标是避免 NullPointerExceptions,那么这种特定方法仅在您已经知道要分配非空值的情况下才有用,在这种情况下,为什么还需要 Optional? 例子:

try{
optionalString=Optional.of(optionalTest.getNullString());
if(optionalString.isPresent()){
System.out.println(optionalString.get().toString());
}
}catch(NullPointerException x){
System.out.println("NullPointerException, I thought Optional totally banished these?!");
}

  


因此,我们使用 Optional.ofNullable 来创建一个可能包含空值的 Optional 实例。 我们可以在 Optional 上调用 ifPresent 方法,而不是检查空引用的可怕负担:

optionalString=Optional.ofNullable(optionalTest.getNullString());
optionalString.ifPresent(s->{System.out.println(s.toString());});
我真的很困惑为什么这比这更可取:

String s=optionalTest.getNullString();
if(s!=null){System.out.println(s.toString());}
这个新的 Optional 类还有另外两个缺点:

1) 这是使堆管理和调试堆栈跟踪变得更糟的好方法。 同样,Optional 是一个包装器,这意味着如果您使用它,您现在将拥有两个以前拥有的对象引用。

2)它不是可序列化的,因此在许多情况下都无用。

所以回顾一下 – 为了摆脱 NullPointerExceptions 我们有一个新类:

抛出 NullPointerExceptions
本身可以为空,导致 NullPointerException
增加堆大小
使调试更加困难
使序列化对象(例如外部客户端的 XML 或 JSON)变得更加困难
====

在之前的一篇文章《Java8新特性系列-Optional有什么意义?》中,对Optional做了一些阐述,不是很明白这个类到底是为了解决什么问题而存在,原文是如下描述的

Optional is intended to provide a limited mechanism for library method return types where there needed to be a clear way to represent “no result,” and using null for such was overwhelmingly likely to cause errors.

意思是说,Optional 旨在为库里面方法返回类型提供一种有限制的机制,在需要一种明确的方式来表示“无结果”,并且使用 null 来表示这种情况极有可能导致错误的情况下使用最好。总结来说有以下几点

Optional 是用来作为方法返回值的
Optional 是为了明确地表达返回值中存在“无结果”的可能性
如果这个“无结果”通过返回 null来表示 很可能导致调用端产生错误(尤其是NullPointerException)
通过这样分析就能够理解到这个类的主要用途了

1. 不应该把这个当做空指针判断的通用替代方案

2. 应该在设计方法接口时针对返回值做出语义性的说明,来表示该方法存在“无结果”的可能

posted @ 2022-03-08 00:13  小爱博客  阅读(253)  评论(0编辑  收藏  举报