Java 程序中要求参与的计算的数据,必须要保证数据类型的一致性,如果数据类型不一致将发生类型的转换
一个 int 类型变量和一个 byte 类型变量进行加法运算
int i = 1;
byte b = 2;
运算结果,变量的类型将是 int 类型,这就是出现了数据类型的自动类型转换现象
public static void main(String[] args) {
int i = 1;
byte b = 2;
// byte x = b + i; // 报错
//int类型和byte类型运算,结果是int类型
int j = b + i;
System.out.println(j);
}
自动转换:将取值范围小的类型自动提升为取值范围大的类型
我们先看看 Java 中的基本数据类型
Types | Default | Size | Range |
---|---|---|---|
byte | 0 | 8 bits | -128 to 127 |
short | 0 | 16 bits | -32768 to 32767 |
int | 0 | 32 bits | -2147483648 to 2147483647 |
float | 0.0f | 32 bits | ±1.4E-45 to ±3.4028235E+38 |
long | 0L | 64 bits | -9223372036854775808 to 9223372036854775807 |
double | 0.0d | 64 bits | ±4.9E-324 to ±1.7976931348623157E+308 |
--- | --- | --- | --- |
boolean | false | 1bits | NA |
char | ‘\u0000’ | 16 bits | \u0000 to \uFFFF |
自动转换如下图
蓝色箭头指向自动转换时不会造成数据丢失,红色箭头指向在进行自动转换时候则要注意可能会有数据丢失的问题。
结合上文的表和图我们可以发现 自动转换是范围小的可以自动转换为范围大的基本数据类型
byte,short,char-->int-->long-->float-->double
注意:自动转换要提防数据溢出问题,自动转换时数据溢出也是一些企业面试题的考点
public class hello {
public static void main(String[] args) {
int x = 100000000;
int y = 100;
long z = x*y;
System.out.println(z);
}
}
输出结果是:1410065408
如果这种情况出现在金融项目中,一个程序员就可能给公司干倒闭
为什么编译都通过了计算出来的答案却是错的呢?
为什么和正确答案 10000000000
相差了这么多呢?
这不是肯定不是巧合!
我们再来回过头来看看 int 的取值范围
int 的取值范围 -2147483648
to 2147483647
x*y 的正确结果 199000000000
,妈耶!不小心玩现了!
IDE 也没有提示我强制类型转换呀!
x*y 的计算结果超过了 int 的取值范围,我明明记得有自动转换这个东西的,再说 IDE 也没有提示我强制类型转换呀!难道这个东西没起作用?
自动类型转换当然起作用了,不过是在赋值的时候起作用的,x 和 y 都是 int 数据类型,两个 int 相乘 结果还是 int 类型的,然后赋值给 long 类型的 z 在这个时候自动类型转换生效将计算结果(尽管计算结果可能是错的)转换为 long 类型赋值给 z。
当变量的数据类型所提供的位数无法适应某个值时,就会发生溢出(上溢)或下溢。就像往水桶里装水,水满则溢,变量也是这样,如果要存储的值超过了变量所能提供的位数,就会出现问题。
先来看一个例子
假设在一个使用了 2 个字节内存的 short int 类型变量中存储了以下值:
现在高阶位我标红的高阶位方里面是 0,表示正数
学过计算机组成原理而且课上没睡觉的同学已经口算(我不信)算出来了,这是 32 767
的二进制表示。
这也是 2 个字节所能表示的该数据类型的最大值。
现在我们再让它加 1 就会变成下面这个情况
我的天呐!它变性了!口误。。。它变形了,它变成了负值,也就是 -32 768
这不是 32768 而是-32768,二进制 1 流入到高阶位,改变了正负号
。(这种情况属于数据溢出(上溢))
我们把这个图反着来试一试
-32768
减去 1 变成了 32767
你一定发现了什么!
当一个变量保存的数值在其数据类型负值范围的最远端(即最小负值),那么当它被减去 1 时,其高位中的 1 将变为 0,结果数将被解释为正数
当一个变量保存的数值在其数据类型正值范围的最远端(即最大值),那么当它被加 1 时,其高位中的 0 将变为 1,结果数将被解释为负数
发现了规律 就好办了,以后就能盘它!
你 duck 不必去纠结 溢出值的计算,只需要记住溢出对我们得程序没有一点好处,它就是一个 bad word,一些骇客利用内存溢出来实现攻击或入侵,我们要防止溢出情况的发生.
我们的 IDE 通常可以立即发现你在基本数据类型的范围取值的边界进行 +/-的骚操作,会实时告知你此处需要强制类型转换(就是提醒会有精度丢失或计算不准确的情况发生),但是当你在赋值时候直接进行俩个变量的乘法操作时候,至少目前已知的 IDE 是不会检测出来的.