请考虑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类型的常量表达式的情况.
有任何想法吗 ?
解决方法:
Short s = 10;
这是一个赋值转换,10是一个常量表达式. JLS说:
5.2. Assignment Conversion
Assignment conversion occurs when the value of an expression is assigned to a variable: the type of the expression must be converted to the type of the variable.
……
In addition, if the expression is a constant expression of type byte, short, char, or int:
- A narrowing primitive conversion followed by a boxing conversion may be used if the type of the variable is:
- Short and the value of the constant expression is representable in the type short.
takeShort(10);
这是一个方法调用转换. JLS说:
5.3. Method Invocation Conversion
Method invocation conversion is applied to each argument value in a method or constructor invocation : the type of the argument expression must be converted to the type of the corresponding parameter.
Method invocation contexts allow the use of one of the following:
- an identity conversion
- a widening primitive conversion
- a widening reference conversion
- a boxing conversion optionally followed by widening reference conversion
- an unboxing conversion optionally followed by a widening primitive conversion.
……
If the type of the expression cannot be converted to the type of the parameter by a conversion permitted in a method invocation context, then a compile-time error occurs.
与分配转换不同,上面列出的非转换可以将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.