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);
}
}
2 に答える
編集
三項演算子は、内部でいくつかの型変換を行います。あなたの場合、プリミティブとラッパータイプを混合しています。この場合、ラッパータイプはボックス化されておらず、三項演算子の結果は「再ボックス化」されます。
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回出力する可能性があります。
奇妙な振る舞いを理解するには、これが何をするのかを区別する必要があります。
(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;