2011-02-07 5 views
13

最近、ランダムなアドホックテストで私のコードに異常なバグが見つかりました。だから、私はそれのためのテストケースを作った。Javaの三項演算子では、式が偽の値になっても最初の引数を評価できますか?

はここに私のテストケースである:

SampleRequest request = new SampleRequest(); 
    request.setA(null); 
    request.setB(null); 
    assertEquals(null, request.getAOrB()); 

A及びBは、java.lang.Integerのタイプとして定義され、要求にその値を設定するために直接セッターメソッドを有しています。

列挙型もあります。これは、プリミティブな整数値と、このコードで使用されるメソッドを持っています。関連する部分をここに掲載します:

enum Swapper { 
public int c; 
Swapper findSwapperToUse(final int a) { 
    for(Swapper swapper : values()) { 
     if(swapper.c == a) { 
      return swapper; 
     } 
    } 
    return null; 
} 
} 

ここでは、混乱している方法があります。そのメソッドでtestメソッドを呼び出すと、NPEが返されますが、メソッドの最後の行にあります。

public class SampleRequest { 
    private Integer A; 
    private Integer B; 

    public void setA(final Integer A) { 
     this.A = A; 
    } 

    public void setB(final Integer B) { 
     this.B = B; 
    } 


public Integer getAOrB() { 
    return A != null ? Swapper.findSwapperToUse(A).c 
     : B; 
} 
} 

このテストでは、AとBの両方がnullに設定されています。したがって、A!= nullはfalseを返します。しかし、私は:B行の行番号でNullPointerExceptionを取得します。

何らかの理由でSwapper.findSwapperToUse(A).cという最初の式が評価されているため、A.intValue()がオートボクシングによって呼び出され、null値でNullPointerExceptionが発生します。デバッグによって、findSwapperToUse()が呼び出されないことがわかっています。

しかしながら、これによれば起こらないはずquestionthis:選択されない Java ternary (immediate if) evaluation

オペランド式は、条件式のその特定の評価のために評価されません。

null(B)を返すことでNullPointerExceptionが発生することはありません。ここではNullPointerExceptionが返されます。

何が起こっているのですか?

編集: - 私は私があればまっすぐステートメントを使用してこれを回避するために、コードを変更することを追加するのを忘れ、次のコードは、期待通りの作業を行います。

public Integer getAOrB() { 
    if(A != null) { 
     return Swapper.findSwapperToUse(A).c; 
    } 
    return B; 
} 
+2

(例えば、戻り値の型の欠如)あなたがコンパイルされないでしょう与えられたコードを。短いものの*完全な例を挙げてください。何が起きているのかがわかります。 –

+0

AがNULLであることを確認するにはどうすればよいですか? –

+0

私は戻り値の型を提供しました、ごめん、それはSwapperでした。 @Thor - テストのため(request.setA(null)、request.setB(null)) – MetroidFan2002

答えて

22

私は問題は、コンパイラが式全体

A != null ? Swapper.findSwapperToUse(A).c : B 
の種類を推測することに起因すると思い

Swapper.cのタイプからintと入力します。したがって、アンボックス変換をBに適用しようとします。第二及び第三のオペランドが変換可能なタイプを持っている場合、そうでない場合

  • (5.1.8)数値型に、次にいくつかの場合がある:ここ

    the JLS, §15.25から関連の抜粋です。

    • ...
    • そうでない場合、バイナリ数値昇格(5.6.2)は、オペランドに タイプを適用し、条件式のタイプがPRであります2番目と3番目のオペランドの の除外型です。 バイナリ数値昇格は、 アンボックス変換(§5.1.8)と値セット変換(§5.1.13)を実行することに注意してください。

次のキャストを追加することによって、それを防ぐことができます。

A != null ? (Integer) Swapper.findSwapperToUse(A).c : B 
+1

よく目にされたSir –

+0

それはばかげたことですが、それはそれでした!ありがとう。 – MetroidFan2002

+2

:(これらのものをキャッチするために自動ボクシングを無効にするコンパイラフラグがあるはずです –

0

あなたfindSwapperToUseメソッドがnullを返して、そしてあなたできませんnull.c

本のことを確認するには、私は読むためにあなたのコードを変更します

public Integer getAOrB() { 
    if(A != null) { 
     Swapper foundSwapper = Swapper.findSwapperToUse(A); 
     return foundSwapper.c; 
    } 
    return B; 
} 
+0

これも私が思ったことですが、質問の一番下の部分は説明しません。 –

+0

OPは、このメソッドが呼び出されていないことを明示しています。これは、Aがnullであることを考慮すると驚くことではないので、 'int'を受け入れる関数の引数にすることはできません。 –

+0

@Sergey oopsはそのビットを逃しました:) – Rich

関連する問題