我试图在不使用int
基元类型的情况下实现存储32位数字的类。为此,我使用两个short
变量msbs
和lsbs
来存储数字的32位,每个变量中包含16位。
变量msbs
将存储数字的前16位,lsbs
变量将存储16位。
当涉及将给定字节保存到变量时,我应用下一个公式:(字节顺序以Little-Endian表示法给出)
输入 - > byte[] n = {0b00110101, -3, 0b1001, 0b0};
到数字0b00000000 00001001 11111101 00110101(654645)
msbs = ((n[3] << 8) | n[2]);
lsbs = ((n[1] << 8) | n[0]);
如下图所示
private void saveNumber(byte[] n) {
msbs = (byte)((n[3] << 8) | n[2]);
lsbs = (byte)((n[1] << 8) | n[0]);
System.out.println(Integer.toBinaryString((n[1] << 8) | n[0]));//Prints 11111111111111111111110100110101
System.out.println("msbs -> " + Integer.toBinaryString(msbs));
System.out.println("lsbs -> " + Integer.toBinaryString(lsbs));//Prints 110101
}
该行
System.out.println(Integer.toBinaryString((n[1] << 8) | n[0]));//Prints 11111111111111111111110100110101
完全打印出我需要的内容,尽管在开始时有大量无用的1位(我可以通过将其转换为short
来摆脱它)
但是,当我打印lsbs
我存储完全相同的值(显然)时,它输出110101时它应该是0b1111110100110101
为什么会出现这种情况?我理解它必须是Java在将值11111111111111111111110100110101
存储到16位原始类型时执行的“内部”转换(我个人认为不会发生因为我正在移位8位)在8位数字的左边,应该给我一个16位数字)
作为旁注,msbs
变量正在完成我想要它做的事情,所以问题应该与Java表示负数的方式有关
顺便说一下,我知道Java并不是最好用的语言。
答案 0 :(得分:4)
为什么会出现这种情况?
在Java中,所有按位操作都是32位或64位操作。这与其他一些语言不同,可能会出乎意料。但事实就是如此。
我明白它必须是&#34;内部&#34;由Java执行的演员......
Java并没有在你的任何一个例子 1 中进行隐式缩小演员表。事实上,我认为意外行为的原因是代码中明确的缩小范围:
msbs = (byte)((n[3] << 8) | n[2]);
您已明确地将((n[3] << 8) | n[2])
的32位值转换为byte
。根据您的期望,您应该投向short
。
除此之外:当你写这样的东西&#34;我个人认为这种情况发生了......&#34; 这意味着你怀疑是否正确Java编译器。事实上,在99.999%的情况下 2 ,真正的问题是有人不明白编译器应该对他们做什么;即他们对语言的了解太浅 3 。在大多数情况下,编程语言的规范说明精确特定构造的含义。在Java案例中,它是Java语言规范。
1 - 实际上我能想到的唯一情况是基本类型在内部缩小的位置在赋值运算符中。
2 - 我提出了这个数字,但重点是编译器错误很少是导致意外应用程序行为的原因。
3 - 或者它可能只是程序员错过的应用程序错误。疲倦会给大脑带来坏事......