为什么“short 30 = 3 * 10”是一个合法的任务?
如果short
在算术运算中被自动提升为int
,那么为什么是:
short thirty = 10 * 3;
一个short
variables的法定分配thirty
?
反过来,这个:
short ten = 10; short three = 3; short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED
以及这个:
int ten = 10; int three = 3; short thirty = ten * three; // DOES NOT COMPILE AS EXPECTED
不会编译,因为如果不按预期方式转换,则不允许将int
值分配给short
。
数字文字有什么特别的吗?
因为编译器本身在编译时用编译器replace了10*3
。 所以,有效地:在编译时间计算short thirty = 10 * 3
。
尝试改变ten
和three
final short
(使他们编译时间常量),看看会发生什么:P
使用javap -v
检查两个版本的字节码( 10*3
和final short
)。 你将能够看到没有什么区别。
好的,所以,这里是不同情况下的字节码差异。
情况1 :
Java代码:main(){short s = 10 * 3; }
字节码:
stack=1, locals=2, args_size=1 0: bipush 30 // directly push 30 into "s" 2: istore_1 3: return
情况-2:
public static void main(String arf[]) { final short s1= 10; final short s2 = 3; short s = s1*s2; }
字节码:
stack=1, locals=4, args_size=1 0: bipush 10 2: istore_1 3: iconst_3 4: istore_2 5: bipush 30 // AGAIN, push 30 directly into "s" 7: istore_3 8: return
情况-3:
public static void main(String arf[]) throws Exception { short s1= 10; short s2 = 3; int s = s1*s2; }
字节码:
stack=2, locals=4, args_size=1 0: bipush 10 // push constant 10 2: istore_1 3: iconst_3 // use constant 3 4: istore_2 5: iload_1 6: iload_2 7: imul 8: istore_3 9: return
在上述情况下, 10
和3
取自局部variabless1
和s2
是的,在字面情况下有一些特殊的情况:在编译时将会评估10 * 3
。 所以你不需要一个明确的(short)
转换乘以文字。
ten * three
不是编译时可评估的,所以需要一个明确的转换。
如果ten
和three
标记为final
那将是另一回事。
以下答案添加了JLS部分和关于此行为的一些细节。
根据JLS§15.2 – expression式的forms
有些expression式的值可以在编译时确定。 这些是常量expression式(§15.28)。