Java 数据类型自动转换中的溢出情况

雪月书韵茶香 专心做可以提升自己的事情学习并拥有更好的技能成为一个值得交往的人 本文由博客端 https://www.xysycx.cn 主动推送
本贴最后更新于 449 天前,其中的信息可能已经水流花落

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

自动转换如下图
image.png

蓝色箭头指向自动转换时不会造成数据丢失,红色箭头指向在进行自动转换时候则要注意可能会有数据丢失的问题。

结合上文的表和图我们可以发现 自动转换是范围小的可以自动转换为范围大的基本数据类型

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

如果这种情况出现在金融项目中,一个程序员就可能给公司干倒闭
image.png

为什么编译都通过了计算出来的答案却是错的呢?
为什么和正确答案 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 类型变量中存储了以下值:

image.png

现在高阶位我标红的高阶位方里面是 0,表示正数

学过计算机组成原理而且课上没睡觉的同学已经口算(我不信)算出来了,这是 32 767 的二进制表示。
这也是 2 个字节所能表示的该数据类型的最大值。

现在我们再让它加 1 就会变成下面这个情况

image.png

我的天呐!它变性了!口误。。。它变形了,它变成了负值,也就是 -32 768

这不是 32768 而是-32768,二进制 1 流入到高阶位,改变了正负号
。(这种情况属于数据溢出(上溢))

我们把这个图反着来试一试

image.png

-32768 减去 1 变成了 32767

你一定发现了什么!

当一个变量保存的数值在其数据类型负值范围的最远端(即最小负值),那么当它被减去 1 时,其高位中的 1 将变为 0,结果数将被解释为正数

当一个变量保存的数值在其数据类型正值范围的最远端(即最大值),那么当它被加 1 时,其高位中的 0 将变为 1,结果数将被解释为负数

发现了规律 就好办了,以后就能盘它!

你 duck 不必去纠结 溢出值的计算,只需要记住溢出对我们得程序没有一点好处,它就是一个 bad word,一些骇客利用内存溢出来实现攻击或入侵,我们要防止溢出情况的发生.

我们的 IDE 通常可以立即发现你在基本数据类型的范围取值的边界进行 +/-的骚操作,会实时告知你此处需要强制类型转换(就是提醒会有精度丢失或计算不准确的情况发生),但是当你在赋值时候直接进行俩个变量的乘法操作时候,至少目前已知的 IDE 是不会检测出来的.

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    2923 引用 • 8123 回帖 • 669 关注

广告 我要投放

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...