黑马程序员--数据类型转换问题
自动类型转换与强制类型转换
数据类型转换就是把数据的类型转变为另一种类型。例如:可以把login类型数据“251”转换成一个int整数类型。Java对数据类型的转换有严格的规定,数据从占用存储空间较小的类型转换为占用存储空间较大的数据类型时,不用做显式的类型转换(即自动类型转换);反之则强制类型转换。
转换成类型的转换分为两种:自动类型转换和强制类型转换两种。
我们先从几个例子中进行比较:
(一):自动类型转换问题
Java中有8中基本数据类型可以混合运算。不同类型的数据在运算过程中,首先会自动转换为同一类型,再进行运算。数据类型可以根据占用存储空间大小分为高低级别,占用空间越小级别越低;占用空间越大,级别越高。自动类型转换遵循低级到高级的转换。
1 . Java中数据类型转换原则:
(1)精度小的向精度大的转换
(2)字节短的向字节长的转换
(3)char和int可以互换,char是用ASCII码表示
byte->(int=char)->long->float->double
默认情况下,其顺序为:byte-->short(char)-->int-->long-->float-->double
需要注意的是:所有的类型只要是碰到了String,则都会向String类型进行转换。
例如:
int x=55;//定义一个整型变量
int y=88;//定义一个整型变量
String s="sxl";//定义一个字符串变量
System.out.println(s+x+y);
//结果:sxl5588;
默认情况下,各个基本数据类型间是可以进行转型操作的:byte—>shortàintàlong—>floatàdouble。//但是所有的类型只要是碰到了String,则都会向String类型进行转换
System.out.println(x+y+s);//结果:143sxl;注意两种不同结果的差别
System.out.println(s+(x+y));//结果:sxl143;
特点:自动类型提升对数据运算带来了方便,但容易带来编译错误。
例如:
byte x=30;
x=-x; //编译错误!不能向byte变量赋以提升的int类型值。
因为:byte 占8位,int 占32位,在运算过程中,byte类型自动转化为int类型再把它赋给byte类型就会出错。
x = (byte) -x.这样就可以了
不同类型的数据先转化为同一类型(从低级到高级),然后再进行运算,x=-x <=> x=0-x。
2 . 变量赋值:
当为变量赋值的数据类型与变量类型不一致,并且赋值的数据类型级别低于变量类型的级别时,自动数据类型转换会将变量赋值数据数据自动转换为变量类型。
例如:
Byte byteNum = 23;//声明byte类型变量
Int intNum = byteNum;//把byte类型数据赋值给int类型变量
3 . 方法调用:
把一个数值传递给方法的参数,并且这个数值的数据类型低于方法的参数数据变量的数据类型。例如:
Public static void say(int num){
System.out.println(“这是一个int类型数值:”+num);
}
Public static void main(String[] args){
Byte byteNum = 23;
Say(byteNum);//把byte数值传递给方法的int参数
}
4 . 一元运算符:
在一元运算符中(除了++和—运算符),如果操作数的类型低于int类型(即:byte, short和char类型),则操作数会自动转换为int类型。
5 . 二元运算符:
在二元运算符中,所有低级的数据类型都会转换为运算中级别最高的数据类型。也就是说,如果一个操作数是double类型,其他操作数都会自动转换为double类型。如果 中最高的数据类型是float,其他操作数都会转换为float类型。如皋最高的数据类型为long,那么所有的操作数都会自动转换为char类型都会自动转换为int类型或运算符中最高的数据类型。
下面在主方法中创建不同的数据类型的变量,实现各变量的自动类型转换:
public class Conversion {
public static void main(String[] args) {
byte b = 34; //定义一个byte型变量
short s = 123;//定义一个short型变量
char c = 'B';//定义一个char型变量
int i = 40;//定义一个int型变量
long l = 900l;//定义一个long型变量
float f = 8.11f;//定义一个float型变量
double d = 3.1415926;//定义一个double型变量
System.out.println("double/byte+char-->double\t"+(d/b+c));
System.out.println("long+short-->long\t\t"+(l+s));
System.out.println("char+byte+short-->int\t\t"+(c+b+s));
System.out.println("float+b/s-->float\t\t"+(f+b/s));
System.out.println("int+double-->double\t\t"+(i+d));
} }
运行结果:
double/byte+char-->double 66.09239978235294
long+short-->long 1023
char+byte+short-->int 223
float+b/s-->float 8.11
int+double-->double 43.1415926
(二):强制类型转为问题
当把高级别(即占用存储空间较大)的数据类型赋值给低级别(即占用存储空间较小)的数据类型时,必须进行强制类型转换。其语法格式如下:(类型)(表达式)
类型是要转换成目标类型,例如int,short,double等,表达式是要转换的目标数据,它可以是任何基本类型的算术表达式。
例如:long num = 900l; //定义一个long型变量num
short snum = (short)num; //定义一个short型变量snum,把num强制转换成short
long类型的数值900没有超过short类型的取值范围,所以short类型的变量snum完全容纳了强制类型转换后的数值。
基本数据类型的强制类型转换需要注意数据完整性的问题,当高级的数据类型强制转换成低级的数据类型时,如果数值超出低级数据类型的取值范围,则数值将被截取,会导致数据丢失,不完整。
例如:
short snum = 516; //定义一个short型变量snum
byte bnum = (byte)snum; //定义一个byte型变量bnum,把snum强制转换成byte
snum是short类型,数据长度是16位,而bnum是byte类型,长度为8位。当snum强制转换为byte类型时,数值516超出了byte类型的取值范围,这时只能从short类型截取低8位的数据赋值给byte类型的bnum变量。这样就造成了数据的丢失,所以在使用强制类型转换时,一定要加倍小心。
注意:boolean布尔型的数值不能被强制类型转换为其他数据类型,反之亦然。
byte b=8;//定义一个byte类型的变量b并初始化值为8;
//b=b+5;
System.out.println(b);
这个时候我们会发现程序会报错,其原因是:5是int类型,它是由四个八位bit组成;b是byte类型,它是一个八位bit组成;这时涉及到的是:类型转换问题。所以我们需要强制转换:b=(byte)(b+5); 将int类型的结果(b+5)结果强制转换为byte类型
但是当b+=5的时候,这时又能通过编译,这时程序是:
byte b=8;//定义一个byte类型的变量b并初始化值为8;
//b=b+5;
b+=5;
System.out.println(b);
对于b+=5;这个表达式我们可以理解为:b=b+5;但是,+=是赋值运算符,赋值的是两边的和,并进行检查,底层自动进行转换动作。所以运行的时候编译器没有报错。
虽然强制类型转换可以将结果转换成你所需要的类型,但是,需要注意的问题是:容易丢失精度,一般本人不提倡使用
例如:一个int类型数据在计算机中存储的是:0000-00000000-0000 0000-0001 0000-0011 ,如果要求将该int类型的数据强制转换为byte类型的数据,结果就是:0000-0011 ;比较之后,很明显我们可以看出丢失了精度
例子:
byte b=8;//定义一个byte类型变量
b=(byte)(b+200);//将(b+200)的结果转换成byte类型,并赋值给b;很明显我们需要的结果是208
System.out.println(b);//输出结果b为-53
(三):面试题:
byte b=3;
//b=4+7;
System.out.println(b);
对于上述的题目我们可以看出没有问题,其实这就相当于b=11;
那么我们再来看看下面的情况:
byte b=3;
byte b1=4;
byte b2=7;
b=b1+b2;
System.out.println(b);
这时候出现了这种情况:cannot convert from intto byte,为什么会出现这种情况呢?这时b=b1+b2;有人认为:b1+b2的结果和4+7的结果不是一样的吗?那么真的是一样的吗?
分析:
(1)byte b=3;
3是int类型的数据;b是byte类型的变量,那么int类型的数据怎么赋值给byte类型的变量呢?
首先我们要明确的是:byte b=3;当编译器发现后面的数据是3时,编译器首先判断3是不是在byte的范围之内(-128~127),如果在,则默认强转并赋值给b;不在,则报错。
(2)b=b1+b2;
首先我们要先明确b1和b2是变量;这就意味着b1和b2的数值会变化的,也就是说b1和b2的值是不确定的,这时如果我们给b1或者b2重新赋值(b2=130;),这时的结果呢?
还有就是:b1和b2是变量;变量那么就意味着编译器无法检查。所以这时候如果你进行强制运行,那么编译器就会报错。
对于第一种情况:b=4+7;这时b右边的数值是固定的,则意味着编译器可以进行判断这个数据是否在byte范围之内。
下面我们在来看一题:
int x;
int x1=100;
int x2=108;
x=x1+x2;//
System.out.println(x);//208
这个时候运行是没有错误的,原因:
在计算机中,任何整数运算的结果还是整数。
另一种情况:
int x;
intx1=Integer.MAX_VALUE;
int x2=2;
x=x1+x2;
System.out.println(x);
int类型是32位类型的数据,对于超过的部分进行舍弃,这就意味着最高位就是1了,也就是负数
总结:默认int类型运算,一旦超过运算,底层则自动进行强制转换,保留自己原有位置,对于超过的部分全部舍弃。
(四)Java基本数据类型的自动类型转换和强制类型转换的规律:
(1)布尔型和其它基本数据类型之间不能相互转换;
(2)byte型可以转换为short、int、、long、float和double;
(3)short可转换为int、long、float和double;
(4)char可转换为int、long、float和double;
(5)int可转换为long、float和double;
(6)long可转换为float和double;
(7)float可转换为double;