为什么会出现编译时错误? 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)不适用于arguements(int,int)。
编辑:我认为答案就在这里:http://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.3但我没有得到它:(
答案 0 :(得分:5)
您必须区分分配转换和方法调用转换。
缩小原始转化
首先,请看JLS §5.1.3:
原始类型的22个特定转换称为缩小基元转换:
[...]
int to byte,short或char
[...]
请注意,这只能解释机制,而不能解释允许或不允许此类转换的位置。
作业转换
接下来,请查看JLS §5.2:
[...]
此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):
- 如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。
[...]
这清楚地描述了在赋值byte b = 2
中允许从类型 int 到类型 byte 的缩小转换。
方法调用转换
但是,在阅读JLS §5.3时,您不会阅读有关缩小转化的任何内容。所以编译器正在做正确的工作。
答案 1 :(得分:3)
这是因为2被解释为int,不能将其隐式转换为字节。
您的选择是将方法签名更改为(int a, int b
),还是明确执行转换:test.sum(1, (byte)2)
答案 2 :(得分:1)
您无法隐式输入强制转换int
到byte
。
调用方法为:
sum(1, (byte)2);
答案 3 :(得分:1)
修订回答:
java语言规范说,在查找函数调用的候选匹配项时,根据函数名称找到候选项后,以及实际与形式参数的数量,最终到达{{3} }。
“如果m不是泛型方法,则m适用于松散调用,如果,1≤i≤n,ei在松散的调用上下文中与Fi或ei兼容,则与适用性无关。”
显然,当它到达第二个实际参数时,它决定'int'在'松散调用上下文'中与'byte'不兼容。因此,它拒绝在第1阶段找到的唯一匹配候选人。
我无法在JLS中找到“松散调用”的正式定义。
感谢VikasMangal和KisHanarsecHaGajjar指出我原来答案的愚蠢,这些愚蠢在下面重复以获得永恒的耻辱。
我原来回答的评论如下所示。
Java规范部分phase 2说应能够执行此操作。
此外,在关于常量赋值的5.2节中,它说
“此外,如果表达式是byte,short,char或int类型的常量表达式(第15.28节):
如果变量的类型是byte,short或char,则可以使用缩小的基元转换,并且常量表达式的值可以在变量的类型中表示。“
然而,编译器似乎是按照自己的方式进行的。
答案 4 :(得分:0)
由于Narrowing Primitive Conversions(§5.1.3)表示int
缩小byte
,short
或char
。因此,您需要将int
强制转换为调用方法的byte
。像这样:
test.sum(1, (byte)2);
答案 5 :(得分:0)
您可以使用原始整数实现更多功能。因此,每次编写一个可以是“整数”值的值时,Java都会自动想要进行转换,从而将其视为整数。
与此相反的是当您尝试在此尝试的内容时会发生什么。 Java看到一个可以作为整数的值,但是要将它视为一个字节,你需要明确告诉。这有点像说,好吧,我知道我在做什么,我确实意识到将数字转换成一个字节有其局限性,但我还是希望你能这样做。