对于 Java 开发者来讲,null
是一个使人头疼的类型,一不当心就会发生 NPE (空指针) 问题。也是 Java 语言为人诟病的一个重要缘由之一。在咱们消除可恶的 NPE 问题以前咱们要回顾一下 Java 中 null 的概念。html
翻译自 Oracle Java 文档java
Java语言中有两种类型,一种是 基本类型 ,另外一种是 引用类型。还有一种没有名字的特殊类型,即表达式null
。
因为null
类型没有名称,因此不可能声明为null
类型的变量或者转换为null
类型。
null
引用是null
类型表达式惟一可能的值。
null
引用能够转换为任意引用类型。
事实上,程序员能够忽略null
类型,能够认为null
仅仅是一个能够成为任何引用类型的特殊符号。
从上面的描述咱们能够了解到,其实 null 仅仅是一个关键字标识量,既不是一种类型也不算对象,没法直接声明 null 和被转换为 null,仅仅只能被引用,null 能够转换为任何引用类型。当一个 Java 引用类型对象被引用为 null 时表明当前对象不引用对象,并无为其分配内存。 这也是咱们在没有引用的对象上调用方法出现空指针的根本缘由。
大多数状况下 Java 开发者使用 null
是为了表示某种不存在的意思。程序员
不少时候咱们对数据是否存在有本身的指望,可是这种指望并不能直接被咱们掌控,一个返回值为 null 所表达的意思并不明确过于模糊,每每经过是否判断为 null
来规避空指针问题。因而 Google 工程师在他们的 Guava
工具类库中设计了 Optional<T>
来解决 null
不可控的问题。 让你在不得不使用 null
的时候,能够更加简便明确的使用 null
并帮助你避免直接使用 null
带来的问题。
Java 8 将此设计吸取。咱们能够直接使用 Java 提供的 Optional
来解决空指针问题。接下来咱们来研究一下 Java 8 中的 Optional
。编程
Java 8 中的 Optional
是一个可选值的包装类。它的意义不只仅帮咱们简化了 NPE 问题的处理,同时也是 Java 函数式编程的一个重要辅助。 咱们接下来将对其 API 进行讲解以帮助你在实际开发中使用他们。安全
Optional
只能经过静态方法来声明。它提供了三个静态方法:oracle
empty() 返回一个值为 null
的 Optional
实例函数式编程
Optional<Object> empty = Optional.empty();
of(T) 返回一个值不为 null
的 Optional
实例函数
Optional<String> nonNull = Optional.of("Felordcn");
ofNullable() 返回一个值可能为 null
的 Optional
实例工具
// value 值来自其它不肯定的来源 String value = SomeApi.source(); // 可能为 null Optional<String> nullable = Optional.ofNullable(value); // 也可能不为 null Optional<String> hasValue = Optional.ofNullable(value);
isPresent() 若是值存在则返回 true
,不然返回 false
。若是 Optional
值不肯定,可以使用该方法进行安全校验spa
Optional<String> nonNull = Optional.of("Felordcn"); // true boolean present =nonNull.isPresent();
get() 获取 Optional
中的值,若是为空会抛出 NoSuchElementException
异常
Optional<String> nonNull = Optional.of("Felordcn"); // Felordcn String str = nonNull.get();
ifPresent(Consumer) 若是值存在则该值被消费函数 Consumer
消费 , 不然不作任何事情。 isPresent()
增强版
// 非空打印出字符串 nullable.ifPresent(System.out::println); //等同于 if (nullable.isPresent()) { System.out.println(nonNull); }
filter(Predicate) 若是值知足断言函数 Predicate
则返回该 Optional
,不然返回 Optional.empty()
Optional<String> nonNull = Optional.of("Felordcn"); Optional<String> felord = nonNull.filter(s -> s.startsWith("Felord")); // str = "Felordcn" String str = felord.get();
map(Function) 获取元素某个属性的 Optional
。 若是该属性为 null
返回 Optional.empty()
,不然返回对应值的 Optional
Optional<User> userOpt = Optional.ofNullable(user); // username 为空 则为 空 Optional Optional<String> usernameOpt = userOpt.map(User::getUsername);
flatMap(Function) 有时候咱们会返回 Optional<Optional<T>>
很是不便于处理,咱们须要将元素展开,可以使用该方法处理,参考 Stream Api 中的相关方法
orElse(other) 若是 Optional
的值存在,返回 Optional
, 不然指定一个 Optional
orElseGet(Supplier) 若是 Optional
的值存在,返回 Optional
, 不然指定一个执行 Supplier
函数来获取值
orElseThrow(Supplier<? extends Throwable>) 若是 Optional
的值存在,返回 Optional
, 不然抛出一个指定 Supplier
函数提供的异常
or(Supplier) orElseGet
的改进类型。不仅仅返回具体的值,而能够函数式的返回 Optional
stream() 将 Optional
和 Stream
打通
ifPresentOrElse(Consumer) ifPresent
方法提供了有值后的消费逻辑而没有值的逻辑没有提供入口。新方法 ifPresentOrElse
弥补了这一缺陷
Optional
很香可是也不能滥用。一个危险的举动就是将 Optional
做为入参传递给方法。 由于入参是不可控的,你没法保证入参中的 Optional
是否为 null
。这偏偏违背了 Optional
的本意。因此尽可能在表达式中使用 Optional
或者在返回值中使用,而不是在方法的参数中使用 Optional
。
今天对 Optional
进行讲解。从 Optional
的设计本意到其经常使用的方法。咱们也对 Optional
在 Java 9 中的新 API 进行了介绍。另外 Optional
也不是万能的,合理的使用才能发挥其优点。但愿今天的文章对你有用。
关注公众号:Felordcn 获取更多资讯