Java - 短整型和类型转换

11

我有以下代码片段。

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涉及使用变量的表达式,则需要进行转换
那么,根据前面的总结,为什么需要转换第二个方法调用的参数?

请参见https://dev59.com/dnRB5IYBdhLWcg3w4bKv。 - Jim Kiley
3个回答

19

以下是相关的JLS章节:

JLS 5.1.1 标识转换

任何类型都可以进行从一种类型到该类型本身的转换。

JLS 5.2 赋值转换

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

  • 标识转换
  • [...]

此外,如果表达式是类型为 byteshortcharint 的常量表达式:

  • 如果变量的类型是 byteshortchar,并且常量表达式的值可以用变量的类型表示,则可以使用缩小原始类型转换。

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

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第二版》,第41条:谨慎地使用重载,而不是解释方法解析的确切工作方式:

决定哪个重载被选择的规则非常复杂。它们在语言规范中占用了33页,很少有程序员能理解所有细节。


参见


谢谢您所有的回答!那帮了我很多! - chr1s

1

short类型的算术运算结果总是int类型。因为你没有指定7是short类型,所以test(7)无法工作。编译器应该在这里更加智能。


所以你的意思是当函数被调用时,对字面参数7应用了某种算术运算? - chr1s
不,test(7)中没有算术运算。 a + b 是一个具有整数结果的算术运算,而 test(7) 是使用整型字面值作为参数的方法调用。 - deamon

1

在调用 test(7); 中的 '7' 是一个 int,不会自动转换为 short

当您声明和初始化 short 值时,它可以工作,但这是编译器的特殊情况。对于方法调用,不存在这种特殊情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接