簡體   English   中英

內存中的Java原始類型和對象結構

[英]Java primitive types and objects structure in memory

當我們創建 Java 原始變量或 Java 對象時,它是如何在內存中表示/結構化的?

int A;

// 是否創建了對整數類型的引用?
// 保存在內存中分配的整數類型所需的內存空間嗎?

A = 3;

// 現在是否分配了保存整數類型所需的內存空間? 然后A引用那個空間。

int B = 2;
A = B;

// A 是否將內存位置引用為 B ? 而 A 引用的舊內存位置是 Garbage Collected ?
// 如果是,那么修改 A 將導致也修改 B,對嗎?
// 如果沒有,那么已經完成了傳值。
// 是否修改了 A 引用的內存位置,或者創建了一個能夠保存 int 的新內存位置,填充了 B 引用的值,然后被 A 引用?

如果 A 是一個類對象,是否也有相同的類比?

Java 中的原語進入堆棧,因此它們存儲在變量的位置。 請記住,雖然 String 被認為是不可變的,但它不是原始類型,而是一個類。

因此變量 A 和 B 都持有值 2,但不共享該值。 附帶說明一下,Java 對 int 變量做了一些有趣的事情。 如果它們足夠低,它們實際上甚至不會存儲在堆棧中,而是引用內存中的靜態分配(預編譯器處理)。

現在對於您要分配類實例的部分。 然后事情發生了一些變化。 如果您將實例分配給 A,您將在堆棧上分配對 A 的引用並在堆上分配它。 當您將 A 分配給 B 時,兩者都將引用堆中的同一個實例。 在兩個引用都超出范圍之前,不會對該實例進行垃圾回收。

如果您重新分配 A 或 B,它們將不再指向堆中的同一個實例。

在您的場景中,在堆棧上進行的內存管理:不在堆上,可以描述如下: 在此處輸入圖片說明

當你這樣做時, A=B ,為A引用的整數分配的內存變得有資格進行 GC。

現在,當您對任一變量進行修改時,您正在引用與該值對應的其他內存位置,並且由於它在堆棧上,因此不會影響另一個。

例如,做A = 6 ,不會影響B的值; B 仍然保持值為2

最后,它與如果 A 是類對象的情況不同,因為對象進入堆內存。

看看這篇Wiki文章,我發現它的解釋性很強。

每種類型的數據類型都有不同的數據量,用於存儲該數據類型,這就是為什么我們對大小有限制,例如,整數可以是(-2,147,483,648 到 2,147,483,647,最多 32位)。 其他數據類型,例如 floats 和 doubles,具有不同的值,其中 float 是 32 位浮點值,double 是 64 位雙精度浮點值。

至於你的問題,如果你改變B,它會改變A,簡短的回答是否定的。 當您定義一個等於 B 的變量 A 時,您所做的是將 A 的值更改為等於 B。另一個例子,如果您有以下代碼(任何面向對象的語言),您在做什么正在內存中創建一個值為零的位置(並分配了 32 位的空間),並且您正在創建第二個變量,其值為變量a ,該值為零。 編輯:第二個變量完全獨立於第一個。

int a = 0;
int b = a;

有這樣一種東西,可以通過改變原始值來修改一個變量,這就是所謂的指針。 指針是一種特殊的小工具,用於保存有關數據存儲在內存中的位置的信息,也稱為內存地址。 看看下面的代碼。

Person* person = new Person();
int* age = person.age;

在這里,我聲明了兩個指針,一個是對正在實例化的對象的引用,另一個是指向該對象中的字段的鏈接。 指針存儲給定數據在內存中存儲位置的信息(內存地址)。 由此,每當使用指針時,它都充當指向該內存地址的指針供我們訪問。 因此,它並不是真正的變量,而是充當“目錄”中的列表,您可以在其中使用它來查找數據。 因為它不直接存儲任何數據,而只是對存儲數據的引用,當直接用person.age改變人的年齡時,它也會更新內存中的數據,但地址保持不變,並且將反映在指針上。

至於垃圾收集的問題,在 Java 或 C# 等語言中,只有在不再引用該信息時才會對數據進行垃圾收集。 但是,在 C++ 等語言中,不會自動進行垃圾回收,您必須刪除使用delete關鍵字創建的指針。

無論如何,希望這會有所幫助!

對於原始類型:

int i = 10;
int j = i;
i = 11

在 java 中,為 i 和 j 的值分配了 8 字節的內存(i 為 4 字節,j 為 4 字節)。 i 的值傳遞給 j,現在 j 和 i 具有相同的值但不同的內存地址。 現在 i 的值更改為 11,這意味着對於相同的內存地址,i 的值從 10 更改為 11,但 j 的值位於不同的內存位置,因此它保持為 10。

在此處輸入圖片說明

在對象的情況下,值(或引用)本身是一個地址(或堆地址),所以如果一個人改變了它,它也會反映給其他人。 例如在對象中:-

Person p1 = new Person();
Person p2 = p1;

在此處輸入圖片說明

因此,無論是 p1 進行更改還是 p2 進行更改,兩者都會更改。 無論是 Java、Python 還是 Javascript,它都是一樣的。 在原始值的情況下,它是實際值,但在對象的情況下,它是實際對象的地址 - 這就是技巧。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM