剛剛開始接觸java數組的人都會聽到一句相似的話:java是純面向對象的語言,他的數組也是一個對象。因而乎,筆者就按照一個對象的方式來使用數組,問心無愧。直到我接觸到C的數組後,才發現將數組做爲一個類來使用在實現上是多麼的「不天然」。java
首先咱們看一下表面現象,數組建立的時候採用的是以下語句:數據庫
MyClass[] arr = new MyClass[9];數組
而普通類採用的是以下語句:網絡
MyClass obj = new MyClass();spa
就是說,建立數組的時候不使用小括號傳參。使得數組和普通類看起來就有不少不一樣,由於小括號裏的參數是傳遞給構造方法的,進而讓人感受數組類是沒有構造方法的。htm
再往深了想,還有不少讓人感受不天然的東西。能夠確定的是,java確實將數組做爲了一個類來處理。仍是用上面的例子說明:對象
能夠經過如下方法獲得MyClass[]的Class實例:arr.getClass()或MyClass[].class。這樣,我就能夠向數組類裏面「窺探」了。內存
Class clazz = MyClass[].class;
System.out.println(clazz.getConstructors().length);字符串
打印出來的結果是0;證實數組類確實沒有構造方法。
若是強行執行clazz.newInstance();就會獲得下面的錯誤。
java.lang.InstantiationException: [Larraytest.MyClass;
證實數組類不可以經過普通的反射方式來建立一個實例。
再看看數組類的「廬山真面目」:
System.out.println(clazz);
輸出是:
[Larraytest.MyClass
對Java Class文件結構稍有告終就知道,這個字符串的意思就是一個元素類型爲arraytest.MyClass的一維數組。也就是說,數組類型不是和普通類 同樣,以一個全限定路徑名+類名來做爲本身的惟一標示的,而是以[+一個或者多個L+數組元素類全限定路徑+類來最爲惟一標示的。這個()也是數組和普通 類的區別。而這個區別彷佛在某種程度上說明數組和普通java類在實現上有很大區別。由於java虛擬機(java指令集)在處理數組類和普通類的時候, 確定會作出區分。筆者猜測,可能會有專門的java虛擬機指令來處理數組。
既然咱們能夠獲得數組的Class類實例,就說明確定須要調用ClassLoader的 defineClass(不必定非要是loadClass方法)方法,來構造一個Class實例。java虛擬機規範規定,任何一個能夠被加載的類,若是 其類文件存儲在文件系統上,那麼一個*.class文件只能存儲一個類信息,也就是說,數組類的信息不可能以類文件的形式存儲在本地磁盤上(不然任意一個 類都要配有255個數組類了.....),既然這樣,那就說明java虛擬機確定內置了一塊用來聲明數組類的數據(不論是幾級數組)。這是符合java虛 擬機規範的,規範規定class類數據能夠來自任意介質,包括本地磁盤、網絡、數據庫、內存等等。
分析到這裏,我基本上能夠確定:java對數組對象化的操做的支持是指令級的,也就是說java虛擬機有專門針對數組的指令。數組的Class類實例是java虛擬機動態建立動態加載的,其結構與普通java類的Class實例有一些不一樣。
JDK API中有一個java.lang.reflect.Array類,這個類提供了不少方法(絕大多數是native方法,這在另外一個方面證實了java對數組的支持是專用指令支持的,不然用本地方法幹嗎^_^),用來彌補咱們對數組操做的侷限性。
下面這句話用來建立一個一維的、長度爲10的、類型爲arraytest.MyClass的數組:
arraytest.MyClass[] arr = (arraytest.MyClass[]) Array.newInstance(arraytest.MyClass, 10);
下面這句話用來建立一個二維的、3乘5的、類型爲arraytest.MyClass的數組:
int[] arrModel = new int[]{3,5};
Object arrObj = Array.newInstance(Sub.class, arrModel);
固然你能夠用一個數組的引用指向上面的二維數組,這裏咱們用一個Object的引用指向他。
使用的時候,咱們也是能夠利用Array類提供的方法來實現:
System.out.println(Array.getLength(arrObj);//第一維長度爲3
System.out.println(Array.getLength(Array.get(arrObj, 2)));//第二維長度爲5,這裏若是寫3,就會獲得你意想之中的java.lang.ArrayIndexOutOfBoundsException
打印結果是如咱們所想的:
3
5
對於數組的Class類實例,還有一些奇怪的現象:
在運行代碼 java.lang.reflect.Field fieldarr = clazz.getField("length");的時候,會拋出異常:java.lang.NoSuchFieldException: length,這彷佛在說數組類沒有length這個域,而這個域實際上是咱們用的最多的一個(也就是說這個域是確定存在的)。筆者認爲關於數組的 Class類實例、數組的實現等,還有不少「貓膩」在裏面。 順便說一句,java數組最多隻能是255維的。這個讓人看到了C的影子,嘿嘿。「Java把數組看成一個java類來處理」提及來容易,用起來天然,可是細細想來,仍是有不少不簡單的地方。