基本数据类型
浏览 语言基础 主题: ) |
基本类型是 Java 语言中最基本的数据类型。共有 8 种:boolean
、byte
、char
、short
、int
、long
、float
和 double
。这些类型是 Java 中数据操作的基础。这些类型只服务于一个目的 - 包含纯粹的、简单的某种类型的值。因为这些数据类型在 Java 类型系统中默认定义,所以它们附带了许多预定义的操作。你无法为这些基本类型定义新的操作。在 Java 类型系统中,还有三种基本类型的类别。
- 数值基本类型:
short
、int
、long
、float
和double
。这些基本数据类型只保存数值数据。与这些数据类型相关的操作是简单算术(加、减等)或比较(大于、等于等)。 - 文本基本类型:
byte
和char
。这些基本数据类型保存字符(可以是Unicode 字母表甚至数字)。与这些类型相关的操作是文本操作(比较两个单词、连接字符构成单词等)。但是,byte
和char
也可以支持算术运算。 - 布尔和空基本类型:
boolean
和null
。
所有基本类型都有固定大小。因此,基本类型的值范围有限。较小的基本类型(byte
)可以包含的值比更大的类型(long
)少。
类别 | 类型 | 大小(位) | 最小值 | 最大值 | 精度 | 示例 |
---|---|---|---|---|---|---|
整数 | byte
|
8 | -128 | 127 | 从 +127 到 -128 | byte b = 65;
|
char
|
16 | 0 | 216-1 | 所有 Unicode 字符[1] | char c = 'A';
| |
short
|
16 | -215 | 215-1 | 从 +32,767 到 -32,768 | short s = 65;
| |
int
|
32 | -231 | 231-1 | 从 +2,147,483,647 到 -2,147,483,648 | int i = 65;
| |
long
|
64 | -263 | 263-1 | 从 +9,223,372,036,854,775,807 到 -9,223,372,036,854,775,808 | long l = 65L;
| |
浮点型 | float
|
32 | 2-149 | (2-2-23)·2127 | 从 3.402,823,5 E+38 到 1.4 E-45 | float f = 65f;
|
double
|
64 | 2-1074 | (2-2-52)·21023 | 从 1.797,693,134,862,315,7 E+308 到 4.9 E-324 | double d = 65.55;
| |
其他 | boolean
|
-- | -- | -- | false, true | boolean b = true;
|
void
|
-- | -- | -- | -- | -- |
整数基本类型会静默溢出
|
|
由于 Java 是强类型语言,因此不能将浮点数(带小数点的数字)赋值给整型变量
代码部分 3.53:将浮点数设置为 int (整型)类型的值。
int age;
age = 10.5;
|
基本类型应通过适当的值设置。基本类型可以用字面量初始化。大多数字面量都是基本类型的值,除了字符串字面量,它们是 String
类的实例。
编程可能不再像以前那样只是处理大量的数字,既不平凡也不无聊。然而,如今任何编程语言(更不用说 Java)中编写的代码的大部分都在痴迷地处理数字,无论是生成巨大的素数[2],还是仅仅计算你的踏板车排放的成本。1965 年,双子座五号 太空任务险些因编程错误而发生致命事故[3]。1979 年,一个计算机程序高估了五个核反应堆抵抗地震的能力;这些工厂暂时关闭[4]。这两个编程错误都有一个共同点:错误发生时正在计算的主题数据是数值的。从过去的经验来看,Java 带来了针对数值数据的改进的类型检查,并非常重视正确识别其不同类型。在编程方面,你必须认识到数值数据的意义。
数字使用二进制系统存储在内存中。内存就像一个单元格网格
每个单元格可以包含一个二进制数字(简称为位),也就是说,零或一
0 |
1 |
1 |
0 |
0 |
1 |
0 |
1 |
实际上,每个单元格确实包含一个二进制数字,因为一位大约相当于1
,而内存中的空单元格表示0
。单个二进制数字只能保存两种可能的值:零或一。
内存状态 | 给出 | ||||||||
0 |
→ | 0 | |||||||
1 |
→ | 1 |
多个位组合在一起可以保存多个排列 - 2 位可以保存 4 种可能的值,3 位可以保存 8 种,依此类推。例如,8 位可以保存的最大数字(二进制中的11111111
)在十进制系统中是255
。因此,从 0 到 255 的数字可以放入 8 位中。
内存状态 | 给出 | ||||||||
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
→ | 0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
→ | 1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
→ | 2 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
→ | 3 |
... |
... | ||||||||
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
→ | 255 |
一切都很好,但这样我们只能保存正数(或无符号整数)。它们被称为无符号整数。无符号整数是所有为正的整数值,不归因于负值。出于这个原因,我们会要求 8 位中的一个位保存有关数字符号(正数或负数)的信息。这使我们只剩下 7 位来实际计算一个数字。这 7 位可以保存的最大数字(1111111
)在十进制系统中是127
。
正数
内存状态 | 给出 | |||||||||
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
→ | 0 | |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
→ | 1 | |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
→ | 2 | |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
→ | 3 | |
... |
... |
... | ||||||||
0 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
→ | 127 |
负数
内存状态 | 给出 | |||||||||
1 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
→ | -128 | |
1 |
0 |
0 |
0 |
0 |
0 |
0 |
1 |
→ | -127 | |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
→ | -126 | |
1 |
0 |
0 |
0 |
0 |
0 |
1 |
1 |
→ | -125 | |
... |
... |
... | ||||||||
1 |
1 |
1 |
1 |
1 |
1 |
1 |
1 |
→ | -1 |
总之,使用这种方法,8 位可以保存从-128
到127
(包括零)的数字 - 共 256 个数字。有人可能会认为,这不算太糟糕。与无符号整数相反的是有符号整数,它能够保存正值和负值。
但是,较大的数字怎么办?你需要更多的位来保存更大的数字。这就是 Java 的数值类型发挥作用的地方。Java 有多种数值类型 - 它们的尺寸取决于参与的位数。
在 Java 中,数字使用专门用于保存数值数据的类型进行处理。但在深入研究这些类型之前,我们必须首先确定一些概念。就像你在高中(甚至小学)做的那样,Java 中的数字被放置在明显不同的组和系统中。你可能已经知道,数字系统包括整数(0、1、2 ... ∞);负整数(0、-1、-2 ... -∞)甚至实数和有理数(圆周率值、¾、0.333~ 等)。Java 只是倾向于将这些数字分成两组,整数(-∞ ... 0 ... ∞)和浮点数(任何带有小数点或分数表示的数字)。目前,我们只关注整数值,因为它们更容易理解和使用。
通过我们迄今为止学到的知识,我们将识别出在 Java 中可以创建和操作的不同类型有符号整数。以下是最基本数值类型:整数的表格。正如我们之前讨论过的,Java 中用于整数的数据类型既可以容纳正值也可以容纳负值,因此它们是 **有符号数值类型**。数值类型的大小以位为单位,它决定了该类型的最小值和最大值。如有疑问,您始终可以计算这些值。
让我们看看这些新发现的 Java 中基本整数类型的知识如何融入整体。假设您想对一年中的天数进行数值操作——所有 365 天。您会使用哪种类型?由于数据类型 `byte` 仅能达到 127,您是否愿意冒着赋予它大于其允许最大值的风险?此类决定可能会让您免受可能因编程代码而产生的可怕错误的困扰。对于此类数值操作,更明智的选择可能是 `short`。现在,为什么他们不能只制作一种数据类型来保存所有类型的数字呢?让我们来探讨一下原因。
当您告诉程序您需要使用一个整数,比如甚至是一个 `byte` 时,Java 程序会在内存中分配一个空间。它会分配 8 位的完整内存。尽管对于拥有近 12 万亿个此类位的存储模块而言,这似乎并不重要,但在其他情况下却很重要。一旦分配,该部分内存就会被使用,并且只有在操作完成后才能收回。考虑一个复杂的 Java 程序,其中您唯一使用的数据类型是 `long` 整数。当没有空间进行更多内存分配作业时会发生什么?您听说过 **堆栈溢出错误** 吗?这就是确切发生的事情——您的内存会被完全使用,而且速度很快。因此,请务必谨慎选择数据类型。
说够了,让我们看看如何创建数值类型。数值类型以类型的名称开头(`short`、`int` 等),然后为内存中分配的空间提供一个名称。以下是操作方式。假设我们需要创建一个变量来保存一年中的天数。
代码部分 3.54:一年中的天数。
short daysInYear = 365;
|
这里,`daysInYear` 是变量的名称,它保存 `365` 作为其值,而 `short` 是该特定值的类型。Java 中整数数据类型的其他用途可能需要您编写如下所示的代码
代码部分 3.55:Java 中的整数数据类型。
byte maxByte = 127;
short maxShort = 32767;
int maxInt = 2147483647;
long maxLong = 9223372036854775807L;
|
整数和浮点数
[edit | edit source]可以用于整数的数据类型是 `byte`、`short`、`int` 和 `long`,但是当涉及浮点数时,我们使用 `float` 或 `double`。现在我们知道了这一点,我们可以修改 代码部分 3.53 中的代码,如下所示
代码部分 3.56:正确的浮点声明和赋值。
double age = 10.5;
|
为什么不是 `float`,您问?如果我们使用 `float`,则必须在数字末尾添加一个 `f` 作为后缀,因此 `10.5` 应该是 `10.5f`,如下所示
代码部分 3.57:定义类型为 `float` 的浮点数的正确方法。
float age = 10.5f;
|
浮点数学永远不会抛出异常。将非零值除以 `0` 等于 `infinity`。将非无穷值除以 `infinity` 等于 `0`。
**问题 3.7:**考虑以下代码
问题 3.7:基本类型赋值。
...
a = false;
b = 3.2;
c = 35;
d = -93485L;
e = 'q';
|
这些是五个变量。有一个 `long`、一个 `byte`、一个 `char`、一个 `double` 和一个 `boolean`。获取每个变量的类型。
答案 3.7:基本类型赋值和声明。
boolean a;
double b;
byte c;
long d;
char e;
a = false;
b = 3.2;
c = 35;
d = -93485L;
e = 'q';
|
- `a` 只能是 `boolean`,因为只有布尔类型可以处理布尔值。
- `e` 只能是 `char`,因为只有字符类型可以包含一个字符。
- `b` 只能是 `double`,因为只有双精度类型可以包含此处的十进制数。
- `d` 是 `long`,因为 `byte` 无法包含如此小的值。
- `c` 是剩下的一个,所以它是 `byte`。
数据转换(强制转换)
[edit | edit source]数据转换(强制转换)可以在两种基本类型之间进行。强制转换有两种类型
- 隐式:不需要强制转换操作;数值的大小始终保持不变。但是,从整数类型转换为浮点类型时,可能会丢失 *精度*。
- 显式:需要强制转换操作;数值的大小可能无法保持不变。
**代码部分 3.58:隐式强制转换(int 转换为 long,不需要强制转换)。**
int i = 65;
long l = i;
|
**代码部分 3.59:显式强制转换(long 转换为 int,需要强制转换)。**
long l = 656666L;
int i = (int) l;
|
下表显示了基本类型之间的转换,它显示了显式转换的强制转换操作
从 byte |
从 char |
从 short |
从 int |
从 long |
从 float |
从 double |
从 boolean | |
---|---|---|---|---|---|---|---|---|
到 byte |
- | (byte) | (byte) | (byte) | (byte) | (byte) | (byte) | N/A |
到 char |
- | (char) | (char) | (char) | (char) | (char) | N/A | |
到 short |
(short) | - | (short) | (short) | (short) | (short) | N/A | |
到 int |
- | (int) | (int) | (int) | N/A | |||
到 long |
- | (long) | (long) | N/A | ||||
到 float |
- | (float) | N/A | |||||
到 double |
- | N/A | ||||||
到 boolean |
N/A | N/A | N/A | N/A | N/A | N/A | N/A | - |
与 C、C++ 和类似语言不同,Java 无法将 `false` 表示为 `0` 或 `null`,也无法将 `true` 表示为非零。Java 无法从布尔类型转换为非布尔基本数据类型,反之亦然。
对于非基本类型
到 Integer | 到 Float | 到 Double | 到 String | 到 Array | |
---|---|---|---|---|---|
整数 | - | (float)x | (double)x x.doubleValue() |
x.toString() Float.toString(x) |
new int[] {x} |
Float | java.text.DecimalFormat("#").format(x) | - | (double)x | x.toString() | new float[] {x} |
Double | java.text.DecimalFormat("#").format(x) | java.text.DecimalFormat("#").format(x) | - | x.toString() | new double[] {x} |
String | Integer.parseInt(x) | Float.parseFloat(x) | Double.parseDouble(x) | - | new String[] {x} |
Array | x[0] | x[0] | x[0] | Arrays.toString(x) | - |
注释
[edit | edit source]- ↑ 根据 "STR01-J. Do not assume that a Java char fully represents a Unicode code point". Carnegie Mellon University - Software Engineering Institute. Retrieved 27 Nov 2018., 并非所有 Unicode 字符都适合 16 位表示。
- ↑ 截至编辑(2013 年 12 月 11 日),互联网梅森素数大搜索 项目迄今为止已将最大的素数识别为 17,425,170 位。素数对于密码学家来说很有价值,因为数字越大,他们就可以使用该特定数字使其数据加密逻辑更安全。
- ↑ 由于软件错误,双子座5号飞船在太平洋预定着陆点以西 130 公里处着陆。 地球自转速度被编程为每太阳日旋转一周,而不是正确的每恒星日旋转一周。
- ↑ 他们设计中使用的程序使用了变量的算术和,而应该使用它们的绝对值的和。(Evars Witt,“小电脑和大问题”,美联社新闻,1979 年 3 月 16 日。另见 Peter Neumann,“关于软件正确性和社会过程的社论”软件工程笔记,第 4 卷(2),1979 年 4 月,第 3 页)