public class test {
    public static void main(String[] args) {
        short a = (short) 0;
        System.out.println(~a);
    }
}

结果输出 -1

分析:a=0x0000, ~a=0xffff,二进制为1111 1111 1111 1111,当你要输出的时候,编译器发现最高位符号位是1,这个数是个负数,而负数在计算机里面是用补码存储的,所以此时计算机认为这个0xffff是补码,它要转换成原码输出,于是先减去1,再除了符号位不变,其他位全部取反。

就得到了原码0x8001即二进制1000 0000 0000 0001,我们知道原码这个数就代表-1

再来一个例子:

public class test {
    public static void main(String[] args) {
        short a = (short) -2;
        System.out.println(~a);
    }
}

结果输出 1

分析:a=-2,原码是0x8002,二进制为1000 0000 0000 0010,在计算机中补码表示为1111 1111 1111 1110

要输出的时候按位取反~,~a就是0000 0000 0000 0001,此时计算机发现它最高位是0,这个数是正数,原码补码是一样的,所以直接输出为1

public class test {
    public static void main(String[] args) {
        short a = (short) 3;
        System.out.println(~a);
    }
}

结果输出 -4

分析:a=3的二进制位为0000 0000 0000 0011,~a=1111 1111 1111 1100

输出时计算机发现最高位符号位是1,这个数是负数,也就是存储的是补码,要转换成原码输出,就在原数基础上-1再除开符号位其他位都取反

变成了1000 0000 0000 0100,这个数就是-4的原码,所以输出-4

总结提示:按位取反这个符号~是数据的所有位取反,不管什么符号位,而求补码是原码取反再加1,这个步骤中的取反是除开了符号位的其他位取反。

========================================Talk is cheap, show me the code=======================================