成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

有關JVM處理Java數組方法的思考

開發 后端
在Java中,獲取數組的長度和String的長度是兩種不同的方法,這引起了本文作者的一番思考。本文從JVM的角度,探討了Java數組在JVM中是什么對象,有哪些成員,以及聲明方法。

本文來自jarfield的博客,原文標題為《為什么如此獲取Java數組的長度》。

記得vamcily 曾問我:“為什么獲取數組的長度用.length(成員變量的形式),而獲取String的長度用.length()(成員方法的形式)?”

我當時一聽,覺得問得很有道理。做同樣一件事情,為什么采用兩種風格迥異的風格呢?況且,Java中的數組其實是完備(full-fledged)的對象,直接暴露成員變量,可能不是一種很OO的風格。那么,設計Java的那幫天才為什么這么做呢?

帶著這個疑問,我查閱了一些資料,主要是關于“JVM是如何處理數組”的。

數組對象的類是什么?

既然數組都是對象,那么數組的類究竟是什么呢?當然不是java.util.Arrays啦!我們以int一維數組為例,看看究竟。

  1. public class Main {   
  2. public static void main(String args[]){   
  3. int a[] = new int[10]; Class clazz = a.getClass();   
  4. System.out.println(clazz.getName());   
  5. }   
  6. }  
  7.  

在SUN JDK 1.6上運行上述代碼,輸出為:

[I

看起來數組的類很奇怪,非但不屬于任何包,而且名稱還不是合法的標識符(identifier)。具體的命名規則[1]可以參見java.lang.Class.getName()的javadoc。簡單的說,數組的類名由若干個'['和數組元素類型的內部名稱組成,'['的數目代表了數組的維度。

具有相同類型元素和相同維度的數組,屬于同一個類。如果兩個數組的元素類型相同,但維度不同,那么它們也屬于不同的類。如果兩個數組的元素類型和維度均相同,但長度不同,那么它們還是屬于同一個類。

數組的類有哪些成員呢?

既然我們知道了數組的類名是什么,那么就去看看數組的類究竟是什么樣的吧?有哪些成員變量?有哪些成員方法?length這個成員變量在哪?是不是沒有length()這個成員方法?

找來找去,在JDK的代碼中沒有找打'[I'這個類。想想也對,'[I'都不是一個合法的標識符,肯定不會出現public class [I {...}這樣的Java代碼。我們暫且不管[I類是誰聲明的,怎么聲明的,先用反射機制一探究竟吧。

  1. public class Main {   
  2. public static void main(String[] args) {   
  3. int a[] = new int[10]; 
  4. Class clazz = a.getClass();   
  5. System.out.println(clazz.getDeclaredFields().length);   
  6. System.out.println(clazz.getDeclaredMethods().length);   
  7. System.out.println(clazz.getDeclaredConstructors().length);   
  8. System.out.println(clazz.getDeclaredAnnotations().length);   
  9. System.out.println(clazz.getDeclaredClasses().length);   
  10. System.out.println(clazz.getSuperclass());   
  11. }   
  12. }  
  13.  

在SUN JDK 1.6上運行上述代碼,輸出為:

  1. 0 
  2. 0 
  3. 0 
  4. 0 
  5. 0 
  6. class java.lang.Object  
  7.  

可見,[I這個類是java.lang.Object的直接子類,自身沒有聲明任何成員變量、成員方法、構造函數和Annotation,可以說,[I就是個空類。我們立馬可以想到一個問題:怎么連length這個成員變量都沒有呢?如果真的沒有,編譯器怎么不報語法錯呢?想必編譯器對Array.length進行了特殊處理哇!

數組的類在哪里聲明的?

先不管為什么沒有length成員變量,我們先搞清楚[I這個類是哪里聲明的吧。既然[I都不是合法的標識符,那么這個類肯定在Java代碼中顯式聲明的。想來想去,只能是JVM自己在運行時生成的了。JVM生成類還是一件很容易的事情,甚至無需生成字節碼,直接在方法區中創建類型數據,就差不多完工了。

還沒有實力去看JVM的源代碼,于是翻了翻The JavaTM Virtual Machine Specification  Second Edition,果然得到了驗證,相關內容參考5.3.3 Creating Array Classes。

規范的描述很嚴謹,還摻雜了定義類加載器和初始化類加載器的內容。先不管這些,簡單概括一下:

類加載器先看看數組類是否已經被創建了。如果沒有,那就說明需要創建數組類;如果有,那就無需創建了。

如果數組元素是引用類型,那么類加載器首先去加載數組元素的類。

JVM根據元素類型和維度,創建相應的數組類。

呵呵,果然是JVM這家伙自個偷偷創建了[I類。JVM不把數組類放到任何包中,也不給他們起個合法的標識符名稱,估計是為了避免和JDK、第三方及用戶自定義的類發生沖突吧。

再想想,JVM也必須動態生成數組類,因為Java數組類的數量與元素類型、維度(最多255)有關,相當相當多了,是沒法預先聲明好的。

居然沒有length這個成員變量!

我們已經發現,偷懶的JVM沒有為數組類生成length這個成員變量,那么Array.length這樣的語法如何通過編譯,如何執行的呢?

讓我們看看字節碼吧!編寫一段最簡單的代碼,使用jclasslib查看字節碼。

  1. public class Main {   
  2. public static void main(String[] args)   
  3. int a[] = new int[2]; int i = a.length;   
  4. }   
  5. }  
  6.  

使用SUN JDK 1.6編譯上述代碼,并使用jclasslib打開Main.class文件,得到main方法的字節碼:

  1. 0 iconst_2                   //將int型常量2壓入操作數棧  
  2. 1 newarray 10 (int)    //將2彈出操作數棧,作為長度,創建一個元素類型為int, 維度為1的數組,并將數組的引用壓入操作數棧  
  3. 3 astore_1                 //將數組的引用從操作數棧中彈出,保存在索引為1的局部變量(即a)中  
  4. 4 aload_1                  //將索引為1的局部變量(即a)壓入操作數棧  
  5. 5 arraylength            //從操作數棧彈出數組引用(即a),并獲取其長度(JVM負責實現如何獲取),并將長度壓入操作數棧  
  6. 6 istore_2                 //將數組長度從操作數棧彈出,保存在索引為2的局部變量(即i)中  
  7. 7 return                    //main方法返回  
  8.  

可見,在這段字節碼中,根本就沒有看見length這個成員變量,獲取數組長度是由一條特定的指令arraylength實現(怎么實現就不管了,JVM總有辦法)。編譯器對Array.length這樣的語法做了特殊處理,直接編譯成了arraylength指令。另外,JVM創建數組類,應該就是由newarray這條指令觸發的了。

很自然地想到,編譯器也可以對Array.length()這樣的語法做特殊處理,直接編譯成arraylength指令。這樣的話,我們就可以使用方法調用的風格獲取數組的長度了,這樣看起來貌似也更加OO一點。那為什么不使用Array.length()的語法呢?也許是開發Java的那幫天才對.length有所偏愛,或者拋硬幣拍腦袋隨便決定的吧。 形式不重要,重要的是我們明白了背后的機理。

Array in Java

最后,對Java中純對象的數組發表點感想吧。

#t#相比C/C++中的數組,Java數組在安全性要好很多。C/C++常遇到的緩存區溢出或數組訪問越界的問題,在Java中不再存在。因為Java使用特定的指令訪問數組的元素,這些指令都會對數組的長度進行檢查。如果發現越界,就會拋出java.lang.ArrayIndexOutOfBoundsException。

Java數組元素的靈活性比較大。一個數組的元素本身也可以是數組,只要所有元素的數組類型相同即可。我們知道數組的類型和長度無關,因此元素可以是長度不同的數組。這樣,Java的多維數組就不一定是規規矩矩的矩陣了,可以千變萬化。

責任編輯:yangsai 來源: JavaEye博客
相關推薦

2022-11-13 15:33:30

JavaScript數組開發

2019-07-25 10:08:05

JavaScript數組轉換

2023-07-04 15:52:49

JavaScript數組

2023-02-01 08:31:48

2016-10-08 21:25:36

Javascript數組Web

2020-03-19 15:30:08

JavaScript數組字符串

2024-10-21 13:05:40

2022-11-23 16:12:57

JavaScript數據類型數組

2021-02-07 07:52:07

數組 JavaScript結構

2022-05-06 12:03:16

數組Javascript

2022-09-15 08:05:16

緩沖區類型TypedArray

2025-02-10 07:00:00

JavaScript數組方法前端

2022-04-28 08:41:53

JavaScript數組

2011-04-13 14:04:14

Java數組

2023-11-14 16:57:10

2009-06-11 13:00:08

Java數組賦值

2024-03-21 14:27:13

JavaScript數組

2010-09-27 13:41:22

JVM內存回收

2009-07-09 17:36:58

jvm.cfg

2009-09-10 15:32:54

事件與委托
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美精品网站 | 日韩免费一二三区 | 成人精品区 | 伊人久久麻豆 | 99av成人精品国语自产拍 | 国产国拍亚洲精品av | 中文字幕日韩欧美 | 国产免费一区 | 欧美精品一区二区三区视频 | 综合久久av| 久久久久久艹 | 国产精品成人一区二区三区吃奶 | 亚洲欧美日韩精品久久亚洲区 | 六月色婷 | 91久久精品一区二区二区 | 亚洲精品一区中文字幕乱码 | 九九免费视频 | 色偷偷噜噜噜亚洲男人 | 日本理论片好看理论片 | 午夜免费视频 | 免费在线观看一级毛片 | 久久丝袜| 亚洲狠狠爱 | 一区二区三区在线观看视频 | 天天天堂| 日韩1区| 久久久片 | 中文天堂在线一区 | 成人午夜精品 | 天天射影院 | 亚洲电影一区二区三区 | 2019天天操| 精品一区二区在线视频 | 玖玖国产 | 97精品国产 | 欧美福利一区 | 亚洲一区二区精品视频 | 国产日韩一区二区三区 | 国产真实精品久久二三区 | 中文字幕免费观看 | 国产一区二区三区视频 |