Java中的数组是否存储数据或指针 [英] Do arrays in Java store data or pointers

查看:23
本文介绍了Java中的数组是否存储数据或指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读有关数据局部性的文章,并想用它来改进我正在编写的游戏引擎.

假设我在不同的时间创建了五个对象,它们现在都位于内存中的不同位置,而不是彼此相邻.如果我将它们全部添加到一个数组中,该数组是否只保存指向这些对象的指针,并且它们将保留在内存中的同一位置,或者将它们全部添加到一个数组中,重新排列它们并使它们连续.

我问这个是因为我认为使用数组是使它们连续的好方法,但我不知道数组是否能解决我的问题!

解决方案

tl;dr

操作对对象的引用数组对对象没有影响,并且对对象在内存中的位置没有影响.

对象

对象的

添加元素可能是便宜的",因为如果内存恰好在内存的隔壁可用,则可以将其分配给数组以为更多元素腾出空间.在实践中这是不可能的.很有可能必须在内存中的其他地方构建一个新数组,所有指针都被复制到新数组,然后丢弃原始数组.

这样的新数组和复制是昂贵的".在可行的情况下,我们希望避免这种操作.如果您知道数组可能的最大大小,请在声明数组时指定该大小.整个连续内存块立即被占用,数组中的内容为空,直到您稍后为元素分配一个指针.

插入数组的中间也很昂贵.要么构建新数组并复制元素,要么必须将插入点之后的所有元素向下移动到其相邻位置.

这些对数组的操作都不会影响对象.对象在内存的以太中漂浮.对象对数组一无所知.对数组的操作不会影响对象及其在内存中的位置.唯一的关系是,如果数组中保存的引用是最后一个仍然指向对象的引用,那么当该数组元素被清除或删除时,该对象将成为

提示

在商业应用中,通常最好使用对象.

这意味着使用包装类而不是原语.例如,Integer 而不是 int.Java 中的自动装箱 工具通过自动使这变得更容易在原始值和它们的对象包装器之间进行转换.

首选对象意味着使用 Collection 而不是数组,通常是 List,特别是 ArrayList.或者对于不可变用途,从新的 List.of 方法返回的 List 实现.

与商业应用相比,在速度和内存使用率至高无上的极端情况下,例如您的游戏引擎,然后充分利用数组和原语.

I was reading about data locality and want to use it to improve my game engine that I'm writing.

Let's say that I have created five objects at different times that are now all in different places in the memory not next to each other. If I add them all to an array, will that array only hold pointers to those objects and they will stay in the same place in the memory or will adding them all to an array rearrange them and make them contiguous.

I ask this because I thought that using arrays would be a good way to make them contiguous, but I don't know if an array will fix my problem!

解决方案

tl;dr

Manipulating an array of references to objects has no effect on the objects, and has no effect on the objects’ location in memory.

Objects

An array of objects is really an array of references (pointers) to objects. A pointer is an address to another location in memory.

We speak of the array as holding objects, but that is not technically accurate. Because Java does not expose pointers themselves to us as programmers, we are generally unaware of their presence. When we access an element in the array, we are actually retrieving a pointer, but Java immediately follows that pointer to locate the object elsewhere in memory.

This automatic look-up, following the pointer to the object, makes the array of pointers feel like an array of objects. The Java programmer thinks of her array as holding her objects when in reality the objects are a hop-skip-and-a-jump away.

Arrays in Java are implemented as contiguous blocks of memory. For an array of objects, the pointers to those objects are being stored in contiguous memory. But when we access the elements, we are jumping to another location in memory to access the actual object that we want.

Adding elements may be "cheap" in that if memory happens to be available next door in memory, it can be allocated to the array to make room for more elements. In practice this is unlikely. Chances are a new array must be built elsewhere in memory, with all the pointers being copied over to the new array and then discarding the original array.

Such a new-array-and-copy-over is "expensive". When feasible, we want to avoid this operation. If you know the likely maximum size of your array, specify that size when declaring the array. The entire block of contiguous memory is claimed immediately, with empty content in the array until you later assign a pointer to the elements.

Inserting into the middle of an array is also expensive. Either a new array is built and elements copied over, or all the elements after the insertion point must be moved down into their neighboring position.

None of these operations to the array affect the objects. The objects are floating around in the ether of memory. The objects know nothing of the array. Operations on the array do not affect the objects nor their position in memory. The only relationship is that if the reference held in the array is the last reference still pointing to the object, then when that array element is cleared or deleted, the object becomes a candidate for garbage-collection.

Primitives

In Java, the eight primitive types (byte, short, int, long, float, double, boolean, and char) are not objects/classes and are not Object-Oriented Programming. One advantage is that they are fast and take little memory, compared to objects.

An array of primitives hold the values within the array itself. So these values are stored next to one another, contiguous in memory. No references/pointers. No jumping around in memory.

As for adding or inserting, the same behavior discussed above applies. Except that instead of pointers being shuffled around, the actual primitive values are being shuffled around.

Tips

In business apps, it is generally best to use objects.

That means using the wrapper classes instead of primitives. For example, Integer instead of int. The auto-boxing facility in Java makes this easier by automatically converting between primitive values and their object wrapper.

And preferring objects means using a Collection instead of arrays, usually a List, specifically a ArrayList. Or for immutable use, a List implementation returned from the new List.of method.

In contrast to business apps, in extreme situations where speed and memory usage are paramount, such as your game engine, then make the most of arrays and primitives.

这篇关于Java中的数组是否存储数据或指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆