在Java中重载方法时的奇怪行为

时间:2010-05-31 21:49:39

标签: java

我今天遇到了这种奇怪的(在我看来)行为。拿这个简单的测试类:

public class Test {

public static void main(String[] args) {
    Test t = new Test();
    t.run();
}

private void run() {
    List<Object> list = new ArrayList<Object>();
    list.add(new Object());
    list.add(new Object());
    method(list);
}

public void method(Object o) {
    System.out.println("Object");
}

public void method(List<Object> o) {
    System.out.println("List of Objects");
}
}

它的行为与您期望的一样,打印“对象列表”。但是如果你改变以下三行:

List<String> list = new ArrayList<String>();
list.add("");
list.add("");

你会得到“对象”。

我尝试了其他一些方法并获得了相同的结果。这是一个错误还是正常行为?如果这是正常的,有人可以解释原因吗?

感谢。

5 个答案:

答案 0 :(得分:12)

这是正常行为。 List<String>不是List<Object>,因此method(Object)是唯一适用的方法。

如果List<String>List<Object>,您就可以违反类型安全,例如,将Integer添加到List<String>(并且不能由于类型擦除而在运行时捕获):

public void method(List<Object> o) { 
    o.add(new Integer(10));
}

另请注意,数组具有不同的行为 - String[]Object[],因为如果您尝试将错误的对象放入其中,则数组会知道其元素类型并抛出运行时异常。

答案 1 :(得分:6)

这是正常行为,因为当您使用泛型定义签名时,您指定一个类。 (除非您使用的是wildcards,否则链接会解释)...

所以List<String>不是List<Object>。不过,List<? extends Object>是试一试。

答案 2 :(得分:1)

这是预期的 - 列表不是List<Object>类型。要获得您期望使用的结果:

public void method(List<?> o)

作为外卡,这将与您的列表匹配。

答案 3 :(得分:0)

正如预期的那样,List<String>不是List<Object>,如另一个答案中所述。要获得所需的行为,您需要使用通配符:

public void method(List<? extends Object> o) { //or an unbounded wildcard List<?>
    System.out.println("List of Objects");
}

另见

答案 4 :(得分:0)

您需要了解java泛型。 List<String>不是List<Object>Any simple way to explain why I cannot do List<Animal> animals = new ArrayList<Dog>()?