从Java原语转换为包装类

时间:2015-02-05 03:43:20

标签: java type-conversion boxing

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

我不理解原因的逻辑:

  1. 可以将byte分配给ByteShort,但不能IntegerLong参考
  2. 可以将short分配给ByteShort,但不能IntegerLong参考
  3. 可以将int分配给ByteShortInteger,但不能Long参考
  4. 可以将long分配给Long,但不能分配ByteShortInteger参考
  5. 我看不到模式。任何洞察力都会非常有用。 感谢。

    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;
    

3 个答案:

答案 0 :(得分:3)

让我们看一下assignment context中允许的转化类型。

主要地:

  

分配上下文允许使用以下一个

     
      
  • 身份转换

  •   
  • 扩大基元转换

  •   
  • 扩大参考转化

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

  •   
  • 一个拆箱转换,可选择后跟一个加宽的基元转换。

  •   

(注意我强调一个。)

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

Integer s11 = (short)7;

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

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

Byte s9 = (short)7;

这是缩小的原始转换,然后是装箱转换

这是一个特例:

  

此外,如果表达式是byteshortcharint [...]类型的常量表达式,则缩小基元转换后跟如果变量的类型是:

,则可以使用装箱转换      
      
  • Byte,常量表达式的值可在byte类型中表示。

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

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

  •   

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

答案 1 :(得分:2)

这似乎是特定于编译器的行为。当我将代码粘贴到运行Java 7的Eclipse中时,我看不到您为shortIntegerbyteInteger报告的编译器错误。

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

long

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

答案 2 :(得分:0)

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