学科分类
目录
Java基础

变量的类型转换

在程序中,当把一种数据类型的值赋给另一种数据类型的变量时,需要进行数据类型转换。根据转换方式的不同,数据类型转换可分为两种:自动类型转换和强制类型转换。

1.自动类型转换

自动类型转换也叫隐式类型转换,指的是两种数据类型在转换的过程中不需要显式地进行声明。当把一个类型取值范围小的数值直接赋给另一个取值范围大的数据类型变量时,系统就会进行自动类型转换,否则需要进行强制类型转换。

Java中的自动类型转换就好比将小瓶水倒入到大瓶的换装过程。我们将小瓶水倒入到大瓶中时,由于小瓶的容量比大瓶的容量小,所以倒入的水永远不可能溢出大瓶。同样,在Java中,将取值范围小的数据类型的变量值赋值给取值范围大的数据类型的变量时,程序也不会出现任何问题。

Java中支持的不同数据类型之间的自动转换如图1所示。

图1 自动类型转换图

从图1可以看出,Java中取值范围小的byte、short、char等类型数据都可以自动转换为取值范围大的数据类型(如int类型),并最终都可以自动转换为双精度浮点数类型。例如:

byte b = 3;
int x = b;             // 程序把byte类型的变量b转换成了int类型,无需特殊声明
double y = x;         // 将int类型的变量x转换成double类型,无需特殊声明

上面的语句中,首先将byte类型的变量b的值赋给了int类型的变量x,然后将int类型的变量x赋值给了double类型的y。由于int(double)类型的取值范围大于byte(int)类型的取值范围,编译器在赋值过程中不会造成数据丢失,所以编译器能够自动完成这种转换,在编译时不报告任何错误。

2.强制类型转换

强制类型转换也叫显式类型转换,指的是两种数据类型之间的转换需要进行显式地声明。当两种类型彼此不兼容,或者目标类型取值范围小于源类型时,自动类型转换无法进行,这时就需要进行强制类型转换。

Java中的强制类型转换就好比将大瓶水倒入到小瓶中一样,如果大瓶中的水的容量小于小瓶的大小,那么水是可以完全倒入的;如果大瓶水过多,其容量超过了小瓶的大小,那么多出来的水就会溢出,从而造成损失。同理,将取值范围大的数据类型的变量值赋值给取值范围小的数据类型的变量时,就可能造成数据的丢失,所以系统默认不支持这种行为,只能由开发者自己决定是否进行强制类型转换。

接下来先演示一个错误类型转换的例子,如文件1所示。

文件1 Example01.java

 1    public class Example01 {
 2        public static void main(String[] args) {
 3            int num = 4;
 4            byte b = num;
 5            System.out.println(b);
 6        }
 7    }

程序编译时报错,结果如图2所示。

图2 运行结果

在进行Java代码编写时,Eclipse开发工具会自动对已编写的代码进行检测,如果发现问题,它会以红色波浪线和红叉的形式进行提醒。将鼠标悬停在出现红色波浪线错误的位置时,会出现一个悬浮框,悬浮框内将提示错误信息以及快速解决方案。

从图2可以看出,程序编译过程中出现了类型转换异常,提示“cannot convert from int to byte(无法将int类型转换为byte类型)”。出现这样错误的原因是将一个int型的值赋给byte类型的变量b时,int类型的取值范围大于byte类型的取值范围,这样的赋值可能会导致数值溢出,也就是说一个字节的变量无法存储四个字节的整数值。

在这种情况下,就需要进行强制类型转换,其语法格式如下:

目标类型 变量名 = (目标类型)值;

将文件1中的第4行代码修改为下面的代码:

byte b = (byte) num;

修改后保存源文件,Eclipse中的程序将不再报错。程序的运行结果如图3所示。

图3 运行结果

需要注意的是,在对变量进行强制类型转换时,会发生取值范围较大的数据类型向取值范围较小的数据类型的转换情况,如将一个int类型的数转为byte类型,这样做极容易造成数据精度的丢失。接下来通过一个案例来说明,如文件2所示。

文件2 Example02.java

 1    public class Example02 {
 2        public static void main(String[] args) {
 3            byte a;                // 定义byte类型的变量a
 4            int b = 298;          // 定义int类型的变量b,其表现形式是十六进制
 5            a = (byte) b;
 6            System.out.println("b=" + b);
 7            System.out.println("a=" + a);
 8        }
 9    }

运行结果如图4所示。

>图4 运行结果

文件2中,第5行代码进行了强制类型转换,将一个int类型的变量b强制转换成byte类型,然后再将强转后的结果赋值给byte类型的变量a。从图2-7可以看出,变量b本身的值为“298”,然而在赋值给变量a后,变量a的值却为42,这说明在强制转换过程中丢失了精度。出现这种现象的原因是,变量b为int类型,在内存中占用4个字节,而byte类型的数据在内存中占用1个字节,当将变量b的类型强转为byte类型后,前面3个高位字节的数据已经丢失,这样数值就发生了改变。int类型转byte类型的过程如图5所示。

图5 int类型变量强制转换为byte类型

image-20200525154334368多学一招:表达式类型自动提升

所谓表达式是指由变量和运算符组成的一个算式。变量在表达式中进行运算时,也有可能发生自动类型转换,这就是表达式数据类型的自动提升,如byte、short和char类型的变量在运算期间类型会自动提升为int,然后再进行运算。下面通过一个具体的案例来演示,如文件3所示。*

文件3 Example03.java

 1    public class Example03 {
 2        public static void main(String[] args) {
 3            byte b =3;
 4            short s =4;
 5            char c =5;  
 6            //将byte、short、char类型数值相加,再赋值给byte类型
 7            byte b2 = b+s+c;  
 8             System.out.println("b2=" + b2);
 9        }
 10    }

程序编译报错,如图6所示。

图6 程序编译报错

图6中,出现了和图5相同的类型转换错误,这是因为在表达式b+s+c运算期间,byte类型的b、short类型的s和char类型的c都被自动提升为int型,表达式的运算结果也就成了int型,这时如果将该结果赋给byte型的变量就会报错,此时就需要进行强制类型转换。

要解决文件3中的错误,必须要将文件3中第5行的代码修改为:

byte b2 = (byte) (b+s+c);

再次编译后,程序不会报错,运行结果如图7所示。

图7 运行结果

点击此处
隐藏目录