自动类型转换
赋值的自动类型转换
当把一个表述范围小的字面量或者变量直接赋值给另一个表述范围大的变量时,系统将可以进行自动类型转换。
具体的规则很简单,看下面的自动类型转换图即可:
规则为:箭头左边的类型会自动转换为箭头右边的类型。有精度损失的转换用虚线表示
注意:
1、java的char类型是2个字节,short也是2个字节(java中char的类型宽度和C++里的不一样),它们之间不能自动类型转换。
2、虽然char类型是2个字节,而byte是1个字节,但byte类型不能自动转换为char类型。
3、int转换为float有精度损失,但是转换成double不会。因为double处理尾数有52位,超过了int的32位,可以完全保存int的数据。
4.long有64位,所以,不管转换为double还是float,都会损失精度。因为double的尾数部分也只有52位。
运算符的自动类型转换
“+”不仅可以用于算术运算,也是字符串的连接运算符。
任何基本类型的值和字符串值进行连接运算时,都会自动转换为字符串。
比如:String s = true + “”; 这时候,s就等于"true",也就是true的字符串形式。
如果想把基本类型的值转换为对应的字符串形式,就可以用+连接空字符串。
表达式的自动提升
当算术表达式中包含多个基本类型的值时,整个表达式的数据类型会按照如下规则自动提升:
1.所有byte,short,char类型会自动提升到int类型。
比如:
short sValue1 = 2;
short sValue2 = 4;
//下面这行代码会报错,因为右边表达式的2个short类型都自动提升为int类型,相当于将int类型赋值给short类型
short sValue3 = sValue1 - sValue2;
//必须在右边表达式前面使用强制类型转换,下面的代码就能正确运行
short sValue3 = (short)(sValue1 - sValue2);
2.整个算术表达式的数据类型会自动提升到与表达式中最高等级操作数同样的类型。
比如short sValue = sValue - 2;(易错的知识点)
这行代码会报错,因为表达式会自动转换成int类型(2这个字面量默认为int类型),所以相当于将int类型的值赋值给short类型,所以会报错。
举例2:
Object obj1 = true ? new Integer(1) : new Double(2.0d);
// 结果为1.0而不是1
System.out.println(obj1);
这是因为整个三元运算符的最高数据类型是double类型,所以返回的值1会被自动提升为1.0d。
强制类型转换
强制类型转换的语法格式为:(targetType)value,**圆括号()**就是强制类型转换符。
当将更大的类型转换为更小类型时,会引起溢出。所以需要强制类型转换符显式的告知系统,程序员能接受这种可能的溢出。如果不使用强制类型转换,大的数据类型转换成更小的类型就会报错。
强制类型转换的计算方式
强制类型转换是使用截断的方式计算。
.1.将浮点数转换成整数类型,小数部分就会截断
看下面的例子:
int iValue = (int)3.9;
iValue的值为3,0.9部分会被截断而不是四舍五入。
如果想要四舍五入,应该使用**Math.round()**方法,例子是:
int iValue = (int)Math.round(3.9);
3.9会四舍五入变为4,iValue的值就为4(需要强制转换为int是因为round()方法的返回值为long类型)。
2.将大的整数类型转换为小的整数类型,会对存储的空间进行截断,再按补码方式计算最终结果
例子1:byte bValue = (byte)255;
255是整型字面量,默认为int类型,强制类型转换为byte后,只保留最后的8位。第一位符号位是1,所以转换后按补码计算应该是负数。
1111 1111的补码值就是-1。
所以,bValue的值为-1。
由于这种溢出的存在,所以最好不要对超过小整数类型的值进行强制类型转换。
比如,将值转换为byte类型的变量,值的范围在-128~127才不会出现溢出的情况。
例子2:char cValue = (char)(65536+65);
由于右边的数字超过了char的最大范围,所以会发生截断。会截断掉65536 =
2
16
2^{16}
216,只剩下65。
所以,cValue的值等于65,也就是对应的字符’A’。