Java – 简短和铸造
我有以下代码片段。
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) { }
以下摘要是否正确(仅针对上面的例子使用short)?
- 不使用强制转换的直接初始化只能使用文字或单个变量(只要该值在声明的类型范围内)
- 如果赋值的rhs使用变量处理表达式,则必须进行强制转换
但是为什么我需要在考虑前面的摘要的情况下强制转换第二个方法调用的参数?
这些是相关的JLS部分:
JLS 5.1.1身份转换
任何类型都允许从类型到相同类型的转换。
JLS 5.2分配转换
将表达式的值赋给变量时会发生赋值转换:必须将表达式的类型转换为变量的类型。 赋值上下文允许使用以下之一:
- 身份转换
- […]
另外,如果表达式是
byte
,short
,char
或int
类型的常量表达式:
- 如果变量的类型是
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
至于为什么这不编译:
test(7); // DOES NOT COMPILE! There's no test(int) method!
这是因为使用常数缩小转换仅为分配定义; 不适用于具有完全不同规则的方法调用。
JLS 5.3。 方法调用转换
方法调用转换特别不包括整数常量的隐式缩小,这是赋值转换的一部分。 Java编程语言的设计者认为,包含这些隐式缩小转换将为重载方法匹配解析过程增加额外的复杂性。
我将引用Effective Java 2nd Edition ,第41项:明智地使用重载:而不是解释方法解析如何正确工作。
确定选择哪个重载的规则非常复杂。 他们在语言规范中占用了三十三页,很少有程序员理解他们的所有细微之处。
也可以看看
- 不同的行为可能会导致精度下降
-
short x = 3; x += 4.6;
由于复合赋值的语义而编译
-
对short
值进行算术运算的结果始终为int
。 test(7)
不起作用,因为你没有说7是short
型的。 编译器在这里应该更聪明一些。
呼叫test(7);
的’7′ test(7);
是一个int
,不会自动转换为short
。
它在您声明和初始化short
值时有效,但这是编译器的特例。 方法调用不存在这种特殊情况。