只是想了解自动装箱,除了一件事之外我做的:
Short s = 250;
Long l = 250;
对
Long l
的分配失败。我预计,这是因为你不能加宽 then box(即它试图将 int
值 250
加宽到 long
然后将它装箱,这是它做不到的)。
但是,对
Short s
的分配有效。是什么让这一切变得美好?我的假设是它仍在进行装箱和某种转换。但是,如果它知道 250
适合 short
,为什么它不知道 250
适合 long
?
通常,您不能在赋值中应用多个(隐式)转换(JLS §5.2 赋值转换):
赋值转换发生在将表达式的值赋值给变量(§15.26)时:表达式的类型必须转换为变量的类型。分配上下文允许使用以下之一:
- 身份转换(§5.1.1)
- 扩大原始转换(§5.1.2)
- 扩大参考转换(§5.1.5)
- 装箱转换(§5.1.7)可选地后跟扩大参考转换
- 拆箱转换(§5.1.8)可选地后跟扩大原始转换。
Long l=250;
需要两次转换(加宽原始转换,然后是装箱转换),这就是它无法编译的原因。
Long l=250l;
编译,因为它需要一次装箱转换。
但是常量表达式的收缩转换是一种特殊情况,这就是为什么
Short s=250;
编译:
此外,如果表达式是 byte、short、char 或 int 类型的常量表达式(§15.28):
- 如果变量的类型是 byte、short 或 char,并且常量表达式的值可以用变量的类型表示,则可以使用缩小原始转换。
- 如果变量的类型是:
- Byte 和常量表达式的值可以用 byte 类型表示。
- Short 并且常量表达式的值可以用 short 类型表示。
- 字符和常量表达式的值可以用 char 类型表示。
理想情况下,不允许自动缩小。
但是因为没有字节/短文字,我们不能写
byte b = 0b;
这似乎很傻
byte b = (byte)0;
所以常量整数的自动缩小是允许的,所以我们可以写
byte b = 0;
被带到自动装箱盒中。
对于 long/Long,因为有 long 字面值,所以这不是什么问题。不过,它应该被允许,因为有符号整数的自动扩展总是安全的。