Java - 简短和铸造

chr*_*r1s 11 java casting primitive-types

我有以下代码片段.

public static void main(String[] args) {
 short a = 4;
 short b = 5;
 short c = 5 + 4;
 short d = a;
 short e = a + b; // does not compile (expression treated as int)


 short z = 32767;
 short z_ = 32768; // does not compile (out of range)

 test(a);
 test(7); // does not compile (not applicable for arg int)
}

public static void test(short x) { }
Run Code Online (Sandbox Code Playgroud)

以下摘要是否正确(仅针对上面的例子使用short)?

  • 不使用强制转换的直接初始化只能使用文字或单个变量(只要该值在声明的类型范围内)
  • 如果赋值的rhs使用变量处理表达式,则必须进行强制转换

但是,为什么我需要在考虑前一个摘要的情况下转换第二个方法调用的参数?

pol*_*nts 18

这些是相关的JLS部分:

JLS 5.1.1身份转换

任何类型都允许从类型到相同类型的转换.

JLS 5.2分配转换

将表达式的值赋给变量时会发生赋值转换:必须将表达式的类型转换为变量的类型.赋值上下文允许使用以下之一:

  • 身份转换
  • [...]

此外,如果表达式的类型是恒定表达byte,short,charint:

  • 如果变量的类型是byte,, short或者char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示.

以上规则解释了以下所有内容:

short a = 4;     // representable constant
short b = 5;     // representable constant
short c = 5 + 4; // representable constant
short d = a;     // identity conversion
short e = a + b; // DOES NOT COMPILE! Result of addition is int

short z  = 32767; // representable constant
short z_ = 32768; // DOES NOT COMPILE! Unrepresentable constant
Run Code Online (Sandbox Code Playgroud)

至于为什么这不编译:

test(7); // DOES NOT COMPILE! There's no test(int) method!
Run Code Online (Sandbox Code Playgroud)

这是因为使用常数缩小转换仅为分配定义; 不适用于具有完全不同规则的方法调用.

JLS 5.3.方法调用转换

方法调用转换特别不包括整数常量的隐式缩小,这是赋值转换的一部分.Java编程语言的设计者认为,包含这些隐式缩小转换将为重载方法匹配解析过程增加额外的复杂性.

我将引用Effective Java第2版,第41项:明智地使用重载:而不是解释方法解析如何正确工作.

确定选择哪个重载的规则非常复杂.它们在语言规范中占用了三十三页,很少有程序员理解它们的所有细微之处.


也可以看看