java8---Optional容器

背景:

1965年,英国一位名为Tony Hoare的计算机科学家在设计ALGOL W语言时候提出了null引用的想法,ALGOL W是第一批在堆上分配记录类型的语言之一,Hoare选择用null这种代替空引用,其理由是简单,但是后来的很多语言都采用了类似的设计方式,比如我们熟悉的Java,但是这种方式在开发中为我们带来了巨大的麻烦,我们几乎无时不刻要判断某个对象是否为空,然后才能对其做一些其他的操作。

常规操作:

例子

新建三个类:分别是Person,Car,Insurance,他们的关系是依赖
Insurance依赖Car依赖Person

Insurance:

package com.tangbaobao.java8.option;

import lombok.Getter;

/**
 * @author tangxuejun
 * @version 2018/9/28 10:13 AM
 */
@Getter
public class Insurance {
    private String InsuranceName;
    private double price;
}

Car:

package com.tangbaobao.java8.option;

import lombok.Getter;

/**
 * @author tangxuejun
 * @version 2018/9/28 10:12 AM
 */
@Getter
public class Car {
	private String carName;
    private Insurance insurance;
}

Person:

package com.tangbaobao.java8.option;

import lombok.Getter;

import java.util.Optional;

/**
 * @author tangxuejun
 * @version 2018/9/28 10:12 AM
 */
@Getter
public class Person {
	private name;
    private Car car;
}

出现NullPointException

public class {
public static void main(String ...){
		Person p;
		System.out.println(p.getCar());
	}
}

这是因为调用了一个未在堆上分配内存空间的空引用,即person 为null

解决办法:

通常我们在拿取形参的时候都会判断这个参数是否不为null,类似这样:

public void displayPerson(Person person){
	if(person !=null){
		System.out.println(person);
	}
}

**如果是要调用最底层的类型,则要判断很多层,类似这样:

public void dispayInsuranceName(Person person){
	if(person !=null){
		if(person.getCar !=null){
			if(person.getCar.getInsurance()!=null){
				System.out.println(person.getCar.getInsurance().getInsuranceName());
			}
		}
	}
}

如果对象很多层是不是看着很挫?

Optional操作:

汲取了其他语言对null的处理,在java8中引入了java.util.Optional<T>类来对对象做一些简单的封装,Optional会将对象包进去,如果对象为空则用Optional提供的静态方法Optional.empty();返回一个空的Optional对象;

重构Person,Car,Insurance类

Insurance:

package com.tangbaobao.java8.option;

import lombok.Getter;

/**
 * @author tangxuejun
 * @version 2018/9/28 10:13 AM
 */
@Getter
public class Insurance {
	//对于Insurance来说,它的名称和价格都不应该不存在,所以不用Optional容器来包装
    private String InsuranceName;
    private double price;
}

Car:

package com.tangbaobao.java8.option;

import lombok.Getter;

/**
 * @author tangxuejun
 * @version 2018/9/28 10:12 AM
 */
@Getter
public class Car {
	private String carName;
	//汽车可能没有保险,所以用Optional容器来包装
    private Optional<Insurance> insurance;
}

Person:

package com.tangbaobao.java8.option;

import lombok.Getter;

import java.util.Optional;

/**
 * @author tangxuejun
 * @version 2018/9/28 10:12 AM
 */
@Getter
public class Person {
	private name;
	//人可能没有汽车,所以也用Optional容器来包装
    private Optional<Car> car;
}

重构获取保险名称的代码

在Option类中同样提供了map(Function)方法来对Optional容器做一些操作:

//获取Car
Optional<Person> person = Optional.empty();
Optional<Optional<Car>> car = person.map(Person::getCar);
//获取保险名称
Optional<Insurance> insurance = Optional.empty();
Optional<String> s = insurance.map(Insurance::getInsuranceName);

如上所示,可以用map方法获取Optional中的对象,但是获取的对象还是为Optional类型,所以要将上一层的Optiona去除,这时我们要用到流的扁平化中用到的flatMap,它可以将多个流中扁平化达到我们的效果;

Optional<Person> person = Optional.empty();
Optional<String> insuraceName = person.flatMap(Person::getCar)
        .flatMap(Car::getInsurance)
        .map(Insurance::getInsuranceName);

如果Person,Car,Insurance中的一个为空,都会返回一个空的Optional对象,不会报空指针异常,这样是不是很优雅了呢?

两个Optional对象组合:

public Insurance findChecpestInsurance(Optional<Car> car,Optional<Person> person){
	if(car.isPresent()&&person.isPresent()){
		return dosomething(p.get(),car.get());
	}
	return Optional.empty();
}
private Insurance dosomething(Person p, Car c) {
        return null;
}

以上的代码是不是很像判断null一样呢?接下来给出更加优雅的写法:

 public Optional<Insurance> findChecpestInsurance(Optional<Person> person, Optional<Car> car) {
        return person.flatMap(p -> car.map(c -> dosomething(p, c)));
    }
    private Insurance dosomething(Person p, Car c) {
        return null;
    }

如果其中一个为空,都不会往下执行;

Optional特性:

操作了map和flatMap()是不是觉得和Stream有些类似?的确,你可以将Optional理解为最多含有一个元素的Stream。
它还提供了过滤一些元素的方法:

//过滤名称为人寿保险的公司
    public void filterByName() {
        Optional<Insurance> insurance = Optional.of(new Insurance());
        Optional<String> name = insurance
                .filter(x -> x.getInsuranceName().equals("人寿保险"))
                .map(Insurance::getInsuranceName);
    }
### 回答1: Java8中的Optional类是一个容器对象,可以包含null或非null值。它提供了一种优雅的方式来处理null值,避免了NullPointerException异常的出现。Optional类可以用于返回值、方法参数和实例变量等场景中,使代码更加简洁、清晰和安全。使用Optional类可以使代码更加健壮,减少了代码中的null检查和异常处理,提高了代码的可读性和可维护性。 ### 回答2: Optional类是Java 8中新引入的一个类,它的主要作用是在避免NullPointerException的情况下将null值返回给调用者。这个类是一个容器对象,它可以保存非空的对象,也可以保存空值(null)。 Optional类提供了通过判断一个对象是否为空来避免空指针异常的方式。它可以在代码中替换传统的null判断,这样可以更加方便地编写代码,并且可以使代码更加健壮。 在Java中,如果一个方法返回值为null,那么在调用该方法返回值的时候,会有可能抛出NullPointerException异常。而Optional类的出现可以帮助我们避免这种情况的出现,在调用Optional类的get()方法时,如果Optional类中保存的对象不为null,就会返回该对象,否则抛出一个NoSuchElementException异常。 Optional类还提供了一些方法来简化代码,比如orElse()方法,如果Optional类中保存的对象不为null,则返回该对象,否则返回指定的default值。还有ifPresent()方法,当Optional类中保存的对象不为null时,会执行指定的代码,否则不执行。 总之,Optional类是Java 8中一个很有用的类,它可以帮助我们更加方便地处理null值,避免空指针异常的出现,并且可以简化代码。但是需要注意的是,不应该滥用Optional类,因为它并不是完美的解决方案,有时候需要对null值进行特殊处理。 ### 回答3: Java 8在语言层面上增加了一个新的类:Optional。这是一个特殊的容器对象,可以包含一个null或非null的值。 Optional的目的是解决Java中的null引用问题。在Java中,如果一个变量被赋值为null,而我们试图调用该变量所对应的方法,那么就会出现NullPointerException异常。 使用Optional可以避免这种情况的发生。如果一个变量是Optional对象,那么我们必须显式地检查该对象是否包含非null的值,才能对其进行操作。这样,在我们试图调用该变量所对应的方法之前,就可以避免空指针异常的发生。 Optional类提供了很多方法来判断是否有值、获取值、如果没有值则返回默认值等等,使得我们可以更加方便地处理空值。 下面是一些Optional类提供的方法: 1. Optional.of(T value):创建一个包含非null值的Optional对象,如果T为null,则抛出NullPointerException异常。 2. Optional.ofNullable(T value):创建一个Optional对象,如果T为null,则该对象为空。 3. Optional.empty():创建一个空的Optional对象。 4. get():如果值存在,则返回该值,否则抛出异常。 5. orElse(T other):如果值存在,则返回该值,否则返回其他默认值。 6. isPresent():返回一个boolean类型的值,表示该Optional对象是否包含值。 7. ifPresent(Consumer<? super T> consumer):如果该Optional对象包含值,则对该值执行给定的操作。 在编写Java程序时,我们应该始终努力避免使用null值。使用Optional类,可以使得我们的代码更加健壮、可读性更强。但是,过多地使用Optional可能会导致代码过于冗长,所以在使用的过程中需要权衡利弊。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值