long oneYearWithL = 1000*60*60*24*365L;
long oneYearWithoutL = 1000*60*60*24*365;
你的第一个值实际上是一个长整型(因为 365L
是一个 long
,而 1000*60*60*24
是一个 integer
,所以将一个 long
值和一个 integer
值相乘的结果是一个 long
值。
但是第二个值是一个整数(因为你只是将一个 integer
值与一个 integer
值相乘。所以结果将会是一个 32位
整数。现在所得到的结果超出了整数的实际范围。因此,在分配给变量之前,它被截断以适应有效整数范围。
看看以下的打印语句:-
System.out.println(1000*60*60*24*365L);
System.out.println(1000*60*60*24*365);
System.out.println(Integer.MAX_VALUE);
当您运行上述代码时:-
输出:-
31536000000
1471228928
2147483647
所以,你可以看到它们之间的差异..
011101010111101100010010110000000000
01111111111111111111111111111111
如果你在数字结尾没有加上 L
,那么第一个二进制串中将会被移除4个最高有效位。
于是,该字符串变为...
(0111)01010111101100010010110000000000 -- Remove the most significant bits..
01010111101100010010110000000000 -- Binary equivalent of 1471228928
(你将其作为输出获得)
更新: -
从上面的解释中,您也可以理解,在第一次赋值时,如果您的整数乘法的结果在乘以 365L
之前超出范围,那么它将再次被截断以适合整数范围,或者如果需要,则转换为 2的补码表示
,然后才会将它乘以 long value - 365L
。
例如:-
long thirtyYearWithL = 1000*60*60*24*30*365L
在上面的示例中,考虑第一部分 -
1000*60*60*24*30
。这个乘积的结果是:-
2592000000
。现在让我们看看它在
二进制等价物
中表示为何:-
2592000000 = 10011010011111101100100000000000
01100101100000010011100000000001
二进制补码的十进制表示为1702967297
。因此,在将2592000000
乘以365L
之前,它被转换为-1702967297
。现在,由于此值适合整数范围
:-[-2147483648 to 2147483647]
,因此不会进一步截断。
因此,实际结果将是:-
long thirtyYearWithL = 1000*60*60*24*30*365L
= 2592000000 * 365L
= -1702967297 * 365L = -621583063040
因此,所有这些东西只考虑应用算术运算后最终结果的实际类型
。并且在移动操作时逐个检查每个临时结果,从左到右
(考虑具有从左到右
结合性的运算符)。如果发现任何临时结果超出范围,则会相应地转换为适合所需范围,然后再进行下一个操作。
更新2: -
所以,不是: -
long thirtyYearWithL = 1000*60*60*24*30*365L
如果你将365L
放在开头,那么你就会得到正确的结果:-
long thirtyYearWithL = 365L*1000*60*60*24*30; // will give you correct result
因为此时你的temporary
结果将会是long
类型,并且能够容纳该值。