死磕面試系列,Java到底是值傳遞還是引用傳遞?

Java到底是值傳遞還是引用傳遞?
這雖然是一個老生常談的問題,但是對于沒有深入研究過這塊 , 或者Java基礎不牢的同學,還是很難回答得讓人滿意 。
可能很多同學能夠很輕松的背出JVM、分布式事務、高并發、秒殺系統、領域模型等高難度問題,但是對于Java基礎問題不屑一顧 。這種抓大放小的初衷是對的 , 要是碰到深究基礎細節的面試官,就抓瞎了 。
今天一燈帶你一塊深入剖析Java傳遞的底層原理,看完這篇文章再去面試 , 面試官肯定要豎起大拇哥夸你:
“小伙子 , 你是懂Java傳遞的!”
1. 什么是形參和實參形參: 就是形式參數,用于定義方法的時候使用的參數,是用來接收調用者傳遞的參數的 。
實參: 就是實際參數,用于調用時傳遞給方法的參數 。實參在傳遞給別的方法之前是要被預先賦值的 。
/** * @author 一燈架構 * @apiNote Java傳遞示例 **/public class Demo {public static void main(String[] args) {String name = "一燈架構"; // 這里的name就是實際參數update(name);System.out.println(name);}// 這里方法參數列表中name就是形式參數private static void update(String name) {// doSomething}}在Java方法調用的過程中,就是把實參傳遞給形參,形參的作用域在方法內部 。
2. 什么是值傳遞和引用傳遞值傳遞: 是指在調用方法時,將實際參數拷貝一份傳遞給方法,這樣在方法中修改形式參數時,不會影響到實際參數 。
引用傳遞: 也叫地址傳遞,是指在調用方法時,將實際參數的地址傳遞給方法,這樣在方法中對形式參數的修改,將影響到實際參數 。
也就是說值傳遞,傳遞的是副本 。引用傳遞,傳遞的是實際內存地址 。這是兩者的本質區別,下面會用到 。
3. 測試驗證3.1 基本數據類型驗證先用基本數據類型驗證一下:
/** * @author 一燈架構 * @apiNote Java傳遞示例 **/public class Demo {public static void main(String[] args) {int count = 0;update(count);System.out.println("main方法中count:" + count);}private static void update(int count) {count++;System.out.println("update方法中count:" + count);}}輸出結果:
update方法中count:1main方法中count:0可以看到雖然update方法修改了形參count的值,但是main方法中實參count的值并沒有變,但是為什么沒有變?我們深究一下底層原理 。
我們都知道Java基本數據類型是存儲在虛擬機棧內存中,棧中存放著棧幀 , 方法調用的過程,就是棧幀在棧中入棧、出棧的過程 。
當執行main方法的時候,就往虛擬機棧中壓入一個棧?。?棧幀中存儲的局部變量信息是count=0 。

死磕面試系列,Java到底是值傳遞還是引用傳遞?

文章插圖
當執行update方法的時候,再往虛擬機棧中壓入一個棧幀 , 棧幀中存儲的局部變量信息是count=0 。
死磕面試系列,Java到底是值傳遞還是引用傳遞?

文章插圖
修改update棧幀中數據,顯然不會影響到main方法棧幀的數據 。
3.2 引用類型驗證再用引用類型數據驗證一下:
/** * @author 一燈架構 * @apiNote Java傳遞示例 **/public class Demo {public static void main(String[] args) {User user = new User();user.setId(0);update(user);System.out.println("main方法中user:" + user);}private static void update(User user) {user = new User();user.setId(1);System.out.println("update方法中user:" + user);}}輸出結果:
update方法中user:User(id=1)main方法中user:User(id=0)由代碼得知,update方法中重新初始化了user對象,并重新賦值,并不影響main方法中實參數據 。
當執行main方法時,會在堆內存中開辟一塊內存,在棧內存中壓入一個棧?。?棧幀中存儲一個引用 , 指向堆內存中的地址 。
死磕面試系列,Java到底是值傳遞還是引用傳遞?

文章插圖
當調用update方法時,會把main方法的棧幀拷貝一份,再壓入棧內存中,指向同一個堆內存地址 。
死磕面試系列,Java到底是值傳遞還是引用傳遞?

文章插圖
當執行update方法,重新初始化user對象,并重新賦值的時候 。會在堆內存中再開辟一塊內存,再把棧內存中update棧幀指向新的堆內存地址,并修改新的堆內存中的數據 。
死磕面試系列,Java到底是值傳遞還是引用傳遞?

文章插圖
從這里可以看出是值傳遞,修改了形參里面數據 , 實參并沒有跟著變化 。
3.3 同一地址的引用類型驗證/** * @author 一燈架構 * @apiNote Java傳遞示例 **/public class Demo {public static void main(String[] args) {User user = new User();user.setId(0);update(user);System.out.println("main方法中user:" + user);}private static void update(User user) {user.setId(1);System.out.println("update方法中user:" + user);}}

推薦閱讀