Java 8の新しい特性のOptionalクラスの進歩知識

8872 ワード

目次
●Optionalクラスについて
●実戦演習コード再構築
●まとめ
●Optionalクラスについて
前の記事ではOptional類を概説していましたが、多くの読者がまだよく把握できていないかもしれません.筆者が最初にこのクラスに触れたときも特にメリットは発見されず、特に「空のポインタの異常を効果的に回避できる」という特徴について理解が足りなかったのはなぜだろうか.コードを組み合わせて、筆者の当初の疑問と、どのようにしてこの疑問を解決したのかを話します.
//      
User user = userService.getUserbyId(0);
user.setUserName("  ");


//    Optionnal
User user = userService.getUserbyId(0);
Optional op = Optional.of(user);
if(op.isPresent()){
    op.get().setUserName("  ");
}

ロジックは簡単で、idが0のユーザー名を「明ちゃん」に設定します.元のビジネスコードでは、idが0のユーザーがデータベースに存在しない可能性があるため、空のポインタ異常が発生する可能性があります.だから、空ではない判断をしなければならない.
初めてOptionalクラスを使ってみると、意外にも空のポインタ異常が現れ、Optional op=Optional.of(user);この行は、おかしいと思いますが、Optionalクラスはnullオブジェクトを入れることができるのではないでしょうか.Optionalクラスは空のポインタの異常を効果的に回避できるということではないでしょうか.どうしてこんなことになったの?後でまたよく調べてみると、もともと学んだのは皮毛だけで、工場の方法であればOptional.of()Optionalクラスを構築するには、パラメータが空でないオブジェクトであることを保証する必要があります.しかし、この時は依然として疑問があって、Optionalがnullの対象を包装できると言っているのではないでしょうか.なぜポインタが異常になったのでしょうか.
順藤は瓜を触って、Optionalを見てみましょう.of()メソッドのソース:
  /**
     * Returns an {@code Optional} with the specified present non-null value.
     *
     * @param  the class of the value
     * @param value the value to be present, which must be non-null
     * @return an {@code Optional} with the value present
     * @throws NullPointerException if value is null
     */
    public static  Optional of(T value) {
        return new Optional<>(value);
    }


  /**
     * Constructs an instance with the value present.
     *
     * @param value the non-null value to be present
     * @throws NullPointerException if value is null
     */
    private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }

  /**
     * Checks that the specified object reference is not {@code null}. This
     * method is designed primarily for doing parameter validation in methods
     * and constructors, as demonstrated below:
     * 

     * public Foo(Bar bar) {
     *     this.bar = Objects.requireNonNull(bar);
     * }
     * 
*
* @param obj the object reference to check for nullity
* @param the type of the reference
* @return {@code obj} if not {@code null}
* @throws NullPointerException if {@code obj} is {@code null}
*/
public static T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
そもそも、この を いてOptional を する には、Objectsが いられていた.requireNonNull()のNull チェックメソッドです.したがって、 パラメータがnullの 、Nullポインタ が します. の に わせて、この は の を すべきである.ofNullable()で します.
OK、それなら、コードを のように します.
User user = userService.getUserbyId(0);
Optional op = Optional.ofNullable(user);
if(op.isPresent()){
    op.get().setUserName("  ");
}

はい、 がまた ました. かに、 ってもいいです.isPresent()は び しですが、 に プログラミングの を していますか?この き は の き と ているのではないでしょうか.
User user = userService.getUserbyId(0);
if(null != user){
    user.setUserName("  ");
}

if(op.isPresent()を してOptionalオブジェクトを にするのを れた 、プログラムは のポインタ を します.ネット では、Optionalを して なステップを するように するという があります.isPresent()とget()は、Optionalの を し、 ミスを けるように します. の の はWTF??? はこれからも オブジェクトに なステップを します:if(null!=T)、 にあなたに をして、 いを しないように します.これは じではありませんか?まるで に しているようだ.
その 、 はOptionalの や「Java 8 プログラミング」という の をたくさん んで、よく えてから、やっと し って、Optionalの しい き を しました.
  • isPresent()とget()の い をあきらめ、forget it!!!
  • java 8のLambdaとStreamの しい を に み わせて、チェーン び しをしましょう.

  • ネット で えているisPresent()とget()の なやり は、まったくでたらめで、 にOptionalの「 のポインタの を に ける」ことがifPresent()、orElse()、orElseGet()、orElseThrow()のいくつかの であることを しています.
    ビジネスシーン(opはOptionalオブジェクトを す)
    しい い の
    エラー
    opのオブジェクトが でない は、 を います.
    op.ifPresent(o->o.setUserName(「 」)
    if(op.isPresent(){op.get().setUserName(" ");}
    opのオブジェクトが でない は、それを します.そうでなければ の を します
    op.orElse(initUser);
    if(op.isPresent()){        return op.get(); } else{         return initUser; }
    opのオブジェクトが でない は、それを します.そうでなければ を う
    op.orElseGet()->new User(0,「 」);
    if(op.isPresent()){        return op.get(); } Else{return new User(0,「 」);}
    opのオブジェクトが でない は、それを します. を げ す
    op.orElseThrow(IllegalArgumentException::new);
    if(op.isPresent()){        return op.get(); } else{         throw new IllegalArgumentException() }
     
    ● コード
    このように に えば、 は なプロジェクトコードと びつけて て、 えば、フロントが を して、 パラメータを えて、バックグラウンドで のIDを して、データベースの で するIDの を して、そしてこの の とタイプを します.このニーズを するために、 のJAVA 7のコードがどのように かれているかを てみましょう.
        public String test0(AlarmAllParmeter alarmAllParmeter) {
            String errorResult = "";
            if (null != alarmAllParmeter) {
                Integer alarmId = alarmAllParmeter.getAlarmEventInputId();
                if (null != alarmId) {
                    AlarmEventInput alarmEventInput = alarmEventInputService.get(alarmId);
                    if (null != alarmEventInput) {
                        String alarmName = alarmEventInput.getAlarmName();
                        int alarmType = alarmEventInput.getAlarmType();
                        return String.valueOf(alarmType) + "-" + alarmName;
                    } else {
                        return errorResult;
                    }
                } else {
                    return errorResult;
                }
            } else {
                return errorResult;
            }
        }

    のポインタ を するために,if(null!=T)のテンプレートコードをコードに に いたことが らかになった.Optionalクラスを めて した は、 のコードを く があります.
        public String test1(AlarmAllParmeter alarmAllParmeter){
            String errorResult = "";
            Optional op = Optional.ofNullable(alarmAllParmeter);
            if(op.isPresent()){
                Integer alarmId = op.get().getAlarmEventInputId();
                Optional op1 = Optional.ofNullable(alarmId);
                if(op1.isPresent()){
                    AlarmEventInput alarmEventInput = alarmEventInputService.get(op1.get());
                    Optional op2 = Optional.ofNullable(alarmEventInput);
                    if (op2.isPresent()) {
                        String alarmName = alarmEventInput.getAlarmName();
                        int alarmType = alarmEventInput.getAlarmType();
                        return String.valueOf(alarmType) + "-" + alarmName;
                    } else {
                        return errorResult;
                    }
                }
                else {
                    return errorResult;
                }
            }
            else {
                return errorResult;
            }
        }

    そのプログラミングの はやはり「コマンドプログラミング」のレベルにとどまっており、このようなOptional を に うやり はかえって くのことに え、 には なテンプレートコードを くのと じように、 に にOptional をつけただけだ. に、Optionalの しい き でこのニーズを し、 のコードを します.
        public String test2(AlarmAllParmeter alarmAllParmeter){
            return Optional.ofNullable(alarmAllParmeter)
                           .map(a -> a.getAlarmEventInputId())
                           .map(a -> alarmEventInputService.get(a))
                           .map(a -> String.valueOf(a.getAlarmType())+"-"+a.getAlarmName())
                           .orElse("");
        }

    にJunit 4テストに した は の りです.
    public class OptionalTestTest {
    
        AlarmAllParmeter alarmAllParmeter = new AlarmAllParmeter();
        @Before
        public void setAlarmAllParmeter(){
            alarmAllParmeter.setAlarmEventInputId(1001);
        }
    
        @Test
        public void test0() {
            System.out.println("Test0 is: "+new OptionalTest().test0(alarmAllParmeter));
        }
    
        @Test
        public void test1() {
            System.out.println("Test1 is: "+new OptionalTest().test1(alarmAllParmeter));
        }
    
        @Test
        public void test2() {
            System.out.println("Test2 is: "+new OptionalTest().test2(alarmAllParmeter));
        }
    }
    
             ————
    Test0 is: 1-      
    Test1 is: 1-      
    Test2 is: 1-      

    ましたか、これがJAVA 8の です.Optional、Lambda、Streamの は、コードの き を めて しています( では1 のコードだけで みますが、 みやすいように、 ではチェーン び しをステップ に うことを くお めします).これはもう しているJava ではないように えますが、 は しており、 け れ、 れ、 な が の に いつくことができます.
     
    ●まとめ
    Java 8の しい に する はすでに3 かれており、 に のプロジェクトで することができ、 しいプロジェクトを くにしても、 の したコードを しても、 してみる があります. は を て、Java 8の が に の じを えるのは プログラミングの であることを し、これは の プログラミングの とは く なり、 に に け れるのはまだ し しいが、 にこのような しいプログラミングの に れていると、 が に いことを することができる.C++を していた のように、Cに べて、 つのオブジェクトの が くなったような がします. ですが、 で り ってみると、オブジェクト けプログラミングがプロセス けプログラミングよりも いメリットがあることを しました.Java 8のこの は に いと わざるを ません.
    に、この で べたOptionalの しい い はチェーン であり、 くのネット で べたようにisPresent() をしてget()を るべきではないことを めて します. 、あなたはマスターしましたか?