Java 应用于字节变量的无符号右移行为

Java 应用于字节变量的无符号右移行为,java,bit-shift,Java,Bit Shift,考虑以下java代码片段 byte b=(byte) 0xf1; byte c=(byte)(b>>4); byte d=(byte) (b>>>4); 输出: c=0xff d=0xff 预期产出: c=0x0f 怎么做? 二进制形式的b1111 0001 在无符号右移之后0000 1111因此0x0f但是为什么0xff如何?我猜b在移位之前是符号扩展到int 因此,这可能会像预期的那样起作用: (byte)((0x000000FF & b)>

考虑以下java代码片段

byte b=(byte) 0xf1;
byte c=(byte)(b>>4);
byte d=(byte) (b>>>4);
输出:

c=0xff
d=0xff
预期产出:

c=0x0f
怎么做? 二进制形式的b
1111 0001

在无符号右移之后
0000 1111
因此
0x0f
但是为什么
0xff
如何?

我猜
b
在移位之前是符号扩展到
int

因此,这可能会像预期的那样起作用:

(byte)((0x000000FF & b)>>4)
根据:

无符号右移运算符“>>>”将零移到最左侧位置,而“>>”之后的最左侧位置取决于符号扩展


因此,使用
b>>4
可以将
11110001
转换为
1111111
(b为负数,因此它附加
1
),即
0xff

,问题是在移位操作发生之前,所有参数都首先提升为
int

byte b = (byte) 0xf1;
b
是有符号的,因此其值为-15

byte c = (byte) (b >> 4);
b
首先扩展到整数
-15=0xFFFFF1
,然后右移到
0xFFFFFF
,并通过转换到
字节
而截断到
0xff

byte d = (byte) (b >>> 4);
b
首先扩展到整数
-15=0xFFFFF1
,然后右移到
0x0fffffff
,并通过转换到
字节
截断为
0xff

byte d = (byte) (b >>> 4);

您可以执行
(b&0xff)>>4
以获得所需的效果。

Java试图通过定义两个不同的移位运算符来略过对无符号基本类型的显式支持

问题讨论的是无符号右移,但示例同时讨论(有符号和无符号),并显示有符号右移的值(>>)


您的计算将适用于无符号移位(>>)

字节操作数在移位之前提升为int

对每个操作数分别执行一元数字提升(§5.6.1)。(不在操作数上执行二进制数字提升(§5.6.2)

否则,如果操作数是编译时类型byte、short或char,则通过扩大原语转换(§5.1.2)将其提升为int类型的值

字节b=(字节)0xf1

如果(b>1)和(字节)(0x7F))>>3)

否则

d=(字节)(b>>>4)

首先,检查值: 如果该值为负。右移一次,然后&0x7F,它将变为正值。然后,您可以轻松完成右移(4-1=3)的其余部分


如果该值为正值,则使用>>4或>>4进行右移。它在结果上没有区别,也没有右移的问题。

也许字节是第一个符号扩展到的int@PPJava中没有无符号数字不是问题(整数除法除外,这最终将在JDK 8中解决):