Java的八种基本数据类型(非常详细,附带实例)
对于任何编程语言来说,数据类型都是最基本的概念,也是新手入门时必须最先学习的知识。
Java 是一门强类型语言,所谓强类型就是强制定义类型,必须为每个变量定义类型,比如当我们声明变量 a 时必须说明它是整数还是小数。强类型的优势在于所编写的代码更易理解,而且可以在编译的过程中发现许多容易被人忽略的错误。
Java 语言的数据类型可以分为两大类,即基本数据类型和引用数据类型,如下图所示。

图 1 Java 数据类型
可能大家会产生疑惑,Java 语言为什么要定义这些数据类型呢?
这事还得从计算机内存结构说起,内存中可以操作的最小单位是字节(byte),1 字节等于 8 位(bit),也就是说由 8 个 1 或 0 组成。Java 定义了一个 byte 整数类型,它可以存放 8 位二进制数,即数值范围为 00000000~11111111,换算成十进制数为 0~255。
那么超过 8 位的二进制整数在 byte 类型的空间存放不下该怎么办呢?
我们可以用 16 位的 short 类型、32 位的 int 类型或 64 位的 long 类型来表示。类似地,浮点类型可以由 32 位的 float 类型或者 64 位的 double 类型来表示,各种基本数据类型所占用的位数如下图所示。

图 2 数据类型位数
回到上面的问题,定义数据类型实际上就是指定用多少位的内存空间来保存数据,而且指定数据是什么类型。这样做的好处有以下几点:
下表列出了各种基本数据类型所占用的内存空间大小、默认值以及取值范围。
可以清晰看到 4 种整数类型和两种浮点类型的取值范围,最后两种数据类型比较特殊,其中 char 类型的取值范围是 Unicode 字符集(\u0000~\uFFFF),而 boolean 类型的值只能是 true 或 false。
Java 中一共有 4 种整数类型,分别为 byte、short、int 和 long,它们既可以存放正整数也可以存放负整数。它们的差异在于存储空间的大小不同,从 1 字节到 4 字节,字节数越大就能表示数值越大的整数,如下图所示。

图 3 整数类型
下面我们通过一个实例来看如何定义整数类型:
下面我们来验证默认类型是不是 int。由于 Java 语言没有提供检测基本数据类型的方法,因此我们只能间接来证明。我们通过一个实例让编译器告知我们 200 和 40000 是什么类型。
如果不添加“L”,系统会默认为 int 类型,而 400000000000 明显已经超过 int 类型的取值范围了。解决这个问题的方法就是在后面加“L”来声明该整数为 long 类型,“L”也可以换用小写“l”。
那么 byte 类型和 short 类型是否不用在后面加上“B”和“S”呢?是的,确实不用加,而且不能加。Java 语言规定了 int 类型可以自动转换成 byte 类型和 short 类型,只要 int 的值不超出 byte 和 short 的取值范围。
比如我们把 200 赋值给 age 变量和把 40000 赋值给 listedCompany 变量,会分别得到“从int转换到byte可能会有损失”和“从int转换到short可能会有损失”这两个报错信息,从而导致错误。
如果要强制让 int 转换成 byte 或 short 呢?可以在值前面加上“(byte)”和“(short)”:
Java 中规定以“0b”开头的为二进制整数,以“0”开头的为八进制整数,以“0x”开头的为十六进制整数。通过下面实例大家就知道具体的使用方法了。
我们可以像下面实例中这样定义浮点类型:
整数类型与浮点类型能够互相转换吗?Java 允许通过强制转换的方式对它们进行转换,整型转成浮点型会在数值后面添加“.0”,而浮点型转成整型则会将数值的小数点和小数部分去掉。
通过一个实例来看它们之间的转换:
我们都知道除法可能会产生小数,不管是整数相除还是小数相除都可能会产生小数。下面的实例展示了 Java 中不同类型的除法操作:
世界上所有语言的文字和符号都有相应的 Unicode 编码,但由于 char 类型规定只有两字节,因此它只能表示 Unicode 的基本字符,不过这些字符都是最常见的字符,基本够我们使用了。
总体而言,Java 语言本身对字符的支持比较完善,支持英文字母、数字、常见中文文字以及各种符号。
下面的实例中定义了三个 char 类型的变量,为它们分别赋值英文字母“A”、汉字“你”以及数字“1”:
我们通过一个实例来看看是如何转换的:
类似地,也能将汉字“你”和数字“0”字符转换成对应的编码值。这些编码值实际上就是 Unicode 的编码值。
为了帮助大家更形象地理解编码值,下图中给出了 Unicode 前 128 个编码值及其对应的字符,其实就是 ASCII 编码,因为 Unicode 编码完全兼容 ASCII 编码。

图 4 Unicode前128个编码值及对应字符
可以看到大写字母 A~Z 对应 65~90,小写字母 a~z 对应 97~122,数字 0~9 对应 48~57。我们可以很容易发现一个规律:同一个字母的大小写形式的 Unicode 编码值之间相差 32,通过这个规律就可以实现字母大小写的转换。
下面实例中的十六进制数“0041”“002f”“4f60”转换成十进制数分别为“65”“47”“20320”,对应的Unicode编码的字符分别为“A”“/”和“你”。
布尔值只包含 true 和 false 两个值,分别表示命题为真或为假。
Java 使用 boolean 类型来表示布尔类型,它是一个二值(true 或 false)数据类型。实际上程序中的处理逻辑经常会涉及 boolean 类型的场景,比如是与否、开与关、真与假等。
我们可以直接定义一个 boolean 类型变量,然后将 true 或 false 赋值给它,当然也可以将某个表达式的计算结果赋值给它。
我们看一个实例:
它可以直接将 true 赋值给变量 b,也可以将表达式“10 > 8”和“10 == 20”的计算结果分别赋值给 bb 和 bbb,true 表示命题为真,false 则表示命题为假。
相比于 Java 中的 boolean 类型,很多编程语言并没有所谓的布尔类型。使用这些语言编程时一般会有一个约定,那就是 0 表示 false,非 0 则表示 true。
那么在 Java 中整型数值能赋值给 boolean 变量吗?或者 boolean 类型能转换成整数类型吗?通过看下面的实例就能知道答案了。
Java 是一门强类型语言,所谓强类型就是强制定义类型,必须为每个变量定义类型,比如当我们声明变量 a 时必须说明它是整数还是小数。强类型的优势在于所编写的代码更易理解,而且可以在编译的过程中发现许多容易被人忽略的错误。
Java 语言的数据类型可以分为两大类,即基本数据类型和引用数据类型,如下图所示。

图 1 Java 数据类型
- 基本数据类型:是 Java 语言规范中定义的最基本的类型,Java 语言一共有 8 种基本数据类型,分别通过 byte、short、int、long、float、double、char 与 boolean 这 8 个关键字来表示。这 8 种类型可以归类为数值类型、字符类型和布尔类型,数值类型又可以进一步分为整数类型和浮点类型。
- 引用数据类型:用于表示某个对象的引用,引用就好比是指向某个对象的内存地址,可以通过这个地址找到我们想要的对象。引用数据类型可以是类、接口或数组。我们先初步了解即可,后面章节会做更详细的讲解。
可能大家会产生疑惑,Java 语言为什么要定义这些数据类型呢?
这事还得从计算机内存结构说起,内存中可以操作的最小单位是字节(byte),1 字节等于 8 位(bit),也就是说由 8 个 1 或 0 组成。Java 定义了一个 byte 整数类型,它可以存放 8 位二进制数,即数值范围为 00000000~11111111,换算成十进制数为 0~255。
那么超过 8 位的二进制整数在 byte 类型的空间存放不下该怎么办呢?
我们可以用 16 位的 short 类型、32 位的 int 类型或 64 位的 long 类型来表示。类似地,浮点类型可以由 32 位的 float 类型或者 64 位的 double 类型来表示,各种基本数据类型所占用的位数如下图所示。

图 2 数据类型位数
回到上面的问题,定义数据类型实际上就是指定用多少位的内存空间来保存数据,而且指定数据是什么类型。这样做的好处有以下几点:
- 充分利用内存资源:我们可以根据实际情况选择数据存储空间,比如年龄用 byte 类型就足够了,不必选择 int 或 long 类型,这样能更好地利用内存资源。
- 更优的纠错机制。集成开发环境(如 IDEA)能检测赋值是否正确,比如声明了一个 int 类型的变量,却为其赋值 0.5,这时集成开发环境就会检测出来并提示错误。
- 限定操作:不同的数据类型有各自特定的作用和操作,比如数值类型可以进行加减乘除操作,而字符类型和布尔类型则不能执行该操作,所以说数据类型可以限定操作。
下表列出了各种基本数据类型所占用的内存空间大小、默认值以及取值范围。
数据类型 | 占用内存 | 默认值 | 取值范围 |
---|---|---|---|
byte | 1字节 | 0 | -128~127 |
short | 2字节 | 0 | -32768~32767 |
int | 4字节 | 0 | -2147483648~2147483647 |
long | 8字节 | 0L | -9223372036854775808~9223372036854775807 |
float | 4字节 | 0.0f | 1.4e-45~3.4028235e+38 |
double | 8字节 | 0.0d | 4.9e-324~1.7976931348623157e+308 |
char | 2字节 | ‘\u0000’ | Unicode字符集(\u0000~\uFFFF) |
boolean | 1字节 | false | true 或 false |
可以清晰看到 4 种整数类型和两种浮点类型的取值范围,最后两种数据类型比较特殊,其中 char 类型的取值范围是 Unicode 字符集(\u0000~\uFFFF),而 boolean 类型的值只能是 true 或 false。
1、Java整数类型
整数类型用来定义整数,就是数学上的整数。Java 中一共有 4 种整数类型,分别为 byte、short、int 和 long,它们既可以存放正整数也可以存放负整数。它们的差异在于存储空间的大小不同,从 1 字节到 4 字节,字节数越大就能表示数值越大的整数,如下图所示。

图 3 整数类型
整数类型的选择
对于这 4 种整数类型该如何选择呢?主要是根据实际情况进行选择,比如下面 4 种情况:- 描述年龄使用 byte 类型足矣,因为除了极少数人,其他普遍不超过 127。
- 描述我国 A 股上市公司数量使用 short 类型,目前上市公司数量有 4000 多家,而且可预见的是未来也不会超过 short 的最大值。
- 描述我国人口数可以使用 int 类型,因为未来也不太可能超过 21 亿人口。
- 描述银河系中数千亿的恒星数则要使用 long 类型。
下面我们通过一个实例来看如何定义整数类型:
public class IntegerTest { public static void main(String args[]) { byte age = 100; short listedCompany = 4000; int chinesePopulation = 1370000000; long galaxyStar = 400000000000L; System.out.println("年龄:" + age); System.out.println("上市公司数:" + listedCompany); System.out.println("我国人口:" + chinesePopulation); System.out.println("银河系恒星数:" + galaxyStar); } }结果输出为:
年龄:100
上市公司数:4000
我国人口:1370000000
银河系恒星数:400000000000
默认整型
代码中的所有整数默认都是 int 类型的,比如上述代码中的 100、4000 和 1370000000 三个数值实际上刚开始都是 int 类型的,当我们将它们赋值给 byte 或 short 变量时会被编译器处理成对应的类型。下面我们来验证默认类型是不是 int。由于 Java 语言没有提供检测基本数据类型的方法,因此我们只能间接来证明。我们通过一个实例让编译器告知我们 200 和 40000 是什么类型。
public class IntegerDefaultTypeTest { public static void main(String args[]) { byte age = 200; short listedCompany = 40000; } }通过“javac IntegerDefaultTypeTest.java”命令编译代码时产生了如下的报错信息:
IntegerDefaultTypeTest.java:5: 错误: 不兼容的类型: 从int转换到byte可能会有损失 byte age = 200; ^ IntegerDefaultTypeTest.java:6: 错误: 不兼容的类型: 从int转换到short可能会有损失 short listedCompany = 40000; ^ 2 个错误很明显,“从 int 转换到 byte 可能会有损失”和“从 int 转换到 short 可能会有损失”都已经告知我们默认类型就是 int。
为什么要加L?
注意,我们在第一个实例中为 galaxyStar 变量赋值时最后加了一个“L”,这是为了声明 400000000000 是 long 类型,而且是强行要求的,否则编译时会报错“错误:整数太大”。如果不添加“L”,系统会默认为 int 类型,而 400000000000 明显已经超过 int 类型的取值范围了。解决这个问题的方法就是在后面加“L”来声明该整数为 long 类型,“L”也可以换用小写“l”。
那么 byte 类型和 short 类型是否不用在后面加上“B”和“S”呢?是的,确实不用加,而且不能加。Java 语言规定了 int 类型可以自动转换成 byte 类型和 short 类型,只要 int 的值不超出 byte 和 short 的取值范围。
比如我们把 200 赋值给 age 变量和把 40000 赋值给 listedCompany 变量,会分别得到“从int转换到byte可能会有损失”和“从int转换到short可能会有损失”这两个报错信息,从而导致错误。
如果要强制让 int 转换成 byte 或 short 呢?可以在值前面加上“(byte)”和“(short)”:
byte age = (byte)200; short listedCompany = (short)40000;Java 语言规定了这样就是强制类型转换,此时编译不会再报错。但是结果却会因为转换过程中的损失而导致错误,可以看到输出结果中两个值都变成负数了。所以从取值范围大的整型转换到取值范围小的整型时要格外谨慎。
不同进制写法
除了我们比较熟悉的十进制外,在 Java 中还能很方便地使用由二进制、八进制和十六进制表示的整数。Java 中规定以“0b”开头的为二进制整数,以“0”开头的为八进制整数,以“0x”开头的为十六进制整数。通过下面实例大家就知道具体的使用方法了。
public class IntegerCarryTest { public static void main(String[] args) { int a = 0b101; int b = 017; int c = 10; int d = 0x16; System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); System.out.println("d = " + d); } }运行结果为:
a = 5
b = 15
c = 10
d = 22
2、Java浮点类型
Java 中使用浮点类型来定义小数,包括 float 和 double 两种类型,它们分别使用 4 字节和 8 字节保存数值,保存的值可以是正小数也可以是负小数。我们可以像下面实例中这样定义浮点类型:
public class DecimalTest { public static void main(String args[]) { float f = 200.0F; float ff = 200.0f; double d = 200.0; System.out.println("f = " + f); System.out.println("ff = " + ff); System.out.println("d = " + d); } }输出结果:
f = 200.0
ff = 200.0
d = 200.0
Java 代码中的小数都默认为 double 类型,所以要在 200.0 后面加上“F”或“f”以表明它是 float 类型,而不是默认的 double 类型。注意“F”和“f”的意义是一样的,可以任选一个。
整数类型与浮点类型能够互相转换吗?Java 允许通过强制转换的方式对它们进行转换,整型转成浮点型会在数值后面添加“.0”,而浮点型转成整型则会将数值的小数点和小数部分去掉。
通过一个实例来看它们之间的转换:
public class DecimalIntegerTest { public static void main(String args[]) { float f = 200.6f; double d = 200.0; int i = (int) f; int ii = (int) d; float ff = (float) i; double dd = (double) i; System.out.println("i = " + i); System.out.println("ii = " + ii); System.out.println("ff = " + ff); System.out.println("dd = " + dd); } }输出结果为:
i = 200
ii = 200
ff = 200.0
dd = 200.0
我们都知道除法可能会产生小数,不管是整数相除还是小数相除都可能会产生小数。下面的实例展示了 Java 中不同类型的除法操作:
public class DecimalDivisionTest { public static void main(String[] args) { int a = 2; int b = 3; double c = 0.2; System.out.println(a / b); System.out.println((float) a / b); System.out.println(a / (float) b); System.out.println((double) a / b); System.out.println(a / (double) b); System.out.println(a / c); } }输出结果:
0
0.6666667
0.6666667
0.6666666666666666
0.6666666666666666
10.0
3、Java字符类型
Java 使用字符(char)类型来声明字符,char 类型使用两字节(16位)的 Unicode 编码来表示不同的字符。世界上所有语言的文字和符号都有相应的 Unicode 编码,但由于 char 类型规定只有两字节,因此它只能表示 Unicode 的基本字符,不过这些字符都是最常见的字符,基本够我们使用了。
总体而言,Java 语言本身对字符的支持比较完善,支持英文字母、数字、常见中文文字以及各种符号。
定义字符型
我们在定义了一个 char 类型的变量后可以通过单引号将一个字符赋值给该变量,比如 char c = 'A'。下面的实例中定义了三个 char 类型的变量,为它们分别赋值英文字母“A”、汉字“你”以及数字“1”:
public class CharTest { public static void main(String args[]) { char c = 'A'; char cc = '你'; char ccc = '1'; System.out.println("c = " + c); System.out.println("cc = " + cc); System.out.println("ccc = " + ccc); } }输出结果为:
c = A
cc = 你
ccc = 1
与整型互相转换
由于编码就是使用不同的数值来表示不同的字符,因此字符型能够与整型互相转换。我们通过一个实例来看看是如何转换的:
public class CharIntegerTest { public static void main(String args[]) { char c = 'A'; int i = c; int ii = i + 32; char cc = (char) ii; char ccc = '你'; int iii = ccc; char cccc = '0'; int iiii = cccc; System.out.println("c = " + c); System.out.println("i = " + i); System.out.println("cc = " + cc); System.out.println("iii = " + iii); System.out.println("iiii = " + iiii); } }输出结果为:
c = A
i = 65
cc = a
iii = 20320
iiii = 48
类似地,也能将汉字“你”和数字“0”字符转换成对应的编码值。这些编码值实际上就是 Unicode 的编码值。
为了帮助大家更形象地理解编码值,下图中给出了 Unicode 前 128 个编码值及其对应的字符,其实就是 ASCII 编码,因为 Unicode 编码完全兼容 ASCII 编码。

图 4 Unicode前128个编码值及对应字符
可以看到大写字母 A~Z 对应 65~90,小写字母 a~z 对应 97~122,数字 0~9 对应 48~57。我们可以很容易发现一个规律:同一个字母的大小写形式的 Unicode 编码值之间相差 32,通过这个规律就可以实现字母大小写的转换。
Unicode方式赋值
当然我们也可以直接把 Unicode 的编码值赋值给 char 类型变量,格式为“\u”加 4 位十六进制的数,比如“\u0041”。下面实例中的十六进制数“0041”“002f”“4f60”转换成十进制数分别为“65”“47”“20320”,对应的Unicode编码的字符分别为“A”“/”和“你”。
public class CharUnicodeTest { public static void main(String args[]) { char c = '\u0041'; char cc = '\u002f'; char ccc = '\u4f60'; System.out.println(c); System.out.println(cc); System.out.println(ccc); } }输出结果为:
A
/
你
4、Java布尔类型
布尔类型的命名取自英国的一个数学家乔治·布尔,他最大的成就就是通过二进制将逻辑与数学进行了融合,从而使逻辑能进行运算操作。由于他在符号逻辑运算领域作出了特殊的贡献,很多编程语言将逻辑运算称为布尔运算,而运算的结果则称为布尔值。布尔值只包含 true 和 false 两个值,分别表示命题为真或为假。
Java 使用 boolean 类型来表示布尔类型,它是一个二值(true 或 false)数据类型。实际上程序中的处理逻辑经常会涉及 boolean 类型的场景,比如是与否、开与关、真与假等。
我们可以直接定义一个 boolean 类型变量,然后将 true 或 false 赋值给它,当然也可以将某个表达式的计算结果赋值给它。
我们看一个实例:
public class BooleanTest { public static void main(String[] args) { boolean b = true; boolean bb = 10 > 8; boolean bbb = 10 == 20; System.out.println("b:" + b); System.out.println("“10大于8”命题:" + bb); System.out.println("“10等于20”命题:" + bbb); } }输出结果:
b:true
“10大于8”命题:true
“10等于20”命题:false
它可以直接将 true 赋值给变量 b,也可以将表达式“10 > 8”和“10 == 20”的计算结果分别赋值给 bb 和 bbb,true 表示命题为真,false 则表示命题为假。
相比于 Java 中的 boolean 类型,很多编程语言并没有所谓的布尔类型。使用这些语言编程时一般会有一个约定,那就是 0 表示 false,非 0 则表示 true。
那么在 Java 中整型数值能赋值给 boolean 变量吗?或者 boolean 类型能转换成整数类型吗?通过看下面的实例就能知道答案了。
public class BooleanIntegerTest { public static void main(String[] args) { boolean b = true; int i = (int) b; boolean bb = (boolean) 0; } }执行 javac BooleanIntegerTest.java 命令进行编译,结果为“错误: 不兼容的类型: boolean 无法转换为 int”和“错误: 不兼容的类型: int 无法转换为 boolean”。