1.參考變量
在 Java 語言中,有兩種變量:原始變量和其他變量。碰巧的是,我們現在要談談“其他一切”。
其實說有原始變量和引用變量更正確。那麼這些參考變量是什麼?
與變量直接存儲值的原始類型不同,引用變量存儲對對象的引用。即內存某處有一個對象,引用變量只是存儲了這個對像在內存中的地址(對象的引用)。
只有基本類型將值直接存儲在變量中。所有其他類型只存儲一個對象引用。順便說一下,您已經遇到過兩種類型的變量——String
變量和數組變量。
數組和字符串都是存儲在內存中某處的對象。String
變量和數組變量僅存儲對對象的引用。
int a, int b and double d
是將它們的值存儲在自身內部的原始變量。
變量String str
是一個引用,將地址(引用)存儲到String
內存中的對象。
將原始值分配給原始類型的變量時,其值被複製(複製)。分配引用變量時,僅複製對象的地址——不復制對象本身 。
2. 什麼是參考文獻?
參考變量和原始變量之間的根本區別是什麼?
原始變量就像一個盒子:您可以在其中存儲一些值。參考變量更像是一張上面有電話號碼的紙。
汽車 vs 汽車鑰匙
想像一下,您決定在朋友生日時送他一輛車。你不會把它包在一個盒子裡隨身攜帶:汽車太大了。
將車鑰匙放在一個足夠大的盒子裡會方便得多。當他從盒子裡拿出鑰匙時,你的朋友就會明白一切。當您只需交出鑰匙時,就無需隨身攜帶整輛車。
一個人 vs 她的電話號碼
或者這是另一個比較:一個人和她的電話號碼。一個電話號碼不是那個人,但是一個電話號碼可以用來給她打電話,向她詢問一些信息,或者提供指示。
類似地,引用用於與對象交互。所有對像都使用引用相互交互。我們不是“交換人”,而是簡單地交換電話號碼。
為原始變量賦值時,其值被複製(複製)。為引用變量賦值時,只會復制對象的地址(電話號碼)——不會復制對象本身。
引用提供了另一個優勢:您可以將對象引用傳遞給某個方法,該方法將能夠通過使用對對象的引用、調用對象的方法和訪問對象內部的數據來修改(更改)對象。
3.分配引用
分配引用變量時,只分配對像在內存中的地址。對象本身不會出現或消失。
這種方法避免了複製大量內存。如果您需要將一個非常大的對像傳遞給方法,我們只需傳遞對象引用即可。引用佔用的空間要少得多。
所有引用變量(無論其類型如何)的大小都是相同的——4 個字節(類似於 int)。但!如果您的應用程序在 64 位 Java 機器上運行,那麼所有引用的大小都是 8 字節(64 位)。
更何況,引用只能相互賦值。您不能更改引用或為引用變量分配任意值:
代碼 | 描述 |
---|---|
|
這是允許的 |
|
但這是不允許的 |
|
這是不允許的 |
4.null
參考
如果還沒有分配給它,引用變量存儲什麼?
它存儲空引用。null
是一個特殊的 Java 關鍵字,表示沒有引用(空引用)。該null
值可以分配給任何引用變量。
所有引用變量都是,null
除非它們已經分配了某種引用。
例子:
代碼 | 描述 |
---|---|
|
該 String name 變量有一個默認值:null 。該 int age 變量有一個默認值:0 。 |
對於原始類型和引用類型,未賦值的局部變量被視為未初始化。
如果一個變量存儲了對某個對象的引用,而您想清除該變量的值,則只需為其分配一個空引用即可。
代碼 | 描述 |
---|---|
|
s 商店null 。存儲對字符串對象存儲的s 引用。s null |
5.傳遞對方法的引用
如果方法的參數是引用類型,則值將以與處理非引用變量時相同的方式傳遞給該方法。該參數只是簡單地分配了另一個變量的值。
例子:
代碼 | 描述 |
---|---|
|
用傳遞的值 ( )填充 fill 傳遞的數組( )。array value |
fill
調用該方法時,array
參數會被分配一個對數組的引用data
。該value
變量被分配了對字符串對象(“Hello”)的引用。
這是調用方法之前 內存的樣子fill
:
這是方法運行時 內存的樣子fill
:
和變量引用(存儲引用)內存中的同一容器data
。array
該value
變量存儲對字符串對象 ( ) 的引用"Hello"
。
數組的單元格也只存儲對"Hello"
對象的引用。
事實上,沒有對像被複製——只有引用被複製。
6.與C/C++語言的比較
在面試中,有時會問 Java 程序員,Java 中數據是如何傳遞給方法的?有時問題是數據是按引用傳遞還是按值傳遞?
這個問題來自 C++,但在 Java 中意義不大。在 Java 中,參數總是簡單地分配參數的值。所以正確的答案是“按價值”。
但是請準備好解釋您的立場,因為您可能會立即聽到反駁:“原始類型按值傳遞,而引用類型按引用傳遞。”
這個問題的由來源於很多Java程序員過去都是C++程序員。在該編程語言中,如何將參數傳遞給方法的問題非常重要。
在 Java 中,一切都是明確的:原始類型存儲值,而引用類型也存儲一個值——一個引用。這是一個變量是否被認為是一個值的問題。
在 C++ 中,變量可以存儲對對象的引用和對象本身。原始類型也是如此:原始變量可以存儲一個值或將變量聲明為對int
. 因此,為了避免混淆,C++ 程序員總是將引用的對象稱為引用,將對象本身稱為值。
在 C++ 中,您很容易遇到這樣的情況:一個變量包含一個對象,而另一個變量包含對該對象的引用。因此,變量存儲什麼的問題——對象本身或只是對它的引用——非常重要。當一個對像被傳遞給一個方法時,它被複製(如果通過值傳遞),而不是被複製(如果通過引用傳遞)。
在 Java 中,這種二元性不存在,所以正確答案是:arguments are passed to Java methods by value。只是當我們談論引用變量時,這個值是一個引用。