基本数据类型的隐式转换和强制转换

1. 基本数据类型

Java中有8种基本数据类型,分为4个类别:

  • 整数型:byte、short、int 、long

  • 浮点型:float、double

  • 字符型:char

  • 布尔型:boolean

    基本类型 位数 字节 默认值
    byte 8 1 0
    short 16 2 0
    int 32 4 0
    long 64 8 0L
    float 32 4 0f
    double 64 8 0d
    char 16 2 'u0000'
    boolean 1 false

注意:

  1. 对于boolean,官方文档未明确定义,它依赖于 JVM厂商的具体实现。逻辑上理解是占用 1位,但是实际中会考虑计算机高效存储因素。
  2. long类型不加L默认是int,int转为long是安全的,所以会自动转,能编译通过 。但是如果超过了int的取值范围还不加L,则会编译不通过。
  3. 浮点数不加F默认是double类型,double转float可能损失精度,因为不会自动转,编译通不过 。

2. 基本类型的隐式转换

如下图所示,从表示范围小的类型转换为表示范围大的类型,可以直接转换,称为隐式转换。

image-20201013222329007

图中有6个黑色箭头,表示无信息丢失的自动转换;有3个红色箭头,表示有精度损失的自动转换。例如,123 456 789是一个大整数,它所包含的位数比float类型所能表达的位数多。当将这个大整数转为float类型时,将会得到同样大小的结果,但却丢失了一定的精度。long转为double类型同理。

int n = 123456789;
float f = n ; //f is 1.23456798E8

当使用上面两个数值进行二元操作时(算术运算,例如 n+f,n是整数,f是浮点数),先要将两个操作数转换成同一种类型(如果是包装类型,则先自动拆箱),然后在进行计算。

注意:

  • 转换类型的过程中,如果两个操作数中含有浮点型,则优先转为浮点型(顺序为double、float、long、int,即优先转为表示范围大的类型)。

3. 基本数据类型的强制转换

我们知道,在从小范围类型转为大范围类型时,系统会自动帮我们隐式转换。但如果是大范围类型转换为小范围类型时,编译就会报错,如下所示。

double d = 6.66;
int n = d ;//编译错误

Java允许进行这种数值之间的类型转换。当然,有可能会丢失一些信息。在这种情况下,需要通过强制类型转换实现这个操作。强制类型转换的语法格式是在圆括号中给出想要转换的目标类型,后面紧跟待转换的变量名。例如:

double d = 6.66;
int n =(int) d ;//n is 6

变量d的值 6.66 通过强制转换将浮点型转换成了整形,赋值给变量n,此时变量n的值为6。强制类型转换所带来的结果不仅是会丢失精度。如果此数值尚在范围较小的类型数值范围内,对于整型变量精度不变,但如果超出范围较小的类型数值范围内,很可能出现一些意外情况。例如:

int n =666;
byte b= (byte)n; //b is -102

上面的例子中输出值是 -102。

为什么结果是-102?需要从最根本的二进制存储考虑。

666的二进制表示为:22位0 + 1010011010,byte型只有8位,于是从高位开始舍弃,截断后剩下:10011010,由于二进制最高位1表示负数,0表示正数,其相应的负数为-102。

需要注意的是:

当进行数学运算时,数据类型会自动发生提升到运算符左右之较大者,以此类推。当将最后的运算结果赋值给指定的数值类型时,可能需要进行强制类型转换。例如:

short s = 1;
s = s+1; //编译报错,需强转
s = (short) s+1 ; //s+1在运算过程中,会转换成int型,所以需要强转

有意思的是,在赋值中使用二元运算符时,会自动进行强制转换。例如:

short s = 1;
s += 1; //编译通过,等价于 s=(short) s+1;

有兴趣的可以通过下面链接了解一下。

为什么Java的+ =,-=,* =,/ =复合赋值运算符不需要强制转换?

posted @ 2020-10-14 00:16  渺渺孤烟起  阅读(818)  评论(0)    收藏  举报