1. 内存的结构
每台计算机都有内存(RAM)。它究竟是什么、具有什么特性,更重要的是,这对我们有什么用?
每个程序(包括用 Java 编写的程序)在执行前都会被加载到内存中。内存中包含程序代码(由处理器执行)和程序数据(由程序自身写入内存)。
那么,内存到底是什么?它像什么?
想象一下 Excel 😎。Excel 的工作表由单元格组成,每个单元格都有其唯一编号(A1、A2、... B1、B2)。知道单元格编号,就可以向其中写入某个值,或读取其中存储的值。计算机内存的组织方式与此相似。

程序及其数据在运行时存放在内存中。整个计算机内存可以看作许多很小的单元——字节。每个单元都有唯一编号——0、1、2、3、...(编号从 0 开始)。知道单元编号,我们就能把数据写入该单元,或从中读取。在一些单元中存放的是程序代码——供处理器执行的指令集合;在另一些单元中存放的是程序数据。单元的编号也被称为单元地址。
处理器会执行加载到内存中的程序指令。几乎所有处理器指令都是类似这样的流程:从若干单元中取数据 → 对其进行处理 → 将结果放入其他单元。
通过组合数百条简单指令,我们可以得到复杂而有用的操作。
当在程序代码中声明变量时,会为它分配一段尚未使用的内存,通常是几个字节。声明变量时必须指定程序要在其中存储的数据类型:数字、文本或其他数据。因为如果不知道数据类型,就无法确定应为变量分配多大的内存块。
在计算机发展的早期,程序直接使用内存单元编号来工作;后来为了方便程序员,给这些单元起了名字。变量的唯一名称首先是为了程序员的便利:程序在运行时仅靠编号也完全可以工作。
2. 内存中的变量
在 Java 中有 4 种用于存储整数的基本数据类型:byte、short、int 和 long。
| 类型 | 大小,字节 | 名称来源 |
|---|---|---|
|
|
Byte,因为它占用一个字节的内存 |
|
|
缩写自 Short Integer |
|
|
缩写自 Integer |
|
|
缩写自 Long Integer |
此外,在 Java 中还有 2 种浮点类型——float 和 double:
| 类型 | 大小,字节 | 名称来源 |
|---|---|---|
|
|
缩写自 Floating Point Number |
|
|
缩写自 Double Float |
每当程序执行到创建变量的语句时,都会为该变量分配一小块内存(大小取决于变量的类型)。
变量的地址被认为是为其分配的内存块中第一个单元的地址。
Java 程序不允许直接访问内存。所有与内存的交互只能通过Java 虚拟机进行。
3. 内存中的 String 类型
String 类型可以存储大量数据,因此它不只是一个数据类型,而是一个完整的对象。
String 类型的数据(文本)存放在一个专门的对象中,会为该对象分配内存;而该对象的地址会被存入变量中,变量本身也会分配内存。

- 变量 a 类型为 int,占用 4 字节,存储值 1。
- 变量 b 类型为 int,占用 4 字节,存储值 10,555。逗号不是小数点,而是千位分隔符。小数部分用点分隔。
- 变量 d 类型为 double,占用 8 字节,存储值 13.001。
- 变量 str 类型为 String,存储值 D12——包含文本的对象首单元的地址。
对象类型为 String(包含文本)时,会单独存放在一块内存中。其首地址存储在变量 str 中。
4. 赋值时会发生什么
另一件重要的事情——赋值是如何工作的。例如:
int a = 10;
int b = a;
b = 20;
System.out.println(a); // 10
在这个例子中,内存中会创建两个单元:一个给 a,一个给 b。当我们写 b = a; 时,复制的是值(10),而不是“盒子”本身。对 b 的更改不会影响 a。
现在看一个关于字符串的类似情况:
String s1 = "Hello";
String s2 = s1;
s2 = s2 + " World";
System.out.println(s1); // "Hello"
System.out.println(s2); // "Hello World"
在这里,s1 和 s2 两个变量在修改之前都指向同一个字符串 "Hello"。但当我们执行 s2 = s2 + " World"; 时,会为 s2 创建一个新的字符串 "Hello World",而 s1 依然指向旧的字符串 "Hello"。
5. 为什么编程中几乎一切都从 0 开始编号
人们常常会好奇,为什么在编程里几乎处处都从 0 开始计数。原因在于,有许多场景从 0 开始更方便(当然也有从 1 开始更方便的情况)。
举个类比。你在商店里排着一条长队,这时收银员说:所有从第 20 位开始的顾客,请到第二个收银台。他们的号码会是多少?20、21、22、23、... 很合理。那么相对于第 20 位呢?0、1、2、3、...
当我们把一组元素表示为“第一个元素的编号” + “数量”时,组内的相对编号自然就是 +0、+1、+2、...
在编程中也是如此。如果为你的变量分配了100 字节内存,并且你有 X——第一个字节的地址,那么所有字节的地址是什么?X+0、X+1、X+2、...、X+99。于是我们得到一组字节,其索引为 0、1、2、99。
当我们从某个数据块的相对地址来思考时,编号总是从 0 开始。这就是从 0 开始计数的第一条、也是最普遍的原因。
GO TO FULL VERSION