int[] arr = new int[10];
int len1 = arr.length; // 字段訪問
String str = "hello";
int len2 = str.length(); // 方法調用
同為「獲取長度」,語法風格卻截然不同。數組是完整對象,為何暴露公共字段違反封裝原則?
int[] a = new int[10];
System.out.println(a.getClass().getName()); // 輸出: [I
[ 表示數組維度I 表示 int 類型 (JVM 內部類型簽名)int[][] → [[IString[] → [Ljava.lang.String;Class clazz = int[].class;
System.out.println("字段數: " + clazz.getDeclaredFields().length); // 0
System.out.println("方法數: " + clazz.getDeclaredMethods().length); // 0
System.out.println("構造器數: " + clazz.getDeclaredConstructors().length); // 0
System.out.println("父類: " + clazz.getSuperclass()); // class java.lang.Object
震驚發現:數組類 [I 是 Object 的直接子類,自身零成員 — 無字段、無方法、無構造器!連 length 字段都不存在。
// Java 代碼
int[] a = new int[2];
int len = a.length;
// 字節碼 (javap -c)
0: iconst_2
1: newarray 10 (int) // 創建 int[],引用入棧
3: astore_1 // 存入局部變量 1
4: aload_1 // 載入引用
5: arraylength // 專用指令:獲取數組長度入棧
6: istore_2 // 存入局部變量 2
7: return
關鍵發現:編譯器將 arr.length 直接編譯為 arraylength 字節碼指令,完全繞過字段訪問機制。JVM 內部直接從數組對象頭讀取長度信息。
arr.length() 編譯為 arraylength,但未這樣做每次數組訪問 (aaload, iastore 等指令) JVM 自動檢查索引邊界,越界拋出 ArrayIndexOutOfBoundsException,徹底消除 C/C++ 緩衝區溢出隱患。
int[][] matrix = new int[3][];
matrix[0] = new int[2];
matrix[1] = new int[5];
matrix[2] = new int[1]; // 每行長度不同,非矩形矩陣
因為數組類型僅由元素類型和維度決定,與長度無關。
.length 是編譯器語法糖 → arraylength 指令 → JVM 直接讀取對象頭