首先来看一道java面试题:以下程序错误的是_____
A: short s1 = 1; s1 = s1 + 1; B: short s1 = 1; s1 += 1;
答案是A,A编译不通过,int型不能自动转化为short型,需要强制转换。
两者看起来似乎是一样的,关键在于 s1=s1+1是否等价于s1+=1。在我以前的认知里,s1 += 1;就是等于s1 = s1+1啊,没毛病啊。但是,这个等价是需要在一定条件下才满足的,比如,右边s1+1的结果类型与左边s1的类型相等,它们才会等价。
在上题中,s1是short类型的,而s1+1是int型的,很明显左右类型不等,而且int型不能自动向下转型为short型,所以A会报错;
B选项中,s1 += 1的运算,首先会计算右边的:s1+1,结果是2,int类型的,然后把结果2放到s1中,同时将s1的类型转为short类型
下面就来仔细看看java的类型转换规则:摘自(http://www.cnblogs.com/lwbqqyumidi/p/3700164.html)
1.基本数据类型中,java支持自动向上转型,不支持自动向下转型。向上向下的意思是类型的取值范围大小,大的就属于上层(如long>int>short>byte),小的就属于下层(如doublt>float);当将一个数值范围小的类型赋给一个数值范围大的数值型变量(如int赋给long),jvm在编译过程中俊将此数值的类型进行了自动提升。在数值类型的自动类型提升过程中,数值精度至少不应该降低(整型保持不变,float赋给double时精度将变高)。
public class TestCast {
public static void main(String[] args) {
long a = 10000000000; //编译出错: The literal 10000000000 of type int is out of range
long b = 10000000000L; //编译正确
int c = 1000;
long d = c;
float e = 1.5F;
double f = e;
}
}
如上:定义long类型的a变量时,将编译出错,原因在于10000000000默认是int类型,而int类型的数值范围是-2^31 ~ 2^31-1,因此,10000000000已经超过此范围内的最大值,故而其自身已经编译出错,更谈不上赋值给long型变量a了。
此时,若想正确赋值,改变10000000000自身默认的类型即可,直接改成10000000000L即可将其自身类型定义为long型。此时再赋值编译正确,如b。
将值为1000的int型变量c赋值给long型变量d,按照上文所述,此时直接发生了自动类型提升, 编译正确。同理,将e赋给f编译正确。
接下来,还有一个地方需要注意的是:char型其本身是unsigned型,同时具有2个字节,其数值范围是0 ~ 2^16-1,这直接导致 byte型不能自动类型提升到char,char和short直接也不会发生自动类型提升(因为负数的问题).但是,byte(1字节)当然可以直接提升到short型(2字节)。2.boolean类型不能与其他类型进行类型转换,否则将编译出错。
3.在Java整数类型(byte/short/int/long)中,对于未声明数据类型的整形,其默认类型为int型。在浮点类型(float/double)中,对于未声明数据类型的浮点型,默认为double型
public class TestCast {
public static void main(String[] args) {
byte a = 1000; // 编译出错 Type mismatch: cannot convert from int to byte
float b = 1.5; // 编译出错 Type mismatch: cannot convert from double to float
byte c = 3; // 编译正确
int d = 3;
byte e = d; // 编译出错 Type mismatch: cannot convert from int to byte
final int f = 3;
byte g = f; //编译正确
}
}
首先了解一下,byte类型占1个字节,取值范围为:-128~127;第一条语句,a是byte类型,1000是没有声明的数据类型,所以是int类型(占4字节),且超过byte的最大值127;所以int不会隐式转换为byte类型,编译出错;
float占4个字节,1.5是没有声明的浮点型,默认是double型(占8字节),double转为float属于向下转型,所以也会编译出错;
而c变量,3是int型,按理说int型转为byte型会编译报错;但是jvm在编译int型数据时,如果int型数据(这里为3)在左边变量类型(这里的c是byte类型)的取值范围内,那么会自动进行隐式类型转换(这里是int转为byte类型,为什么?因为3在byte的取值范围-128~127之间啊)。
有了上面这一点,那么也能解释变量a为什么编译出错了,因为1000不在-127~127之间,也就不会自动转换(就算转了你这个a也装不下啊)。
再来看d和e的转换,d是int类型的3,按照上面的说法,应该能隐式转换为byte类型啊。其实不然,区别在于前者c中的3是直接量,编译期间可以直接进行判定,后者d为一变量,需要到运行期间才能确定,也就是说,编译期间为以防万一,当然不可能编译通过了。此时,需要进行强制类型转换。
而同样的g却编译正确,这是为什么呢?因为f是用final修饰的,用final修饰后,相当于f的值已经确定为常量3了,所以将3赋给g时允许的。
有了以上的知识,我们再回头看开篇的那道面试题:
short s1 = 1;这句应该都能理解,1是int类型,非变量,且在short类型的取值范围内,所以int会隐式转换short;
short s1 = s1 + 1;s1+1是int类型,由于s1是变量,所以编译期不能确定其值,不能直接由int转成short,编译会报错;
short s1 += 1;符号“+=”表示先把右边结果强制转换为左边的数据类型,然后再赋值给左边