为什么 "short thirty = 3 * 10" 是合法的赋值?

Why is "short thirty = 3 * 10" a legal assignment?

如果在算术运算中short自动提升为int,那么为什么是:

short thirty = 10 * 3;

short 变量的合法赋值 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

数字文字有什么特别之处吗?

是的,字面大小写有一些特殊之处:10 * 3 将在 compile 时计算。所以你不需要对乘法文字进行显式 (short) 转换。

ten * three 编译时不可评估,因此需要显式转换。

如果tenthree标记为final就另当别论了。

因为编译器在 编译时 本身将 10*3 替换为 30。所以,实际上: short thirty = 10 * 3 是在编译时计算的。

尝试将 tenthree 更改为 final short(使它们成为编译时间常量),看看会发生什么:P

使用 javap -v 检查两个版本(10*3final short)的字节码。你会发现差别不大。

好的,所以,这是不同情况下的字节码差异。

案例-1 :

Java Code : 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 

在上面的例子中,103取自局部变量s1s2

以下 answer 添加了 JLS 部分和有关此行为的一些详细信息。

根据JLS §15.2 - Forms of Expressions

Some expressions have a value that can be determined at compile time. These are constant expressions (§15.28).