关于基本类型的简单赋值和复合赋值运算
来源:互联网 发布:淘宝卖家如何删除订单 编辑:程序博客网 时间:2024/05/08 23:13
通过阅读下面转载的文章,Kaiwii学习到以下的内容:
1、需要判断一个变量的类型,可以采用下面的方式完成:
假如我要弄清楚2.0/SAMPLING_COUNT的结果的类型,Kaiwii可以这样做:
Object var=2.0/SAMPLING_COUNT;System.out.println(var.getClass().getSimpleName());
2、可以通过查看和比较生成的class文件来判断两种写法的实际执行过程是否一样
3、自动提升类型和自动降低类型的理解:
在运算过程中,一般情况下会进行进行自动提升类型,也就是一个低精度的变量为了与高精度的变量进行运算而发生的低精度向高精度类型转换的过程。比如文中提到的:
short s1 = 1; s1 = s1 + 1;
为什么不正确,是因为1是int类型的,所以S1与其发生运算的过程中会升级为int类型,所以最终生成的结果的类型应该是int的。一个int类型的变量怎么可以赋值到一个shor类型的变量中去呢?除非使用强制转换的方式吧……
另外,只有在直接将一个常量值赋值给一个变量的时候,才可能发生自动降低类型的情况。比如文中提到的情况:
short i=1
分析:1是int类型的常量,可以通过自动降低类型的方式赋值给一个更低精度的变量i
其中,比较特殊的自动降低类型的方式还包括:
short i+=1好吧,Kaiwii说了那么废话,直接上原文吧……
有一道很经典的面试题是这样的:
short s1 = 1; s1 = s1 + 1; 有什么错? short s1 = 1; s1 += 1;有错吗?
答案很简单:
1. 编译出错。类型不匹配,需要强制类型转换。
2. 没有错误。
有一朋友说不是太明白这是为什么。我在这里分析一下原因。
对于前半部分:
- short s1 = 1; s1 = s1 +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。我们看一下这个例子:
- short s1 = 1;
- Object result = s1 + 1;
- System.out.println(result.getClass().getSimpleName());
short s1 = 1;Object result = s1 + 1;System.out.println(result.getClass().getSimpleName());
结果是:
Integer
从结果可以看出,结果是int的包装类Integer。所以s1 + 1的结果是int类型的。因此把s1 + 1重新赋值给s1,即s1 = s1 + 1,会丢失精度,编译出错。
对于后半部分 s1 += 1,个人认为可以分为两部分,见下面代码:
- short s1 = 1;
- s1 = (short)((int) s1 +1);
short s1 = 1;s1 = (short)((int) s1 + 1);
这样解释的原因可以再看下面的例子:
- public class Test {
- public void test1(){
- short s1 = 1;
- s1 = (short)((int) s1 +1);
- }
- public void test2() {
- short s1 = 1;
- s1 += 1;
- }
- }
public class Test {public void test1(){short s1 = 1;s1 = (short)((int) s1 + 1);}public void test2() {short s1 = 1;s1 += 1;}}
查看Test.class文件的字节码文件:
- public void test1();
- 0 iconst_1
- 1 istore_1 [s1]
- 2 iload_1 [s1]
- 3 iconst_1
- 4 iadd
- 5 i2s
- 6 istore_1 [s1]
- 7 return
- Line numbers:
- [pc: 0, line: 4]
- [pc: 2, line: 5]
- [pc: 7, line: 6]
- Local variable table:
- [pc: 0, pc: 8] local:this index: 0 type: Test
- [pc: 2, pc: 8] local: s1 index:1 type: short
- public void test2();
- 0 iconst_1
- 1 istore_1 [s1]
- 2 iload_1 [s1]
- 3 iconst_1
- 4 iadd
- 5 i2s
- 6 istore_1 [s1]
- 7 return
- Line numbers:
- [pc: 0, line: 9]
- [pc: 2, line: 10]
- [pc: 7, line: 11]
- Local variable table:
- [pc: 0, pc: 8] local:this index: 0 type: Test
- [pc: 2, pc: 8] local: s1 index:1 type: short
public void test1(); 0 iconst_1 1 istore_1 [s1] 2 iload_1 [s1] 3 iconst_1 4 iadd 5 i2s 6 istore_1 [s1] 7 return Line numbers: [pc: 0, line: 4] [pc: 2, line: 5] [pc: 7, line: 6] Local variable table: [pc: 0, pc: 8] local: this index: 0 type: Test [pc: 2, pc: 8] local: s1 index: 1 type: short public void test2(); 0 iconst_1 1 istore_1 [s1] 2 iload_1 [s1] 3 iconst_1 4 iadd 5 i2s 6 istore_1 [s1] 7 return Line numbers: [pc: 0, line: 9] [pc: 2, line: 10] [pc: 7, line: 11] Local variable table: [pc: 0, pc: 8] local: this index: 0 type: Test [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会自动提升类型的表达式为:
- short +|-|*|/|% short = (int)short +|-|*|/|% (int)short;
- byte +|-|*|/|% byte = (int)byte +|-|*|/|% (int)byte;
- char +|-|*|/|% char = (int)char +|-|*|/|% (int)char;
short +|-|*|/|% short = (int) short +|-|*|/|% (int) short;byte +|-|*|/|% byte = (int) byte +|-|*|/|% (int) byte;char +|-|*|/|% char = (int) char +|-|*|/|% (int) char;
因为这些类型的运算很容易就会越界。它们之间的任意组合都会先转换成int,然后再运算,结果为int类型。但是遇到更高精度的操作数,如float、double,它们也会向float、double自动提升类型。自动提升类型除基本赋值外,都是向精度高的方向进行的。
对于short、byte、char的基本赋值,就像short s1 = 1;是int类型自动降低类型到short的。
- 关于基本类型的简单赋值和复合赋值运算
- 关于基本类型的简单赋值运算和复合赋值运算
- 复合赋值运算符
- Java复合赋值运算
- 复合赋值运算总结
- 复合赋值运算符的应用
- 复合赋值运算符的使用
- 关于自增和赋值的运算
- 复合赋值操作符和简单赋值操作符的区别。
- java 赋值操作符:基本类型的赋值和对象的赋值
- swift-基本操作02-自增和复合赋值运算符
- (集合和引用类型、基本数据类型赋值不一样)一个简单的java问题 先后的赋值问题
- 基本赋值运算符和扩展赋值运算符的区别
- 【java解惑】复合赋值与简单赋值
- JS基本类型和引用类型赋值的区别
- Swift语法基础:11 - Swift的运算术语, 赋值运算, 数值运算, 复合赋值
- 基本类型和引用类型赋值
- 赋值 和复合赋值操作符
- 读 input 子系统
- 深入解说:ARM流水线、PC值和冯诺依曼、哈佛结构
- 关于让WPF软件界面支持全球化和本地化
- JAVA复制对象给另一个对象
- 理解ThreadLocal
- 关于基本类型的简单赋值和复合赋值运算
- Java编程中“为了性能”尽量要做的几点
- ASP.NET生成静态页面的四种方法
- C#与Oracle插入或修改或查询时间的处理
- JMF 视频传输
- Xcode4.2+SVN代码管理研究(一)
- 在路上,仅作记录
- 对volatile修饰符的理解和使用
- 为jquery-easyui 树添加,删除,修改树的节点