溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析

發(fā)布時(shí)間:2022-03-28 12:47:44 來源:億速云 閱讀:291 作者:小新 欄目:編程語(yǔ)言

這篇文章主要介紹JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

首先明確的一點(diǎn)就是在java中只有值傳遞!只有值傳遞!理論依據(jù)來自《think in java》。接下來就是具體說明為何java只有值傳遞。
因?yàn)閖ava中有基本類型和引用類型兩種數(shù)據(jù)類型,再加上String這個(gè)特殊的類型,所以主要從三個(gè)方面就行解釋。

1. 基本數(shù)據(jù)類型

先看代碼

public class Demo01 {
    
    public void change(int a) {
        System.out.println("副本a 的初始值" + a);
        a = 20;
        System.out.println("副本a 的新值值" + a);
    }

    public static void main(String[] args) {
        int a = 10;
        Demo01 d = new Demo01();
        d.change(a);
        System.out.println("change方法執(zhí)行后的值" + a);
    }
}

分析:

在java中基本數(shù)據(jù)類型遵循值傳遞,所以對(duì)象d在調(diào)用change()方法時(shí),只是將原數(shù)據(jù)a的副本傳給方法中的參數(shù),第一時(shí)間原本和副本a的值都是10,在執(zhí)行到a=20后,副本a的值變成了20。

所以運(yùn)行結(jié)果為:

JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析

原理參考下圖

JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析

2. 引用數(shù)據(jù)類型

先看代碼

public class Demo02 {

    char[] ch = {'a', 'b', 'c'};

    public void change(char ch[]) {
        System.out.println("方法中ch[0]的初始值:" + ch[0]);
        ch[0] = 'g';
        System.out.println("方法中ch[0]執(zhí)行后的新值:" + ch[0]);
    }

    public static void main(String[] args) {
        Demo02 d = new Demo02();
        System.out.println("對(duì)象d中數(shù)組的初始值是:"+d.ch);
        d.change(d.ch);
        System.out.println("對(duì)象d中數(shù)組的最終值是:"+d.ch);
    }
}

分析:

在引用類型作為參數(shù)進(jìn)行傳遞時(shí),也屬于值傳遞,此時(shí)傳遞的是地址值副本,但是這兩個(gè)地址指向同一個(gè)地方。在副本地址沒有進(jìn)行更改指向時(shí),對(duì)副本地址指向的數(shù)據(jù)進(jìn)行操作會(huì)影響到原始數(shù)據(jù)的值。方法中ch[] 數(shù)組和原始ch[]數(shù)組指向同一個(gè)數(shù)據(jù),所以初始階段ch[0]都指向’a’;接著對(duì)副本中的ch[0]進(jìn)行新的賦值變?yōu)椤甮’。
所以運(yùn)行結(jié)果為:

JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析

原理參考下圖

JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析

3. 字符串的參數(shù)傳遞

先看代碼

public class Demo03 {
    public void change(String str2) {
        System.out.println("方法中str2初始值" + str2);
        System.out.println("方法中str2初始hashcode值" + str2.hashCode());
        str2 = "bbb";
        System.out.println("方法中str2賦值后:" + str2);
        System.out.println("方法中str2賦值后hashcode值:" + str2.hashCode());
    }

    public static void main(String[] args) {
        String str1 = new String("aaa");
        System.out.println("原始字符串str1的hashcode值:" + str1.hashCode());
        Demo03 d = new Demo03();
        d.change(str1);
        System.out.println("方法調(diào)用后str1的值" + str1);
    }
}

分析:

字符串是一個(gè)特殊的數(shù)據(jù)類型,它的底層是一個(gè)final 型的char[]數(shù)組,屬于無法更改,所以字符串在作為參數(shù)傳遞時(shí),可以當(dāng)做一個(gè)特殊的數(shù)組進(jìn)行操作,同樣的它也是將復(fù)制一份原本的對(duì)象引用給了副本,此時(shí)副本對(duì)象的引用和原本對(duì)象的引用都指向原始字符串的位置,也就是str2在剛開始初始化時(shí)它指向的地址和原對(duì)象str1指向的位置一致,即str2的初始hashcode值和原對(duì)象str1的hashcode值一樣,str2經(jīng)過str2=“bbb”操作后,由于字符串的不可變性,此時(shí)str2會(huì)指向一個(gè)新的對(duì)象引用,即此時(shí)str2指向“bbb”的位置。str2的hashcode值會(huì)變化,但是原本str1它的對(duì)象引用沒有發(fā)生改變,并且“aaa”也未發(fā)生改變,所以str1仍然指向”aaa”。運(yùn)行結(jié)果如下:

JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析

接下來看一個(gè)更具體的字符串例子:

public class Demo04 {

    public static void main(String[] args) {
        StringBuffer s = new StringBuffer("hello");
        StringBuffer s2 = new StringBuffer("hi");
        test(s, s2);
        System.out.println("方法調(diào)用后s的值:" + s);
        System.out.println("方法調(diào)用后s2的值:" + s2);
    }

    static void test(StringBuffer s3, StringBuffer s4) {
        System.out.println("方法初始化時(shí)s3的值" + s3);
        System.out.println("方法初始化時(shí)s4的值" + s4);
        s4 = s3;
        s3 = new StringBuffer("new");
        System.out.println("第一步變化后s3的值" + s3);
        System.out.println("第一步變化后s4的值" + s4);
        s3.append("boy");
        s4.append("gril");
        System.out.println("第二步變化后s3的值" + s3);
        System.out.println("第二步變化后s4的值" + s4);

    }
}

這次先看結(jié)果:
JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析

然后進(jìn)行分析:

在未執(zhí)行方法之前,字符串s1和s2指向的位置分別是“hello”和“hi”,這個(gè)毋容置疑,

(1)接著進(jìn)入方法內(nèi)部,方法中參數(shù)s3和s4初始化時(shí)和上面例子相同,此時(shí)它們和s1s2指向同一個(gè)位置,或者說s1s2將對(duì)象引用副本給了s3s4,此時(shí)s3s4的值為“hello”和“hi”

(2)接著執(zhí)行s4=s3,這個(gè)操作就是將s3的對(duì)象引用給了s4,此時(shí)s4為“hello”;s3=new StringBuffer(”new”);這個(gè)操作要注意,此時(shí)相當(dāng)于給了s3一個(gè)新的對(duì)象引用,s3指向一個(gè)字符串為“new”的位置,所以此時(shí)s3=“new”,s4=“hello”

(3)然后s3.append(“boy”);s4.append(“gril”);在StringBuffer中的append方法要注意,它的操作不會(huì)為s3s4指向一個(gè)新的對(duì)象引用,是在原來的基礎(chǔ)上進(jìn)行操作,因此操作完之后s3=“newboy”,s4=“hellogril”

(4)此時(shí)方法調(diào)用完,回頭捋一下s3s4在此過程中的對(duì)s1s2的影響。
——- A . 首先是s3和s1一樣剛開始指向“hello”,接著給s3創(chuàng)建一個(gè)新的對(duì)象引用“new”,此時(shí)s3和s1再無半毛錢關(guān)系,s3進(jìn)行append(boy)后,s3=“newboy”;
——– B . s4剛開始和s2都指向“hi”,接著s3將自己初始值(也就是s1的副本)給了s4,此時(shí)s4指向“hello”(這會(huì)s4和s1有了關(guān)系),s4執(zhí)行append(grill)操作,因?yàn)樗蛃1指向相同位置,所以它們的共同指向的對(duì)象會(huì)變化,s4=s1=“hellogrill”。
——- C .然后就清楚了,s2指向的對(duì)象“hi”并未變化,s1指向的“hello”在append(“grill”)操作下變成了“hellogril”。

4. 總結(jié)

  • 當(dāng)使用基本數(shù)據(jù)類型作為方法的形參時(shí),在方法體中對(duì)形參的修改不會(huì)影響到實(shí)參的數(shù)值

  • 當(dāng)使用引用數(shù)據(jù)類型作為方法的形參時(shí),若在方法體中修改形參指向的數(shù)據(jù)內(nèi)容,會(huì)對(duì)實(shí)參變量的數(shù)值產(chǎn)生影響,因?yàn)樾螀⒆兞亢蛯?shí)參變量共享同一塊堆區(qū);

  • 當(dāng)使用引用數(shù)據(jù)類型作為方法的形參時(shí),若在方法體中改變了形參變量的指向,此時(shí)不會(huì)對(duì)實(shí)參變量的數(shù)值產(chǎn)生影響,因此形參變量和實(shí)參變量分別指向不同的堆區(qū);最后一個(gè)例子就是最形象的解釋。

  • 關(guān)于字符串做參數(shù),也是看它的參數(shù)變量指向是否發(fā)生了變化,因?yàn)镾tring的底層為final類型的char[]原因,當(dāng)你在String s = “aaa”還是String s = new String(“aaa”)時(shí),都會(huì)為s創(chuàng)建一個(gè)新的對(duì)象引用。但是調(diào)用了append()方法時(shí),是不會(huì)指向新的對(duì)象,會(huì)在原來的指向的對(duì)象上發(fā)生改變,與它共享的對(duì)象引用也會(huì)發(fā)生變化。

  • 最后重復(fù)的是java中沒有引用傳遞,只有值傳遞,引用類型屬于特殊值傳遞(是將它的地址副本給了參數(shù),但是它與基本數(shù)據(jù)類型不同,如果地址指向的對(duì)象發(fā)生了變化,因?yàn)楣蚕碓?,原始?duì)象也會(huì)改變)。


以上是“JAVA中字符串和數(shù)組做參數(shù)傳遞的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI