我正在研究数据本地化,并希望将其用于改善我正在编写的游戏引擎。假设我已经在不同的时间创建了五个对象,它们现在都在内存中的不同位置,而不是相邻的位置。如果我将它们全部添加到数组中,那么该数组是否仅包含指向这些对象的指针,并且它们将保持在内存中的同一位置,或者将它们全部添加到数组中会重新排列它们并使它们连续?我问这个问题是因为我认为使用数组是使它们连续的好方法,但我不知道数组是否能解决我的问题!
操作对象引用数组不会影响对象本身,也不会影响对象在内存中的位置。
一个对象的数组实际上是一个对象引用(指针)的数组。指针是指向内存中另一个位置的地址。
我们说数组中保存了对象,但这并不准确。因为Java不会将指针本身暴露给程序员,所以我们通常不知道它们的存在。当我们访问数组中的元素时,实际上是检索指针,但Java立即跟随该指针以定位内存中的对象。
这种自动查找指针到对象的过程,使得指针数组感觉像是一个对象数组。Java程序员认为她的数组保存了她的对象,而实际上对象离数组只有一步跳和跳之遥。
Java 中的数组是作为连续的内存块实现的。对于对象数组,这些对象的指针被存储在连续的内存中。但当我们访问元素时,我们要跳转到内存中的另一个位置来访问我们想要的实际对象。 添加元素可能是“便宜”的,因为如果内存恰好在相邻的内存中可用,可以将其分配给数组以腾出更多元素的空间。但实际上这是不太可能的。很可能需要在其他地方建立一个新数组,并将所有指针复制到新数组中,然后丢弃原始数组。在Java中,八种基本类型(byte
、short
、int
、long
、float
、double
、boolean
和char
)不是对象/类也不是面向对象编程。其中一个优点是它们比对象快且占用的内存较少。
在商业应用程序中,通常最好使用对象。
这意味着使用包装类而不是基本类型。例如,使用Integer
代替int
。Java中的auto-boxing功能使这更容易,自动在原始值和它们的对象包装之间进行转换。
而且,首选对象意味着使用Collection
而不是数组,通常使用List
,特别是ArrayList
。或者对于不可变使用,可以使用从新的List.of
方法返回的List
实现。
与商业应用相反,在极端情况下,例如游戏引擎,速度和内存使用量至关重要,则充分利用数组和基本类型。
如果Valhalla项目中的工作取得成果,那么将来对象和基本类型之间的区别可能会变得模糊。
AtomicReference
类或使用关键字volatile
。有关此问题的强制阅读资料:Brian Goetz等人的Java并发实践。 - Basil Bourqueint[]
或 float[]
可以适应 CPU 缓存。但是,如果您真的关心管理缓存未命中,也许您应该使用诸如 C、Rust 或 Swift 等 系统编程语言,而不是 Java。 - Basil Bourque
T[]
只保存对象引用。 - Ousmane D.