• Upgrading to Java 8——第三章 Optional and Similar Classes


      Java程序员对付空指针异常已经好多年了。在Java8中将有新的方式去处理他们。通过包装一个潜在的可能为null的类称为Optianal。

    在Java8中添加了the Optional, OptionalInt, OptionalLong 和 OptionalDouble 类来处理空指针异常(NullPointerExceptions)。

    在java.util的包中,有很多使用Lambda表达式和方法引用的范例类。

    这四个类是很相似的,Optional是它们当中最重要的类因为他可以用在任何类型上,其他的类只能各自用在integer,long和double上。

       Optional 是一个包含可能会为null的值的容器。你应该认识到,试图去一个null的引用去调用方法或是属性会发生NullPointerException异常。处理空指针异常不是很难,但是很乏味。

      考虑下面的代码,一个公司会有一个办公室,进而会有一个地址。为了简单起见,在这里地址有两个属性是街道和城市,这些所有的属性都可能为null。一个公司可能会没有办公室,一个地址可能没有完整的街道和城市的信息。

    class Company {
        private String name;
        private Office office;
    
        public Company(String name, Office office) {
        this.name = name;
        this.office = office;
        }
    
        public String getName() {
        return name;
        }
    
        public Office getOffice() {
        return office;
        }
    }
    
    class Office {
        private String id;
        private Address address;
    
        public Office(String id, Address address) {
        this.id = id;
        this.address = address;
        }
    
        public String getId() {
        return id;
        }
    
        public Address getAddress() {
        return address;
        }
    }
    
    class Address {
        private String street;
        private String city;
    
        public Address(String street, String city) {
        this.street = street;
        this.city = city;
        }
    
        public String getStreet() {
        return street;
        }
    
        public String getCity() {
        return city;
        }
    }
    
    public class OptionalDemo1 {
    
        public static void main(String[] args) {
        Address address1 = new Address(null, "New York");
        Office office1 = new Office("OF1", address1);
        Company company1 = new Company("Door Never Closed", office1);
    
        // What is the street address of company1?
        // In which city company1 is located?
        String streetAddress = null;
        String city = null;
        if (company1 != null) {
            Office office = company1.getOffice();
            if (office != null) {
            Address address = office.getAddress();
            if (address != null) {
                streetAddress = address.getStreet();
                city = address.getCity();
            }
            }
        }
        System.out.println("Street Name:" + streetAddress);
        System.out.println("City:" + city);
        }
    }

    OptionalDemo1类为了测试创建了Company实例去获取公司的街道地址,考虑到所有的属性可能为空,我们在调用方法前都做了非空的处理,就像下面的代码:

    if (company1 != null) {
                Office office = company1.getOffice();
    
                if (office != null) {
                    Address address = office.getAddress();
                    if (address != null) {
                        streetAddress = address.getStreet();
                        city = address.getCity();
                    }
                } 
            }

      这种代码既无聊也读起来遭罪。
      这个时候Optional能够帮助你,如果你决定用它,你需要把所有可能为null的属性全部用Optional包装起来。例如,Company类中的office属性应该是这样的:

    private Optional<Office> office;

      Address类中的city属性应该是这样的:

     private Optional<String> city;

    在重写上面的代码之前,先看下Optional类的一些方法:

    方法 描述
    empty   返回一个空的Optional类
    filter 如果一个值存在并且能供匹配给定的Prdicate接口,则返回Optiaonal描述的值,否则,返回一个空的Optional类    
    flatMap 如果值存在,应用指定的映射方法给这个值,返回Optional类描述的映射结果;如果值不存在,则返回一个空的Optional类
    get 如果值存在,则返回该值;否则,抛出NoSuchElementException异常。
    ifPresent 如果值存在,调用指定的Consumer接口用这个值。
    isPresent 如果值存在,返回true;否则,返回false。
    map 如果值存在,给它应用指定的映射方法。如果结果不为null,返回一个Optional类的描述结果。
    of 返回一个Optional描述的不为null的值。
    ofNullable 如果给定的值不为null,返回Optional描述的值,如果为null,返回空的Optional类。
    orElse 如果值存在,返回该值,否则返回指定的值。                                    

      

    这些方法很容易使用,把一个值包装在Optional类中,调用它的静态方法or或orNullable。如果你确定你包装的值不为null就用of方法。如果值可能潜在存在null就用ofNullable方法。相应的,empty静态方法返回一个空的Optional类,例如,一个没有值的Optional类。

      剩下的方法就来对Optional的处理。如果你想简单的检索一个值在Optional中,首先检查一个值是否存在,你可以使用isPresent 方法然后接着使用get方法。

    if (optional.isPresent()) {
        value = optional.get();
    }

    不管怎样,这很类似跟不用Optional处理null的情况,但这是个更好的方式。
      ifPresent方法接收一个Consumer函数式接口如果值存在的话会被调用,所以,如果想简单打印值,可以这样:

    optional.ifPresent(System.out::println);

      如果值存在,则什么都不会发生。

      flatMapfang方法应用一个映射方法并返回一个Optional描述的值,不止这些,它可以被级联调用,像下面这样检查以系列的null的情况:

    company1.flatMap(Company::getOffice)
            .flatMap(Office::getAddress)
            .flatMap(Address::getCity)
            .ifPresent(System.out::println);

    现在,我们用Optional类来重写OptionalDemo2类。
      OptionalInt, OptionalLong and OptionalDouble 有Optional的子集的方法。他们都有empty, ifPresent, isPresent, of需要一个原始类型。因为原始类型不能是null,所以没有ofNullable和get方法。取代的,OptionalInt有getAstInt方法,OptionalLong有getAsLong方法,OptiaonalDouble有getAsDouble方法。他们没有filter,flatMap和map方法。

  • 相关阅读:
    客户端相关知识学习(三)之Android原生与H5交互的实现
    客户端相关知识学习(二)之h5与原生app交互的原理
    nslookup基础用法
    十大渗透测试演练系统
    最新的windows xp sp3序列号(绝对可通过正版验证)
    Metasploit基础命令
    msf回退一步
    验证SMB登入
    Nmap使用指南(1)
    postgreSql基础命令及linux下postgreSql命令
  • 原文地址:https://www.cnblogs.com/IcanFixIt/p/4308821.html
Copyright © 2020-2023  润新知