3.2 基本数据类型
到目前为止,相信读者已经对Java有了一些初步的认识,如果想在程序中使用一个变量,就必须先声明,此时编译程序会在未使用的内存空间中寻找一块能保存这个变量的空间以供这个变量使用。Java的基本数据类型如表3-1所示。
表3-1 Java基本数据类型
技术穿越:关于基本数据类型的选择。
实际上在编程初期许多的读者会对选择哪种基本数据类型出现犹豫,包括也会思考是否要记住这些数据类型所表示的数据范围,而最终的结果会发现可能根本就记不下来,考虑到这样的原因,笔者与大家分享一下基本数据类型选择经验:
- 如果要想表示整数就使用int(例如,表示一个人的年龄),表示小数就使用double(例如,表示一个人的成绩或者是工资);
- 如果要描述日期时间数字或者表示文件或内存大小(程序中是以字节为单元统计大小的)使用long;
- 如果要实现内容传递(IO操作、网络编程)或者是编码转换(JSP开发中使用UTF-8编码)时使用byte;
- 如果要想实现逻辑的控制,可以使用boolean描述(boolean只有true和false两种值);
- 如果要想处理中文,使用char可以避免乱码问题。
而且由于现在的计算机硬件价格(CPU、内存、磁盘)逐步走低,这样对于数据类型的选择也不像最早编程那样需要严格的限制其大小,所以像short、float等数据类型已经很少出现了。但是考虑到本书综合的学习效果,所以依然会尽可能全地使用这些给出的数据类型,以帮助读者加深学习效果。
3.2.1 整数类型
当数据不带有小数或分数时,即可以声明为整数变量,如3、-147等即为整数。在Java中,整数数据类型可以分为long、int、short及byte 4种:long为64位,也就是8个字节(bytes),可表示范围为-9223372036854775808~9223372036854775807;int为32位,也就是4个字节,表示范围为-2147483648~2147483647;若是数据值的范围在-32768~32767之间时,可以声明为short(短整数)类型;若是数据值更小,在-128~127之间时,可以声明为byte类型,以节省内存空间。举例来说,想声明一个短整型变量sum时,可以在程序中做出如下的声明:
经过声明之后,Java即会在可使用的内存空间中,寻找一个占有两个字节的内存块供sum变量使用,同时,这个变量的范围只能在-32768~32767之间。
在Java中对于一个整型常量,其类型默认的就是int型,所以在声明常量时不要超过int数据类型的范围。
【例3.1】以下代码验证了如果数据过长则有可能出现的问题
以上代码为int变量初始化的时候给的值超过了其本身的范围,所以在编译程序的时候出现了以下的错误提示:
3.2.2 数据的溢出
当整数的数据大小超出了可以表示的范围,而程序中又没有做数值范围的检查时,这个整型变量所输出的值将发生紊乱,且不是预期的运行结果。在下面的程序范例中声明了一个整型的数,并把它赋值为整型所可以表示范围的最大值,然后将它分别加1及加2。
【例3.2】将整型的最大值加1和加2
程序执行结果:
当最大值加上1时,结果反而变成表示范围中最小的值;当最大值加上2时,结果变成表示范围中次小的值,这就是数据类型的溢出。读者可以发现,这个情形会出现一个循环,若是想避免这种情况的发生,在程序中就必须加上数值范围的检查功能,或者使用较大的表示范围的数据类型,如长整型。
当声明了一整数变量max时,其表示的范围为-2147483648~2147483647,当max的值设为最大值2147483647,仍在整数的范围内,但是当max加1或加2时,整数max的值反而变成-2147483648和-2147483647,成为可表示范围的最小及次小值。
图3-2 数据类型的溢出
上述情形就像计数器的内容到最大值时会自动归零一样。而在整数中最小值为-2147483648,所以当整数max的值最大时,加上1就会变成最小值-2147483648,也就是产生了溢出。可以参考图3-2来了解数据类型的溢出问题。
为了避免int类型的溢出,可以在该表达式中的任一常量后加上大写的“L”,或在变量前面加上long,作为强制类型的转换。在下面的程序中加上防止溢出的处理,为了让读者方便比较,特意保留一个整数的溢出语句。
【例3.3】使用强制类型转换,防止数据溢出
程序执行结果:
由上面的程序可知,处理int类型的溢出,可以利用强制类型转换方式。但是对于long类型的溢出,就没有处理办法了,此时就需要在程序中加上变量值的界限检查,在运行时才不会发生错误。
说明
提问:Integer是什么?
Integer的作用是什么?在有的书中也经常可以看到这样的名称?既然可以求出整型的最大值,那能否求出整型的最小值呢?除了这些之外,Integer还有什么其他的作用?
回答:classpath在编译时不起作用。
Integer在Java中属于包装类,对于包装类的概念,本书将在Java常用类库章节有所介绍,有兴趣的读者也可以自己先提前翻看。对于Integer可以使用MAX_VALUE取得最大值,也可以通过MIN_VALUE取得其最小值。Integer的最大作用在于字符串与整型的转换上,以及自动拆箱和装箱的功能。这点在以后都会详细介绍,但在这里提醒读者的是,MAX_VALUE必须大写。
3.2.3 字符类型
字符类型在内存中占有两个字节,可以用来保存英文字母等字符。计算机处理字符类型时,是把这些字符当成不同的整数来看待。因此,严格说来,字符类型也算是整数类型的一种。
在计算机的世界里,所有的文字、数值都只是一连串的0与1。这些0与1对于设计者来说实在是难以理解,于是就产生了各种方式的编码。它们指定一个数值来代表某个字符,如常用的字符码系统ASCII。
虽然各类的编码系统合起来有数百种之多,却没有一种是包含足够的字符、标点符号及常用的专业技术符号。这些编码系统之间可能还会有相互冲突的情形发生,也就是说,不同的编码系统可能会使用相同的数值来表示不同的字符,在数据跨平台时就会发生错误。
Unicode就是为了避免上述情况的发生而产生的,它为每个字符制订了一个唯一的数值,因此在任何的语言、平台、程序中都可以安心地使用。Java所使用的就是Unicode字符码系统。
例如,Unicode中的小写a是以97来表示。在下面的程序中可以看到,声明字符类型的变量ch1、ch2,分别将变量ch1的值设为97,ch2的值设为字符a,再输出字符变量ch1及ch2的内容。
【例3.4】测试字符和整型之间的相互转换
程序执行结果:
给字符变量赋值可以使用数值和字符,它们都可以使程序正确地运行。要注意的是,字符要用一对单引号('')括起。
例如,想在程序中输出一个包括双引号的字符串时,可把字符变量赋值为转义字符,再将它输出来,即:在程序中声明一个字符类型变量ch,然后把ch设置为“\"”,再进行输出的操作。或者,也可以直接在要输出的字符串中加入特殊的转义字符。常用的转义字符如表3-2所示。
表3-2 常用的转义字符
以下面的程序为例,将ch1赋值为“\"”、ch2赋值为“\\”,并将字符变量ch输出在显示器上,同时,在打印的字符串里直接加入转义字符。
【例3.5】转义字符的应用
程序执行结果:
3.2.4 浮点数类型与双精度浮点数类型
在日常生活中经常会使用到小数类型的数值,如身高、体重等需要精确的数值时,整数将不能满足程序设计者的要求。在数学中,这些带有小数点的数值称为实数,在Java中,这种数据类型称为浮点数类型(float),其长度为32个字节,有效范围为-3.4E38~3.4E38。当浮点数的表示范围不够大时,还有一种双精度(double)浮点数可供使用。双精度浮点数类型的长度为64个字节,有效范围为-1.7E308~1.7E308。
浮点数的表示方式除了指数的形式外,还可用带有小数点的一般形式来表示。例如,想声明一个double类型的变量num与一个float类型的变量sum,并同时给sum赋初值3.0,可以在程序中做出如下的声明及设置:
声明之后,Java即会在可使用的内存空间中开辟一个占有8个字节的内存块供num变量使用,其范围在-1.7×10308~1.7×10308之间。之后再开辟另一个占有4个字节的内存块供sum变量使用,而这个变量的范围只能在-3.4×1038~3.4×1038之间。在此例中,sum的初值为3.0。
下列为声明与设置float与double类型的例子:
需要注意的是,使用浮点型数值时,默认的类型是double,在数值后面可加上D或是d,作为double类型的标识。在Java中,D或d是可有可无的。在数据后面加上F或是f,则作为float类型的识别。若没有加上,Java就会将该数据视为double类型,而在编译时就会发生错误,错误提示会告诉设计者可能会失去精确度。
在下面的程序里,声明一个float类型的变量num,并赋值为3.0,将num*num的运算结果输出到显示器上。
【例3.6】浮点型数据计算
程序执行结果:
3.2.5 布尔类型
布尔(boolean)类型的变量,只有true(真)和false(假)两种。也就是说,当将一个变量定义成布尔类型时,它的值只能是true或false,除此之外,没有其他的值可以赋值给这个变量。例如,声明名称为flag的变量为布尔类型,并设置为true值,可以使用下面的语句:
经过声明之后,布尔变量的初值即为true,当然如果在程序中需要更改flag变量的值时,以随时更改。将上述的内容写成了程序DateDemo07,读者可以先熟悉一下布尔变量的使用。
【例3.7】布尔类型的使用
程序执行结果:
布尔值通常用来控制程序的流程,读者可能会觉得有些抽象,本书会陆续在后面的章节中介绍布尔值在程序流程中所起的作用。
3.2.6 基本数据类型的默认值
在Java中,若在变量的声明时没有给变量赋初值,则会给该变量赋默认值,表3-3列出了各种类型的默认值。
表3-3 基本数据类型的默认值
在某些情形下,Java会给这些没有赋初始值的变量一个确切的默认值,这没有任何意义,是没有必要的,但应该保证程序执行时不会有这种未定义值的变量存在。虽然这种方式给程序编写者带来了很多便利,但是过于依赖系统给变量赋初值,就不容易检测到是否已经给予变量应有的值了,这是需要注意的问题。