thinking in java (八) ----- 陣列(Array)
一般來說,程式會產生新的物件,有的時候只能到執行期,才能具體知道產生了多少物件,為了存放這些物件的存放(或者說是reference的存放),程式設計師必須提供物件的存放容器。
陣列(Array)
陣列是java用來存放以及隨機訪問一連串物件的各種做法中,最有效率的一種。陣列是簡單的線性序列,其中元素能夠被快速訪問,不過缺點是:當你產生陣列後,你不能改變其size。在java中,陣列是一個比較特殊的物件。
public class Main{ public static void main(String[] args) { int[] a = new int [10]; System.out.println(a.getClass().getSuperclass()); System.out.println(a.getClass().getName()); } } ———————————————————— class java.lang.Object [I
可以看出Array是Object的直接子類,但是又與一般的java物件有所不同。可以看出其類名是[I,非常滴奇怪,
下面我們再看
public class Main{ public static void main(String[] args) { System.out.println("Object[]:" + Object[].class); System.out.println("Object[][]:" + Object[][].class); System.out.println("Object:" + Object.class); } } ++++++++++++++++++++ Object[]:class [Ljava.lang.Object; Object[][]:class [[Ljava.lang.Object; Object:class java.lang.Object
從這個例項中我們可以看出陣列類和一般java類是不同的,普通的java類是全限定路徑名+名字作為自己的唯一標識,但是陣列是以[+L+陣列元素類全限定路徑+類名來作為自己的唯一標識,多了[和L。
看下面一組程式碼:
public class Main{ public static void main(String[] args) { int[] a = new int [10]; System.out.println(a.getClass().getName()); int[][] a1 = new int [10][10]; System.out.println(a1.getClass().getName()); } } ++++++++++++++++++++++++++ [I [[I
通過這個例子我們知道,[代表一維,[[代表二維。可以簡單滴說陣列的類名由若干個[和"I"組成,下面使用反射機制看一下。
public class Main{
public static void main(String[] args) {
int a [] =new int [10];
Class myClass = a.getClass();
System.out.println(myClass.getDeclaredFields().length);
System.out.println(myClass.getDeclaredMethods().length);
System.out.println(myClass.getDeclaredAnnotations().length);
System.out.println(myClass.getDeclaredConstructors().length);
System.out.println(myClass.getDeclaredClasses().length);
System.out.println(myClass.getSuperclass());
}
}
++++++++++++++++
0
0
0
0
0
class java.lang.Object
可見, [I這個直接子類自身沒有申明任何成員方法,構造方法,成員變數,註解等。可以說這就是一個空類。但是我們經常使用.lenth來檢視陣列的長度,那麼為為甚沒有length這個成員方法呢。先不管這length,先搞清楚[I在哪申明的吧。
首先[I不是一個識別符號,那麼這個類肯定是在程式碼中顯式地申明瞭,只能是在JVM自己執行的時候生成的、java虛擬機器這本書中寫到:
類載入器先看看陣列類是否已經建立,如果建立了就無需建立,如果沒有就建立一個,
如果陣列是引用型別元素的話,那麼類載入器首先去載入元素的類
JVM根據元素型別和唯獨,建立相應的類,
因此,是JVM動態地生成了[I類,再想想,JAVA陣列中的元素型別,數量都是未知的,因此必須是動態生成陣列類。
為了研究length是怎麼來的,我們看下一段程式碼。
public class Main{
public static void main(String[] args) {
int a [] =new int [10];
int i = a.length;
}
}
其位元組碼檔案:
0 iconst_2 //將int型常量2壓入運算元棧
1 newarray 10 (int) //將2彈出運算元棧,作為長度,建立一個元素型別為int, 維度為1的陣列,並將陣列的引用壓入運算元棧
3 astore_1 //將陣列的引用從運算元棧中彈出,儲存在索引為1的區域性變數(即a)中
4 aload_1 //將索引為1的區域性變數(即a)壓入運算元棧
5 arraylength //從運算元棧彈出陣列引用(即a),並獲取其長度(JVM負責實現如何獲取),並將長度壓入運算元棧
6 istore_2 //將陣列長度從運算元棧彈出,儲存在索引為2的區域性變數(即i)中
7 return //main方法返回
可見在這段程式碼中,是沒有length這個成員變數的,獲取陣列長度是由一條特定的指令arraylength實現(具體不知道如何實現),另外沒JVM建立陣列類,應該就是newarray這條指令發出的了。