前情提要:
- 【2023,学点儿新Java-33】字符型变量char | 布尔类型变量 boolean:true、false
- 【2023,学点儿新Java-32】Java基础小练习:根据圆周率与半径求圆的面积 | 温度转换 | 计算矩形面积 | 判断奇偶数 | 年龄分类
- 【2023,学点儿新Java-31】测试:整型和浮点型变量的使用 | 附:计算机存储单位(转换关系)| 企业真题:为什么0.1+0.2不等于0.3
- …
- 更多系列文章,可参阅本专栏或博主主页哦~
高考分数的高低是别人赋予的意义,而你赋予它的没有意义,只有三年的青春。
🎯作者主页: 追光者♂🔥
🌸个人简介:
💖[1] 计算机专业硕士研究生💖
🌟[2] 2022年度博客之星人工智能领域TOP4🌟
🏅[3] 阿里云社区特邀专家博主🏅
🏆[4] CSDN-人工智能领域优质创作者🏆
📝[5] 预期2023年10月份 · 准CSDN博客专家📝
- 无限进步,一起追光!!!
🍎感谢大家 点赞👍 收藏⭐ 留言📝!!!
🌿本篇,主要介绍 java中的基本数据类型变量的运算规则,具体介绍自动类型提升 以及 强制类型转换。尽量用通俗易懂的语言讲解清楚,并给出简单易理解的示例和说明,希望对大家有所帮助!有用的话,就点个赞吧!(要是收藏+关注(三连),那博主会更开心!)抽时间为大家带来更多干货知识~
🕝目录
我们知道,在Java程序中,不同的基本数据类型(只有7种,不包含boolean类型)变量的值 经常需要进行相互转换。
转换的方式有两种:自动类型提升
和强制类型转换
。
💥一、自动类型提升
✨1.1 介绍
首先来介绍自动类型提升的知识。
规则:将取值范围小(或容量小)的类型 自动提升为 取值范围大(或容量大)的类型 。
这就好比 :估计这也是我们大多数人的“梦想”吧~~
基本数据类型的转换规则 如下图所示:
✨1.2 举例说明
(1)当把存储范围小的值(常量值、变量的值、表达式计算的结果值)赋值给了存储范围大的变量时:
int i = 'A';//char自动升级为int,其实就是把“字符的编码值”赋值给i变量了
double d = 10;//int自动升级为double
long num = 1234567; //右边的整数常量值 如果在int范围呢,编译和运行都可以通过,这里涉及到数据类型转换
//byte bigB = 130;//错误,右边的整数常量值 超过byte范围
long bigNum = 12345678912L;//右边的整数常量值 如果超过int范围,必须加L,显式表示long类型。否则编译不通过
(2)当存储范围小的数据类型 与 存储范围大的数据类型变量 一起混合运算时,会按照其中最大的类型运算。
int i = 1;
byte b = 1;
double d = 1.0;
double sum = i + b + d;//混合运算,升级为double
(3)当byte,short,char数据类型的变量 进行算术运算时,按照int类型处理。
byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2;//编译报错,b1 + b2自动升级为int
char c1 = '0';
char c2 = 'A';
int i = c1 + c2;//至少需要使用int类型来接收
System.out.println(c1 + c2);//113
✨1.3 来看一个 小练习:
设 x 为float型变量,y为double型变量,a为int型变量,b为long型变量,c为char型变量,则表达式
x + y * a / x + b / y + c
的值类型为:
A. int B. long C. double D. char
解析:
答案是
double
,因为在表达式中 包含了double类型的变量y和操作符乘法(*)和除法(/),而且还涉及到 除法操作符的优先级高于加法操作符。根据C/C++语言的运算规则,有以下几点可以解释为什么答案是double: (注:不仅适用于C/C++,Java亦可~~)
-
当一个表达式中包含不同类型的操作数时,C/C++会自动进行类型转换,将较低精度的操作数转换为较高精度的操作数
。在这个表达式中,int类型的变量a会被自动转换为double类型,保证了乘法结果的类型是double。 -
除法操作符(/)在C/C++中 对于整数类型会进行整数除法,而对于浮点类型会进行浮点除法
。所以y * a / x中,y*a的结果会是double类型的,x的值也会被自动转换为double类型,保证整个除法结果的类型是double。 -
加法操作符(+)在C/C++中要求参与运算的操作数类型一致,如果不一致会进行类型提升
。在这个表达式中,b/y的结果是long类型的,但是加上前面已经是double类型的结果,会将long类型提升为double类型。 -
最后加上char类型的变量c,根据C/C++的类型提升规则,char类型的值会被自动提升为int类型。
因此,整个表达式中的操作数类型都是double类型,所以表达式的值类型为double。
💥二、强制类型转换
✨2.1 问题引入
思考一个问题:将3.14
赋值到int
类型变量会发生什么?
————产生编译失败,肯定无法赋值!
int i = 3.14; // 编译报错
想要赋值成功,只有通过强制类型转换
,将double
类型强制转换成int
类型才能赋值。
形象一点儿,就好比:
规则:将取值范围大(或容量大)的类型 强制转换成 取值范围小(或容量小)的类型。
值得指出的是:自动类型提升是Java自动执行的,而强制类型转换是自动类型提升的逆运算,需要我们自己手动执行。
具体转换格式:
数据类型1 变量名 = (数据类型1)被强转数据值; //()中的数据类型必须<=变量值的数据类型
来看下面的例子:
✨2.2 举例说明
(1)当把存储范围大的值(常量值、变量的值、表达式计算的结果值)强制转换为 存储范围小的变量时,可能会损失精度
或溢出
。
int i = (int)3.14;//损失精度
double d = 1.2;
int num = (int)d;//损失精度
int i = 200;
byte b = (byte)i;//溢出
(2)当某个值 想要提升数据类型时,也可以使用强制类型转换。这种情况的强制类型转换是没有风险
的,通常省略。
int i = 1;
int j = 2;
double bigger = (double)(i/j);
(3)声明long类型变量时,可以出现 省略后缀的情况。float则不同。
long l1 = 123L;
long l2 = 123;//如何理解呢? 此时可以看做是int类型的123自动类型提升为long类型
//long l3 = 123123123123; //报错,因为123123123123超出了int的范围。
long l4 = 123123123123L;
//float f1 = 12.3; //报错,因为12.3看做是double,不能自动转换为float类型
float f2 = 12.3F;
float f3 = (float)12.3;
✨2.3 小练习:能否通过编译?
1)short s = 5;
s = s-2; //判断:no
2) byte b = 3;
b = b + 4; //判断:no
b = (byte)(b+4); //判断:yes
3)char c = ‘a’;
int i = 5;
float d = .314F;
double result = c+i+d; //判断:yes
4) byte b = 5;
short s = 3;
short t = s + b; //判断:no
需要知道,“大的”要是 想往 “小的”转,需要使用 强制转换符(具体地数据类型) 才行。(否则,编译时就会报错!)
✨2.4 小问答:为什么标识符的声明规则里要求不能数字开头?
//如果允许数字开头,则如下的声明编译就可以通过:
int 123L = 12;
//从而,如下的声明中 l的值到底是123?还是变量123L对应的取值12呢? 出现歧义了。
long l = 123L;
啰嗦一下:
就是说,如果说 允许声明标识符时 以数字开头,那么我们可以将 int 123L = 12;
理解为变量 123L 的取值是12。
那么同样地,若根据赋值语句, long l = 123L;
意思就是 变量l的值 和 变量123L 的取值相同,都是12。
但是,对于 long l = 123L;
,还可以这样理解:这就是一个普通的赋值语句啊, 变量 l 就是一个普通的长整型变量,这时候 123 就是 变量l的值了。——————出现歧义了!!! 123 到底是 变量l的值 还是 变量l的值 与 变量123L的值相同 是12呢?
我想我已经解释地很清楚啦!没看明白的朋友,再想想,很简单的哟!
事实上,标识符的声明规则要求不能以数字开头主要有以下几个原因:
总的来说,禁止标识符以数字开头是为了消除歧义,与常量区分,提高代码可读性,以及遵循命名规范。这样能够保证代码的可维护性和可理解性。
-
消除歧义:如果允许标识符以数字开头,那么编译器在识别
标识符
和整型字面量
时可能会产生歧义。例如,如果允许变量名直接以数字开头,那么编译器在处理类似于"123"的标识符时无法确定这是一个变量名还是一个整数字面量。 -
与常量区分:在某些编程语言中,常量的表示方式与标识符类似,通过 在数字前 添加前缀或后缀 来表示
不同的数据类型
(如0x表示十六进制数,0b表示二进制数)。如果允许标识符以数字开头,那么在这种情况下很难区分常量和标识符。 -
提高可读性:标识符的主要目的是 用来命名变量、函数、类等代码实体,以便于人们理解和阅读代码。
如果允许标识符以数字开头,可能会使代码变得 难以理解和阅读
,因为 数字 通常不具备某种含义或描述的能力
。 -
遵循命名规范:各种编程语言都有一套命名规范或约定,其中包括不以数字开头的规则。这些规范的目的是
提高代码的一致性、可读性和可维护性
。通过禁止以数字开头,可以强制开发人员遵循这些规范,使代码更易于理解和维护。
💥三、整体小练习(简单示例代码+说明)
结合注释的说明 与 实际的小例子,可以快速了解 自动类型提升 以及 强制类型转换的知识~
/*
测试基本数据类型变量间的运算规则。
1. 这里提到可以做运算的基本数据类型有7种,不包含boolean类型。
2. 运算规则包括:
① 自动类型提升
② 强制类型转换
3. 此VariableTest3.java用来测试自动类型提升
规则:当容量小的变量与容量大的变量做运算时,结果自动转换为容量大的数据类型。
byte 、short 、char ---> int ---> long ---> float ---> double
特别的:byte、short、char类型的变量之间做运算,结果为int类型。
说明:此时的容量小或大,并非指占用的内存空间的大小,而是指表示数据的范围的大小。
long(8字节) 、 float(4字节)
*/
class VariableTest3 {
public static void main(String[] args) {
int i1 = 10;
int i2 = i1;
long l1 = i1;
float f1 = l1;
byte b1 = 12;
int i3 = b1 + i1;
//编译不通过
//byte b2 = b1 + i1;
//**********************************************
//特殊的情况1:byte、short之间做运算
byte b3 = 12;
short s1 = 10;
//编译不通过
//short s2 = b3 + s1;
i3 = b3 + s1;
byte b4 = 10;
//编译不通过
//byte b5 = b3 + b4;
//特殊的情况2:char
char c1 = 'a';
//编译不通过
//char c2 = c1 + b3;
int i4 = c1 + b3;
//**********************************************
//练习1:
long l2 = 123L;
long l3 = 123; //理解为:自动类型提升 (int--->long)
//long l4 = 123123123123; //123123123123理解为int类型,因为超出了int范围,所以报错。
long l5 = 123123123123L;//此时的123123123123L就是使用8个字节存储的long类型的值
//练习2:
float f2 = 12.3F;
//编译不通过
//float f3 = 12.3; //不满足自动类型提升的规则(double --> float)。所以报错
//练习3:
//规定1:整型常量,规定是int类型。
byte b5 = 10;
//byte b6 = b5 + 1;
int ii1 = b5 + 1;
//规定2:浮点型常量,规定是double类型。
double dd1 = b5 + 12.3;
//练习4:说明为什么不允许变量名是数字开头的。为了“自洽”
/*
int 123L = 12;
long l6 = 123L;
*/
}
}
当然,这里 我没有打印输出内容,只是简单测试编译能否通过,大家可以自行打开注释来运行测试学习,看能否编译通过
(javac 文件名.java
)即可~
🍒 热门专栏推荐:
- 🥇Python&AI专栏:【Python从入门到人工智能】
- 🥈前端专栏:【前端之梦~代码之美(H5+CSS3+JS.】
- 🥉文献精读&项目专栏:【小小的项目 (实战+案例)】
- 🍎C语言/C++专栏:【C语言、C++ 百宝书】(实例+解析)
- 🍏Java系列(Java基础/进阶/Spring系列/Java软件设计模式等)
- 🌞问题解决专栏:【工具、技巧、解决办法】
- 📝 加入Community 一起追光:追光者♂社区
持续创作优质好文ing…✍✍✍
记得一键三连哦!!!
求关注!求点赞!求个收藏啦!