java java 大端_Java中的大端和小端

Java整型的字节序是()

A.Little-Endian(小端)

B.Big-Endian(大端)

C.由运行程序的CPU决定

D.由编译程序的CPU决定

对于大小端,我估计肯定有很多开发人员跟我一样都没听过

由于Java是跨平台的,JVM为我们屏蔽了大量的底层细节和复杂性,导致在平时的时候根本不会接触到。以下是我通过大量咨询,查找整理的结果。

字节序:指多字节数据在计算机内存中存储或者网络传输时各字节的存储顺序,有大端和小端两种方式

大端:指高位字节存放在内存的低地址端,低位字节存放在内存的高地址端。十六进制整数0x01020304在内存中存储方式,由于一个整型在内存中占4个字节,因此被划分成4份分别存储在连续的内存地址位中

4b77c293-6861-40d2-a44f-00eb51c77417.png

小端:指低位字节放在内存的低地址端,高位字节放在内存的高地址端。同样0x01020304在内存中的存储方式为

359f9421-4ad4-4417-b3a0-ddf8797861fa.png

在计算机中既可以是大端存储,也可以小端存储,跟CPU架构有关,IA架构(Intel、AMD)的CPU中是Little-Endian,而PowerPC 、SPARC和Motorola处理器是Big-Endian

基于Java8,在Java中提供了一个api可以获取CPU使用的字节序:

ByteOrder byteOrder = ByteOrder.nativeOrder();

//LITTLE_ENDIAN,CPU是Intel的

System.out.println(byteOrder);

通过查看ByteOrder.nativeOrder() 源码,其最后调用了Bits.byteOrder()

// -- Processor and memory-system properties --

private static final ByteOrder byteOrder;

static ByteOrder byteOrder() {

if (byteOrder == null)

throw new Error("Unknown byte order");

return byteOrder;

}

/**

* 通过返回0x01,还是0x08来判断CPU使用的是BIG_ENDIAN,还是LITTLE_ENDIAN

**/

static {

long a = unsafe.allocateMemory(8);

try {

unsafe.putLong(a, 0x0102030405060708L);

byte b = unsafe.getByte(a);

switch (b) {

case 0x01: byteOrder = ByteOrder.BIG_ENDIAN; break;

case 0x08: byteOrder = ByteOrder.LITTLE_ENDIAN; break;

default:

assert false;

byteOrder = null;

}

} finally {

unsafe.freeMemory(a);

}

}

对于Java,其实既有使用大端,也有使用小端,对于ByteBuffer,默认使用的Big-Endian(大端),也可以对默认方式进行修改,如下例子

int x = 0x01020304;

ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[4]);

byteBuffer.asIntBuffer().put(x);

String before = Arrays.toString(byteBuffer.array());

System.out.println("默认字节序:"+byteBuffer.order().toString() + "," + "内存数据:"+before);

byteBuffer.order(ByteOrder.LITTLE_ENDIAN);

byteBuffer.asIntBuffer().put(x);

String after = Arrays.toString(byteBuffer.array());

System.out.println("修改字节序:"+byteBuffer.order().toString()+","+"内存数据:"+after);

默认字节序:BIG_ENDIAN,内存数据:[1, 2, 3, 4]

修改字节序:LITTLE_ENDIAN,内存数据:[4, 3, 2, 1]

通过查看ByteBuffer.wrap,其声明了一个HeapByteBuffer

public static ByteBuffer wrap(byte[] array, int offset, int length)

{

try {

return new HeapByteBuffer(array, offset, length);

} catch (IllegalArgumentException x) {

throw new IndexOutOfBoundsException();

}

}

所以byteBuffer.asIntBuffer()实际调用了HeapByteBuffer中的方法

public IntBuffer asIntBuffer() {

int size = this.remaining() >> 2;

int off = offset + position();

return (bigEndian

? (IntBuffer)(new ByteBufferAsIntBufferB(this,-1,0,size,size,off))

: (IntBuffer)(new ByteBufferAsIntBufferL(this,-1,0,size,size,off)));

}

bigEndian表示是否是大端,默认为true,所以后面put的时候实际是往ByteBufferAsIntBufferB大端中存储数据,但也可以调整为使用小端来存储数据,byteBuffer.order(ByteOrder.LITTLE_ENDIAN);

这题的答案是B,但实际却是Java中既能有大端也能有小端,只是Java默认使用了大端

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值