在以下代码段中,有一个名为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){}
- 中间版本?
答案 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在泛型上具有协方差,但它没有。
这意味着如果A
是B
的超类,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"
}
}
使用泛型参数化列表,一切都应该有效。