Java允许将字节分配给java.lang.Short,但不允许分配给java.lang.Integer

Paw*_*cik 8 java autoboxing type-conversion wrapper

final byte b = 12;  
Short s = b;  
Integer i = b;
Run Code Online (Sandbox Code Playgroud)

程序编译为Short,但是对于Integer编译失败,出现"不兼容类型"消息.

我很难理解这种行为.我找不到任何针对这种特定情况的东西..

rge*_*man 6

我试图用更广泛的赋值语境复制它:

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;
Run Code Online (Sandbox Code Playgroud)

不仅分配给a Integer,还分配给a Float,a Long或a Double也是一个错误.

有趣的是,如果原始声明b不是final,则分配给a Character,a char或a Short也失败.

JLS的第5.2节对分配上下文及其允许的转换主题略有说明.

赋值上下文允许使用以下之一:

  • 身份转换(§5.1.1)

  • 扩展的原始转换(第5.1.2节)

  • 扩大参考转换(第5.1.5节)

  • 一个拳击转换(§5.1.7),可选地后跟一个加宽的引用转换

  • 一个拆箱转换(第5.1.8节),可选地后跟一个加宽的基元转换.

这涵盖了所有的转换到更广泛的原始变量,它总是被允许的,不管bfinal或不是.(除非b是否定,否则保留,在这种情况下,对无符号char(或Character)的赋值将失败.)继续:

此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):

  • 如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示.

  • 如果变量的类型是:则可以使用缩小的基元转换,然后进行装箱转换:

    • 字节和常量表达式的值可在类型字节中表示.

    • Short和常量表达式的值可以在short类型中表示.

    • 字符和常量表达式的值可在char类型中表示.

因为bfinal,表达式b是一个常量表达式,允许它从变窄int常量表达式12byte,charshort,然后向盒装Byte,Character,或Short,但是奇怪的是,不Integer或任何"上方".我能想到的唯一可能的解释是,该均受到了原始收缩转换常数表达式未明确允许转换为Integer,Long,Float,或Double.

如果b不是final,则不允许缩小后跟拳击,并且不能将非常量表达式提升bytechar任何一个.