代码:
public static void main(String[] args) {
numberNoLSuffixCal();
numberHasLSuffixCal();
}
private static void numberHasLSuffixCal() {
long maxStamp = System.currentTimeMillis();
long minStamp = maxStamp - 30 * 86400 * 1000l;//两个方法中有区别的地方
System.out.println("num has l suffix output==>max:" + maxStamp);
System.out.println("num has l suffix output==>min:" + minStamp);
}
private static void numberNoLSuffixCal() {
long maxStamp = System.currentTimeMillis();
long minStamp = maxStamp - 30 * 86400 * 1000;//两个方法中有区别的地方
System.out.println("num no l suffix output==>max:" + maxStamp);
System.out.println("num no l suffix output==>min:" + minStamp);
}
输出:
重点观察:
“no l”的输出中min的值居然大于max的值;min明明是用max-30天的毫秒数,怎么可能算下来还大了呢?
“has l”的输出中符合预期,正常的两个长整型数字相减的结果。
原因分析:
在numberNoLSuffixCal()
方法中,如果minStamp
的值大于maxStamp
,这通常是由于计算过程中发生了整数溢出。在Java中,long
类型的取值范围是-9,223,372,036,854,775,808
到9,223,372,036,854,775,807
。如果计算的结果超出了这个范围,就会发生溢出,导致数值变得非常大或者非常小。
在numberNoLSuffixCal()
方法中,minStamp
是通过maxStamp - 30 * 86400 * 1000
计算得出的。这里的30 * 86400 * 1000
是一个int
类型的表达式,其值超过了int
类型的最大值2,147,483,647
。因此,在运算时,这个表达式的结果会溢出,并且得到一个错误的int
类型的值。随后,这个错误的int
类型的值会被隐式地转换为long
类型,并与maxStamp
进行减法运算。由于这个错误的int
值实际上是一个负数(因为溢出),所以最终的minStamp
值会异常地大,甚至可能大于maxStamp
。
记录一下吧,这个问题相信小伙伴们很容易忽略~~~