【问题标题】:Java allows to assign byte to java.lang.Short but not to java.lang.IntegerJava 允许将字节分配给 java.lang.Short 但不能分配给 java.lang.Integer
【发布时间】:2014-08-13 17:27:22
【问题描述】:
final byte b = 12;  
Short s = b;  
Integer i = b;

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

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

【问题讨论】:

  • 使用 int 而不是 Integer
  • 这不是 100% 的重复,因为它没有说明为什么允许 Short,但 Integer 不允许,所以我撤回了密切投票。不过非常相关:stackoverflow.com/questions/7014171/…
  • 在我看来,“非常相关”的问题没有足够的答案——它只是让一群人胡乱猜测。我认为关闭它是错误的。
  • 情节变厚了:删除 'final' 关键字会导致 Short 自动装箱也会生成编译器错误。这可能是导致这种奇怪行为原因的一些线索。
  • 还有一个奇怪的细微差别:Character c = b 编译也很好。但是chars 没有签名!那么当您将b 更改为-12 时会发生什么?然后编译失败!

标签: java type-conversion wrapper autoboxing


【解决方案1】:

我试图用更广泛的分配上下文组来复制它:

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 也会失败。

Section 5.2 of the JLS 阐明了赋值上下文及其允许的转换的主题。

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

  • 身份转换(§5.1.1)

  • 扩大的原始转换(§5.1.2)

  • 扩大参考转换 (§5.1.5)

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

  • 拆箱转换(第 5.1.8 节)可选地后跟扩展原语转换。

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

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

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

  • 如果变量的类型为:

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

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

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

因为bfinal,所以表达式b 是一个常量表达式,允许它从int 常量表达式12 缩小到byte,@ 987654344@,或short,然后装箱到ByteCharacter,或Short,但奇怪的是,不是Integer或任何“以上”。我能想到的唯一可能的解释是,不允许将受原始窄化转换的常量表达式专门转换为IntegerLongFloatDouble

如果b 不是final,则不允许紧跟装箱,也不能将非常量表达式从byte 提升为char

【讨论】:

  • Character c = b; // Only an error if b isn't final(或 b 是否定的。)很好的答案!
  • @MarkPeters 真的。正如上面 JLS 引用中所述,“常量表达式的值可以用变量的类型表示”。否定的final b 也会导致char c = b; 失败并出现错误。
  • 但奇怪的是,不是 Integer 或任何“高于”的东西我认为这是可以预料的,因为那时你正在使用 Short 和 @987654364 @ 并且这些包装器类型无法扩展。参见$JLS 5.1.5如果ST 的子类型,则存在从任何引用类型S 到任何引用类型T 的扩展引用转换。 显然没有连接直接在ShortInteger 之间。
  • @JeroenVannevel 是的,但我发现奇怪的是,在扩大原始转换之后进行装箱转换是不允许的。
猜你喜欢
  • 1970-01-01
  • 2011-12-20
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
相关资源
最近更新 更多