首页 > 编程笔记 > Java笔记 阅读:32

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 数据类型位数

回到上面的问题,定义数据类型实际上就是指定用多少位的内存空间来保存数据,而且指定数据是什么类型。这样做的好处有以下几点:
下表列出了各种基本数据类型所占用的内存空间大小、默认值以及取值范围。

表:基本数据类型说明
数据类型 占用内存 默认值 取值范围
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 种情况:
下面我们通过一个实例来看如何定义整数类型:
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

“byte age = 100;”表示声明了一个 byte 类型的 age 变量并将其赋值为 100。类似地,声明 short 类型、int 类型和 long 类型,最后我们通过 System.out.println() 将我们定义的变量都输出到控制台。

默认整型

代码中的所有整数默认都是 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

“float f = 200.0F”表示声明一个 float 类型的变量并将 200.0 赋值给它,注意后面要加“F”,这是强制要求加的,否则编译时会报错。

注意“F”和“f”的意义是一样的,可以任选一个。

Java 代码中的小数都默认为 double 类型,所以要在 200.0 后面加上“F”或“f”以表明它是 float 类型,而不是默认的 double 类型。

整数类型与浮点类型能够互相转换吗?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

其中“(int)”“(float)”和“(double)”就是强制转换操作。需要特别注意的是 200.6 转成整型后为 200,实际上就是损失了小数部分的值。

我们都知道除法可能会产生小数,不管是整数相除还是小数相除都可能会产生小数。下面的实例展示了 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

可以看到 int 类型除以 int 类型得到的结果中小数部分被去掉了,如果要保证结果的准确性,则要将除数或者被除数转为 double 类型或 float 类型。

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

将字符“A”转换成 int 类型后的值为 65,然后将 65 加上 32 后的值强制转换成 char 类型后为字符“a”。

类似地,也能将汉字“你”和数字“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”。

相关文章