Java——數組(概念理解+應用舉例)

1.關於Java中的數組:  

在Java語言中,數組是一個非常重要的概念,我們經常使用的數組,在這裏和C語言基本上是一樣的,無非是“一維數組”和“二維數組”,那麼對數組的初始化定義有兩種方法,一個是“靜態初始化”,另一個自然就是“動態初始化”。

數組是一種數據結構,系統爲數組分配的存儲空間是連續的、指定長度的、且大小固定不變的,用來存儲一組大小固定並且類型相同的數據。 這些數據可以通過索引進行訪問,數組的下標索引是從 0 開始,其取值範圍必需是:0~數組長度-1 。 數組是JVM的核心類型,是 Java 語言的基元類型。數組類和數組實例的數據結構具有特殊性,由 JVM 決定。運行時,數組越界的檢查通過數組實例的 length 屬性來完成,數組元素類型匹配的檢查通過數組類中的元素類型屬性來完成。

Java數組具有以下幾個特點:

①多維數組均是一維指針數組(數組實例) 。

②Java 中的數組是靜態數組,數組被創建後,其大小是不能改變的。

③由JVM掃描時產生數組類型(數組類型動態產生)。

④數組越界,在 Java 中是運行時錯誤,產生異常(數組的 length 字段)。在 C 語言中是邏輯錯誤。而JVM 在運行時判斷,如果未越界則繼續運行,如果越界則拋出異常。例如:數組越界、顯式強類型轉換等。

當然了,我們在使用Java數組的時候,難免的會出現一些錯誤問題,在處理這些問題的時候,一般是下面的步驟👇👇👇

存在的問題→檢測問題→解決問題

1. 存在的問題:①數組越界問題,②數組元素類型匹配問題。(這兩個相信大家在C語言的學習中,一定不陌生)

2. 檢測問題:①數組越界問題由JVM在運行時來檢測,如果存在問題,則拋出異常。

                      ②數組元素類型匹配,值類型匹配錯誤是邏輯錯誤。

                      ③數組元素類型匹配,引用類型匹配錯誤是異常。

3. 解決問題:捕獲異常,處理異常。

下面,我們來看一個例子:👇👇👇

public class Test {
	public static void main(String[] args) {
		int[] a= {4,5,6};//靜態初始化
		a[0]=1234567890;//修改a[0]的內容
		System.out.println("int a[0]="+a[0]);//輸出修改之後的a[0]
		try {
			int i=3;
                        //由於所創建的數組a中只有三個值,而數組下標從0開始,所以只有a[0],a[1]和a[2]
			a[i]=8;
                        //這裏的a[3]顯然會產生越界問題
		}
		catch (Exception e) {//在這裏直接捕獲,並處理異常
			System.out.println("數組越界異常!");
		}
	}
}

運行結果如下: 

可以看到程序輸出了上圖的結果!!!

在這裏,我們首先使用靜態初始化來創建一個數組a,包含3個數,因爲數組的下標是從0開始的,所以這三個數分別對應a[0],a[1]和a[2],那麼,我們修改a[0]是完全可以的。但是後面又企圖對a[3]進行賦值,顯然已經超出數組下標的最大範圍,這裏會產生越界問題,直接跳轉到下面的catch語句來捕獲並處理異常!!!

2.一維數組:

1. JVM 在運行一個方法之前,先掃描方法體,如果類對象不存在,則先創建該類 對象。然後,單步解釋執行 main()方法體內的代碼。

2. 數組類對象非常特殊,是由 JVM 掃描時自動產生的。在掃描 main()方法體時, JVM 將首先在 Java 方法區,建立int[ ]數組類對象、double[ ]數組類對象、 char[ ]數組類對象、boolean[ ]數組類對象、String[ ]數組類對象。 數組實例的數據結構具有特殊性,也由 JVM 決定。

3. 然後,單步解釋執行 main()方法體內的代碼。

例如:double[ ] b = new double[10]; 賦值語句

①賦值號左邊,首先在堆棧壓棧一個變量b,該變量b的類型是一個double[ ]數組類型,是一個引用類型。

②然後賦值號右邊,生成double[ ]數組類型的一個數組實例。

③最後賦值號,將生成的數組實例的引用賦予變量b,即變量b引用數組實例。

下面,我們來看一個例子!!!👇👇👇

import java.util.*;
public class Main
{
	public static void main(String[] args)
	{
		int[] a=new int[10];
		double[] b=new double[10];
		char[] c=new char[100];
		boolean[] d=new boolean[20];
		String[] s=new String[5];
		/*下面輸出各數組的數組名,注意輸出的內容 */ 
		System.out.println("輸出數組對象*****************");
		System.out.println(a);// 輸出整型數組對象的哈希瑪(地址)   
		System.out.println(b);// 輸出雙精度浮點型數組對象的哈希瑪(地址)   
		System.out.println(c);// 輸出字符型數組中的內容   
		System.out.println(d);// 輸出布爾型數組對象的哈希瑪(地址)   
		System.out.println(s);// 輸出字符串數組對象的哈希瑪(地址)
		System.out.println("-------------------------"); 
		/*下面輸出各數組中第一個元素的值,注意輸出的內容 */ 
		System.out.println("輸出數組對象的成員************");
		System.out.println(a[0]);   
		System.out.println(b[0]);   
		System.out.println(c[0]); 
		System.out.println(d[0]);
		System.out.println(s[0]);   
		System.out.println("-------------------------"); 
		/*下面輸出各數組的長度 */ 
		System.out.println("輸出數組對象的長度***********");
		System.out.println("a.length="+a.length);   
		System.out.println("b.length="+b.length);   
		System.out.println("c.length="+c.length);   
		System.out.println("d.length="+d.length);   
		System.out.println("s.length="+s.length);   
		System.out.println("-------------------------"); 
		//getClass()是Object的方法成員  
		//getSuperclass()、getName()是Class的方法成員
		System.out.println("輸出數組類的超類和反射類***********");        
		System.out.println("int數組實例的類:"+a.getClass().getName());
		System.out.println("double數組實例的類:"+b.getClass().getName());
		System.out.println("char數組實例的類:"+c.getClass().getName());
		System.out.println("boolean數組實例的類:"+d.getClass().getName());
		System.out.println("String數組實例的類:"+s.getClass().getName());
		//輸出類的超類Object
		System.out.println("int數組實例的類的父類:"+a.getClass().getSuperclass().getName());
		//輸出類的反射類類Class
		System.out.println("int數組實例的類的反射類:"+a.getClass().getClass().getName());
		Class c1=a.getClass();
		Class c2=b.getClass();
		System.out.println("a、b相同的父類:"+(c1==c2));
		Class d1=a.getClass().getSuperclass();
		Class d2=b.getClass().getSuperclass();
		System.out.println("a、b相同的父類:"+(d1==d2));
	}
}

運行結果如下: 

在Java語言中,Object類是所有類的父類,在代碼中,我們通過getClass()來獲取當前類的對象,而getSuperclass()是獲取父類的對象,後面的getName()則是獲取對應的名稱。

最後6行中,因爲數組a是int類型的,而數組b是double類型的,所以它們通過getClass()獲取當前類的對象並不是相同的,而通過getSuperclass()獲取當前父類的對象是相同的,因爲其父類都是Object。

(這段代碼的輸出結果中,有哈希碼、反射類這些知識,博主也還在學習的過程中,所以在這裏先不談這個)

3.初始化數組

public class Test {
	public static void main(String[] args) {
		int[] a= {5,7,20};//定義並初始化數組,使用靜態初始化 
		int[] b=new int[4];//定義並初始化數組,使用動態初始化 
		for(int i=0;i<b.length;i++) {
			b[i]=i+1;
		}	
		//循環輸出a數組的元素   
		System.out.println("數組a中的元素是:");
		for(int i=0;i<a.length;i++) {
			System.out.print(a[i]+" ");
		}
		System.out.println();
		//輸出b數組的長度
		System.out.println("b數組的長度爲:"+b.length);   
		System.out.println("數組b中的元素是:");
		//循環輸出b數組的元素   
		for(int i=0;i<b.length;i++) {
			System.out.print(b[i]+" ");
		}
		System.out.println();
		//因爲a是int[]類型,b也是int[]類型,所以可以將a的值賦給b。   
		//也就是讓b引用指向a引用指向的數組
		b=a;
		//再次輸出b數組的長度   
		System.out.println("b數組的長度爲:"+b.length);
		//再次循環輸出b數組的元素  
		for(int i=0;i<b.length;i++) {
			System.out.print(b[i]+" ");
		}
	}
}

運行結果如下:

代碼中註釋寫的挺詳細的,大家可以看一下,對比程序運行結果,理解一下Java初始化數組的這樣一個過程!!!

下面,我們在初始化數組的過程中,如果想要遍歷輸出數組元素,有下面兩種方法👇👇👇

for(int i=0;i<a.length;i++) {
    System.out.print(a[i]+" ");
}
for(int e:a) {
    System.out.print(e+" ");
}
public class Test {
	public static void main(String[] args) {
		int[] a=new int[5];//定義並初始化數組,使用動態初始化 
		for(int i=0;i<a.length;i++) {
			a[i]=i+1;
		}
		System.out.println("數組a中的元素是:");
		//使用foreach語句遍歷輸出a數組中的元素 
		for(int e:a) {
			System.out.print(e+" ");
		}
	}
}

運行結果如下: 

4.二維數組

Java中的多維數組本質上是多維的指針數組,均由多個一維數組組成。 

Java的二維數組實際上是一維的指針數組。在Java中不存在矩陣數組。 

我們來看下面的例子!!!👇👇👇

public class Test {
	public static void main(String[] args) {
		int[][] a={ {1,2,3 },{4,5,6} };//二維數組靜態初始化    
		System.out.println("數組a一維長度:"+a.length);   
		System.out.println("數組a二維長度:"+a[0].length);   
		System.out.println("數組a中的元素:");   
		//使用嵌套的for循環輸出   
		for(int i=0;i<a.length;i++) {    
			for(int j=0;j<a[i].length;j++) {     
				System.out.print(a[i][j]+" ");    
			}    
			System.out.println();   
		}   
		System.out.println("-------------------------");    
		int[][] c=new int[3][4];//二維數組動態初始化,一維和二維都指定長度    
		//使用嵌套的for循環初始化二維數組  
		for(int i=0;i<c.length;i++) {    
			for(int j=0;j<c[i].length;j++) {     
				c[i][j]=i+j;    
			}   
		}   
		System.out.println("數組c中的元素:");
		//使用嵌套的for循環輸出   
		for(int i=0;i<c.length;i++) {    
			for(int j=0;j<c[i].length;j++) {     
				System.out.print(c[i][j]+" ");
			}    
			System.out.println();   
		}   
		System.out.println("-------------------------"); 
		int[][] d=new int[2][];//聲明二維數組時,只給出一維長度   
		//二維長度不等   
		d[0]=new int[3];   
		d[1]=new int[4];   
		//初始化   
		for(int i=0;i<d.length;i++) {    
			for(int j=0;j<d[i].length;j++) {     
				d[i][j]=i+j;    
			}   
		}   
		System.out.println("數組d中的元素:");   
		//使用嵌套的for循環輸出   
		for(int i=0;i<d.length;i++) {    
			for(int j=0;j<d[i].length;j++) {     
				System.out.print(d[i][j]+" ");    
			}    
			System.out.println();   
		}   
		System.out.println("-------------------------"); 
		//數組類的超類和反射類   
		System.out.println("a數組實例的類:"+a.getClass().getName());   
		System.out.println("a[0]數組實例的類:"+a[0].getClass().getName());   
		System.out.println("a數組實例的類的父類:"+a.getClass().getSuperclass().getName());   
		System.out.println("a數組實例的類的反射類:"+a.getClass().getClass().getName());
		Class c1=a.getClass();   
		Class c2=d.getClass();   
		System.out.println("a、d相同的父類:"+(c1==c2));
	}
}

運行結果如下:

在Java語言的二維數中,它的一維長度其實就是對應的二維數組的行數,而二維長度其實就是對應的二維數組的列數。而二維長度可以明確指定,也可以不指定,即二維長度不一定是相等的,也可能在第一行中是3列,在第二行中變成了4列。

在遍歷輸出二維數組的時候,要注意雙重for循環👇👇👇

for(int i=0;i<a.length;i++) {//對應的是二維數組a的行數
    for(int j=0;j<a[i].length;j++) {//對應的是二維數組a的列數
	System.out.print(a[i][j]+" ");    
    }    
    System.out.println();   
}

在這裏,我們仍然可以通過getClass().getSuperclass().getName()來獲取其父類的名字,也就是Object類。

因爲二維數組a和二維數組d都是int類型的,所以直接通過getClass()獲取的當前類的對象就是相同的,即true。


在看完了這篇博文之後,我們主要對Java數組有了一定的理解,包括:使用數組會產生的一些問題及解決方法,一維和二維數組的定義初始化、賦值以及遍歷輸出。

這就是博主總結的Java數組的相關內容,希望對你們有所幫助!!!歡迎大家留言評論!!!😀😀😀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章