中文字幕在线观看,亚洲а∨天堂久久精品9966,亚洲成a人片在线观看你懂的,亚洲av成人片无码网站,亚洲国产精品无码久久久五月天

Java:關(guān)于值傳遞你需要了解的事情

2018-07-02    來(lái)源:importnew

容器云強(qiáng)勢(shì)上線!快速搭建集群,上萬(wàn)Linux鏡像隨意使用

我們都知道,在Java中,方法的參數(shù)傳遞永遠(yuǎn)都是指值傳遞。讓我們來(lái)看一看基本類(lèi)型和集合的參數(shù)傳遞在內(nèi)存中是如何體現(xiàn)的。

原文鏈接:https://dzone.com/articles/java-pass-by-reference-or-pass-by-value

在討論Java中參數(shù)是如何傳遞之前,我們有必要先弄清楚Java的變量(主要指的是基本類(lèi)型和對(duì)象)是怎么存儲(chǔ)在內(nèi)存中的。
基本類(lèi)型一般都存儲(chǔ)在堆棧中;對(duì)于Java對(duì)象,實(shí)際的對(duì)象數(shù)據(jù)存儲(chǔ)在堆中,而對(duì)象的指針(指向推中的對(duì)象)存儲(chǔ)在堆棧中。

 

1.png

1.傳值 vs 傳引用

“傳值”和“傳引用”分別是什么意思:

  • 傳值:當(dāng)方法參數(shù)是值傳遞時(shí),意味著原參數(shù)的一個(gè)拷貝被傳到了參數(shù)內(nèi)部而不是原始參數(shù),所以任何對(duì)于該參數(shù)的改變都只會(huì)影響這個(gè)拷貝值。
  • 傳引用:當(dāng)方法參數(shù)是引用傳遞時(shí),意味著原始參數(shù)的引用或者說(shuō)指針被傳遞到了方法內(nèi)部,而不是這個(gè)原始參數(shù)的內(nèi)容。

2.在Java中參數(shù)是怎么傳遞的

在Java中,不管原始參數(shù)的類(lèi)型是什么,參數(shù)都是按值傳遞的。每次當(dāng)一個(gè)方法被執(zhí)行的時(shí)候,在堆棧中就會(huì)為每個(gè)參數(shù)創(chuàng)建一個(gè)拷貝,這個(gè)拷貝會(huì)被傳遞到方法內(nèi)部。

  • 如果原始參數(shù)是基本類(lèi)型,那么在堆棧中創(chuàng)建的便是這個(gè)參數(shù)的簡(jiǎn)單拷貝
  • 如果原始參數(shù)不是基本類(lèi)型,那么在堆棧中創(chuàng)建的便是指向真正對(duì)象數(shù)據(jù)的新的引用或指針。這個(gè)新的引用被傳遞到方法內(nèi)部(在這種情況下,有2個(gè)引用指向了同一個(gè)對(duì)象數(shù)據(jù))

3.解決疑惑

在接下來(lái)的示例中,我們通過(guò)往方法中傳遞不同類(lèi)型的參數(shù)(基本類(lèi)型,包裝類(lèi),集合類(lèi),自定義類(lèi)),在方法執(zhí)行完成后去檢查他們是否被修改了來(lái)嘗試證明“在Java中參數(shù)傳遞永遠(yuǎn)是值傳遞”。

基本類(lèi)型參數(shù)

public static void main(String[] args) {
    int x = 1;
    int y = 2;
    System.out.print("Values of x & y before primitive modification: ");
    System.out.println(" x = " + x + " ; y = " + y );
    modifyPrimitiveTypes(x,y);
    System.out.print("Values of x & y after primitive modification: ");
    System.out.println(" x = " + x + " ; y = " + y );
}
private static void modifyPrimitiveTypes(int x, int y)
{
    x = 5;
    y = 10;
}

輸出:

Values of x & y before primitive modification:  x = 1 ; y = 2
Values of x & y after primitive modification:  x = 1 ; y = 2

說(shuō)明:
x,y這2個(gè)參數(shù)是基本類(lèi)型,所以存儲(chǔ)在堆棧中。當(dāng)調(diào)用modifyPrimitiveTypes()方法時(shí),在堆棧中創(chuàng)建了這2個(gè)參數(shù)的拷貝(我們就叫它們w,z),實(shí)際上是w,z被傳遞到了方法中。所以原始的參數(shù)并沒(méi)有被傳遞到方法中,在方法中的任何修改都只作用于參數(shù)的拷貝w,z

2.png

 

包裝類(lèi)

public static void main(String[] args) {
    Integer obj1 = new Integer(1);
    Integer obj2 = new Integer(2);
    System.out.print("Values of obj1 & obj2 before wrapper modification: ");
    System.out.println("obj1 = " + obj1.intValue() + " ; obj2 = " + obj2.intValue());
    modifyWrappers(obj1, obj2);
    System.out.print("Values of obj1 & obj2 after wrapper modification: ");
    System.out.println("obj1 = " + obj1.intValue() + " ; obj2 = " + obj2.intValue());
}
private static void modifyWrappers(Integer x, Integer y)
{
    x = new Integer(5);
    y = new Integer(10);
}

輸出:

Values of obj1 & obj2 before wrapper modification: obj1 = 1 ; obj2 = 2
Values of obj1 & obj2 after wrapper modification: obj1 = 1 ; obj2 = 2

說(shuō)明:
包裝類(lèi)存儲(chǔ)在堆中,在堆棧中有一個(gè)指向它的引用
當(dāng)調(diào)用modifyWrappers()方法時(shí),在堆棧中為每個(gè)引用創(chuàng)建了一個(gè)拷貝,這些拷貝被傳遞到了方法里。任何在方法里面的修改都只是改變了引用的拷貝,而不是原始的引用

3.png

 

P.S: 如果方法中的表達(dá)式為x += 2,x值得改變也不會(huì)影響到方法外部,因?yàn)榘b類(lèi)是immutable類(lèi)型的。當(dāng)他們的state變化時(shí),他們就會(huì)創(chuàng)建一個(gè)新的實(shí)例。如果你想了解更多關(guān)于immutable類(lèi),可以閱讀How to create an immutable class in Java。字符串類(lèi)型和包裝類(lèi)相似,所以以上的規(guī)則對(duì)于字符串也有效。

集合類(lèi)型

public static void main(String[] args) {
    List<Integer> lstNums = new ArrayList<Integer>();
    lstNums.add(1);
    System.out.println("Size of list before List modification = " + lstNums.size());
    modifyList(lstNums);
    System.out.println("Size of list after List modification = " + lstNums.size());
}
private static void modifyList(List<Integer> lstParam)
{
    lstParam.add(2);
}

輸出:

Size of list before List modification = 1
Size of list after List modification = 2

說(shuō)明:
當(dāng)我們創(chuàng)建一個(gè)ArrayList或任意集合,在堆棧中便會(huì)創(chuàng)建一個(gè)指向堆中多個(gè)對(duì)象的引用。當(dāng)modifyList()被調(diào)用時(shí),一個(gè)引用的拷貝被創(chuàng)建中傳遞到了方法中,F(xiàn)在有2個(gè)引用指向了真正的對(duì)象數(shù)據(jù),其中任何一個(gè)引用的數(shù)據(jù)改變會(huì)影響到另一個(gè)。
在方法中,當(dāng)我們調(diào)用lstParam.add(2)時(shí),一個(gè)Integer對(duì)象在堆中被創(chuàng)建,添加到了現(xiàn)有的list對(duì)象。所以原始的list引用可以看見(jiàn)這次修改,因?yàn)?個(gè)引用都指向了內(nèi)存中的同一個(gè)對(duì)象

 

4.png

 

自定義對(duì)象

public static void main(String[] args) {
    Student student = new Student();
    System.out.println("Value of name before Student modification = " + student.getName());
    modifyStudent(student);
    System.out.println("Value of name after Student modification = " + student.getName());
}
private static void modifyStudent(Student student)
{
    student.setName("Alex");
}

輸出:

Value of name before Student modification = null
Value of name after Student modification = Alex

說(shuō)明:
student對(duì)象在堆中被創(chuàng)建,在堆棧中存儲(chǔ)著指向它的引用。當(dāng)調(diào)用calling modifyStudent(),在堆棧中創(chuàng)建了這個(gè)引用的拷貝,傳遞到了方法中。所以任何對(duì)這個(gè)對(duì)象屬性的修改會(huì)影響原始的對(duì)象引用

結(jié)論

在Java中,參數(shù)都是按值傳遞的。被傳遞到方法中的拷貝值,要不就是一個(gè)引用或一個(gè)變量,取決于原始參數(shù)的類(lèi)型。從現(xiàn)在開(kāi)始,下面的幾條規(guī)則將幫助你理解方法中對(duì)于參數(shù)的修改怎么影響原始參數(shù)變量。

  1. 在方法中,修改一個(gè)基礎(chǔ)類(lèi)型的參數(shù)永遠(yuǎn)不會(huì)影響原始參數(shù)值。
  2. 在方法中,改變一個(gè)對(duì)象參數(shù)的引用永遠(yuǎn)不會(huì)影響到原始引用。然而,它會(huì)在堆中創(chuàng)建了一個(gè)全新的對(duì)象。(譯者注:指的是包裝類(lèi)和immutable對(duì)象)
  3. 在方法中,修改一個(gè)對(duì)象的屬性會(huì)影響原始對(duì)象參數(shù)。
  4. 在方法中,修改集合和Maps會(huì)影響原始集合參數(shù)。

標(biāo)簽:

版權(quán)申明:本站文章部分自網(wǎng)絡(luò),如有侵權(quán),請(qǐng)聯(lián)系:west999com@outlook.com
特別注意:本站所有轉(zhuǎn)載文章言論不代表本站觀點(diǎn)!
本站所提供的圖片等素材,版權(quán)歸原作者所有,如需使用,請(qǐng)與原作者聯(lián)系。

上一篇:JAVA 同步實(shí)現(xiàn)原理

下一篇:深入Spring Boot:快速集成Dubbo + Hystrix