在Java中重载方法

时间:2012-12-26 01:51:24

标签: java oop overloading

在以下代码段中,有一个名为show()的方法的三个版本。

package overloading;

import java.util.ArrayList;
import java.util.List;

public final class Main
{
    private void show(Object object)
    {
        System.out.println("Object");
    }

    private void show(List<Object> list)  //Unused method
    {
        System.out.println("List");
    }

    private void show(Object[] objects)
    {
        System.out.println("Objects");
    }

    private void addToList()
    {
        List<String>list=new ArrayList<String>();
        list.add("String1");
        list.add("String2");
        list.add("String3");
        show(list); // Invokes the first version

        String []s={"111", "222", "333"};
        show(s);   // Invokes the last version
    }

    public static void main(String[] args)
    {
        new Main().addToList();
    }
}

在这个最简单的Java代码中,此方法调用show(s);addToList()方法中的最后一行)调用重载方法的最后版本。它提供了一个字符串数组 - String[],它被Object[]类型的接收参数接受。

此函数调用show(list);但是会​​尝试调用重载方法的第一个版本。它传递一个类型字符串列表 - List<String>,它应该被接收参数类型为List<Object>的中间版本接受。方法的中间版本完全未使用。如果删除了第一个版本,那么这是一个编译时错误。

为什么此次调用show(list); 调用此版本 - private void show(List<Object> list){} - 中间版本?

3 个答案:

答案 0 :(得分:7)

简而言之,List<Object>不是List<String>

要“修复”您的代码,请使用以下代码

private void show(List<? extends Object> list)
{
    System.out.println("List");
}

与数组(Java中的协变)不同,泛型类型的不同实例化彼此不兼容,甚至不是显式的。

声明Generic<Supertype> superGeneric; Generic<Subtype> subGeneric; 编译器会报告铸件(Generic<Subtype>)superGeneric(Generic<Supertype>)subGeneric的转换错误。

如果将?用作实际类型参数,通配符可能会使这种不兼容性变得柔和:Generic<?>是泛型类型的所有实例化的抽象超类型。

另外see

答案 1 :(得分:4)

List<Object>不是java中List<String>的超类。您所假设的是Java在泛型上具有协方差,但它没有。

这意味着如果AB的超类,List<A>不是List<B>的超类

Cannot convert generic to expanded nested type中遇到了类似的问题,你可以看看那里的任何工作是否适合你。

也许正在改变

private void show(List<Object> list)

private void show(List<? extends Object> list)

会像你期望的那样工作吗?

答案 2 :(得分:3)

我想说这是因为参数不同,List <Object>List <String>不同 因此,当您调用重载方法时,它将默认为第一个仅接受对象的方法。

这是一个简短的例子:

public class Test
{
  public static void overload (Object o)
  {
    System.out.println ("Object");

  }

   public static void overload (List <Object> o)
  {
    System.out.println ("List Object");
  }

   public static void main (String [] args)
   {
     overload (new ArrayList <Object>()); //"List Object"
     overload (new ArrayList <String>()); //"Object"

   }
}

使用泛型参数化列表,一切都应该有效。