java 8 Optional解决空指针异常问题

         在写程序时,经常需要对创建的对象或属性进行null值判断,但是有时可能会疏忽没有对null进行判断,就会引发空指针问题,null值在程序设计语言中,是为了表示变量值的缺失;

          java8中引入了Optional,可以表示值的存在与不存在(null),对存在或不存在的变量值进行建模,并且可以避免空指针异常.

以下实例演示可以说明Optional可以很好解决类型T为null时的问题。

package com.xiaomifeng1010.rbacboot.common.util;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;

import java.util.Optional;
import java.util.function.Supplier;

/**
 * @author xiaomifeng1010
 * @version 1.0
 * @date: 2020/3/21 16:18
 */

public class Java8Optional {
    /**
     * 在java8之前如果要保存Info对象,需要做多层非空检查,多层if嵌套
     * @param info
     */
//    public void savaInfo(Info info){
//        if (info !=null){
//            if (info.getAddress() != null) {
                则保存info
//            }
//        }
//
//    }

    /**
     * 过多的退出语句
     * @param info
     */
//    public void savaInfo2(Info info){
//        if (info==null){
//            return;
//        }
//        if (info.getAddress()==null){
//            return;
//        }
//    }

//    Optional可以解决判断null问题

    /**
     * 创建Optional对象
     */
    public void createOptional(){
        //    创建一个空白的Optional
        Optional
optionalAddress=Optional.empty(); // 依据一个非空值创建Optional(new Address()不能为null) Optional
optionalAddress2=Optional.of(new Address()); // 可接受null值创建Optional(当new Address()为null时,调用empty()方法,创建一个空白Optional对象) Optional
getOptionalAddress3= Optional.ofNullable(new Address()); } /** * 使用map(同Stream API中的中间操作map)从optional对象中提取和转换值 */ public void mapToOptional(){ Optional
addressOptional=Optional.ofNullable(new Address("南京路","20号")); // 直接从Optional
中获取Address类中street属性 Optional street=addressOptional.map(Address::getStreet); } public void flatMapToOptional(){ Info info=new Info(); Optional infoOptional=Optional.of(info); // 再使用map就会报错,因为map转换输出的还是一个optional对象,会造成原本的optional里面存放optional对象 // infoOptional.map(info -> info.getOptionalAddress()); // 可以使用flatMap方法从Info类中获取Optional
,然后获取Address类型的street属性 Optional stringOptional=infoOptional.flatMap(Info::getOptionalAddress).map(Address::getStreet); System.out.println(stringOptional); } /** * 默认行为及解引用 optional对象 */ @Test public void defaultValue(){ Optional
addressOptional= Optional.ofNullable(null); // 获取街道名,如果无,则设置为"上海路" String street = addressOptional.map(Address::getStreet).orElse("上海路"); System.out.println(street); } public static void main(String[] args) { Info info=new Info(); info.setUsername("xiaomifeng1010"); info.setPassword("123456"); info.setAge(30); info.setOptionalAddress(Optional.of(new Address("广州路","12号"))); boolean present=info.getOptionalAddress().filter(address -> address. getDoor().contains("23")) // isPresent():如果存在值,则为true.不存在值,则为false .isPresent(); System.out.println(present); // address为null,过滤会报错,需要抛出异常,并处理 info.setOptionalAddress(Optional.empty()); Address address=null; try { address= info.getOptionalAddress().filter(address1 -> address1.getDoor().contains("34")) .orElseThrow(new Supplier() { @Override public Throwable get() { return new Exception("哎呀,出错了"); } }); } catch (Throwable throwable) { throwable.printStackTrace(); } // Info类中的年龄为30,不满足大于50,所以不会找到地址信息,输出“不存在” System.out.println(getSteet(Optional.of(info),50)); } public static String getSteet(Optional info,int minAge){ return info.filter(information -> information.getAge()>= minAge). flatMap(Info::getOptionalAddress) .map(Address::getStreet).orElse("不存在"); } } /** * 自定义一个类Info */ @Data class Info{ private String username; private String password; private Integer age; // private Address address; /** * 为了解决空指针问题(即Address可能为null的情况),创建Optional对象,当Address未赋值初始化, * 会生成一个empty(空白)的Optional对象,而不会产生null(可以允许Address对象缺失) * **/ Optional
optionalAddress; } /** * 住址对象 */ @Data @AllArgsConstructor @NoArgsConstructor class Address{ /** * 街道 */ private String street; /** * 门牌 */ private String door; }

Optional对应的常用方法:

方法 描述
empty 返回一个空的 Optional 实例
of 将指定值用 Optional 封装之后返回,如果该值为 null,则抛出一个 NullPointerException 异常
ofNullable 将指定值用 Optional 封装之后返回,如果该值为 null,则返回一个空的 Optional 对象
map(Function mapper)
如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
flatMap(Function> mapper)
与map 类似,要求返回值必须是Optional
filter 如果值存在并且满足提供的断言, 就返回包含该值的 Optional 对象;否则返回一个空的 Optional 对象
get 如果该值存在,将该值用 Optional 封装返回,否则抛出一个 NoSuchElementException 异常
public void ifPresent(Consumer consumer)
如果值存在,就执行使用该值的方法调用,否则什么也不做
public boolean isPresent()
如果值存在就返回 true,否则返回 false
orElse 如果有值则将其返回,否则返回一个默认值(即orElse中设置的值
orElseGet(Supplier other)
如果有值则将其返回,否则返回一个由指定的 Supplier 接口生成的值
public  T orElseThrow(Supplier exceptionSupplier) throws X
如果有值则将其返回,否则抛出一个由指定的 Supplier 接口生成的异常

 

 

 

你可能感兴趣的:(java基础,java,8新特性,java8,java基础,Optional)