Java三元运算符不工作?

Java三元运算符不工作?,java,stringbuilder,ternary-operator,Java,Stringbuilder,Ternary Operator,假设我们有一个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

假设我们有一个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
is
3.0
3将被追加时,如果
d
is
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
进行转换时,它才会起作用。。。但每一次,这不是我想要的。这里有什么问题?为什么三元运算符不工作?

此行为记录在JLS-15.25中

如果其中一个操作数为T类型,其中T为字节、短字符或字符,而另一个操作数为int类型的常量表达式(§15.28),其值可在T类型中表示,则条件表达式的类型为T

当你写作时

(a > b) ? 'a' : 65
第二种类型转换为char


浏览JLS,它解释了其他情况下的行为(相同的方法)。

在原语数上使用三元运算符时,第二个和第三个操作数会受到二进制数字提升的影响。在您的例子中,
int
被转换为
double
。这是在中指定的。

此行为的原因是带有三元运算符的表达式具有定义良好的类型。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

方法
StringBuilder.append()
对不同类型的参数有许多重载。使用哪种方法重载是编译时的决定。三元运算符的结果只有一种类型,在本例中为
int
double
-
double


if
语句的情况下,编译器根据分支使用适当的
append()
方法重载。

我认为编译器将
sb.append(d%1==0?(int)d:d)
视为
sb.append(double)
,否则
sb.append((int)d)
视为
sb.append(int)

数值条件表达式是独立表达式(§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操作数将转换为另一种类型。 否则,较小的类型将转换为下一个较大的类型,直到两个操作数具有相同的类型。转换顺序为:

字节->短->整数->长->浮点->双精度

字符->整数->长->浮点->双精度


最终,整个条件表达式将获得其第二个和第三个操作数的类型。

您应该使用
DecimalFormat(“0.#”)
来去除尾随的零,而不是强制转换为
int
。奇怪的是,如果我计算
d%1==0?(int)d:d
(其中d=3)在eclipse中返回“3”。但随后附加了“3.0”。但这可能是日食的结果。