转自:微点阅读 https://www.weidianyuedu.com
长整数造成数据溢出
看下面的代码会打印什么?
1public class LongDivision{ 2 public static void main(String args[]){ 3 final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000; 4 final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000; 5 System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY); 6 } 7}
整个过程,除数与被除数都是 long 型,很容易保存这两个数,结果一定是1000,但是结果让你失望了,是 5。
这又是怎么回事呢?首先这个表达式 24606010001000 总是在 int 类型的基础上进行计算。即表达式是按照 int 的规则计算,很容易看出这个表达式计算的范围早已超出 int 的取值范围,纵然使用 long 去存储计算结果,但是在计算的过程中就已经出现计算数据溢出,这是一个隐藏错误。Java 目标确定类型的特性是必须指定数据类型才能按照指定的规则进行运算。就用前面这个例子来看,当指定 24 为 24L 就能防止数据计算溢出,在进行乘法运算的时候就已经是在 long 的基础上进行计算。
1public class LongDivision{ 2 public static void main(String args[ ]){ 3 final long MICROS_PER_DAY = 24L * 60 * 60 * 1000 * 1000; 4 final long MILLIS_PER_DAY = 24L * 60 * 60 * 1000; 5 System.out.println(MICROS_PER_DAY/MILLIS_PER_DAY); 6 } 7}
思考:当操作数很大的时候,要预防操作数溢出,当无法确定计算数会不会溢出,所要做的就是用储存范围最大的类型 long 来进行计算。
long 的 "L" 与 "l" 所引发的错误
从上面 "长整数运算造成数据溢出" 引发又一个问题,看下面例子:
1public class Elementary{ 2 public static void main(String[] args){ 3 System.out.println(12345+5432l); 4 } 5}
乍一看,这很简单,计算结果时是 6666,但是打印的结果是 17777,我开始头晕了,这很不合理。思考过后发现了一个问题,我把 "l" 看作是 "1","l" 只是用于标识 5432 是一个 long 类型,这个视觉上的错误将会引发更严重的问题。思考:小写字母 l 与 1 很容易造成混淆,为了避免这种错误,在表示 long 类型数据要做的就是将 "l" 换做 "L",掐断产生混乱的源头。