
2.4 数据类型转换
通常整型、浮点型、字符型数据可能需要混合运算或相互赋值,这就涉及类型转换的问题。Java语言是强类型的语言,即每个常量、变量、表达式的值都有固定的类型,而且每种类型都是严格定义的。在Java程序编译阶段,编译器要对类型进行严格的检查,任何不匹配的类型都不能通过编译器。例如,在C/C++中可以把浮点型的值赋给一个整型变量,在Java中这是不允许的。如果一定要把一个浮点型的值赋给一个整型变量,需要进行类型转换。
在Java中,基本数据类型的转换分为自动类型转换和强制类型转换两种。
2.4.1 自动类型转换
自动类型转换也称加宽转换,是指将具有较少位数的数据类型转换为具有较多位数的数据类型。例如:

将byte型变量b的值赋给int型变量i,这是合法的,因为int型数据占的位数多于byte型数据占的位数,这就是自动类型转换。
以下类型之间允许自动转换:
- 从byte到short、int、long、float或double;
- 从short到int、long、float或double;
- 从char到int、long、float或double;
- 从int到long、float或double;
- 从long到float或double;
- 从float到double。
这种转换关系可用图2-1表示。

图2-1 基本类型的自动转换
在图2-1中,箭头方向表示可从一种类型自动转换成另一种类型。从一种整数类型扩大转换到另一种整数类型时,不会有信息丢失的危险。同样,从float转换为double也不会丢失信息。但从int或long转换为float,从long转换为double可能发生信息丢失。图2-1中的6个实心箭头表示不丢失精度的转换,3个虚线箭头表示的转换可能丢失精度。
例如,下面代码的输出就丢失了精度。

当使用二元运算符对两个值进行计算时,如果两个操作数类型不同,一般要自动转换成更宽的类型。例如,计算n + f,其中n是整数,f是浮点数,则结果为float型数据。对于宽度小于int型数据的运算,结果为int型。
注意:布尔型数据不能与其他任何类型的数据相互转换。
2.4.2 强制类型转换
可以将位数较多的数据类型转换为位数较少的数据类型,如将double型数据转换为byte型数据,这时需要通过强制类型转换来完成。其语法是在括号中给出要转换的目标类型,随后是待转换的表达式。例如:

上面语句的最后输出结果是−56。转换过程是先把d截去小数部分转换成整数,但转换成的整数也超出了byte型数据的范围,因此最后只得到该整数的低8位,结果为−56。
由此可以看到,强制类型转换有时可能要丢失信息。因此,在进行强制类型转换时应测试转换后的结果是否在正确的范围。
一般来说,以下类型之间的转换需要进行强制转换:
- 从short到byte或char;
- 从char到byte或short;
- 从int到byte、short或char;
- 从long到byte、short、char或int;
- 从float到byte、short、char、int或long;
- 从double到byte、short、char、int、long或float。
2.4.3 表达式中类型自动提升
除了赋值可能发生类型转换外,在含变量的表达式中也有类型转换的问题,如下所示:

上面代码中,尽管a + b的值没有超出byte型数据的范围,但是如果将其赋给byte型变量c将产生编译错误。这是因为,在计算表达式a + b时,编译器首先将操作数类型提升为int类型,最终计算出a+b的结果90是int类型。如果要将计算结果赋给c,必须使用强制类型转换。这就是所谓的表达式类型的提升。
下面代码不发生编译错误,即常量表达式不发生类型提升。

自动类型转换和强制类型转换也发生在对象中,对象的强制类型转换也使用括号实现。关于对象类型的转换问题,请参阅7.5节“对象转换与多态”。
下面的程序要求用户从键盘输入一个double型数,输出该数的整数部分和小数部分。
程序2.6 FractionDemo.java

下面是程序的一次运行结果:
