请考虑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的常量表达式。 有什么想法吗?
答案 0 :(得分:3)
Short s = 10;
这是Assignment Conversion
,10
是常量表达式。 JLS说:
5.2。作业转换
将表达式的值赋给变量时会发生赋值转换:必须将表达式的类型转换为变量的类型。
...
此外,如果表达式是byte,short,char或int类型的常量表达式:
- 如果变量的类型为:
,则可以使用缩小的基元转换,然后使用装箱转换
- 简短,常量表达式的值可以在short类型中表示。
takeShort(10);
这是Method Invocation Conversion
。 JLS说:
5.3。方法调用转换
方法调用转换应用于方法或构造函数调用中的每个参数值:必须将参数表达式的类型转换为相应参数的类型。
方法调用上下文允许使用以下之一:
- 身份转换
- 扩大原始转化
- 扩大参考转化
- 拳击转换,可选地后跟加宽参考转换
- 取消装箱转换,可选地后跟扩展的原始转换。
...
如果表达式的类型无法通过方法调用上下文中允许的转换转换为参数类型,则会发生编译时错误。
与分配转换不同,上面列出的转化不可以将int
转换为Short
,因此会发生编译时错误。
不幸的是有些人在我批准之前拒绝了kiruwka的编辑,所以我自己编辑
Method调用转换的示例:
// 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.
答案 1 :(得分:2)
Java中默认10
这样的文字是int
。因此,您尝试将int
分配给以Short
或short
作为参数的方法,这需要显式强制转换。您可以将10
分配给short
变量,但不能将其作为参数传递给接受Short
或short
的方法。您可以按如下方式投射并传递它:
takeShort((short)10);
编辑:
int
的范围为-2147483648
到2147483647
,而short
的范围为-32768
到32767
。除非文字的值在short
的范围内,否则编译器将其转换为short
是正常的。但是,正如Boris the Spider在评论中提到的那样,一旦文字的值超出short
的范围,它就无法将文字转换为short
,因为会有数据丢失。因此,当在方法中作为参数传递时,编译器不会将文字转换为short
。