short i = 6; i = i + 6;就是这2句代码第二句错误的原因: i是short 6是int (数字常量都是int型) ,加之前都转成int了,结果当然是int第一句没错的原因: 6是int类型,i是short类型,本来应该是错的,这种情况编译器自动做了转换,因为编译器能判断6可以精确的转为short ,而 i+6编译器就没办法判断了。
short ddddd = 222222;无法通过 是不是可以这样解释, 首先"222222"被当作int来看待,没超过范围;所以编译没有出现"out of range" 然后编译器再去看对应的ddddd类型,结果发现是short,所以把"222222"强制转为short,显然"222222"超过了short的范围,结果出现了"can't convert from int to short"
short i = 6 可以,因为6是常量,编译器在编译时就能知道6能不能装到short中 i = i + 6 不可以,因为i是变量,编译器在编译时不知道i多大,当然也不知道i+6多大,当然也就不知道i+6能不能装进short。再来看 final int i = 6; short j = i;可以,但把final去掉就不行。 这个例子应该充分说明常量和变量对编译器的区别了至于 float f = 2.0不行,只能归结于浮点数的特殊性了。在java中所有直接写的值,比如1,2,,3.0,'a'。都成为表示值(或字面值或其他什么) 对于不带小数点的数字表示值,一律当成int处理 带小数点的,一律当成double处理 short i = 6 i + 6 i是short,6是int,int+short,表达式上升为int 将int赋值给short肯定通不过编译,除非你做强制类型转换final short i = 6 i + 6则不同,编译器在编译时就可以确定i + 6 = 12,实际上在最后编译时,此处直接被12替代了。
short i = 0;i += 6可以 和上面说的一样 +=是复合赋值运算符 也就是说是赋值运算符 将一个明显能被short装下的常量赋值给一个short是可以的,编译器这么认为 即使 short i = 32767; i += 1;会溢出,这也可以
float f = 1.0通过不过应该这么理解 虽然你看见的是1.0,但编译器编译时,这里放的却可能是0.999999999999999999999999999 精度达到double的精度 这个精度如果要往float里面放,是会丢失精度的 所以这种赋值不允许浮点数有精度的问题,整数没,这就是浮点数的特殊性
i = i + 6;
i = i + 6;就是这2句代码
i = i + 6;就是这2句代码第二句错误的原因:
i是short 6是int (数字常量都是int型) ,加之前都转成int了,结果当然是int第一句没错的原因:
6是int类型,i是short类型,本来应该是错的,这种情况编译器自动做了转换,因为编译器能判断6可以精确的转为short ,而 i+6编译器就没办法判断了。
那么,float kkk = 1.0;为什么又编译不通过呢?
我们知道1.0默认应该是double类型,按照楼上的说法,编译器不能判断1.0可以精确的转为float?
嗯,了解;多谢
那么,float kkk = 1.0;为什么又编译不通过呢?
我们知道1.0默认应该是double类型,按照楼上的说法,编译器不能判断1.0可以精确的转为float?
kkk=1.0f就好了
我的理解和treeroot(旗鲁特)正好相反,
一个常数是什么类型,编译的时候就根据它的大小确定了的,只不过编译以后都是用的int类型存储,
比如
byte b=123;
int i=123;编译器确定123是byte类型,所以两个都是使用的bipush来调入,但是在压栈的时候都是使用的istore。当参与运算的时候,即使是
byte b2=b+b;
也是用的iload来调入数据的。所以运算结果必定是int。对于float和double,至于为什么无法在编译器来确定输入值是float还是double,我猜想是由于浮点数据的难以比较性所造成的,所有float和double在调入和压栈时都是分开来的。
因此可能flyforlove(吾将远去) 的说法("编译以后都是用的int类型存储")是正确的,因为2222222222这个超过了int的范围,但是在long的范围之内
? 又试验了一下: long xxx = 2222222222;这句无法编译通过
因此可能flyforlove(吾将远去) 的说法("编译以后都是用的int类型存储")是正确的,因为2222222222这个超过了int的范围,但是在long的范围之内---------------------------我可没有对long做过这个论断,如果是long的话,不管大小编译器都会在后面添加l并用lstore进行存储,你编译不通过是因为它已经超出了int的范围,必须手动在后面添加l
也就是long xxx = 2222222222l
这样就不会出错了。
记住,不管数值大小,只要声明了是long,都是用lstore来存储的。
如果真的是一个类似“2222222222”这种明确的整型数值,编译器就试图用int来“对付”它,那么就说的通。
是不是可以这样解释,
首先"222222"被当作int来看待,没超过范围;所以编译没有出现"out of range"
然后编译器再去看对应的ddddd类型,结果发现是short,所以把"222222"强制转为short,显然"222222"超过了short的范围,结果出现了"can't convert from int to short"
比如要是编译器强制需要long类型必须在后面添加l修饰符,也没有什么错。
(i + 6) 的结果默认是int类型,把int直接负值给 i的short类型有冲突!
所以 i=(short)(i+6)正解!
i+=6 相当于i+=(short)6 6被转成short型再参与运算.
int i=i+6;
是不对的!
知道"="运算规则吗?
它是从右到左运算的,所以编译器它没有那么聪明,它不会未卜先知!更不会把0作为初值首先赋值给右边的i.
至于上边他们讨论的类型转换,赋值,以及运算等,最好还是去查一查关于类型转换,定义类型时该注意些什么,什么时候需要强制性转换比较好!
如果是数据类型 小于 int , 运算时 数据类型会自动转为 int , 自然运行结果也是 int
所以你必须对
i = (short)(i+6);
对于一个在short范围里面的int 是可以把值赋给它的,不管是不是在定义中。
例如short i; i=12;这是可以的。但是为什么i=i+3不可以呢?那是因为在编译的时候,编译器
不能确认i+3的值在short范围里面。i+3的值只有在运行的时候程序才能知道它的值。至于float f=1.23;报错的原因:
这是规定。没有原因,java中就不容许double值直接赋给float.
大家如果学过c语言就知道,float f=1.23是可以通过编译的。那么为什么java中要这样定义呢?
1。
对于一个在short范围里面的int 是可以把值赋给它的,不管是不是在定义中。
2。
java中就不容许double值直接赋给float.那就是编java的人的思路了。
大家可以踊跃的猜一猜,但是没有标准答案哟。
我是这样猜的:
从int 到short 要么不能成功赋值,如果成功赋值后就不会丢失值。假如设定double可以转到float 的话。就会有三中情况:一,不能成功赋值。二,可以成功赋值,也没有丢失值。三,可以成功赋值,但是丢失了精度,比如:float f = 1.23456789;就得损失后面的几位。为了防止这种不经意的损失,java中就规定了:不容许double值直接赋给float.
其实编程很多地方都是死的,它没有数学那么严格的逻辑要求,别人怎么定义我们就怎么用了,
经常粘牛角尖只会浪费我们越来越多的时间。
i = i + 6 不可以,因为i是变量,编译器在编译时不知道i多大,当然也不知道i+6多大,当然也就不知道i+6能不能装进short。再来看
final int i = 6;
short j = i;可以,但把final去掉就不行。
这个例子应该充分说明常量和变量对编译器的区别了至于
float f = 2.0不行,只能归结于浮点数的特殊性了。在java中所有直接写的值,比如1,2,,3.0,'a'。都成为表示值(或字面值或其他什么)
对于不带小数点的数字表示值,一律当成int处理
带小数点的,一律当成double处理
short i = 6
i + 6
i是short,6是int,int+short,表达式上升为int
将int赋值给short肯定通不过编译,除非你做强制类型转换final short i = 6
i + 6则不同,编译器在编译时就可以确定i + 6 = 12,实际上在最后编译时,此处直接被12替代了。
和上面说的一样
+=是复合赋值运算符
也就是说是赋值运算符
将一个明显能被short装下的常量赋值给一个short是可以的,编译器这么认为
即使
short i = 32767; i += 1;会溢出,这也可以
虽然你看见的是1.0,但编译器编译时,这里放的却可能是0.999999999999999999999999999
精度达到double的精度
这个精度如果要往float里面放,是会丢失精度的
所以这种赋值不允许浮点数有精度的问题,整数没,这就是浮点数的特殊性