short a =128; byte b =(byte) a;
源码的表示范围是 -(2^7 - 1)到 2^7 - 1 补码的表示范围是 -2^7 到 2^7 - 1 补码要多出一个数,而这个数就是你10000000 在源码里面00000000和100000000都是表示0 这样比较浪费,在补码里面,就把100000000当做 -2^7 ,以扩大补码表示范围 如果没有这个约定 1000 0000 (补码)->0111 1111(反码)->0000 0000(源码)应该是表示0的。
我想结合高票答案的解释,再补充一下下~
二进制表示:
int a = 128 00000000 00000000 10000000 00000000
short a = 128 00000000 10000000 (强转后前面 16 位被截断)
可以看出来,a 的值输出应该还是 128
那么对于 byte b = (byte) a;
二进制表示:
short a = 128 00000000 10000000
byte b = 128 10000000 (强转后前面 8 位被截断)
但是,输出的 b 的值为什么不是 128 而是 -128 呢
Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics)
byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
这是因为 byte 是一个 8 位有符号二进制补码整数,它包含的值的范围是 [-128, 127],因此 byte 类型的值是无法表示 128 的
那么在发生截断后,1000 0000 表示的就是一个补码,从这个补码可以看出来它的原码肯定是一个负数,那么我们根据这个补码反推得到它的反码:1111 1111,从而得到它的原码:1000 0000,可以看出这个值就是 -0,但是在我们的生活中是没有 -0 的,所以在计算机中就把它识别成 -128,因此这就是为什么 b 的值的输出是 -128 的原因。
ps: 关于 -0 对应于 -128 的具体解释,我懒得写了,因为感觉取决于个人的理解,不想细究,如果有人还有疑问,可以看看这个人的解释 byte类型取值范围为什么是127到-128? - 知乎