1. 程式人生 > 其它 >假期java自學-----陣列1

假期java自學-----陣列1

一直以來陣列的學習對我來說都比較抽象,今天特對c++和java陣列做了對比
一、 陣列名區別
1.java中不用說,本著一切皆物件的原則,所以java中的陣列也是物件.那麼陣列類是哪個,當然不是java.util.Arrays.詳見Java陣列方法的思考
2.而在c++中陣列名其實是一種資料結構,有人會說不是指標嗎,關於這一點見(C++中陣列名其實是一種資料結構)。
從上面兩點中我們可以看出java陣列名是物件,而c++陣列名是資料結構。那麼有人又會問物件和資料結構又有什麼區別呢?詳見資料結構與物件的區別。
二、原理區別
JAVA裡陣列的記憶體分配是在堆裡面的,必須用new來分配,而C++裡面是在棧裡面分配的,定義的時候會自動分配。
java中的陣列
1、陣列不是集合,它只能儲存同種型別的多個原始型別或者物件的引用。陣列儲存的僅僅是物件的引用,而不是物件本身。陣列宣告的兩種形式:一、int[]arr;二、intarr[];推薦使用前者,這是一個int陣列物件,而不是一個int原始型別。
2、陣列本身就是物件,Java中物件是在堆中的,因此陣列無論儲存原始型別還是其他物件型別,陣列物件本身是在堆中的。
3、在陣列宣告中包含陣列長度永遠是不合法的!如:int[5]arr;。因為,宣告的時候並沒有例項化任何物件,只有在例項化陣列物件時,JVM才分配空間,這時才與長度有關。
4、在陣列構造的時候必須指定長度,因為JVM要知道需要在堆上分配多少空間。例:int[]arr=newint[5];
5、一維陣列的構造。形如:String[]sa=newString[5];或者分成兩句:String[]sa;sa=newString[5];
6、原始型別陣列元素的預設值。對於原始型別陣列,在用new構造完成而沒有初始化時,JVM自動對其進行初始化。預設值:byte、short、int、long--0float--0.0fdouble--0.0boolean--falsechar--'"u0000'。(無論該陣列是成員變數還是區域性變數)
7、物件型別的陣列雖然被預設初始化了,但是並沒有呼叫其建構函式。(C++中則會呼叫)也就是說:Car[]myCar=newCar[10];只建立了一個myCar陣列物件!並沒有建立Car物件的任何例項!
8、多維陣列的構造。float[][]ratings=newfloat[9][];第一維的長度必須給出,其餘的可以不寫,因為JVM只需要知道賦給變數ratings的物件的長度。
9、陣列索引的範圍。陣列中各個元素的索引是從0開始的,到length-1。每個陣列物件都有一個length屬性,它儲存了該陣列物件的長度。(注意和String物件的length()方法區分開來)
10、Java有陣列下標檢查,當訪問超出索引範圍時,將產生ArrayIndexOutOfBoundsException執行時異常。注意,這種下標檢查不是在編譯時刻進行的,而是在執行時!也就是說int[]arr=newint[10];arr[100]=100;這麼明顯的錯誤可以通過編譯,但在執行時丟擲!
Java中的陣列中既可以儲存基本的值型別,也可以儲存物件。物件陣列和原始資料型別陣列在使用方法上幾乎是完全一致的,唯一的差別在於物件陣列容納的是引用而原始資料型別陣列容納的是具體的數值。在討論關於陣列的問題時,一定要先確定陣列中儲存的是基本值型別還是物件。特別是在除錯程式時,要注意這方面。
三、.類陣列是否呼叫建構函式
對於上面提到的第7點物件型別的陣列雖然被預設初始化了,但是並沒有呼叫其建構函式。我必須要重點解釋下,因為在c++中會呼叫其建構函式,這裡最容易搞混。
publicclassTestextendsJPanel{
privatestaticfinallongserialVersionUID=4767050156491994899L;
publicstaticvoidmain(String[]args){
AnimApp[]array=newAnimApp[3];//沒有執行建構函式,在這裡只是申請了空間.
array[0]=newAnimApp(3);//構造一個物件
}
}
classAnimApp{
publicAnimApp(inttimes){
System.out.println("classAnimApp");
}
}
看下上面這段java程式碼,當執行AnimApp[]array=newAnimApp[3];時並不會呼叫建構函式,僅僅申請了空間。構造物件的時候才會呼叫建構函式。
Java中,定義一個數組,new[]時,並沒有執行建構函式,只是申請了一段記憶體空間,與C++中的allocator<T>.allocate(size)(因為allocator<T>的型別在執行時確定,所以不是指定空間的位元組數,而是用元素個數,每個元素的大小allocator中有記錄)相似.然後在構造一個物件的時候,即如上newAnimApp(3)時,才真正的構造物件,似allocator<T>.construct(param).
C++中,new[]操作符(預設的)就會去先申請空間,接著執行建構函式,申請了多少個物件的空間,執行多少次(每個物件一次),所以想為無無參建構函式的類使用預設的new[]來定義一個數組是不行的,這點與Java不同,他是即申請空間,同時也要構造物件,Java只是申請一段空間,對於空間中的每個物件,得自己顯示的用newClassName(param)來構造.
對於Java這種與C++不同之處的原因要歸為它們之間的實現不同。
1)Java的陣列不是集合,它只能儲存同種型別的多個原始型別或者物件的引用。陣列儲存的僅僅是物件的引用,而不是物件本身。
2)陣列本身就是物件,Java中物件是在堆中的,因此陣列無論儲存原始型別還是其他物件型別,陣列物件本身是在堆中的。
3)在Java中,官方推薦的宣告方式是Object[]array,並且不能指定長度,只有new的時候才指定長度。
4)物件型別陣列中的引用被預設初始化為null。如:Object[]myobj=newObject[10];相當於從myobj[0]到myobj[9]都這樣被自動初始化為myCar[i]=null;並沒有呼叫建構函式。在myobj[1]=newObject的時候才呼叫。
至於Java為什麼要選擇這種方式,則是其刻意避免指標(容易犯錯),符號都是引用型別。
幾乎所有的程式設計語言都支援陣列。在C和C++中使用陣列是很危險的。因為C和C++中的陣列就是記憶體塊。如果一個程式要訪問其自身記憶體塊之外的陣列,或者在陣列初始化之前使用它,都會產生難以預料的後果。
java的主要目標之一就是安全性。java確保陣列會被初始化,而且不能在它的範圍之外被訪問。這種範圍檢查,是以每個陣列上少量的記憶體開銷以及執行時的下標檢查為代價的。但是由此換來的安全性和效率的提高,也是值得的。
當java建立一個數組物件時,實際上就是建立了一個引用陣列,並且每個引用都會被自動初始化一個特殊值。該值擁有自己的關鍵字null,一旦java看見了null,就知道這個引用還沒有指向某個物件。如果使用某個指向null的引用,就會在執行時報錯。