亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中值傳遞的深度分析

 更新時(shí)間:2019年04月07日 15:14:41   作者:昆明--菜鳥入門  
這篇文章主要給大家介紹了關(guān)于Java中值傳遞的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言

首先說觀點(diǎn):java只有值傳遞沒有引用傳遞

然后再來看看值傳遞與引用傳遞兩者的定義

值傳遞(pass by value)是指在調(diào)用函數(shù)時(shí)將實(shí)際參數(shù)復(fù)制一份傳遞到函數(shù)中,這樣在函數(shù)中如果對(duì)參數(shù)進(jìn)行修改,將不會(huì)影響到實(shí)際參數(shù)。

引用傳遞(pass by reference)是指在調(diào)用函數(shù)時(shí)將實(shí)際參數(shù)的地址直接傳遞到函數(shù)中,那么在函數(shù)中對(duì)參數(shù)所進(jìn)行的修改,將影響到實(shí)際參數(shù)。

這里牢記值傳遞中將實(shí)際參數(shù)復(fù)制一份。

然后就是對(duì)于參數(shù)類型:值類型 和 引用類型。

結(jié)合起來理解就是:值類型傳遞,java是將其值內(nèi)容復(fù)制一份給形參;對(duì)于引用類型傳遞,java是將其地址復(fù)制一份給形參。

下面結(jié)合實(shí)例深入理解為什么java只有值傳遞

package 字符串;

public class 值傳遞 {
 public static void main(String[] args)
 {
 String str1="abc";
 updateStr1(str1);
 System.out.println("main函數(shù)中"+str1);
 }
 public static void updateStr1(String str1)
 {
 str1="cba"; //<注解>
 System.out.println("調(diào)用函數(shù)中"+str1);
 }
 
}

結(jié)果:

在這里我們能夠清晰看到我們傳遞的是String類型的對(duì)象即(引用類型),并且在調(diào)用函數(shù)中我們修改了str1為cba,如果是引用傳遞那么我們?cè)谥骱瘮?shù)打印則應(yīng)該是cba,

但是很遺憾我們?cè)谥骱瘮?shù)中仍然打印出來的是abc。所以我們可以說java是值傳遞類型了嗎,答案是不完全的。

接下來再看這一段代碼:

package 字符串;
  

  public class person {   private int age;   public int getAge() { return age; } public void setAge(int age) { this.age = age; }

}
public class 值傳遞2 {
 public static void main(String[] args)
 {
 person p1=new person();
 p1.setAge(10);
 System.out.println("我在主函數(shù)里對(duì)p1的年齡屬性賦值為"+p1.getAge());
 setage(p1);
 System.out.println("我再從主函數(shù)里獲取P1的年齡屬性"+p1.getAge());
 }
 
 public static void setage(person p1)
 {
 p1.setAge(18); //不是我們對(duì)它的地址進(jìn)行了操作,而是我們對(duì)它地址的內(nèi)容進(jìn)行了操作
 System.out.println("我在調(diào)用函數(shù)里對(duì)p1的年齡屬性重新賦值為"+p1.getAge());
 }

}

結(jié)果:

咦,怎么回事這次也是傳遞的對(duì)象(引用類型),為什么這次我們對(duì)年齡這個(gè)字段的修改在主函數(shù)同步了呢?

別急,下面我們先來分析這兩個(gè)例子。

首先第一個(gè)類型的例子中,我們傳遞的是String類型的變量,它是一個(gè)特殊的類型的引用變量。

(不可變字符串:編譯器可讓字符串共享,即將各種字符串存放于公共存儲(chǔ)池中,字符串變量是指向其中相應(yīng)位置    --出自《Java核心技術(shù) 卷1》)

出于這句話的理解就是每個(gè)字符串都對(duì)應(yīng)一個(gè)地址:我們例一中是將str1的地址復(fù)制給了我們的形參str1,并且形參中str1的地址進(jìn)行了改變指向了“cba”的地址。所以說在主函數(shù)中的str1的地址仍然指向的是“abc”所對(duì)應(yīng)的地址。

所以說對(duì)于String類型的變量,我們對(duì)于給它重新賦值不是改變了它的內(nèi)容,而是改變了它指向字符串的位置。這也就解釋了為什么java中String類型是不可變類型。

而在我們例二中,我們將p1的地址復(fù)制給了我們形參中的p1,此時(shí)他們都指向的內(nèi)存中一塊相同的地址這里存放著相同內(nèi)容,所以我們?cè)谡{(diào)用函數(shù)對(duì)這個(gè)地址中的內(nèi)容進(jìn)行修改時(shí)就會(huì)同步到我們主函數(shù)中的p1。所以這個(gè)并不意味著這個(gè)是引用傳遞。

好吧,那怎么才能解釋好Java確實(shí)是值傳遞呢(上面String類型例子是特殊的引用類型不方便解釋)

下面我們通過這個(gè)例子說明:

package 字符串;
public class person {
 private int age;
 public int getAge() {
 return age;
 }
 public void setAge(int age) {
 this.age = age;
 }

}
public class 值傳遞3 {
 public static void main(String[] args) {
 person p1=new person();
 person p2=new person();
 p1.setAge(10);
 p2.setAge(18);
 System.out.println("我在主函數(shù)里對(duì)p1的年齡屬性賦值為"+p1.getAge());
 System.out.println("我在主函數(shù)里對(duì)p2的年齡屬性賦值為"+p2.getAge());
 swap(p1,p2); 
 System.out.println("************我是主函數(shù)里的分割線***************");
 //我再在主函數(shù)里分別對(duì)p1,p2獲取他們的年齡,若為引用傳遞則p1的年齡應(yīng)該為18,p2為10.
 System.out.println("我在主函數(shù)里獲取p1的年齡"+p1.getAge());
 System.out.println("我在主函數(shù)里獲取p1的年齡"+p2.getAge());
 }
 public static void swap(person p1,person p2)
 {
 System.out.println("************我是調(diào)用函數(shù)里的分割線***************");
 person temp=new person();
 temp=p1;
 p1=p2;
 p2=temp;
 System.out.println("我在調(diào)用函數(shù)里交換了p1和p2指向的地址");
 System.out.println("我在調(diào)用函數(shù)里對(duì)p1的年齡屬性賦值為"+p1.getAge());
 System.out.println("我在調(diào)用函數(shù)里對(duì)p2的年齡屬性賦值為"+p2.getAge());
 
 }

}

結(jié)果:

看到?jīng)],這就是充分說明Java是值傳遞的例子。在這個(gè)例子中我們依然傳遞的是person類的對(duì)象p1,p2(引用類型),他們將各自的地址復(fù)制一份到了形參p1、p2。

然后我們?cè)谡{(diào)用函數(shù)中交換了他們的地址,確實(shí)在調(diào)用函數(shù)中他們的age屬性發(fā)生交換。但是再當(dāng)我們?cè)谥骱瘮?shù)獲取他們的age時(shí),如果是引用傳遞則應(yīng)該p1的age為18,p2的age為10,

和我們?cè)谡{(diào)用函數(shù)中打印結(jié)果一致。但是,很遺憾在主函數(shù)中他們的值仍然是p1(10),p2(18)。所以這也充分印證了java是值傳遞。

那么什么是引用傳遞呢?我們把代碼放入C#看看。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 值傳遞or引用傳遞
{
 public class person
 {
  private int age;
  public int getAge()
  {
   return age;
  }
  public void setAge(int age)
  {
   this.age = age;
  }

 }
 class Program
 {
  static void Main(string[] args)
  {
   person p1 = new person();
   person p2 = new person();
   person p3 = new person();
   p1.setAge(10);
   p2.setAge(18);
   p3.setAge(15);
   Console.WriteLine("我在主函數(shù)里對(duì)p1的年齡屬性賦值為" + p1.getAge());
   Console.WriteLine("我在主函數(shù)里對(duì)p2的年齡屬性賦值為" + p2.getAge());
   Console.WriteLine("我在主函數(shù)里對(duì)p3的年齡屬性賦值為" + p3.getAge());
   swap(ref p1,ref p2,p3);
   Console.WriteLine("************我是主函數(shù)里的分割線***************");
   //我再在主函數(shù)里分別對(duì)p1,p2獲取他們的年齡,若為引用傳遞則p1的年齡應(yīng)該為18,p2為10.
   Console.WriteLine("我在主函數(shù)里獲取p1的年齡" + p1.getAge());
   Console.WriteLine("我在主函數(shù)里獲取p2的年齡" + p2.getAge());
   Console.WriteLine("我在主函數(shù)里獲取p3的年齡" + p3.getAge());
  }
  public static void swap(ref person p1,ref person p2, person p3)
  {
   Console.WriteLine("************我是調(diào)用函數(shù)里的分割線***************");
   person temp = new person();
   temp = p1;
   p1 = p2;
   p2 = temp;
   p3.setAge(20);
   Console.WriteLine("我在調(diào)用函數(shù)里交換了p1和p2指向的地址");
   Console.WriteLine("我在調(diào)用函數(shù)里對(duì)p1交換地址后年齡為" + p1.getAge());
   Console.WriteLine("我在調(diào)用函數(shù)里對(duì)p2交換地址后年齡為" + p2.getAge());
   Console.WriteLine("我在調(diào)用函數(shù)里修改p3年齡為" + p3.getAge());

  }
 }
}

結(jié)果:

請(qǐng)注意在C#中如果我們要實(shí)現(xiàn)引用傳遞,請(qǐng)加上關(guān)鍵字ref,否則,它執(zhí)行的原理仍然與我們java中執(zhí)行的機(jī)制一樣,即拷貝一份地址給形參。

如果你還有點(diǎn)暈,不妨我們來看看下面兩張圖。

 為了方便大家理解把圖畫成這樣,然后關(guān)于java的值傳遞深度分析就到這里。歡迎大家一起討論。(可以打臉/哈哈)

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • SpringBoot如何讀取application.properties配置文件

    SpringBoot如何讀取application.properties配置文件

    這篇文章主要介紹了SpringBoot如何讀取application.properties配置文件問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • MySQL中關(guān)鍵字UNION和UNION ALL的區(qū)別

    MySQL中關(guān)鍵字UNION和UNION ALL的區(qū)別

    本文主要介紹了MySQL中關(guān)鍵字UNION和UNION ALL的區(qū)別,深入探討UNION和UNION ALL的定義、用法、主要區(qū)別,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-06-06
  • 一次線上websocket返回400問題排查的實(shí)戰(zhàn)記錄

    一次線上websocket返回400問題排查的實(shí)戰(zhàn)記錄

    最近項(xiàng)目中有端對(duì)端通信場(chǎng)景,實(shí)時(shí)性要求較高,考慮后選用了websocket 這一通信協(xié)議,下面這篇文章主要給大家介紹了一次線上websocket返回400問題排查的實(shí)戰(zhàn)記錄,需要的朋友可以參考下
    2022-04-04
  • Spring MVC全局異常處理和單元測(cè)試_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Spring MVC全局異常處理和單元測(cè)試_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    本篇文章主要介紹了Spring MVC全局異常處理和單元測(cè)試,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • Java instanceof和getClass()區(qū)別實(shí)例解析

    Java instanceof和getClass()區(qū)別實(shí)例解析

    這篇文章主要介紹了Java instanceof和getClass()區(qū)別實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • Java編程中的條件判斷之if語句的用法詳解

    Java編程中的條件判斷之if語句的用法詳解

    這篇文章主要介紹了Java編程中的條件判斷之if語句的用法詳解,是Java入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11
  • Java有效處理異常的三個(gè)原則

    Java有效處理異常的三個(gè)原則

    Java中異常提供了一種識(shí)別及響應(yīng)錯(cuò)誤情況的一致性機(jī)制,有效地異常處理能使程序更加健壯、易于調(diào)試。那么這篇文章總結(jié)了Java有效處理異常的三個(gè)原則,有需要的朋友們可以參考借鑒。
    2016-09-09
  • SpringBoot?Application核心注解詳解

    SpringBoot?Application核心注解詳解

    進(jìn)入到@SpringBootApplication的源碼,可以看到里面組合了三個(gè)我們感興趣的注解@ComponentScan、@EnableAutoConfiguration、@SpringBootConfiguration,我們一一分析這三個(gè)注解
    2022-10-10
  • 基于java使用JavaMail發(fā)送郵件

    基于java使用JavaMail發(fā)送郵件

    這篇文章主要介紹了基于java使用JavaMail發(fā)送郵件 ,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2016-12-12
  • Java利用poi讀取Excel詳解實(shí)現(xiàn)

    Java利用poi讀取Excel詳解實(shí)現(xiàn)

    Apache POI 是用Java編寫的免費(fèi)開源的跨平臺(tái)的 Java API,Apache POI提供API給Java對(duì)Microsoft Office格式檔案讀和寫的功能。POI為“Poor Obfuscation Implementation”的首字母縮寫,意為簡(jiǎn)潔版的模糊實(shí)現(xiàn)
    2022-07-07

最新評(píng)論