内容来自《 java8实战 》,本篇文章内容均为非盈利,旨为方便自己查询、总结备份、开源分享。如有侵权请告知,马上删除。
书籍购买地址:java8实战
-
如下代码
public class Person {
private Car car;
public Car getCar() {
return car;
}
}
public class Car {
private Insurance insurance;
public Insurance getInsurance() {
return insurance;
}
}
public class Insurance{
private String name;
public String getName() {
return name;
}
}
//将要使用的代码
public String getCarInsuranceName(Person person){
return person.getCar().getInsurance().getName();
}
-
如上代码如果使用,如果某个Person没有车,那么就会引发空指针异常,在平常我们使用if来去判断的,比如
public String getCarInsuranceName(Person person){
if (null != person){
Car car = person.getCar();
if (null != car){
Insurance insurance = car.getInsurance();
if (insurance != null) {
return insurance.getName();
}
}
}
return "UnKnow";
}
-
或者更容易读的是这样的,避免了if的嵌套难以阅读
public String getCarInsuranceName(Person person){
if (person == null) {
return "UnKnow";
}
Car car = person.getCar();
if (car == null){
return "UnKnow";
}
Insurance insurance = car.getInsurance();
if (insurance == null) {
return "UnKnow";
}
return insurance.getName();
}
- 如上null的解决办法使用中的,并且不容易阅读,java8使用了Optional来解决null问题
![markdown_img_paste_20181122155551525 markdown_img_paste_20181122155551525]()
- Optional只能包含一个对象,对象存在的时候,Optional只是对对象的简单封装,如果没有对象,那么缺失的值被建模成一个空的Optional对象,有方法Optional.empty()返回
Optional的创建
- 空对象:
Optional.empty()
- 依靠一个非空对象创建Optional:
Optional.of(notnullobj),如果notnullobj是一个空对象,那么就会抛出空指针异常
- 可接受null对象的Optional:
Optional.ofNullable(car),car对象可以是空对象也可以不是空对象,如果是空对象则得到一个空的Optional
使用map从Optional中提取和转换值
String name = null;
if (insurance != null){
name = insurance.getName();
}
-
如上是原来的提取的代码,先判断在取值,避免空指针,如下使用Optional
Optional<String> name = Optional.ofNullable(insurance).map(Insurance::getName);
- map函数会应用于流的每个元素上,然后返回name,可以把Optional看作是一个特殊的集合数据,至多包含一个元素,如果insurance包含值,那么就交给map处理,否则返回空Optional,就什么也不做
-
本文开头提到的这样一连串的调用,怎么用Optional解决呢?
//原来
public String getCarInsuranceName(Person person){
return person.getCar().getInsurance().getName();
}
public String getCarInsuranceName(Optional<Person> person){
person.map(Person::getCar)
.map(Car::getInsurance)
.map(Insurance::getName);
}
- 如上代码是编译通过不了的,因为person对象是一个Optional对象,那么他调用map将会返回一个Optional>,这显然是错误的
- 之前我们在Stream遇到同样的问题,当时是用flatMap解决的,在这同样适用,如下
public String getCarInsuranceName(Optional<Person> person){
return person.flatMap(Person::getCar)
.flatMap(Car::getInsurance)
.map(Insurance::getName)
.orElse("Unknow");
}
- 如上我们很清楚的就可以知道哪些对象可能是null,并且省去了if语句的平判断,在最后orElse:如果map得到的是null,那么就会有默认的UnKnow替代null,以防止发生空指针
Optional无法序列化
使用filter剔除特定的值
-
如果需要判断某个公司,那么我们需要这样的判断
Insurance insurance = ...;
if (null != insurance && "lalala".equals(insurance.getName())){
System.out.println("...");
}
-
使用filter方法
Optional<Insurance> insurance = null;
insurance.filter(i -> "lalala".equals(i.getName()))
.ifPresent(i -> System.out.println("..."));
- 如上的ifPresent方法是判断i是否是空值,不是空值就执行后面的输出,是空即什么都不做
异常与Optional对象
- String转换为Integer对象,如果转换错误就会爆数字格式化异常,我们必须try上异常以处理异常
-
需求:输入参数转换为int,然后返回该转换后的值,出错的话就返回0
public Integer StringParse(String str){
if (null == str) return 0;
try {
return Integer.parseInt(str);
}catch (NumberFormatException e){
return 0;
}
}
-
用Optional解决
public Optional<Integer> StringParse(String str){
try {
return Optional.of(Integer.parseInt(str));
}catch (NumberFormatException e){
return Optional.empty();
}
}
避免使用基本类型的Optional对象
- 对于之前的函数式接口,我们提到的如果基本类型比较多,那么就优先使用对应的基本类型的函数式接口,比如IntFunction,但是Optional不推荐使用OptionalInt等类似的基本类型对象,因为这些对象中并没有map和filter等方法