条件表达式的类型问题

条件表达式在编程中经常被用到,如 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 byteshortcharint
2nd         
float bnp(float,byte) bnp(float,short) bnp(float,char) bnp(float,int)
Float bnp(Float,byte) bnp(Float,short) bnp(Float,char) bnp(Float,int)
double bnp(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

posted @ 2017-06-28 13:06  钟Sir_Zzz  阅读(1250)  评论(0编辑  收藏  举报