Byte为什么要做0xFF与运算

最近看代码, 其中看到MD5加密的时候感到很有意思, 就是为什么得到了byte数组后, 每个byte转成十六进制之前, 转换成整数的时候, 都要和 0xFF 做一遍与运算.
小弟看了很是很是困惑

demo代码

public static String clacMD5(String str){
	try{
		MessageDigest md = MessageDigest.getInstance("MD5");
		md.update(str.getBytes());//将String转换成字节码数组,使用该数组更新md5的计算函数
		byte[] digesta = md.digest();// 获取返回md5 的hash值数组
		return byte2hex(digesta);
	}catch(Exception e){
		return null;
	}
}

public static String byte2hex(byte[] b){
	String hs = "";
	String stmp = "";
	for(int i = 0; i < b.length; i++){
		stmp = (Integer.toHexString(b[n] & 0xFF));// ???
		if(stmp.length() == 1){
			// 该处理的目的是当得到的十六进制Hex值小于F的时候,往前补0
			hs = hs + "0" + stmp;
		}else{
			hs = hs + stmp;
		}
		if(i < b.length - 1)// 获取可以删去?
			hs = hs + "";
	}
	return hs;
}

问题点

就在于转换成HexString的时候, 为什么要和 0XFF进行与运算呢?

看了一篇博文之后,大概清楚了原因
http://www.cnblogs.com/think-in-java/p/5527389.html

原因在于Integer.toHexString() 传入的参数是个int类型的参数, 而md5得到的是一个byte数组, 当byte[i]传入之后, 底层就会被转化成int类型, byte只有8位, 而int有32位.
java底层在进行转换的时候, 如果是负数, 8位以外的24位补的都是1, 而整数, 补的都是0.
例如:
10的byte三码都是 0000 1010, 补成int, 三码就是0000 0000 0000 0000 0000 0000 0000 1010
而-10 三码就不一样了
原码:10001010 反码: 11110101 补码(反码+1): 11110110
而jvm底层将其转成int后, 补码就是: 1111 1111 1111 1111 1111 1111 1111 0110

System.out.println(Integer.toBinaryString(-10));//输出-10的二进制码

而MD5最后希望得到的是, 两位的十六进制(HexString)字符串
不妨来看看, byte 为-10和10时的HexString

byte j = -10;
System.out.println(Integer.toHexString(j)); // ffff fff6
byte i =10;
System.out.println(Integer.toHexString(i)); // 则为 a

怎么把他们变成只有两位的十六进制字符串
 1111 1111 1111 1111 1111 1111 1111 0110
  &0000 0000 0000 0000 0000 0000 1111 1111(0xFF)
完美地将前面java自动补充的1全部转成0 , 而最后的8位保持原来的样子;
与运算后,结果就是 1111 0110 -> 0xF6 (转换成十进制就是 246)

换言之, 因为java认为它是32位的, 所以与运算后,符号位被认为是0, 因此负数变成了一个正数!
但是如此一来, 就能保证无论是负数还是正数, 都能保证被转换成2位的HexString了.当然正数小于16的时候,只有1位,这时候就要在其前面补0了.
八位的byte表示范围是[-128,127], 与运算后,0到正数部分不变, 但是负数部分就映射到[128, 255], 映射关系为: 值 = 256 + 负数(即 -1 的HexString应当为FF, 即255)

画外音

当一些时候, 我们不需要判断传进来的数是正数还是负数, 但是希望得到的结果一定是一个正数的时候, 我们就可以通过与运算相应位的0XFF, 就能保证得到的一定是一个正数.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值