Java中原码、补码与反码
Java中的原码、补码与反码是进行位操作及类型转换时十分重要的知识点,因此这里简单做一点总结。
原码
原码比较好理解,也就是该数字不进行其他操作时数字最原始的二进制表示,在Java中我们有熟悉的byte,short,int,long的整数型基本数据类型以及float,double的浮点型基本数据类型。
在Java中,对于整数而言,其原码格式为最高位为符号位,该位上1表示负数而0表示正数,剩余位数为该数字的二进制表示。在这里我们简单用int型的整数5及-5看下例子:
5的原码:00000000 00000000 00000000 00000101
-5的原码:10000000 00000000 00000000 00000101
因此,对于原码来说,绝对值相等的正数和负数只有符号位不同。
反码
从反码开始略有些复杂了,正数的原码即为其反码,对于负数而言只需要将原码除符号位以外的位数取反(如果为0改为1,如果为1改为0),便得到了当前负数的反码。
我们依旧拿数字5举例:
5的反码:00000000 00000000 00000000 00000101
-5的反码:11111111 11111111 11111111 11111010
补码
明白了反码的规则,补码的表示方法就很简单了,正数的原码即为其补码,负数的补码是上面取得的反码加1。
5的补码:00000000 00000000 00000000 00000101
-5的补码:11111111 11111111 11111111 11111011
同时注意:Java中所有基本数据类型均使用该数字的补码进行表示,所以在Java中测试5与-5的输出我们能看到这样的结果:
int i = 5;
int j = -5;
System.out.println(Integer.toBinaryString(i));
//101 之前的29位全0被忽略了
System.out.println(Integer.toBinaryString(j));
//11111111111111111111111111111011
总结
正数:原码、反码、补码相同。
负数:反码符号位不变化,其余位数取反,补码即为反码+1。
在明白以上几点后,我们现在了解一下Java的数据类型的表示方式的机制。
Java基本数据类型转换
我们知道Java中基本数据类型的范围是各不相同的,因此在不同类型进行转换时,我们会经常使用诸如(int)这样的cast前缀来进行强制类型转换,一般而言在不考虑无法转换及同为数值类型的前提下,如果该数据类型的范围比目标数据类型的范围大,那么我们无需使用前缀进行强制类型转换,倘若反过来,现有数据类型的范围无法容纳较大数据类型的内容,Java便会在运行时对范围较大数进行截断。
例如int类型比所有byte合法类型大,因此不要求显式强制类型转换。对于数字类型,整型和浮点型都是彼此兼容的,但是数字类型和字符类型和布尔类型是不兼容的,字符类型和布尔类型也不是互相兼容的。
目标类型指定了要转换成为的类型。例如将int型转为byte型,int型取值范围大于byte型,它的值将对byte型范围进行取模。而把浮点型赋值给整数型,就会出现截断,截取掉小数部分。从其他数值类型转换为char类型时,必须进行强制转换。将char类型转换为其他数值类型时,除了byte、short必须强制转换之外,int、long、float、double都不用强制转换。
int a = 1;
char b= (char) a;
char c= 'a';
int d = c;//不需要强转
short e = 1;
byte f = (byte) e;//byte无法容纳short类型,需要强转
char g = 'a';
double h = g;//不需要强转
接下来我们看几道小测试,请说出以下程序的输出:
byte b = (byte) 128;
System.out.println(b);
byte b1 = (byte) -129;
System.out.println(b1);
double d = 200.123;
System.out.println((int)d);
char c ='a';
byte s = (byte) c;
System.out.println(s);
答案分别是:-128 127 200 97。
第一个byte因为无法容纳128(byte范围是-128-127),因此需要进行截断,用二进制表示过程就是这样的:
int 00000000 00000000 00000000 10000000
byte 10000000 //最高位符号位1代表此数为负数,因此是-128。
第二个输出:
int 11111111 11111111 11111111 01111111
byte 011111111 //即127。
第三个:
double转换为int时会去掉小数位,因此输出200。
第四个:
char转换为byte时,由于byte无法容纳char的16位,因此需要进行强制转换并截断一部分,但是由于’a’字符对应的十进制97并未超过byte的范围因此此处直接输出’a’的AscⅡ码97。
另外在某些面试题中,我们会经常看到类似这样让你判断是否编译错误的问题:
short s = 1;
s = s + 1;//编译错误
s+ = 1;//正确
这是因为编译s = s + 1或其他类似运算时Java会默认将其编译为默认的int类型(小数则默认为double),因此必须将s进行类型转换。
byte b = 127;
System.out.println(b+b);//输出254,表示当前结果已经成为int类型了
而第三行s+=1则实际上隐含了类型转换,它等于s=(short)(s+1)。类似的,在使用三目运算符时,如果取值均为数值类型,那么它将会根据类型提升原则提升结果。如果取值中的一侧为引用类型,那么编译时他们会提升至Object类型。
byte b = 10;
short s = 20;
int i = (b == 10) ? b : s;
int i1 = 10;
String str = "Hello";
Object obj = (i1 == 10) ? i1 : str; // 在这里变量i进行了自动装箱操作
参考博文:
https://blog.csdn.net/czengze/article/details/52976820
————————————————
版权声明:本文为CSDN博主「ZincChampagne」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_37870009/article/details/79775926