陣列與方法
陣列按照使用可以分為一維陣列/二維陣列/多維陣列.
1.陣列的概述
-
陣列是相同資料型別的有序集合
陣列描述的是相同型別的若干個資料,按照一定的先後次序排列組合而成.其中,每個資料稱作一個陣列的元素,每個陣列元素可以通過一個索引(或者下標)來訪問它們.
-
陣列的三個特點:
- 陣列的長度是確定的. 陣列當被建立時,它的大小就是不可以改變的.
- 陣列元素必須是相同型別,不允許出現混合型別
- 陣列中的元素可以是任何資料型別,包括基本資料型別和引用資料型別
2.一維陣列
(1) 宣告方式
-
方式一
資料型別 陣列名[] = null ; //宣告一維陣列 陣列名 = new 陣列型別[長度]; // 分配記憶體給陣列 複製程式碼
-
方式二
資料型別[] 陣列名 = null ; //宣告一維陣列 陣列名 = new 陣列型別[長度]; // 分配記憶體給陣列 複製程式碼
-
簡寫方式
資料型別 陣列名[] = new 資料型別[個數]; //宣告陣列的同時分配記憶體 複製程式碼
(2) 陣列中元素的表示方法
-
陣列的宣告以及簡單輸出
package com.shxt.demo01; public class ArrayDemo01 { public static void main(String[] args) { int[] score = null; //宣告陣列,但是為開闢記憶體空間 score = new int[3]; //為陣列開闢"堆記憶體"空間 System.out.println("score[0]="+score[0]); //分別輸出陣列的每個元素 System.out.println("score[1]="+score[1]); //分別輸出陣列的每個元素 System.out.println("score[2]="+score[2]); //分別輸出陣列的每個元素 // 使用迴圈依次輸出陣列中的全部內容 for (int i = 0; i < 3; i++) { System.out.println("score["+i+"]="+score[i]); } } } 複製程式碼
對於陣列的訪問採用"陣列名稱[索引或者下標]"的方式,索引從0開始計數,假設程式中取出的內容超過了這個下標範圍,例如:
score[3]
程式執行會存在以下的異常錯誤提示資訊:java.lang.ArrayIndexOutOfBoundsException:3 複製程式碼
提示的內容為陣列索引超出繫結的異常(經常說的陣列越界異常),這個是未來你們初學者經常出現的問題,請引起重視.此外,我們發現以上的程式執行的結果的內容都是"0",這是因為宣告的陣列是整型陣列.
預設初始化資料:陣列元素相當於物件的成員變數,預設值跟成員的規則是一樣的,重點記憶!
系統將按照如下規則分配初識值:
- 陣列元素的型別是基本型別中的整數型別(byte,short,int和long),則陣列元素的值為0
- 陣列元素的型別是基本型別中的浮點型別(float,double),則陣列元素的值為0.0
- 陣列元素的型別是基本型別中的字元型別(char),則陣列元素的值為'\u0000'(空格)
- 陣列元素的型別是基本型別中的布林型別(boolean),則陣列元素的值為false
- 陣列元素的型別是引用資料型別(類,介面和陣列),則陣列元素的值為null
-
為陣列中的元素賦值並進行輸出
宣告整型陣列,長度為5,通過for迴圈賦值1,3,5,7,9的資料
package com.shxt.demo01; public class ArrayDemo02 { public static void main(String[] args) { int[] score = null; //宣告陣列,但是為開闢記憶體空間 score = new int[5]; //為陣列開闢"堆記憶體"空間 for (int i = 0; i < 5; i++) { score[i] = i*2+1; } for (int i = 0; i < 5; i++) { System.out.println("score["+i+"]="+score[i]); } } } 複製程式碼
-
陣列長度的取得
陣列名稱.length --> 返回一個int型的資料 複製程式碼
package com.shxt.demo01; public class ArrayDemo03 { public static void main(String[] args) { int[] score = new int[5]; System.out.println("陣列長度為:"+score.length); } } 複製程式碼
(3) 陣列的初始化方式
-
動態初始化
之前練習的就是使用的動態初始化方式
package com.shxt.demo01; public class ArrayDemo04 { public static void main(String[] args) { int[] score = null; //宣告陣列,但是為開闢記憶體空間 score = new int[3]; //為陣列開闢"堆記憶體"空間 score[0] = 100; score[1] = 200; score[2] = 300; } } 複製程式碼
-
靜態初始化
資料型別[] 陣列名={初始值0,初始值1,...,初始值N} 或者 資料型別[] 陣列名 = new 資料型別[]{初始值0,初始值1,...,初始值N} 複製程式碼
package com.shxt.demo01; public class ArrayDemo04 { public static void main(String[] args) { int[] score = {10,20,30,40,50}; for (int i = 0; i < score.length; i++) { System.out.println("score["+i+"]="+score[i]); } } } 複製程式碼
(4) 課堂練習
-
已知一個字元陣列
char[] letterArray = new char[26]
,請動態初始化資料為A~Zpackage com.shxt.demo01; public class ArrayDemo05 { public static void main(String[] args) { char[] letterArray = new char[26]; for (int i = 0; i < letterArray.length; i++) { letterArray[i] = (char)('A'+i); } for (int i = 0; i < letterArray.length; i++) { System.out.print(letterArray[i]+"\t"); } } } 複製程式碼
-
請求陣列中最大和最小值
package com.shxt.demo01; public class ArrayDemo06 { public static void main(String[] args) { int array[]={74,12,48,888,30,5,17,62,777,666}; int max = array[0]; int min = array[0]; for (int i = 0; i < array.length; i++) { if(array[i]>max){ max=array[i]; } if(array[i]<min){ min=array[i]; } } System.out.println("最高成績:"+max); System.out.println("最低成績:"+min); } } 複製程式碼
-
對整數陣列按照由小到大的順序進行排序
public class ArrayDemo07 { public static void main(String[] args) { int arr[] = {13,34,57,78,99,66,43,45,87,100}; for (int i = 0 ; i < arr.length; i++) { for (int j = 0; j < arr.length-1; j++) { if(arr[j]>arr[j+1]){ int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } System.out.print("第"+i+"次排序的結果:\t"); for (int k = 0; k < arr.length; k++) { System.out.print(arr[k]+"\t"); } System.out.println(); } System.out.print("最終的排序結果:\t"); for (int k = 0; k < arr.length; k++) { System.out.print(arr[k]+"\t"); } } } 複製程式碼
排序自學參考資料: http://geek.csdn.net/news/detail/113928
(5) 陣列的問題
-
陣列一定要初始化嗎?
在之前我們說在使用Java陣列之前必須要先初始化陣列(即在使用陣列之前,必須先建立陣列).實際上,如果真正掌握了Java陣列中的分配機制,那麼可以完全換一個方式來初始化陣列.
始終記住:Java的陣列變數只是引用型別的變數,它並不是陣列物件本身,只是讓陣列變數指向有效的陣列物件,程式中即可使用該陣列變數
package com.shxt.demo01; public class ArrayDemo08 { public static void main(String[] args) { // 靜態初始化:定義並且初始化nums陣列 int nums[] = {13,34,57,100}; // 定義一個scores陣列變數 int[] scores; //讓scores陣列執行nums所引用的陣列 scores = nums ; // 對scores進行變數 System.out.print("scores陣列資料:"); for (int i = 0; i < scores.length; i++) { System.out.print(scores[i]+"\t"); } // 將scores陣列中第3個元素賦值為200 scores[2] = 200; // 訪問 nums 陣列的第3個元素,將看到輸出值為200 System.out.println("\nnums 陣列的第3個元素,將看到輸出值為:"+nums[2]); } } 複製程式碼
既然陣列內容可以進行引用傳遞,那麼就可以把陣列作為方法中的引數,而如果一個方法想接收引數,則對應的引數型別必須是陣列
-
使用方法接收陣列
package com.shxt.demo01; public class ArrayDemo09 { public static void main(String[] args) { // 靜態初始化:定義並且初始化nums陣列 int nums[] = {13,34,57,100}; // 引用傳遞, int[] temp = nums print(nums); } public static void print(int[] temp){ for (int i = 0; i < temp.length; i++) { System.out.print(temp[i]+"\t"); } } } 複製程式碼
-
使用方法修改陣列的內容
package com.shxt.demo01; public class ArrayDemo10 { public static void main(String[] args) { // 靜態初始化:定義並且初始化nums陣列 int nums[] = {1,2,3,4,5}; // 引用傳遞, int[] temp = nums inc(nums); //擴容操作 print(nums); //列印內容 } public static void inc(int[] temp){ for (int i = 0; i < temp.length; i++) { temp[i]*=2; } } public static void print(int[] temp){ for (int i = 0; i < temp.length; i++) { System.out.print(temp[i]+"\t"); } } } 複製程式碼
3.二維陣列
之前定義的陣列只有一個"[]",表示一維陣列,如果有兩個"[]"就是二維陣列,其實本質上不存在多維陣列的概念,其實就是一維陣列中有巢狀了陣列而已
-
一維陣列表格表示
索引 0 1 2 3 4 5 資料 10 20 30 40 50 60
-
二維陣列表格表示
int[3][6]
索引 0 1 2 3 4 5 0 3 4 5 6 7 8 1 10 20 30 50 40 60 2 111 222 333 444 555 666 -
二維陣列的定義
-
動態初始化
資料型別[][] 陣列名 = new 資料型別[行數][列數]; 複製程式碼
-
靜態初始化
資料型別[][] 陣列名 = new 資料型別[[]{{值1,值2},{值1,值2,值3...},{值1...}}; 複製程式碼
-
-
遍歷二維陣列
package com.shxt.demo01; public class ArrayDemo11 { public static void main(String[] args) { int[][] data = new int[][]{{1,2,3},{10},{100,200}}; for (int i = 0; i < data.length; i++) { //迴圈行數 for (int j = 0; j < data[i].length; j++) { //迴圈列數 System.out.print(data[i][j]+"\t"); } System.out.println(); } } } 複製程式碼
4.Java新特性對陣列的支援
(1) 可變引數
在呼叫一個方式,必須根據方法的定義傳遞指定的引數,但是在JDK1.5之後產生了新的概念--可變引數(即方法中可以接收的引數不再是固定的,而是隨著需要傳遞的)
a.可變引數的定義格式
返回值型別 方法名稱(資料型別... 引數名稱)
複製程式碼
方法中傳遞可變引數之後, 實際上引數是以 陣列 的形式儲存下來的,關鍵點
b.使用可變引數定義的方法
package com.shxt.demo02;
public class TestVarArgus {
public static void main(String[] args) {
System.out.println("不傳遞引數 fun():");
fun(); //不傳遞引數
System.out.println("傳遞1個引數 fun(100) :");
fun(100); //傳遞一個引數
System.out.println("\n傳遞2個引數 fun(10,20,30,40,50) :");
fun(10,20,30,40,50); //傳遞5個引數
}
public static void fun(int... params){ //可變引數可以接收任意多個引數
for (int i = 0; i < params.length; i++) {
System.out.print(params[i]+"\t"); // 實際上引數是以 陣列 的形式儲存下來的
}
}
}
複製程式碼
程式碼分析:
通過main方法裡的呼叫,可以看出來這個可變引數既可以是沒有引數(空引數),也可以是不定長的。看到這裡估計都能明白,這個不定長的引數其實和陣列引數挺像的。事實上,也確實是這麼回事兒。編譯器會在悄悄地把這最後一個形參轉化為一個陣列形參,並在編譯出的class檔案裡作上一個記號,表明這是個實參個數可變的方法。請看程式碼:
fun();//fun(int[] intArray{}); fun(100);//fun(int[] intArray{100}); fun(10,20,30,40,50);//fun(int[] intArray{10,20,30,40,50}); 複製程式碼
c.發現問題
問題1:看看是不是這個可變引數就是陣列類引數?
問題2:可變引數能否接收陣列呢?
package com.shxt.demo02;
public class TestVarArgus {
public static void main(String[] args) {
int[] intArray = { 1, 2, 3 };
fun(intArray); //傳遞陣列,編譯通過,正常執行
}
public static void fun(int... params){ //可變引數可以接收任意多個引數
for (int i = 0; i < params.length; i++) {
System.out.print(params[i]+"\t");
}
}
}
複製程式碼
錯誤的示例程式碼
程式碼分析:
通過這兩端程式碼可以看出來,[重點知識]可變引數是相容陣列類引數的,但是陣列類引數卻無法相容可變引數!
問題3:可變引數可以放置在形參中的任意位置嗎?
程式碼分析:
可變引數型別必須作為引數列表的最後一項,而不能放在定長引數的前面。
問題4:過載方法的優先順序問題?
package com.shxt.demo02;
public class TestVarArgus {
public static void fun(int... intArray) {
System.out.println("11111");
}
public static void fun(int num1 , int num2) {
System.out.println("22222");
}
public static void main(String args[]) {
fun(100,200);
}
}
複製程式碼
程式碼分析:
控制檯的資料結果為: 22222
這裡需要記住:能匹配定長的方法,那麼優先匹配該方法。含有不定引數的那個過載方法是最後被選中的。
留在最後的一句話: main方法的引數就是一個陣列型別的,那麼它其實也是可以改成不定引數型別
複製程式碼
d.可變引數的總結
- 只能出現在引數列表的最後;
- ... 位於變數型別和變數名之間,前後有無空格都可以;
- 呼叫可變引數的方法時,編譯器為該可變引數隱含建立一個陣列,在方法體中以陣列的形式訪問可變引數。
- 如果一個是兩個方法是過載,一個是可變引數,一個是固定引數,然後我們呼叫方法如果故常長度的能滿足,那麼有優先呼叫固定長度的,
###(2) foreach輸出
陣列的輸出一遍都會使用for迴圈,但是在JDK1.5後為了方便陣列的輸出,提供了foreach的語法,格式如下
for(資料型別 變數名稱 : 陣列名稱){
//程式碼主體
}
複製程式碼
簡單示例程式碼
package com.shxt.demo02;
public class TestVarArgus {
public static void main(String[] args) {
System.out.println("不傳遞引數 fun():");
fun(); //不傳遞引數
System.out.println("傳遞1個引數 fun(100) :");
fun(100); //傳遞一個引數
System.out.println("\n傳遞2個引數 fun(10,20,30,40,50) :");
fun(10,20,30,40,50); //傳遞5個引數
}
public static void fun(int... params){ //可變引數可以接收任意多個引數
for (int num : params) {
System.out.print(num+"\t");
}
}
}
複製程式碼
擴充套件說明:
可以反編譯class檔案,我們會看到增強(加強)for迴圈的語法結構為:
public static void fun(int... params) { int[] var1 = params; int var2 = params.length; for(int var3 = 0; var3 < var2; ++var3) { int num = var1[var3]; System.out.print(num + "\t"); } } 複製程式碼