Java8 Optional类的使用

初步认识:

  Java 8 中引入了一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是空指针异常(NullPointerException)。这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

  简单示例一:

  从前的写法:

public String getName(User user) {
    if (null == user) {
        return "未知用户";
    }
    return user.name;
}

  使用了Optional 类的写法:

public String getName(User user) {
    return Optional.ofNullable(user)
        .map(x -> x.name)
        .orElse("未知用户");
}
  简单示例二:

  从前的写法:

public String getName(King king) throws IllegalArgumentException {
    if (null != king) {
        King result = king.getResult();
        if (null != result) {
            User realKing = result.getKing();
            if (null != realKing) {
                return realKing.getName();
            }
        }
    }
    throw new IllegalArgumentException("本届海贼王尚未诞生!");
}

  使用了Optional 类的写法:

public String getName(King king) throws IllegalArgumentException {
    return Optional.ofNullable(king)
        .map(x -> x.getResult())
        .map(y -> y.getKing())
        .map(z -> z.getName())
        .orElseThrow(() -> new IllegalArgumentException("本届海贼王尚未诞生!"));
}

  看到这里,相信大家已经对Optional 类有了足够的兴趣,接下来我们就看看它的具体方法及使用。


具体使用:

  1、of:

    为非null的值创建一个Optional。(如果传入参数为null,则抛出NullPointerException)

@Test
public void testOf() {
	Optional<String> ofOptional = Optional.of("张三");
	Optional<String> nullOptional = Optional.of(null);
}
  2、ofNullable:

    为指定的值创建一个Optional,如果指定的值为null,则返回一个空的Optional。

@Test
public void testOfNullable() {
    Optional<String> nullOptional = Optional.ofNullable(null);
    System.out.println(nullOptional);

    Optional<String> ofNullableOptional = Optional.ofNullable("李四");
    System.out.println(ofNullableOptional);
}
  3、empty:

    创建一个空的Optional对象。

@Test
public void testEmpty() {
    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional);
}
  4、get:

    如果Optional对象中有值存在则返回此值。(如果没有值存在,则抛出NoSuchElementException)

@Test
public void testGet() {
    Optional<String> stringOptional = Optional.of("王五");
    System.out.println(stringOptional.get());

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.get());
}
  5、orElse:

    如果Optional实例有值则将其返回,否则返回orElse方法传入的参数。

@Test
public void testOrElse() {
    Optional<String> stringOptional = Optional.of("赵六");
    System.out.println(stringOptional.orElse("备用输出(赵六)"));

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.orElse("orElse(空)"));
}
  6、orElseGet:

    orElseGet与orElse方法类似,区别在于得到的默认值。orElse方法将传入的字符串作为默认值,orElseGet方法可以接受Supplier接口的实现用来生成默认值。

@Test
public void testOrElseGet() {
    Optional<String> stringOptional = Optional.of("孙七");
    System.out.println(stringOptional.orElseGet(() -> "孙七"));

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.orElseGet(() -> "orElseGet(空)"));
}
  7、orElseThrow:

    如果Optional实例有值则将其返回,否则抛出一个由指定的Supplier接口生成的异常。

@Test
public void testOrElseThrow() {
    Optional<String> stringOptional = Optional.of("钱八");
    System.out.println(stringOptional.orElseThrow(CustomException::new));

    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.orElseThrow(CustomException::new));
}
private static class CustomException extends RuntimeException {
    public CustomException() {
        super("自定义异常");
    }
    public CustomException(String message) {
        super(message);
    }
}
  8、filter:

    如果值存在并且满足断言条件返回包含该值的Optional,否则返回空Optional。

@Test
public void testFilter() {
    Optional<String> stringOptional = Optional.of("biggerthanfive");
    System.out.println(stringOptional.filter(e -> e.length() > 5).orElse("长度大于5"));

    stringOptional = Optional.of("oh");
    System.out.println(stringOptional.filter(e -> e.length() > 5).orElse("长度小于5"));
}

    注意:Optional中的filter方法和Stream中的filter方法是有点不一样的。Stream中的filter方法是对一堆元素进行过滤,而Optional中的filter方法只是对一个元素进行过滤,可以把Optional看成是最多只包含一个元素的Stream。

  9、map:

    如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。

@Test
public void testMap() {
    Optional<String> stringOptional = Optional.of("small");
    System.out.println(stringOptional.map(e -> e.toUpperCase()).orElse("大写转换失败"));

    stringOptional = Optional.empty();
    System.out.println(stringOptional.map(e -> e.toUpperCase()).orElse("大写转换失败"));
}
  10、flatMap:

    flatMap方法与map方法类似,区别在于mapping函数的返回值不同。map方法的mapping函数返回值可以是任何类型T,而flatMap方法的mapping函数必须是Optional。调用结束时,flatMap不会对结果用Optional封装。

@Test
public void testFlatMap() {
    Optional<String> stringOptional = Optional.of("刘九");
    System.out.println(stringOptional.flatMap(e -> Optional.of("卓十")).orElse("转换失败"));

    stringOptional = Optional.of("刘九");
    System.out.println(stringOptional.flatMap(e -> Optional.empty()).orElse("转换失败"));
}
  11、ifPresent:

    如果Optional实例有值则为其调用Consumer接口,否则不做处理。

@Test
public void testIfPresent() {
    Optional<String> stringOptional = Optional.of("萧十一");
    stringOptional.ifPresent(e -> System.out.println("我被执行了…………" + e));
}

  这里补充两段代码比较orElse与orElseGet的不同:
  12、值为null时,效果一样:

    

@Test
public void testdiffOne() {
    String str = null;
    log.info("Using orElse");
    String result1 = Optional.ofNullable(str).orElse(createNewString());
    log.info("Using orElseGet");
    String result2 = Optional.ofNullable(str).orElseGet(() -> createNewString());
}
private String createNewString() {
    log.info("Creating New String");
    return new String("新·字符串");
}
  13、值不为null时,使用orElseGet不会调用createNewString方法:

    

@Test
public void testdiffTwo() {
    String str = "不为null";
    log.info("Using orElse");
    String result1 = Optional.ofNullable(str).orElse(createNewString());
    log.info("Using orElseGet");
    String result2 = Optional.ofNullable(str).orElseGet(() -> createNewString());
}
private String createNewString() {
    log.info("Creating New String");
    return new String("新·字符串");
}

  一句话小结:使用 Optional 时尽量不直接调用 Optional.get() 方法,Optional.isPresent() 更应该被视为一个私有方法,应依赖于其他像 Optional.orElse(),Optional.orElseGet(),Optional.map() 等这样的方法。

  最后,Java 9 为 Optional 类添加了三个方法:or()、ifPresentOrElse() 和 stream()。有兴趣的朋友可以自行继续拓展,此处只做引出不再深入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值