4

为什么这会给出编译时错误?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)。

编辑:我认为答案就在这里:http ://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.3但我不明白:(

4

6 回答 6

5

您必须区分赋值转换方法调用转换

缩小原始转换

首先,看看JLS §5.1.3

原始类型的 22 种特定转换称为窄化原始转换

  • [...]

  • int 到 byte、short 或 char

[...]

请注意,这仅解释了机制,而不是允许或不允许此类转换的地方。

作业转换

接下来,查看JLS §5.2

[...]

此外,如果表达式是 byte、short、char 或 int 类型的常量表达式(第 15.28 节):

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

[...]

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

方法调用转换

但是,在阅读JLS §5.3时,您不会阅读任何有关缩小转换的内容。所以编译器正在做正确的工作。

于 2014-06-26T07:58:08.257 回答
3

这是因为 2 被解释为 int,不能隐式转换为字节。

您的选择是将方法签名更改为 ( int a, int b),或显式进行强制转换:test.sum(1, (byte)2)

于 2014-06-26T07:27:20.773 回答
1

您不能隐式键入 cast intto 。byte调用方法为:

sum(1, (byte)2); 
于 2014-06-26T07:26:42.177 回答
1

修改后的答案:

Java 语言规范说,在寻找函数调用的候选匹配项时,在根据函数名称以及实际参数与形式参数的数量找到候选对象后,最终会到达阶段 2

“如果 m 不是泛型方法,则 m 可通过松散调用适用,如果对于 1 ≤ i ≤ n,ei 在松散调用上下文中与 Fi 兼容,或者 ei 与适用性无关。”

显然,当它到达第二个实际参数时,它决定了“int”在“松散调用上下文”中与“byte”不兼容。因此,它拒绝了它在阶段 1 中找到的唯一匹配的候选者。

我无法在 JLS 中找到“松散调用”的正式定义。

感谢 VikasMangal 和 KisHanarsecHaGajjar 指出我原来的答案的愚蠢性,下面重复这个答案是为了永远的耻辱。

评论所指的我的原始答案如下。

Java 规范第5.1.3节说你应该能够做到这一点。

另外在第 5.2 节关于常量的分配中它说

“此外,如果表达式是 byte、short、char 或 int 类型的常量表达式(第 15.28 节):

如果变量的类型是 byte、short 或 char,并且常量表达式的值可以在变量的类型中表示,则可以使用缩小原语转换。”

但是,编译器似乎正在走自己的路。

于 2014-06-26T07:27:42.510 回答
0

由于Narrowing Primitive Conversions(§5.1.3)说缩小int,或. 因此,您需要将其转换为调用该方法的位置。像这样 :byteshortcharintbyte

test.sum(1, (byte)2);
于 2014-06-26T07:33:26.243 回答
0

您可以使用原始整数实现更多目标。因此,每次您编写一个可以是“整数”值的值时,Java 都会自动进行强制转换,从而将其视为整数。

当您尝试此处尝试的内容时,会发生相反的情况。Java 看到一个可以作为整数的值,但要将其视为字节,您需要明确告知。这有点像说,好吧,我知道我在做什么,而且我确实意识到将数字转换为字节有其局限性,但无论如何我希望你这样做。

于 2014-06-26T07:34:46.503 回答