ByteBuffer getInt()的问题

8
我们正在使用Java ByteBuffer与C ++服务器进行套接字通信。我们知道Java是大端字节序,套接字通信也是大端字节序。因此,每当Java接收到字节流并将其放入ByteBuffer中时,我们调用getInt()获取值。没有问题,无需转换。
但是,如果我们明确将ByteBuffer的字节顺序设置为小端字节序(我的同事实际上就是这样做的),
1. 当数据被放入ByteBuffer中时,Java是否会自动将大端字节序转换为小端字节序? 2. 然后,小端字节序版本的getInt()将向您返回正确的值吗?
我猜想对于上述两个问题的答案都是肯定的。但是,当我尝试验证我的猜测并尝试找到ByteBuffer中getInt()的工作原理时,我发现它是一个抽象方法。 ByteBuffer的唯一子类是MappedByteBuffer类,它没有实现抽象的getInt()。那么getInt()方法的实现在哪里呢?
对于发送来说,因为我们正在使用小端字节序的ByteBuffer,所以在将它们放入套接字之前,需要将它们转换为大端字节序的字节。

Java 6 中有两种 ByteBuffer 的实现,它们都包含 getInt() 方法。它们是 java.nio.DirectByteBuffer 和 java.nio.HeapByteBuffer。快速查看 HeapByteBuffer 看起来它确实处理了你所期望的字节顺序。 - Joshua
什么是套接字通信?基础设施,即TCP/UDP等都是大端的,但发送的数据取决于您如何放置它以及所使用的平台。 - roni bar yanai
1
您有超过40个问题没有被采纳的答案。也许您可以跟进这些答案,以便它们可以被接受。 - Peter Lawrey
我猜上面两个问题的答案都是肯定的。否则很难理解为什么会提供这样的功能。 - user207421
2个回答

9

ByteBuffer会自动使用您指定的字节顺序。(默认为大端)

 ByteBuffer bb =
 // to use big endian
 bb.order(ByteOrder.BIG_ENDIAN);

 // to use little endian
 bb.order(ByteOrder.LITTLE_ENDIAN);

 // use the natural order of the system.
 bb.order(ByteOrder.nativeOrder()); 

直接缓冲区和堆缓冲区都可以按照您的指定重新排序字节。


3

那么getInt()方法的实现在哪里呢?

ByteBuffer 确实是一个抽象类。有几种方法可以创建字节缓冲区:

在我的JDK中,它们创建了内部类 HeapByteBufferDirectByteBuffer 的实例。它们各自的 getInt 函数如下:

// HeapByteBuffer

public int getInt() {
    return Bits.getInt(this, ix(nextGetIndex(4)), bigEndian);
}

public int getInt(int i) {
    return Bits.getInt(this, ix(checkIndex(i, 4)), bigEndian);
}

并且

// DirectByteBuffer

private int getInt(long a) {
    if (unaligned) {
        int x = unsafe.getInt(a);
        return (nativeByteOrder ? x : Bits.swap(x));
    }
    return Bits.getInt(a, bigEndian);
}

public int getInt() {
    return getInt(ix(nextGetIndex((1 << 2))));
}

public int getInt(int i) {
    return getInt(ix(checkIndex(i, (1 << 2))));
}

在上述代码中,nativeByteOrderbigEndian是两个布尔成员,分别表示配置的字节顺序是否与本机字节顺序匹配(a)以及是否为大端字节序(b),这有些冗余。

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