java的數組初始化

來源:互聯網
上載者:User

在C中初始化數組極易出錯,而且相當麻煩。C++通過“集合初始化”使其更安全(注釋⑥)。Java則沒有象C++那樣的“集合”概念,因為Java中的所有東西都是對象。但它確實有自己的數組,通過數組初始化來提供支援。
數組代表一系列對象或者基礎資料型別 (Elementary Data Type),所有相同的類型都封裝到一起——採用一個統一的標識符名稱。數組的定義和使用是通過方括弧索引運算子進行的([])。為定義一個數組,只需在類型名後簡單地跟隨一對空方括弧即可:
int[] al;
也可以將方括弧置於標識符後面,獲得完全一致的結果:
int al[];
這種格式與C和C++程式員習慣的格式是一致的。然而,最“通順”的也許還是前一種文法,因為它指出類型是“一個int數組”。本書將沿用那種格式。
編譯器不允許我們告訴它一個數組有多大。這樣便使我們回到了“控制代碼”的問題上。此時,我們擁有的一切就是指向數組的一個控制代碼,而且尚未給數組分配任何空間。為了給數組建立相應的儲存空間,必須編寫一個初始設定式。對於數組,初始化工作可在代碼的任何地方出現,但也可以使用一種特殊的初始設定式,它必須在數組建立的地方出現。這種特殊的初始化是一系列由花括弧封閉起來的值。儲存空間的分配(等價於使用new)將由編譯器在這種情況下進行。例如:
int[] a1 = { 1, 2, 3, 4, 5 };
那麼為什麼還要定義一個沒有數組的數組控制代碼呢?
int[] a2;
事實上在Java中,可將一個數組分配給另一個,所以能使用下述語句:
a2 = a1;
我們真正準備做的是複製一個控制代碼,就象下面示範的那樣:

 

//: Arrays.java// Arrays of primitives.public class Arrays {  public static void main(String[] args) {    int[] a1 = { 1, 2, 3, 4, 5 };    int[] a2;    a2 = a1;    for(int i = 0; i < a2.length; i++)      a2[i]++;    for(int i = 0; i < a1.length; i++)      prt("a1[" + i + "] = " + a1[i]);  }  static void prt(String s) {    System.out.println(s);  }} ///:~


大家看到a1獲得了一個初始值,而a2沒有;a2將在以後賦值——這種情況下是賦給另一個數組。
這裡也出現了一些新東西:所有數組都有一個本質成員(無論它們是對象數組還是基本類型數組),可對其進行查詢——但不是改變,從而獲知數組內包含了多少個元素。這個成員就是length。與C和C++類似,由於Java數組從元素0開始計數,所以能索引的最大元素編號是“length-1”。如超出邊界,C和C++會“默默”地接受,並允許我們胡亂使用自己的記憶體,這正是許多程式錯誤的根源。然而,Java可保留我們這受這一問題的損害,方法是一旦超過邊界,就產生一個運行期錯誤(即一個“違例”,這是第9章的主題)。當然,由於需要檢查每個數組的訪問,所以會消耗一定的時間和多餘的代碼量,而且沒有辦法把它關閉。這意味著數組訪問可能成為程式效率低下的重要原因——如果它們在關鍵的場合進行。但考慮到網際網路訪問的安全,以及程式員的編程效率,Java設計人員還是應該把它看作是值得的。
程式編寫期間,如果不知道在自己的數組裡需要多少元素,那麼又該怎麼辦呢?此時,只需簡單地用new在數組裡建立元素。在這裡,即使準備建立的是一個基礎資料型別 (Elementary Data Type)的數組,new也能正常地工作(new不會建立非數組的基本類型):

 

//: ArrayNew.java// Creating arrays with new.import java.util.*;public class ArrayNew {  static Random rand = new Random();  static int pRand(int mod) {    return Math.abs(rand.nextInt()) % mod + 1;  }  public static void main(String[] args) {    int[] a;    a = new int[pRand(20)];    prt("length of a = " + a.length);    for(int i = 0; i < a.length; i++)      prt("a[" + i + "] = " + a[i]);  }  static void prt(String s) {    System.out.println(s);  }} ///:~


由於數組的大小是隨機決定的(使用早先定義的pRand()方法),所以非常明顯,數組的建立實際是在運行期間進行的。除此以外,從這個程式的輸出中,大家可看到基礎資料型別 (Elementary Data Type)的數組元素會自動初始化成“空”值(對於數值,空值就是零;對於char,它是null;而對於boolean,它卻是false)。
當然,數組可能已在相同的語句中定義和初始化了,如下所示:
int[] a = new int[pRand(20)];
若操作的是一個非基本類型對象的數組,那麼無論如何都要使用new。在這裡,我們會再一次遇到控制代碼問題,因為我們建立的是一個控制代碼數組。請大家觀察封裝器類型Integer,它是一個類,而非基礎資料型別 (Elementary Data Type):

 

//: ArrayClassObj.java// Creating an array of non-primitive objects.import java.util.*;public class ArrayClassObj {  static Random rand = new Random();  static int pRand(int mod) {    return Math.abs(rand.nextInt()) % mod + 1;  }  public static void main(String[] args) {    Integer[] a = new Integer[pRand(20)];    prt("length of a = " + a.length);    for(int i = 0; i < a.length; i++) {      a[i] = new Integer(pRand(500));      prt("a[" + i + "] = " + a[i]);    }  }  static void prt(String s) {    System.out.println(s);  }} ///:~


在這兒,甚至在new調用後才開始建立數組:
Integer[] a = new Integer[pRand(20)];
它只是一個控制代碼數組,而且除非通過建立一個新的Integer對象,從而初始化了物件控點,否則初始化進程不會結束:
a[i] = new Integer(pRand(500));
但若忘記建立對象,就會在運行期試圖讀取空數組位置時獲得一個“違例”錯誤。
下面讓我們看看列印語句中String對象的構成情況。大家可看到指向Integer對象的控制代碼會自動轉換,從而產生一個String,它代表著位於對象內部的值。
亦可用花括弧封閉列表來初始化對象數組。可採用兩種形式,第一種是Java 1.0允許的唯一形式。第二種(等價)形式自Java 1.1才開始提供支援:

 

//: ArrayInit.java// Array initializationpublic class ArrayInit {  public static void main(String[] args) {    Integer[] a = {      new Integer(1),      new Integer(2),      new Integer(3),    };    // Java 1.1 only:    Integer[] b = new Integer[] {      new Integer(1),      new Integer(2),      new Integer(3),    };  }} ///:~


這種做法大多數時候都很有用,但限制也是最大的,因為數組的大小是在編譯期間決定的。初始化列表的最後一個逗號是可選的(這一特性使長列表的維護變得更加容易)。
數組初始化的第二種形式(Java 1.1開始支援)提供了一種更簡便的文法,可建立和調用方法,獲得與C的“變數參數列表”(C通常把它簡稱為“變參表”)一致的效果。這些效果包括未知的參數(自變數)數量以及未知的類型(如果這樣選擇的話)。由於所有類最終都是從通用的根類Object中繼承的,所以能建立一個方法,令其擷取一個Object數組,並象下面這樣調用它:

 

//: VarArgs.java// Using the Java 1.1 array syntax to create// variable argument listsclass A { int i; }public class VarArgs {  static void f(Object[] x) {    for(int i = 0; i < x.length; i++)      System.out.println(x[i]);  }  public static void main(String[] args) {    f(new Object[] {         new Integer(47), new VarArgs(),         new Float(3.14), new Double(11.11) });    f(new Object[] {"one", "two", "three" });    f(new Object[] {new A(), new A(), new A()});  }} ///:~


此時,我們對這些未知的對象並不能採取太多的操作,而且這個程式利用自動String轉換對每個Object做一些有用的事情。在第11章(運行期類型標識或RTTI),大家還會學習如何調查這類對象的準確類型,使自己能對它們做一些有趣的事情。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.