类型转换
类型转换总结来说就是:自动提升 手动下降
3.1 自动类型转换
自动类型转换需要满足的要求
- 两种类型相互兼容
- 例:int类型的取值范围包含了short类型的取值范围
- 目标类型大于源类型
- 目标类型的取值范围(等号左边)大于源类型(等号右边)的取值范围
代码举例
public class ConvertTest {
public static void main(String[] args) {
byte b1 = 100;
short s1 = b1;
int i1 = b1;
long l1 = b1;
float f1 = b1;
double d1 = b1;
System.out.println("b1 = " + b1);
System.out.println("s1 = " + s1);
System.out.println("i1 = " + i1);
System.out.println("l1 = " + l1);
System.out.println("f1 = " + f1);
System.out.println("d1 = " + d1);
}
}
-
此代码证明了,不一定相邻之间的类型才能兼容,只要目标类型的范围包含了源类型的范围即可,
-
char类型的自动转换,因为char也可以存储整数,所以也可以与兼容的数据类型进行转换
public class ConvertTest { public static void main(String[] args) { char c1 = 'L'; int i1 = c1; long l1 = c1; float f1 = c1; double d1 = c1; System.out.println("c1 = " + c1); System.out.println("i1 = " + i1); System.out.println("l1 = " + l1); System.out.println("f1 = " + f1); System.out.println("d1 = " + d1); } }
- short类型无法跟char类型进行自动类型转换,即使他们的字节数相同,但是short的取值范围是-3276832767,而char的取值范围是065535,他们的类型产生了冲突
- 运行结果
3.2 自动类型提升规则
圣经:
- 两个操作数有一个为double,计算结果提升为double。
- 如果操作数中没有double,有一个为float,计算结果提升为float。
- 如果操作数中没有float,有一个为long,计算结果提升为long。
- 如果操作数中没有long,有一个为int,计算结果提升为int。
- 如果操作数中没有int,均为short或byte或者char,计算结果提升为int。
- 特殊:任何类型与String相加(+)时,实为拼接,其结果为String。
当多个操作数进行数值运算时,往往都是提升为操作数中取值范围最大的类型
3.2 强制类型转换
强制类型转换需要满足两个要求
- 两种类型要相互兼容
- 数值与数值之间相互兼容
- 目标类型小于源类型
- 目标类型的取值范围(等号左边)小于源类型(等号右边)的取值范围
代码举例
public class ConvertTest {
public static void main(String[] args) {
short s1 = 123;
byte b1 = (byte)s1;
System.out.println("s1 = " + s1);
int i1 = 12345;
short s2 = (short) i1;
System.out.println("s2 = " + s2);
float f1 = 3.9F;
long l1 = (long) f1;
System.out.println("l1 = " + l1);
double d1 = 48.2;
char c1 = (char)d1;
System.out.println("c1 = " + c1);
}
}
运行结果
-
可以看到在此串代码中,l1经过强制类型转换后,不是四舍五入,而是直接截断 取3
float f1 = 3.9F; long l1 = (long) f1; System.out.println("l1 = " + l1);
3.3 特殊情况下的强制类型转换
超出目标类型的数值进行强制类型转换,是特殊的强制类型转换
代码举例
public class ConvertTest {
public static void main(String[] args) {
short s1 = 257;
byte b1 =(byte)s1;
System.out.println("s1 = " + s1);
System.out.println("b1 = " + b1);
}
}
运行结果
为什么强制类型转换之后是1呢?这个就是涉及到二进制的概念了,二进制分为原码、反码和补码,而计算机通常都是以补码的形式来存放整数的
- 正数的原码、反码、补码都一样
- 负数要经过一系列的操作把他转换成补码
接下来我们来解析一下代码
我们知道short占2个字节,即16个位,用二进制存放如下
byte占1个字节,即8个位,如下
因为byte只有8位,short有16位,所以只能把低位8位存的下去,高位的存不下全部截断
最终得到1
再来看一个代码
package com.csdn.code.day3;
public class ConvertTest {
public static void main(String[] args) {
short s1 = 128;
byte b1 =(byte)s1;
System.out.println("s1 = " + s1);
System.out.println("b1 = " + b1);
}
}
先看看计算机是怎么存放的
那么结果是什么呢
可以看到,变成-128了,那是因为在二进制中,最高位是符号位,其他位都是数值位,如图中,红色部分都是符号位,那么为什么是-128呢
-
首先排除一个问题,最高位就是符号位,其他位就是数值位,按照正常来说应该是-0,但事实上,0既不是正数也不是负数,所以也不可能是-0,那么-128是怎么来的呢?
-
在8位的二进制中,最高能容纳127的数值,那么我们要-127-1,是不是能得到-128,那么我们前面说过,负数需要经过一系列的操作才能把它转换补码,现在就用-127来转换一下
-
写出-127的原码:
-
求出-127的反码:(原码的符号位不变,数值位按位取反)
-
求出-127的补码:(反码+1=补码)
-
-127-1=-128
- 对吧图上的存放图,可以发现是一模一样的,所以我们通过求解知道了这个就是-128
-
-
二进制补充
- 对于我们这个二进制计算,他是有范围的,他的范围就是一个字节,这一个字节最大就是127,如果你+1了,就存不下了,所以在+1时,他就会变成-128,也就是一个字节中最小的一位,类似于时钟一样,一圈就12小时,过了12点之后,下一点又是从1开始
- 对于我们这个二进制计算,他是有范围的,他的范围就是一个字节,这一个字节最大就是127,如果你+1了,就存不下了,所以在+1时,他就会变成-128,也就是一个字节中最小的一位,类似于时钟一样,一圈就12小时,过了12点之后,下一点又是从1开始