Java基础复习才发现入门时对于数据类型没有学通,这次学通啦
复杂点在符号右移和无符号右移方面,正负数的移位方式不一样。
阅读前提:
1. 计算机程序中只有2进制。
2. 理解 原码、反码、补码 ,知道 byte1字节、short 2字节、char 2字节、int 4字节、float 4字节等
3.明白 与 或 亦或 按位取反 类型强转
4. 数据在内存中用补码表示
5.16进制数默认是int类型,使用16进制强转byte来获得负数,便于阅读
6.代码中写的16进制数实际上是一个整数的补码 比如 (byte)0xc5 表示负数
7.短整数(1、2字节)无符号右移会变成长整数(4字节)
8. 请注意,0xXX默认是Int类型的补码
代码部分:
package datatype; public class Logical { public static void main(String[] args) { System.out.println("------------与或非--------------"); // 提取低位的半个字节 System.out.println("01010101 & 0x00ff 结果为"+(0x55 & 0x0f)); // 按位或 // 在socket通信DataInputStream.readUnsignedShort()中用来合并byte System.out.println("00001111 | 11110000 结果为:"+(byte)(15 | 15 << 4)); // 按位亦或 System.out.println("01011100 ^ 11111010 结果为:"+(0x5c ^ 0xfa));// 10100110 0xa6 System.out.println(Integer.toBinaryString(0xaf)); int a = ((int)0x8a)|((int)0x05); System.out.println(Integer.toBinaryString(a)+" a:"+(-1|a)); System.out.println(Integer.toBinaryString((int)((0x87 - 0x01) ^ 0xff))+"十进制:-"+""+(int)((0x87 - 0x01) ^ 0xff)); System.out.println(Integer.toBinaryString(1)); System.out.println("------------按位取反-------------"); // 数值取反 System.out.println(Integer.toBinaryString(~(9-0x01))); System.out.println(Integer.toBinaryString(-9)); System.out.println("------------类型强转--------------"); // 所有整数在内存中均用补码表示 // 0x8f = 1000 1111 ; 1000中 1为符号位,表示负数 ; // 1000 1111 (补码) ---> 1000 1110 (反码) ----> 1111 0001 (原码) // 所以 0x8f 表示 -(7*16 + 1) = -113 System.out.println((byte)0x8f); short s = (short) 0x80ff; // 0x80ff --> 10000000 11111111 (补码,符号位1,表示负数) ---> 10000000 11111110 (反码) // ---> 11111111 00000001 (原码) = -(7*16^3 + 15*16^2 +1) = 28672 + 3840 + 1 = -32513 System.out.println("0x80ff:"+s); // 输出 0xc5 = 1100 0101 符号位为1; 补码11000101-->反码11000100-->原码10111011= -(3*16+11) = -59 System.out.println("0xc5:"+(byte)0xc5); System.out.println("------------符号右移-------------"); // 负数符号右移 高位补1 // 0xc5=1100 0101(补码) --> 1100 0100 (反码) --> 1011 1011 (原码) = -(3*16+11) = -59 // 0xc5=1100 0101 --> 右移一位 1110 0010 = 0xe2 // -30 = 1001 1110 (原码) <-- 1110 0001 <-- 1110 0010 (补码)= 0xe2 System.out.println("(byte)0xc5>>1:"+((byte)0xc5>>1)); // 正数符号右移 高位补0 // 0101 0101 >>1 --> 0010 1010 = 0x2a = 2*16+10 = 42 System.out.println("(byte)0x55>>1:"+((byte)0x55>>1)); System.out.println("------------无符号右移------------"); //注意 0xc5默认是正整数int类型4字节,为了获得负数,强转为byte类型1字节 // 正数无符号右移 高位补0 System.out.println("(byte)0x55>>>1:"+((byte)0x55>>>1)); // 负数无符号右移 高位补0 // 0xc5= 1100 0101 >>>1 0111 1111 1111 1111 1111 1111 1110 0010 = 0x7fffffe2 // 0xc5= 1100 0101 >>>2 0x7ffffff1 System.out.println("(byte)0xc5>>>1:"+((byte)0xc5>>>1)); // -5 原码 10000000 00000000 00000000 00000101 反码 11111111 11111111 11111111 11111010 // 补码 11111111 11111111 11111111 11111011 = 0xfffffffb >>>1 补码无符号右移1位 最高位为0 // 结果 01111111 11111111 11111111 11111101 = 0x7ffffffd System.out.println(-5>>>1==0x7ffffffd); /* -6 原码 10000000 00000000 00000000 00001000 反码 11111111 11111111 11111111 11110111 补码 11111111 11111111 11111111 11111000 无符号右移两位 01111111 11111111 11111111 11111110 = 0x7ffffffe 3ffffffe 0x00111111 11111111 11111111 11111110 */ } }