条件表达式的类型问题
条件表达式在编程中经常被用到,如 a=b?x:y 简单的一行语句,就能替换一个 if else 语句块,所以非常受欢迎。但在使用时,对条件表达式返回的类型需要留意,特别是在第二、第三运算符涉及到基本数据类型装箱、拆箱与数值类型提升时。
一、案例
下面一段代码想要执行的操作是:将系统的价格数字转换为通用的价格,如果showDecimal为true,显示小数点后的数字,否则不显示小数点。
private static void transPrice(long price, boolean showDecimal) { Float formatPrice = price/10000F; Object data = showDecimal ? formatPrice : formatPrice.intValue(); System.out.println(data.toString()); }
transPrice(135000, true); //期待输入结果: 13.5
transPrice(0, false); //期待结果: 0
调用该方法后,预期输出 0,实际得到 0.0。也即黑体字一行并未达到预期要的结果。反编译该段代码后,如下:
Object data = Float.valueOf(showDecimal?formatPrice.floatValue():(float)formatPrice.intValue());
看完这段代码后,我们大致可以知道出现该结果的原因,但是编译器为何会将这段代码这样处理呢?
二、案例分析
根据 Java 语言规范 jls-15.25 (JDK8)的描述
The process for determining the type of a conditional expression depends on the kind of conditional expression, as outlined in the following sections.
The following tables summarize the rules above by giving the type of a conditional expression for all possible types of its second and third operands. bnp(..) means to apply binary numeric promotion.
Table 15.25-A. Conditional expression type (Primitive 3rd operand, Part I)
3rd → byteshortcharint2nd ↓ floatbnp( float,byte)bnp( float,short)bnp( float,char)bnp( float,int)Floatbnp( Float,byte)bnp( Float,short)bnp( Float,char)bnp( Float,int)doublebnp( double,byte)bnp( double,short)bnp( double,char)bnp( double,int)
也就是说:当条件表达式的第二运算符是 Float 引用类型、第三运算符是 int 基本数据类型时,需要对第二、第三运算符进行双目数值类型提升(binary numeric promotion)。
该操作的结果是:
1.第二运算符是引用 Float 引用类型,对其进行拆箱操作,第二运算符调用 formatPrice.floatValue()
2.第二运算符现在是 float 类型,第三运算符是 int 类型,因此将第三运算符也转换成 float 类型,于是有 (float)formatPrice.intValue()
最后,在赋值给 data 时,需要将 float 类型的数据装箱为 Float.valueOf(...)
三、解决方案
使用 if else 语句
Float formatPrice = price/10000F; Object data; if (hasDecimal) {
priceNum = formatPrice; } else { priceNum = formatPrice.intValue(); }
这样,就保证了 int 不会被提升为 float 类型。
当然,本例稍微有点特殊。一般情况下使用条件表达式,只需要得到一个类型的结果。此处只是借此来分析条件表达式对于第二、第三运算符类型的处理。
参考文档:
JDK 8规范文档:http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.25

浙公网安备 33010602011771号