在 Java 中,数组是一个对象,因此它有一个对象引用。在 Java 中,引用是一个指向内存中对象的地址值。
对于一个 Java 数组,可以使用以下方式获取它的地址值:
int[] array = new int[5]; System.out.println(array); // 输出数组的地址值
在这个例子中,array 是一个 int 类型的数组,它有五个元素。System.out.println(array) 语句输出的是数组对象的地址值,它是一个十六进制数。
array
int
System.out.println(array)
请注意,如果使用 System.identityHashCode(array) 方法,可以获得与上述输出相同的结果。该方法返回给定对象的哈希码,这通常是基于对象的内存地址计算得出的。
System.identityHashCode(array)
int[] array = new int[5]; System.out.println(System.identityHashCode(array)); // 输出数组的地址值
总之,Java 数组的地址值是一个指向数组对象在内存中位置的引用。
除了上述提到的直接输出数组对象或使用 System.identityHashCode 方法获取数组对象的地址值之外,还有其他方法可以获取 Java 数组的地址值。下面是一些例子:
System.identityHashCode
int[] array = new int[5]; System.out.println(System.identityHashCode(array[0])); // 输出第一个元素的地址值
java.util.Arrays
hashCode
int[] array = new int[5]; System.out.println(Arrays.hashCode(array)); // 输出数组的哈希码
java.nio.Buffer
address
ByteBuffer
MappedByteBuffer
ByteBuffer buffer = ByteBuffer.allocate(1024); long address = ((DirectBuffer) buffer).address(); System.out.println(address); // 输出 ByteBuffer 对象的地址值
需要注意的是,Java 数组的地址值是一个引用,它指向数组对象在内存中的位置。该地址值可以用于比较两个数组对象是否相等,或者用于在 JNI(Java Native Interface)中访问本地代码中的数组。但是,在一般的 Java 编程中,我们很少直接使用数组的地址值,而是使用数组的下标访问元素。
在 Java 中,所有的对象都存储在堆(Heap)中。当创建一个数组对象时,Java 会为它分配一块连续的内存空间,这个空间被称为数组的元素空间。在内存中,数组对象的地址指向数组元素空间的起始位置。
下面是一个示例,展示如何在内存中存储一个 int 类型的数组。
int[] array = new int[3];
这个语句创建了一个长度为 3 的 int 数组对象。在内存中,这个对象会占用一段连续的空间,其中包括一个对象头和三个 int 类型的数组元素。下图展示了这个数组对象在内存中的存储方式。
+----------------+ | 对象头 | +----------------+ | 第一个元素 | +----------------+ | 第二个元素 | +----------------+ | 第三个元素 | +----------------+
在这个例子中,对象头包含了一些元数据信息,比如对象的类、锁状态等等。每个 int 类型的数组元素占用 4 个字节的内存空间,因此整个数组对象占用的空间为 16 个字节(对象头 + 3 个 int 类型的数组元素)。
当访问数组元素时,Java 会根据元素的类型和位置来计算出它在内存中的地址。对于一个 int 类型的数组元素,可以使用下面的代码计算出它的地址值:
int[] array = new int[3]; int index = 1; int address = System.identityHashCode(array) + index * 4;
在这个例子中,System.identityHashCode(array) 方法返回的是数组对象的地址值,index * 4 是要访问的元素在内存中的偏移量。因为每个 int 类型的数组元素占用 4 个字节的内存空间,所以要乘以 4。最终得到的 address 变量就是要访问的数组元素的地址值。
index * 4
在 Java 中,数组是一个对象,因此它有一个对象头和数组元素。在内存中,数组的元素是连续存储的,每个元素的大小由数组的类型决定。
对于一个多维数组,它的内存布局也是连续的。多维数组可以看作是一维数组的嵌套,每个嵌套的数组元素是一个一维数组。
例如,下面是一个二维数组的示例:
int[][] matrix = new int[2][3];
这个语句创建了一个 2 行 3 列的二维数组对象。在内存中,这个对象会占用一段连续的空间,其中包括一个对象头和两个一维 int 数组元素。每个一维数组元素也是一个对象,包括一个对象头和三个 int 类型的数组元素。下图展示了这个二维数组对象在内存中的存储方式。
+----------------+ | 对象头 | +----------------+ | 第一个一维数组对象 | +----------------+ | 第二个一维数组对象 | +----------------+ +----------------+ | 对象头 | +----------------+ | 第一个元素 | +----------------+ | 第二个元素 | +----------------+ | 第三个元素 | +----------------+ +----------------+ | 对象头 | +----------------+ | 第一个元素 | +----------------+ | 第二个元素 | +----------------+ | 第三个元素 | +----------------+
在这个例子中,外层的二维数组对象包含两个一维数组元素。每个一维数组元素都是一个对象,包含一个对象头和三个 int 类型的数组元素。因此,整个二维数组对象占用的空间为 36 个字节(对象头 + 2 个一维数组元素对象 + 6 个 int 类型的数组元素)。
当访问二维数组的元素时,需要指定它在数组中的行列索引。对于一个二维数组,可以使用下面的代码计算出它的地址值:
int[][] matrix = new int[2][3]; int row = 1; int col = 2; int address = System.identityHashCode(matrix) + row * 2 * 4 + col * 4;
在这个例子中,System.identityHashCode(matrix) 方法返回的是二维数组对象的地址值,row * 2 * 4 是要访问的元素在内存中的偏移量。因为一个一维数组元素占用的空间为 12 个字节(对象头 + 3 个 int 类型的数组元素),所以要乘以 2。col * 4 是要访问的元素在一维数组中的偏移量,因为每个 int 类型的数组元素占用 4 个字节的内存空间,所以乘以 4。
System.identityHashCode(matrix)
row * 2 * 4
col * 4
需要注意的是,这种计算地址值的方式只适用于数组元素的访问,而不适用于数组对象本身的访问。如果想要访问数组对象本身的地址值,可以使用 System.identityHashCode 方法或者 Object.hashCode 方法。
Object.hashCode
总之,Java 数组的地址值可以通过计算数组对象的地址值和元素在内存中的偏移量来得到。对于多维数组,需要考虑嵌套数组元素的内存布局,计算出偏移量时要乘以每个一维数组元素的大小。
原文链接:codingdict.net