【发布时间】:2013-07-29 22:40:56
【问题描述】:
我不明白为什么 java 不进行扩展然后自动装箱。
Integer i = (short) 10;
我认为会发生以下情况:
- 首先将转换范围从
10缩小到short。 -
然后
short会扩大到int。 -
然后
int会自动装箱到Integer。
反而是编译错误。
示例 2:
短 x = 10;
整数 y = x;
这也失败了。
【问题讨论】:
标签: java type-conversion
我不明白为什么 java 不进行扩展然后自动装箱。
Integer i = (short) 10;
我认为会发生以下情况:
10 缩小到short。short 会扩大到int。int 会自动装箱到Integer。反而是编译错误。
示例 2:
短 x = 10;
整数 y = x;
这也失败了。
【问题讨论】:
标签: java type-conversion
根据JLS, Section 5.2,它处理赋值转换:
分配上下文允许使用以下之一:
身份转换 (§5.1.1)
加宽基元转换 (§5.1.2)
扩大参考转换 (§5.1.5)
一个装箱转换(第 5.1.7 节)可选地后跟一个加宽 参考转化
一个拆箱转换 (§5.1.8) 可选地后跟一个加宽 原始转换。
不能同时应用两个转换(加宽原始转换和装箱转换);此处只能应用一次转换,因此必须导致错误。
解决方案是将short 强制转换回int(强制转换),这将允许赋值转换成为装箱转换:
Integer i = (int) (short) 10;
(或者在这里,首先不要将其转换为short。)
Integer i = 10;
【讨论】:
Short 和Integer 之类的包装对象时,重要的是要认识到Short 不是 Integer;一个不子类化另一个。您在此处引用的转换(扩大引用转换)在此处不适用。
这里发生的是从int 到short 的强制转换,然后是从short 到Integer 的尝试赋值转换。
分配转换 (§5.2) 允许先装箱然后加宽,但不允许先加宽然后装箱。
分配上下文允许使用以下之一:
身份转换 (§5.1.1)
加宽基元转换 (§5.1.2)
扩大参考转换 (§5.1.5)
一个装箱转换(第 5.1.7 节)可选地后跟一个加宽 参考转化
一个拆箱转换 (§5.1.8) 可选地后跟一个加宽 原始转换。
【讨论】:
short 到 int 是扩大的原始转换,int 到 Integer 是装箱转换。赋值转换只能执行这两个操作之一,不能同时执行。
在 java 中,无论您是否在做,它都遵循“自动装箱然后加宽”的顺序 这 : 整数 x =5; 对象 obj = x;
或者 这个:
int x = 5; 长 l = x;
仅当存在 is-a 关系时才会发生扩展。
因此,虽然应用上述序列的第一种情况对编译器非常有效,因为 int 将自动装箱为 Integer,然后分配给 Object,即加宽(即先自动装箱,然后加宽),处于 Is-A 关系。但是在第二种情况下,如果 int x 是 autbox 到 Integer 并且分配给 Long 则不允许,因为不是 is-a 关系,因此会引发编译错误。
【讨论】:
可以在自动装箱和扩展方面使用重载来模拟类似的用例。
public static void m(short s) {
System.out.println("widening");
}
public static void m(Integer i) {
System.out.println("Autoboxing");
}
public static void main(String[] args) {
short x = 10;
m(x);
}
输出:加宽
因此,简而言之,我们可以说,Java 中的自动装箱占主导地位
【讨论】: