Jdk 8 Optionalの正しい姿勢

10449 ワード

Java 8にはいくつかの有用なAPIが追加されていることを知っています.そのうちの1つはOptionalです.もしそれに対して少し偽の探求がなければ、ただ軽く描写してNullPointExceptionの問題を優雅に解決することができると思って、そこでコードはこのように書き始めました.
Optional<User> user = ......

if (user.isPresent()) {

    return user.getOrders();

} else {

    return Collections.emptyList();

}

私たちの思考は依然としてその場で足を踏み入れていると言わざるを得ませんが、本能的にはUserの実例の包装にすぎないと思っています.これは私たちが前に書いたものと同じです.
User user = .....

if (user != null) {

    return user.getOrders();

} else {

    return Collections.emptyList();

}

実質的には何の違いもない.これがJava 8 Optionalタイプをうまく使う正しい姿勢です.
リオ五輪の時、ニュースは何度も五星紅旗に問題があると言ったが、私はどう見ても何の問題も見えず、後になって小星が中央を拝む姿勢が間違っていると言った.だから私达はくれぐれも自分の惯れている事に対して当然だと感じないでください、少しも妥当ではありませんと感じないで、言い換えればつまり私达がJava 8のOptionalに切り替える时、継承性の前でnullの时のあのような思惟に対応することができなくて、新しいことを掌握して、正しくJava 8 Optionalの正しい姿势を使うべきです.
率直に言うと、次のような方法でOptionalを使っているうちに、自分を見つめ始めなければなりません.
  • isPresent()メソッドを呼び出すとき
  • get()メソッドを呼び出すとき
  • Optionalタイプがクラス/インスタンス属性である場合
  • Optionalタイプをメソッドパラメータとする場合
  • isPresent()とobj!=nullは何の違いもなく、私たちの生活は依然として一歩一歩驚いている.isPresent()をクッションにしないget()呼び出しはIntelliJ IDEAでアラームを受信します
    Reports calls to java.util.Optional.get() without first checking with a isPresent() call if a value is available. 
    If the Optional does not contain a value, get() will throw an exception. 

    (Optional.get()を呼び出す前にisPresent()で値が使用可能かどうかをチェックしない.Optionalに値が含まれていない場合、get()は例外を放出します.
    Optionalタイプを属性やメソッドパラメータとして使用するのはIntelliJ IDEAではさらに強く推奨されていません
    Reports any uses of java.util.Optional, java.util.OptionalDouble, java.util.OptionalInt, 
    java.util.OptionalLong or com.google.common.base.Optional as the type for a field or a parameter. 
    Optional was designed to provide a limited mechanism for library method return types where there needed to
    be a clear way to represent "no result". Using a field with type java.util.
    Optional is also problematic if the class needs to be Serializable, which java.util.Optional is not. 
    

    (Optionalのようなタイプをフィールドやメソッドパラメータとして使用することは望ましくない.Optionalはクラスライブラリメソッドとして設計されており,値がない場合の戻りタイプを明確に示すことができる.Optionalタイプはシーケンス化できず,フィールドタイプとして使用すると問題が発生する)
    だからOptionalで私たちが本当に依存できるのはisPresent()とget()の他の方法を除くべきです.
  • public Optional map(Function super T, ? extends U> mapper)
  • public T orElse(T other)
  • public T orElseGet(Supplier extends T> other)
  • public void ifPresent(Consumer super T> consumer)
  • public Optional filter(Predicate super T> predicate)
  • public Optional flatMap(Function super T, Optional> mapper)
  • public T orElseThrow(Supplier extends X> exceptionSupplier) throws X

  • 私は少し自信を持ってそれらの使用頻度によって上の方法に順番を並べた.
    まず、Optionalの3つの構造方法:Optional.of(obj) , Optional.ofNullable(obj)と明確なOptional.empty()
    Optional.of(obj):入力されたobjがnull値ではないことを要求します.そうしないと、まだ役に入っていないのにNull PointerException異常に倒れてしまいます.
    Optional.ofNullable(obj):Optionalインスタンスをインテリジェントで寛容な方法で構築する.来る者は拒まずnullが届くとOptionalを得る.Empty()はnull以外でOptionalを呼び出す.of(obj) .
    それは私たちがOptionalを使うだけではないでしょうか.ofNullable(obj)は一労永逸で、不変応二変でOptionalインスタンスを構築すればいいのでしょうか.それは必ずしもそうではありませんof(obj)はどうしてそんなに暴露する必要があるのか、私有ならいいのか.
    私自身の観点は:1.Optionalに伝えることが非常に明確になったときof(obj)のobjパラメータがnullであるはずがない場合、例えばnewが出たばかりのオブジェクト(Optional.of(new User(...))である場合、またはnull以外の定数である場合.2.objのためにnullではないと断言したい場合、すなわちobjがnullの場合、Null PointException異常を直ちに報告し、空のポインタ異常を隠すのではなく、直ちに修正したい場合、Optionalを断固として使用すべきである.of(obj)は、予測不可能なnull値に乗じてOptionalに隠れないようにOptionalインスタンスを構築する.
    既存のOptionalインスタンスをどのように使用するかを始めました.Optional userのインスタンスがあると仮定します.以下はいくつかの一般的なもので、if(user.isPresent(){...}else{...}のいくつかのアプリケーションを避けるべきです.
    存在する場合は戻り、ない場合はデフォルト値を指定します.
    return user.orElse(null);  //    return user.isPresent() ? user.get() : null;
    return user.orElse(UNKNOWN_USER);

    存在は戻り、無は関数によって生成されます.
    return user.orElseGet(() -> fetchAUserFromDatabase()); //    return user.isPresent() ? user: fetchAUserFromDatabase();

    存在こそが何かをする
    user.ifPresent(System.out::println);
    
    //       
    if (user.isPresent()) {
      System.out.println(user.get());
    }

    map関数が盛大に登場
    user.isPresent()が真で、それに関連するordersを取得し、偽で空の集合を返すとき、私たちが上のorElse、orElseGetメソッドを使って力がないとき、それはもともとmap関数の責任であり、私たちはこのようにすることができます.
    return user.map(u -> u.getOrders()).orElse(Collections.emptyList())
    
    //          Java 8      
    if(user.isPresent()) {
      return user.get().getOrders();
    } else {
      return Collections.emptyList();
    }

    mapは無限にカスケードされる可能性があります.例えば、もう1階深く、ユーザー名の大文字を取得します.
    return user.map(u -> u.getUsername())
               .map(name -> name.toUpperCase())
               .orElse(null);

    これを前に置くには、各レベルの呼び出しの展開にnull値の判断が必要です.
    User user = .....
    if(user != null) {
      String name = user.getUsername();
      if(name != null) {
        return name.toUpperCase();
      } else {
        return null;
      }
    } else {
      return null;
    }

    Groovyはこの方面に対して安全な属性/方法アクセスオペレータを提供した.
    user?.getUsername()?.toUpperCase();

    Swiftにも似たような文法があり、Optionalのタイプにしか作用しない.
    NullPointerExceptionをisPresent()で処理するのは優雅ではなく、orElse、orElseGetなどがあり、特にmapの方法が優雅と呼ばれています.
    その他、filter()は条件に合わない値をempty()とし、flatMap()は常にmap()メソッドとペアとなり、orElseThrow()は値があるときに直接戻り、値がないときに所望の異常を投げ出す.
    一言小結:Optionalを使用する場合はOptionalを直接呼び出さないようにします.get()メソッド、Optional.isPresent()は、他のOptionalに依存するプライベートメソッドと見なすべきである.orElse() , Optional.orElseGet() , Optional.map()などのこのような方法.
    最後に、Java 8 Optionalを最もよく理解する方法は、そのソースコードjavaを見ることにほかならない.util.Optional、ソースコードを読んでこそ本当にあなたに最も底力があることを説明することができて、Optionalの方法の中で基本的には内部呼び出しisPresent()判断で、本当の時は値を処理して、偽の時は何もしません.
    転載先:【Java】jdk 8 Optionalの正しい姿勢