关于基本类型的简单赋值运算和复合赋值运算

原文网址:http://tianlihu.iteye.com/blog/376603

有一道很经典的面试题是这样的: 

short s1 = 1; s1 = s1 + 1; 有什么错? short s1 = 1; s1 += 1;有错吗? 

答案很简单: 
1. 编译出错。类型不匹配,需要强制类型转换。 
2. 没有错误。 

有一朋友说不是太明白这是为什么。我在这里分析一下原因。 
对于前半部分: 
Java代码   收藏代码
  1. short s1 = 1; s1 = s1 + 1;  

   在java语言规范里,如果表达式中, 当对中间值的精确要求有时可能会超过任何一个操作数的范围, JVM会临时自动提升这个操作数的类型。 
    像我们这个题目的前面部分,s1 + 1, 我们把类型写出来s1(short) + 1(int)这时JVM会自动把s1先提升成int,然后再跟后面的1(int)相加,这样就是int + int的运算了。但是为什么会有编译错误呢?因为int + int的结果还是int。我们看一下这个例子: 
Java代码   收藏代码
  1. short s1 = 1;  
  2. Object result = s1 + 1;  
  3. System.out.println(result.getClass().getSimpleName());  

结果是: 
Integer 

从结果可以看出,结果是int的包装类Integer。所以s1 + 1的结果是int类型的。因此把s1 + 1重新赋值给s1,即s1 = s1 + 1,会丢失精度,编译出错。 

对于后半部分 s1 += 1,个人认为可以分为两部分,见下面代码: 
Java代码   收藏代码
  1. short s1 = 1;  
  2. s1 = (short)((int) s1 + 1);  

这样解释的原因可以再看下面的例子: 
Java代码   收藏代码
  1. public class Test {  
  2.     public void test1(){  
  3.         short s1 = 1;  
  4.         s1 = (short)((int) s1 + 1);  
  5.     }  
  6.       
  7.     public void test2() {  
  8.         short s1 = 1;  
  9.         s1 += 1;  
  10.     }  
  11. }  

查看Test.class文件的字节码文件: 
Java代码   收藏代码
  1. public void test1();  
  2.    0  iconst_1  
  3.    1  istore_1 [s1]  
  4.    2  iload_1 [s1]  
  5.    3  iconst_1  
  6.    4  iadd  
  7.    5  i2s  
  8.    6  istore_1 [s1]  
  9.    7  return  
  10.      Line numbers:  
  11.        [pc: 0, line: 4]  
  12.        [pc: 2, line: 5]  
  13.        [pc: 7, line: 6]  
  14.      Local variable table:  
  15.        [pc: 0, pc: 8] local: this index: 0 type: Test  
  16.        [pc: 2, pc: 8] local: s1 index: 1 type: short  
  17.    
  18.  public void test2();  
  19.    0  iconst_1  
  20.    1  istore_1 [s1]  
  21.    2  iload_1 [s1]  
  22.    3  iconst_1  
  23.    4  iadd  
  24.    5  i2s  
  25.    6  istore_1 [s1]  
  26.    7  return  
  27.      Line numbers:  
  28.        [pc: 0, line: 9]  
  29.        [pc: 2, line: 10]  
  30.        [pc: 7, line: 11]  
  31.      Local variable table:  
  32.        [pc: 0, pc: 8] local: this index: 0 type: Test  
  33.        [pc: 2, pc: 8] local: s1 index: 1 type: short  

    除了11-13行和28-30行的内的行号不同之外,其余部分都一样。即这两上写法其实是等效的。 
    s1 = (short)((int) s1 + 1);  可以简化为s1 = (short)(s1 + 1);因为从short到int JVM会自动提升类型。 

    最后补充一点,JVM会自动提升类型的表达式为: 
Java代码   收藏代码
  1. short +|-|*|/|% short = (intshort +|-|*|/|% (intshort;  
  2. byte  +|-|*|/|% byte  = (intbyte  +|-|*|/|% (intbyte;  
  3. char  +|-|*|/|% char  = (intchar  +|-|*|/|% (intchar;  

   因为这些类型的运算很容易就会越界。它们之间的任意组合都会先转换成int,然后再运算,结果为int类型。但是遇到更高精度的操作数,如float、double,它们也会向float、double自动提升类型。自动提升类型除基本赋值外,都是向精度高的方向进行的。 
   对于short、byte、char的基本赋值,就像short s1 = 1;是int类型自动降低类型到short的。 
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值