在将基元分配给包装类引用时,我对Java编译器的行为感到困惑。请参阅下面的代码。带注释的行不会编译。
我不理解原因的逻辑:
byte
分配给Byte
或Short
,但不能Integer
或Long
参考short
分配给Byte
或Short
,但不能Integer
或Long
参考int
分配给Byte
,Short
或Integer
,但不能Long
参考long
分配给Long
,但不能分配Byte
,Short
或Integer
参考我看不到模式。任何洞察力都会非常有用。 感谢。
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;
答案 0 :(得分:3)
让我们看一下assignment context中允许的转化类型。
主要地:
分配上下文允许使用以下一个:
身份转换
扩大基元转换
扩大参考转化
一个拳击转换,可选地后跟一个加宽的引用转换
一个拆箱转换,可选择后跟一个加宽的基元转换。
(注意我强调一个。)
大多数不编译的示例,例如
Integer s11 = (short)7;
要求扩展原始转换,然后进行装箱转换。这不是允许的转换。
但是你可能想知道为什么下面的例子会编译:
Byte s9 = (short)7;
这是缩小的原始转换,然后是装箱转换。
这是一个特例:
此外,如果表达式是
,则可以使用装箱转换byte
,short
,char
或int
[...]类型的常量表达式,则缩小基元转换后跟如果变量的类型是:
Byte
,常量表达式的值可在byte
类型中表示。
Short
,常量表达式的值可在short
类型中表示。
Character
,常量表达式的值可在char
类型中表示。
这种特殊情况是必要的,因为无法表达比int
更窄的整数文字。
答案 1 :(得分:2)
这似乎是特定于编译器的行为。当我将代码粘贴到运行Java 7的Eclipse中时,我看不到您为short
向Integer
或byte
向Integer
报告的编译器错误。
相反,我看到byte
,short
和int
都可以分配到Byte
,Short
和Integer
,但是不能Long
和long
只能分配到Long
。有趣的是,如果您将变量更改为基元而不是包装类型,byte
,short
和int
行为不会更改,但现在将其他类型的分配更改为{{ 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处的原语
)