【Java8新特性】——Optional
前提
著名的NullPointerException是导致Java应用程序失败的最常见原因,而在Java8中对这种常见错误提出了Optional<T>类(java.util.Optional)是一个容器类,代表一个值存在或不存在。Optional不是对null关键字的一种替代,而是对于null判定提供了一种更加优雅的实现,还可以避免空指针异常。
空指针是运行时异常,对于这一类异常,大多数情况下,不是没有具体的处理措施,而是根本没有意识到空指针异常的存在。当异常发生的时候,处理策略非常简单,加一个if语句判定即可。良好的程序设计,在代码中尽可能减少null关键字!而Java8中提供的Optional类则在减少NullPointException的同时,提升代码的美观度。
没有Optional
if(null == str) { // 空指针判定 return 0; } return str.length();
使用Optional类,如下
return Optional.ofNullable(str).map(String::length).orElse(0);
Optional基本使用方式
1、对象创建
//1、创建一个空Optional对象 Optional<Object> empty = Optional.empty(); //2、创建对象,如果str对象为null,则会抛出NullPointException String str = "test"; Optional<String> optStr = Optional.of(str); //3、创建对象,如果str对象非null,则返回一个Optional描述指定的值,否则返回空值Optional Optional<String> optStrNotNull = Optional.ofNullable(str);
2、流式处理
Optional提供两个基本流操作,映射和过滤。
map——map(Function<? super T,? extends U> mapper)
如果存在值,则将提供的映射函数应用于该函数,如果结果不为空,则返回Optional描述结果。
注意:如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。
//map方法中的lambda表达式返回值可以是任意类型,在map函数返回之前会包装为Optional。 Optional<Object> map = op.map( Employess::getAge ).map( t -> Optional.get( t ) ); Integer mapAge = op.map( Employess::getAge ).orElse( 19 );
flatMap——flatMap(Function<? super T,Optional> mapper)
如果存在值,则将提供的Optional映射函数应用于该函数,返回该结果,否则返回空值 Optional。
注意:flatMap方法中的lambda表达式返回值必须是Optionl实例。
// flatMap方法中的lambda表达式返回值必须是Optionl实例。 Integer flatAge = op.flatMap( emp -> Optional.of( emp.getAge() ) ).orElse( 19 );
3、默认行为
默认行为是当Optional为不满足/满足时条件时所执行的操作。
Optional<String> str = Optional.of("test"); //1、判断str是否为null,如果不为null,则为true,否则为false if (str.isPresent()) { //get用于获取变量的值,当变量不存在的时候会抛出NoSuchElementException,如果不能确定变量一定存在值,则不推荐使用 str.get(); } //2、如果存在值,则使用该值调用消费者,否则不执行任何操作 str.ifPresent(s -> System.out.println(s.toUpperCase())); // 3、ofNullable(T value)(静态)返回一个Optional描述指定的值,如果非null,否则返回一个空值Optional。 Optional<String> toUpperCase = Optional.ofNullable(str.toString().toUpperCase()); //4、orElse(T other) 返回值如果存在,则返回,否则返回 other String s = str.orElse("str is null"); //5、orElseGet(Supplier<? extends T> other)返回值如果存在,否则调用other并返回该调用的结果 String orElseGet = str.orElseGet(() -> "test".toUpperCase()); System.out.println(orElseGet); //6、orElseThrow(Supplier<? extends X> exceptionSupplier) // 返回包含的值(如果存在),否则抛出由提供的供应商创建的异常。 str.orElseThrow(NoSuchElementException::new); //7、filter(Predicate<? super T> predicate) //如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional Optional<String> filterOpt = str.filter(value -> value.length() > 3);
注意:
if(null == str) { // 空指针判定 return 0; } return str.length();
利用Optional if中的判断和处理,本质上和if null没有区别,当然这不是更好使用Java8 Optional正确的打开方式。
在IDEA中没有isPresent()做铺垫的get()会收到警告
Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. If the Optional does not contain a value, get() will throw an exception. (调用 Optional.get() 前不事先用 isPresent() 检查值是否可用. 假如 Optional 不包含一个值, get() 将会抛出一个异常)
把 Optional 类型用作属性或是方法参数在 IntelliJ IDEA 中更是强力不推荐的
Reports any uses of java.util.Optional
如果一定要使用Optional作为属性,可以使用如下方式
private long phone; public Optional<Long> getPhone() { return Optional.ofNullable(this.phone); }
4、其他
// 返回当前值的哈希码值(如果有的话),如果没有值,则返回0(零)。 int hashCode = str.hashCode(); // 返回适用于调试的此可选的非空字符串表示形式。 String s1 = str.toString();
总结
多去尝试新的特性,尽力提高自己的代码质量,是程序员的基本的职业素养!
还没有评论,来说两句吧...