Java中的直接缓冲区是否像数组一样初始化为默认值?

12

当我在Java中初始化一个数组,比如:

float[] array = new float[1000];

所有元素是否都初始化为0。如果我像这样分配直接缓冲区,情况是否也是这样:

FloatBuffer buffer = ByteBuffer.allocateDirect(4*1000).asFloatBuffer();

?我似乎总是只得到零,但也许这取决于实现方式...


2
有趣的问题。[ByteBuffer javadoc] (http://download.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html) 看起来似乎没有提到这个问题。但请注意,这两种情况稍有不同。在第一种情况下,每个元素都被初始化为 0.0f,而在后一种情况下,每个读取到的浮点数都是 0.0f,只是因为 IEEE-754 位模式 为“全零” - user166390
请看我的回答:ByteBuffer的javadoc没有提到任何内容,但是其父类Buffer有。 - Neil Coffey
4个回答

5
看起来答案可能是这样的。
查看ByteBuffer的实现,它在底层使用DirectByteBuffer。查看Android的源代码,可以得知以下注释:

在新分配的操作系统内存上构造给定容量的新直接字节缓冲区。内存将被清零。

因此,当您分配一个缓冲区时,所有的内存内容都将被初始化为零。Oracle的实现也会进行这种清零操作。
不过这只是一个实现细节。由于javadoc没有提到清零操作,依赖这个操作是技术上不正确的。要正确起见,您应该自己清零缓冲区。实际上,如果您真的担心性能问题,可以省略这一步骤,但需要注意的是,JVM的某些实现可能不会执行清零操作。

2
我不同意:这个注释只是一个实现注释,而不是Javadoc注释。而且它只存在于Android的实现中。Oracle实现的源代码并没有包含这个注释,尽管它也将内存设置为0。所以我的答案是它可能总是被清零,但你不能确定。 - JB Nizet
更新了我的答案,更清晰地表明这是一个实现细节。谢谢@jb-nizet。 - jterrace
请看我的回答:它有点隐藏,但是javadoc确实暗示您不能依赖缓冲区一定被清零。 - Neil Coffey
1
@Neil Coffey,这不仅是暗示,而是明确声明的。 - user207421

3

从父抽象类Buffer的文档中可以得知:

缓冲区的初始内容通常是未定义的

在没有其他说明的情况下,我认为这也适用于通过ByteBuffer.allocateDirect()分配的缓冲区。有趣的是,我认为严格来说这也适用于普通的基于数组的缓冲区,尽管在分配Java数组时隐含着数组将被清零。


我相信您在发布这个答案时是正确的,但现在已经不正确了。 - Paul Taylor
我认为在当时是正确的,但正如你所说,最近的JDK已经澄清了这一点,可以假定直接缓冲区被清零。 - Neil Coffey

3

查看Java 7Java 8的Javadoc

现在它说

新缓冲区的位置将为零,其限制将是其容量,其标记将未定义,并且其每个元素都将初始化为零。是否具有支持数组是未指定的。

因此,您不再需要自己将它们清零。


0

无法确定,因此问题是徒劳的。初始位置为零,因此您无法执行任何API以返回尚未“放置”的缓冲区部分。


那么 buffer.get(int index) 怎么样呢?我可以这样做: FloatBuffer buf = ByteBuffer.allocateDirect(400).asFloatBuffer(); System.out.println(buf.get(7));这将输出 0.0 - Se Norm
如果什么都没放进去,它肯定会抛出下溢异常吧? - user207421
据我所知,它对我没有用,索引仅针对缓冲区限制进行检查。据我所知,只有在使用相对访问方法且超出限制时才会抛出下溢异常。绝对获取(例如get(int index))会抛出越界异常,但仅当index>limit时。 - Se Norm
@Se Norm 好吧,我是猴子的叔叔,不要理我! - user207421

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