JDK14が出であることを、あなたはオプションのエレガントなハンドルNULLポインタを使用することはできませんか?

1.はじめに

あなたはNULLポインタを処理していない場合は、実際のJavaプログラマではありません。


NULLポインタが問題の多くは、私たちは多くの場合、空への参照に遭遇し、その後、あなたが他の値に空のブーストアクセスから参照したい、そしてもちろん会いましたNullPointExceptionこれは、あなたが次のコードに比べて、エラーライン数をちらっと見た、良い取引与えられた、と思うかもしれないです。私の心は瞬時に「右、右、右、空がある可能性が高い」点滅した後、追加null check取り扱いやすいです。しかし、あなたは、これはnullポインタ例外の数との最初の契約であるかわかりません。上記課題を解決するために、中ジャワSE8の新しいクラスの導入このクラスはでき軽減する上記の問題を。

java.util.Optional

私が使用する上であなたは発見したことが容易にするためではなく、解決します多くの人々は、これは中のJava SE8ことを、非常に適切な場所ではありません理解しOptional、クラスがNULLポインタの問題を解決することができます。実際には、任意のクラスの使用は唯一促し、あなたをここにNULL値があるかもしれない、特別な処理を必要とし、いくつかの特別な治療方法を提供します。あなたが取る場合はOptional代わりにNULLポインタプラス思考の使用のわらとしてクラスを、その後、まだエラーが発生しました。

そのためOptionalイエスのJava SE8を導入するので、これは避けられないようなJDK8文法の一部になりますラムダ式、ストリーム処理など、基本的な形態である、あまりにも複雑なケースは存在しないでしょう。

2.オプションを作成

オプションは、以下の3つの方法の合計を作成しました。

/**
 * 创建一个 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受信値がnullの場合、この方法は、報告されるNullPointerException異常。

3.オプション判決

オプションちょうどあなたが値を評価するラッパーオブジェクトを使用することができる、全く存在しない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.オプションのGet価値

使用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.オプションのデフォルト

使用orElseorElseGet無価値の場合に与えられたデフォルト値を取得する方法。

/**
 * 如果没有值,获取默认值
 */
@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

我々は2を提供する理由はここにあなたには、いくつかの疑問を見ることができ、これらの2つの方法は、まったく同じ効果のように見えますか?例では次のような外観、あなたは違いを見つけるでしょう。

 /**
 * 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.異常オプション

使用する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.オプション機能・インターフェース

OptionalJDK8と一緒に表示され、このような関数インタフェースとしてJDK8の新機能のいくつかがなければなりません。Optional3つの主な方法はそれぞれ着信インターフェイス機能は、あります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.オプションケース

(で次のコードを使用するコンピュータ、サウンドカード、USB 3つのハードウェアを想定注釈を)。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.オプションの要約

この記事では、我々はJavaのSE8を使用する方法を説明しましたjava.util.Optionalクラス。Optionalクラスの目的は、ユーザーが知ることができるので、各null参照でコードを置き換えるために、より良い設計プログラムを支援することではない時間値のみ属性タイプを観察することができていません。また、Optionalそれは使用の有無に対処するためにあなたを強制的に、値を取得する直接的な方法を提供していません。間接NULLポインタの影響から、あなたのプログラムをしましょう。

テキストコードは、アップロードされたのGithubを

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

記事のJDK8新しいシリーズ:
うちもJDK14、姿勢で対処するJdk8時間は約知りませんか?
<終了>

著者: のための未読コード
の私のマイクロ手紙:wn8398
プロフィール: https://www.codingme.net
この記事は、転載することを歓迎ブロガーのオリジナルの記事、である、見かけ上の位置復刻の元のリンクを示しています。
世間の注目リソースへの返事は、コアJavaのインタビュー&仕上げ材料の知識を習得することはできません。

おすすめ

転載: www.cnblogs.com/niumoo/p/11796296.html