查看下面的代码:

public class ByteTest {
    public static void main(String[] args) {
        byte a = 1;
        byte b = 2;
        a = 1+b;
//        a+=b;
    }
}

 

iOS Byte相加_补码

发现抱错,编译器提示你提供了一个int类型的数据,但是你需要的是一个byte类型的。

原因是:byte和short类型的数据,在进行计算的时候,会自动提升数据类型为int,所以等号右边的结果类型是int,需要强转为byte类型。

在来看看第7行代码的结果:

iOS Byte相加_包装类_02

编译器正常且结果也正确,是因为“+=”,“++”等等操作符并没有自动类型提升

再来看看下面代码的计算结果:

iOS Byte相加_补码_03

计算结果出乎我们的意料,为什么byte的127加1变成了-128呢?

我们知道,基本数据类型的取值范围如下:

类型

字节长度 

 取值范围

int

 4字节

 -2 147 483 648 ~ 2 147 483 647

short

2字节 

 -32 768 ~ 32 767

long 

8字节 

-9 223 372 036 854 775 808 ~ 9 223 372 036 854 775 807

byte 

1字节 

 -128 ~ 127

float

4字节

大约±3.402 823 47E+38F(6~7位有效数字)

double 

8字节 

大约±1.797 693 134 862 315 70E+308(15位有效数字) 

byte的最大值是127,下面是Byte包装类的部分源码:

public final class Byte extends Number implements Comparable<Byte> {

  
    public static final byte   MIN_VALUE = -128;

    public static final byte   MAX_VALUE = 127;

   
    @SuppressWarnings("unchecked")
    public static final Class<Byte>     TYPE = (Class<Byte>) Class.getPrimitiveClass("byte");

    public static String toString(byte b) {
        return Integer.toString((int)b, 10);
    }

    private static class ByteCache {
        private ByteCache(){}

        static final Byte cache[] = new Byte[-(-128) + 127 + 1];

        static {
            for(int i = 0; i < cache.length; i++)
                cache[i] = new Byte((byte)(i - 128));
        }
    }
    public static Byte valueOf(byte b) {
        final int offset = 128;
        return ByteCache.cache[(int)b + offset];
    }
......

此包装类里面在内里面维护了一个私有的静态内部类,缓存了-128到127直接的byte对应的包装类型,通过value of这个静态方法将结果返回,此时我们取得时候同一个byte值对应的包装对象就全部是一样的。

看下面的代码就知道缓存的作用了:

public class Test {
    public static void main(String[] args)  {
        Integer i1 = 100;
        Integer i2 = 100;
        Integer i3 = 200;
        Integer i4 = 200;
        System.out.println(i1 == i2); //true
        System.out.println(i3 == i4); //false
    }
}

int里面也缓存了从-128到127之间的值,不创建对象,之间使用赋值的方式,100会之间使用缓存里面的值,所以"=="比较的地址值相同,而200超过了缓存范围,会之间使用创建对象的方式进行输出,地址值不相等,所以是false.

下面解释为什么结果是-128:

大家知道,byte类型对应1个字节,也就是8个位,最左边的是符号位,在二进制里面127是01111111,如果还想给127加一的话,结果0111 111变为1000 0000。计算机中存储负数,存的是补码的形式。左边第一位 为符号位。

 java中负数的补码转换成十进制如下:

一个数如果为正,则它的原码、反码、补码相同;一个正数的补码,将其转化为十进制,可以直接转换。

已知一个负数的补码,将其转换为十进制数,步骤:

      1、先对各位取反;

      2、将其转换为十进制数;

      3、加上负号,再减去1。
按照上面的步骤:1000 0000的结果为,第一步:0111 1111,第二步:127,第三步:-127-1 = -128,也就是最终的结果了。