Java 三元运算符不起作用?
Java ternary operator not working?
假设我们有一个 StringBuilder 和一个 double。现在想追加双倍。如果双精度可以表示为整数(例如 3.0、5.0 等),我想将其添加为整数,否则为双精度。
第一个实现方法是:
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
上投射时它才有效......但每次都不是我想要的。这是什么问题?为什么三元运算符不起作用?
JLS - 15.25 中记录了此行为。 Conditional Operator ? : :
If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression (§15.28) of type int whose value is representable in type T, then the type of the conditional expression is T
写的时候
(a > b) ? 'a' : 65
第二种类型转换为字符。
通过 JLS,它解释了其他情况下的行为(相同的方法)。
对原始数使用三元运算符时,第二个和第三个操作数受二进制数值提升的影响。在您的例子中,int
被转换为 double
。这在 JLS #15.25.
中指定
此行为的原因是带有三元运算符的表达式具有明确定义的类型。 JLS比较详细的描述了这个类型是如何求值的,但是粗略的说,就是冒号前的表达式类型和冒号后的表达式类型的最小上界。
例如,如果b
是boolean
,i
是int
,d
是double
,那么[的类型=16=] 是 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 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式 (§15.28),其值可以用 T 类型表示,则类型条件表达式的是 T.
如果其中一个操作数是 T 类型,其中 T 是 Byte、Short 或 Character,而另一个操作数是 int 类型的常量表达式,其值可表示为 U 类型,这是应用的结果拆箱转换为T,则条件表达式的类型为U。
否则,二进制数值提升(§5.6.2)应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。
将类型转换为相应的原始类型,这称为拆箱。
如果一个操作数是常量 int(拆箱前不是 Integer),其值可以用另一种类型表示,则 int 操作数将转换为另一种类型。
否则,较小的类型将转换为下一个较大的类型,直到两个操作数具有相同的类型。转换顺序为:
byte -> short -> int -> long -> float -> double
char -> int -> long -> float -> double
最终整个条件表达式获得其第二个和第三个操作数的类型。
假设我们有一个 StringBuilder 和一个 double。现在想追加双倍。如果双精度可以表示为整数(例如 3.0、5.0 等),我想将其添加为整数,否则为双精度。
第一个实现方法是:
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
上投射时它才有效......但每次都不是我想要的。这是什么问题?为什么三元运算符不起作用?
JLS - 15.25 中记录了此行为。 Conditional Operator ? : :
If one of the operands is of type T where T is byte, short, or char, and the other operand is a constant expression (§15.28) of type int whose value is representable in type T, then the type of the conditional expression is T
写的时候
(a > b) ? 'a' : 65
第二种类型转换为字符。
通过 JLS,它解释了其他情况下的行为(相同的方法)。
对原始数使用三元运算符时,第二个和第三个操作数受二进制数值提升的影响。在您的例子中,int
被转换为 double
。这在 JLS #15.25.
此行为的原因是带有三元运算符的表达式具有明确定义的类型。 JLS比较详细的描述了这个类型是如何求值的,但是粗略的说,就是冒号前的表达式类型和冒号后的表达式类型的最小上界。
例如,如果b
是boolean
,i
是int
,d
是double
,那么[的类型=16=] 是 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 是 byte、short 或 char,而另一个操作数是 int 类型的常量表达式 (§15.28),其值可以用 T 类型表示,则类型条件表达式的是 T.
如果其中一个操作数是 T 类型,其中 T 是 Byte、Short 或 Character,而另一个操作数是 int 类型的常量表达式,其值可表示为 U 类型,这是应用的结果拆箱转换为T,则条件表达式的类型为U。
否则,二进制数值提升(§5.6.2)应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。
将类型转换为相应的原始类型,这称为拆箱。 如果一个操作数是常量 int(拆箱前不是 Integer),其值可以用另一种类型表示,则 int 操作数将转换为另一种类型。 否则,较小的类型将转换为下一个较大的类型,直到两个操作数具有相同的类型。转换顺序为:
byte -> short -> int -> long -> float -> double
char -> int -> long -> float -> double
最终整个条件表达式获得其第二个和第三个操作数的类型。