Java入門part4——數組

數組

數組的定義

  • 數組:相同類型數據的集合 內存是連續的
  • 定義方法:
    (1) int[] arr={1,2,3,4}; 靜態初始化
    (2)int[] arr=new int[]{1,2,3,4}; 動態初始化
    這兩種定義的時候[]內是不能出現數組長度的
    === 》所以如果要知道數組長度 數組名.length求數組長度,其中 length不是方法 是一個屬性
    (3)int[] arr=new int[5]; 未初始化 只是產生了一段空間
    注意:
  • 數組名裏放的是數組首元素地址 ===》所以arr叫做引用(用來存放數組的地址)
  • 下標訪問操作不能超出有效範圍 [0, length - 1] , 如果超出有效範圍, 會出現下標越界異常java.lang.ArrayIndexOutOfBoundsException
  • 當定義好數組之後沒有初始化,數組當中如果是簡單類型默認值爲0 如果是引用類型那麼默認值就是null

數組的遍歷

  • for循環
for (int i = 0; i < arr.length; i++) {
    System.out.println(arr[i]);
}
  • foreach循環
for(表達式1(數組中的變量):表達式2(數組名)){   
	System.out.print(x+" ");
}   

例如

 for(int x : arr){
	System.out.print(x+" ");
 }    

數組作爲方法的參數

Java中數組的內存分析
public static void main(String[] args) {
    int num = 0;
    func(num);
    System.out.println("num = " + num);
}
public static void func(int x) {
    x = 10;
    System.out.println("x = " + x);
}
// 執行結果
x = 10
num = 0

在這裏插入圖片描述

==》形參的改變並不影響實參的值 此時是按值傳參

public static void main(String[] args) { 
	 int[] arr = {1, 2, 3}; 
	 func(arr); 
	 System.out.println("arr[0] = " + arr[0]); 
} 
public static void func(int[] a) { 
	 a[0] = 10; 
	 System.out.println("a[0] = " + a[0]); 
} 
// 執行結果
a[0] = 10 
arr[0] = 10

在這裏插入圖片描述
==》此處可發現在函數內部改變參數的值,函數外面也發生了改變
因爲此時的函數名arr是一個引用,此時傳參是按引用傳參
所謂的 “引用” 本質上只是存了一個地址. Java 將數組設定成引用類型, 這樣的話後續進行數組參數傳參, 其實只是將數組的地址傳入到函數形參中. 這樣可以避免對整個數組的拷貝(數組可能比較長, 那麼拷貝開銷就會很大).

Java中數組的存儲

Java中數組在堆上存儲而不在棧上

JVM區域劃分

在這裏插入圖片描述
在這裏插入圖片描述

  • Java虛擬機棧:存放局部變量

  • 本地方法棧:存放native方法 底層由C語言或C++實現 速度快

  • 程序計數器(PC register):存放下一條要執行的指令

  • 堆:放的是對象 通過new關鍵字new出來的

  • 方法區: 靜態變量 類的信息

  • 常量池:用來存放字符串常量 String str=“hello”;
    在JDK1.7之前 常量池在方法區當中
    在JDK1.7開始,被挪到堆當中

  • 每一個線程都有程序計數器 jvm虛擬機棧和本地方法棧
    null 是所有引用類型的初始值

  • 數組名.length 字符串名.length()
    點號之前如果是null 大概率情況下肯定會出現空指針異常
    空指針異常 java.lang.NullPointerException

  • System.out.println(Arrays.toString(array)); 將數組以字符串類型輸出 要導入包alt+enter

數組作爲方法的返回值

/** 將數組中每個元素都乘以2* */
public class com {
    public static int[] fun(int[] arr){
        for (int i = 0; i <4 ; i++) {  
            arr[i]=arr[i]*2;        
        } 
        return arr;
    }
    public static void main(String[] args) {
        int[] arr={1,2,3,4};
        int[] arr2=fun(arr);
        for (int x:arr2) {    
                System.out.print(x+" ");
        }
     }
 }

由於數組是引用類型, 返回的時候只是將這個數組的首地址返回給函數調用者, 沒有拷貝數組內容, 從而比較高效.

  • 可以通過javap -c進行反彙編

數組的應用

數組拷貝

int[] arr={2,3,4};
int[] arr2=new int[arr.length];
  1. 拷貝方式1
    arraycopy(Object src, int srcPos, Object dest, int destPos, int length) //將指定源數組中的數組從指定位置複製到目標數組的指定位置。 (原數組,從原數組第幾號下標開始拷,目標數組,放到目標數組第幾號下標,拷貝多長)
    需要new才能使用
  2. 拷貝方式2
    arr2=Arrays..copyOf(arr,arr.length);
    不需要new 深拷貝 深拷貝的定義見下
  3. 拷貝方式3
    利用for循環拷貝
  4. 拷貝方式4
    原數組名.clone() 用的較少
  • System.arraycopyArrays..copyOf的區別和聯繫
    查原碼發現
    System.arraycopy是被native底層使用C語言寫的 所以拷貝速度快
    Arrays..copyOf方法內部調用了 System.arraycopy()所以相較於System.arraycopy速度慢

以上四種拷貝方式對存放簡單類型的數組來講是深拷貝
對存放引用類型的數組來講是淺拷貝

  • 深拷貝和淺拷貝
    • 深拷貝
      修改原有變量不會改變新拷貝的變量
    • 淺拷貝
      如果是兩個引用同時指向一個對象 那麼通過一個引用修改當前對象的值後 那麼另一個引用也會受到影響 這種拷貝就叫做淺拷貝
  • 注意
    int[] arr={1,2,3};
    int[] arr2=arr; 這個不是拷貝

二維數組

   int[][] arr={{1,2},{3,4},{5,6}};
   int[][] arr=new int[][]{{1,2},{3,4},{5,6}};
   int[][] arr=new int[3][2];

不規則的二維數組

  int[][] arr=new int[3][];
  int[][] arr={{1},{3,4},{5,6}};
  • 打印二維數組除了遍歷還可以System.out.println(Arrays.toString(array));返回指定數組的內容的字符串表示形式將其打印

  • 不規則數組的打印如果用尋常遍歷方式會出現數組越界 所以應將條件改爲i<arr.length j<arr[i].length

Arrays工具類的使用

Arrays.equals(arr,arr2);//判斷兩數組是否相同
Arrays.fill(arr,9);//將arr中全部填充爲9
Arrays.fill(arr,2,6,9) ;//將arr中從下標2到5全部填充爲9
Arrays. sort(arr); //對數組中的元素排序,底層是用雙軸快速排序
Arrays.toString(arr);//返回指定數組的內容的字符串表示形式。
Arrays.deepToString(arr);//返回指定數組的“深度內容”的字符串表示形式。
Arrays.copyOfRange(int[] original, int from, int to);//將指定數組的指定範圍複製到新數組中。

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