话不多说,直接上干货
干货结论:
- java不论是负数还是正数在定义、存储、计算的过程中,都是用其补码
- 第二个结论需要自己去体会,详情看下面的2.从byte(字节)的bit(位)层面去理解编码
论证说明:
1.Byte类型用二进制八进制十六进制定义数值类型数据举例
用byte存一个负数,比如负27,我们一般情况下用十进制可以这样表示:
byte b1 = -27;
那么用二进制如何去声明负27这个数呢?用气原码,反码,还是补码去声明呢?
我们都知道负27这个数,其:
原码:1001 1011
反码:1110 0100
补码:1110 0101
这里我先直接告诉大家,定义-27这个数的时候用的是补码,存储到内存的时候也是用的补码,参与运算的时候到cpu的通用寄存器中的也是补码。
用二进制(0b)存储-27声明如下:
byte b2 = (byte) 0b11100101;
用八进制(0)存储-27声明如下:
byte b3 = (byte) 0345;
ps:
-27的补码二进制1110 0101转八进制:从后往前每三位二进制的数为一组,高位不足补零,划分为:011 100 101,八进制为:345(八进制)
用十六进制(0x)存储-27声明如下:
byte b4 = (byte) 0xe5;
ps:
-27的补码二进制1110 0101转十六进制:从后往前每四位二进制的数为一组,高位不足补零,划分为:1110 0101,十六进制为:e5(十六进制)
2.从byte(字节)的bit(位)层面去理解编码
2.从byte(字节)的bit(位)层面去理解编码
2.1Unicode编码与UTF-8编码的关系
2.1Unicode编码与UTF-8编码的关系
Unicode编码:Unicode(统一码、万国码)它是一种理论层面的东西。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。UTF-8编码:是Unicode编码的具体实现,它的UTF-8以字节为单位对Unicode进行编码。
以下是UTF-8的形式:
0xxxxxx
说明:它是可变长编码,出现频率较多的字符,如ASCII中的字符,通常是一个字节,这样节省存储空间110xxxxx 10xxx1110xxxx 10xxxxxx 10xxxxxx
说明:汉字通常是3个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
ps: xx…x解读:其中一个x对应到Unicode编码中的一bit(位)
UTF-8的特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。Unicode的最大码位0x10FFFF也只有21位。
2.2用汉字举例,Unicode编码对应到UTF-8编码
2.2用汉字举例,Unicode编码对应到UTF-8编码
我们可以去查
喻
这个字,它的Unicode编码为:55bb(十六进制)
把它转换成二进制为: 0101 0101 1011 1011喻
的Unicode编码为2个字节占16位,对应到UTF-8的时候,我们需要用到上面2.1中提到的1110xxxx 10xxxxxx 10xxxxxx
这种形式,把0101 0101 1011 1011
按位填入到xxx中,即把1110xxxx 10xxxxxx 10xxxxxx
中的x用0101 0101 1011 1011
替换掉。
替换后的结果为:1110
0101 10
010110 10
111011
这就是其UTF-8编码,用十六进制表示为:e596bb(十六进制)
java代码举例:用byte数组定义汉字:
public class StringDemo {
public static void main(String[] args) {
//二进制形式
byte[] bytes = {
(byte) 0b11100101,(byte) 0b10010110,(byte) 0b10111011};
//也可以写成十六进制形式
//byte[] bytes = {(byte)0xe5,(byte)0x96,(byte)0xbb};
System.out.println(Arrays.toString(bytes));
System.out.println(binary(bytes,16));
try {
String s = new String(bytes, 0, bytes.length, "UTF-8");
System.out.println(s);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public static String binary(byte[] bytes,int radix){
return new BigInteger(1,bytes).toString(radix);
}
}
测试输出结果: