我为自己编写了一个小型演示,以便更好地理解移位字节值。所以我的字节'd'的值为127:
class Demo {
public static void main (String args[]) {
byte d = 127; // 8-bit is equal to 0 111 1111
我尝试做的是将值向左移动到左边:
int e = d << 2; /* 32-bit shifted value is equal to 0 000 0000 0000 0000 0000 0001 1111 1100
0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6 + 1 * 2^7 + 1 * 2^8 =
0 * 1 + 0 * 2 + 1 * 4 + 1 * 8 + 1 * 16 + 1 * 32 + 1 * 64 + 1 * 128 + 1 * 256 =
0 + 0 + 4 + 8 + 16 + 32 + 64 + 128 + 256 = 508
*/
如果我的评论中的逻辑是正确的,请告诉我,因为这是我第一次做这样的事情。所以真正的问题是关于内存分配,一旦我尝试将'e'转换回byte:
byte f = (byte)(e); /* [] indicates 8-bit at 32-bit shifted value: 0 000 0000 0000 0000 0000 0001 [1111 1100]
0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6 - 1 * 2^7 =
0 * 1 + 0 * 2 + 1 * 4 + 1 * 8 + 1 * 16 + 1 * 32 + 1 * 64 - 1 * 128 =
0 + 0 + 4 + 8 + 16 + 32 + 64 - 128 = -4
*/
int g = (byte)(e);
}
}
字节'f'和int'g'都很完美,但我现在正在阅读的书建议我使用类似条件的int而不做任何解释,所以我担心的真实事情是'内存分配'。使用哪种类型或者一旦字节值移位并且内存扩展到32位是否真的重要,是不是可以将其减少到8位?
另外,我有一个奇怪的问题。如何查看任何值的真实“位数”?让我们说当我执行这样的事情时:
byte a = 10;
System.out.println(Integer.toBinaryString(a));
int b = 10;
System.out.println(Integer.toBinaryString(b));
两种情况下结果都是'1010'。但是,如果我得到正确的字节'a'使用8位内存而int'b'使用32.但是对于:
byte c = 5 << 1;
System.out.println(Integer.toBinaryString(c));
结果也是'1010',但现在它使用32位内存,而在计算表达式时,字节和短值被提升为int。我怎样才能真实地看到这一点并由我自己确保?
答案 0 :(得分:1)
我不完全确定您要执行的操作,但对于f
和g
的分配,两者都会给出相同的结果,因为您为其分配了(byte) e
它适合一个字节变量。
如果你在没有强制转换的情况下进行分配,你会得到不同的结果,因为e
的值太大而不适合一个字节。
对于toBinaryString
的结果,它们显然不显示前导零,这就是为什么你看到一个字节变量和一个保持相同值的int变量的相同结果。如果你想看到所有的位,你必须自己打印前导零,前导零的数量取决于变量的类型(因此,对于一个字节变量,你必须添加前导零到总共达到8位,对于int,你必须达到32位等等。)。
如果您想查看前导零,可以创建自己的toBinaryString
版本。查看Integer
的实施,我发现toBinaryString
调用toUnsignedString
:
public static String toBinaryString(int i) {
return toUnsignedString(i, 1);
}
private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32];
int charPos = 32;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = digits[i & mask];
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
如您所见,此方法仅返回表示int的二进制值的32
char
的一部分。如果您返回new String(buf)
,您将获得带有前导零的完整二进制字符串。