您的位置:首页 > 其它

(byte)129 = -127问题分析

2018-03-08 15:34 232 查看
今天看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    

=============================================================

下面进入正题, byte的溢出问题:

上面所提出的问题, 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如果有问题的可以用这个方法来检查你的结果是否正确。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息