MessageDigest md5 = MessageDigest.getInstance("MD5"); String pwd = "pass123"; md5.update(pwd.getBytes()); byte[] result = md5.digest();
先看上面一段简单代码,是MD5的加密,把字符串pwd加密后得到类型为byte[]的密文。
那么我们怎么识别,或者直观的理解这个byte[]呢?
这样的例子举不胜举,例如IO的读写,消息的传输,都是以byte[]的方式传输,可以这样讲:目前绝大多数计算机(包括网路设备)之间数据的传输都是byte[]类型。
也就是说,我们能之间操作的最小单元是byte,即字节(8bit)。
为什么呢?我们都知道,计算机Bus传输是8位的,比如网线、双绞线、总线等。这里特别注意:32位和64位是计算机一次能处理的二进制数是2^32和2^64,指的是cpu处理能力,不要混淆。
接下来我们一起学习它的原理。
byte[]其实是一组连续内存地址单元(每个地址8bit)组成的。每个byte表示由8位0和1组成的二进制,范围是-128~127。
扩充知识,内存的寻址算法是:首地址a0+n,其中n表示该类型所表示的字节个数。
其中:byte、boolean的字节个数是1;short、char的字节个数是2;int、float的字节个数是4;long、double的字节个数是8;(1个字节是8个bit)
那么,byte的范围为什么是-128~127,而不是0~255或者-127~127呢?
以下1、2、3摘自链接:https://blog.csdn.net/weixin_38357164/article/details/87912475
1:我们知道计算机底层都是加法计数器运算,不能计算减法,但是我们生活中还必须有负数,有减法,这样符合人类数学思维习惯。
2:我们还知道一个byte字节占八位,也就是八位1和0组成的二进制数串,这个数串最小是00000000,最大是11111111,也就是表示了0-255的范围,那么问题来了。这个范围都是正的啊,没有负数,没有负数就没有减法,怎么办?
3:其实我们正好反过来解决了这个问题,计算机底层都是要将一个byte存储的负数转换成0-255范围的正数来计数的,但是按照人类的习惯,要直接在写代码的时候就有负数,有减法才能符合人类的思维习惯,那么怎么将负数和减法在计算机的世界里表现出来呢。这时候补码就诞生了。
计算机中的符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,是计算机中对数字的二进制定点表示方法。符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。下面依次介绍并给出相互的转换关系:
原码:
简单直观;例如,我们用8位二进制表示一个数,+11的原码为00001011,-11的原码就是10001011。但参加运算可能出错。例如数学上,1+(-1)=0,而在二进制中,00000001+10000001=10000010,换算成十进制为-2,显然出错了。
反码:
反码通常是用来由原码求补码或者由补码求原码的过渡码。反码跟原码是正数时,一样;负数时,反码就是原码符号位除外,其他位按位取反。
补码:
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
注:附图一张,-128的补码好像有点问题,后面再补充