我不明白为什么 java 不进行扩展然后自动装箱。
Integer i = (short) 10;
我认为会发生以下情况:
10
首先从到缩小转换short
。short
然后会扩大到int
。int
然后会自动装箱到Integer
.
相反,这是一个编译错误。
示例 2:
短 x = 10;
整数 y = x;
这也失败了。
我不明白为什么 java 不进行扩展然后自动装箱。
Integer i = (short) 10;
我认为会发生以下情况:
10
首先从到缩小转换short
。short
然后会扩大到int
。int
然后会自动装箱到Integer
.相反,这是一个编译错误。
示例 2:
短 x = 10;
整数 y = x;
这也失败了。
根据JLS,第 5.2 节,处理赋值转换:
赋值上下文允许使用以下之一:
身份转换(§5.1.1)
扩大的原始转换(§5.1.2)
扩大参考转换(§5.1.5)
一个装箱转换(第 5.1.7 节)可选地后跟一个扩大的参考转换
一个拆箱转换(第 5.1.8 节)可选地后跟一个扩大的原始转换。
不能同时应用两个转换(加宽原始转换和装箱转换);此处只能应用一次转换,因此必须导致错误。
解决方案是将short
back 转换为int
(转换转换),这将允许赋值转换成为装箱转换:
Integer i = (int) (short) 10;
(或者在这里,首先不要将其投射到short
。)
Integer i = 10;
这里发生的是从int
to的强制转换short
,然后是从short
to的尝试赋值转换Integer
。
赋值转换(第 5.2 节)允许先装箱然后加宽,但不允许先加宽然后装箱。
赋值上下文允许使用以下之一:
身份转换(§5.1.1)
扩大的原始转换(§5.1.2)
扩大参考转换(§5.1.5)
一个装箱转换(第 5.1.7 节)可选地后跟一个扩大的参考转换
一个拆箱转换(第 5.1.8 节)可选地后跟一个扩大的原始转换。
在 java 中,无论您是否这样做,它都遵循“自动装箱然后加宽”的顺序: int x =5; 对象 obj = x;
或这个:
诠释 x = 5; 长 l = x;
只有当存在一种关系时才会发生扩大。
因此,虽然应用上述序列第一种情况对编译器非常有效,因为 int 将自动装箱为 Integer,然后分配给 Object,即扩大(即先自动装箱然后扩大),处于 Is-A 关系。但是在第二种情况下,如果 int x 是对 Integer 的 autbox 并且对 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 中,Widening 支配着 Autoboxing