运行下面的代码片段:
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
最后打印出来的应该是10吧,错!是5。小改一下便可得到正常的结果1000:
final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000L;
final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L;
System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
注意上面两个整数的右边都添加了一个字母L。
虽然等号的左边定义的是long,但如果所有乘数都是int型的,那么就都按int型来计算,包括结果,如果有溢出的话,并不报错——右边按照int的型运算结束了,溢出也发生了,在cast成long型,错误就带过去了;改后的代码明确了右边运算的范围在long的范围里,没有溢出。
Java Puzzle曰:“当用到大数的时候,要留心溢出问题——它是个温柔的杀手。”(When working with large number, watch out for overflow -- it's a silent killer.),JP亦针对语言设计者有N曰,大致说,为啥Java不能像Ada那样在这种情况下就抛个错呢?为啥不能像Lisp那样去自动转个型呢?为啥不能像Modula-3那么那么做呢?——问题是,无论是Ada, Lisp or Modula-3,sorry啦,我都没用过,这段,当对我弹琴了一番,skim之!
附