尽管Java是一种面向对象的编程语言,但这也并不代表所有Java的值都是对象。Java中的一些值依然属于 基本类型 (primitive type)。基本类型中有4种类型是有符号整数类型;两种是浮点类型;一种是在字符串编码中使用的char类型;另一种是表示真值的boolean(布尔)类型。在下面的小节中我们将详细学习这些类型。
有符号整数类型适用于没有小数部分的数,可以是负数。Java提供了4种有符号整数类型,如表1-1所示。
表1-1 Java中的有符号整数类型
注意: 常量Integer.MIN_VALUE与Integer.MAX_VALUE分别是int类型的最小值和最大值。此外,Long、Short和Byte类也分别都有MIN_VALUE和MAX_VALUE常量。
在大多数情况下,int类型是最实用的。但是如果想表示整个地球的居住人口数量,就需要使用long类型了。byte和short类型主要用于特定的应用场合,例如,底层文件处理,或者存储空间有限的大数组。
注意: 如果long类型依然不够,那么可以使用BigInteger类。参见1.4.6小节了解详细信息。
在Java中,整数类型的范围不取决于运行程序的机器。毕竟,Java是被设计为“一次编写,处处运行”的语言。相比之下,C和C++程序中的整数类型的大小还取决于编译该程序的处理器。
可以使用后缀L来表示长整型字面量(例如,4000000000L)。但是,byte类型或short类型的字面量无法通过后缀区分。这时需要使用强制转换符号(参见1.4.4小节)。例如,(byte)127表示byte类型。十六进制字面量具有前缀0x(例如,0xCAFEBABE)。二进制数值具有前缀0b,例如,0b1001是9。
警告: 八进制数值具有前缀0,例如,011是9。但这样的形式可能会容易混淆,因此最好远离八进制字面量和0开头的数值。
你可以在数字字面量中添加下划线进行长数字的分组,例如,使用1_000_000(或0b1111_0100_ 0010_0100_0000)来表示100万。但这里的下划线仅仅是为了让人更易阅读,Java编译器会删除它们。
注意: 如果使用的整数值永远不会是负数,并且确实需要一个额外的数位来存储数据,那么可以将有符号整数值解释为无符号数,但是需要非常仔细。例如,一个byte类型的值b的表示范围通常是−128~127。如果想表示0~255的范围,仍然可以将其存储在byte类型中。由于二进制算术运算的性质,如果不发生溢出,那么加法、减法和乘法都是可以正常工作的。对于其他运算,可以调用Byte.toUnsignedInt(b)来获得0~255的int类型的值,然后就可以处理整数值,并将结果强制转换回byte类型。Integer和Long类也有用于处理无符号数的除数和余数的方法。
浮点类型表示有小数部分的数值。Java中的两种浮点类型如表1-2所示。
表1-2 浮点类型
很多年前,当内存还是一种稀缺资源时,4字节的浮点数是最常用的。但现在7位有效数字已经不太适用了,因此“双精度”数是系统的默认值。只有当需要存储大量的浮点数时,使用float类型才有意义。
float类型的数值有一个后缀F(例如,3.14F);没有后缀F的浮点数(例如,3.14)是double类型的。当然,你可以选择使用后缀D(例如,3.14D)来表示double类型的数值。
注意: 你可以用十六进制来表示浮点数。例如,0.0009765625 = 2 −10 ,也可以写成0x1.0p-10。在十六进制符号中,你需要使用p而不是e来表示指数。(因为e是一个十六进制数字。)请注意,即使数字是十六进制的,但指数(即2的幂)也需要使用十进制。
Java中有一些特殊的浮点值:Double.POSITIVE_INFINITY表示∞;Double.NEGATIVE_INFINIY表示−∞;Double.NaN表示“非数值”。例如,算式1.0/0.0的结果是正无穷大。算式0.0/0.0或负数的平方根会生成NaN。
警告: 所有“非数值”都会被认为是各不相同的。因此,你不能使用条件测试语句if (x == Double.NaN) 来检查 x 是否为 NaN。而是应该使用 if (Double.isNaN(x))来判断。此外,也应当使用Double.isInfinite来测试±∞,用Double.isFinite来检查一个浮点数既不是无穷也不是NaN。
浮点数并不适用于金融计算的场景,因为它在计算中发生的一些舍入误差对金融领域来讲可能是无法容忍的。例如,System.out.println(2.0 - 1.7)将会打印出0.30000000000000004,而不是你所期望的0.3。这种舍入误差是由浮点数在二进制系统中的表示规则造成的。此外,小数3/10也没有精确的二进制表示,就像十进制系统中1/3没有精确的表示一样。如果你需要任意精度且没有舍入误差的数值计算,可以使用1.4.6小节中介绍的BigDecimal类。
char类型描述了Java使用的UTF-16字符编码中的“代码单元”。有关的详细信息颇有一些技术难度,请参见1.5节。你可能不会经常使用char类型。
偶尔你可能会遇到用单引号括起来的字符字面量。例如,'J'是值为74(或十六进制4A)的字符字面量,表示Unicode字符“U+004A,拉丁大写字母J”的代码单元。这里的代码单元可以用十六进制表示,并使用\u作为前缀。例如,'\u004A'与'J'相同。更奇特的例子是'\u263A',☺的代码单元,“u+263A白色笑脸”。
此外一些特殊的代码,例如'\n'、'\r'、'\t'、'\b'分别表示换行、回车、制表和退格。
如果需要使用'\'则需要使用两个斜杠表示'\\'。
boolean(布尔)类型有两个值:false和true。
在Java中,boolean类型不是数值类型。boolean类型的值与整数类型中的0和1并没有任何关系。