1. 程式人生 > >Java中的值傳遞和地址傳遞(傳值、傳引用)

Java中的值傳遞和地址傳遞(傳值、傳引用)

首先,不要糾結於 Pass By Value 和 Pass By Reference 的字面上的意義,否則很容易陷入所謂的“一切傳引用其實本質上是傳值”這種並不能解決問題無意義論戰中。
更何況,要想知道Java到底是傳值還是傳引用,起碼你要先知道傳值和傳引用的準確含義吧?可是如果你已經知道了這兩個名字的準確含義,那麼你自己就能判斷Java到底是傳值還是傳引用。
這就好像用大學的名詞來解釋高中的題目,對於初學者根本沒有任何意義。

一:搞清楚 基本型別 和 引用型別的不同之處
int num = 10;
String str = "hello";

<img src="https://pic2.zhimg.com/166032bc90958c21604110441ad03f45_b.jpg" data-rawwidth="728" data-rawheight="458" class="origin_image zh-lightbox-thumb" width="728" data-original="https://pic2.zhimg.com/166032bc90958c21604110441ad03f45_r.jpg">如圖所示,num是基本型別,值就直接儲存在變數中。而str是引用型別,變數中儲存的只是實際物件的地址。一般稱這種變數為"引用",引用指向實際物件,實際物件中儲存著內容。

如圖所示,num是基本型別,值就直接儲存在變數中。而str是引用型別,變數中儲存的只是實際物件的地址。一般稱這種變數為"引用",引用指向實際物件,實際物件中儲存著內容。

二:搞清楚賦值運算子(=)的作用
num = 20;
str = "java";
<img src="https://pic3.zhimg.com/287c0efbb179638cf4cf27cbfdf3e746_b.jpg" data-rawwidth="714" data-rawheight="572" class="origin_image zh-lightbox-thumb" width="714" data-original="https://pic3.zhimg.com/287c0efbb179638cf4cf27cbfdf3e746_r.jpg">對於基本型別 num ,賦值運算子會直接改變變數的值,原來的值被覆蓋掉。

對於基本型別 num ,賦值運算子會直接改變變數的值,原來的值被覆蓋掉。
對於引用型別 str,賦值運算子會改變引用中所儲存的地址,原來的地址被覆蓋掉。但是原來的物件不會被改變(重要)。
如上圖所示,"hello" 字串物件沒有被改變。(沒有被任何引用所指向的物件是垃圾,會被垃圾回收器回收)

三:呼叫方法時發生了什麼?引數傳遞基本上就是賦值操作
第一個例子:基本型別
void foo(int value) {
    value = 100;
}
foo(num); // num 沒有被改變

第二個例子:沒有提供改變自身方法的引用型別
void foo(String text) {
    text = "windows";
}
foo(str); // str 也沒有被改變

第三個例子:提供了改變自身方法的引用型別
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder.append("4");
}
foo(sb); // sb 被改變了,變成了"iphone4"。

第四個例子:提供了改變自身方法的引用型別,但是不使用,而是使用賦值運算子。
StringBuilder sb = new StringBuilder("iphone");
void foo(StringBuilder builder) {
    builder = new StringBuilder("ipad");
}
foo(sb); // sb 沒有被改變,還是 "iphone"。

重點理解為什麼,第三個例子和第四個例子結果不同?

下面是第三個例子的圖解:
<img src="https://pic4.zhimg.com/d8b82e07ea21375ca6b300f9162aa95f_b.jpg" data-rawwidth="772" data-rawheight="398" class="origin_image zh-lightbox-thumb" width="772" data-original="https://pic4.zhimg.com/d8b82e07ea21375ca6b300f9162aa95f_r.jpg">builder.append("4")之後builder.append("4")之後
<img src="https://pic4.zhimg.com/ff2ede9c6c55568d42425561f25a0fd7_b.jpg" data-rawwidth="696" data-rawheight="424" class="origin_image zh-lightbox-thumb" width="696" data-original="https://pic4.zhimg.com/ff2ede9c6c55568d42425561f25a0fd7_r.jpg">下面是第四個例子的圖解:下面是第四個例子的圖解:
<img src="https://pic4.zhimg.com/d8b82e07ea21375ca6b300f9162aa95f_b.jpg" data-rawwidth="772" data-rawheight="398" class="origin_image zh-lightbox-thumb" width="772" data-original="https://pic4.zhimg.com/d8b82e07ea21375ca6b300f9162aa95f_r.jpg">
builder = new StringBuilder("ipad"); 之後
<img src="https://pic2.zhimg.com/46fa5f10cc135a3ca087dae35a5211bd_b.jpg" data-rawwidth="710" data-rawheight="438" class="origin_image zh-lightbox-thumb" width="710" data-original="https://pic2.zhimg.com/46fa5f10cc135a3ca087dae35a5211bd_r.jpg">

相關推薦

Java傳遞地址傳遞引用

首先,不要糾結於 Pass By Value 和 Pass By Reference 的字面上的意義,否則很容易陷入所謂的“一切傳引用其實本質上是傳值”這種並不能解決問題無意義論戰中。 更何況,要想知道Java到底是傳值還是傳引用,起碼你要先知道傳值和傳引用的準確含義吧?可是如果你已經知道了這兩個名字的準確

Java傳遞地址傳遞

0.前言 被java中的“值傳遞”和“引用傳遞”困擾過一陣子,在實際程式碼中也犯過不少錯,記錄一下,方便檢視。 1.問題 首先看看程式碼: public class Test { public static void main(Stri

Java傳遞地址傳遞:關於String型別集合型別作為函式引數時問題的測試

這個問題,可能是太簡單了。稍微有點經驗的,估計都不會犯這個錯誤。不好意思,過了個年,幾天不寫程式碼,生疏了,也就有了下面的bug。先看程式碼,你要是一眼就看出問題了,那就請允許在下水那麼一回。 基本資

指標的傳遞地址傳遞

值傳遞: 形參是實參的拷貝,改變形參的值並不會影響外部實參的值。從被呼叫函式的角度來說,值傳遞是單向的(實參->形參),引數的值只能傳入, 不能傳出。當函式內部需要修改引數,並且不希望這個改變影響呼叫者時,採用值傳遞。 指標傳遞: 形參為指向實參地址的指標,

傳遞地址傳遞的區別

首先了解一下jvm的內部如何儲存資料: 1.jvm中每個執行緒都對應一個執行時記憶體區-----棧。棧中存放執行緒自己用到的所有變數。 2.jvm規定棧和堆分開。棧儲存基本資料型別和物件引用。而物件儲存在堆裡。 3.物件引用中儲存的值是堆中物件的地址。 呼叫方法時,實參賦值形參, 值傳遞:(形式引數型

深入剖析Java的裝箱拆箱淺度深度都有了

     自動裝箱和拆箱問題是Java中一個老生常談的問題了,今天我們就來一些看一下裝箱和拆箱中的若干問題。本文先講述裝箱和拆箱最基本的東西,再來看一下面試筆試中經常遇到的與裝箱、拆箱相關的問題。   以下是本文的目錄大綱:     什麼是裝箱?什麼是拆箱?      

java的getset方法比較詳細

屬性的訪問器包含與獲取(讀取或計算)或設定(寫)屬性有關的可執行語句。訪問器宣告可以包含 get 訪問器或 set 訪問器,或者兩者均包含。宣告採用下列形式之一: set {accessor-body} get {accessor-body} 其中: accessor-bod

3.7 Java之列印流資料流附字元位元組流練習

列印流 例項 資料流 資料流輸出 資料流輸入 字元位元組流練習 位元組流輸出 字元流輸出

Java基本型別封裝型別資料與堆棧的關係

Java的堆是一個執行時資料區,類的(物件從中分配空間。這些物件通過new、newarray、anewarray和multianewarray等 指令建立,它們不需要程式程式碼來顯式的釋放。堆是由垃圾回收來負責的,堆的優勢是可以動態地分配記憶體大小,生存期也不必事先告訴編譯

JVM的新生代老年代Eden空間兩個Survior空間

現有的主流JVM分別是HotSpot和JRockit,主要研究物件也是這兩個。這篇文章裡,我們只研究HotSpot,也就是所謂的Sun JVM。目前階段,Sun的GC方式主要有CMS和G1兩種。考慮到效果和實際應用,這裡只介紹CMS。CMS,全稱Concurrent Low

fault tolerance的錯誤故障檢測Error and Fault Detection Mechanisms

這裡的介紹來自論文Survey of Error and Fault Detection Mechanisms: 下面這張圖來自論文,反映了當今關於錯誤檢測機制(Error Detection Mec

Java併發程式設計:Synchronized底層優化偏向鎖輕量級鎖 Java併發程式設計:Synchronized底層優化偏向鎖輕量級鎖

轉自:https://www.cnblogs.com/paddix/p/5405678.html Java併發程式設計:Synchronized底層優化(偏向鎖、輕量級鎖)   Java併發程式設計系列: J

【深度學習數學基礎】向量點乘內積叉乘外積向量積概念及幾何意義解讀

1. 點乘 向量的點乘,也叫向量的內積、數量積,對兩個向量執行點乘運算,就是對這兩個向量對應位一一相乘之後求和的操作,點乘的結果是一個標量。 對於向量a和向量b:                                                 

向量點乘內積叉乘外積向量積概念及幾何意義解讀

向量是由n個實陣列成的一個n行1列(n*1)或一個1行n列(1*n)的有序陣列; 向量的點乘,也叫向量的內積、數量積,對兩個向量執行點乘運算,就是對這兩個向量對應位一一相乘之後求和的操作,點乘的結果是一個標量。 點乘公式 對於向量a和向量b:            

JAVA之大數操作及小數操作BigInteger類BigDecimal類

  今天我們來講講在 Java中 經常被忽視的兩個細節 —— 大數操作與小數操作。   本篇將對如何使用 BigInteger類 和 BigDecimal類 進行大數操作與小數操作做簡要講解,幫助大家快速掌握其用法。。(BigInteger類 與 BigD

Java併發程式設計:Synchronized底層優化偏向鎖輕量級鎖

Java併發程式設計系列: 一、重量級鎖   上篇文章中向大家介紹了Synchronized的用法及其實現的原理。現在我們應該知道,Synchronized是通過物件內部的一個叫做監視器鎖(monitor)來實現的。但是監視器鎖本質又是依賴於底層的作業系統的Mutex Lock來實現的。而

清華大學張長水教授:機器學習影象識別附視訊PPT下載

本篇乾貨整理自清華大學自動化系教授張長水於2018年4月27日在清華大學資料科學研

在Angular2使用SVG自定義圖表條形圖折線圖元件

要求:使用者將資料作為引數傳進來,通過型別決定渲染何種型別的圖示。 demo: html: <ngo-chart [inputParams]="options"></ngo-ch

向量點乘內積叉乘外積向量積概念及幾何意義解讀經典

宣告: 本文轉自這裡 向量是由n個實陣列成的一個n行1列(n*1)或一個1行n列(1*n)的有序陣列; 向量的點乘,也叫向量

JAVA語言程式設計 第十七章 17.817.9

程式小白,希望和大家多交流,共同學習 17.8_1 import java.io.File; import java.io.PrintWriter; import java.util.Scanner; import java.io.IOExceptio