int,byte之间转换

基础知识

整形(int)

4个字节,占32位,1111,1111,1111,1111,1111,1111,1111,1111
整型int 其实不能说是去掉3个字节,只能说在读取数据的时候只读取了最低的一个字节里的数据而已,那另外的3个字节还在 ,只是没有读取里面的内容而已,因为高位都是0,可以不显示。
int转换成4个byte的时候,byte[4] b=b[0][1][2][3]需要移位,从1个字节开始移位。

字节(byte)

1个字节,占8位,1111,1111
byte的数据范围:-128-127,255+符号位=256长度。

  • byte转换成int,需要左移(数据范围低->数据范围大,发生自动类型转换)。
  • int转换成byte,需要右移。

    位移

    左移

    <<低位补0,相当于×2的n次方。

    右移

    >>高位补0,相当于/2的n次方

    补码反码

    Java的2进制采用的是补码形式。包括:2进制转10进制,10进制转2进制。
    第1位表示符号位,符号位是负数情况,按补码进行存取。
    负数都是按照补码形式表示。补码=反码+1。
    反码=原码除了符号位之外,进行按位取反。

    正数

    原码,反码,补码都相同

    负数

    原码=源码,反码=除了第一个符号位为1,其他全部按位取反,补码=反码+1

    int在byte[]

    byte[]图解

    “一”表示一个字节,即 8位:一,一,一,一
  • 下标0:从32位右移24位,>>24,在下标3的位置,需要把高位清空为0,用&,即&0x0000ff;以此类推。
  • 下标1:>>160x00ff0xff=f表示4位二进制数,f=1111
  • 下标2:>>80xff
  • 下标3:不移动,也不需要清空0。
    1
    2
    3
    [0]  [1]  [2]  [3] 表示 index
    一, 一, 一, 一
    [0] [1] [2] [3]

1个intbyte表示[0][1][2][3],1个byte占8位,一个int占32位,一个int[]代表一个byte大小。

1
2
3
4
value%256            b[3]
value/256%256 b[2] //表示,除以256是b[3]的256,%是获取b[2]的值
value/65536%256 b[1]
value/16777216%256 b[0]----》256*256*256

int有正负数,所以要消除符号位(&256),负数的符号位补码影响。256=$2^8$ = 1111,1111,每位都可以表示:0,1;所以1111,1111 = $2^8$。

1
2
3
4
5
6
7
8
9
value%256            b[3]           //取余是b[3]的值
value/256%256 b[2] //除以256是b[3]的256,是获取b[3]的值,%是获取b[2]的值
value/65536%256 b[1] //256*256,这里的256是,b[3],b[2]的2个256,扣除b[3],b[2]的2个256,b[1]的值是取余的获得
value/16777216%256 b[0] //256*256*256==[3],[2],[1]的256 

value&255 b[3] //&255表示清除值是负数,高位是1,java2进制按照补码取值.0&1=0;低位8个11,高位24个0.
(value&255)>>8 b[2]
(value&255)>>16 b[1]
(value&255)>>24 b[0]

b[0][1][2][3]多维素组

1
2
3
4
5
b[0][1][2][3]  
b[0]:2563次方 11111111111111111111111111111111
b[1]:2562次方 //[1],[2],[3]
b[2]:2561次方 //[2],[3]
b[3]:2560次方 //[3]

int->byte

例子1

转换成 byte[] b

1
int a=270

因为byte占256长度,超出256长度,则溢出,向高位进1,a = 270 = b[1][14]
b每1维占256长度,超过进1位。

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
int a = 2;
byte[] b = new byte[4];
b[0] = (byte) (a >> 24); //第一个字节
b[1] = (byte) (a >> 16); //第二个字节
b[2] = (byte) (a >> 8); //第三个字节
b[3] = (byte) (a); //第四个字节
System.out.println(b[0] + "" + b[1] + "" + b[2] + "" + b[3]);
}

1
0002

例子2

(int类型)156转byte是-100。
156=10011100最高位为符号位,而11100=28 故为-28,结果为10011100(此时,第一位符号位为1,为负),由于负数按补码存储,所以转换为byte之后的真值为反码=11100101,补码=11100100(进1位),然后加上-1(符号位是-1),即-100。

例子3

1
2
3
4
5
6
7
public static void main(String[] args) {
// 95+46=141
int c1 = 46;
int c2 = 95;
byte c3 = (byte) (c1 + c2);
System.out.println("c3=" + c3);
}
  • 95+46=141
  • (00000000 00000000 00000000)10001101
  • 负数,按补码的方式存10001101的补码11110010
  • 64 +32+ 16 +2=(-)114 //补码的方式进行,负号还是要保留
  • 符号位占一位,-114-1 = -115

    byte->int

    0xFF

    byte[]转化十六进制的字符串,注意这里b[i] & 0xFF将一个byte0xFF进行了与运算,然后使用Integer.toHexString取得了十六进制字符串,可以看出b[i] & 0xFF运算后得出的仍然是个int,那么为何要和0xFF进行与运算呢?直接Integer.toHexString(b[i]);将byte强转为int不行吗?答案是不行的。
  • byte的大小为8bits,int的大小为32bits
  • Java的二进制采用的是补码形式(正数:源码,反码,补码相同。负数:源码。反码除了符号位,其余相反。补码是反码+1)
  • 0xFF = 1111,1111;因为前3个字节不读取,只是读取最后一个字节,所以可以看成1111,1111;但是实际上还是 00000000,00000000,00000000,1111,1111。这样就可以消除因为负数符号位,补码的时候按位取反,高位是1的情况,&实际上是为了消除1。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public static String bytes2HexString(byte[] b) {
    String ret = "";
    for (int i = 0; i < b.length; i++) {
    String hex = Integer.toHexString(b[i] & 0xFF);
    if (hex.length() == 1) {
    hex = '0' + hex;
    }
    ret += hex.toUpperCase();
    }
    return ret;
    }

例子1

没有&255

1
2
3
4
5
6
public static void main(String[] args) {
byte b=-1;
int a=b;
String c=Integer.toBinaryString(a);
System.out.println(c);
}

1
11111111111111111111111111111111

&255

1
2
3
4
5
6
public static void main(String[] args) {
byte b = -1;
int a = b & 255; //1
String c = Integer.toBinaryString(a);
System.out.println(c);
}

1
11111111

代码标注

  1. 255=0xff=1111,1111=0000,0000,0000,0000,1111,1111;通过&运算进行,前24位被清1。

Java中的一个byte,其范围是-128~127的,而Integer.toHexString的参数本来是int,如果不进行&0xff,那么当一个byte会转换成int时,对于负数,会做位扩展(因为负数是取补码,按位取反,&0xff是为了负数),举例来说,一个byte的-1(即0xff),会被转换成int的-1(即0xffffffff),那么转化出的结果就不是正确。而0xff默认是整形,所以,一个byte0xff相与会先将那个byte转化成整形运算(32位),这样,结果中的高的24个byte就总会被清1。

例子2

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
int a = 2;
byte[] b = new byte[4];
b[0] = (byte) (a >> 24); // 第一个字节
b[1] = (byte) (a >> 16); // 第二个字节
b[2] = (byte) (a >> 8); // 第三个字节
b[3] = (byte) (a); // 第四个字节
System.out.println(b[0] + "" + b[1] + "" + b[2] + "" + b[3]);
//byte->int
System.out.println(((b[0] & 0x000000ff) << 24) | ((b[1] & 0x000000ff) << 16) | ((b[2] & 0x000000ff) << 8) | (b[3] & 0x000000ff));
}
1
2
0002
2

&255(0x000000ff)

消除符号位,比如负数的情况,要按照补码取值,补码是反码+1。这里有可能b是负数,高位按照补码进行存取会是1111,1111...,所以要消除1。

# Java

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×