byte为什么要与上0xff(转)
无意间翻看之间的代码,发现了一段难以理解的代码。

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位,再参与运算。
其实是从数字类型扩展到较宽的类型时,补零扩展还是补符号位扩展。
这是因为Java中只有有符号数,当byte扩展到short, int时,即正数都一样,因为为符号位是0,所以无论如何都是补零扩展;但负数补零扩展和按符号位扩展结果完全不同。
补符号数,原数值不变。
补零时,相当于把有符号数看成无符号数,比如-127 = 0x81,看成无符号数就是129, 256 + (- 127)
对于有符号数,从小扩展大时,需要用&0xff这样方式来确保是按补零扩展。
而从大向小处理,符号位自动无效,所以不用处理。
让我理解更深了,也就是说在byte向int扩展的时候,自动转型是按符号位扩展的,这样子能保证十进制的数值不会变化,而&0xff是补0扩展的,这样子能保证二进制存储的一致性,但是十进制数值已经发生变化了。也就是说按符号位扩展能保证十进制数值不变,补0扩展能保证二进制存储不会变。而正数可以说是既按符号位扩展,又是补0扩展,所以在二进制存储和十进制数值上都能保证一致。
http://www.cnblogs.com/think-in-java/p/5527389.html
byte为什么要与上0xff(转)的更多相关文章
- byte为什么要与上0xff?
无意间翻看之间的代码,发现了一段难以理解的代码. byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ; ...
- [转]byte为什么要与上0xFF?
无意间翻看之间的代码,发现了一段难以理解的代码. byte[] bs = digest.digest(origin.getBytes(Charset.forName(charsetName))) ; ...
- byte & 0xff char 转换
https://blog.csdn.net/lixingtao0520/article/details/75450883 版权声明:本文为博主原创文章,转载请注明作者与出处,http://blog.c ...
- byte为什么要与0xff
面对带正负号的数,会采用符号扩展,如果原值是正数,则高位补上0:如果原值是负数,高位补1.二进制是计算技术中广泛采用的一种数制.二进制数据是用0和1两个数码来表示的数.当前的计算机系统使用的基本上是二 ...
- java byte&0xFF
做串口端口通讯时,数据都是以byte类型发送的 普通的byte范围是-128-127,而java的byte范围是0-255 因此将数据的byte转成java的byte时,需要与0xff(1111111 ...
- [转]java中byte转换int时为何与0xff进行与运算
在剖析该问题前请看如下代码public static String bytes2HexString(byte[] b) { String ret = ""; for (int ...
- Java中byte与16进制字符串的互换原理
我们都知道Java中的byte是由8个bit组成的,而16进制即16中状态,它是由4个bit来表示的,因为24=16.所以我们可以把一个byte转换成两个用16进制字符,即把高4位和低4位转换成相应的 ...
- byte ---> hex String
public static String byte2HexString(byte[] b){ String ret = ""; ;i<b.lenght;i++){ Strin ...
- 从JDK源码角度看Byte
Java的Byte类主要的作用就是对基本类型byte进行封装,提供了一些处理byte类型的方法,比如byte到String类型的转换方法或String类型到byte类型的转换方法,当然也包含与其他类型 ...
随机推荐
- qq邮箱是怎么做到同一个浏览器让多个不用用户同时打开的? --session的控制
待解:..... 借鉴网址:http://www.zhihu.com/question/20235500 欢迎来讨论.....
- opencv保存视频
利用opencv提供的方法,从摄像头获取视频,并保存为.avi格式文件. win8.1,opencv248,vs2013下测试 #include<opencv\cv.h> #include ...
- 改ucosii的中断禁止和恢复代码,这是一个荒谬的错误【 mrs msr】
ucosii原来的禁止中断以及恢复中断的代码是最简的,但是使用之前,必须声明一个固定名为 OS_CPU_SR cpu_sr 的变量,吊在那里感觉很怪. ;********************* ...
- Java进阶03 IO基础
链接地址:http://www.cnblogs.com/vamei/archive/2013/04/11/3000905.html 作者:Vamei 出处:http://www.cnblogs.com ...
- BZOJ 1047: [HAOI2007]理想的正方形( 单调队列 )
单调队列..先对每一行扫一次维护以每个点(x, y)为结尾的长度为n的最大最小值.然后再对每一列扫一次, 在之前的基础上维护(x, y)为结尾的长度为n的最大最小值. 时间复杂度O(ab) (话说还是 ...
- 幻世(OurDream)2D图形引擎使用教程11——播放媒体文件(1)
声明:本教程版权归Lizcst Software Lab所有,欢迎转载,但是转载必须保留本段声明文字,并注明文章来源:http://blog.csdn.net/kflizcst 谢谢合作! 播放媒体是 ...
- [转]apache下htaccess不起作用,linux,windows详解
可能出现下面这三种的错误可能性: 第一种:启用 rewrite 和 .htaccess 设置 rewrite设置:找到apache的配置文件httpd.conf文件,找到:#LoadModule re ...
- Android GsonUtils工具类
有那么一个开源jar包,叫gson 可以很方便的将java中的对象和字符串相互转化,数据传输和处理的时候,用到的可能性很大 https://github.com/google/gson http:// ...
- RVCT的Linux环境变量配置 ARM® RVDS™ 4.1(b713)
下载解压 armrvds.tar.gz到/opt 下 在自己的build.sh下导入RVCT的环境变量配置ARM® RVDS™4.1(b713): export ARMROOT=/opt/armrvd ...
- [置顶] 【玩转cocos2d-x之三十】点九图和输入框的使用
原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/17297721 登录界面一个帐号/密码输入框或者主角命名框是少不了的.这节就来 ...