/**
* Int类型使用纪要:
*
* Java虚拟机在对Int类型的数据进行处理的时候,有两条默认的规则:
* 1. 当程序中出现“整型常量”的时候,默认会以int类型处理;
* 2. 如果算数表达式中出现的所有整形常量(数字)都是int类型,默认的运算结果也是int类型;
*
* 注意:
* 需要注意一点:在程序编辑过程中,编译器只对直接出现的int常量进行超范围检查,
* 但是对于在编译中算数运算、表达式产生的int型值则不会进行范围检查;
*/
public class IntGo {
/**
* Java主函数|入口;
*
* 下面看一个示例:
* @param args
*/
public static void main(String[] args) {
/**
* 我们用”9999999999999999“给long类型的变量l赋值,其实”9999999999999999“这个值
* 并没有超出long的大小。但是编译器认为这条赋值语句有语法错误,这是为什么呢?
*
* 我们一开始的时候说过,当程序中出现“整型常量”的时候,默认都是以int类型存储的。而”9999999999999999“
* 就是直接出现的”整型常量“,所以编译器会把他当作int型看待。尽管它最总被赋值给了long类型。
*
* 刚才说过,编译器会对”直接出现“的int常量进行数据超范围的检查,而”9999999999999999“
* 就是直接出现在程序中的,并且还被当作int整型数据来看待,所以编译器要对其进行检查,而
* 经过检查这个数字已经超过了int类型所表示的范围,所以就会报错;
*
* 解决办法:
* 修改这个错误的方法很简单,只需要在直接出现的整型常量“9999999999999999"这个数字后面加”L“
* 即可解决这个问题;
*/
/**
* 2.
* 上面说了,编译器会对直接出现的整型常量做超范围检查的操作,能够避免int类型数据超出范围存储-
* 导致的数据丢失问题出现。
* 但是对于编译器不报错的情况就需要注意了,下面就来说明一下:
*
* 就像下面的一个例子:
*/
/**
* 计算24小时共计多少微秒;
* (1小时=60分钟)
* (1分钟=60秒)
* (1秒=1,000毫秒)
* (1毫秒=1,000微秒)
* (1微秒=1,000纳秒)
* (1秒=1,000,000微秒)
*
* 根据上面的单位进制可以得到下面的公式:
*/
long lTimeError = 24 * 60 * 60 * 1000 * 1000;
/**
* 上面的计算中,考虑到最终的计算结果会超出int类型的表示范围,在存储的时候很小心的把计算结果保存在
* 了long类型的变量中。(正确计算结果:86,400,000,000)
*
* 但是运行结果却不尽然;
* 如下图:
*/
/**
* 在这个算数运算中,所有出现的整型常量都会被编译器当作int类型的数据进行计算,并且上面的
* 算数运算所有参与运算的常量都是int类型且没有任何一个参数常量出现超范围异常。
* 那为什么最终的结果却出现了差池呢?
* 在运算中,因为全部的数据都是int类型,所以每一步的运算结果都会被保存在一个int型的临时
* 变量中,但是由于每一步的运算结果都不是“直接出现的数字”,因此编译器不会对每一步的结果
* 进行超范围检查。
* 最终的结果就是:随着常数值的越来越大,最终超出了int类型的表示范围。而编译器由于没有对
* 其进行超范围检查,故而在压根不知道当前的这个结果会出现超出范围的情况下,把一个超范围的
* 值赋给了int类型的临时变量,从而出现了“溢出”的现象;int类型取值时会将赋值超出范围的高位
* 部分舍弃,只取了地位数据,最后得到的就是一个错误的结果;
*
* 所以在运算过程中,一定要考虑到运算结果对应的临时类型的取值范围;
* 否则必定会出现运算结果超类型所能表示的最大范围导致“溢出”,最终取值错误的情况;
*
* 当然,解决这个问题的办法也很简单,只需要在运算没有超范围之前升一下对应的类型,增大临时类型
* 能够存储的范围即可;
*
* 就上面的例子,可以在运算结果没有超范围之前升型(加L);
*
* 如下图:
*/
/**
* 关于int类型还有一个问题,int类型最大能够表示的数是2147483647。
* 如下图:
*/
/**
* 倘若以下面的方式循环,表面上看只能执行101次,但其实这是一个死循环;
* 因为2147483647是int类型所能表示的最大的数,如果++1就会变成-2147483648;
* 然后循环就会一直遍历,最终变成一个死循环;
*/