Java中使用new重新分配对象

5
这是一个关于Java内存分配的初学者问题。 我想知道以下重新分配是否“有问题”:
例如:
byte[] b = new byte[10];

..

b = new byte[20]

....

b = new byte[4]

这会清空堆栈并分配新的内存吗?我们能否重新调整变量/对象的大小并以此重新定义它?


1
@AbimaranKugathasan 已经说得很清楚了,但您使用这个的用例是什么?为什么要调整数组大小?列表可能更合适。 - Joffrey
一个快速的观察:那些通过建议使用 List<Byte> 来贡献答案的人应该非常清楚这种解决方案有多么_空间低效_。这就是为什么你几乎在任何地方都不会遇到它的原因。 - VH-NZZ
7个回答

7

这会清空堆栈并分配新的内存吗?

是的,如果旧对象没有任何活跃引用,它们将被垃圾回收。

我们可以改变变量/对象的大小和维度吗?

不可以,Java数组无法动态增长,它们的大小始终固定。

如果是其他对象,您可以更改对象的状态。例如:ArrayList,您可以在创建列表后更改其大小。

Probably just an additional question. If this is only allocating new memory and the old one taken care of by GC, is it ok to do the following:

MyObject myobject = new MyObject(byte[20])
... 
myobject= new MyObject(byte[10]);

是的,这是完全正确的。您正在将一个新对象重新分配给旧引用myobject


如果您经常调整大小,请注意各种列表实现的插入成本。 - VH-NZZ
你的话可能会让新手感到困惑,对于问题“这会清空堆栈吗?”的回答“是”的不正确,因为在“...”块中可能会有像byte[] c = b;这样的代码。 - Dmitry Ginzburg
@ginz:我认为在发布的代码上下文中不会引起混淆。 - Abimaran Kugathasan
可能只是一个额外的问题。如果这只是分配新内存,旧的内存由垃圾回收处理,那么做以下操作是否可以:MyObject myobject = new MyObject(byte[20])...myobject = new MyObject(byte[10]); - user907810
@user907810:已更新回答以回应您的最新问题。 - Abimaran Kugathasan

1
将新对象分配给变量将使先前的对象有资格进行垃圾回收,如果它没有被任何活动线程引用..你可以像你所做的那样..将一个对象分配给另一个对象只会分配对象引用(一个指针或多或少)。它不会复制成员变量等。例如,b=c;

0

是的,这将分配新的内存,"擦除"原始数组中的数据。

如果您想调整数组大小,但保留其中的数据,请查看Arrays.copyOf()方法及其相关方法。这可以让您有效地将数据从一个数组移动到另一个数组:

int[] arr = new int[4];
arr = Arrays.copyOf(arr, 8); // Array is now 8 ints long, with the last 4 slots "empty"

通常,如果你想要自动调整大小的数据结构,请看一下ArrayList,它由普通本地数组支持,但为你包装处理自动调整大小。

0
任何使用new创建的对象只要有引用,就会一直驻留在堆中。
在你的情况下。
byte[] b = new byte[10];  // new memory is created in heap

b = new byte[20] // new memory is created in heap

此时,您在堆中的对象(byte[10])将有资格进行垃圾回收。

b = new byte[4] //new memory is created here

此时您在堆中的对象(byte[20])将会被标记为可回收垃圾

数组不会动态增长。每次使用new初始化一个新的数组,旧的内存将被标记为可回收垃圾。


0

第一条:每当您使用new关键字时,它都会创建新的内存并删除先前的引用。但这并不意味着堆清除了,实际上这是分配给GC的任务,它会非常高效地管理它。

第二条:您无法调整数组的大小,但可以将该数据引用到另一个具有新的更大大小的数组中,在那里未引用的对象将被GC自动删除。

第三条:ArrayList在创建后可以动态增加其大小。


0

不会,一旦新对象被创建,JVM会自动回收旧对象。你无法在堆栈中找到它们。

正如@Abiram所解释的那样,您无法修改数组的状态。您可以尝试使用ArrayList添加动态值。如果您没有显式初始化实例变量,则该变量在new返回其引用时仍将具有其默认初始值。 初始值为:

Type            Default Value
boolean         false
byte           (byte) 0
short          (short) 0
int 0
long             0L
char            \u0000
float           0.0f
double          0.0d
object reference    null

你可以在这里参考文档
希望能帮到你!!

0

new 关键字将始终创建一个独立于指定类型的新实例。

这会清除堆栈并分配新内存吗?

是的,它将为每个 new 分配新的内存。当下一次垃圾回收完成时,旧位置将被清除,因此它将清除已分配的空间。

我们可以调整变量/对象的大小并以此重新定义它吗?

我的答案是否定的,您无法真正创建具有动态大小的字节数组。事实上,向单个对象分配过多的内存将创建内存问题。因此,最好基于机器修复一些大小,并明智地使用对象以避免此类问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接