最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

為什么Java中只有值傳遞

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

參數(shù)傳遞

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

值傳遞

相信有很多人都是學(xué)C語言入門的,剛開始寫代碼時,用的最多的就是值傳遞了。

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

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

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

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

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;
}

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

指針傳遞

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

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

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

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

實際上,指針傳遞也是值傳遞。我們將上面的代碼改寫:

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;
}

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

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

引用傳遞

指針固然強大,但是由于代碼不易讀,難以理解等問題,也是廣為詬病。C++作為C語言的超大杯,引入了引用傳遞來簡化指針傳遞的寫法。

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

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

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

可見,引用傳遞的底層也是賦值操作。

Java中的參數(shù)傳遞

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

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

基本變量類型

首先,對于int、char等基本類型,Java是使用值傳遞的,很容易驗證。

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語言中一樣,這里n的值是不會改變的。

對象

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;
  }
}

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

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

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

所以,Java中只有值傳遞。

值得一提

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

數(shù)組

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

實際上,Java中的數(shù)組也是一種對象,數(shù)組類也是繼承自O(shè)bject類。在將數(shù)組作為參數(shù)時,也是傳遞的數(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ù)組引用賦給一個新的數(shù)組后,這個引用就不能操作之前的數(shù)組了。

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

包裝類和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類型實例的句柄,卻并沒有成功改變對象的值,這是為什么呢?

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

private final int value;

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

在上述加一的過程中,會重新new一個Integer對象,讓后將這個對象賦給引用n。這樣以來,之前的對象自然是不會改變的。

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

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

相關(guān)文章

  • Spring Boot 在啟動時進行配置文件加解密的方法詳解

    Spring Boot 在啟動時進行配置文件加解密的方法詳解

    這篇文章主要介紹了Spring Boot 在啟動時進行配置文件加解密的方法,本文通過實例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • 關(guān)于mybatis一對一查詢一對多查詢遇到的問題

    關(guān)于mybatis一對一查詢一對多查詢遇到的問題

    這篇文章主要介紹了關(guān)于mybatis一對一查詢,一對多查詢遇到的錯誤,接下來是對文章進行操作,要求查詢?nèi)课恼拢㈥P(guān)聯(lián)查詢作者,文章標(biāo)簽,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • Java Swing JToggleButton開關(guān)按鈕的實現(xiàn)

    Java Swing JToggleButton開關(guān)按鈕的實現(xiàn)

    這篇文章主要介紹了Java Swing JToggleButton開關(guān)按鈕的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Java中Tuple的功能及使用詳解

    Java中Tuple的功能及使用詳解

    Java中的Tuple是一種非常有用的數(shù)據(jù)結(jié)構(gòu),它可以讓開發(fā)者在處理多個數(shù)據(jù)元素時更加方便和高效,通過Tuple,我們可以將多個變量打包成一個對象,從而減少了代碼量,提高了代碼可讀性,這篇文章主要介紹了Java中Tuple的功能及使用場景,需要的朋友可以參考下
    2024-01-01
  • java通過方向鍵控制小球移動的小游戲

    java通過方向鍵控制小球移動的小游戲

    這篇文章主要為大家詳細(xì)介紹了java通過方向鍵控制小球移動的小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • 詳解Spring中的JavaConfig注解

    詳解Spring中的JavaConfig注解

    在開發(fā)Java程序,尤其是Java EE應(yīng)用的時候,總是免不了與各種配置文件打交道。java注解則幫我們使之更整潔,不會配置文件滿天飛了。 下面這篇文章主要介紹了Spring中的JavaConfig注解,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-02-02
  • 用遞歸查找有序二維數(shù)組的方法詳解

    用遞歸查找有序二維數(shù)組的方法詳解

    本篇文章是對用遞歸查找有序二維數(shù)組的方法進行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • Spring Boot 中嵌入式 Servlet 容器自動配置原理解析

    Spring Boot 中嵌入式 Servlet 容器自動配置原理解析

    這篇文章主要介紹了Spring Boot 中嵌入式 Servlet 容器自動配置原理解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java高效讀取大文件實例分析

    Java高效讀取大文件實例分析

    這篇文章主要介紹了Java高效讀取大文件實例分析,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • Mac安裝Maven的幾種方法小結(jié)

    Mac安裝Maven的幾種方法小結(jié)

    本文主要介紹了Mac安裝Maven的幾種方法小結(jié),主要包括通過Homebrew安裝Maven,通過SDKMAN安裝Maven和通過官方網(wǎng)站下載安裝包安裝Maven,感興趣的可以了解一下
    2024-01-01

最新評論

嵊州市| 肇州县| 赤峰市| 德保县| 巫溪县| 桦南县| 邵阳县| 磴口县| 左权县| 福海县| 荔波县| 连城县| 青浦区| 扎赉特旗| 台北县| 富宁县| 斗六市| 临沭县| 报价| 萍乡市| 五原县| 湄潭县| 侯马市| 仙游县| 新田县| 安西县| 镇江市| 平远县| 丁青县| 伊宁县| 德惠市| 鄂尔多斯市| 吉林省| 瑞金市| 中牟县| 五莲县| 济南市| 牟定县| 北京市| 久治县| 达孜县|