(byte)129 = -127问题分析

今天看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

如果有问题的可以用这个方法来检查你的结果是否正确。

            
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页