《Java从小白到大牛》纸质版已经上架了!!!
在声明变量或常量时会用到数据类型,在前面已经用到一些数据类型,例如int、double和String等。Java语言的数据类型分为:基本类型和引用类型。
5.1 基本数据类型
基本类型表示简单的数据,基本类型分为4大类,共8种数据类型。
- 整数类型:byte、short、int和long
- 浮点类型:float和double
- 字符类型:char
- 布尔类型:boolean
基本数据类型如图5-1所示,其中整数类型、浮点类型和字符类型都属于数值类型,它们之间可以互相转换。
5.2 整型类型
从图5-1可见Java中整数类型包括:byte、short、int和long ,它们之间的区别仅仅是宽度和范围的不同。Java中整数都是有符号,与C不同没有无符号的整数类型。
Java的数据类型是跨平台的(与平台无关),无论你计算机是32位的还是64为的,byte类型整数都是一个字节(8位)。这些整数类型的宽度和范围如表5-1所示。
表 5-1 整数类型
整数类型 | 宽度 | 取值范围 |
---|---|---|
byte | 1个字节(8位) | -128~127 |
short | 2个字节(16位) | -215~215-1 |
int | 4个字节(32位) | -231~231-1 |
long | 8个字节(64位) | -263~263-1 |
Java语言的整型类型默认是int类型,例如16表示为int类型常量,而不是short或byte,更不是long,long类型需要在数值后面加l(小写英文字母)或L(大写英文字母),示例代码如下:
public class HelloWorld {
public static void main(String[] args) {
// 声明整数变量
// 输出一个默认整数常量
System.out.println("默认整数常量 = " + 16); ①
byte a = 16; ②
short b = 16; ③
int c = 16; ④
long d = 16L; ⑤
long e = 16l; ⑥
System.out.println("byte整数 = " + a);
System.out.println("short整数 = " + b);
System.out.println("int整数 = " + c);
System.out.println("long整数 = " + d);
System.out.println("long整数 = " + e);
}
}
上述代码多次用到了16整数,但它们是有所区别的。其中代码①行的16是默认整数类型,即int类型常量。代码②行16是byte整数类型。代码③行的16是short类型。代码第④行的16是int类型。代码第⑤行的16后加了L,这是说明long类型整数。代码第⑥行的16后加了l(小写英文字母l),这是也long类型整数。
提示 在程序代码中,尽量不用小写英文字母l,因为它容易与数字1混淆,特别是在Java中表示long类型整数时候很少使用小写英文字母l,而是使用大写的英文字母L。例如:16L要比16l可读性更好。
5.3 浮点类型
浮点类型主要用来储存小数数值,也可以用来储存范围较大的整数。它分为浮点数(float)和双精度浮点数(double)两种,双精度浮点数所使用的内存空间比浮点数多,可表示的数值范围与精确度也比较大。浮点类型说明如表5-2所示。
表 5-2 浮点类型
浮点类型 | 宽度 |
---|---|
float | 4个字节(32位) |
double | 8个字节(64位) |
Java语言的浮点类型默认是double类型,例如0.0表示double类型常量,而不是float类型。如果想要表示float类型,则需要在数值后面加f或F,示例代码如下:
public class HelloWorld {
public static void main(String[] args) {
// 声明浮点数
// 输出一个默认浮点常量
System.out.println("默认浮点常量 = " + 360.66); ①
float myMoney = 360.66f; ②
double yourMoney = 360.66; ③
final double PI = 3.14159d; ④
System.out.println("float整数 = " + myMoney);
System.out.println("double整数 = " + yourMoney);
System.out.println("PI = " + PI);
}
}
上述代码①行的360.66是默认浮点类型double。代码②行360.66f是float浮点类型,float浮点类型常量表示时,数值后面需要加f或F。代码第③行的360.66表示是double浮点类型。事实上double浮点数值后面也可以加字母d或D,以表示是double浮点数,代码第④行是声明一个double类型常量,数值后面加了d字母。
5.4 数字表示方式
整数类型和浮点类型都表示数字类型,那么在给这些类型的变量或常量赋值时,应该如何表示这些数字的值呢?下面介绍一下数字和指数等的表示方式。
5.4.1 进制数字表示
如果为一个整数变量赋值,使用二进制数、八进制数和十六进制数表示,它们的表示方式分别如下:
- 二进制数:以 0b 或0B为前缀,注意0是阿拉伯数字,不要误认为是英文字母o。
- 八进制数:以0为前缀,注意0是阿拉伯数字。
- 十六进制数:以 0x 或0X为前缀,注意0是阿拉伯数字。
例如下面几条语句都是表示int整数28。
int decimalInt = 28;
int binaryInt1 = 0b11100;
int binaryInt2 = 0B11100;
int octalInt = 034;
int hexadecimalInt1 = 0x1C;
int hexadecimalInt2 = 0X1C;
5.4.2 指数表示
进行数学计算时往往会用到指数表示的数值。如果采用十进制表示指数,需要使用大写或小写的e表示幂,e2表示102。
采用十进制指数表示的浮点数示例如下:
double myMoney = 3.36e2;
double interestRate = 1.56e-2;
其中3.36e2表示的是3.36×102,1.56e-2表示的是1.56×10-2。
5.5 字符类型
字符类型表示单个字符,Java中char声明字符类型,Java中的字符常量必须用单引号括起来的单个字符,如下所示:
char c = 'A';
Java字符采用双字节Unicode编码,占两个字节(16位),因而可用十六进制(无符号的)编码形式表示,它们的表现形式是\un,其中n为16位十六进制数,所以'A'字符也可以用Unicode编码'\u0041'表示,如果对字符编码感兴趣可以到维基百科(https://zh.wikipedia.org/wiki/Unicode字符列表)查询。
示例代码如下:
public class HelloWorld {
public static void main(String[] args) {
char c1 = 'A';
char c2 = '\u0041';
char c3 = '花';
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
}
}
上述代码变量c1和c2都是保存的'A',所以输出结果如下:
A
A
花
提示 字符类型也属于是数值类型,可以与int等数值类型进行数学计算或进行转换。这是因为字符类型在计算机中保存的是Unicode编码,双字节Unicode的存储范围在\u0000\uFFFF,所以char类型取值范围0216-1。
在Java中,为了表示一些特殊字符,前面要加上反斜杠(\),这称为字符转义。常见的转义符的含义参见表5-3。
表 5-3 转义符
字符表示 | Unicode编码 | 说 明 |
---|---|---|
\t | \u0009 | 水平制表符tab |
\n | \u000a | 换行 |
\r | \u000d | 回车 |
" | \u0022 | 双引号 |
' | \u0027 | 单引号 |
\ | \u005c | 反斜线 |
示例如下:
//在Hello和World插入制表符
String specialCharTab1 = "Hello\tWorld.";
//在Hello和World插入制表符,制表符采用Unicode编码\u0009表示
String specialCharTab2 = "Hello\u0009World.";
//在Hello和World插入换行符
String specialCharNewLine = "Hello\nWorld.";
//在Hello和World插入回车符
String specialCharReturn = "Hello\rWorld.";
//在Hello和World插入双引号
String specialCharQuotationMark = "Hello\"World\".";
//在Hello和World插入单引号
String specialCharApostrophe = "Hello\'World\'.";
//在Hello和World插入反斜杠
String specialCharReverseSolidus = "Hello\\World.";
System.out.println("水平制表符tab1: " + specialCharTab1);
System.out.println("水平制表符tab2: " + specialCharTab2);
System.out.println("换行: " + specialCharNewLine);
System.out.println("回车: " + specialCharReturn);
System.out.println("双引号: " + specialCharQuotationMark);
System.out.println("单引号: " + specialCharApostrophe);
System.out.println("反斜杠: " + specialCharReverseSolidus);
输出结果如下:
水平制表符tab1: Hello World.
水平制表符tab2: Hello World.
换行: Hello
World.
回车: Hello
World.
双引号: Hello"World".
单引号: Hello'World'.
反斜杠: Hello\World.
5.6 布尔类型
在Java语言中声明布尔类型的关键字是boolean,它只有两个值:true和false。
提示 在C语言中布尔类型是数值类型,它有两个取值:1和0。而在Java中的布尔类型取值不能用1和0替代,也不属于数值类型,不能与int等数值类型之间进行数学计算或类型转化。
示例代码如下:
boolean isMan = true;
boolean isWoman = false;
如果试图给它们赋值true和false之外的常量,如下所示。
boolean isMan = 1;
boolean isWoman = 'A';
则发生类型不匹配编译错误。
5.7 数值类型相互转换
学习了前面的数据类型后,大家会思考一个问题,数据类型之间是否可以转换呢?数据类型的转换情况比较复杂。基本数据类型中数值类型之间可以互相转换,布尔类型不能与它们之间进行转换。但有些不兼容类型之间,如String(字符串)转换为int整数等,可以借助于一些类的方法实现。本节只讨论数值类型的互相转换。
从图5-1可见数值类型包括了byte、short、char、int、long、float和double,这些数值类型之间的转换有两个方向:自动类型转换和强制类型转换。
5.7.1 自动类型转换
自动类型转换就是需要类型之间转换是自动的,不需要采取其他手段,总的原则是小范围数据类型可以自动转换为大范围数据类型,列类型转换顺序如图5-2所示,从左到右是自动。
注意 如图5-2所示,char类型比较特殊,char自动转换为int、long、float和double,但byte和short不能自动转换为char,而且char也不能自动转换为byte或short。
自动类型转换不仅发生在赋值过程中,在进行数学计算时也会发生自动类型转换,在运算中往往是先将数据类型转换为同一类型,然后在进行计算。计算规则如表5-4所示。
表5-4 计算过程中自动类型转换规则
操作数1类型 | 操作数2类型 | 转换后的类型 |
---|---|---|
byte、short、char | int | int |
byte、short、char、int | long | long |
byte、short、char、int、long | float | float |
byte、short、char、int、long、float | double | double |
示例如下:
// 声明整数变量
byte byteNum = 16;
short shortNum = 16;
int intNum = 16;
long longNum = 16L;
// byte类型转换为int类型
intNum = byteNum;
// 声明char变量
char charNum = '花';
// char类型转换为int类型
intNum = charNum;
// 声明浮点变量
// long类型转换为float类型
float floatNum = longNum;
// float类型转换为double类型
double doubleNum = floatNum;
//表达式计算后类型是double
double result = floatNum * intNum + doubleNum / shortNum; ①
上述代码第①行中表达式loatNum * intNum + doubleNum / shortNum进行数学计算,该表达式是由4个完全不同的数据类型组成,范围最大的是double,所以在计算过程中它们先转换成double,所以最后的结果是double。
5.7.2 强制类型转换
在数值类型转换过程中,除了需要自动类型转换外,有时还需要强制类型转换,强制类型转换是在变量或常量之前加上“(目标类型)”实现,示例代码如下:
//int型变量
int i = 10;
//把int变量i强制转换为byte
byte b = (byte) i;
上述代码(byte) i表达式实现强制类型转换。强制类型转换主要用于大宽度类型转换为小宽度类型情况,如把int转换为byte。示例代码如下:
//int型变量
int i = 10;
//把int变量i强制转换为byte
byte b = (byte) i;
int i2 = (int)i; ①
int i3 = (int)b; ②
上述代码第①行是将int类型的i变量“强制类型转换”为int类型,这显然是没有必要,但是语法也是允许的。代码第②行是将byte类型的b变量强制转换为int类型,从图5-2可见这个转换是自动,不需要强制转换,本例中这个转换没有实际意义,但有时为了提高精度需要种转换。示例代码如下:
//int型变量
int i = 10;
float c1 = i / 3; ①
System.out.println(c1); ②
//把int变量i强制转换为float
float c2 = (float)i / 3; ③
System.out.println(c2); ④
输出结果:
3.0
3.3333333
上述代码比较输出结果发现c1和c2变量小数部分差别比较大的,这种差别在一些金融系统中是不允许的。在代码第①行i除以3从结果是小数,但由于两个操作数都是整数int类型,小数部分被截掉了,结果是3,然后再赋值给float 类型的c1变量,最后c1保持的是3.0。为了防止两个整数进行除法等运算导致小数位被截掉问题,可以将其中一个操作数强制类型转换为float,见代码第③行,这样计算过程中操作数是float类型,结果也是float不会截掉小数部分。
再看一个强制类型转换与精度丢失的示例。
long yourNumber = 6666666666L;
System.out.println(yourNumber);
int myNuber = (int)yourNumber;
System.out.println(myNuber);
输出结果:
6666666666
-1923267926
上述代码输出结果可见,经过强制类型转换后,原本的6666666666L变成了负数。当大宽度数值转换为小宽度数值时,大宽度数值的高位被截掉,这样就会导致数据精度丢失。除非大宽度数值的高位没有数据,就是这个数比较小的情况,例如将6666666666L换为6L就不会丢失精度。
5.8 引用数据类型
在Java中除了8种基本数据类型外,其他数据类型全部都是引用(reference)数据类型,引用数据类型用了表示复杂数据类型,如图5-3所示,包含:类、接口和数组声明的数据类型。
提示 Java中的引用类型,相当于C等语言中指针(pointer)类型,引用事实上就是指针,是指向一个对象的内存地址。引用类型变量中保持的是指向对象的内存地址。很多资料上提到Java不支持指针,事实上是不支持指针计算,而指针类型还是保留了下来,只是在Java中称为引用类型。
引用数据类型示例如下:
int x = 7; ①
int y = x; ②
String str1 = "Hello"; ③
String str2 = str1; ④
str2 = "World"; ⑤
上述代码声明了两个基本数据类型(int)和两个引用数据类型(String)。当程序执行完第②行代码后,x值为7,x赋值给y,这时y的值也是7,它们的保持方式如图5-4所示,x和y两个变量值都是7,但是它们之间是独立的,任何一个变化都不会影响另一个。
当程序执行完第③行时,字符串“Hello”对象被创建,保持到内存地址0x12345678中,str1是引用类型变量,它保存的是内存地址0x12345678,这个地址指向“Hello”对象。
当程序执行完第④行时,str1变量内容(0x12345678)被赋值给str2是引用类型变量,这样一来str1和str2保存了相同的内存地址,都指向“Hello”对象。见图5-4所示,此时str1和str2本质上是引用一个对象,通过任何一个引用都可以修改对象本身。
当程序执行完第⑤行时,字符串“World”对象被创建,保持到内存地址0x23455678中,地址保存到str2变量中,此时,str1和str2不再指向相同内存地址,见图5-5所示。
本章小结
本章主要介绍了Java中的数据类型,读者需要重点掌握基本数据类型,理解基本数据类型与引用数据类型的区别,熟悉数值类型如何互相转换。
配套视频
http://www.zhijieketang.com/classroom/6/courses
配套源代码
http://www.zhijieketang.com/group/5