stringbuilder Java三值运算符不工作?
假设我们有一个StringBuilder和一个double。现在,我想添加双精度。如果double可以表示为整数(例如3.0、5.0等),我想将其添加为整数,否则添加为double
实现这一点的第一种方法是:
StringBuilder sb = new StringBuilder();
double d = 3.5;
if (d % 1 == 0) sb.append((int) d);
else sb.append(d);
System.out.println(sb.toString());
这仍然有效,当d
是3.0
时,3将被追加,如果d
是3.5
时,3.5将被追加
现在我想简单地用三元运算符:
StringBuilder sb = new StringBuilder();
double d = 3.5;
sb.append(d % 1 == 0 ? (int) d : d);
System.out.println(sb.toString());
所以现在我有一个问题,每次,如果double是3.0
或3.5
,它将被添加为double值!只有当我在理论上对true
和false
施压时,它才有效。。。但每一次,这不是我想要的。这是什么问题?为什么三元运算符不起作用
# 1 楼答案
这种行为记录在JLS-15.25中Conditional Operator ? : :
当你写作的时候
第二种类型被转换为char
通过JLS,它解释了其他情况下的行为(相同的方法)
# 2 楼答案
在原语数上使用三元运算符时,第二个和第三个操作数将进行二进制数字升级。在您的例子中,
int
被强制转换为double
。这是在JLS #15.25中指定的# 3 楼答案
数值条件表达式是独立表达式(§15.2)
数值条件表达式的类型确定如下:
如果第二个和第三个操作数的类型相同,则这就是条件表达式的类型
如果第二个和第三个操作数中的一个是基元类型T,而另一个的类型是对T应用装箱转换(§5.1.7)的结果,则条件表达式的类型是T
如果其中一个操作数的类型为byte或byte,而另一个操作数的类型为short或short,则条件表达式的类型为short
如果其中一个操作数是T类型,其中T是字节、短字符或字符,而另一个操作数是int类型的常量表达式(§15.28),其值可在T类型中表示,则条件表达式的类型是T
如果其中一个操作数是T类型,其中T是字节、短字符或字符,而另一个操作数是int类型的常量表达式,其值可在U类型中表示,U类型是对T应用取消装箱转换的结果,则条件表达式的类型是U
否则,二进制数字提升(§5.6.2)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型
这些类型被转换为它们相应的基本类型,称为取消装箱。 如果一个操作数是常数int(在解装箱之前不是整数),其值可在另一种类型中表示,则该int操作数将转换为另一种类型。 否则,较小的类型将转换为下一个较大的类型,直到两个操作数具有相同的类型。转换顺序如下:
字节->;短->;int->;长->;浮动->;加倍
char->;int->;长->;浮动->;加倍
最终,整个条件表达式将获得其第二个和第三个操作数的类型
# 4 楼答案
这种行为的原因是带有三元运算符的表达式具有定义良好的类型。JLS详细描述了如何计算该类型,但粗略地说,它是冒号之前表达式类型和冒号之后表达式类型的最小上界
例如,如果
b
是boolean
,i
是int
,d
是double
,那么b ? i : d
的类型是double
,因为double
是int
和double
的最小上界。当您在StringBuilder
上调用append( b ? i : d )
时,您会得到带有double
参数的append
版本。同样的事情也会发生在你的案例中,比如d % 1 == 0 ? (int) d : d
# 5 楼答案
我认为编译器将
sb.append(d % 1 == 0 ? (int) d : d)
视为sb.append(double)
,否则sb.append((int) d)
视为sb.append(int)