15

NullPointerException先日、三項演算子の予期しない型キャストが原因で、本当に奇妙なことに遭遇しました。この(役に立たない模範的な)関数を考えると:

Integer getNumber() {
    return null;
}

コンパイル後、次の2つのコードセグメントが完全に同一になることを期待していました。

Integer number;
if (condition) {
    number = getNumber();
} else {
    number = 0;
}

対。

Integer number = (condition) ? getNumber() : 0;

の場合、 -ステートメントconditionは正常に機能しますが、2番目のコードセグメントの三項演算子は。をスローします。三項演算は、結果を自動ボックス化して!?!に戻す前に、両方の選択肢を型キャストすることを決定したようです。実際、明示的にtoをキャストすると、例外はなくなります。言い換えると:trueifNullPointerExceptionintInteger0Integer

Integer number = (condition) ? getNumber() : 0;

と同じではありません:

Integer number = (condition) ? getNumber() : (Integer) 0;

if-elseしたがって、三項演算子と同等のステートメント(私が予期していなかったもの)の間にはバイトコードの違いがあるようです。これは3つの質問を提起します:なぜ違いがあるのですか?これは三項実装のバグですか、それとも型キャストの理由がありますか?違いがあるとすると、三項演算は同等のステートメントよりも多かれ少なかれパフォーマンスが高くなりますかif(私は知っていますが、違いは大きくはありませんが、それでも)?

4

3 に答える 3

15

JLSによると:-

条件式のタイプは次のように決定されます。

  • 2番目と3番目のオペランドが同じ型(null型の場合もあります)の場合、それが条件式の型です。
  • 2番目と3番目のオペランドの1つがプリミティブ型Tであり、もう1つの型がボクシング変換
    (§5.1.7)をTに適用した結果である場合、条件式の型はTです。
于 2012-10-06T21:31:50.850 に答える
11

問題はそれです:

Integer number = (condition) ? getNumber() : 0;

getNumber()の結果のボックス化解除と再ボックス化を強制します。これは、3進数(0)のfalse部分が整数であるため、getNumber()の結果をintに変換しようとするためです。以下はそうではありませんが:

Integer number = (condition) ? getNumber() : (Integer) 0;

これはバグではなく、Javaが物事を行うために選択した方法です。

于 2012-10-06T21:24:27.213 に答える
2

これはそれが機能することになっている方法です。三項演算子は、通常のステートメントと同等であることを意味するものではありません。ifとの本体はステートメントifであり、とに続く部分はであり、同じタイプに評価する必要があります。else?:

別の言い方a = b ? c : dをすれば、はと同等ではないはずif (b) a = c; else a = d;です。代わりに、b ? c : dはそれ自体の式であり、その結果の割り当ては結果にa影響を与えません。

于 2012-10-06T21:24:36.200 に答える