K_K*_*K_K 3 java binary byte bit-shift bitwise-operators
我知道这>>>
是无符号右移,并且由于byte
在 Java 中是有符号的 8 位,因此 -1 将表示为1111 1111
。结果,对于下面的代码:
byte b = (byte) -1;
b >>>= 1;
System.out.println(b);
Run Code Online (Sandbox Code Playgroud)
它不应该打印127
(二进制的0111 1111)吗?-1
但无论我执行多少次(例如在循环中),>>>
我b
得到的结果始终是。
任何人都可以解释为什么以及以什么方式我可以获得我期望的结果(即执行无符号右移,其中-1
右移一次等于Java中的127
a byte
)?我的理解有错吗?多谢!
rzw*_*oot 10
您遇到了一系列非常奇怪的 Java 设计选择,这些选择使这段代码“撒谎”(它似乎做了一件事,但实际上不会做那件事)。让我们来分解一下:
byte
、short
、char
和boolean
较差在java中,byte
, short
, char
,boolean
是下级原语,int
, long
,double
和float
是上级原语。除了数组存储和数组加载之外,没有其他操作码。java中没有将2个字节加在一起的操作码。它只是不存在。。javac
鉴于不知道要生成什么,因此实际上不可能做到这一点。所以与其:
byte b = 5;
byte c = 10;
byte d = b + c;
Run Code Online (Sandbox Code Playgroud)
实际上的意思是:
byte b = 5;
byte c = 10;
byte d = (int) b + (int) c;
Run Code Online (Sandbox Code Playgroud)
因此,这是一个编译器错误 - int + int
is的结果int
,并且在没有显式转换的情况下不允许尝试将 an 分配int
给 a 。byte
您可以轻松地查看任何Java 字节码列表。您将找到 FADD、DADD、IADD 和 LADD(分别为“浮点加法”、“双倍加法”、“整数加法”和“长加法”)。但你找不到 byte/short/char 变体;没有 BADD、CADD 或 SADD。
这:a += b;
实际上根本不一样a = a + b;
!我知道你是这么教的,但这是不正确的。事实上,它等于a = (byte) (a + b);
它本身byte
的类型a
:
double d = 5.5;
int x = 5;
x = x + d; // obviously, compiler error. Explicit cast needed.
Run Code Online (Sandbox Code Playgroud)
相对:
double d = 5.5;
int x = 5;
x += d;
Run Code Online (Sandbox Code Playgroud)
完全合法。结果 x 为 10。完整流程为:
double
因为 java 只能在相同类型的两个事物之间进行数学运算。d
是5.5,已经是双倍了,不错。DADD
字节码被执行;结果是 10.5。int
,导致10
,被分配给x
。javap
如果你想看到这个就跑吧。
因此,让我们分解您的代码:
byte b = (byte) -1;
Run Code Online (Sandbox Code Playgroud)
这使得 int -1(32 个“1”位),然后将其转换为 byte,从而b
得到值1111 1111
。到目前为止,一切都很好,没有什么令人惊讶的。
b >>>= 1;
Run Code Online (Sandbox Code Playgroud)
呼男孩。这看起来很简单,但是却非常复杂。它的语法糖用于:
b = (byte) (((int) b) >>> 1);
Run Code Online (Sandbox Code Playgroud)
分解一下:
(int) b
结果为 32 个 1 位。b
以字节为单位为 -1,将其转换为 int 会产生 -1 int,即 32 个 1 位。>>> 1
然后将其设为 0,后跟 31 个 1 位。byte
基本上不要使用。除非在以下情况下,否则不要使用劣质基元:
byte[]
很有用,而且每个项目实际上只占用 1 个字节。对于所有其他事情(例如单个字段和针对数学的局部变量,例如您正在做的事情),不要. 正如您在这里发现的那样,他们的行为并不像您想象的那样。
只需使用整数即可。如果您想要一个“无符号字节”,只需创建一个int
变量并使用它:
byte b = (byte) -1;
int x = b & 0xFF; // x is now 0000...0000 1111 1111.
System.out.println(x); // prints 255
x >>= 1;
System.out.println(x); // prints 127
Run Code Online (Sandbox Code Playgroud)
byte
作为一个单一值(不仅仅是byte[]
)byte
,在任何方面都不比64 位架构上的效率更高int
,甚至可能更高效。long
Java 不会分配更少的内存(因为所有东西都必须在字边界上对齐),操作也不会更快(CPU 已经在 64 位块中工作)。