2013-08-23 18 views
5

最近、次の2つのコードスニペットを実行しようとしましたが、出力に驚いていました。短絡ブール式では、アンボックスはどのように機能しますか?

まず:

// ... 
System.out.println((Boolean)null || true); 
// ... 

二次出力に

第2の実施の結果:以下の出力で

// ... 
System.out.println((Boolean)null || false); 
// ... 

第1の実施の結果
スレッド "main" javの例外com.blah.mainでa.lang.NullPointerException
     (SanityCheck.java:26)

任意短絡が適用されるように私は、両方の実施例は、ヌルポインタ例外が発生しなければならないと考えているだろう左右に。ブール値からブール値を取り除こうとする試みは、論理値の反対側が考慮される前に失敗していたはずです。

誰もこの一貫性のない動作を説明できますか?

+0

この動作は、[JLS](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.24)と矛盾するように見えます。「実行時には、左-handle演算子の式が最初に評価され、結果にブール型の場合はアンボックス変換されます。 –

+2

SanityCheck.java – arynaq

答えて

2

私はそれでジャブを取るでしょう。 コンパイラは2つのステートメントを解釈しようとするので、主な違いは、右側にtrueのステートメントは左手のブールで計算する必要はなく、右側のステートメントはfalseであることです。

ブール値はObjectなので、nullに設定できます。例外がスローされる場所ではありません。 nullに設定されたBooleanオブジェクトに対して操作を実行しようとすると、NullPointerExceptionがスローされます。実際のケースでは、コンパイラはnullをブール値に渡します。また、ORでORをとると常にtrueになるため、条件は真です。偽の場合、コンパイラはnullを再びブール値に渡し、falseをチェックし、条件がfalseの場合、条件が最終的に真または偽となる可能性があるため、論理和をORで計算する必要があります。計算が行われると、NullPointerExceptionがスローされます。

+0

これは良い答えですが、短絡が左から右に発生したと考えました。またはで左のオペランドが真である場合、右のオペランドは評価されません。同様に、左側のオペランドがandで真であれば、右側のオペランドは評価されません。私はそれがコンパイラによっていくつかの最適化かもしれないと推測しているので、私はクラスファイルを逆コンパイルしようとします。 – studro

+0

私は実際にあなたが書いたものを誤解していると思います。短絡は、コンパイル時に最適化されているため適用されません。見つけた – studro

+0

修正!キャスティング・パス、そして真実のパス。それで本当のOR *の必要はありません。なぜなら、それは常に真実だからです。 – user1549672

4

JADを通じてクラスファイルを実行して、最適化されたコードの外観を確認しました。偽の場合のために

// ... 
System.out.println(true); 
// ... 

:真の場合について

// ... 
System.out.println(null.booleanValue()); 
// ... 
1

私はあなたの結果を再現することはできません。私は実際に両方のケースでNPEを取得します。

JLSごとに、左側のオペランド式が常に最初に評価されます。 (Boolean)nullが評価されると、ヌルBooleanオブジェクトに対して自動アンボックスが実行されます。特に、基礎となるコードnull.booleanValue()がNPEを引き起こしています。

+1

真のケースのNPEを取得すべきではありません。 (ブール値)nullは単独で正常に動作します。最初に評価されたとしても、NullPointerExceptionはスローされるべきではありません。 – user1549672

+0

@ user1549672それは本当に私に起こっているので、私はまだ問題を把握しようとしています。結果は私が使用しているJDKのバージョンに依存しますか? –

+0

わかりません。どのバージョンを実行していますか? – user1549672

関連する問題