数字文字的自动装箱:包装器初始化与传递方法参数不一致

kir*_*wka 7 java primitive autoboxing compiler-errors compilation

请考虑2个案例:

//1
Short s = 10; //obviously compiles    

//2
takeShort(10); //error - int is not applicable

//where:
static void takeShort(Short s) {}
Run Code Online (Sandbox Code Playgroud)

我假设情况1被编译器更改为:

short _temp_s = 10;
Short s = Short.valueOf(_temp_s);
Run Code Online (Sandbox Code Playgroud)

你能否解释一下编译器在案例2中尝试做什么,所以它不能编译?如果它不像在案例1中那样尝试应用自动装箱,那么为什么呢?

编辑

johnchen902中对JSL的引用解释了编译器的行为.

仍然不完全清楚为什么JLS不支持方法调用转换的"缩小原始转换后跟装箱转换",因为它在分配转换中为byte,short,char或int类型的常量表达式的情况.有任何想法吗 ?

joh*_*902 3

Short s = 10;
Run Code Online (Sandbox Code Playgroud)

这是一个Assignment Conversion, ,并且10是一个常量表达式。JLS说道:

5.2. 分配转换

当将表达式的值赋给变量时,就会发生赋值转换:表达式的类型必须转换为变量的类型。

......

另外,如果表达式是 byte、short、char 或 int 类型的常量表达式:

  • 如果变量的类型是:
    • Short 和常量表达式的值可以用short 类型表示。

takeShort(10);
Run Code Online (Sandbox Code Playgroud)

这是一个Method Invocation ConversionJLS说道:

5.3. 方法调用转换

方法调用转换应用于方法或构造函数调用中的每个参数值:参数表达式的类型必须转换为相应参数的类型。

方法调用上下文允许使用以下之一:

  • 身份转换
  • 扩大原始转换
  • 扩大参考转换
  • 装箱转换(可选)后跟扩大参考转换
  • 拆箱转换(可选)后跟扩展原始转换。

......

如果表达式的类型无法通过方法调用上下文中允许的转换转换为参数的类型,则会发生编译时错误。

与赋值转换不同,上面列出的转换不能转换intShort,因此会发生编译时错误。

不幸的是,在我批准之前,有些人拒绝了 kiruwka 的编辑,所以我自己编辑它

方法调用转换示例:

// takeInteger(int) takeDouble(double) takeObject(Object) takeIntegerObject(Integer)

takeInteger(5);  // an identity conversion
takeDouble(5);   // a widening primitive conversion
takeObject(new Integer(5)); // a widening reference conversion
takeIntegerObject(5);   // a boxing conversion
takeObject(5);   // a boxing conversion followed by widening reference conversion
takeInteger(new Integer(5)); // an unboxing conversion
takeDouble(new Integer(5)); // an unboxing conversion followed by a widening primitive conversion.
Run Code Online (Sandbox Code Playgroud)