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

2022-01-13 00:00:00 wrapper type-conversion java autoboxing
final byte b = 12;  
Short s = b;  
Integer i = b;

对于 Short,程序编译正常,但对于 Integer 编译失败,并显示不兼容的类型"消息.

Program compiles fine for Short but for Integer compilation fails with "incompatible types" message.

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

I am having difficult time trying to understand this behavior. I could not find anything for this specific scenario..

推荐答案

我试图用更广泛的赋值上下文来复制这个:

I attempted to duplicate this with a wider group of assignment contexts:

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 是也是一个错误.

Assigning not just to a Integer, but also to a Float, a Long or a Double is also an error.

有趣的是,如果 b 的原始声明不是 final,那么将 Character 分配给一个 char,或者 Short 也会失败.

Interestingly, if the original declaration of b was NOT final, then assigning to a Character, a char, or a Short fails also.

JLS 第 5.2 节 稍微阐明了赋值上下文及其允许的转换的主题.

Section 5.2 of the JLS sheds a little light on the subject of assignment contexts and their allowed conversions.

分配上下文允许使用以下之一:

Assignment contexts allow the use of one of the following:

  • 身份转换(第 5.1.1 节)

  • an identity conversion (§5.1.1)

一个扩大的基元转换(§5.1.2)

a widening primitive conversion (§5.1.2)

扩大参考转换 (§5.1.5)

a widening reference conversion (§5.1.5)

装箱转换(第 5.1.7 节)可选地后跟扩大参考转换

a boxing conversion (§5.1.7) optionally followed by a widening reference conversion

一个拆箱转换(第 5.1.8 节)可选地后跟一个加宽的原始转换.

an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

这涵盖了到更广泛的原始变量的所有转换,无论 b 是否为 final,这些都是允许的.(除非 b 为负数,否则对无符号 char(或 Character)的赋值将失败.)继续:

This covers all of the conversions to wider primitive variables, which are always allowed, whether b is final or not. (That holds unless b is negative, in which case the assignment to an unsigned char (or Character) would fail.) Continuing:

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

In addition, if the expression is a constant expression (§15.28) of type byte, short, char, or int:

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

  • A narrowing primitive conversion may be used if the type of the variable is byte, short, or char, and the value of the constant expression is representable in the type of the variable.

如果变量的类型为:

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

  • Byte and the value of the constant expression is representable in the type byte.

Short 并且常量表达式的值可以用 short 类型表示.

Short and the value of the constant expression is representable in the type short.

字符和常量表达式的值可以用char类型表示.

Character and the value of the constant expression is representable in the type char.

因为bfinal,表达式b是一个常量表达式,可以从int 常量表达式 12bytecharshort 然后装箱到 ByteCharacterShort,但奇怪的是,不是 Integer 或任何以上"的东西.我能想到的唯一可能的解释是,不允许将受原始缩小转换影响的常量表达式转换为 IntegerLong浮点数,或双数.

Because b is final, the expression b is a constant expression, allowing it to be narrowed from the int constant expression 12 to byte, char, or short and then boxed to Byte, Character, or Short, but strangely, not to Integer or anything "above". The only possible explanation I can think of is that constant expressions that are subject to a primitive narrowing conversion aren't specifically allowed to be converted to Integer, Long, Float, or Double.

如果 b 不是 final,则不允许紧跟装箱,并且不能从 提升非常量表达式bytechar 也可以.

If b isn't final, then the narrowing followed by boxing isn't allowed, and a non-constant expression can't be promoted from byte to char either.

相关文章