表达式类型的陷阱

Java语言规定:当一个算术表达式中包含多个基本类型的值时,整个算术表达式的数据类型将发生自动提升。Java语言中的自动提升规则如下:

  • 所有byte型、short型和char型将被提升为int型
  • 这个算术表达式的数据类型自动提升到与表达式中最高等级操作数同样的类型。操作数的等级排列如下所示:
表达式类型的陷阱
文章图片

例子:
public class Main { public static void main(String args[]) { //定义一个short类型的变量 short s=4; //表达式中的s将自动提升到int类型,则右边的表达式类型为int //将一个int类型赋给short类型的变量时将发生错误 s=s-2; byte b=2; char c='a'; int i=23; double d=.324; //右边表达式中在最高等级操作数为d(double型) //则右边表达式的类型为double型,故赋给一个double型变量 double result=b+c+i*d; System.out.println(result); int val=3; //右边表达式中2个操作数都是int,故右边表达式的类型为int //因此,虽然23/3不能除尽,依然得到一个int整数 int intResult=23/val; System.out.println(intResult); //程序自动将7、'a'等基本类型转化为字符串,输出字符串Hello!a7 System.out.println("Hello!"+'a'+7); //程序将'a'当成int处理,因此'a'+7得到104,输出字符串104Hello! System.out.println('a'+7+"Hello!"); } }

在复合赋值运算符中有点不同,由前面的介绍可知,下面的语句会引起编译错误:
short s=4; s=s-2;

因为s-2表达式的类型将自动提升为int类型,所以程序将一个int类型的变量赋给s时导致了编译错误。但是下面形式就没有任何问题:
short s=4; s-=2;

上面的表达式使用了复合赋值运算符,此时将不会产生编译错误。Java语言几乎允许所有的双目运算符和=一起结合成复合赋值运算符,如+=、-=、*=、/=、%=、<<=、>>=、>>>=、&=、^=、|=等。根据Java语言规范,复合赋值运算符包含了一个隐式的类型转换,即:
a+=5;

等价于
a=(a的类型)(a+5);

【表达式类型的陷阱】也就是说,复合赋值运算符会自动地将它计算的结果值强制类型转换为其左侧变量的类型,强制类型转换将有可能导致高位"截断"。

    推荐阅读