Java允许将字节分配给java.lang.Short,但不允许分配给java.lang.Integer
final byte b = 12; Short s = b; Integer i = b;
程序编译为Short,但是对于Integer编译,“不兼容类型”消息失败。
我很难理解这种行为。 我找不到这个特定场景的任何东西..
我试图用更广泛的赋值语境复制它:
final byte b = 12; Byte b2 = b; Character c = b; // Only an error if b isn't final char c2 = b; // Only an error if b isn't final Short s = b; // Only an error if b isn't final short s2 = b; Integer i = b; // Error, as indicated in the question int i2 = b; Long l = b; // Also an error long l2 = b; Float f = b; // Also an error float f2 = b; Double d = b; // Also an error double d2 = b;
不仅要分配给Integer
,还要分配给Float
, Long
或Double
也是一个错误。
有趣的是,如果b
的原始声明不是final
,那么分配给Character
, char
或Short
也会失败。
JLS的第5.2节对分配上下文及其允许的转换主题略有说明。
赋值上下文允许使用以下之一:
身份转换(第5.1.1节)
扩展的原始转换(第5.1.2节)
扩大参考转换(第5.1.5节)
一个拳击转换(第5.1.7节),可选地后跟一个加宽的引用转换
一个拆箱转换(第5.1.8节),可选地后跟一个加宽的基元转换。
这涵盖了所有转换为更宽的原始变量,这些变量始终是允许的,无论b
是否为final
。 (除非b
为负数,否则保持不变,在这种情况下,对unsigned char
(或Character
)的赋值将失败。)继续:
此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):
如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。
如果变量的类型是:则可以使用缩小的基元转换,然后进行装箱转换:
字节和常量表达式的值可在类型字节中表示。
Short和常量表达式的值可以在short类型中表示。
字符和常量表达式的值可在char类型中表示。
因为b
是final
,所以表达式b
是一个常量表达式 ,允许它从int
常量表达式12
缩小到byte
, char
或short
,然后装箱到Byte
, Character
或Short
,但奇怪的是,不是Integer
或任何东西“以上”。 我能想到的唯一可能的解释是,不能特别允许将原始缩小转换的常量表达式转换为Integer
, Long
, Float
或Double
。
如果b
不是final
,则不允许缩小后跟装箱,并且也不能将非常量表达式从byte
提升到char
。