昨天和今天,看到两个跟赋值语句中类型转换有关的帖子:http://bbs.itheima.com/thread-126799-1-1.html 和http://bbs.itheima.com/thread-121036-1-1.html 。概括一下,涉及这么几个赋值语句:
1. short b = 1;
2. short b = 1; ++b;
3. short b = 1; b+=1;
4. short b = 1; b = b + 1;
前三段代码没问题,最后一段代码编译器会报错:cannot convert from int to short
我之前学过C,C标准规定,整数常量的类型是能容纳该整数的最小类型。所以在C中,b=b+1是不会报错的。Java不一样,Java语言规范明确说:整数常量如果末尾带L是long类型,不带L则是int类型(An integer literal is of type long if it is suffixed with an ASCII letter L or l (ell); otherwise it is of type int )。所以1是int类型,b+1的结果是int类型,而b是short类型,int赋值给short又没有经过强转就会报错。按这个思路,++和+=为啥不报错?有人说++和+=会自动强转。好,我先接受这个说法。那么b=1为什么也不报错?
带着困惑,我又去查了Java语言规范。Java把short、byte提升到int这种情况称为widening conversion,把int转为short或byte这种情况称为narrowing conversion。在赋值时,Java要求赋值=右边的类型必须被转为=左边的类型。Java会自动执行5种转换,其中有widening conversion而没有narrowing conversion。所以, 上面第4段代码中b=b+1的右边是int,Java不会自动转为short,于是造成=左右类型不一致,报错。
好,问题来了:
short b=1 、++b 和 b+=1也有int转short的情况,为什么不报错?答案只能是:它们属于特殊情况。
对于short b = 1 Java语言规范说:如果=的右边是常量表达式,而且类型是byte、short、char或int,那么Java在必要时会自动执行narrowing conversion,只要这个常量表达式的值在=左边变量的取值范围之内(if the expression is a constant expression of type byte, short, char, or int: A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable) 哦,原来如此!short b = 1; 1是常量表达式,类型是int,且在short的取值范围之内,所以Java自动强转,不会报错。但如果你写short b=200000,200000虽然是常量,但超过short取值范围,照样报错。
对于++, Java语言规范说:如有必要,++计算之后的结果会先执行narrowing conversion,再存入变量中(If necessary, the sum is narrowed by a narrowing primitive conversion and/or subjected to boxing conversion (§5.1.7) to the type of the variable before it is stored)。也就是说,虽然b是short类型,但Java在++运算上的自动强转保证了++b不会报错
同样,对于+=Java也会自动强转。对于b+=1,Java会转成b = (short)(b+1)
因为之前受C语言的影响,这两天看到相关帖子,搞得我云里雾里。查了Java语言规范,总算是搞清楚了,发出来和大家分享一下 |
|