Java将int隐式转换为byte

我即将开始处理需要读取字节和创建字符串的事情。 正在读取的字节代表UTF-16字符串。 所以只是为了测试我想要将UTF-16编码的简单字节数组转换为字符串。 数组中的前2个字节必须表示字节序,因此必须是0xff 0xfe或0xfe 0xff。 所以我尝试按如下方式创建我的字节数组:

byte[] bytes = new byte[] {0xff, 0xfe, 0x52, 0x00, 0x6F, 0x00}; 

但是我收到一个错误,因为0xFF和0xFE太大而无法放入一个字节(因为字节是用Java签名的)。 更准确地说,错误是int无法转换为字节。 我知道我可以使用强制转换显式地从int转换为byte并获得所需的结果,但这不是我的问题。

为了尝试一些东西,我创建了一个String并调用了getBytes(“UTF-16”)然后打印了数组中的每个字节。 输出有点令人困惑,因为前两个字节是0xFFFFFFFE 0xFFFFFFFF,后跟0x00 0x52 0x00 0x6F。 (显然这里的字节顺序与我上面尝试创建的不同,但这并不重要)。

使用此输出我决定尝试以相同的方式创建我的字节数组:

 byte[] bytes = new byte[] {0xffffffff, 0xfffffffe, 0x52, 0x00, 0x6F, 0x00}; 

奇怪的是,它工作得很好。 所以我的问题是,为什么Java允许0xFFFFFF80或更大的整数值自动转换为没有显式强制转换的字节,但任何等于或大于0x80的东西都需要显式强制转换?

这里要记住的关键是Java中的int是一个带符号的值。 当你指定0xffffffff (它是2^32 -1 )时,它被转换为值-1有符号int – 一个int实际上不能表示像0xffffffff那样大的正数。

因此,对于小于0x80且大于0xFFFFFF80的值,结果int值介于-128和127之间,可以明确地表示为byte 。 超出该范围的任何东西都不可能,并且需要强制使用显式强制转换,在此过程中丢失数据。

如果使用没有提示的数字(例如1234L很长),编译器会假定一个整数。 值0xffffffff是一个值为-1的整数,可以在没有警告的情况下转换为byte

因为0xffffffff是数字-1,-1可以解释为一个字节。

0xff与写入0x000000ff相同,而不是0xffffffff 。 这就是你的问题; 整数是正数(255),但字节(如果逐位转换)将是负数(-1)。 但是0xffffffff是-1作为intbyte

因为int是有符号的,0xffffffff代表-1,而0xff代表值255的整数,它不在一个字节的-128(0x80)+127(0x7f)范围内。