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

為什么Java中只有值傳遞

 更新時(shí)間:2021年01月13日 08:50:29   作者:mengde  
這篇文章主要介紹了為什么Java中只有值傳遞,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下

參數(shù)傳遞

在我們?nèi)粘>帉?xiě)代碼的過(guò)程中,調(diào)用函數(shù)可能是最常見(jiàn)的操作了。那么,在調(diào)用函數(shù)時(shí),參數(shù)是怎么樣傳遞的呢?

值傳遞

相信有很多人都是學(xué)C語(yǔ)言入門(mén)的,剛開(kāi)始寫(xiě)代碼時(shí),用的最多的就是值傳遞了。

void plus_one(int a){
  a++;
  printf("a: %d", a);
}

int main(){
  int n = 10;
  plus_one(n);
  printf("n:%d", n);
  return 0;
}

這是一個(gè)簡(jiǎn)單的值傳遞的例子,無(wú)需多言,plus_one函數(shù)的作用就是將傳進(jìn)來(lái)的數(shù)加一,然后輸出。所謂值傳遞,就是直接將實(shí)參n的值賦給形參a,賦值完成之后,兩者再無(wú)瓜葛。

因此,上面的代碼可以等效為:

int main(){
  int n = 10;
  
  // plus_one start
  int a;
  a = n;
  a++;
  printf("a: %d", a);
  // plus_one end
  
  printf("n:%d", n);
  return 0;
}

可以看到,值傳遞簡(jiǎn)單直觀,然而,調(diào)用函數(shù)并不能改變實(shí)參n的值。

指針傳遞

那么,當(dāng)我們需要改變實(shí)參的值的時(shí)候,我們就會(huì)想到使用指針傳遞,也就是所謂的地址傳遞。

void plus_one(int* p){
  *p = *p + 1;
}

int main(){
  int n = 10;
  plus_one(&n);
  printf("The result is %d", n);
  return 0;
}

這里,我們將實(shí)參n的地址傳入plus_one函數(shù),在函數(shù)中,直接對(duì)指針p所指向的值,也就是n做操作,自然就可以改變實(shí)參n的值了。

實(shí)際上,指針傳遞也是值傳遞。我們將上面的代碼改寫(xiě):

int main(){
  int n = 10;
  
  // plus_one start
  int* p;
  p = &n;
  *p = *p + 1;
  printf("The result is %d", n);
  // plus_one end
  
  return 0;
}

可以看到,所謂的指針傳遞,也只不過(guò)是將變量n的地址值賦給指針變量p,實(shí)際上也是值傳遞。

所以,可以不負(fù)責(zé)任的概括為,C語(yǔ)言中只有值傳遞;

引用傳遞

指針固然強(qiáng)大,但是由于代碼不易讀,難以理解等問(wèn)題,也是廣為詬病。C++作為C語(yǔ)言的超大杯,引入了引用傳遞來(lái)簡(jiǎn)化指針傳遞的寫(xiě)法。

void plus_one(int& a){
  a++;
}

int main(){
  int n;
  plus_one(n);
  printf("The result is %d", n);
  return 0;
}

C++中,對(duì)&運(yùn)算符進(jìn)行了重載,實(shí)現(xiàn)了引用傳遞。具體實(shí)現(xiàn)為,在調(diào)用plus_one函數(shù)時(shí),在函數(shù)調(diào)用棧中存變量n的地址,而不是n的值。因此,plus_one中的變量a就相當(dāng)于是n的"別名",對(duì)a操作時(shí),自然會(huì)改變n的值。

可見(jiàn),引用傳遞的底層也是賦值操作。

Java中的參數(shù)傳遞

那么,在Java中,究竟是引用傳遞,還是值傳遞呢?

Java中變量分為基本變量和對(duì)象,我們不妨分別討論。

基本變量類(lèi)型

首先,對(duì)于int、char等基本類(lèi)型,Java是使用值傳遞的,很容易驗(yàn)證。

static void plusOne(int a){
  a++;
  System.out.println("a: " + a);
}

public static void main(String[] args){
  int n = 10;
  plusOne(n);
	System.out.println("n: " + n);
}

顯然,與C語(yǔ)言中一樣,這里n的值是不會(huì)改變的。

對(duì)象

public class PassObject {
  public static void main(String[] args) {
    Dog myDog = new Dog("Test");
    foo(myDog);
    System.out.println(myDog.getName());// TestPlus
  }

  public static void foo(Dog dog) {
    dog.setName("TestPlus");
  }
}

class Dog{

  private String name;

  public Dog(String name) {
    this.name = name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }
}

通過(guò)上面的例子可以看到,傳入對(duì)象的引用時(shí),是可以改變對(duì)象的屬性變量的。那么Java在傳遞對(duì)象作為參數(shù)時(shí),是引用傳遞嗎?

實(shí)際上并非如此,Java中,對(duì)象的引用,實(shí)際上相當(dāng)于對(duì)象的指針。在Java中操作對(duì)象,只有通過(guò)引用操作這一種途徑。某種意義上,Java中是不能直接操作對(duì)象的。

也就是說(shuō),在上例中傳參時(shí),沒(méi)有對(duì)myDog對(duì)象實(shí)例做任何操作,只是把myDog引用值賦給了foo函數(shù)中的本地變量dog。并沒(méi)有像引用傳遞一樣,傳入對(duì)象實(shí)體,但是只在棧中保存對(duì)象引用的操作。所以,Java中傳遞對(duì)象時(shí),也是值傳遞。

所以,Java中只有值傳遞。

值得一提

然而,還是會(huì)有一些特殊情況,會(huì)讓人懷疑上述結(jié)論。

數(shù)組

上面只分析了基本變量類(lèi)型和對(duì)象,數(shù)組呢?

實(shí)際上,Java中的數(shù)組也是一種對(duì)象,數(shù)組類(lèi)也是繼承自O(shè)bject類(lèi)。在將數(shù)組作為參數(shù)時(shí),也是傳遞的數(shù)組的引用,并沒(méi)有傳遞數(shù)組的實(shí)體。

public static void changeContent(int[] arr) {
  arr[0] = 10;
}

public static void changeRef(int[] arr) {
  arr = new int[2];
  arr[0] = 15;
}

public static void main(String[] args) {
  int [] arr = new int[2];
  arr[0] = 4;
  arr[1] = 5;

  changeContent(arr);
  System.out.println(arr[0]); // 10
  changeRef(arr);
  System.out.println(arr[0]); // 10
}

在上例中可以看到,將傳入的數(shù)組引用賦給一個(gè)新的數(shù)組后,這個(gè)引用就不能操作之前的數(shù)組了。

關(guān)于引用,英文是reference,實(shí)際上,我自認(rèn)為,翻譯為句柄是更為貼切的,引用就像是一個(gè)柄,一個(gè)Handler,你可以用它操作實(shí)體,但他并不是實(shí)體本身。就像手柄可以操控游戲機(jī),但不是游戲機(jī)本身,當(dāng)你將這個(gè)手柄連接到另一個(gè)游戲機(jī)的時(shí)候, 它就不能操控之前的游戲機(jī)了。

包裝類(lèi)和String

public static void main(String[] args) {
  Integer n = 1;
  plusOne(n);
  System.out.println(n); // 1
}

private static void plusOne(Integer n) {
  n = n + 1;
  System.out.println(n);// 2
}

在這段代碼中,n作為Integer類(lèi)型實(shí)例的句柄,卻并沒(méi)有成功改變對(duì)象的值,這是為什么呢?

在Integer類(lèi)中,存對(duì)應(yīng)值的屬性是value,其聲明如下:

private final int value;

可見(jiàn),value值是不能改的,那加的操作是怎么實(shí)現(xiàn)的呢?

在上述加一的過(guò)程中,會(huì)重新new一個(gè)Integer對(duì)象,讓后將這個(gè)對(duì)象賦給引用n。這樣以來(lái),之前的對(duì)象自然是不會(huì)改變的。

實(shí)際上,包裝類(lèi)以及String類(lèi)的值,都是final的,所以在執(zhí)行+的過(guò)程中,都會(huì)重新生成一個(gè)對(duì)象,然后對(duì)它賦值。

以上就是為什么Java中只有值傳遞的詳細(xì)內(nèi)容,更多關(guān)于Java 值傳遞的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Kafka日志清理實(shí)現(xiàn)詳細(xì)過(guò)程講解

    Kafka日志清理實(shí)現(xiàn)詳細(xì)過(guò)程講解

    這篇文章主要為大家介紹了Kafka日志清理實(shí)現(xiàn)詳細(xì)過(guò)程講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Java常見(jiàn)的轉(zhuǎn)義字符舉例詳解

    Java常見(jiàn)的轉(zhuǎn)義字符舉例詳解

    在java字符常量中,反斜杠(\)是一個(gè)特殊的字符,被稱(chēng)為轉(zhuǎn)義字符,它的作用是用來(lái)轉(zhuǎn)義后面一個(gè)字符,這篇文章主要給大吉介紹了關(guān)于Java常見(jiàn)轉(zhuǎn)義字符的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-02-02
  • 一起因MySQL時(shí)間戳精度引發(fā)的血案分析

    一起因MySQL時(shí)間戳精度引發(fā)的血案分析

    這篇文章主要給大家介紹了一起因MySQL時(shí)間戳精度引發(fā)的血案的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用MySQL具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • spring task @Scheduled注解各參數(shù)的用法

    spring task @Scheduled注解各參數(shù)的用法

    這篇文章主要介紹了spring task @Scheduled注解各參數(shù)的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • 在idea中創(chuàng)建SpringBoot項(xiàng)目

    在idea中創(chuàng)建SpringBoot項(xiàng)目

    這篇文章主要介紹了在idea中創(chuàng)建SpringBoot項(xiàng)目,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • SpringBoot Kafka 整合使用及安裝教程

    SpringBoot Kafka 整合使用及安裝教程

    這篇文章主要介紹了SpringBoot Kafka 整合使用及安裝教程,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下
    2019-07-07
  • java hasNextInt判斷是否為數(shù)字的方法

    java hasNextInt判斷是否為數(shù)字的方法

    今天小編就為大家分享一篇java hasNextInt判斷是否為數(shù)字的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • springboot @RequestBody 接收字符串實(shí)例

    springboot @RequestBody 接收字符串實(shí)例

    這篇文章主要介紹了springboot @RequestBody 接收字符串實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java8中的LocalDateTime和Date一些時(shí)間操作方法

    Java8中的LocalDateTime和Date一些時(shí)間操作方法

    這篇文章主要介紹了Java8中的LocalDateTime和Date一些時(shí)間操作方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • MybatisPlus創(chuàng)建時(shí)間不想用默認(rèn)值的問(wèn)題

    MybatisPlus創(chuàng)建時(shí)間不想用默認(rèn)值的問(wèn)題

    MybatisPlus通過(guò)FieldFill注解和MpMetaObjectHandler類(lèi)支持自動(dòng)填充字段功能,特別地,可以設(shè)置字段在插入或更新時(shí)自動(dòng)填充創(chuàng)建時(shí)間和更新時(shí)間,但在特定場(chǎng)景下,如導(dǎo)入數(shù)據(jù)時(shí),可能需要自定義創(chuàng)建時(shí)間
    2024-09-09

最新評(píng)論