前面在学习算术操作符时,我们知道了Java中整数、小数都支持基本算术运算,如加减乘除。当时并没有提到字符是否也支持简单算术运算。
如果我们像这样编写代码,
System.out.println('0' + 'A');
程序在执行这行代码时不会报错,并且会在屏幕上打印
113
大家肯定会疑惑为什么结果会是一个整数。主要原因是在计算字符的“加法运算”时,程序先将字符“0”转换成它的编码48,接着再将字符“A”转换成对应编码65,最后再进行加法运算(48 + 65 = 113)。这就涉及到本节教程的主题了–数据类型转换。
在Java中存在两种类型数据转换,隐式类型转换和显式类型转换。隐式类型转换由程序在执行时自动根据表达式上下文进行类型转换,比如计算两个字符的加法,或者计算一个整数与一个字符的加法。
System.out.println(48 + 'A');
显式类型转换则需要我们在编写代码时主动使用类型转换符,比如转换成常规整型(int)。接下来仍然通过丰富的代码示例来帮助大家理解Java中的这两种类型转换。
System.out.println(120 + 3.14);
如果运行这行代码,屏幕上会打印
123.14
这行代码表面上看是两种不同类型的数字在进行加法运算,实际上是浮点数加法运算。当程序执行时,会首先将整数120转换成浮点数类型,确切地说是转换成双精度浮点类型,因为浮点数3.14被Java默认当作双精度类型处理。
因此,这里就出现了数据类型转换的第一条规则。当表达式中同时出现两种数据类型,小类型会自动转换成大类型。以前面的代码为例,数字120是常规整型,在内存中占32个比特位,而3.14是双精度浮点类型,占用64个比特位,因此这里整数就是小类型,浮点数就是大类型。
如果大家理解了这个,就不会疑惑为什么下面这行代码会正常运行,
System.out.println('a' + 3.14);
这是因为相对于浮点数,字符a是小类型,它在内存中只占16个比特位。
然而像这样编写代码
System.out.println(false + 3.14);
在Java中却是不被支持的。大家需要注意一下。
小类型到大类型的隐式转换,除了可以出现在字符、整数以及浮点数之间,还可以出现在不同细分类型之间,比如常规整型到长整型的自动转换,单精度浮点类型到双精度浮点类型的转换。
System.out.println(100 + 3000000000L);
System.out.println(12.35F + 24.44);
如果大家运行这段代码,屏幕上将会打印
3000000100
36.790000381469724
对于字符的隐式类型转换,情况比较特殊,这是因为程序在执行时会将字符转换成对应的编码,然后才来进行算术运算。
System.out.println('a' + 'A');
System.out.println('a' - 'A');
System.out.println('a' * 'A');
System.out.println('a' / 'A');
System.out.println('a' % 'A');
大家可以试一试在电脑上运行这段代码。
对于显式类型转换,比如将字符“A”转换成整数,可以这样编写代码,
System.out.println((int)'A');
如果运行这行代码,大家的屏幕上将会打印
65
这正是在ASCII编码标准里面大写字母“A”对应的编码“65”。除了常规整型转换符(int),字符类型还可以转换成字节类型、短整型、长整型,甚至还可以转换成浮点类型。
System.out.println((byte)'A');
System.out.println((short)'A');
System.out.println((long)'A');
System.out.println((float)'A');
System.out.println((double)'A');
上面这段代码里面的所有用法都是合法的。
与隐式类型转换不同,显式类型转换除了支持小类型到大类型的转换,比如将字符转换成整数,还支持从大类型到小类型的转换。需要特别注意的是,从大类型到小类型的转换可能会丢失数据,比如将浮点数转换成整数会丢弃小数部分。
System.out.println((int)3.14);
如果大家运行上面这行代码,屏幕上将会打印
3
数字“3.14”的小数部分被程序直接丢弃了。
同样都是整数类型,将位数多的大类型转换成位数少的小类型也会直接丢弃部分数据,以下面这行代码为例,
System.out.println((byte)314);
这里我们尝试将常规整型(int)转换成字节类型(byte)。如果大家学习过二进制表示,容易知道314的最后八位二进制表示为“00111010”,如果将这个用二进制表示的数转换成十进制,刚好是58。这正是上面这行代码会在屏幕上打印出来的结果。
也就是说,用32位二进制表示的整数314,在显式地转换成小类型字节类型时,除了最后面的8位二进制数据没有丢弃,其余16位二进制数据都被丢弃了。因此大家需要特别注意大类型到小类型的转换。
下面仍然贴上本节教程的完整代码,
public class TypeConversionDemo {
public static void main(String[] args) {
System.out.println('0' + 'A'); // 48 + 65
System.out.println(48 + 'A'); // 48 + 65
System.out.println("=======================");
// 隐式类型转换
System.out.println(120 + 3.14);
System.out.println('a' + 3.14);
System.out.println("=======================");
// Java不支持这样使用
// System.out.println(false + 3.14);
System.out.println(100 + 3000000000L);
System.out.println(12.35F + 24.44);
System.out.println("=======================");
// 隐式类型转换特殊情况
System.out.println('a' + 'A');
System.out.println('a' - 'A');
System.out.println('a' * 'A');
System.out.println('a' / 'A');
System.out.println('a' % 'A');
System.out.println("=======================");
// 显式类型转换
System.out.println((int)'A');
System.out.println((byte)'A');
System.out.println((short)'A');
System.out.println((long)'A');
System.out.println((float)'A');
System.out.println((double)'A');
// Java不支持这样使用
// System.out.println((boolean)'A');
System.out.println("=======================");
// 大类型到小类型
System.out.println((int)3.14);
System.out.println((byte)314);
}
}