从Java原语转换为包装类

在将基元分配给包装类引用时,我对Java编译器的行为感到困惑。 请参阅下面的代码。 带注释的行不会编译。

我不明白为什么的逻辑:

  1. 一个byte可以分配给ByteShort ,但不能分配给IntegerLong引用
  2. short可以分配给ByteShort ,但不能分配给IntegerLong引用
  3. int可以分配给ByteShortInteger ,但不能分配给Long引用
  4. long可以分配给Long ,但不能分配给ByteShortInteger

我看不到这种模式。 对此的任何见解都将非常有用。 谢谢。

 Byte s5 = (byte)7; Short s6 = (byte)7; Integer s7 = (byte)7; // Does not compile Long s8 = (byte)7; // Does not compile Byte s9 = (short)7; Short s10 = (short)7; Integer s11 = (short)7; // Does not compile Long s12 = (short)7; // Does not compile Byte s1 = (int)7; Short s2 = (int)7; Integer s3 = (int)7; Long s4 = (int)7; // Does not compile Byte s13 = (long)7; // Does not compile Short s14 = (long)7; // Does not compile Integer s15 = (long)7; // Does not compile Long s16 = (long)7; 

我们来看一下赋值上下文中允许的转换类型。

原则上:

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

  • 身份转换

  • 扩大原始转换

  • 扩大参考转换

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

  • 取消装箱转换,可选地后跟扩展的原始转换。

(注意我强调一个 。)

例如,大多数不编译的示例

 Integer s11 = (short)7; 

需要扩展原始转换,然后进行装箱转换 。 这不是允许的转换。

但是你可能想知道为什么下面的例子会编译:

 Byte s9 = (short)7; 

这是一个缩小的原始转换,然后是拳击转换

这是一个特例:

另外,如果表达式是byteshortcharint类型的常量表达式,如果变量的类型是:则可以使用缩小的原语转换,然后使用装箱转换:

  • Byte和常量表达式的值可在类型byte表示。

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

  • Character和常量表达式的值可在char类型中表示。

这种特殊情况是必要的,因为无法表达比int更窄的类型的整数文字。

这似乎是特定于编译器的行为。 当我将代码粘贴到Eclipse中,运行Java 7时,我没有看到您向Integer报告的编译器错误或者向Integer报告的byte

相反,我看到byteshortint都可以分配给ByteShortInteger ,但不能分配给Long ,而long只能分配给Long 。 有趣的是,如果将变量更改为基元而不是包装类型,则byteshortint行为不会更改,但现在其他类型的赋值也可以long

 javac 1.7.0_02 | byte | Byte || short | Short || int | Integer || long | Long | From byte | Yes | Yes || Yes | Yes || Yes | No || Yes | No | From short | Yes | Yes || Yes | Yes || Yes | No || Yes | No | From int | Yes | Yes || Yes | Yes || Yes | Yes || Yes | No | From long | No | No || No | No || No | No || Yes | Yes | Eclipse Indigo | byte | Byte || short | Short || int | Integer || long | Long | From byte | Yes | Yes || Yes | Yes || Yes | Yes || Yes | No | From short | Yes | Yes || Yes | Yes || Yes | Yes || Yes | No | From int | Yes | Yes || Yes | Yes || Yes | Yes || Yes | No | From long | No | No || No | No || No | No || Yes | Yes | 

鉴于不同的编译器允许不同的转换,我怀疑在JLS中实际上没有拼写出“正确”的行为。 似乎某些转换是在封面下完成的,因为编译器编写者认为它很方便(例如, byte a = (int)1是允许的但byte a = (int)1000不是),不是因为它是语言的文档部分。

根据我的研究,我发现一个字节是一个8位有符号整数。 短裤是16位有符号整数。 因此我可以看出为什么它们是兼容的,它们都是两个补码的有符号整数,强调签名 。 long是64位整数,但它也可以是无符号的(考虑到它有比较无符号long的方法)。 这可能解释了为什么你的转换为long导致错误 – 你将一个带符号的字节转换为一个可能无符号的长整数。 (来源:阅读http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html上的原语)