public class Test {
public static void main(String[] args) {
// java中负数的 & >> >>> 运算 案例
// 1.byte的范围问题
// b = 0b01000000
byte b = 64;
// b = b + 64; // 编译报错,byte在运算时会先转成int类型再运算,结果也是int类型,int -> byte 需要强转
b += b; // += 会把结果自动进行强转
// b 转为int : 0b01000000 --> 0b00000000 00000000 00000000 01000000
// 输出-128,b + b = 0b00000000 00000000 00000000 01000000 + 0b00000000 00000000 00000000 01000000 = 0b00000000 00000000 00000000 10000000
// 结果0b00000000 00000000 00000000 10000000 转为byte-> 0b10000000 = -128的补码 = -128
formatPrint("b + b = %s + %s = 0b%s = %s", toBinaryString(64), toBinaryString(64), Integer.toBinaryString(b).substring(24), b);
b = 64 + 63; // jvm对常量运算做了优化,直接把运算的结果赋值给b
// b = 64 + 64; // 编译报错,因为64+64超出byte的范围,不能用byte接收
formatPrint("64 + 63 = %s + %s = %s = %s", toBinaryString(64), toBinaryString(63), toBinaryString(b), b);
formatPrint("-----------------------------------------------------------------------");
// 2.负数运算操作 & >> >>>
// 计算机的运算都是用补码来计算的,正数:原码=反码=补码,负数:反码=除符号位原码各位取反,补码=反码+1
b = -1; // -1:0b10000001(原) -> 0b11111110(反) -> 0b11111111(补)
// b转为int类型:0b10000000 00000000 00000000 00000001(原) -> 0b11111111 11111111 11111111 11111110(反) -> 0b11111111 11111111 11111111 11111111(补)
// i = 0b11111111 11111111 11111111 11111111 & 0b00000000 00000000 00000000 11111111 = 0b00000000 00000000 00000000 11111111 = 255
int i = b & 0xFF;
formatPrint("-1 & 0xFF = %s & %s = %s = %s", toBinaryString(b), toBinaryString(0xFF), toBinaryString(i), i);
// >> :带符号右移,正数右移高位补0,负数右移高位补1
int i2 = b >> 4; // i2 = 0b11111111 11111111 11111111 11111111 >> 4 = 0b11111111 11111111 11111111 11111111 = -1补码 = -1
formatPrint("-1 >> 4 = %s >> %s = %s = %s", toBinaryString(b), 4, toBinaryString(i2), i2);
// >>> :无符号右移,无论是正数还是负数,高位都补0
int i3 = b >>> 4; // i3 = 0b11111111 11111111 11111111 11111111 >>> 4 = 0b00001111 11111111 11111111 11111111 = 268435455
formatPrint("-1 >>> 4 = %s >>> %s = %s = %s", toBinaryString(b), 4, toBinaryString(i3), i3);
formatPrint("-----------------------------------------------------------------------");
// 再如 -127
b = -127; // -1:0b11111111(原) -> 0b10000000(反) -> 0b10000001(补)
// b转为int类型:0b10000000 00000000 00000000 01111111(原) -> 0b11111111 11111111 11111111 10000000(反) -> 0b11111111 11111111 11111111 10000001(补)
i = b & 0xFF; // i = 0b11111111 11111111 11111111 10000001 & 0b00000000 00000000 00000000 11111111 = 0b00000000 00000000 00000000 10000001 = 129
formatPrint("%s & 0xFF = %s & %s = %s = %s", b, toBinaryString(b), toBinaryString(0xFF), toBinaryString(i), i);
i2 = b >> 4;
formatPrint("%s >> 4 = %s >> %s = %s = %s", b, toBinaryString(b), 4, toBinaryString(i2), i2);
i3 = b >>> 4;
formatPrint("%s >>> 4 = %s >>> %s = %s = %s", b, toBinaryString(b), 4, toBinaryString(i3), i3);
}
/**
* 格式化输出字符串
* @param format 要格式化的字符串
* @param args 参数
*/
private static void formatPrint(String format, Object ... args) {
System.out.println(String.format(format, args));
}
/** int类型十进制转二进制 保持32位,i为负值时,返回的是其二进制的补码 */
private static String toBinaryString(int i) {
String bs = Integer.toBinaryString(i);
String pre = IntStream.range(0, 32 - bs.length()).mapToObj(x -> "0").collect(Collectors.joining());
return String.format("0b%s%s", pre, bs);
}
/** int类型十进制转十六进制 保持8位,i为负值时,返回的是其十六进制的补码 */
private static String toHexString(int i) {
return String.format("%#010x", i);
}
}
案例:将byte数组转十六进制字符串
public class TestExample {
public static void main(String[] args) throws Exception {
// sha256加密一个数 返回的是一个byte数组
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] encrypted = md.digest("3".getBytes(StandardCharsets.UTF_8));
// 將 byte 转换16进制 string
String result;
// 1 遍历逐个转换
StringBuilder strHexString = new StringBuilder();
// 遍历byte buffer
for (byte b : encrypted) {
// String hex = Integer.toHexString(0xff & b).toUpperCase();
// if (hex.length() == 1) {
// strHexString.append('0');
// }
// strHexString.append(hex);
// 保持两位不足用0补全
strHexString.append(String.format("%02X", b));
}
result = strHexString.toString();
System.out.println(result.length());
System.out.println(result);
// 2 先转换为BigInteger类型,再使用toString方法转换
result = new BigInteger(encrypted).toString(16).toUpperCase();
System.out.println(result);
// 3 调用DatatypeConverter.printHexBinary方法
result = DatatypeConverter.printHexBinary(encrypted);
System.out.println(result);
result = printHexBinary(encrypted);
System.out.println(result);
}
// 同 DatatypeConverter.printHexBinary
private static String printHexBinary(byte[] data) {
char[] hexCode = "0123456789ABCDEF".toCharArray();
StringBuilder r = new StringBuilder(data.length * 2);
for (byte b1 : data) {
int b = b1 & 0xFF; // 将byte的负值转为int类型的正值
// byte 共八位二进制 相当于两位十六进制
r.append(hexCode[b >>> 4]); // 取前四位的值
r.append(hexCode[(b & 0xF)]); // 取后四位的值
}
return r.toString();
}
}