首页 > 编程语言 >Java千问07:你真的会用Java的int型变量吗?有些坑你真的不知道!

Java千问07:你真的会用Java的int型变量吗?有些坑你真的不知道!

时间:2022-12-28 10:02:59浏览次数:63  
标签:Java 千问 int long 编译器 类型 数据 运算

​我们在进行Java编程的时候,使用最频繁的数据类型基本上就是int型了。平时在使用这种数据类型的过程中,我们似乎也并没有感觉到有什么太多需要注意的地方,其实int类型的变量在使用过程中也会有一些隐藏很深的坑,我们通过一篇短文来了解一下。

首先我们先来明确一下Java虚拟机在对int型数据进行处理时默认的两条规则​

1. 当程序出现“整型常量”的时候,默认都是以int型存储的​

2. 如果算术表达式中出现的所有的数字都是int型的,默认运算结果也是int类型​

了解了这两条基本规则之后,我们接着往下看。在程序编译过程中,编译器只对“直接出现”的int常量进行数据超范围检查,而对“运算产生的int型值”并不进行超范围检查。这句话是什么意思呢?我们来看下面的代码

Java千问07:你真的会用Java的int型变量吗?有些坑你真的不知道!_int

我们使用数字2200000000给long类型的变量x赋值,2200000000其实并没有超过long类型数据的范围,但是编译器却认为这条语句有语法错误,为什么呢?刚才我们强调过:当程序出现“整型常量”的时候,默认都是以int型存储的,这个2200000000就是一个“整型常量”,所以编译器会把它当作int型数据来看待,尽管它最终被赋值给了long类型的变量。刚才说过,编译器会对“直接出现”的int常量进行数据超范围检查,这个2200000000就是“直接出现”在程序中的,并且还被当作了int型,所以编译器要对其进行检查,经检查发现这个数字已经超过了int型的表示范围,所以会报错。​

修改这个错误的办法也很简单,只要在2200000000后面加一个字母L就可以让它转换为long类型数据,这样语法错误自然消失。那么,既然编译器已经已经用如此明显的形式给我们报错,我们当然能排除掉错误,但是对于编译器不报错的情况,我们很有可能就会“掉坑”,来看下面的代码:

Java千问07:你真的会用Java的int型变量吗?有些坑你真的不知道!_int_02

我们希望计算一天有多少微秒(1秒=1百万微秒),于是我们给出了上面的计算公式,并且考虑到计算结果会超过int类型的表示范围,我们很小心的把计算结果保存到了一个long类型的变量当中。首先明确,这个计算结果是86400000000,它并没有超过long类型数据的表示范围,但是,运行结果如下图,是一个完全错误的数值

Java千问07:你真的会用Java的int型变量吗?有些坑你真的不知道!_编译器_03

这是为什么呢?刚才已经强调过:算术表达式当中,如果全部是int类型的数据进行运算,那么运行结果也是int类型的。现在程序中的算术表达式就是典型的这种情况:全部由int类型的数据参与运算,所以运算结果也是int类型的。虽然明白了这个道理,但是还是没说清楚计算结果为什么如此“不靠谱”。解释这个现象,就必须用到我们刚才所说的一条规则:编译器对“运算产生的int型值”并不进行超范围检查。在运算过程中,因为全部数据都是int型,所以每一步运算结果都会被保存到一个int型的临时变量当中。但是因为每一步的运算结果都不是“直接出现的数字”,所以编译器对每一步运算结果都不做超范围检查,那么,算着算着,相乘的结果不知不觉就已经超过了int类型的表示范围,虽然超过了范围,但编译器坐视不理,仍然进行赋值。把一个超范围的数据赋值给int型的临时变量会导致“溢出”现象,也就是说,运算结果超范围的高位部分被丢弃了,只保留了低位数据,从而导致产生了一个错误结果。所以,我们不能简单认为理论上的计算结果86400000000没有超过long类型数据的表示范围,就可以直接把这些int型数据直接进行相乘并赋值。消除这个程序错误的方法也很简单,就是把乘法表达式当中任意一个乘数因子的后面加上字母L,使其变成一个long类型的数据就可以了。一旦编译器发现有long类型的数据参与了运算,就不会把运算结果看作是int型,而是自动提升为long类型。这样就不会出错了。​

关于int型数据,还有一个隐藏很深的大坑,大家来看代码

Java千问07:你真的会用Java的int型变量吗?有些坑你真的不知道!_数据_04

这个循环看似只能执行101次,其实它是一个无限循环(死循环)!原因就是2147483647是int类型数据所能表示的最大值,而循环变量i在到达最大值以后,再进行加1操作,得到却是-2147483648!这导致i永远都会满足循环条件,从而使看起来有限次数的循环变成了无限。至于为什么在int型最大值的基础上再加1会变成-2147483648,大家可以看《​​Java千问06:Java语言中最大的整数再加1等于多少?看完秒懂!​​》,这里就不详细解释了。​

看完这篇文章之后,是不是有一种被惊出一身冷汗的感觉呢?所以千万不要小看一个简单的int类型哟!

如果想系统学习Java编程可以点击这里观看我在本站的视频课程。


标签:Java,千问,int,long,编译器,类型,数据,运算
From: https://blog.51cto.com/mugexuetang/5973823

相关文章

  • Java千问08:关于Java语言复合赋值运算符的两个问题,快来瞧瞧!
    ​我们知道,在Java以及很多高级编程语言当中,都有一种运算符叫做复合赋值运算符。复合赋值运算符由两个符号组成,它所能完成的运算操作也分为两步:第一步是运算,第二步是赋值。比......
  • JAVA代码审计_若依管理系统
    若依管理系统代码审计该项目使用Mybatis作为数据库持久化框架。全局搜索${、关注xxxmapper.xml文件寻找SQL注入。1)后台角色管理处SQL注入漏洞点“SysRoleMapper.x......
  • windows配置java17
    最近重置系统了,所有东西都得重装一遍。但是为了能继续撸树盖房子,java又是必不可少的,先把java搞回来再说。jdk下载地址https://www.oracle.com/java/technologies/javase......
  • 问题解决:Failed to download metadata for repo ‘appstream‘: Cannot prepare inter
    https://cloud.tencent.com/developer/article/1993317 大家都知道Centos8于2021年年底停止了服务,大家再在使用yum源安装时候,出现下面错误“错误:Failedtodownloadmet......
  • Loki Promtail 使用 multiline 对Java 堆栈日志进行多行处理的示例
    promtail使用multiline处理java多行日志文本的示例Environment:promtail_version:v2.7.1originJavalogcontent:logfilecontentstdout-a.log:2022-Dec-270......
  • JavaWeb
    JavaWeb1、基本概念1.1前言静态webhtmlcss动态web技术栈:Servlet/JSP、ASP、php动态web资源开发技术统称为JavaWeb1.2web应用程序:可以提供浏览......
  • Java String类为什么用final修饰
    在Java语言中,使用final修饰符修饰的类是不可以被继承的,也就是说,如果一个类被声明为final,则不能被其他类所继承。因此,当String类被声明为final时,意味着它不能被其他类所继承......
  • cpp jsoncpp serialize vector class into plain text file and deserialize from pla
    //model/book.h#pragmaonce#ifndef__book_h__#define__book_h__#include<iostream>usingnamespacestd;structbook{uint64_tidx;uint64_tid;......
  • hrnet的get_joint
    他的第18个keypoint存的是平均坐标。defget_joints(self,anno):num_people=len(anno)area=np.zeros((num_people,1))joints=np.zeros(......
  • 为 Github 创造 Integration
    现在你可以从我们的集成件目录里面找到更多工具。这个目录目前有超过15个分类—从API管理到应用监控,Github的集成件可以支持您的开发周期的每一个阶段。......