在Java中,方法调用中的收缩是如何工作的?

在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

为什么会出现编译时错误? 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)
{
    System.out.println("method byte");
    return a+b;
}
}
错误是: ForTest类型中的方法sum(int,byte)不适用于参数(int,int)


编辑:我想答案就在这里:但我不明白:(

你不能隐式地将cast
int
to
byte
键入。 调用方法为:

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或int类型的常量表达式(§15.28):

  • 如果变量的类型是byte、short或char,并且常量表达式的值可以在变量的类型中表示,则可以使用窄化原语转换
[……]

这清楚地描述了在赋值
字节b=2
中,允许从int类型到byte类型的缩小转换

方法调用转换


但是,当阅读时,你不会阅读任何关于缩小转换的内容。因此编译器的工作是正确的。

你能提供参考链接吗?已修复,但必须向下滚动到5.1.3,应该很容易找到。--编辑,无需担心,找到了锚。哈,完全正确!我跳过了句子中的该词,希望它们在l中最大到最小的顺序。@caskey根据您的参数,2在字节中的表示方式比它在这里自动类型转换时的表示方式要多。例如:byte b=2;是允许的,因为2是int,并且可以用byteNo表示,问题是我引用的是java语言规范,该规范将常数赋值给类型更窄的变量。这是ins实例是编译器,在这种情况下,它是我应该关注的编译器规范。问题的可能重复至少现在有字节文本来缓解问题(我认为)。它可以在赋值中隐式转换为字节,但这是一个例外。例如
字节b=2;