short s1 = 1; s1 = s1 + 1;我知道有错因为s1+1运算结果是int型,需要强制转换类型
但为什么short s1 = 1; s1 += 1;不会有错呢?
但为什么short s1 = 1; s1 += 1;不会有错呢?
解决方案 »
- 关于怎么样从c的思维转到java面向对象的思维上,高手有什么可以给些建议吗?
- 帮忙解决一下
- 求助:java如何操作windows日志文件
- StringTokenizer
- 大家用过.jj文件没?好像用javacc来编译,最近需要用到编解码,要用这个,不太了解,请了解的哥们出来说名一下,多谢了
- 使用jni调用c++编译的dll为什么不是立即执行?
- 关于getScaledInstance()进行图形压缩处理的问题
- 怎样在JTextArea控件中,对不同行的字体设置不同的颜色?
- 那位大虾知道,那里有jb6下载
- 解释简单语句!给30分!
- 请教各位:ResultSet
- 显示未定义超隐式构造函数Transport(),必须显示调用另一个构造函数。方法main不能声明为静态和无法解析wh。大侠请赐教,偶是初学者。方法main不能声明为静态以及无法解析wh。偶是初学者,请大侠们赐教
short s1 = 1;
int i = 1;
首先,因为short类型是16位的,而int类型是32位的,在进行
(s1+i) 运算时,自动将s1提升到32位,然后与i相加,得到的结果是32位的,而此时
s1=s1+i; 必然报错,因为如果赋值成功,只是把低16位赋给了s1,这个虽然正是楼主想要的结果,但是编译程序却不能判定你的意图是什么.
执行强转:
s1=(short)(s1+i); 就没问题了.
s1+=i;能编译通过并得到正确结果,而 s1=s1+i; 却报错,是因为它们并不像楼主认为的那样是等价的,s1+=i的方式java会对i进行窄化转换,由编译程序自动执行.
java规范中说:
E1 op=E2 实际上等价于 : E1=(T)( (E1)op(E2) )
其中T是E1的数据类型.这种类型转换或者是一个恒等转换,或者是一个窄化转换.
这个说明java是一种强类型的语言,对数据类型的要求是非常严格的,否则会引起混乱.
下面解释一下三种类型转换:恒等转换(相同容量的两个数据类型之间的赋值);拓宽转换(小容量类型赋值给大容量类型);窄化转换(大容量赋值给小容量类型). 实际上,前两种转换都是编译程序自动执行的,而窄化转换则要求必须显式的执行.
第一种方式:
short s1 = 1; s1 = s1 + 1;需强行转化
因为short s1=1在栈中开辟了一个short类型的空间;
而s1=s1+1;中s1是short类型,在栈中开辟了一个short类型的空间,而1是int类型,
int类型比short类型大,所以相加后的结果应为比较大的类型,把s1+1的结果赋予short类型的变量s1,固然需要强行转化;
第二种方式:
short s1 = 1; s1 += 1;(可以正确编译)
由于+=运算符有自加功能,定义short s1 = 1;时,开辟了一个空间,当通过+=运算符运算时,只是在原来的栈中进行运算;不需强行转化;
如上面的s1 += 1; 他的结果是short型的。
而s1 = s1 + 1;“+”是不会窄化转换的,它执行时由于1是int的,结果也将隐式转换为int的。
short s2 = 1;
s1 = s1 + s2;//两个short相加为什么了是错的.
short s2 = 1;
s1 = s1 + s2;//两个short相加为什么了是错的.
对于short类型 jvm没有提供运算支持,它们的运算都是通过提升为int进行的。
举个例子 ,public class Test{
public static void main(String[] args){
short i=1;
i+=1;
short j=8;
short k=(short)(i+j);
System.out.println(i);
System.out.println(j);
System.out.println(k);
}
}bytecode:Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: returnpublic static void main(java.lang.String[]);
Code:
0: iconst_1 //常数1放入栈顶
1: istore_1 //存入 局部变量i,实现 赋值运算i=1
2: iload_1 //读入i放到栈顶
3: iconst_1 //常数1放入栈顶
4: iadd //int加法,计算i+1,结果放到栈顶
5: i2s //把int转换为short
6: istore_1 //把short存入i
7: bipush 8
9: istore_2
10: iload_1
11: iload_2
12: iadd
13: i2s //int转换为short
14: istore_3
15: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
18: iload_1
19: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
22: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
25: iload_2
26: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
29: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
32: iload_3
33: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
36: return}跟汇遍差不多,应该很容易理解,不过jvm的指令是基于栈的,不是基于寄存器的。
关键看看i2s指令 ,i+=1;时编译器自动会加上强制转换语句
其他情况下是需要自己强制转换
short s1 = 1; s1 = s1 + 1;我知道有错因为s1+1运算结果是int型,需要强制转换类型
但为什么short s1 = 1; s1 += 1;不会有错呢?
因为第一种是s1=s1+1这时s1又从新开辟拉一个新地址空间,跟原来的不一样啦,所以他的类型也不一样啦
,那么第二种没有重新开辟空间,还是原来的地址空间,所以类型还没有变化亚
----Thinking in Java (4th)
所以,你想要对的,只有
s1 = (short)s1 + s2;
PS:前面的是真高手,并非文盲....
E1 op=E2 实际上等价于 : E1=(T)( (E1)op(E2) )
能说明这个问题!
s1 = (short)(s1 + s2);
....
哪位解释一下,是不是c环境下不存在此问题??