自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java深入學(xué)習(xí)系列之值傳遞Or引用傳遞?

開(kāi)發(fā) 后端
在Java方法傳參時(shí),究竟是引用傳遞還是值傳遞?關(guān)于Java里值傳遞還是引用傳遞,至少?gòu)谋憩F(xiàn)形式上來(lái)看,兩種觀點(diǎn)都有支撐的論據(jù)。Java內(nèi)部方法傳參不是引用傳遞,而是引用本身的"值"的傳遞,歸根結(jié)底還是值傳遞。

[[171642]]

 我們來(lái)看一個(gè)新手甚至寫(xiě)了多年Java的朋友都可能不是十分確定的問(wèn)題:

在Java方法傳參時(shí),究竟是引用傳遞還是值傳遞?

為了說(shuō)明問(wèn)題, 我給出一個(gè)非常簡(jiǎn)單的class定義:

  1. public class Foo { 
  2.   String attribute; 
  3.   Foo(String s) { 
  4.     this.attribute = s; 
  5.   } 
  6.   void setAttribute(String s) { 
  7.     this.attribute = s; 
  8.   } 
  9.   String getAttribute() { 
  10.     return this.attribute; 
  11.   } 
  12.  

下面在闡明觀點(diǎn)時(shí),可能會(huì)多次用到該類。

關(guān)于Java里值傳遞還是引用傳遞,至少?gòu)谋憩F(xiàn)形式上來(lái)看,兩種觀點(diǎn)都有支撐的論據(jù)。下面我來(lái)一一分析:

觀點(diǎn)1:引用傳遞

理由如下:先看一段代碼

  1. public class Main { 
  2.   public static void modifyReference(Foo c){ 
  3.     c.setAttribute("c"); // line DDD 
  4.   } 
  5.  
  6.   public static void main(String[] args) { 
  7.     Foo fooRef = new Foo("a"); // line AAA 
  8.     modifyReference(fooRef); // line BBB 
  9.     System.out.println(fooRef.getAttribute()); // 輸出 c 
  10.   } 
  11.  

上述示例,輸出結(jié)果為"c",而不是"c"。

我們?cè)趌ine AAA處新創(chuàng)建了一個(gè)Object Foo并將其引用fooRef在line BBB處傳給了方法modifyReference()的參數(shù)cRef, 該方法內(nèi)部處理后,fooRef指向的Object中的值從"a"變成了"c", 而引用fooRef還是那個(gè)引用, 因此,我們是否可以認(rèn)為,在line BBB處發(fā)生了引用傳遞?

先留著疑問(wèn),我們繼續(xù)往下看。

觀點(diǎn)2:值傳遞

繼續(xù)看一段代碼

  1. public class Main { 
  2.   public static void changeReference(Foo aRef){ 
  3.     Foo bRef = new Foo("b"); 
  4.     aRef = bRef;   // line EEE 
  5.   } 
  6.    
  7.   public static void main(String[] args) { 
  8.     Foo fooRef = new Foo("a"); // line AAA 
  9.     changeReference(fooRef); // line BBB 
  10.     System.out.println(fooRef.getAttribute()); // 輸出 a 
  11.   } 
  12.  

上述示例,輸出結(jié)果為"a", 而不是"b"。

我們?cè)趌ine AAA處新創(chuàng)建了一個(gè)Object Foo并將其引用fooRef在line EEE處傳給了方法changeReference()的參數(shù)aRef, 該方法內(nèi)部引用aRef在line DDD處被重新賦值。如果是引用傳遞,那么引用aRef在line EEE處已經(jīng)被指向了新的Object, 輸出應(yīng)該為"b"才對(duì),事實(shí)上是怎樣的呢?事實(shí)上輸出了"b",也就是說(shuō)changeReference()方法改變了傳入引用所指對(duì)象的值。

觀點(diǎn)1和觀點(diǎn)2的輸出結(jié)果多少會(huì)讓人有些困惑,別急,我們繼續(xù)往下看。

深入分析

為了詳細(xì)分析這個(gè)問(wèn)題,把上述兩段代碼合起來(lái):

  1. public class Main { 
  2.   public static void modifyReference(Foo cRef){ 
  3.     cRef.setAttribute("c"); // line DDD 
  4.   } 
  5.   public static void changeReference(Foo aRef){ 
  6.     Foo bRef = new Foo("b"); // line FFF 
  7.     aRef = bRef;   // line EEE 
  8.   } 
  9.    
  10.   public static void main(String[] args) { 
  11.     Foo fooRef = new Foo("a"); // line AAA 
  12.     changeReference(fooRef); // line BBB 
  13.     System.out.println(fooRef.getAttribute()); // 輸出 a 
  14.      
  15.     modifyReference(fooRef); // line CCC 
  16.     System.out.println(fooRef.getAttribute()); // 輸出 c 
  17.      
  18.  
  19.   } 
  20.  

下面來(lái)深入內(nèi)部來(lái)詳細(xì)分析一下引用和Object內(nèi)部的變化。來(lái)看下面圖示:

① Line AAA, 申明一個(gè)名叫fooRef,類型為Foo的引用,并見(jiàn)其分配給一個(gè)新的包含屬性值為"f"的對(duì)象,該對(duì)象類型為Foo。

  1. Foo fooRef = new Foo("a"); // line AAA 

 

 ② Line DDD, 方法內(nèi)部,申明了一個(gè)Foo類型的名為aRef的引用,且aRef被初始化為null。

  1. void changeReference(Foo a); 

 

③ Line CCC, changeReference()方法被調(diào)用后,引用aRef被分配給fooRef指向的對(duì)象。

  1. changeReference(fooRef); 

 ④ Line FFF, 申明一個(gè)名叫bRef,類型為Foo的引用,并見(jiàn)其分配給一個(gè)新的包含屬性值為"b"的對(duì)象,該對(duì)象類型為Foo。

  1. Foo bRef = new Foo("b"); 

 

 ⑤ Line EEE, 將引用aRef重新分配給了包含屬性"b"的對(duì)象。此處注意,并非將fooRef重新分配,而是aRef。

  1. aRef = bRef; 

 

 ⑥ Line CCC, 調(diào)用方法modifyReference(Foo cRef)后,新建了一個(gè)引用cRef并將之分配到包含該屬性"f"的對(duì)象上,該對(duì)象同時(shí)被兩個(gè)引用fooRef和cRef指向著。

  1. modifyReference(fooRef);  

 ⑦ Line DDD, cRef.setAttribute("c");將會(huì)改變cRef引用指向的包含屬性"f"的對(duì)象,而該對(duì)象同時(shí)被引用fooRef指向著。

  1. cRef.setAttribute("c"); 

 

 此時(shí)引用fooRef指向的對(duì)象內(nèi)部屬性值"f"也被重新設(shè)置為"c"。

總結(jié)

Java內(nèi)部方法傳參不是引用傳遞,而是引用本身的"值"的傳遞,歸根結(jié)底還是值傳遞。將一個(gè)對(duì)象的引用fooRef傳給方法的形參newRef,將給該對(duì)象新增了一個(gè)引用,相當(dāng)于多了一個(gè)alias。我們可以通過(guò)這個(gè)原引用fooRef,或這是方法參數(shù)里的新引用newRef去訪問(wèn)、操作原對(duì)象,也可以改變參數(shù)里的引用newRef本身的值,卻無(wú)法改變?cè)胒ooRef的值。

責(zé)任編輯:龐桂玉 來(lái)源: segmentfault
相關(guān)推薦

2022-07-29 08:05:31

Java值傳遞

2015-09-08 10:16:41

Java參數(shù)按值傳遞

2022-11-02 15:00:03

Java值傳遞引用傳遞

2023-11-15 09:14:27

Java值傳遞

2024-09-04 01:36:51

Java對(duì)象傳遞

2020-09-02 08:00:51

Java引用傳遞值傳遞

2009-08-17 14:48:44

Java參數(shù)傳遞機(jī)制

2020-03-23 14:15:51

RadonDB安裝數(shù)據(jù)庫(kù)

2012-02-21 14:04:15

Java

2011-03-25 13:44:28

Java值傳遞

2010-09-25 14:38:18

Java內(nèi)存分配

2017-12-05 08:53:20

Golang參數(shù)傳遞

2015-09-29 08:57:46

javascript對(duì)象

2009-11-17 14:13:34

PHP配置

2009-09-04 11:00:13

通過(guò)C#引用傳遞

2021-10-18 15:50:49

Android強(qiáng)引用軟引用

2010-08-31 13:06:45

CSS

2010-09-28 09:22:34

DOM模型Html

2010-06-29 15:29:22

UML建模流程

2015-09-29 09:27:04

JavaScript對(duì)象
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)