后记
本来写下这篇文章,是因为密码学作业。虽然Java有对应的方法,但是不了解内容,所以就自己实现了字符存储为字节数组。不过现在了解了字符存储为byte数组的原理
1、左移与右移
1、左移
1、未溢出,转换测试
byte b = 0b01110000;
//未溢出,转换测试
System.out.println(b<<1);//224
System.out.println((byte)(b<<1));//-32
总结一:
1、默认左移操作转换后将机器数解释为int
2、可用类型转换,取机器数低位,解释为byte或short
2、溢出,转换测试
溢出就进行模操作,模的数值为0XFFFFFFFF(int,8)或0XFFFFFFFFFFFFFFFF(long,16)
int i = 0xFFFFFFFF;
//测试转换类型
System.out.println(i<<1);//-2,理论上为0X1FFFFFFFE,转换为了0XFFFFFFFE
long l = 0xFFFFFFFFFFFFFFFFL;
System.out.println(l<<1);
2、右移
1、正数
缩小两倍
2、负数
算术右移
需要注意的是,如果右移位数超过了数据类型的位数,就会对右移数进行模运算。
System.out.println(10L>>99);
//Shift operation '>>' by overly large constant value 99
或者
System.out.println(10>>99);
IDE会提示,99超出了数据类型的位数,而且可以将99替换成模运算后的数值。
即右移99位等价于以下右移位数
long : 99 % 64 = 35
int : 99 % 32 = 3
总结二:
- byte类型用二进制表示,只能表示7位数值位,符号位用+、-,即输入的是原码,不能直接输入补码
byte b = -0b1111111;//表示-127,7位
byte b1 = -0b0000001;//表示-1,7位
byte b2 = 0b10000000;//报错,8位
- int与long类型可以直接输入补码,也可以输入原码
补码:
int i = 0xFFFFFFFF;//-1
原码:
int j = -0x00000001;//-1
- byte与其他数值类型相互转换时,机器数也会相应变化
byte b = -1;
int i = b;
System.out.println(Integer.toHexString(i));
输出:ffffffff
2、char用byte存储与表示
public void A() throws Exception {
int i = '您';
byte[] bytes = new byte[4];
//用byte数组存储字符
for (int j = 0; j < 4; j++) {
bytes[j] = (byte) (i>>(8*j));
}
int k = 0;
for (int j = 0; j < 4; j++) {
k+=(bytes[j]&0xff)<<(j*8);
}
System.out.println((char) k);
}
输出:您
思路:将字符的值存储在byte[]中,在将byte[]的值转换成字符。
重点:bytes[j]&0xff
,将byte转换为unsinged byte,借助int类型
原因:
1、这里需要注意对机器数进行解释的问题(不懂的去百度)
eg:byte b= -1
机器数为 0XFF;转换为int后,机器数为0XFFFFFFFF。
举个例子,您 的字符值为24744(十进制),如果直接左移还原,还原后的字符值为24488。这是因为 24488 = -88 + 24576 + 0 + 0。
直接左移的补码与真值的对应关系:
-88 = 0X10000048 << 0;24576 = (OB01100000) << 8
正确的补码与真值的对应关系:24744 = 168 + 24576 + 0 + 0
168 = 0X000000A8 << 0;24576 = (OB01100000) << 8
3、String
String是字符序列,可以将字符分离,在进行存储