以下方法接受三个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传递给字节参数时,为什么会出现编译错误;
int 是byte,short,int,long的默认文字,然后为什么接受字节c = 15而不强制转换而不是方法参数。
先谢谢您。
答案 0 :(得分:1)
原因是因为当您尝试将int
强制转换为byte
时,您正在执行缩小原始转换。由于这可能会导致信息丢失,因此编译器要求您进行显式转换(例如,在两种情况下,您都将15显式转换为byte
类型时所做的操作)。参见this
要回答另一个问题,为什么您可以简单地声明byte c = 15
而没有编译错误,这是因为15
仍然在byte
允许的-128到-127的范围内。如果尝试分配较大的值,例如byte d = 128
,仍然会遇到编译时错误。参见this
答案 1 :(得分:1)
您的问题可以归结为:
为什么将15
分配给byte
才能在变量声明中起作用:
byte b = 15;
但是调用方法时不可以吗?
subtractNumbers(15,16,17);
这是因为这两种情况在两个不同的上下文中。第一个在分配上下文中,而第二个在调用上下文中。
根据JLS §5.2 Assignment Contexts,
分配上下文允许使用以下之一:
...
此外,如果该表达式是以下内容的常量表达式(第15.28节) 输入byte,short,char或int类型:
- 如果变量的类型为byte,short或char,并且常量表达式的值为,则可以使用缩窄的原始转换。 可以表示为变量的类型。
15
当然是一个常量表达式,因此允许从int
到byte
的狭窄原始转换。
但是,在调用上下文中,这是不正确的:
严格的调用上下文允许使用以下之一:
- 身份转换(第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 :(得分:0)
Java具有缩小编译时的想法。这样可以使以下内容在编译时有效:
byte b = 15;
大多数人被告知,12
之类的文字将默认为int
。这并非总是如此。像double
,float
和long
这样的类型具有显式文字(例如15d
,15f
和15L
),但是下面的非浮点原语32位不。
这就是为什么15
在编译时被确定为byte
类型的原因。
在您的情况下,编译器正在尝试在编译时执行类型匹配。方法subtractNumbers
的方法签名为byte
,int
,int
,因此您必须给它一个精确的匹配项。不幸的是,在此过程中,编译器在推断15
的类型之前不会查看可用方法的列表。我相信这是由于方法重载造成的。
考虑一下:
public static void test(byte a, int b){}
public static void test(int a, int b){}
现在,如果您调用test(15, 16)
,并且如果允许15
自动缩小到byte
,那么就会有歧义。