在编程语言中,存在不同的数据类型,C#和JAVA共同的拥有byte这种类型,不过同样叫byte,存储的时候却有细微差别的。JAVA语言中,是没有unsigned,每个数据类型的高位都是符号位,0表示整数,1表示负数。当超过当前数据类型的数字时,计算机会采用一种补码的方式来存储。
同样是128,java中的byte占一个字节空间,最高位是符号位,剩余7位能表示0-127,加上符号位的正负,就是-127至+127。byte整数无法存储,转为补码,就用负零表示-128(即原码1000,0000)。(计算机转补码后存储)
比较有意思的是,当byte转为short,int这种较大范围,能够存储128的数值时,打印出来还是-128.
这里涉及到小类型转大类型时的补位操作。
既然值没有改变,可以猜测,高位补位扩展转为大类型时是补零,高位保留了原有符号。
128 ->byte = -128 二进制 1000 0000 ->short 二进制 1000 0000 1000 0000 = -128
->int 二进制 1000 0000 0000 0000 0000 0000 1000 0000 = -128
那要怎样才能保证byte存储的128,转成int,short的值也应该是128了?java源码这样写道:
我们发现了一个有趣的地方,byte & 0xFF。根据计算机常识
1000 0000 0000 0000 0000 0000 1000 0000 & 1111 1111 = 0000 0000 0000 0000 0000 0000 1000 0000 = 128
这里0xFF是强制去掉了补位操作的高位的符号位。
那如果我们本来就是存进去的就是一个负数呢?转成int的时候又会怎么样?
-2 & 0xFF发生了什么?
总所周知,计算机保存负数是保存数的反码。
-2 源码 1000 0010 反码 1111 1101 补码 1111 1110
-2 & 0xFF 1111 1110 & 1111 1111 = 1111 1110 = 254
如果不&上0xFF自动扩展,保留符号
(byte)-2 1111 1110 转int 1111 1111 1111 1111 1111 1111 0111 1110 = -2