7

请考虑2种情况:

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

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

//where:
static void takeShort(Short s) {}

我假设编译器将案例 1 更改为:

short _temp_s = 10;
Short s = Short.valueOf(_temp_s);

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

编辑

在 johnchen902 答案中对 JSL 的引用解释了编译器的行为。

仍然不完全清楚为什么 JLS 不支持方法调用转换的“缩小原始转换后跟装箱转换”,就像它在赋值转换中对 byte、short、char 或 int 类型的常量表达式的情况一样。有任何想法吗 ?

4

2 回答 2

3
Short s = 10;

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

5.2. 作业转换

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

……

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

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

takeShort(10);

这是一个Method Invocation Conversion. JLS说:

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.
于 2013-05-12T10:03:14.697 回答
2

10默认情况下,像这样的文字int在 Java 中。因此,您正在尝试分配int一个采用Shortshort作为参数的方法,这需要显式转换。您可以分配10short变量,但不能将其作为参数传递给接受Shortor的方法short。您可以按如下方式转换并传递它:

takeShort((short)10);

编辑 :

int范围为-2147483648to 2147483647,而short范围为-32768to 32767。除非文字的值在 的范围内short,否则编译器可以将其转换为short. 但是,正如蜘蛛鲍里斯在他的评论中提到的那样,一旦字面量的值超过 的范围short,它将无法将字面量转换为short,因为会丢失数据。short因此,当作为方法中的参数传递时,编译器不会将文字转换为 。

于 2013-05-12T09:33:01.463 回答