Java中Varargs中的方法重载和歧义

先决条件—— 可变参数 , 方法重载

null

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主页上,并帮助其他极客。

如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享