Java:在原始数组上使用类型双关?

jav*_*top 4 java buffer bytebuffer primitive-types type-punning

我需要能够将字节数组与其他原始类型数组相互转换,但不是强制转换,我需要类型 punning没有铸造的原始副本的正确术语?

我认为可以执行以下操作:

// idea: byte[12] -> int[3], and int[3] -> byte[12]

int[] ints;

ByteBuffer bb = ByteBuffer.wrap(
    new byte[]{ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3 });
IntBuffer ib = bb.asIntBuffer();

ints = ib.array(); // java.lang.UnsupportedOperationException
ints = ib.duplicate().array(); // java.lang.UnsupportedOperationException
Run Code Online (Sandbox Code Playgroud)

不幸的是,似乎bb.asIntBuffer()被复制的内容“按位”或“原始”创建一个新的IntBuffer,而造成对现有的ByteBuffer一个新的“视图”。这就是为什么.array()要失败。

我浏览了 JDK 的源代码,发现了一些类,这些类被所有这些缓冲区类使用并且可以做我需要的东西,但是是内部的(例如 class Unsafe)。

虽然我认为我的目标可以通过将字节缓冲区包装在 some 中ObjectInputStream并通过 读取原始值来实现.readInt(),但我认为这将是一种混乱且缓慢的解决方法。

那么,在进行神奇的原始类型算术(移位,检查字节序,...)的情况,还有其他可能的解决方案吗?

注意:我需要两个方向:byte[12] -> int[3] 和 int[3] -> byte[12]

wie*_*rob 6

根据 javadoc,array() [1] 返回缓冲区的后备数组,该数组是您通过调用 wrap() [2] 指定的数组。

因此,您必须创建一个具有所需类型的新数组。但是算术仍然可以通过 Buffer 类来处理。

ByteBuffer bb = ByteBuffer.wrap(new byte[]{ 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3 });
IntBuffer ib = bb.asIntBuffer();

int[] intArray = new int[ib.limit()];
ib.get(intArray);
Run Code Online (Sandbox Code Playgroud)

向后需要自己稍微计算一下。

ByteBuffer newBb = ByteBuffer.allocate(intArray.length*4);
newBb.asIntBuffer().put(intArray);
byte[] byteArray = newBb.array();
Run Code Online (Sandbox Code Playgroud)

看:

[1] http://java.sun.com/javase/6/docs/api/java/nio/ByteBuffer.html#array%28%29

[2] http://java.sun.com/javase/6/docs/api/java/nio/ByteBuffer.html#wrap%28byte[]%29