JavaSE基礎:陣列

胖先森發表於2018-01-27

陣列與方法

陣列按照使用可以分為一維陣列/二維陣列/多維陣列.

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~Z

    package 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:看看是不是這個可變引數就是陣列類引數?
JavaSE基礎:陣列
問題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");
        }
    }

}
複製程式碼

錯誤的示例程式碼

JavaSE基礎:陣列

程式碼分析:

通過這兩端程式碼可以看出來,[重點知識]可變引數是相容陣列類引數的,但是陣列類引數卻無法相容可變引數!

問題3:可變引數可以放置在形參中的任意位置嗎?

JavaSE基礎:陣列

程式碼分析:

可變引數型別必須作為引數列表的最後一項,而不能放在定長引數的前面。

問題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");
  }

}
複製程式碼

相關文章