6
public class Test {
    public static final Double DEFAULT_DOUBLE = 12.0;
    public static final Long DEFAULT_LONG = 1L;

    public static Double convertToDouble(Object o) {
        return (o instanceof Number) ? ((Number) o).doubleValue()
                : DEFAULT_DOUBLE;
    }

    public static Long convertToLong(Object o) {
        return (o instanceof Number) ? ((Number) o).longValue() : DEFAULT_LONG;
    }

    public static void main(String[] args){
        System.out.println(convertToDouble(null) == DEFAULT_DOUBLE);
        System.out.println(convertToLong(null) == DEFAULT_LONG);
    }
}
4

2 に答える 2

8

編集

三項演算子は、内部でいくつかの型変換を行います。あなたの場合、プリミティブとラッパータイプを混合しています。この場合、ラッパータイプはボックス化されておらず、三項演算子の結果は「再ボックス化」されます。

2番目と3番目のオペランドの1つがプリミティブ型Tであり、もう1つの型がボクシング変換(§5.1.7)をTに適用した結果である場合、条件式の型はTです。


したがって、コードは基本的に次のようになります(タイプミスは別longValueとしてdoubleValue):

public static void main(String[] args){
    Double d = 12.0;
    System.out.println(d == DEFAULT_DOUBLE);

    Long l = 1L;
    System.out.println(l == DEFAULT_LONG);
}

一部のJVMでは長い値をキャッシュ==できるため、比較でtrueが返される場合があります。あなたがあなたとすべての比較をしたならば、あなたは両方の場合equalsに得るでしょう。true

public static final Long DEFAULT_LONG = 128L;使用して試してみる場合は、次の点に注意してください。

Long l = 128L;
System.out.println(l == DEFAULT_LONG);

Long値は通常、-128〜 + 127の間でのみキャッシュされるため、falseと表示される可能性があります。

注:JLSではchar、、byteおよびint-127〜 + 128の値をキャッシュする必要がありますが、については何も述べていませんlong。したがって、コードは実際には別のJVMでfalseを2回出力する可能性があります。

于 2013-02-06T02:23:17.370 に答える
4

奇妙な振る舞いを理解するには、これが何をするのかを区別する必要があります。

(o instanceof Number) ? ((Number) o).longValue() : DEFAULT_LONG

ここにあるのはlong、とのインスタンスを返すメソッドの呼び出しですLong。2つの異なるタイプ。ただし、条件演算子?は単一の型を生成する必要があります。または。long_ Longそのためには、第2オペランドをボックス化するか、第3オペランドをボックス化解除する必要があります。

この場合、JLSは、3番目のオペランドをボックスから外す必要があると言っています。 JLS 15.25

「2番目と3番目のオペランドの1つがプリミティブ型Tであり、もう1つの型がボクシング変換(§5.1.7)をTに適用した結果である場合、条件式の型はTです。」

そして、それはあなたの定数が箱から出されて、そして再び箱に入れられていることを意味します。

これで、プリミティブ型のボックス化は、ボックス化された型のvalueof()メソッドを呼び出すことによって実行されます。そして、これらのメソッドは、基本タイプに応じてわずかに異なることを行います。

  • 浮動小数点型の場合、valueof常に新しいオブジェクトを作成します
  • 積分型の場合、valueofメソッドは新しいオブジェクトを作成することもあれば、既存のオブジェクトを返すこともあります。

そして後者はここで起こっていることです。 Long.valueof(1L)は常に同じ値を返し、との比較==はを与えtrueます。


2つの「修正」があります...これを修正したいと仮定します:

  • 両方のブランチで、三項演算子をif/elseに置き換えます。return
  • 2番目のオペランドをキャストして、ボックス化を強制します。

    return (o instanceof Number) ? 
            (Long) ((Number) o).longValue() : DEFAULT_LONG;
    
于 2013-02-06T02:35:13.463 に答える