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 ,还要分配给FloatLongDouble也是一个错误。

有趣的是,如果b的原始声明不是final ,那么分配给CharactercharShort也会失败。

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类型中表示。

因为bfinal ,所以表达式b是一个常量表达式 ,允许它从int常量表达式12缩小到bytecharshort ,然后装箱到ByteCharacterShort ,但奇怪的是,不是Integer或任何东西“以上”。 我能想到的唯一可能的解释是,不能特别允许将原始缩小转换的常量表达式转换为IntegerLongFloatDouble

如果b不是final ,则不允许缩小后跟装箱,并且也不能将非常量表达式从byte提升到char