4

在下面的代码片段中,有一个名为 的方法的三个版本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){}中间那个?

4

3 回答 3

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<?>

于 2012-12-26T02:03:22.863 回答
4

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

这意味着 ifA是 的超类B,List<A>不是 的超类List<B>

无法将泛型转换为扩展的嵌套类型中遇到了类似的问题,您可以查看那里的任何解决方法是否适合您。

也许改变

private void show(List<Object> list)

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

会按您的预期工作吗?

于 2012-12-26T01:52:39.333 回答
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"

   }
}

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

于 2012-12-26T01:59:17.187 回答