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

帶你詳細了解Java值傳遞和引用傳遞

 更新時間:2021年04月19日 14:51:13   作者:程序員孫大圣  
這篇文章主要介紹了帶你詳細了解Java值傳遞和引用傳遞,文中有非常詳細的代碼示例,對正在學習java的小伙伴們有一定的幫助,需要的朋友可以參考下

1、什么是值傳遞,什么是引用傳遞?

  • 值傳遞(pass by value)是指在調(diào)用函數(shù)時將實際參數(shù)復(fù)制一份傳遞到函數(shù)中,這樣在函數(shù)中如果對參數(shù)進行修改,將不會影響到實際參數(shù)。
  • 引用傳遞(pass by reference)是指在調(diào)用函數(shù)時將實際參數(shù)的地址直接傳遞到函數(shù)中,那么在函數(shù)中對參數(shù)所進行的修改,將影響到實際參數(shù)。

2、值傳遞和引用傳遞的區(qū)別是什么?

 

3、Java中只有值傳遞

3.1 糾正一下大家以前的那些錯誤看法

錯誤理解一:值傳遞和引用傳遞,區(qū)分的條件是傳遞的內(nèi)容,如果是個值,就是值傳遞。如果是個引用,就是引用傳遞

錯誤理解二:Java是引用傳遞。

錯誤理解三:傳遞的參數(shù)如果是普通類型,那就是值傳遞,如果是對象,那就是引用傳遞。

3.2求值策略

我們說當進行方法調(diào)用的時候,需要把實際參數(shù)傳遞給形式參數(shù),那么傳遞的過程中到底傳遞的是什么東西呢?

這其實是程序設(shè)計中求值策略(Evaluation strategies)的概念。

在計算機科學中,求值策略是確定編程語言中表達式的求值的一組(通常確定性的)規(guī)則。求值策略定義何時和以何種順序求值給函數(shù)的實際參數(shù)、什么時候把它們代換入函數(shù)、和代換以何種形式發(fā)生。

求值策略分為兩大基本類,基于如何處理給函數(shù)的實際參數(shù),分為嚴格的和非嚴格的。

3.3 嚴格求值

在“嚴格求值”中,函數(shù)調(diào)用過程中,給函數(shù)的實際參數(shù)總是在應(yīng)用這個函數(shù)之前求值。多數(shù)現(xiàn)存編程語言對函數(shù)都使用嚴格求值。所以,我們本文只關(guān)注嚴格求值。

在嚴格求值中有幾個關(guān)鍵的求值策略是我們比較關(guān)心的,那就是傳值調(diào)用(Call by value)、傳引用調(diào)用(Call by reference)以及傳共享對象調(diào)用(Call by sharing)

1.傳值調(diào)用(值傳遞):在傳值調(diào)用中,實際參數(shù)先被求值,然后其值通過復(fù)制,在傳遞給被調(diào)函數(shù)的形式參數(shù)。因為形式參數(shù)拿到的只是一個"局部拷貝",所以如果在被調(diào)函數(shù)中改變了形式參數(shù)的值,并不會改變實際參數(shù)的值。

2.傳引用調(diào)用(引用傳遞)在傳引用調(diào)用中,傳遞給函數(shù)的是它的實際參數(shù)的隱式引用而不是實參的拷貝。因為傳遞的是引用,所以,如果在被調(diào)函數(shù)中改變了形式參數(shù)的值,改變對于調(diào)用者來說是可見的。

3.傳共享對象調(diào)用(共享對象傳遞)傳共享對象調(diào)用中,先獲取到實際參數(shù)的地址,然后將其復(fù)制,并把該地址的拷貝傳遞給被調(diào)函數(shù)的形式參數(shù)。因為參數(shù)的地址都指向同一個對象,所以我們也稱之為"傳共享對象",所以,如果在被調(diào)函數(shù)中改變了形式參數(shù)的值,調(diào)用者是可以看到這種變化的。

不知道大家有沒有發(fā)現(xiàn),其實傳共享對象調(diào)用和傳值調(diào)用的過程幾乎是一樣的,都是進行"求值"、"拷貝"、"傳遞"。你品,你細品。

但是,傳共享對象調(diào)用和內(nèi)傳引用調(diào)用的結(jié)果又是一樣的,都是在被調(diào)函數(shù)中如果改變參數(shù)的內(nèi)容,那么這種改變也會對調(diào)用者有影響。你再品,你再細品。

那么,共享對象傳遞和值傳遞以及引用傳遞之間到底有很么關(guān)系呢?

對于這個問題,我們應(yīng)該關(guān)注過程,而不是結(jié)果,因為傳共享對象調(diào)用的過程和傳值調(diào)用的過程是一樣的,而且都有一步關(guān)鍵的操作,那就是"復(fù)制",所以,通常我們認為傳共享對象調(diào)用是傳值調(diào)用的特例

我們先把傳共享對象調(diào)用放在一邊,我們再來回顧下傳值調(diào)用和傳引用調(diào)用的主要區(qū)別:

傳值調(diào)用是指在調(diào)用函數(shù)時將實際參數(shù)復(fù)制一份傳遞到函數(shù)中,傳引用調(diào)用是指在調(diào)用函數(shù)時將實際參數(shù)的引用直接傳遞到函數(shù)中。

是

3.3 java 的求值策略

前面我們介紹過了傳值調(diào)用、傳引用調(diào)用以及傳值調(diào)用的特例傳共享對象調(diào)用,那么,Java中是采用的哪種求值策略呢?

很多人說Java中的基本數(shù)據(jù)類型是值傳遞的,這個基本沒有什么可以討論的,普遍都是這樣認為的。

但是,有很多人卻誤認為Java中的對象傳遞是引用傳遞。之所以會有這個誤區(qū),主要是因為Java中的變量和對象之間是有引用關(guān)系的。Java語言中是通過對象的引用來操縱對象的。所以,很多人會認為對象的傳遞是引用的傳遞。

而且很多人還可以舉出以下的代碼示例:

public static void main(String[] args) {
  Test pt = new Test();
 
  User hollis = new User();
  hollis.setName("Hollis");
  hollis.setGender("Male");
  pt.pass(hollis);
  System.out.println("print in main , user is " + hollis);
}
 
public void pass(User user) {
  user.setName("hollischuang");
  System.out.println("print in pass , user is " + user);
}

 輸出結(jié)果:

print in pass , user is User{name='hollis', gender='Male'}
print in main , user is User{name='hollischuang', gender='Male'}:

可以看到,對象類型在被傳遞到pass方法后,在方法內(nèi)改變了其內(nèi)容,最終調(diào)用方main方法中的對象也變了。

所以,很多人說,這和引用傳遞的現(xiàn)象是一樣的,就是在方法內(nèi)改變參數(shù)的值,會影響到調(diào)用方。

但是,其實這是走進了一個誤區(qū)。

其實Java中使用的求值策略就是傳共享對象調(diào)用,也就是說,Java會將對象的地址的拷貝傳遞給被調(diào)函數(shù)的形式參數(shù)。只不過"傳共享對象調(diào)用"這個詞并不常用,所以Java社區(qū)的人通常說"Java是傳值調(diào)用",這么說也沒錯,因為傳共享對象調(diào)用其實是傳值調(diào)用的一個特例。

值傳遞和共享對象傳遞的現(xiàn)象沖突嗎?

看到這里很多人可能會有一個疑問,既然共享對象傳遞是值傳遞的一個特例,那么為什么他們的現(xiàn)象是完全不同的呢?

難道值傳遞過程中,如果在被調(diào)方法中改變了值,也有可能會對調(diào)用者有影響嗎?那到底什么時候會影響什么時候不會影響呢?

其實是不沖突的,之所以會有這種疑惑,是因為大家對于到底是什么是"改變值"有誤解。

我們先回到上面的例子中來,看一下調(diào)用過程中實際上發(fā)生了什么?

在參數(shù)傳遞的過程中,實際參數(shù)的地址0X1213456被拷貝給了形參。這個過程其實就是值傳遞,只不過傳遞的值得內(nèi)容是對象的應(yīng)用。

那為什么我們改了user中的屬性的值,卻對原來的user產(chǎn)生了影響呢?

其實,這個過程就好像是:你復(fù)制了一把你家里的鑰匙給到你的朋友,他拿到鑰匙以后,并沒有在這把鑰匙上做任何改動,而是通過鑰匙打開了你家里的房門,進到屋里,把你家的電視給砸了。

這個過程,對你手里的鑰匙來說,是沒有影響的,但是你的鑰匙對應(yīng)的房子里面的內(nèi)容卻是被人改動了。

也就是說,Java對象的傳遞,是通過復(fù)制的方式把引用關(guān)系傳遞了,如果我們沒有改引用關(guān)系,而是找到引用的地址,把里面的內(nèi)容改了,是會對調(diào)用方有影響的,因為大家指向的是同一個共享對象。

那么我們改變一下pass方法:

public void pass(User user) {
  user = new User();
  user.setName("hollischuang");
  System.out.println("print in pass , user is " + user);
}

再看一下整個過程中發(fā)生了什么: 

這個過程,就好像你復(fù)制了一把鑰匙給到你的朋友,你的朋友拿到你給他的鑰匙之后,找個鎖匠把他修改了一下,他手里的那把鑰匙變成了開他家鎖的鑰匙。這時候,他打開自己家,就算是把房子點了,對你手里的鑰匙,和你家的房子來說都是沒有任何影響的。

所以,Java中的對象傳遞,如果是修改引用,是不會對原來的對象有任何影響的,但是如果直接修改共享對象的屬性的值,是會對原來的對象有影響的。

4、總結(jié)

我們知道,編程語言中需要進行方法間的參數(shù)傳遞,這個傳遞的策略叫做求值策略。

在程序設(shè)計中,求值策略有很多種,比較常見的就是值傳遞和引用傳遞。還有一種值傳遞的特例——共享對象傳遞。

值傳遞和引用傳遞最大的區(qū)別是傳遞的過程中有沒有復(fù)制出一個副本來,如果是傳遞副本,那就是值傳遞,否則就是引用傳遞。

在Java中,其實是通過值傳遞實現(xiàn)的參數(shù)傳遞,只不過對于Java對象的傳遞,傳遞的內(nèi)容是對象的引用。

我們可以總結(jié)說,Java中的求值策略是共享對象傳遞,這是完全正確的。

但是,為了讓大家都能理解你說的,我們說Java中只有值傳遞,只不過傳遞的內(nèi)容是對象的引用。這也是沒毛病的。

但是,絕對不能認為Java中有引用傳遞。

到此這篇關(guān)于帶你詳細了解Java值傳遞和引用傳遞的文章就介紹到這了,更多相關(guān)Java值傳遞和引用傳遞內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java多線程實現(xiàn)有序輸出ABC

    java多線程實現(xiàn)有序輸出ABC

    這篇文章主要為大家詳細介紹了java多線程實現(xiàn)有序輸出ABC,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-08-08
  • JAVA找不到符號的三種解決方案

    JAVA找不到符號的三種解決方案

    這篇文章主要給大家介紹了關(guān)于JAVA找不到符號的三種解決方案, 找不到符號錯誤主要發(fā)生在我們試圖引用一個未在我們正在編譯的程序中聲明的變量時,這意味著編譯器不知道我們所引用的Java變量,需要的朋友可以參考下
    2024-03-03
  • java實現(xiàn)桌面右下角彈窗效果

    java實現(xiàn)桌面右下角彈窗效果

    這篇文章主要為大家詳細介紹了java實現(xiàn)桌面右下角彈窗效果,模仿類似于qq消息彈窗,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • JAVA把結(jié)果保留兩位小數(shù)的3種方法舉例

    JAVA把結(jié)果保留兩位小數(shù)的3種方法舉例

    在寫程序的時候,有時候可能需要設(shè)置小數(shù)的位數(shù),所以下面這篇文章主要給大家介紹了關(guān)于JAVA把結(jié)果保留兩位小數(shù)的3種方法,文章通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-08-08
  • Java超詳細講解三大特性之一的多態(tài)

    Java超詳細講解三大特性之一的多態(tài)

    多態(tài)就是指程序中定義的引用變量所指向的具體類型和通過該引用變量發(fā)出的方法調(diào)用在編程時并不確定,而是在程序運行期間才確定,即一個引用變量到底會指向哪個類的實例對象,該引用變量發(fā)出的方法調(diào)用到底是哪個類中實現(xiàn)的方法,必須在由程序運行期間才能決定
    2022-05-05
  • Java編程通過匹配合并數(shù)據(jù)實例解析(數(shù)據(jù)預(yù)處理)

    Java編程通過匹配合并數(shù)據(jù)實例解析(數(shù)據(jù)預(yù)處理)

    這篇文章主要介紹了Java編程通過匹配合并數(shù)據(jù)實例解析(數(shù)據(jù)預(yù)處理),分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • java使用鏈表實現(xiàn)約瑟夫環(huán)

    java使用鏈表實現(xiàn)約瑟夫環(huán)

    這篇文章主要為大家詳細介紹了java使用鏈表實現(xiàn)約瑟夫環(huán),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • 用SpringBoot框架來接收multipart/form-data文件方式

    用SpringBoot框架來接收multipart/form-data文件方式

    這篇文章主要介紹了用SpringBoot框架來接收multipart/form-data文件方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 基于mybatis進行批量更新兩種方法

    基于mybatis進行批量更新兩種方法

    這篇文章主要給大家介紹了關(guān)于如何基于mybatis進行批量更新的兩種方法,批量更新的使用,mybatis中批量更新有很多種方法,可以把數(shù)據(jù)一條條更新,也可以傳入一個數(shù)據(jù)集一次性更新,需要的朋友可以參考下
    2023-08-08
  • Idea中Java項目如何修改項目名

    Idea中Java項目如何修改項目名

    這篇文章主要介紹了Idea中Java項目如何修改項目名問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06

最新評論