将方法参数传递给Java中类型为byte、int、int的方法参数

4

以下方法接受三个参数,类型为byte,int,int。该方法被另一个方法调用,但出现了编译错误,提示该方法参数不适用于int,int,int。默认情况下,不识别byte参数,需要进行显式转换。

 public double subtractNumbers(byte arg1,int arg2,int arg3) {
    double sum=arg1+arg2+arg3;
    return sum;
}

现在我们需要在一个方法中调用另一个方法,代码如下:
 public void call(){
  subtractNumbers(15,16,17);   /*Compile error,but 15 is in byte acceptable 
 range of -128 to 127 */
  }

如果我将上面的调用更改为subtractNumbers((byte)15,16,17);,它可以正常工作。
当我声明一个变量byte c=15时,它被接受,但是当15被传递给一个byte参数时,为什么会出现编译错误? intbyte、short、int、long的默认字面值,那么为什么byte c=15可以被接受而方法参数却不能?
提前感谢您的帮助。

可能是因为方法重载的原因:你可以有另一个以int作为第一个参数的subtractNumbers方法,这种情况下,subtractNumber(15,16,17)会调用第二个方法。 - Maurice Perry
https://dev59.com/-m435IYBdhLWcg3w0Tnc - SleepyX667
通过执行(byte) 15byte c = 15,您将此int值向下转换为byte,因此不会出现编译错误。 - benjamin c
3个回答

4
你的问题归结为:
在变量声明中将 15 赋值给一个 byte 类型,为什么能够正常工作:
byte b = 15;

但是调用方法时不会这样?

subtractNumbers(15,16,17);

这是因为这两种情况处于两个不同的语境中。第一个是在赋值语境中,而第二个是在调用语境中。
根据JLS §5.2 赋值语境

赋值语境允许使用以下之一:

...

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

  • 如果变量的类型是byte、short或char,并且常量表达式的值在变量的类型中可表示,则可以使用缩小原始转换。
15肯定是一个常量表达式,因此从intbyte的缩小原始转换是允许的。
然而,在调用语境中,情况并非如此:

JLS §5.3 Invocation Context

严格的调用上下文允许使用以下之一:
  • 身份转换(§5.1.1)
  • 扩展原始类型转换(§5.1.2)
  • 扩展引用类型转换(§5.1.5)
宽松的调用上下文允许更多的转换,因为如果在严格的调用上下文中找不到适用的声明,则仅针对特定调用使用。宽松的调用上下文允许使用以下之一:
  • 身份转换(§5.1.1)
  • 扩展原始类型转换(§5.1.2)
  • 扩展引用类型转换(§5.1.5)
  • 装箱转换(§5.1.7),可选择后跟扩展引用类型转换
  • 拆箱转换(§5.1.8),可选择后跟扩展原始类型转换
“缩小原始类型转换”没有被提及,因此在调用上下文中不被允许。

2

Java有编译时缩小的概念。这允许以下内容在编译时有效:

byte b = 15;

大多数人被教导字面值像12会默认为int。但这并不总是正确的。像doublefloatlong这样的类型有显式的字面量(例如15d15f15L),但是32位以下的非浮点原始数据类型没有。
这就是为什么15在编译时被确定为byte类型的原因。
在您的情况下,编译器试图在编译时执行类型匹配。方法subtractNumbers的方法签名为byteintint,所以您必须提供一个精确的匹配。不幸的是,在此过程中,编译器在推断15的类型之前不会查看可用方法列表。我认为这是由于方法重载造成的。
考虑以下内容:
public static void test(byte a, int b){}
public static void test(int a, int b){}

现在,如果您调用test(15, 16),如果15允许自动缩小为byte,那么就会产生歧义。请注意保留HTML标签。

1
原因是当您尝试将 int 转换为 byte 时,您正在进行一种 缩小原始转换。由于这可能会导致信息丢失,编译器要求您进行显式转换(即像在两种情况下显式将 15 强制转换为 byte 的方式)。请参见this 回答您的另一个问题,为什么您可以简单地声明 byte c = 15 而不会出现编译错误,是因为 15 仍在 byte 允许的 -128 到 -127 的范围内。如果您尝试分配更大的值,例如 byte d = 128,您仍将获得编译时错误。请参见this

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