我遇到了一个我不太了解的奇怪问题,但它并不是我节目的一个显示器。我根据条件的结果设置short
变量的值,如果我使用标准if / else但是如果我使用速记条件赋值则不能正常工作。
这是一个简单的例子:
public class ShortTest {
public static void main(String args []) {
int i = 0;
short s = 0;
// This always works
if( i < 100 )
s = 0;
else
s = 1;
// This causes an error
s = (i < 100)?1:0;
}
}
编译此代码会产生以下结果:
ShortTest.java:13: error: possible loss of precision
s = (i < 100)?1:0;
^
required: short
found: int
1 error
但是,如果您向short
,1
或两者添加强制转换,那么它可以正常工作。所有这三个陈述都有效:
0
s = (i < 100)?(short)1:0;
s = (i < 100)?1:(short)0;
这不是什么大问题,因为if / else很好,但这让我疯了。有没有理由说这些值在短时间条件下无法自动从s = (i < 100)?(short)1:(short)0;
投射到int
?为什么只是其中一个突然使整个声明有效?任何见解将不胜感激!
答案 0 :(得分:5)
1
和0
视为文字int
值,此操作的结果为int
,编译器无法缩小此范围。您应该明确添加一个强制转换:
s = (short) ((i < 100)? 1:0);
Java Language Specification. Chapter 15. Expressions. 15.25. Conditional Operator ?.
中对此进行了解释条件运算符有三个操作数表达式。
?
出现在第一个和第二个表达式之间,:
出现在第二个和第三个表达式之间。(...)
如果第二个和第三个操作数表达式都是数值表达式,则条件表达式是数字条件表达式。
(...)
数字条件表达式是独立表达式(第15.2节)。
数字条件表达式的类型确定如下:
如果第二个和第三个操作数具有相同的类型,那么这就是条件表达式的类型。
如果第二个和第三个操作数之一是原始类型T,而另一个操作数的类型是将装箱转换(第5.1.7节)应用于T的结果,那么条件表达式的类型是吨。
如果其中一个操作数的类型为字节或字节,另一个操作数的类型为short或Short,则条件表达式的类型很短。
如果其中一个操作数是T类型,其中T是byte,short或char,另一个操作数是int类型的常量表达式(第15.28节),其值可在类型T中表示,那么条件表达式的类型是T.
如果其中一个操作数是T类型,其中T是Byte,Short或Character,另一个操作数是int类型的常量表达式,其值可以在U类型中表示,它是U的结果。将取消装箱转换应用于T,则条件表达式的类型为U。
否则,二进制数字提升(第5.6.2节)将应用于操作数类型,条件表达式的类型是第二个和第三个操作数的提升类型。
请注意,二进制数字促销执行值集转换(第5.1.13节)并可执行拆箱转换(第5.1.8节)。
答案 1 :(得分:0)
添加一些细节:正如已经指出的,整数文字总是具有类型int
(当没有L
后缀时)。这样的陈述:
s = 1; // where s is short
因此,执行从int
到short
的缩小转化。通常,这种转换不会自动进行。但是,JLS的第5.2节有一些适用于常量表达式的特殊规则:
此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):
如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。
如果变量的类型为:
,则可以使用缩小的基元转换,然后进行装箱转换。
字节和常量表达式的值可以在类型字节中表示。
简短,常量表达式的值可以在短类型中表示。
字符和常量表达式的值可以在char类型中表示。
这意味着这也是合法的:
s = 1 + 2;
但不幸的是不是这样:
s = (i < 100) ? 1 : 0;
因为右边的表达式不符合常量表达式的定义。从理论上讲,§5.2可以允许这种情况,通过将常量表达式或应用于条件表达式,其中第二个和第三个操作数都是常量表达式(或条件表达式,允许,递归)。是否值得将此视为语言变化,我无法分辨。