基本数据类型的类型转换--java

0.绪论

  java有八大基本数据类型,包括数值型、字符型(char)和布尔型(boolean)。其中,数值型又可分为整数型(byte、short、int、long)和浮点型(float和double)。关于这八个基本类型的详细信息,请阅读java中的8种基本类型,在此不再赘述。本文主要讨论java的8种基本类型之间的类型转换(下文中的类型转换都是指基本类型之间的转换),主要包括以下4个问题:

  (1)java支持的类型转换有哪些?其中,有哪些是自动类型转换,哪些是强制类型转换?

  (2)类型转换规则?

  (3)类型转换过程中发生的数据溢出和精度损失是什么原因导致的?如何判断?

  (3)有哪些类型转换情形,字面量和算术表达式的类型判断?

1.基本类型之间的类型转换

1.1 概述

  除了boolean型之外,其他7种基本类型(byte、short、int、long、float、double和char)之间均可以进行类型转换。boolean型是一个特殊的类型,它只有true和false两个可能取值。因此,布尔型不能与其他基本类型做任何转换。

  类型转换包括自动类型转换和强制类型转换,自动类型转换是指不需要显示转换的类型转换,即java编译器默认支持的类型转换;强制类型转换是指需要显示转换的类型转换。其中,显示转换是指需要用圆括号将目标类型括起来放在源类型变量前面,如(byte)value。其中,value是一个int型变量。

  java中允许的基本类型之间的自动类型转换如下所示:

//java中允许的自动类型转换
//左边可以自动转换成右边,不支持short和char的自动转换
byte-->short
byte,short,char-->int-->long-->float-->double

  自然,除了上述的自动类型转换外,剩下的类型转换都是强制类型转换。

1.2 类型转换规则

  可以看到,由于char型可看做是16位无符号整数,因此java的基本类型转换都是数值类型之间的转换。在java中,整型和char型变量都是用二进制补码表示的,因此在类型转换时我们应当从二进制补码的形式去分析其转换规则。具体的转换规则如下:

  (1)如果最初的数值类型是有符号的,那么就执行符号扩展;如果是char类型,那么不管它要被转换成什么类型,都执行0扩展。

   注:符号扩展用于在数值类型转换时扩展二进制位的长度,以保证转换后的数值和原数值的符号(正或负)和大小相同,一般用于较窄的类型(如byte)向较宽的类型(如int)转换,具体操作方法是在原数值的二进制位左边补齐若干个与源类型相同的符号位;零扩展则是在原数值的二进制左边补0。

  (2)如果目标类型的长度小于源类型的长度,则直接截取目标类型的长度。例如将int型转换成byte型,直接截取int型的右边8位。
  (3)浮点数转整型的时候直接舍弃小数部分,如果整数部分比目标类型的长度长的话,按照规则2处理。
1.3 数据溢出和精度损失
  在类型转换的过程中可能会发生数据溢出和精度损失,尤其是强制类型转换。数据溢出是指由于源类型的数值不在目标类型所表示的范围内,导致类型转换后目标类型数值与源类型数值不相等,精度损失则是指相比于源类型的精度,目标类型的精度要更粗。以下是数据溢出和精度损失的简单示例:
 1 /*
 2 数据溢出
 3 byte到char,强制类型转换
 4 */
 5 byte b = -1;//-1的二进制补码是11111111
 6 char c = (char) b;//byte到char的类型转换:拿符号位补齐高位,所以c的二进制补码是1111111111111111,即FFFF。
 7 System.out.println("b:" + b + ",c:" + (int) c);//直接打印char型变量时,打印的是Unicode字符。所以,需要先将char型变量转换成int型变量
 8  
 9 //输出结果:b:-1,c:65535
10 
11 /*
12 精度损失
13 long到float,自动类型转换
14 */
15 long l = 278878996;
16 float f = l;
17 System.out.println("l:" + l + ",f:" + f);
18 
19 //输出结果:l:278878996,f:2.78879008E8

  问题1:如何判断类型转换可能会导致数据溢出?判断是否会发生数据溢出的关键在于判断目标类型能够表示的取值范围是否包含源类型的取值范围,如果源类型的取值范围是目标类型的取值范围的子集,那么就不会发生数据溢出。

  问题2:如何判断类型转换可能会导致精度损失?精度损失一般发生在浮点数与整型之间的类型转换以及double到float的转换,其产生原因是浮点数用科学计数法去表示一个数。当把一个较大的整型数据转换成浮点数时,会根据float或者double的精度去截取整数位数,在这个截取的过程中可能会发生精度损失。(有一部分低位数据丢失,具体可参见上面的例子)。

 1.4 发生类型转换的情形

  在java中可能会发生基本类型之间的类型转换的情形包括:赋值、算术运算和方法调用 。参与类型转换的一般有变量、字面量和算术表达式,首先我们需要清楚这三者的类型,之后才能按照1.2的转换规则进行类型转换。其中,变量的类型是确定的,字面量和算术表达式的类型判断参见1.4.1和1.4.2。

  1.4.1 字面量的类型

  (1)java中,整型字面量的默认类型是int型,浮点数字面量的默认类型是double型。默认类型是指该字面量后没有后缀缩写标明其类型,如30、1.04等。如果字面量有后缀缩写标明类型,则以后缀缩写为准。大小写L代表long型,大小写F代表float型,大小写D代表double型,如12L、1.0f、1.0D。

  (2)当整型字面量的值在byte、short、char的表示范围内时在赋值时是允许自动类型转换的(注意这个和1.1中提到的不太一致,属于int->byte、short、char的特殊情况),超出时则需要强制类型转换;

  1.4.1 算术运算表达式的类型

  算术运算表达式的最终结果类型确定规则为:

  (1)如果表达式中只有int或者int以下的数据(即byte、short、char),那么byte、short、cha无条件转换成int,最终得到的表达式结果是int型;

  (2)如果表达式中有double、float、long型,则最终的表达式结果是最高的基本类型(long<float<double)。

posted @ 2018-02-26 12:17  赵庆-BUPT  阅读(245)  评论(0编辑  收藏  举报