Varargs中的方法重载
重载允许不同的方法具有相同的名称,但具有不同的签名,其中签名可能因输入参数的数量或输入参数的类型或两者而不同。我们可以通过以下方式重载采用可变长度参数的方法:
- 案例1–仅使用Varargs参数的方法: 在本例中,Java使用类型差异来确定要调用哪个重载方法。如果一个方法签名严格地比另一个更具体,那么Java选择它时不会出错。
//Java program to illustrate
//method overloading in varargs
public
class
varargsDemo
{
public
static
void
main(String[] args)
{
fun();
}
//varargs method with float datatype
static
void
fun(
float
... x)
{
System.out.println(
"float varargs"
);
}
//varargs method with int datatype
static
void
fun(
int
... x)
{
System.out.println(
"int varargs"
);
}
//varargs method with double datatype
static
void
fun(
double
... x)
{
System.out.println(
"double varargs"
);
}
}
输出:
int varargs
这个输出是因为int比double更具体。如JLS部分所述 15.12.2.5 ,如果一个方法调用可以访问并适用于多个成员方法,则有必要选择一个成员方法来为运行时方法分派提供描述符。Java编程语言使用的规则是根据 类型推广 .在这种情况下,以下规则定义了基元类型之间的直接超类型关系:
- 双>浮动
- 浮动>长
- 长>整数
- int>char
- int>short
- 短>字节
- 案例2–使用Varargs和其他参数的方法 在本例中,Java使用参数的数量和类型来确定调用哪个方法。
下面是将fun()方法重载三次的java程序:
// Java program to demonstrate Varargs
// and overloading.
class
Test
{
// A method that takes varargs(here integers).
static
void
fun(
int
... a)
{
System.out.print(
"fun(int ...): "
+
"Number of args: "
+ a.length +
" Contents: "
);
// using for each loop to display contents of a
for
(
int
x : a)
System.out.print(x +
" "
);
System.out.println();
}
// A method that takes varargs(here booleans).
static
void
fun(
boolean
... a)
{
System.out.print(
"fun(boolean ...) "
+
"Number of args: "
+ a.length +
" Contents: "
);
// using for each loop to display contents of a
for
(
boolean
x : a)
System.out.print(x +
" "
);
System.out.println();
}
// A method takes string as a argument followed by varargs(here integers).
static
void
fun(String msg,
int
... a)
{
System.out.print(
"fun(String, int ...): "
+
msg + a.length +
" Contents: "
);
// using for each loop to display contents of a
for
(
int
x : a)
System.out.print(x +
" "
);
System.out.println();
}
public
static
void
main(String args[])
{
// Calling overloaded fun() with different parameter
fun(
1
,
2
,
3
);
fun(
"Testing: "
,
10
,
20
);
fun(
true
,
false
,
false
);
}
}
输出:
fun(int ...): Number of args: 3 Contents: 1 2 3 fun(String, int ...): Testing: 2 Contents: 10 20 fun(boolean ...) Number of args: 3 Contents: true false false
Varargs和歧义
有时,当重载采用可变长度参数的方法时,可能会导致意外错误。这些错误包含歧义,因为这两种方法都是调用的有效候选方法。编译器无法决定绑定方法调用的方法。
// Java program to illustrate Varargs and ambiguity class Test { // A method that takes varargs(here integers). static void fun( int ... a) { System.out.print( "fun(int ...): " + "Number of args: " + a.length + " Contents: " ); // using for each loop to display contents of a for ( int x : a) System.out.print(x + " " ); System.out.println(); } // A method that takes varargs(here booleans). static void fun( boolean ... a) { System.out.print( "fun(boolean ...) " + "Number of args: " + a.length + " Contents: " ); // using for each loop to display contents of a for ( boolean x : a) System.out.print(x + " " ); System.out.println(); } public static void main(String args[]) { // Calling overloaded fun() with different parameter fun( 1 , 2 , 3 ); //OK fun( true , false , false ); //OK fun(); // Error: Ambiguous! } } |
在上面的程序中,fun()的重载是完全正确的。但是,由于以下调用,此程序将无法编译:
fun(); // Error: Ambiguous!
根据(JLS) 15.2.2 ),重载解析中使用了三个阶段:第一阶段执行重载解析,不允许装箱或取消装箱转换;第二阶段执行重载解析,同时允许装箱和取消装箱;第三阶段允许重载与变量算术方法、装箱和取消装箱相结合。如果在这些阶段没有找到适用的方法,则会出现歧义。 上面的调用可以转换为对fun(int…)或fun(boolean…)的调用。这两种方法都同样有效,在重载解析的所有三个阶段之后都不会解析,因为这两种数据类型都不同。因此,这一呼吁本身就是模棱两可的。
另一个模棱两可的例子: fun()的以下重载版本本质上是不明确的:
static void fun(int ... a) { // method body } static void fun(int n, int ... a) { //method body }
这里,尽管fun()的参数列表不同,但编译器无法解决以下调用:
fun(1)
这个调用可能会解析为fun(int…a)或fun(int n,int…a)方法,从而产生歧义。为了解决上述模糊性错误,我们需要放弃重载,只需使用两个不同的方法名。
本文由 高拉夫·米格拉尼 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。