以下声明给了我一个编译时错误“错误:(19,13)java:不兼容的类型:可能从双精度转换为整数”
int i1 = 10.0;
// Error:(19, 14) java: incompatible types: possible lossy conversion from double to int
问题1
我理解该错误,但编译器可以在这种特殊情况下无法推断出不会损失精度吗?
问题2
如果我明确将double转换为int
,那么即使在此示例中我肯定会失去精度,它也可以很好地编译(甚至不是警告)
int i2 = (int)9999999999999.999999999;
如果我不能编译第一种情况-没有损失-那么为什么第二个带有显式转换的示例甚至没有生成编译器警告?
答案 0 :(得分:2)
理论上,编译器可以推断出#1中的特定示例实际上不会基于文字的值来降低精度,但是正如您所看到的那样-不会。
显式强制转换向编译器发出信号,告知您已知道要处理的情况,因此代码实际进行了编译。但是,大多数IDE也可以配置为在这种情况下发出警告。
答案 1 :(得分:2)
将double
值分配给int
变量将需要narrowing conversion,即使该值是编译时常量,因此需要明确的演员表。
除了可以将int
(或short
或char
)常数值分配给byte
,short
,或char
变量,如果常量确实符合变量值范围(如Java语言规范第5.2. Assignment Contexts节中明确记录的内容),则该变量不进行强制转换:
分配上下文允许将表达式的值分配(§15.26)到变量;表达式的类型必须转换为变量的类型。
分配上下文允许使用以下之一:
如果在应用了上面列出的转换后,结果类型为原始类型(§4.8),则可以应用未经检查的转换(§5.1.9)。
此外,如果表达式是类型为
byte
,short
,char
或int
的常量表达式(§15.28)< / strong>:
如果变量的类型为
byte
,short
或char
,并且常量表达式的值为:可表示为变量的类型。如果变量的类型为:
,可以使用变窄的原始转换,然后是装箱转换。
Byte
,常量表达式的值可以用byte
类型表示。
Short
,常量表达式的值可以用short
类型表示。
Character
,常量表达式的值可以用char
类型表示。
答案 2 :(得分:1)
问题1的答案
根据编译器,精度会下降,因为编译器只会看到您在左侧有一个int变量,在右侧有一个double值。编译器并不聪明,以至于10.0
转换为int时不会失去精度。
理论上可以构建编译器以允许该语句进行编译,但是这样做并没有真正的好处。几乎没有人写int x = 10.0
。
问题2的答案
的确确实存在精度损失,但是为什么编译器没有抱怨?因为您使用了演员表。您写了(int)
。这是向编译器表明您知道自己在做什么。通过编写演员表,您告诉它您知道可能会失去精度。
答案 3 :(得分:1)
有趣的问题
从理论上讲这是可能的,project_id
这样做时不会抱怨:
javac
即使short s = 12;
是12
类型的编译时间常数,也可以推断出没有精度损失。我猜这是编译器团队认为最合适的。
好吧,当您int
是一个不同的故事时,即使您放宽了精度,这就像说“相信我,我知道我在做什么”。