无意间翻看之间的代码,发现了一段难以理解的代码。

     byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ;  

        for (int i = 0; i < bs.length; i++) {
int c = bs[i] & 0xFF ;
if(c < 16){
sb.append("0");
}
sb.append(Integer.toHexString(c)) ;
}
return sb.toString() ;

bs是由一段字符串经过MD5加密后,输出的byte数组。我起初难以理解为什么在接下来的循环中要将bs[i]&oxFF再复制给int类型呢?

bs[i]是8位二进制,0xFF转化成8位二进制就是11111111,那么bs[i]&0xFF不是还是bs[i]本身吗?有意思吗?

后来我又写了一个demo

package jvmProject;

public class Test {

    public static void main(String[] args) {
byte[] a = new byte[10];
a[0]= -127;
System.out.println(a[0]);
int c = a[0]&0xff;
System.out.println(c);
}
}

我先打印a[0],在打印a[0]&0xff后的值,本来我想结果应该都是-127.

但是结果真的是出人意料啊!

-127

129

到底是为什么呢?&0xff反而不对了。

楼主真的是不懂啊,后来往补码那个方向想了想。

记得在学计算机原理的时候,了解到计算机内的存储都是利用二进制的补码进行存储的。

复习一下,原码反码补码这三个概念

对于正数(00000001)原码来说,首位表示符号位,反码 补码都是本身

对于负数(100000001)原码来说,反码是对原码除了符号位之外作取反运算即(111111110),补码是对反码作+1运算即(111111111)

概念就这么简单。

当将-127赋值给a[0]时候,a[0]作为一个byte类型,其计算机存储的补码是10000001(8位)。

将a[0] 作为int类型向控制台输出的时候,jvm作了一个补位的处理,因为int类型是32位所以补位后的补码就是1111111111111111111111111 10000001(32位),这个32位二进制补码表示的也是-127.

发现没有,虽然byte->int计算机背后存储的二进制补码由10000001(8位)转化成了1111111111111111111111111 10000001(32位)很显然这两个补码表示的十进制数字依然是相同的。

但是我做byte->int的转化 所有时候都只是为了保持 十进制的一致性吗?

不一定吧?好比我们拿到的文件流转成byte数组,难道我们关心的是byte数组的十进制的值是多少吗?我们关心的是其背后二进制存储的补码吧

所以大家应该能猜到为什么byte类型的数字要&0xff再赋值给int类型,其本质原因就是想保持二进制补码的一致性。

当byte要转化为int的时候,高的24位必然会补1,这样,其二进制补码其实已经不一致了,&0xff可以将高的24位置为0,低8位保持原样。这样做的目的就是为了保证二进制数据的一致性。

当然拉,保证了二进制数据性的同时,如果二进制被当作byte和int来解读,其10进制的值必然是不同的,因为符号位位置已经发生了变化。

象例2中,int c = a[0]&0xff;  a[0]&0xff=1111111111111111111111111 10000001&11111111=000000000000000000000000 10000001 ,这个值算一下就是129,

所以c的输出的值就是129。有人问为什么上面的式子中a[0]不是8位而是32位,因为当系统检测到byte可能会转化成int或者说byte与int类型进行运算的时候,就会将byte的内存空间高位补1(也就是按符号位补位)扩充到32位,再参与运算。上面的0xff其实是int类型的字面量值,所以可以说byte与int进行运算。

byte为什么要与上0xff?的更多相关文章

  1. byte为什么要与上0xff(转)

    无意间翻看之间的代码,发现了一段难以理解的代码. byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ; ...

  2. [转]byte为什么要与上0xFF?

    无意间翻看之间的代码,发现了一段难以理解的代码. byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ; ...

  3. byte & 0xff char 转换

    https://blog.csdn.net/lixingtao0520/article/details/75450883 版权声明:本文为博主原创文章,转载请注明作者与出处,http://blog.c ...

  4. byte为什么要与0xff

    面对带正负号的数,会采用符号扩展,如果原值是正数,则高位补上0:如果原值是负数,高位补1.二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.当前的计算机系统使用的基本上是二 ...

  5. java byte&0xFF

    做串口端口通讯时,数据都是以byte类型发送的 普通的byte范围是-128-127,而java的byte范围是0-255 因此将数据的byte转成java的byte时,需要与0xff(1111111 ...

  6. [转]java中byte转换int时为何与0xff进行与运算

    在剖析该问题前请看如下代码public static String bytes2HexString(byte[] b) {  String ret = "";  for (int ...

  7. Java中byte与16进制字符串的互换原理

    我们都知道Java中的byte是由8个bit组成的,而16进制即16中状态,它是由4个bit来表示的,因为24=16.所以我们可以把一个byte转换成两个用16进制字符,即把高4位和低4位转换成相应的 ...

  8. byte ---> hex String

    public static String byte2HexString(byte[] b){ String ret = ""; ;i<b.lenght;i++){ Strin ...

  9. 从JDK源码角度看Byte

    Java的Byte类主要的作用就是对基本类型byte进行封装,提供了一些处理byte类型的方法,比如byte到String类型的转换方法或String类型到byte类型的转换方法,当然也包含与其他类型 ...

随机推荐

  1. 华为oj 购物单

    这两天断断续续敲完这个(放假的时候比较懒),一次成功有点小激动(●'◡'●)  不过貌似从第一次打开开始计时..... 这道题目很像01背包,我将附件与它们的主件绑定(就是link起来)然后套用动态规 ...

  2. Ruby 里的 %Q, %q, %W, %w, %x, %r, %s, %i (译)转

    原文地址  转自 %Q 用于替代双引号的字符串. 当你需要在字符串里放入很多引号时候, 可以直接用下面方法而不需要在引号前逐个添加反斜杠 (\") >> %Q(Joe said: ...

  3. 剑指Offer面试题:20.栈的压入、弹出序列

    一.题目:栈的压入.弹出序列 题目:输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1.2.3.4.5是某栈的压栈序列,序列4 ...

  4. OOAD利器之UML基础

    UML:Unified Modeling Language,即统一建模语言,简单地说就是一种有特殊用处的语言.本文是我初步学习UML的学习笔记,对于我们菜鸟码农来说,让我们做设计的可能性不大,但至少能 ...

  5. alias指令:设置命令别名

    alias: usage: alias [-p] [name[=value] ... ] 1. 语法    alias [参数][命令别名]=[原命令名称]   2. 功能介绍 该指令主要用于为原命令 ...

  6. Redux

    redux是Flux的一种实现方式,但还是和Flux有些不同. React控制视图层,要想做一个完整的数据流,必须要用react-redux. 官方demo,自己收集了一下: demo1http:// ...

  7. c#方法

    1.引用型参数: 关键字:ref 2.输出型参数 关键字:out 例: double area(out double p) { double t=3.14*10; p=2*t*3.14; return ...

  8. C++中static数据成员详解

        本文和大家分享的主要是c++中static数据成员的相关用法及源码示例,希望能帮助大家更好的学习C++. static(静态存储)数据成员 StaticTest.cpp : 定义控制台应用程序 ...

  9. Js添加消息提示数量

    接到个新需求,类似以下这种需求,得把它封装成一个插件 后端给返回一个这种数据 var data = [ { key:"020506", num:5 }, { key:"0 ...

  10. Sql Server系列:多表连接查询

    连接查询是关系数据中最主要的查询,包括内连接.外连接等.通过连接运算符可以实现多个表查询.内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值.SQL Server中的内连接有 ...