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

淺談Java中真的只有值傳遞么

 更新時間:2019年12月20日 10:07:57   作者:為何不是夢  
這篇文章主要介紹了淺談Java中真的只有值傳遞么?文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

回顧值傳遞和引用傳遞

關(guān)于Java是值傳遞還是引用傳遞,網(wǎng)上有不一樣的說法。

1、基本類型或基本類型的包裝類以及String是值傳遞,引用類型是引用傳遞。
2、Java中只有值傳遞。

關(guān)于這個問題應(yīng)該是存在爭議的。根據(jù)測試出來的結(jié)果和我們自己的經(jīng)驗,以及口口相傳或是上學(xué)時老師講的,我們認(rèn)為是第一種。但第二種說法的呼聲也很高,漸漸地我們也認(rèn)為第2中才是對的。那么下面我們就來分析一下這個問題。

在談這個問題之前我們先了解值傳遞和引用傳遞的概念及現(xiàn)象。我還記得,值傳遞和引用傳遞這些概念是大學(xué)里學(xué)Java的時候老師教給我的,它們的概念是什么呢?老師是通過例子來講解的,大概是這樣的。

值傳遞

例子1:

 public static void main(String[] args){
  TestJavaParamPass() tjpp = new TestJavaParamPass();
  int num = 10;
  tjpp.change(num);
  System.out.println("num in main():"+num);
 }
 public void change(int param){
  param = 20;
  System.out.println("param in change():"+param);
}

控制臺輸出:

param in change():20
num in main():10

mian()方法中的int變量num傳遞給change()方法,change()方法接收到后將值改變?yōu)?0。通過看控制臺輸出,main()方法中的num變量的值沒有改變。

結(jié)論:基本類型是值傳遞。

引用傳遞

例子2:

 public static void main(String[] args){
  TestJavaParamPass() tjpp = new TestJavaParamPass();
  User user = new User();
  user.setName("Jerry");
  tjpp.change(user);
  System.out.println("user in mian():"+user);
 }
 public void change(User param){
  param.setName("Tom");
 System.out.println("param in change():"+param);
}

控制臺輸出:

param in change():User(name=Tom}
user in mian():User(name=Tom}

main()方法中的user變量傳遞給change()方法,change()方法改變了其name屬性值。通過看控制臺輸出,main()方法中的user變量的name屬性值發(fā)生改變。

結(jié)論:引用類型是引用傳遞。

特殊的值傳遞

例子3:

 public static void main(String[] args){
  TestJavaParamPass() tjpp = new TestJavaParamPass();
  String name = "Jerry";
  tjpp.change(name);
  System.out.println("name in main():"+name);
 }
 public void change(String param){
  param = "Tom";
  System.out.println("param in change():"+param);
}

控制臺輸出:

param in change():Tom
name in mian():Jerry

String也是引用類型的數(shù)據(jù)類型,為什么值沒改變?因為在change()方法里param = "Tom";相當(dāng)于param = new String("Tom");就相當(dāng)于param被重新賦值指向了另外一個對象。所以,其實String類型傳的是引用,只不過被重新賦值指向了別的對象了,沒有修改原對象。即,String本質(zhì)上還是引用傳遞,表像上是值傳遞。

結(jié)論:基本類型是值傳遞,引用類型是引用傳遞,String是特殊的值傳遞。

這個結(jié)論也是網(wǎng)絡(luò)上流傳的比較多的,可能大部分程序員的認(rèn)知都是這樣的。至于值傳遞和引用傳遞的概念,接下來便可根據(jù)上面的例子和結(jié)論推斷出來,以及解釋為什么大多數(shù)程序員都將String理解為是特殊的值傳遞。

概念提取

與其叫概念提取好不如叫結(jié)論總結(jié)呢。

值傳遞:基本類型的變量在被傳遞給方法時,傳遞的是該變量的值(即復(fù)制自己的值傳遞給方法)。

引用傳遞:引用類型的變量在被傳遞給方法時, 傳遞的是該變量的引用(即自己所指向的內(nèi)存地址)。

為什么說String是特殊的值傳遞:是因為String和基本類型從表象來說表現(xiàn)出來的結(jié)果是一樣,大概是為了便于記憶這個結(jié)果才這樣說的吧。但是要知道String也是引用傳遞只不過它的引用被重新賦值,指向了別的對象了,所以不會影響原值。所以String不能簡單的說是值傳遞。

解析Java只有值傳遞的說法

只有值傳遞的說法

網(wǎng)上還流傳一種說法叫Java只有值傳遞。網(wǎng)上有文章論證了Java只有值傳遞的說法,其中舉的例子和上面的類似。

分析的很透徹,解釋了上面三個例子的本質(zhì)。指出了上面第二個例子的錯誤之處,舉的例子不恰當(dāng)。并指出下面這樣的例子才恰當(dāng),又舉了鑰匙和房子的例子,佐證了上面第2個例子確實不恰當(dāng)。因為上面的例子的側(cè)重點都是最后實際變量的值有沒有改變。

 public static void main(String[] args){
  TestJavaParamPass() tjpp = new TestJavaParamPass();
  User user = new User();
  user.setName("Jerry");
  tjpp.change(user);
  System.out.println("user in mian():"+user);
 }
 public void change(User param){
  param = new User()
 param.setName("Tom");
 System.out.println("param in change():"+param);
}

輸出:

param in change():User(name=Tom}
user in mian():User(name=Jerry}

最后文章的結(jié)論是Java只有值傳遞。引用類型大概是這樣解釋的( 基本類型就不用說了 ),實際變量(實際參數(shù))賦值一份自己的引用地址的值傳給方法,方法的形式參數(shù)拿到的是實參的引用地址的值。側(cè)重點在值,所以結(jié)論說的是引用類型也是值傳遞。

解析

我覺得論證者分析基本類型和引用類型的實參形參的變化的原理是沒有問題的,但是得出的結(jié)論是不是有點不恰當(dāng)。怎么說呢?請繼續(xù)看。

論證者的意思是,java只有值傳遞。也就是說引用類型也是值傳遞,側(cè)重點是復(fù)制一份引用的地址的值給形參,在于這里的值是引用的地址的值(不是引用所指向的內(nèi)存里存的值),所以說是值傳遞。是不是有點牽強?我覺得有點偷換概念,沒錯,大家都知道引用類型傳遞的是引用的值,但你不能因為傳遞的是值就說是值傳遞,不傳值還能傳什么?引用是內(nèi)存地址,不是也得用值表示么?

而傳統(tǒng)的說法:基本類型是值傳遞(內(nèi)存里存東西所代表的值),引用類型是引用傳遞。我覺得這個側(cè)重點是:基本類型把值復(fù)制一份傳遞過去,引用類型把引用復(fù)制一份傳遞過去。側(cè)重點是傳遞的東西,基本類型傳遞的東西叫變量的值(變量本身所代表的值),引用類型傳遞的東西叫引用(引用本身的值,即內(nèi)存地址),而非引用所指向的內(nèi)存空間內(nèi)的值。所以這樣理解引用類型傳遞的是引用也沒問題啊。

所以,Java中基本類型傳遞的是變量所代表的自身的值(內(nèi)存里存東西所代表的值),是值傳遞;引用類型傳遞的是對象的引用,是引用傳遞;再深一步,引用也是一個確切的值來表示的,或者你把引用看作是對象的值,那也可以說引用類型傳遞的是對象的值,是值傳遞。

文章還說了

無論是值傳遞還是引用傳遞,其實都是一種求值策略(Evaluation strategy)。在求值策略中,還有一種叫做按共享傳遞(call by sharing)。其實Java中的參數(shù)傳遞嚴(yán)格意義上說應(yīng)該是按共享傳遞。

按共享傳遞,是指在調(diào)用函數(shù)時,傳遞給函數(shù)的是實參的地址的拷貝(如果實參在棧中,則直接拷貝該值)。在函數(shù)內(nèi)部對參數(shù)進(jìn)行操作時,需要先拷貝的地址尋找到具體的值,再進(jìn)行操作。如果該值在棧中,那么因為是直接拷貝的值,所以函數(shù)內(nèi)部對參數(shù)進(jìn)行操作不會對外部變量產(chǎn)生影響。如果原來拷貝的是原值在堆中的地址,那么需要先根據(jù)該地址找到堆中對應(yīng)的位置,再進(jìn)行操作。因為傳遞的是地址的拷貝所以函數(shù)內(nèi)對值的操作對外部變量是可見的。

簡單點說,Java中的傳遞,是值傳遞,而這個值,實際上是對象的引用。

這里的意思是,不論是基本類型還是引用類型傳給函數(shù)的是實參的地址拷貝,也就是內(nèi)存地址,可以說是引用,只不過基本類型在棧中,函數(shù)內(nèi)對參數(shù)操作時直接拷貝的值,引用類型的值在堆中,需要先找到它的位置,即地址、引用。最后說java是值傳遞,而這個值是對象的引用。

看到這明白了么?

地址就是引用,那是不是可以說java是引用傳遞了?傳遞的是引用的值,計算機中不全是值嗎,不是值還能是什么,說是引用傳遞是側(cè)重點不同傳,傳過去的就是地址就是引用,引用不用值表示用啥

這里說的值不是一個概念,說基本類型傳的是值,這個是值變量本身的值,說對象傳的也是值,這個值說的是引用是地址,而說對象說是引用傳遞,側(cè)重點在于說是傳的地址,指向?qū)ο笏淼膬?nèi)部的屬性的地址,非對象所表示的內(nèi)部的屬性的值,為的是和基本類型直接傳值區(qū)分開。

維基百科:引用 (程序設(shè)計)

在計算機科學(xué)中,引用(英語:reference)是指一個可以讓程序間接訪問于電腦存儲器或其他存儲設(shè)備中一特定數(shù)據(jù)的值,該數(shù)據(jù)可以為變量或記錄。
引用和數(shù)據(jù)本身不同。一般而言,引用會是數(shù)據(jù)存儲于存儲器或存儲設(shè)備中的物理地址。因此,引用亦常被稱為該數(shù)據(jù)的指針或地址。

看看引用的定義,引用是指一個XXX數(shù)據(jù)的值。好吧,引用本身就是一個值。但不是值還能是什么呢?計算機中不都是值么?

說值傳遞還是引用傳遞都沒有錯,關(guān)鍵是你怎么定義和解釋值傳遞、引用傳遞的概念以及值所表示的東西。

計算機中一切皆值,如果從這點出發(fā),那全都是傳的值啊,只不過細(xì)化到j(luò)ava中,基本類型傳遞的是自身的值,引用類型傳遞的是引用的值,而非對象內(nèi)屬性的值。

所以如果武斷的說只有值傳遞也是沒問題的,因為在計算機中只能用值來表示啊,但覺得有點投機取巧,就和說世界上只有***,那還區(qū)分**和**干嘛,道理差不多。(暫時想不到好的例子哈哈)

還是剛才說的那句,說是引用傳遞,側(cè)重點在于說是傳的是引用是地址,而非對象所表示的內(nèi)部的屬性值,為的是和基本類型直接傳值區(qū)分開,便于記憶.

最后

最后,大家理解現(xiàn)象的原理即可,沒必要追的那么深,或玩文字游戲,鉆牛角尖。

如果有人問你,你可以這么說,基本類型和他們的包裝類是值傳遞,引用類型傳遞的是對象的引用即地址值,String傳遞的也是地址值,只不過在函數(shù)內(nèi)地址值被修改了,所以不會影響到實參,因表現(xiàn)上和基本類型一樣,所以可能為了便于記住這個現(xiàn)象才說String是值傳遞。歸根到底傳的都是值只不過值的含義不同。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring Security permitAll()不允許匿名訪問的操作

    Spring Security permitAll()不允許匿名訪問的操作

    這篇文章主要介紹了Spring Security permitAll()不允許匿名訪問的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java SpringBoot開發(fā)小技巧詳解

    Java SpringBoot開發(fā)小技巧詳解

    這篇文章主要介紹了淺談SpringBoot項目如何讓前端開發(fā)提高效率(小技巧),主要介紹了Swagger和Nginx提高效率的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 教你用java實現(xiàn)學(xué)生成績管理系統(tǒng)(附詳細(xì)代碼)

    教你用java實現(xiàn)學(xué)生成績管理系統(tǒng)(附詳細(xì)代碼)

    教學(xué)管理系統(tǒng)很適合初學(xué)者對于所學(xué)語言的練習(xí),下面這篇文章主要給大家介紹了關(guān)于如何用java實現(xiàn)學(xué)生成績管理系統(tǒng)的相關(guān)資料,文中給出了詳細(xì)的實例代碼,需要的朋友可以參考下
    2023-06-06
  • Java基于注解實現(xiàn)的鎖實例解析

    Java基于注解實現(xiàn)的鎖實例解析

    這篇文章主要介紹了Java基于注解實現(xiàn)的鎖實例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • jar包打包成exe安裝包的實現(xiàn)

    jar包打包成exe安裝包的實現(xiàn)

    本文主要介紹了jar包打包成exe安裝包的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • Java使用字節(jié)流復(fù)制文件的方法

    Java使用字節(jié)流復(fù)制文件的方法

    這篇文章主要為大家詳細(xì)介紹了Java使用字節(jié)流復(fù)制文件的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Springboot基于enable模塊驅(qū)動的實現(xiàn)

    Springboot基于enable模塊驅(qū)動的實現(xiàn)

    這篇文章主要介紹了Springboot基于enable模塊驅(qū)動的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • java面向?qū)ο笾畬W(xué)生信息管理系統(tǒng)

    java面向?qū)ο笾畬W(xué)生信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java面向?qū)ο笾畬W(xué)生信息管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • 解決SpringBoot使用yaml作為配置文件遇到的坑

    解決SpringBoot使用yaml作為配置文件遇到的坑

    這篇文章主要介紹了解決SpringBoot使用yaml作為配置文件遇到的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Spring?ComponentScan的掃描過程解析

    Spring?ComponentScan的掃描過程解析

    這篇文章主要介紹了spring?ComponentScan的掃描過程解析,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03

最新評論