当前位置: 首页 > 工具软件 > Optional > 使用案例 >

Java Optional容器判空处理

宋典
2023-12-01

1. Java判空概述

Java判空方式有很多多,可以if是否为null或者采用Objects.isNull或者Objects.nonNull,或者其他工具类等都可以,本身写法也没什么问题,代码可读性也高,可能有时候不够简洁,所以Java8推出的Optional方式实现同样的功能,更加简洁,但是可读性降低了,这个根据需要权衡使用吧。对于Optional容器本身也会抛出空指针,他是直接抛出,用于快速定位,尽量避免空指针。

2. Java判空方式

2.1 普通判空方式

Objects.isNull();
Objects.nonNull();
Object == null;
... ...

2.2 Optional判空方式

1.Optional数组测试方式


/**
 * 一、Optional 容器类:用于尽量避免空指针异常
 * Optional.of(T t) : 创建一个 Optional 实例
 * Optional.empty() : 创建一个空的 Optional 实例
 * Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则直接抛出异常
 * <p>
 * isPresent() : 判断是否包含值
 * orElse(T t) :  如果调用对象包含值,返回该值,否则返回t
 * orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
 * map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
 * flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
 */
public class TestOptional {

    @Test
    public void test7() {

        List<Integer> list = new ArrayList<Integer>() {{
            add( 1 );
            add( 2 );
            add( 3 );
        }};

        List<Object> objectList = null;
        // 如果list为null就获取orElse中的内容,可以有效避免空指针
        Optional.ofNullable( list ).orElse( new ArrayList<>() ).forEach( System.out::println );
        Optional.ofNullable( objectList ).orElse( new ArrayList<>() ).forEach( System.out::println );
        //下边就会抛出空指针
        objectList.forEach( System.out::println );
        //如果为null就会抛出指定异常,可以自定义异常
        Optional.ofNullable( objectList ).orElseThrow( NullPointerException::new );
        Optional.ofNullable( objectList ).orElseThrow( RuntimeException::new );
        
    }

    @Test
    public void test4() {
        Optional<Employee> op = Optional.of( new Employee( 101, "张三", 18, 9999.99 ) );
        //为null的时候也会空指针
        //Optional<Employee> op = Optional.of( null );

        Optional<String> op2 = op.map( Employee::getName );
        System.out.println( op2.get() );

        Optional<String> op3 = op.flatMap( (e) -> Optional.of( e.getName() ) );
        System.out.println( op3.get() );
    }

    @Test
    public void test3() {
        Optional<Employee> op = Optional.ofNullable( new Employee() );

        //有值就获取,否则不执行
        if (op.isPresent()) {
            System.out.println( op.get() );
        }

        //如果op有值就获取值,没有值就去orElse中的值
        Employee emp = op.orElse( new Employee( "张三" ) );
        System.out.println( emp );
        //如果op有值就获取值,没有值就去orElse中的值
        Employee emp2 = op.orElseGet( () -> new Employee() );
        System.out.println( emp2 );
    }

    @Test
    public void test2() {
        // 不允许为空,直接抛出空指针
        Optional<Employee> op1 = Optional.ofNullable( null );
        System.out.println( op1.get() );

        //允许为空,但是get的时候回抛出空指针
        Optional<Employee> op = Optional.empty();
        System.out.println( op.get() );
    }

    /**
     * Optional.ofNullable( null )也会抛出空指针
     * 它所表达的思想是这里会直接抛出空指针快速定位
     */
    @Test
    public void test1() {
        Optional<Employee> op = Optional.of( new Employee() );
        Employee emp = op.get();
        System.out.println( emp );
    }

    @Test
    public void test5() {
        Man man = new Man();

        String name = getGodnessName( man );
        System.out.println( name );
    }

    /**
     * 需求:获取一个男人心中女神的名字
     */
    public String getGodnessName(Man man) {
        if (man != null) {
            Godness g = man.getGod();

            if (g != null) {
                return g.getName();
            }
        }

        return "苍老师";
    }

    /**
     * 运用 Optional 的实体类
     */
    @Test
    public void test6() {
        Optional<Godness> godness = Optional.ofNullable( new Godness( "林志玲" ) );

        Optional<NewMan> op = Optional.ofNullable( new NewMan( godness ) );
        String name = getGodnessName2( op );
        System.out.println( name );
    }

    public String getGodnessName2(Optional<NewMan> man) {
        return man.orElse( new NewMan() )
                .getGodness()
                .orElse( new Godness( "苍老师" ) )
                .getName();
    }
}

2.Optional对象测试方式
TestOptional


/**
 * Optional避免空指针,采用默认值或者自定义抛出异常
 * 使用场景:多层对象嵌套取值
 * 
 * 
 **/
public class OptionalTest {

    @Test
    public void Test1() {
        // 正常情况,都不为null,都可以正常执行
        User user = User.builder().address( Address.builder()
                .country( Country.builder().countryName( "nj" )
                        .build() )
                .build() )
                .build();

        // user为null
        user = null;

        // Address 为null
        user = User.builder().address( null ).build();

        // country 为null
        user = User.builder().address( Address.builder()
                .country( null ).build() ).build();
        
        OptTest( user );

    }

    public void OptTest(User user) {

        // 第一种方式:存在空指针的风险,只要与一个对象为空就会空指针
        String countryName = user.getAddress().getCountry().getCountryName();
        System.out.println( "第一种方式:" + countryName );

        // 第二种方式:各种if判断避免了空指针,但是if层级太深,代码冗长
        if (user != null) {
            Address address = user.getAddress();
            if (address != null) {
                Country country = address.getCountry();
                if (country != null) {
                    String couName = country.getCountryName();
                    System.out.println( "第二种方式:" + couName );
                }
            }
        }

        // 第三种方式:代码简洁,避免空指针,武林那一步为空都会返回默认值
        String counName = Optional.ofNullable( user )
                .map( User::getAddress )
                .map( Address::getCountry )
                .map( Country::getCountryName )
                .orElse( "china" );
        System.out.println( "第三种方式:" + counName );

        // 第三种方式:代码简洁,避免空指针,武林那一步为空都会返回自定义异常
        String countryNameEx = Optional.ofNullable( user )
                .map( User::getAddress )
                .map( Address::getCountry )
                .map( Country::getCountryName )
                .orElseThrow( () -> new RuntimeException( "countryId is null" ) );
        System.out.println( "第四种方式:" + countryNameEx );
    }

}


user


/**
 * @author zrj
 * @version V1.0
 * @since 2020/11/20
 **/
@Data
@Builder
public class User {
    private Integer userId;

    private String userName;

    private Address address;
}

@Data
@Builder
public class Address {
    private Integer addressId;

    private String addressName;

    private Country country;
}

@Data
@Builder
public class Country {
    private Integer countryId;

    private String countryName;
}


 类似资料: