欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于Java?SE數(shù)組的深入理解

 更新時(shí)間:2022年09月27日 09:28:27   作者:程序猿教你打籃球  
數(shù)組是相同類型數(shù)據(jù)的有序集合,數(shù)組描述的是相同類型的若干個(gè)數(shù)據(jù),按照一定的先后次序排列組合而成,下面這篇文章主要給大家介紹了關(guān)于Java?SE數(shù)組的深入理解,需要的朋友可以參考下

1、數(shù)組的基本概念

1.1 我們?yōu)槭裁葱枰獢?shù)組?

假設(shè)說我們要存每個(gè)同學(xué)的期末考試總成績(jī),如果我們還不知道數(shù)組的話,那我們是不是得新建100個(gè)變量,而且賦值和打印也相當(dāng)?shù)穆闊?nbsp;而且我們發(fā)現(xiàn)成績(jī)的數(shù)據(jù)類型都是一樣的,所以就會(huì)有數(shù)組這個(gè)概念,數(shù)組即是相同類型元素的集合,而且是一塊連續(xù)的存儲(chǔ)空間,每個(gè)空間都有編號(hào),也就是我們口中常說的數(shù)組下標(biāo)。而且使用數(shù)組,也可以是代碼變得更簡(jiǎn)化,方便的進(jìn)行排序查找等,現(xiàn)在,我們就來進(jìn)入數(shù)組的學(xué)習(xí)把:

1.2 數(shù)組的創(chuàng)建與初始化

我們這期是由淺到深講解的,所以在前邊有一些不理解的問題,請(qǐng)堅(jiān)持往后看,會(huì)得到解決的。

在Java中對(duì)數(shù)組的創(chuàng)建并初始化有兩種方式,分別是靜態(tài)初始化和動(dòng)態(tài)初始化:

public static void arrayInit() {
        int[] array1 = { 1,2,3,4,5,6,7,8,9,10 }; //靜態(tài)初始化
        int[] array2 = new int[] { 1,2,3,4,5,6,7,8,9,10 }; //靜態(tài)初始化
    }

這兩種寫法有什么不同呢?第一種雖然省去了 new int[ ],但是在編譯的時(shí)候還是會(huì)還原成第二種方式,這兩種寫法本質(zhì)上沒有區(qū)別,都是在JVM棧上開辟一個(gè) array1和array2元素,同時(shí)也會(huì)在堆上開辟兩個(gè)一維數(shù)組,這兩個(gè)變量分別存這這兩個(gè)數(shù)組的地址,當(dāng)然,這里你不懂沒關(guān)系,后面我們也會(huì)畫圖一一講解到,你只需要知道,這兩種定義并初始化的方式只是寫法上的不同就可以了!

那定義了數(shù)組但是不初始化呢?

public static void arrayInit() {
        int[] array3 = new int[10]; //動(dòng)態(tài)初始化
        int[] array4 = null;
    }

如果是上面這種創(chuàng)建但是不初始化,array3 里面會(huì)默認(rèn)初始化成0,也就是說,如果數(shù)組中存儲(chǔ)的元素為基本類型,默認(rèn)值為基本類型對(duì)對(duì)應(yīng)的默認(rèn)值0,像 array4 賦值成 null 這種情況,就可以理解成這個(gè)數(shù)組沒有引用任何對(duì)象,這個(gè)地方聽不懂沒關(guān)系,往后看就能懂了。

類型默認(rèn)值
byte

0

short0
int0
long0L
float0.0f
double0.0
char/u0000
booleanfalse

不知道學(xué)過C語(yǔ)言的小伙伴還記不記得,C語(yǔ)言數(shù)組是可以不完全初始化的,比如說你一個(gè)數(shù)組5個(gè)元素,你只初始化前三個(gè)元素,在C語(yǔ)言中后續(xù)未初始化的元素會(huì)默認(rèn)補(bǔ)0,但是在Java中你就算完全初始化了,如果你指定了元素個(gè)數(shù)的話,也會(huì)報(bào)錯(cuò),只有在使用 new int[10],動(dòng)態(tài)初始化的時(shí)候才能寫明數(shù)組元素個(gè)數(shù),你們也可以下來自己試試。

在Java的數(shù)組中,我們有幾點(diǎn)需要注意:

  • 數(shù)組 { } 里面的元素類型一定要跟 [ ] 前面的類型保持一致
  • 靜態(tài)初始化的時(shí)候不能指定長(zhǎng)度,動(dòng)態(tài)初始化的時(shí)候 new int[10]需要指定長(zhǎng)度 
  • 雖然沒有指定數(shù)組長(zhǎng)度,但是編譯器在編譯的時(shí)候會(huì)根據(jù) { } 里面的元素個(gè)數(shù)來確定數(shù)組的長(zhǎng)度
  • 雖然Java數(shù)組可以寫成跟C語(yǔ)言一樣的寫法 int array[ ],但不推薦,因?yàn)檫@樣語(yǔ)義不明確!
  • new int[n] ,[ ]中可以是變量

這里有小伙伴就有個(gè)小問題了,如果我定義了但是沒有初始化,我能不能在下面重新賦值呢?

public static void arrayInit() {
        int[] array3;
        array3 = { 1,2,3,4,5 };
    }

這樣是絕對(duì)不可以的,雖然你現(xiàn)在可能不是很理解,但我們前面有提過,數(shù)組變量 array3 里面放的是地址,這個(gè)在下面我們會(huì)細(xì)講。這里你知道即可。

那如何正確的在定義之后初始化呢?或者重新賦值呢?

public static void arrayInit() {
        int[] array1;
        array1 = new int[10];
        
        int[] array2;
        array2 = new int[]{ 1,2,3,4,5 };   
    }

像如上代碼這樣是ok的,本質(zhì)上其實(shí)就是在堆區(qū)創(chuàng)建了一個(gè)新對(duì)象,這個(gè)我們還是在后面細(xì)講,這里讓你們先見一見,為后面細(xì)節(jié)學(xué)習(xí)作鋪墊。

1.3 數(shù)組的使用

數(shù)組是定義好了,我們?nèi)绾稳ナ褂盟??在前面我們提到過,數(shù)組是一塊連續(xù)的內(nèi)存空間,都有對(duì)應(yīng)的編號(hào),也就是下標(biāo),我們就可以通過下標(biāo)的方式快速訪問數(shù)組的任意位置的元素:

public static void main(String[] args) {
 
        int[] array = { 1,2,3,4,5 };
        array[2] = 88;
        System.out.println(array[2]);
    }

同時(shí)也可以對(duì)下標(biāo)的值進(jìn)行修改,但是這里我們要注意幾點(diǎn),數(shù)組的下標(biāo)是從 0 開始的,所以最后一個(gè)元素下標(biāo)應(yīng)該是 n-1,也就是Java中大部分采用的都是左閉右開的,即:[ 0,n )

如果我們下標(biāo)越界訪問了,不用擔(dān)心,程序會(huì)直接剖出下標(biāo)越界異常,我們根據(jù)報(bào)錯(cuò)提示去找對(duì)應(yīng)的位置即可。

1.4 數(shù)組的遍歷 

在Java中對(duì)數(shù)組其實(shí)有三種遍歷打印的方式,每一種的情況都會(huì)講明優(yōu)缺點(diǎn),接著往下看:

for 循環(huán)打印:

public class TestDemo {
    public static void main(String[] args) {
        int[] array = { 1,2,3,4,5 };
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }
}

這種方式是很常規(guī)的通過下標(biāo)遍歷訪問的方式,對(duì)于數(shù)組的長(zhǎng)度我們可以通過,數(shù)組對(duì)象.length 來獲取數(shù)組的長(zhǎng)度。

for-each 循環(huán)打印:

public class TestDemo {
    public static void main(String[] args) {
        int[] array = { 1,2,3,4,5 };
        for (int a : array) {
            System.out.print(a + " ");
        }
        System.out.println();
    }
}

這種打印方式呢,在 for 循環(huán)里冒號(hào)的左邊必須是你要打印的數(shù)組里元素的類型定義的變量,右邊則是你要打印數(shù)組的數(shù)組名,下面就可以通過你定義的變量進(jìn)行打印了。for-each是for循環(huán)的另一種使用方式,他能在代碼上更簡(jiǎn)潔,也可以避免循環(huán)條件和更新語(yǔ)句的書寫錯(cuò)誤,但是這樣也有缺陷,比如說這種方式并不能拿到數(shù)組的下標(biāo)。

Arrays工具類打印

public class TestDemo {
    public static void main(String[] args) {
        int[] array = { 1,2,3,4,5 };
        String ret = Arrays.toString(array); //既然返回的是字符串,我們就用字符串類型來接收
        System.out.println(ret);
        System.out.println(Arrays.toString(array)); //既然有返回值,那我們也可以直接鏈?zhǔn)皆L問
    }
}

首先我們要介紹下Arrays,他是在 java.util 包下的一個(gè)工具類,里面定義了很多對(duì)數(shù)組的操作方法,而 Arrays.toString 他的作用是把數(shù)組轉(zhuǎn)換成字符串并返回,所以嚴(yán)格意義上它并不是遍歷數(shù)組,只是把數(shù)組轉(zhuǎn)化成對(duì)應(yīng)的字符串而已。

以上三種方式各有優(yōu)缺點(diǎn),初學(xué)者結(jié)合實(shí)際情況作應(yīng)用

2、引用類型數(shù)組的深入講解

2.1 簡(jiǎn)單了解 JVM 的內(nèi)存分布

Java的程序需要運(yùn)行在虛擬機(jī)上的,如果對(duì)于內(nèi)存中的數(shù)據(jù)隨意存儲(chǔ)的話,那以后對(duì)內(nèi)存管理起來將會(huì)是很麻煩的一件事,所以JVM也對(duì)所使用的內(nèi)存按照不同的功能進(jìn)行了劃分:

但是我們今天只重點(diǎn)關(guān)心堆和虛擬機(jī)棧這兩塊空間,在后續(xù)學(xué)習(xí)中會(huì)依次詳細(xì)介紹這里面的內(nèi)容:

虛擬機(jī)棧:與方法調(diào)用相關(guān)的一些信息,每個(gè)方法在執(zhí)行的時(shí)候都會(huì)先創(chuàng)建一個(gè)棧幀,棧幀中包含:局部變量,操作數(shù)棧,動(dòng)態(tài)鏈接,返回地址,以及一些其他的信息,保存的都是與方法執(zhí)行相關(guān)的一些信息,比如:局部變量,當(dāng)方法運(yùn)行結(jié)束了后,棧幀也被銷毀,即棧幀中保存的數(shù)據(jù)也被銷毀了

堆:它是JVM管理的最大內(nèi)存區(qū)域,使用 new 創(chuàng)建的對(duì)象都是在堆上保存的,堆是隨著程序的開始而創(chuàng)建,隨著程序的退出而銷毀,堆中的數(shù)據(jù)只要還有在使用,就不會(huì)被銷毀。

2.2 基本類型變量與引用類型變量的區(qū)別

對(duì)這個(gè)理解特別重要,很關(guān)系到你后面進(jìn)行學(xué)習(xí),首先我們要區(qū)別這個(gè)兩個(gè)的區(qū)別,先說基本類型變量,這種變量中直接存放的是所對(duì)應(yīng)的值,而引用類型創(chuàng)建的變量,一般稱為對(duì)象的引用,這種變量里存儲(chǔ)的是對(duì)象所在空間的地址,下面我們用一小段代碼,并且畫圖讓大家理解的更清楚:

public class TestDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int[] array = { 1,2,3,4,5 };
    }
}

其實(shí)看到這張圖,相信大家就能很好的理解了,其實(shí)我們引用變量并不是存儲(chǔ)了對(duì)象本身,只是存儲(chǔ)了對(duì)象的其實(shí)地址,那我們的 array 只是存儲(chǔ)了在堆中開辟的一維數(shù)組的地址!并沒有把整個(gè)數(shù)組都保存在變量中!通過該對(duì)象的地址,引用變量就可以去操作這個(gè)對(duì)象了!

2.3 通過方法更深刻理解引用變量

有了上面的認(rèn)識(shí),我們就要來理解下面這兩個(gè)方法的作用了,相信你看完會(huì)有更深刻的認(rèn)識(shí):

是不是結(jié)果可能跟你想得有點(diǎn)不一樣呢?不用擔(dān)心,我們來一個(gè)個(gè)分析下:

首先我們執(zhí)行的是 func1 我們知道 array 變量中存的是一個(gè)對(duì)象的地址,那么通過傳參給 func1 的 arr1,首先要建立棧幀,把 array 存的地址拷貝到 arr1 當(dāng)中,這樣一來就相當(dāng)于 arr1 也指向了那個(gè)變量,但是我們又 new 了一個(gè)對(duì)象,并把新對(duì)象的地址賦值給了 arr1,相當(dāng)于 arr1  原來存放的地址已經(jīng)被替換了,也就說 arr1 指向了一個(gè)新的對(duì)象,因?yàn)橹皇前?array 存的地址拷貝給了 arr1 所以執(zhí)行完 func1 這個(gè)方法之后,array 并不會(huì)受任何影響,當(dāng)方法結(jié)束,arr2 變量銷毀,因?yàn)閍rr2 銷毀之后沒有變量接著引用在 func1 中 new 的新對(duì)象,所以此時(shí)新的對(duì)象就被 JVM 回收了!

當(dāng)我們執(zhí)行完 func1 時(shí),就是我們說的結(jié)果,所以 array 的值不受任何影響!

我們接著再來看執(zhí)行 func2 之后的結(jié)果,首先前半部分與 func1 一樣,都是傳遞的 array 指向?qū)ο蟮牡刂?,但?func2 里面語(yǔ)句是直接對(duì) arr2 中對(duì)象的地址進(jìn)行下標(biāo)訪問,修改了 [1] 下標(biāo)處的值,因?yàn)楸举|(zhì) array 和 arr2 引用的都是同一個(gè)對(duì)象,當(dāng) arr2 修改了對(duì)象的值,所以當(dāng)函數(shù)結(jié)束后接著打印 array 指向?qū)ο蟮闹悼隙ㄒ脖恍薷牧?!方法結(jié)束,arr2 被銷毀,但是 arr2 指向的對(duì)象仍然被 array 指向著,所以JVM不會(huì)回收此時(shí)的對(duì)象!

看到這,你肯定有了更深刻的理解,前面有疑問的地方肯定得到了解決,所謂的 "引用" 本質(zhì)上只是存了一個(gè)地址,Java將數(shù)組設(shè)定成引用類型,這樣后續(xù)進(jìn)行數(shù)組傳參,其實(shí)只是將數(shù)組的地址傳入到形參當(dāng)中,這樣就可以避免對(duì)整個(gè)數(shù)組的拷貝!

在我們目前認(rèn)識(shí)中,如果對(duì)象沒有被引用,則會(huì)自動(dòng)回收,所以不用考慮內(nèi)存泄漏的問題 

2.4 數(shù)組作為函數(shù)返回值

假設(shè)這里我們有一個(gè)題,需要實(shí)現(xiàn)一個(gè)方法,這個(gè)方法需要獲取斐波那契數(shù)列的前 n 項(xiàng),需要返回一個(gè)數(shù)組回來,本質(zhì)其實(shí)就是返回?cái)?shù)組的地址,如何實(shí)現(xiàn)呢?

public static int[] fib(int n) {
        if (n <= 0) {
            return null;
        }
        int[] array = new int[n];
        array[0] = array[1] = 1;
        for (int i = 2; i < n; i++) {
            array[i] = array[i - 1] + array[i - 2];
        }
        return array;
    }
    public static void main(String[] args) {
        int[] array = fib(8);
        System.out.println(Arrays.toString(array));
    }

當(dāng)然這個(gè)方法如果 n 為1 就會(huì)越界,這個(gè)下來可以自己優(yōu)化下,來到這里我們就來介紹下Arrays這個(gè)工具類里面的一些方法了: 像一些將數(shù)組轉(zhuǎn)換成字符串,數(shù)組二分查找,數(shù)組排序等等,可以下來查閱下幫助手冊(cè),這里我就不細(xì)說了,交給大家自己去擴(kuò)展了,如果以后用到,我會(huì)進(jìn)行說明。

3、二維數(shù)組

3.1 二維數(shù)組的概念和內(nèi)存布局 

這里我們一定要有一個(gè)概念,二維數(shù)組是一個(gè)特殊的一維數(shù)組,如何理解呢?用文字來說,二維數(shù)組的每個(gè)元素是一維數(shù)組,也就是說,二維數(shù)組的每個(gè)元素里面放的是一維數(shù)組的地址!

相信聽完上面的話,大家可能不是很理解,那我們就定義一個(gè)二維數(shù)組,并畫圖:

public static void main(String[] args) {
        int[][] array = { {1,2,3}, {4,5,6} };
    }

這里就很清晰明了了,圖中也能看到,二維數(shù)組本質(zhì)就是一個(gè)一維數(shù)組,只不過這個(gè)一維數(shù)組的每個(gè)元素存的是地址而已!

3.2 二維數(shù)組的定義和初始化 

 當(dāng)然,二維數(shù)組和一維數(shù)組一樣,同樣的三種定義方式:

int[][] array1 = { {1,2,3}, {4,5,6} }; //兩行三列的二維數(shù)組
int[][] array2 = new int[][]{ {1,2,3}, {4,5,6} };
int[][] array3 = new int[2][3];

如果只是單純的 int[][] array; 這樣數(shù)組里面沒有任何引用對(duì)象,并不能直接使用未引用對(duì)象的數(shù)組,如果不引用最好置null

3.3 二維數(shù)組遍歷

for 循環(huán)打印:

public class TestDemo {
    public static void main(String[] args) {
        int[][] array1 = { {1,2,3}, {4,5,6} }; //兩行三列的二維數(shù)組
        for (int i = 0; i < array1.length; i++) {
            for (int j = 0; j < array1[i].length; j++) {
                System.out.print(array1[i][j] + " ");
            }
            System.out.println();
        }
        System.out.println();
    }
}

這里第一個(gè) for 里面的長(zhǎng)度求的是 array1.length,因?yàn)樗旧砭褪且粋€(gè)特殊一維數(shù)組,這樣求出的就是它的行,第二個(gè)for array1[i].length,自然求得就是每一行一維數(shù)組長(zhǎng)度了

for-each 循環(huán)打?。?/strong>

public class TestDemo {
    public static void main(String[] args) {
        int[][] array1 = { {1,2,3}, {4,5,6} }; //兩行三列的二維數(shù)組
        for (int[] arr : array1) { //二維數(shù)組的每個(gè)元素是一維數(shù)組,所以每個(gè)元素的類型是int[]
            for (int a : arr) { //arr是一維數(shù)組,每個(gè)數(shù)組的元素的int
                System.out.print(a + " ");
            }
            System.out.println();
        }
    }
}

Arrays 工具類有個(gè)方法也可以打印二維數(shù)組,是Arrays.deepToString,這個(gè)方法也是打印二維數(shù)組的但只能在一行顯示,感興趣的可以下來自己實(shí)驗(yàn)下。

3.4 不規(guī)則的二維數(shù)組

在Java中,二維數(shù)組的列可以省略,也就是把二維數(shù)組看成一個(gè)特殊的一維數(shù)組的每個(gè)元素指向的一維數(shù)組是可以元素個(gè)數(shù)不同的,如何理解這句話呢?我們還是一樣通過一小段并且以畫圖的形式給大家講解:

int[][] array = new int[2][];
array[0] = new int[3];
array[1] = new int[2];

當(dāng)然,他的遍歷方法是跟普通二維數(shù)組一樣的, 這里我就不多說,自己摸索,實(shí)在不懂可以問下博主。

總結(jié)

到此這篇關(guān)于關(guān)于Java SE數(shù)組的文章就介紹到這了,更多相關(guān)Java SE數(shù)組理解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中正則表達(dá)式匹配過程實(shí)例詳解

    Java中正則表達(dá)式匹配過程實(shí)例詳解

    正則匹配即是在給定字符串中查找符合正則表達(dá)式的字符,下面這篇文章主要給大家介紹了關(guān)于Java中正則表達(dá)式匹配過程的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-10-10
  • java中生成任意之間數(shù)的隨機(jī)數(shù)詳解

    java中生成任意之間數(shù)的隨機(jī)數(shù)詳解

    這篇文章主要介紹了java中生成任意之間數(shù)的隨機(jī)數(shù)詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • Java編程實(shí)現(xiàn)驗(yàn)證哥德巴赫猜想

    Java編程實(shí)現(xiàn)驗(yàn)證哥德巴赫猜想

    這篇文章主要介紹了Java編程實(shí)現(xiàn)驗(yàn)證哥德巴赫猜想,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-12-12
  • 案例講解SpringBoot?Starter的使用教程

    案例講解SpringBoot?Starter的使用教程

    SpringBoot中的starter是一種非常重要的機(jī)制,能夠拋棄以前繁雜的配置,將其統(tǒng)一集成進(jìn)starter,應(yīng)用者只需要在maven中引入starter依賴,SpringBoot就能自動(dòng)掃描到要加載的信息并啟動(dòng)相應(yīng)的默認(rèn)配置,本文通過案例講解SpringBoot?Starter的使用,感興趣的朋友一起看看吧
    2023-12-12
  • 對(duì)Jpa中Entity關(guān)系映射中mappedBy的全面理解

    對(duì)Jpa中Entity關(guān)系映射中mappedBy的全面理解

    這篇文章主要介紹了對(duì)Jpa中Entity關(guān)系映射中mappedBy的全面理解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 解決mybatis一對(duì)多查詢r(jià)esultMap只返回了一條記錄問題

    解決mybatis一對(duì)多查詢r(jià)esultMap只返回了一條記錄問題

    小編接到領(lǐng)導(dǎo)一個(gè)任務(wù)需求,需要用到使用resultMap相關(guān)知識(shí),在這小編記錄下這個(gè)問題的解決方法,對(duì)mybatis一對(duì)多查詢r(jià)esultMap項(xiàng)目知識(shí)感興趣的朋友一起看看吧
    2021-11-11
  • Java單例模式實(shí)現(xiàn)的幾種方式

    Java單例模式實(shí)現(xiàn)的幾種方式

    這篇文章主要介紹了Java單例模式實(shí)現(xiàn)的幾種方式的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • SpringBoot中的@Configuration注解詳解

    SpringBoot中的@Configuration注解詳解

    這篇文章主要介紹了SpringBoot中的@Configuration注解詳解,Spring Boot推薦使用JAVA配置來完全代替XML 配置,JAVA配置就是通過 @Configuration和 @Bean兩個(gè)注解實(shí)現(xiàn)的,需要的朋友可以參考下
    2023-08-08
  • MyBatis與Spring整合過程實(shí)例解析

    MyBatis與Spring整合過程實(shí)例解析

    這篇文章主要介紹了MyBatis與Spring整合過程實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • java設(shè)計(jì)模式--策略模式詳解

    java設(shè)計(jì)模式--策略模式詳解

    這篇文章主要介紹了Java經(jīng)典設(shè)計(jì)模式之策略模式,簡(jiǎn)單說明了策略模式的概念、原理并結(jié)合實(shí)例形式分析了java策略模式的具有用法與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2021-07-07

最新評(píng)論