我认为没有明确的理由发生这个......
public class wrappers
{
public static void main(String []args)
{
short s1=32767; // (primitive) works fine without compile error
short s2=32768; fails as this is beyond short's range
Short s3=32767; //(wrapper) works fine without compile error
Short s4=32768; fails as this is beyond short's range
long l1 =34 // (wrapper)works fine (with_in_range)
Long l2 =34 // fails, without 34L (with_in_range)
}
我知道当您为包装类指定int
字面值时,会调用valueOf()
;
虽然Short(Wrapper)
这似乎有效,但代码中Long(wrapper)
以上的分配失败。
是否有任何规则来管理这些包装类'分配?
答案 0 :(得分:5)
是否有任何规则来管理这些包装类的分配
是 - JLS的规则。它指定widening primitive conversions (5.1.2)和boxing conversions (5.1.7)。
拳击转换列表包括:
- 从类型
int
到类型Integer
- 从类型
long
到类型Long
所以你想要一个扩大的转换,然后是拳击转换。您正尝试在分配上下文(5.2)中执行此操作,其中声明:
分配上下文允许使用以下之一:
- 身份转换(第5.1.1节)
- 扩大原始转换(第5.1.2节)
- 扩大参考转换(第5.1.5节)
- 拳击转换(第5.1.7节),可选地后跟加宽引用转换
- 一个拆箱转换(第5.1.8节),可选地后跟一个加宽的基元转换。
请注意,此列表不包含扩展的原始转换,然后是装箱转换。反之亦然:
Integer x = 10;
long y = x; // Unboxing followed by widening primitive
从表面上看,听起来似乎已经编写了 规则以允许扩展原始转换,然后进行装箱转换,规则使得Object x = 10;
更喜欢装箱{ {1}}而不是Integer
...但是类型转换规则非常很难正确,但有很多细微之处。如果事实证明有一些奇怪的情况会导致大问题,我不会感到惊讶。
转换为Long
的原因是由于5.2中的进一步规则:
此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):
- 如果变量的类型是
Short
,byte
或short
,则可以使用缩小的基元转换,并且常量表达式的值可以在类型中表示。变量- 如果变量的类型是:则可以使用缩小的基元转换,然后使用装箱转换:
char
,常量表达式的值可在Byte
类型中表示。byte
,常量表达式的值可在Short
类型中表示。short
,常量表达式的值可在Character
类型中表示。
在
的情况下char
有一个缩小的原始转换,然后是如上所述的装箱转换。
答案 1 :(得分:5)
为了扩展Jon的答案,允许Short s3=32767
工作的规则也在JLS中指定。有关常量表达式赋值的特殊规则:
此外,如果表达式是常量表达式(第15.28节) 输入byte,short,char或 int :
如果变量的类型是byte,short或char,则可以使用缩小的原语转换,以及常量的值 表达式可以在变量的类型中表示。
如果变量的类型为,则可以使用缩小的原始转换,然后使用装箱转换:
字节和常量表达式的值可以在类型字节中表示。
简短,常量表达式的值可以在短类型中表示。
字符和常量表达式的值可以在char类型中表示。
答案 2 :(得分:1)
仅在基本类型和它们各自的包装类之间进行自动装箱,例如:
int to Integer ,
长到长,
加倍加倍等等。
Java 不允许在原始类型int和Object Long之间进行转换。 但是,它确实允许在原始类型int和long之间进行转换。 因此,如果您需要为Long类型的变量分配int,则需要添加后缀 l 或 L :
Long l2 =34L,