案例描述
同事使用Date类的getTime方法减去30天的毫秒数,反转成Date,发现日期没有像预期那件月份减少一个月,反而增加了。
代码如下:
Date now = new Date();
System.out.println(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date(now.getTime() - 1000*60*60*24*30)));
输出结果:
20181205041335
反编译之:
![](https://img.haomeiwen.com/i14956645/efa50e0b9b79159c.png)
案例分析
1000*60*60*24*30 = 2592000000;
而Integer.MAX_VALUE=2147483647;
30天这个毫秒数值已经溢出。
从反编译结果来看,这个数被解释成long,并且是个负数,所以日期才会不减反增。那么,java对这个整数溢出数怎么个处理逻辑呢?
- 字面值默认类型为int型
0x9A7EC800
- 由于
getTime
函数结果是long型的,会有一个promotion,这个字面值由于是负值,会被符号位补1拓展;
证明:
0x9A7EC800
拓展成8字节为0xFFFFFFFF9A7EC800
0xFFFFFFFF9A7EC800
取反为0x00000000658137ff
0x658137ff+1 =0x65813800
即(0xFFFFFFFF9A7EC800)补 = (-0x65813800)原 = -1702967296
与反编译中constant pool中的数值一致。
![](https://img.haomeiwen.com/i14956645/0fa44eea9cd11919.png)
反思
对于大字面值,需要指定类型:
![](https://img.haomeiwen.com/i14956645/f8e224db7c020faf.png)
L代表long,F代表float,D代表double
![](https://img.haomeiwen.com/i14956645/b21b19c5c762173d.png)
网友评论