posts - 51, comments - 17, trackbacks - 0, articles - 9
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          java 數(shù)組

          Posted on 2007-04-23 11:06 chenweicai 閱讀(152) 評(píng)論(0)  編輯  收藏

          剛剛開(kāi)始接觸java數(shù)組的人都會(huì)聽(tīng)到一句類(lèi)似的話(huà):java是純面向?qū)ο蟮恼Z(yǔ)言,他的數(shù)組也是一個(gè)對(duì)象。
          于是乎,我就按照一個(gè)對(duì)象的方式來(lái)使用數(shù)組,心安理得。直到我接觸到C的數(shù)組后,才發(fā)現(xiàn)將數(shù)組作為一個(gè)類(lèi)來(lái)使用在實(shí)現(xiàn)上是多么的“不自然”。
          首先我們看一下表面現(xiàn)象,數(shù)組創(chuàng)建的時(shí)候采用的是如下語(yǔ)句:
          MyClass[] arr = new MyClass[9];
          而普通類(lèi)采用的是如下語(yǔ)句:
          MyClass obj = new MyClass();
          就是說(shuō),創(chuàng)建數(shù)組的時(shí)候不使用小括號(hào)傳參。使得數(shù)組和普通類(lèi)看起來(lái)就有很多不同,因?yàn)樾±ㄌ?hào)里的參數(shù)是傳遞給構(gòu)造方法的,進(jìn)而讓人感覺(jué)數(shù)組類(lèi)是沒(méi)有構(gòu)造方法的。


          再往深了想,還有很多讓人感覺(jué)不自然的東西。可以肯定的是,java確實(shí)將數(shù)組作為了一個(gè)類(lèi)來(lái)處理。還是用上面的例子說(shuō)明:
          可以通過(guò)以下方法得到MyClass[]的Class實(shí)例:arr.getClass()或MyClass[].class。這樣,我就可以向數(shù)組類(lèi)里面“窺探”了。
          Class clazz = MyClass[].class;
          System.out.println(clazz.getConstructors().length);
          打印出來(lái)的結(jié)果是0;證明數(shù)組類(lèi)確實(shí)沒(méi)有構(gòu)造方法。


          如果強(qiáng)行執(zhí)行clazz.newInstance();就會(huì)得到下面的錯(cuò)誤。
          java.lang.InstantiationException: [Larraytest.MyClass;
          證明數(shù)組類(lèi)不能夠通過(guò)普通的反射方式來(lái)創(chuàng)建一個(gè)實(shí)例。


          再看看數(shù)組類(lèi)的“廬山真面目”:
          System.out.println(clazz);
          輸出是:
          [Larraytest.MyClass

          對(duì)Java Class文件結(jié)構(gòu)稍有了結(jié)就知道,這個(gè)字符串的意思就是一個(gè)元素類(lèi)型為arraytest.MyClass的一維數(shù)組。也就是說(shuō),數(shù)組類(lèi)型不是和普通類(lèi)一樣,以一個(gè)全限定路徑名+類(lèi)名來(lái)作為自己的唯一標(biāo)示的,而是以[+一個(gè)或者多個(gè)L+數(shù)組元素類(lèi)全限定路徑+類(lèi)來(lái)最為唯一標(biāo)示的。這個(gè)()也是數(shù)組和普通類(lèi)的區(qū)別。而這個(gè)區(qū)別似乎在某種程度上說(shuō)明數(shù)組和普通java類(lèi)在實(shí)現(xiàn)上有很大區(qū)別。因?yàn)閖ava虛擬機(jī)(java指令集)在處理數(shù)組類(lèi)和普通類(lèi)的時(shí)候,肯定會(huì)做出區(qū)分。我猜想,可能會(huì)有專(zhuān)門(mén)的java虛擬機(jī)指令來(lái)處理數(shù)組。

          既然我們可以得到數(shù)組的Class類(lèi)實(shí)例,就說(shuō)明肯定需要調(diào)用ClassLoader的defineClass(不一定非要是loadClass方法)方法,來(lái)構(gòu)造一個(gè)Class實(shí)例。java虛擬機(jī)規(guī)范規(guī)定,任何一個(gè)可以被加載的類(lèi),如果其類(lèi)文件存儲(chǔ)在文件系統(tǒng)上,那么一個(gè)*.class文件只能存儲(chǔ)一個(gè)類(lèi)信息,也就是說(shuō),數(shù)組類(lèi)的信息不可能以類(lèi)文件的形式存儲(chǔ)在本地磁盤(pán)上(否則任意一個(gè)類(lèi)都要配有255個(gè)數(shù)組類(lèi)了.....),既然這樣,那就說(shuō)明java虛擬機(jī)肯定內(nèi)置了一塊用來(lái)聲明數(shù)組類(lèi)的數(shù)據(jù)(不管是幾級(jí)數(shù)組)。這是符合java虛擬機(jī)規(guī)范的,規(guī)范規(guī)定class類(lèi)數(shù)據(jù)可以來(lái)自任意介質(zhì),包括本地磁盤(pán)、網(wǎng)絡(luò)、數(shù)據(jù)庫(kù)、內(nèi)存等等。

          分析到這里,我基本上可以肯定:java對(duì)數(shù)組對(duì)象化的操作的支持是指令級(jí)的,也就是說(shuō)java虛擬機(jī)有專(zhuān)門(mén)針對(duì)數(shù)組的指令。數(shù)組的Class類(lèi)實(shí)例是java虛擬機(jī)動(dòng)態(tài)創(chuàng)建動(dòng)態(tài)加載的,其結(jié)構(gòu)與普通java類(lèi)的Class實(shí)例有一些不同。


          JDK API中有一個(gè)java.lang.reflect.Array類(lèi),這個(gè)類(lèi)提供了很多方法(絕大多數(shù)是native方法,這在另一個(gè)方面證明了java對(duì)數(shù)組的支持是專(zhuān)用指令支持的,否則用本地方法干嘛^_^),用來(lái)彌補(bǔ)我們對(duì)數(shù)組操作的局限性。
          下面這句話(huà)用來(lái)創(chuàng)建一個(gè)一維的、長(zhǎng)度為10的、類(lèi)型為arraytest.MyClass的數(shù)組:
          arraytest.MyClass[] arr = (arraytest.MyClass[]) Array.newInstance(arraytest.MyClass, 10);

          下面這句話(huà)用來(lái)創(chuàng)建一個(gè)二維的、3乘5的、類(lèi)型為arraytest.MyClass的數(shù)組:
          int[] arrModel = new int[]{3,5};
          Object arrObj = Array.newInstance(Sub.class, arrModel);
          當(dāng)然你可以用一個(gè)數(shù)組的引用指向上面的二維數(shù)組,這里我們用一個(gè)Object的引用指向他。
          使用的時(shí)候,我們也是可以利用Array類(lèi)提供的方法來(lái)實(shí)現(xiàn):

          System.out.println(Array.getLength(arrObj);//第一維長(zhǎng)度為3
          System.out.println(Array.getLength(Array.get(arrObj, 2)));//第二維長(zhǎng)度為5,這里如果寫(xiě)3,就會(huì)得到你意想之中的java.lang.ArrayIndexOutOfBoundsException

          打印結(jié)果是如我所想的:
          3
          5

          對(duì)于數(shù)組的Class類(lèi)實(shí)例,還有一些奇怪的現(xiàn)象:
          在運(yùn)行代碼java.lang.reflect.Field fieldarr = clazz.getField("length");的時(shí)候,會(huì)拋出異常:java.lang.NoSuchFieldException: length,這似乎在說(shuō)數(shù)組類(lèi)沒(méi)有l(wèi)ength這個(gè)域,而這個(gè)域其實(shí)是我們用的最多的一個(gè)(也就是說(shuō)這個(gè)域是肯定存在的)。我想關(guān)于數(shù)組的Class類(lèi)實(shí)例、數(shù)組的實(shí)現(xiàn)等,還有很多“貓膩”在里面。

           
          順便說(shuō)一句,java數(shù)組最多只能是255維的。這個(gè)讓人看到了C的影子,嘿嘿。

          “Java把數(shù)組當(dāng)作一個(gè)java類(lèi)來(lái)處理”說(shuō)起來(lái)容易,用起來(lái)自然,但是細(xì)細(xì)想來(lái),還是有很多不簡(jiǎn)單的地方呀。 

           


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 阜新市| 南漳县| 麻江县| 汪清县| 若羌县| 新建县| 沿河| 平泉县| 城口县| 黄龙县| 安平县| 和林格尔县| 唐海县| 兴和县| 延寿县| 法库县| 吉木萨尔县| 涟水县| 呼和浩特市| 凌海市| 神木县| 洞口县| 晋城| 甘洛县| 甘南县| 称多县| 新宁县| 凤山市| 宣城市| 华亭县| 南昌市| 凌云县| 南皮县| 屏南县| 徐闻县| 中江县| 海原县| 高雄市| 子洲县| 得荣县| 民乐县|