Skip to content

Java 解惑 -05:十六进制的趣事

🏷️ 《Java 解惑》

java
System.out.println(Long.toHexString(0x100000000L + 0xcafebabe)); // print cafebabe

这段代码并不会打印 1cafebabe ,实际的打印结果没有前面的 1

前面的 1 哪里去了?

这个问题的根源在于使用十六进制的字面量表示法表示数值时,其正负是由最前一位来决定的。

0xcafebabe 是一个 int 型的负数,其实际值为 -889275714

java
System.out.println(0xcafebabe); // print -889275714

在和 long 数值进行加法计算时,会自动提升为 long 型,此时其值为 oxffffffffcafebabe

java
System.out.println(Long.toHexString(0xcafebabe)); // print ffffffffcafebabe
System.out.println(0xffffffffcafebabeL); // print -889275714

至于为什么提升为 long 前面补的不是 0 而是 1 ,这个是因为负数是通过补码的方式表示的。

java
System.out.println(0xffffffffffffffffL); // print -1
System.out.println(01777777777777777777777L); // print -1

0x100000000L + 0xcafebabe 实际的计算过程如下:

bash
  ffffffffcafebabe
+ 0000000100000000
------------------
 100000000cafebabe

最高位(第 65 位)的 1 已经超出了 long 型长度,会被忽略掉,所以结果就变成了 0x00000000cafebabe

如果要打印想定的结果: 1cafebabe ,只需将后面的字面量也定义为 long 型就可以了。

java
System.out.println(Long.toHexString(0x100000000L + 0xcafebabeL)); // print 1cafebabe

此时没有 intlong 型的扩展提升,其实际的计算过程如下:

bash
  00000000cafebabe
+ 0000000100000000
------------------
  00000001cafebabe