[英]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.