在Java中,方法调用中的收缩是如何工作的?
为什么会出现编译时错误? 2在编译时是常量,所以这里应该允许缩小范围,因为2在字节范围内在Java中,方法调用中的收缩是如何工作的?,java,narrowing,Java,Narrowing,为什么会出现编译时错误? 2在编译时是常量,所以这里应该允许缩小范围,因为2在字节范围内 public class Test { public static void main(String[] args) { ForTest test=new ForTest(); test.sum(1, 2); //compile time error here } } class ForTest { public int sum(int a,byte b) { Syst
public class Test {
public static void main(String[] args) {
ForTest test=new ForTest();
test.sum(1, 2); //compile time error here
}
}
class ForTest
{
public int sum(int a,byte b)
{
System.out.println("method byte");
return a+b;
}
}
错误是:
ForTest类型中的方法sum(int,byte)不适用于参数(int,int)
编辑:我想答案就在这里:但我不明白:(你不能隐式地将cast
int
tobyte
键入。
调用方法为:
sum(1, (byte)2);
这是因为2被解释为int,不能隐式转换为字节
您可以选择将方法签名更改为(
inta,intb
),或者显式执行强制转换:测试。求和(1,(字节)2)
修改后的答案:
java语言规范指出,在寻找函数调用的候选匹配项时,在根据函数名和实际参数与形式参数的数量找到候选项后,最终会得到
“如果m不是泛型方法,那么m通过松散调用适用,如果,对于1≤ 我≤ n、 ei与Fi在松散调用上下文中兼容,或者ei与适用性无关。”
显然,当它到达第二个实际参数时,它决定“int”在“松散调用上下文”中与“byte”不兼容。因此,它拒绝在阶段1中找到的唯一匹配候选
我无法在JLS中找到“松散调用”的正式定义
感谢VikasMangal和KisHanarsecHaGajjar指出了我最初答案的愚蠢,下面重复了我的答案,让我永远感到羞愧
下面是评论中提到的我的原始答案。
Java规范部分说您应该能够做到这一点
此外,在关于常数赋值的第5.2节中
此外,如果表达式是byte、short、char或int类型的常量表达式(§15.28):
如果变量的类型为byte、short或char,并且常量表达式的值可在变量的类型中表示,则可以使用窄化原语转换。”
然而,编译器似乎在走自己的路。因为说int
的缩小是通过byte
、short
或char
来完成的。因此,您需要将int
转换为调用该方法的byte
。如下所示:
test.sum(1, (byte)2);
使用基本整数可以实现更多的功能。因此,每次编写一个可以是“整型”值的值时,Java都会自动地对其进行强制转换,从而将其视为整数
与此相反的是,当您尝试这里的方法时会发生什么。Java看到一个可以作为整数的值,但要将其视为一个字节,您需要显式地告诉它。这有点像是说,好吧,我知道我在做什么,我确实意识到将数字转换为一个字节有其局限性,但我希望您无论如何都这样做。区分赋值转换和方法调用转换 缩小原语转换的范围 首先,看看: 22基元类型的特定转换称为缩小基元转换:
- [……]
- int到字节、short或char
- 如果变量的类型是byte、short或char,并且常量表达式的值可以在变量的类型中表示,则可以使用窄化原语转换
字节b=2
中,允许从int类型到byte类型的缩小转换
方法调用转换
但是,当阅读时,你不会阅读任何关于缩小转换的内容。因此编译器的工作是正确的。你能提供参考链接吗?已修复,但必须向下滚动到5.1.3,应该很容易找到。--编辑,无需担心,找到了锚。哈,完全正确!我跳过了句子中的该词,希望它们在l中最大到最小的顺序。@caskey根据您的参数,2在字节中的表示方式比它在这里自动类型转换时的表示方式要多。例如:byte b=2;是允许的,因为2是int,并且可以用byteNo表示,问题是我引用的是java语言规范,该规范将常数赋值给类型更窄的变量。这是ins实例是编译器,在这种情况下,它是我应该关注的编译器规范。问题的可能重复至少现在有字节文本来缓解问题(我认为)。它可以在赋值中隐式转换为字节,但这是一个例外。例如
字节b=2;