java 0x_谈谈java中& 0xFF

上篇文章写了在java中常用的操作运算符,其内容很基础,大多数开发的时候可能只会用到移位算法,而与或非操作则通常会有其他使用方式,比如我在看《How Tomcat Works》解析http请求头文件时使用了 &0xFF,其实我是有些懵b的,我不能直观的一下感受到这样的操作结果是要做什么,于是便有了上篇文章做基础,这篇文章来写 & 0xFF是怎么回事。

在java的计算领域中,使用三种进制来存储和处理数值,分别是二进制、十进制、十六进制,其中二进制是隐式方式处理,没有哪种数据类型是使用bit二进制来直接表示的,也没有一种数据类型可以直观的记录一个二进制,所以我自己将其成为隐式的。十进制是我们日常生活用常用的数字表达形式,常用int、long 等类型表示整型,float、double表示浮点数等,接下来说说十六进制

十六进制是平时开发不太常用的一种进制形式,使用0x为开头表示,比如Integer的最大值是使用

public static final int   MAX_VALUE = 0x7fffffff;

这种形式来表示,而不是MAX_VALUE = 2147483647,虽然长度看起来差不多。。。但如果熟悉了十六进制就可以直观的看出这一段表示的意思

现在来说说进制到底是怎么处理的

二进制:满2进1,当前位置0,比如0+1等于1不够2,则还是显示1,如果再加1得2那么应该显示为进1,就是高位加1,当前位置0,就是{1 0}=十进制2

十进制:满10进1,当前位置0,与上面差不多,1+1是2不够10则不进位,当加到9时,再加1构成十,高位加(进)1,当前置0就变成了10,达到19的时候再加1时,高位加(进)1,当前位置0就变成了20

十六进制:满16进1,当前位置0,同样1+1是2,不够16不进位,当达到15时再加1时是16,满16就需要进位了,高位加1,当前位置0,就是10。。。那么问题是 9+1的10 和15+1的10没法区分,然后科学家们就想了办法,用几个英文字母替代10及之后的数值,直到15,下面是十六进制与10进制对照

十进制   : 0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15

十六进制:0  1  2  3  4  5  6  7  8  9   A    B    C    D    E    F

继续深入对比

16               18                  32                100                  127            190                  255

(1*16+0)10   (1*16+2)12  (2*16+0)20   (6*16+4)64  (7*16+15)7F  (11*16+14)BE  (15*16+15)FF

在java 代码中,写16进制时需使用0x作为前缀,比如int i = 0xF(15)、int i=0x11(17)、

int i=0xFF(255)。

本篇的主角出现了,其中一个 0xFF。另一个主角是&(与运算符)。上篇有介绍&是位运算符,属于二进制的运算符, i(int)  & 0xFF,这就有意思了 i(10进制) &(二进制运算符) 0xFF(十六进制),实际到了计算层面的时候无论十进制、十六进制都会转为2进制进行计算,现在我们来看十六进制与二进制的对比

2的n次方      2^1 ...  2^3-1    2^3        2^4-1        2^4            2^5-1          2^5           2^6-1         2^6

十进制    :   2         7             8            15              16               31                32             63               64

十六进制  :    2         7             8             F               10               1F                20             3F               40

二进制   : {10}    {111}    {1000}    {1111}     {1 0000}   {1 1111}    {10 0000}  {11 1111}   {100 0000}

2^7-1              2^7                   2^8-1                 2^8             ......     2^31-1              2^31

127                  128                   255                      256                       2147483647      -2147483648

7F                    80                      FF                       100                       7FFFFFFF           80000000

{111 1111}    {1000 0000}      {1111 1111}    {1 0000 0000}   {0 后边31个1}     {1后边31个1}

最后写的2的31次方为何为负数,是因为本段对比均以java int值作为运算范围,是有运算符号的,最大范围为32位,最左边的称为高位,是运算符号。

0xFF可以直观的看到对应的二进制是{1111 1111},因为int类型是32位,在进行&运算时,需要补全0才可以运算,根据上篇的(与运算口诀,一 一得一,其他为0)来试一下999& 0xFF

0000 0000  0000 0000  0000 0011  1110 0111        = 999

&

0000 0000  0000 0000  0000 0000  1111 1111        = 0xFF = 255

---------------------------------------------------------------------

0000 0000  0000 0000  0000 0000  1110 0111        = 231

再算一个66 & 0xFF

0000 0000  0000 0000  0000 0000  0100 0010        = 66

&

0000 0000  0000 0000  0000 0000  1111 1111        = 0xFF = 255

---------------------------------------------------------------------

0000 0000  0000 0000  0000 0000  0100 0010       = 66

再来一个负数的,-1024 & 0xFF

1111 1111  1111 1111  1111 1100  0000 0000        =-1024

&

0000 0000  0000 0000  0000 0000  1111 1111        = 0xFF = 255

---------------------------------------------------------------------

0000 0000  0000 0000  0000 0000  00000000       = 0

再来一个负数的,-200 & 0xFF

1111 1111  1111 1111  1111 1111  0011 1000        =-200

&

0000 0000  0000 0000  0000 0000  1111 1111        = 0xFF = 255

---------------------------------------------------------------------

0000 0000  0000 0000  0000 0000  0011 1000       = 56

从以上几个例子可以看出 & 0xFF就像一把剪刀,首先把符号位变成了正符号0,然后剪掉 3个8位留最后一段8位,用行业术语叫高位、低位,使用-200举例高位低位

1111 1111  1111 1111  1111 1111  0011 1000        =-200

\_________高位________/   \_________低位_______/

再啰嗦几句,最左边1位表示符号位时,从左向右是从高位向低位,这种叫做大端模式,有大端就有小端模式,深入了解大小端可去百科传送门

既然像一把剪刀,这把剪刀能干什么,我们来实战演练一下

int类型数值,-3434343,然后进行向右移位操作,试试看-3434343 >> 24

1111 1111  1100 1011  1001 1000  1001 1001

[{1111 1111  1111 1111  1111 1111} 1111 1111]  1100 1011  1001 1000  1001 1001

上篇文章我们有说,带符号右移,负数右移移动多少位就在左边补多少个1,操作后我们最后得到的值是[]内的,右边的都向右溢出舍去,我们将结果再进行 & 0xFF操作,

1111 1111  1111 1111  1111 11111111 1111

&

0000 0000  0000 0000  0000 0000  1111 1111        = 0xFF = 255

---------------------------------------------------------------------

0000 0000  0000 0000  0000 0000  1111 1111        = 255

同样的方式我们右移16位 8位 和直接& 0xFF看到什么结果

1111 1111  1100 1011     1001 1000  1001 1001

[{1111 1111  1111 1111}   1111 1111  1100 1011]  1001 1000  1001 1001(红色部分补位)

1111 1111  1111 11111111 1111  1100 1011

&

0000 0000  0000 0000  0000 0000  1100 1011        = 0xFF = 255

---------------------------------------------------------------------

0000 0000  0000 0000  0000 0000  1100 1011        = 203

..........以下雷同结果分别是

0000 0000  0000 0000  0000 0000  1001 1000        = 152

0000 0000  0000 0000  0000 0000  1001 1001        = 153

结果组装

int 255 = (byte) -1

int 203 = (byte)  -53

int 152 = (byte) -104

int 153 = (byte) -103

那么 -3434343转为byte数组则是 byte [] result = { -1, -53, -104, -103 }

容我再bb两句: -3434343和他的二进制小伙伴(还是上面灰色背景那段)

1111 1111         1100 1011             1001 1000             1001 1001         = -3434343

\___-1(255)____/   \_-53(203)___/    \__-104(152)___/   \___-103(153)____/

是不是瞬间觉得nb了,这4段指的就是java中int占4byte(字节),想取出哪段的值就把他移动到最右边8位的位置,然后用 & 0xFF 剪掉前面0,留下最后8位的值,就得到想取出段的int值了(谁tm发明的,太nb了),(天空中传来小伙伴说为什么不substring ,靠!这个二进制,没提供那功能)

在网上可以找到很多int转byte的代码,但是自己观察好他的最后byte顺序,有的是反的,我不敢保证我的顺序正确,但我敢保证我处理结果与java内置的处理结果(代码在下边)相同,伙伴自己仔细甄别

ByteArrayOutputStream boutput = new ByteArrayOutputStream();

DataOutputStream doutput = new DataOutputStream(boutput);

try {

doutput.writeInt(i);

} catch (IOException e) {

e.printStackTrace();

}

byte[] buf = boutput.toByteArray();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值