今天看Integer类源代码的时候,看到他有这样一个方法byteValue(),实现如下:
/**
* Returns the value of this {@code Integer} as a {@code byte}
* after a narrowing primitive conversion.
* @jls 5.1.3 Narrowing Primitive Conversions
*/
public byte byteValue() {
return (byte)value;
}
于是我顺手调用了这个方法
public static void testXvalue(){
Integer inte = new Integer(22222);
byte b =inte.byteValue();
结果得到的值是:b = -50 ???? 额,怎么回事? 原来是溢出了。
byte:1个字节, 8个bit位, 值范围 -128 ~ 127 (-2^7 ~ 2^7-1)。
int : 4个字节, 32个bit位 取值范围 -2^31 ~ 2^31-1
所以, 在进行类型转换的时候,当值超过127 时, byte就承受不了,开始溢出。(这种情况多发生在大转小的时候)
int 的完整二进制表示法:
00000000 00000000 00000000 00000000;
例如 int = 7; 00000000 00000000 00000000 00000111;
btye的完整二进制表示法:
00000000
例如:byte= 7; 00000111;
有人可能会有疑问,这两个不是一样吗???? 不不不, 不要忽略int的 后面的 那三个字节。因为:
byte : 10000111 , 就变成了负数。而
int : 00000000 00000000 00000000 10000111 ; 还是一个正数。
二进制表示数值时, 他的最后一位并不参与数值的存储, 而仅仅用来表示符号(+或 -)即 正 ,反。
额, 最后一位是在左边哦,不要问我为什么。 规定。
例如: int : 10000000 00000000 00000000 10000111; 表示的就是一个负数。
byte :10000111 ; 也是个负数。
那么这个呢: 10001111 ???? 不好说, 不知道他是表示几个字节的数值, 如果是byte 就是负数, 是int,short, 就是正数。
一个口诀: 负数 = 正数取反+1
这个口诀涉及3个二进制专有名词: 原码,反码, 补码。
原码: 某个数值的二进制表达式。
例如 1 : 00000000 00000000 00000000 00000001
反码: 二进制表达式,除了最后一个符号位外,其他的取反(1变0, 0变1)后的结果。
例如 上面取反:01111111 11111111 11111111 11111110
补码: 取反后的表达式(反码) +1 的结果。
例如 上面取反:01111111 11111111 11111111 11111110
+1
-------------------------------------------------------
结果: 01111111 11111111 11111111 11111111
那么,进过如上三步后的结果: 01111111 11111111 11111111 11111111, 是不是就是 -1 , 的二进制表达式呢?
错,错,错, 还差一步, 你的符号位没有换,上面说过了 1----表示负数, 0------表示正数。
最后结果 : 11111111 11111111 11111111 11111111
=============================================================
上面所提出的问题, int a = 22222, byte(a), 会溢出问题。
int a=22222 : 01010110 11001110 ;( 后面的0 我就不补了)
转换成byte : 11001110 ; 因为byte只有一个字节,所以 01010110 这段二进制码是不属于byte的。 也叫溢出了。
好了, 最后的到的 byte(a) : 11001110; 一看就是负数。 计算他的值。
结果 : 11001110
补码 : -1
11001101
反码: 10110010
原码 : 00110010 结果 50的 负数 -50.
------------------------------------------------------------------------------------------------
感觉用 减1, 好像很容易混,我试了一下, 正三步走也是正确的结果
反码 补码+1 取正
11001110 --------> 10110001 ----------> 10110010 --------> 00110010 结果还是-50
另外: Integer 类提供了一个 获取二进制码的方法:
System.out.println(Integer.toBinaryString(22222));
//结果 101011011001110
System.out.println((byte)22222);
//结果 -50
如果有问题的可以用这个方法来检查你的结果是否正确。