optional_optionalfeatures - CSDN
optional 订阅
optional 是一个英语单词,形容词,作形容词时意思是“可选择的,随意的”。 展开全文
optional 是一个英语单词,形容词,作形容词时意思是“可选择的,随意的”。
信息
外文名
optional
词    性
形容词
optional单词发音
英[ˈɒpʃənl];美[ˈɑːpʃənl] [1] 
收起全文
精华内容
参与话题
  • java8新特性-Optional

    千次阅读 2018-05-18 08:16:20
    Optional 容器类:用于尽量避免空指针异常 Optional.of(T t) : 创建一个 Optional 实例 Optional.empty() : 创建一个空的 Optional 实例 Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则...
     Optional 容器类:用于尽量避免空指针异常
    Optional.of(T t) : 创建一个 Optional 实例
    Optional.empty() : 创建一个空的 Optional 实例
    Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例
    isPresent() : 判断是否包含值
    orElse(T t) :  如果调用对象包含值,返回该值,否则返回t
    orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
    map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()

    flatMap(Function mapper):与 map 类似,要求返回值必须是Optional


    @Test
    	public void test06(){
    		Optional<Student> op=Optional.ofNullable(null);
    		Optional<Integer> map = op.flatMap((e)->Optional.of(e.getAge()));
    		System.out.println(map);//Optional.empty
    		
    		Optional<Student> op1=Optional.ofNullable(null);
    		Optional<Integer> map1 = op1.flatMap((e)->Optional.of(e.getAge()));
    		System.out.println(map1.orElse(12));//12
    		
    
    	}
    	@Test
    	public void test05(){
    		Optional<Student> op=Optional.ofNullable(null);
    		Optional<Integer> map = op.map((e)->e.getAge());
    		System.out.println(map);//Optional.empty
    		
    		Optional<Student> op1=Optional.ofNullable(new Student("丽丽"));
    		Optional<String> map1 = op1.map((e)->e.getName());
    		System.out.println(map1);//Optional[丽丽]
    
    	}
    	@Test
    	public void test04(){
    		Optional< Student> op=Optional.ofNullable(new Student("王丽"));
    		Student orElseGet = op.orElseGet(()->{
    			Student s=new Student("莉莉",12,"ss");
    			return s;
    		});
    		System.out.println(orElseGet);//Student [getName()=王丽, getAge()=0, getSex()=null]
    		Optional< Student> op2=Optional.ofNullable(null);
    		Student orElseGet2 = op2.orElseGet(()->{
    			Student s=new Student("莉莉",12,"ss");
    			return s;
    		});
    		System.out.println(orElseGet2);//Student [getName()=莉莉, getAge()=12, getSex()=ss]
    	}
    	
    	@Test
    	public void test03(){
    		Student s=null;
    		Optional<Student> op2 = Optional.ofNullable(s);
    		System.out.println("op2==="+op2.isPresent());
    		if(!op2.isPresent()){
    			System.out.println(op2.orElse(new Student()));
    		}
    		/**
    		 *
    Student [getName()=null, getAge()=0, getSex()=null]
    		 */
    		
    	}
    	
    	@Test
    	public void test02(){
    	    Student s=null;
    	   Optional<Student> op1 = Optional.ofNullable(s);
    		//System.out.println(op1.get());//null
    		System.out.println(op1.orElse(new Student()));
    	}
    	
    	@Test
    	public void test01(){
    		Optional<Student> of = Optional.of(new Student());
    	    System.out.println("op"+of.get());
    	}
       总结:使用Optional能更好避免空指针的出现,虽然说还得写代码进行判断,但无疑这个容器类可以使我们少写if,else,增强了代码可读性(讲真if我是不喜欢的),和Lambda也可以在一起使用,在进行复杂自定对象获取做默认的时候也简化了代码。
    展开全文
  • Optional是个好东西,你会用么?(全面深度解析)

    万次阅读 多人点赞 2020-03-20 11:29:45
    从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)这个异常就不多说了,肯定是每个 Java 程序员都非常了解的异常。Optional 的完整路径是...

    写在前面

    从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)这个异常就不多说了,肯定是每个 Java 程序员都非常了解的异常。Optional 的完整路径是 java.util.Optional,使用它是为了避免代码中的 if (obj != null) { } 这样范式的代码,可以采用链式编程的风格。而且通过 Optional 中提供的 filter 方法可以判断对象是否符合条件,在符合条件的情况下才会返回,map 方法可以在返回对象前修改对象中的属性。如果觉得有所收获,记得点个关注和点个赞哦

    Optional用处

    本质上,Optional是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。我们要知道,Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。但是 Optional 的意义显然不止于此。我们知道,任何访问对象方法或属性的调用都可能导致 NullPointerException,在这里,我举个简单的例子来说明一下

    String result = test.getName().getTime().getNum().getAnswer();
    

    在上面的这个代码中,如果我们需要确保不触发异常,就得在访问每一个值之前对其进行明确地检查,就是使用if else对test等值进行判断是否为null,这很容易就变得冗长,难以维护。为了简化这个过程,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,并鼓励程序员写更干净的代码。Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
    在这里插入图片描述

    Optional的构造函数

    Optional 的三种构造方式:Optional.of(obj)Optional.ofNullable(obj) 和明确的 Optional.empty()

    • Optional.of(obj):它要求传入的 obj 不能是 null 值的, 否则直接报NullPointerException 异常。
    • Optional.ofNullable(obj):它以一种智能的,宽容的方式来构造一个 Optional 实例。来者不拒,传 null 进到就得到 Optional.empty(),非 null 就调用 Optional.of(obj).
    • Optional.empty():返回一个空的 Optional 对象

    Optional的常用函数

    • of:为非null的值创建一个Optional。of方法通过工厂方法创建Optional类。需要注意的是,创建对象时传入的参数不能为null。如果传入参数为null,则抛出NullPointerException。因此不经常用。
    • ofNullable:为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。
    • isPresent:如果值存在返回true,否则返回false。
    • ifPresent:如果Optional实例有值则为其调用consumer,否则不做处理
    • get:如果Optional有值则将其返回,否则抛出NoSuchElementException。因此也不经常用。
    • orElse:如果有值则将其返回,否则返回指定的其它值。
    • orElseGet:orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值
    • orElseThrow:如果有值则将其返回,否则抛出supplier接口创建的异常。
    • filter:如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。
    • map:如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。
    • flatMap:如果有值,为其执行mapping函数返回Optional类型返回值,否则返回空Optional。

    Optional 应该怎样用

    在使用 Optional 的时候需要考虑一些事情,以决定什么时候怎样使用它。重要的一点是 Optional 不是 Serializable。因此,它不应该用作类的字段。如果你需要序列化的对象包含 Optional 值,Jackson 库支持把 Optional 当作普通对象。也就是说,Jackson 会把空对象看作 null,而有值的对象则把其值看作对应域的值。这个功能在 jackson-modules-java8 项目中。Optional 主要用作返回类型,在获取到这个类型的实例后,如果它有值,你可以取得这个值,否则可以进行一些替代行为。Optional 类可以将其与流或其它返回 Optional 的方法结合,以构建流畅的API。我们来看一个示例,我们不使用Optional写代码是这样的

    public String getName(User user){
    	if(user == null){
    		return "Unknown";
    	}else return user.name();
    }
    

    接着我们来改造一下上面的代码,使用Optional来改造,我们先来举一个Optional滥用,没有达到流畅的链式API,反而复杂的例子,如下

    public String getName(User user){
    	Optional<User> u = Optional.ofNullable(user);
    	if(!u.isPresent()){
    		return "Unknown";
    	}else return u.get().name();
    }
    

    这样改写非但不简洁,而且其操作还是和第一段代码一样。无非就是用isPresent方法来替代原先user==null。这样的改写并不是Optional正确的用法,我们再来改写一次。

    public String getName(User user){
    	return Optional.ofNullable(user)
    							.map(u -> u.name)
    							.orElse("Unknown");
    }
    

    这样才是正确使用Optional的姿势。那么按照这种思路,我们可以安心的进行链式调用,而不是一层层判断了。当然,我们还可以通过getter方式,对代码进行进一步缩减(前提是User要有getter方法哦),如下

    String result = Optional.ofNullable(user)
    	.flatMap(User::getAddress)
    	.flatMap(Address::getCountry)
    	.map(Country::getIsocode)
    	.orElse("default");
    

    Optional最佳实践

    首先我们先上一张图,来简述一下Optional的使用时机
    在这里插入图片描述

    • 避免使用Optional.isPresent()来检查实例是否存在(上面的举例中提到过),因为这种方式和null != obj没有区别,这样用就没什么意义了。
    • 避免使用Optional.get()方式来获取实例对象,因为使用前需要使用Optional.isPresent()来检查实例是否存在,否则会出现NoSuchElementException异常问题。所以使用orElse(),orElseGet(),orElseThrow()获得你的结果

    这里要说明一下的是orElse(…)是急切计算,意味着类似下面代码:

    Optional<Dog> optionalDog = fetchOptionalDog();
    optionalDog
     .map(this::printUserAndReturnUser)
     .orElse(this::printVoidAndReturnUser)
    

    如果值存在则将执行两个方法,如果值不存在,则仅执行最后一个方法。为了处理这些情况,我们可以使用方法orElseGet(),它将supplier 作为参数,并且是惰性计算的。

    • 避免使用Optional作为类或者实例的属性,而应该在返回值中用来包装返回实例对象。
    • 避免使用Optional作为方法的参数,原因同3。
    • 不要将null赋给Optional
    • 只有每当结果不确定时,使用Optional作为返回类型,从某种意义上讲,这是使用Optional的唯一好地方,用java官方的话讲就是:我们的目的是为库方法的返回类型提供一种有限的机制,其中需要一种明确的方式来表示“无结果”,并且对于这样的方法使用null 绝对可能导致错误。
    • 不要害怕使用map和filter,有一些值得遵循的一般开发实践称为SLA-p:Single Layer of Abstraction字母的第一个大写。下面是需要被重构代码到重构的代码

    示例一

    Dog dog = fetchSomeVaraible();
    String dogString = dogToString(dog);
    public String dogToString(Dog dog){
     if(dog == null){
       return "DOG'd name is : " + dog.getName();
     } else { 
       return "CAT";
     }
    }
    //上面代码重构到下面代码
    Optional<Dog> dog = fetchDogIfExists();
    String dogsName = dog
     .map(this::convertToDog)
     .orElseGet(this::convertToCat)
    
    public void convertToDog(Dog dog){
       return "DOG'd name is : " + dog.getName();
    }
    
    public void convertToCat(){
       return "CAT";
    }
    

    示例二

    Dog dog = fetchDog();
    if(optionalDog != null && optionalDog.isBigDog()){
      doBlaBlaBla(optionalDog);
    }
    //上面代码重构到下面代码
    Optional<Dog> optionalDog = fetchOptionalDog();
    optionalDog
     .filter(Dog::isBigDog)
     .ifPresent(this::doBlaBlaBla)
    
    • 不要为了链方法而使用optional。使用optional 时要注意的一件事是链式方法的诱惑。当我们像构建器模式一样链接方法时,事情可能看起来很漂亮。但并不总是等于更具可读性。所以不要这样做,它对性能不利,对可读性也不好。我们应尽可能避免使用null引用。
    Optional
     .ofNullable(someVariable)
     .ifPresent(this::blablabla)
    
    • 使所有表达式成为单行lambda。这是更普遍的规则,我认为也应该应用于流。但这篇文章是关于optional 。使用Optional 重要点是记住等式左边和右边一样重要,这里举个例子
    Optional
     .ofNullable(someVariable)
     .map(variable -> {
       try{
          return someREpozitory.findById(variable.getIdOfOtherObject());
       } catch (IOException e){
         LOGGER.error(e); 
         throw new RuntimeException(e); 
       }})
     .filter(variable -> { 
       if(variable.getSomeField1() != null){
         return true;
       } else if(variable.getSomeField2() != null){
         return false;   
       } else { 
         return true;
       }
      })
     .map((variable -> {
       try{
          return jsonMapper.toJson(variable);
       } catch (IOException e){
         LOGGER.error(e); 
         throw new RuntimeException(e); 
       }}))
     .map(String::trim)
     .orElseThrow(() -> new RuntimeException("something went horribly wrong."))
    

    上面那么冗长代码块可以使用方法替代:

    Optional
     .ofNullable(someVariable)
     .map(this::findOtherObject)
     .filter(this::isThisOtherObjectStale)
     .map(this::convertToJson)
     .map(String::trim)
     .orElseThrow(() -> new RuntimeException("something went horribly wrong."));
    
    展开全文
  • Optional使用(终于明白版)

    万次阅读 2019-10-08 17:23:35
    以前一直不懂Optional有啥用,感觉太无语了,Java8还把它当做一个噱头来宣传,最近终于发现它的用处了,当然不用函数式编程的话,是没感觉的; 举例:一个非洲的Zoo,提供add一个animal进来的功能,可是有可能是用...

    一:简介

    1. 以前一直不懂Optional有啥用,感觉太无语了,Java8还把它当做一个噱头来宣传,最近终于发现它的用处了,当然不用函数式编程的话,是没感觉的;
    2. 举例:一个非洲的Zoo,提供add一个animal进来的功能,可是有可能是用Future来捕捉动物的,也就是说可能没有catch到animal,但是为了防止以后使用的时候,有NPE错误,只有做判断;
    3. 个人觉得Optional实现的功能,有很多替代方案,if-else、三目等都可以;但Optional是用于函数式的一个整体中的一环,让函数式更流畅
    • a)不使用Optional的版本,提变量,判空,必不可少,很繁琐
    List<Animal> zoo = new ArrayList<>();
    
    Animal animal = manCatch();
        if(animal != null){
            zoo.add(animal);
        }
    
    • b) 使用Optional 和函数式编程,一行搞定,而且像说话一样
    List<Animal> zoo = new ArrayList<>();
    
        manCatch().ifPresent(zoo::add);
    

    二:Optional方法介绍(篇幅原因,把实现隐藏)

    1. Optional绝不仅仅是Null的一层封装而已,它提供了
    public final class Optional<T> {
        //Null指针的封装
        private static final java.util.Optional<?> EMPTY = new java.util.Optional<>();
        //内部包含的值对象
        private final T value;
        private Optional() ;
        //返回EMPTY对象
        public static<T> java.util.Optional<T> empty() ;
        //构造函数,但是value为null,会报NPE
        private Optional(T value);
        //静态工厂方法,但是value为null,会报NPE
        public static <T> java.util.Optional<T> of(T value);
        //静态工厂方法,value可以为null
        public static <T> java.util.Optional<T> ofNullable(T value) ;
        //获取value,但是value为null,会报NoSuchElementException
        public T get() ;
        //返回value是否为null
        public boolean isPresent();
        //如果value不为null,则执行consumer式的函数,为null不做事
        public void ifPresent(Consumer<? super T> consumer) ;
         //过滤,如果value不为null,则根据条件过滤,为null不做事
        public java.util.Optional<T> filter(Predicate<? super T> predicate) ;
         //转换,在其外面封装Optional,如果value不为null,则map转换,为null不做事
        public<U> java.util.Optional<U> map(Function<? super T, ? extends U> mapper);
         //转换,如果value不为null,则map转换,为null不做事
        public<U> java.util.Optional<U> flatMap(Function<? super T, java.util.Optional<U>> mapper) ;
        //value为null时,默认提供other值
        public T orElse(T other);
          //value为null时,默认提供other值
        public T orElseGet(Supplier<? extends T> other);
          //value为null时,默认提供other值
        public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) ;
    }
    
    1. map和flatMap方法
      Optional的map和flatMap方法,封装了判空的逻辑,所以可以直接使用,流式,很方便
     public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
            Objects.requireNonNull(mapper);
            if (!isPresent())
                return empty();
            else {
                return Optional.ofNullable(mapper.apply(value));
            }
        }
    
    展开全文
  • Java8中Optional详解

    2019-08-22 21:52:30
    前言2.Optional介绍3.创建Optional3.1empty3.2of3.3ofNullable4.获取Optional的值4.1get()5.检查Optional是否有值5.1isPresent()5.2ifPresent()6.filter7.map8.flatMap9.返回默认值9.1orElse9.2orElseGet9.3...


    Optional的使用

    1.前言

    public class User {
    	private Address address;
    	
    	public Address getAddress() {
    		return address;
    	}
    }
    
    public class Address {
    	private Country country;
    
    	public Country getCountry() {
    		return country;
    	}
    }
    
    public class Country {
    	private String cityName;
    
    	public String getCityName() {
    		return cityName;
    	}
    }
    

    在Java 8之前,任何访问对象方法或属性的调用都可能导致NullPointerException:

    String cityName = user.getAddress().getCountry().getCityName();
    

    如果需要确保不触发异常,就得在访问每一个值之前对其进行明确地检查:

    if (user != null) {
        Address address = user.getAddress();
        if (address != null) {
            Country country = address.getCountry();
            if (country != null) {
                String cityName = country.getCityName();
            }
        }
    }
    

    这很容易就变得冗长,难以维护。为了简化这个过程,使用Optional类进行操作。

    2.Optional介绍

    可能包含也可能不包含非null值的容器对象。如果一个值存在,isPresent()将返回true并且get()将返回其值。

    提供了依赖于是否存在包含值的其他方法,例如orElse()(如果值不存在则返回默认值)和ifPresent()(如果值存在则执行代码块)。
    这是一个基于值的类;在Optional实例上使用标识敏感操作(包括引用相等(==),标识哈希码或同步)可能会产生不可预知的结果,应该避免使用。

    序号 修饰符和类型 方法和描述
    1 static <T> Optional<T> empty()返回一个空Optional实例。
    2 boolean equals(Object obj)判断其它对象是否"等于"此Optional。
    3 Optional<T> filter(Predicate<? super T> predicate)如果存在值,并且值与给定谓词匹配,则返回Optional描述该值的值,否则返回空Optional
    4 <U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)如果存在值,则将提供的Optional-bearing映射函数应用于该值,返回该结果,否则返回空 Optional
    5 T get()如果此Optional中存在值,则返回该值,否则抛出NoSuchElementException
    6 int hashCode()返回当前值的哈希码值(如果有),如果不存在值,则返回0(零)。
    7 void ifPresent(Consumer<? super T> consumer)如果存在值,则使用值调用指定的消费者,否则不执行任何操作。
    8 boolean isPresent()如果存在值则返回true,否则返回false
    9 <U> Optional<U> map(Function<? super T,? extends U> mapper)如果存在值,则将提供的映射函数应用于该值,如果结果为非null,则返回Optional描述结果的值。
    10 static <T> Optional<T> of(T value)返回一个具有指定的当前非null值的Optional
    11 static <T> Optional<T> ofNullable(T value)如果为非null,返回Optional描述指定值的值,否则返回空Optional
    12 T orElse(T other)如果存在则返回值,否则返回other
    13 T orElseGet(Supplier<? extends T> other)如果存在返回该值,否则调用other并返回该调用的结果。
    14 <X extends Throwable>T orElseThrow(Supplier<? extends X> exceptionSupplier)如果存在则返回包含的值,否则抛出由提供的Supplier供应商创建的异常。
    15 String toString()返回此Optional的非空字符串表示形式,适用于调试。

    OptionalIntOptionalDoubleOptionalLong分别表示对int、double和long基础数据类型的操作。

    3.创建Optional

    3.1empty

    返回一个空Optional实例。此Optional没有值。

    注意: 尽管这样做很有诱惑力,但是要避免测试对象是否为空通过将==Option.empty()返回的实例进行比较。不能保证它是单例的。使用isPresent()替代。

    即:通过isPresent()判断对象是否为空。

    Optional<User> empty = Optional.empty();
    

    3.2of

    返回具有指定的当前非null值的Optional。如果值为null则抛出NullPointerException

    Optional<User> userOptional = Optional.of(null);
    

    3.3ofNullable

    如果为非null,返回描述指定值的Optional,否则返回空Optional。

    如果对象可能是null也可能是非null,应该使用ofNullable()。

    Optional<User> userOptional = Optional.ofNullable(null);
    

    4.获取Optional的值

    4.1get()

    如果此Optional中存在值,则返回该值,否则抛出NoSuchElementException

    Optional<User> userOptional = Optional.ofNullable(null);
    if (userOptional.isPresent()) {
    	User user = userOptional.get();
    }
    

    5.检查Optional是否有值

    5.1isPresent()

    如果存在值,则返回true,否则返回false。

    Optional<User> userOptional = Optional.ofNullable(null);
    boolean isPresent = userOptional.isPresent();
    

    5.2ifPresent()

    如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。

    Optional<User> userOptional = Optional.ofNullable(null);
    userOptional.ifPresent(user -> System.out.println(user.getAddress()));
    

    6.filter

    如果存在值,并且值与给定谓词匹配,则返回描述该值的Optional,否则返回空Optional

    Optional<User> userOptional = Optional.ofNullable(null);
    Optional<User> result = userOptional.filter(user -> user.getAddress() != null);
    

    7.map

    如果存在值,则将提供的映射函数应用于该值,如果结果为非null,则返回描述结果的Optional。否则返回空Optional

    注意: 此方法支持对optional值进行后处理,而无需显式检查返回状态。例如,以下代码遍历文件名流,选择一个尚未处理的文件名,然后打开该文件,返回 Optional<FileInputStream>

    Optional<FileInputStream> fis = names.stream()
    									.filter(name -> !isProcessedYet(name))
    									.findFirst()
    									.map(name -> new FileInputStream(name));
    

    在这里,findFirst返回一个Optional<String>,然后map返回一个所需文件的Optional<FileInputStream>(如果存在)。

    Optional<User> userOptional = Optional.ofNullable(null);
    Optional<Address> address = userOptional.map(User::getAddress);
    Optional<Country> country = address.map(Address::getCountry);
    

    使用map进行链式调用

    String result = Optional.ofNullable(new User())
                    .map(User::getAddress)
                    .map(Address::getCountry)
                    .map(Country::getCityName)
                    .orElse("上海");
    System.out.println(result);
    
    // 上海
    

    如果属性值以Optional封装

    public class User {
        private Optional<Address> address;
    
        public Optional<Address> getAddress() {
            return address;
        }
    }
    
    public class Address {
        private Optional<Country> country;
    
        public Optional<Country> getCountry() {
            return country;
        }
    }
    
    public class Country {
        private String cityName;
    
        public String getCityName() {
            return cityName;
        }
    }
    
    Optional<User> userOptional = Optional.ofNullable(null);
    Optional<Optional<Address>> address = userOptional.map(User::getAddress);
    

    可以看出,map返回的是包装原结果类型的Optional类型。

    8.flatMap

    如果存在值,则将提供的Optional-bearing映射函数应用于该值,返回该结果,否则返回空Optional。这个方法类似于map(Function),但提供的映射器是一个结果已经是Optional的映射器,如果被调用,flatMap不会附加一个Optional

    注意:和map的区别是不会附加一个Optional

    Optional<String> stringOptional = Optional.ofNullable("hello")
    		.flatMap(a -> Optional.ofNullable(a + " world!"));
    System.out.println(stringOptional.get());
    
    // hello world!
    

    如果属性值以Optional封装(参见map)

    User user = null;
    String cityName = Optional.ofNullable(user)
    		.flatMap(User::getAddress)
            .flatMap(Address::getCountry)
            .map(Country::getCityName).orElse("上海");
    System.out.println(cityName);
    
    // 上海
    

    值得注意的是,一些博客并没有很详细的说明flatMap和map到底有什么区别,上面的例子如果改成这样

    User user = new User();
    String cityName = Optional.ofNullable(user)
    		.flatMap(User::getAddress)
            .flatMap(Address::getCountry)
            .map(Country::getCityName).orElse("上海");
    System.out.println(cityName);
    

    会报空指针异常java.lang.NullPointerException

    public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Optional.ofNullable(mapper.apply(value));
        }
    }
    
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if (!isPresent())
            return empty();
        else {
            return Objects.requireNonNull(mapper.apply(value));
        }
    }
    

    对比map和flatMap的源码,map返回的是Optional.ofNullable包装的U,而flatMap返回的是Objects.requireNonNull包装的Optional<U>,如果mapper.apply(value)的执行结果为null,那么flatMap就会抛出NullPointerException

    上面的例子也验证了这一点,而且使用flatMap改变原有实体类属性的类型,不符合编程习惯不说,并不能解决链式调用中某一环节出现NullPointerException的情况。

    如果只改变原有get方法的返回值类型为Optional,则使用flatMap不会报错。

    public class User {
        private Address address;
    
        public Optional<Address> getAddress() {
            return Optional.ofNullable(address);
        }
    }
    
    public class Address {
        private Country country;
    
        public Optional<Country> getCountry() {
            return Optional.ofNullable(country);
        }
    }
    
    public class Country {
        private String cityName;
    
        public String getCityName() {
            return cityName;
        }
    }
    

    所以,推荐使用map处理链式调用的情况

    9.返回默认值

    9.1orElse

    如果存在则返回值,否则返回other

    String s = null;
    String str = Optional.ofNullable(s).orElse("default");
    System.out.println(str);
    
    // default
    

    9.2orElseGet

    如果存在则返回值,否则调用other并返回该调用的结果。

    注意: 如果值不存在且other为null则抛出NullPointerException

    String s = null;
    String s1 = Optional.ofNullable(s).orElseGet(() -> null);
    System.out.println(s1);
    String s2 = Optional.ofNullable(s).orElseGet(null);
    System.out.println(s2);
    
    // null
    // java.lang.NullPointerException
    

    9.3orElseThrow

    如果存在返回包含的值,否则抛出由提供的供应商创建的异常。

    注意: 具有空参数列表的异常构造函数的方法引用可以用作供应商。例如, IllegalStateException::new

    String orElseThrow = Optional.ofNullable(s).orElseThrow(IllegalArgumentException::new);
    System.out.println(orElseThrow);
    

    这个方法丰富了语义,可以决定抛出什么样的异常。

    10.orElse和orElseGet的不同之处

    对象为空时两者的行为:

    private static User createNewUser() {
        System.out.println("Creating New User");
        return new User();
    }
        
    User user = null;
    System.out.println("Using orElse");
    User result1 = Optional.ofNullable(user).orElse(createNewUser());
    System.out.println("Using orElseGet");
    User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
    
    // Using orElse
    // Creating New User
    // Using orElseGet
    // Creating New User
    

    当对象为空而返回默认对象时,行为并无差异。

    对象不为空时两者的行为:

    User user = new User();
    System.out.println("Using orElse");
    User result1 = Optional.ofNullable(user).orElse(createNewUser());
    System.out.println("Using orElseGet");
    User result2 = Optional.ofNullable(user).orElseGet(() -> createNewUser());
    
    // Using orElse
    // Creating New User
    // Using orElseGet
    

    两个Optional对象都包含非空值,两个方法都会返回对应的非空值。不过,orElse()方法仍然创建了User对象。与之相反,orElseGet()方法不创建User对象。

    private static String getString() {
        System.out.println("调用我了");
        return "bbb";
    }
    
    String s1 = Optional.ofNullable("aaa").orElse(getString());
    System.out.println(s1);
    
    // 调用我了
    // aaa
    

    在执行较密集的调用时,比如调用Web服务或数据查询,这个差异会对性能产生重大影响

    11.Optional增强

    Java 9为Optional类增加了三个方法:ifPresentOrElse()、or()和stream()。

    11.1ifPresentOrElse

    ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction)
    如果存在值,则使用该值执行给定操作,否则执行给定的基于空值的操作。

    注意: 如果存在值且给定的操作是null,或者没有值且给定的基于空值的操作是null,则抛出NullPointerException

    如果在有值的时候执行某个操作,或者只是跟踪是否定义了某个值,那么这个方法非常有用:

    Optional.ofNullable(null).ifPresentOrElse(s -> System.out.println(s),
                    () -> System.out.println("值不存在"));
    

    11.2or

    如果存在值,则返回描述该值的Optional,否则返回由Supplier函数生成的Optional。
    注意: 如果提供函数是null或产生null结果,则抛出NullPointerException

    String s= null;
    Optional<String> or = Optional.ofNullable(s).or(() -> Optional.of("值不存在"));
    

    11.3stream

    如果存在值,则返回仅包含该值的顺序Stream,否则返回空Stream。
    注意:
    此方法可用于将Stream的optional元素转换为现值元素的Stream:

    Stream<Optional<T>> os = ..
    Stream<T> s = os.flatMap(Optional::stream)
    
    String s= null;
    Stream<String> stream = Optional.ofNullable(s).stream();
    

    11.4orElseThrow

    Java 10增加了orElseThrow方法

    如果值存在则返回该值,否则抛出NoSuchElementException。

    String s= null;
    Optional.ofNullable(s).orElseThrow();
    

    11.5isEmpty

    Java 11增加了isEmpty方法

    如果值不存在,返回true,否则返回false。

    String s= null;
    boolean isEmpty = Optional.ofNullable(s).isEmpty();
    

    本文参考:
    理解、学习与使用 JAVA 中的 OPTIONAL
    Optional (Java Platform SE 8 )

    展开全文
  • optional详解

    千次阅读 2019-09-19 11:00:47
    public class Test { public static void main(String[] args) { People people = new People();... Optional<People> p = Optional.ofNullable(people); String name = p.flatMap(People::getCa...
  • Java中Optional类的使用

    万次阅读 2018-06-21 14:50:20
    从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常。本质上,这是一个包含有可选值的包装类,这...
  • optional

    2018-07-05 17:35:18
    从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常。本质上,这是一个包含有可选值的包装类,这...
  • Optional简单使用

    2020-04-22 11:38:42
    前言 package com.hlj.Optional; import com.hlj.Optional.bean.User;...import java.util.Optional; import java.util.logging.Logger; /** * @Desc: * @Author HealerJean * @Date 2018...
  • JDK8新特性:使用Optional

    万次阅读 2018-06-26 15:56:39
    以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为...
  • Optional

    2019-11-17 14:37:36
    Optional java.util.Optional类是从 Java 8 引入的。 Optional 类主要解决空指针异常(NullPointerException) 的问题。 本质上,Optional 类一个包含有可选值的容器类,它既可以含有对象也可以为空。 示例1: ...
  • Optional处理空指针

    多人点赞 2019-11-14 23:38:07
    为了方便大家更好的处理NPE,Java8中引入了一个新类java.util.Optional。 其实 ,Optional 类的的使用只是提示你这里可能存在空值,需要特殊处理,并提供了一些特殊处理的方法。如果你把 Optional 类当作空指针的...
  • Java 8增加了很多新的工具类,这里要介绍的就是在开发中非常有用的一个jdk8新增的工具类,java.util.OptionalOptional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会...
  • Java 8 Optional 详细用法

    2020-08-27 12:10:04
    Optional 是一个对象容器,具有以下两个特点: 提示用户要注意该对象有可能为null 简化if else代码 二、使用介绍 1. 创建: Optional.empty(): 创建一个空的 Optional 实例 Optional.of(T t):创建一个 Optional ...
  • Java8 lambda用 Optional 处理非空操作

    千次阅读 2019-03-12 10:12:16
    Optional是Java8里面用避免空指针的,无论什么语言“空指针异常”总会是最困扰人的东西,老实说这很有可能就是逻辑错误。为了避免这样的错误,Java8建议使用Optional来培养[避免空指针]的好习惯。Optional的方法大纲...
  • Java8 Optional详解

    千次阅读 2018-05-11 00:01:38
    在Java8中新增了一个Optional类,官方描述是该类是一个容器对象,其中可能包含一个空或非空的值。如果存在一个值,isPresent()将返回true,get()将返回该值。 错误使用姿势 简单的根据描述,我们认为Optional...
  • boost::optional详解

    千次阅读 2020-06-04 14:41:43
    optional: optional库使用"容器"语义,包装了"可能产生无效值"的对象,实现了"未初始化"的概念. #include using namespace boost; "无意义"的值: 函数并不总能返回有效的返回值,很多时候函数可能返回"无意义"的值...
  • 话说Optional类是为了避免空指针而生的,那怎么个避免法呢?以我个人的理解,其实也就是它内部帮我们判断一下然后需要我们提供一个实例而已。 典型的案例: //1、创建一个空的Optional,stu对象肯定是不存在...
  • Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
  • Java8 : Optional 类,优雅判定null

    万次阅读 2019-02-17 15:16:35
    Optional不是对null关键字的一种替代,而是对于null判定提供了一种更加优雅的实现 NullPointException可以说是所有java程序员都遇到过的一个异常,虽然java从设计之初就力图让程序员脱离指针的苦海,但是指针确实...
  • Optional 对象的使用

    千次阅读 2018-10-15 10:31:32
    Optional&lt;Xxx&gt; Optional&lt;TUser&gt; ---------------------------- Optional.of(xxx) //xxx必须为非空 Optional.ofNullable(xxx) //xxx可以为空也可以为非空 Optional.empty() //参数包装成...
1 2 3 4 5 ... 20
收藏数 284,945
精华内容 113,978
关键字:

optional