hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

Jdk14都要出了,还不能运用 Optional文雅的处置惩罚空指针?

2019-11-18杂谈搜奇网49°c
A+ A-

1. 媒介

假如你没有处置惩罚过空指针,那末你不是一名真正的 Java 顺序员。


空指针确切会发生许多题目,我们常常遇到空的援用,然后又想从这个空的援用上去猎取其他的值,接着天经地义的遇到了 NullPointException。这是你能够会想,这报错很好处置惩罚,然后你看了眼报错行数,对比了下代码。脑海里霎时闪过 ”对对对,这里有能够为空“,然后加上 null check轻松处置惩罚。然则你不晓得这已是你处置惩罚的第多少个空指针非常了。

为了处理上面的题目,在 Java SE8 中引入了一个新类 java.util.Optional,这个类能够减缓上面的题目。

你能够已发明了,上面我用的是减缓而不是处理。这也是许多人明白不太对的处所,认为 Java SE8 中的 Optional 类能够处理空指针题目。实在 Optional 类的的运用只是提醒你这里能够存在空值,须要特别处置惩罚,并供应了一些特别处置惩罚的要领。假如你把 Optional 类看成空指针的救命稻草而不加思索的运用,那末依旧会遇到毛病。

由于 Optional 是的 Java SE8 中引入的,因而本文中不免会有一些 JDK8 中的语法,如 Lambda 表达式,流处置惩罚等,然则都是基本形式,不会有过于庞杂的案例。

2. Optional 建立

Optional 的建立一共有三种体式格局。

/**
 * 建立一个 Optional
 */
@Test
public void createOptionalTest() {
    // Optional 组织体式格局1 - of 传入的值不能为 null
    Optional<String> helloOption = Optional.of("hello");

    // Optional 组织体式格局2 - empty 一个空 optional
    Optional<String> emptyOptional = Optional.empty();

    // Optional 组织体式格局3 - ofNullable 支撑传入 null 值的 optional
    Optional<String> nullOptional = Optional.ofNullable(null);
}

个中组织体式格局1中 of 要领,假如传入的值会空,会报出 NullPointerException 非常。

3. Optional 推断

Optional 只是一个包装对象,想要推断内里有无值能够运用 isPresent 要领搜检个中是不是有值 。

/**
 * 搜检是不是有值
 */
@Test
public void checkOptionalTest() {
    Optional<String> helloOptional = Optional.of("Hello");
    System.out.println(helloOptional.isPresent());

    Optional<Object> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.isPresent());
}

获得的输出:

true
false

从 JDK11 最先,供应了 isEmpty要领用来搜检相反的结果:是不是为空。

假如想要在有值的时刻举行一下操纵。能够运用 ifPresent要领。

/**
 * 假如有值,输出长度
 */
@Test
public void whenIsPresent() {
    // 假如没有值,猎取默认值
    Optional<String> helloOptional = Optional.of("Hello");
    Optional<String> emptyOptional = Optional.empty();
    helloOptional.ifPresent(s -> System.out.println(s.length()));
    emptyOptional.ifPresent(s -> System.out.println(s.length()));
}

输出结果:

5

4. Optional 猎取值

运用 get要领能够猎取值,然则假如值不存在,会抛出 NoSuchElementException 非常。

/**
 * 假如没有值,会抛非常
 */
@Test
public void getTest() {
    Optional<String> stringOptional = Optional.of("hello");
    System.out.println(stringOptional.get());
    // 假如没有值,会抛非常
    Optional<String> emptyOptional = Optional.empty();
    System.out.println(emptyOptional.get());
}

获得结果:

hello

java.util.NoSuchElementException: No value present
    at java.util.Optional.get(Optional.java:135)
    at net.codingme.feature.jdk8.Jdk8Optional.getTest(Jdk8Optional.java:91)

5. Optional 默认值

运用 orElse, orElseGet 要领能够在没有值的状况下猎取给定的默认值。

/**
 * 假如没有值,猎取默认值
 */
@Test
public void whenIsNullGetTest() {
    // 假如没有值,猎取默认值
    Optional<String> emptyOptional = Optional.empty();
    String orElse = emptyOptional.orElse("orElse default");
    String orElseGet = emptyOptional.orElseGet(() -> "orElseGet default");
    System.out.println(orElse);
    System.out.println(orElseGet);
}

获得的结果:

orElse default
orElseGet default

看到这里你能够会有些迷惑了,这两个要领看起来结果是如出一辙的,为何会供应两个呢?下面再看一个例子,你会发明二者的区分。

 /**
 * orElse 和 orElseGet 的区分
 */
@Test
public void orElseAndOrElseGetTest() {
    // 假如没有值,默认值
    Optional<String> emptyOptional = Optional.empty();
    System.out.println("空Optional.orElse");
    String orElse = emptyOptional.orElse(getDefault());
    System.out.println("空Optional.orElseGet");
    String orElseGet = emptyOptional.orElseGet(() -> getDefault());
    System.out.println("空Optional.orElse结果:"+orElse);
    System.out.println("空Optional.orElseGet结果:"+orElseGet);
    System.out.println("--------------------------------");
    // 假如没有值,默认值
    Optional<String> stringOptional = Optional.of("hello");
    System.out.println("有值Optional.orElse");
    orElse = stringOptional.orElse(getDefault());
    System.out.println("有值Optional.orElseGet");
    orElseGet = stringOptional.orElseGet(() -> getDefault());
    System.out.println("有值Optional.orElse结果:"+orElse);
    System.out.println("有值Optional.orElseGet结果:"+orElseGet);
}

public String getDefault() {
    System.out.println("   猎取默认值中..run getDeafult method");
    return "hello";
}

获得的输出:

空Optional.orElse
   猎取默认值中..run getDeafult method
空Optional.orElseGet
   猎取默认值中..run getDeafult method
空Optional.orElse结果:hello
空Optional.orElseGet结果:hello
--------------------------------
有值Optional.orElse
   猎取默认值中..run getDeafult method
有值Optional.orElseGet
有值Optional.orElse结果:hello
有值Optional.orElseGet结果:hello

在这个例子中会发明 orElseGet 传入的要领在有值的状况下并不会运转。而 orElse却都邑运转。

6. Optional 非常

运用 orElseThrow 在没有值的时刻抛出非常

/**
 * 假如没有值,抛出非常
 */
@Test
public void whenIsNullThrowExceTest() throws Exception {
    // 假如没有值,抛出非常
    Optional<String> emptyOptional = Optional.empty();
    String value = emptyOptional.orElseThrow(() -> new Exception("发明空值"));
    System.out.println(value);
}

获得结果:

java.lang.Exception: 发明空值
    at net.codingme.feature.jdk8.Jdk8Optional.lambda$whenIsNullThrowExceTest$7(Jdk8Optional.java:118)
    at java.util.Optional.orElseThrow(Optional.java:290)
    at net.codingme.feature.jdk8.Jdk8Optional.whenIsNullThrowExceTest(Jdk8Optional.java:118)

7. Optional 函数接口

Optional 随 JDK8 一同涌现,必定会有一些 JDK8 中的新特征,比方函数接口。Optional 中主要有三个传入函数接口的要领,分别是filtermapflatMap。这内里的完成实际上是 JDK8 的另一个新特征了,因而这里只是简朴演示,不做诠释。背面放到其他 JDK8 新特征文章里引见。

@Test
public void functionTest() {
    // filter 过滤
    Optional<Integer> optional123 = Optional.of(123);
    optional123.filter(num -> num == 123).ifPresent(num -> System.out.println(num));

    Optional<Integer> optional456 = Optional.of(456);
    optional456.filter(num -> num == 123).ifPresent(num -> System.out.println(num));

    // map 转换
    Optional<Integer> optional789 = Optional.of(789);
    optional789.map(String::valueOf).map(String::length).ifPresent(length -> System.out.println(length));
}

获得结果:

123
3

8. Optional 案例

假设有计算机、声卡、usb 三种硬件(下面的代码中运用了 Lombok@Data 注解)。

/**
 * 计算机
 */
@Data
class Computer {
    private Optional<SoundCard> soundCard;
}

/**
 * 声卡
 */
@Data
class SoundCard {
    private Optional<Usb> usb;
}

/**
 * USB
 */
@Data
class Usb {
    private String version;
}

计算机能够会有声卡,声卡能够会有 usb。那末怎样获得 usb 版本呢?

/**
 * 电脑里【有能够】有声卡
 * 声卡【有能够】有USB接口
 */
@Test
public void optionalTest() {
    // 没有声卡,没有 Usb 的电脑
    Computer computerNoUsb = new Computer();
    computerNoUsb.setSoundCard(Optional.empty());
    // 猎取 usb 版本
    Optional<Computer> computerOptional = Optional.ofNullable(computerNoUsb);
    String version = computerOptional.flatMap(Computer::getSoundCard).flatMap(SoundCard::getUsb)
        .map(Usb::getVersion).orElse("UNKNOWN");
    System.out.println(version);
    System.out.println("-----------------");

    // 假如有值,则输出
    SoundCard soundCard = new SoundCard();
    Usb usb = new Usb();
    usb.setVersion("2.0");
    soundCard.setUsb(Optional.ofNullable(usb));
    Optional<SoundCard> optionalSoundCard = Optional.ofNullable(soundCard);
    optionalSoundCard.ifPresent(System.out::println);
    // 假如有值,则输出
    if (optionalSoundCard.isPresent()) {
        System.out.println(optionalSoundCard.get());
    }

    // 输出没有值,则没有输出
    Optional<SoundCard> optionalSoundCardEmpty = Optional.ofNullable(null);
    optionalSoundCardEmpty.ifPresent(System.out::println);
    System.out.println("-----------------");

    // 挑选 Usb2.0
    optionalSoundCard.map(SoundCard::getUsb)
            .filter(usb1 -> "3.0".equals(usb1.map(Usb::getVersion)
            .orElse("UBKNOW")))
            .ifPresent(System.out::println);
}

获得结果:


UNKNOWN
-----------------
SoundCard(usb=Optional[Usb(version=2.0)])
SoundCard(usb=Optional[Usb(version=2.0)])
-----------------

9. Optional 总结

在本文中,我们看到了怎样运用 Java SE8 的 java.util.Optional 类。Optional 类的目标不是为了替代代码中的每一个空援用,而是为了协助更好的设想顺序,让运用者能够仅经由过程视察属性范例就能够晓得会不会有空值。别的,Optional不供应直接猎取值的要领,运用时会强制你处置惩罚不存在的状况。间接的让你的顺序免受空指针的影响。

文中代码已上传 Github。

https://github.com/niumoo/jdk-feature

JDK8 新特征系列文章:
Jdk14 都要出了,Jdk8 的时候处置惩罚姿态还不相识一下?

本文作者: 未读代码
我的微信:wn8398
个人主页: https://www.codingme.net
本篇文章是博主原创文章,迎接转载,转载时在显著位置说明原文链接即可。
关注民众号复兴资本能够猎取Java 中心学问整顿&口试材料。
  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
Jdk14都要出了,还不能运用 Optional文雅的处置惩罚空指针?

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282299.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>