简体   繁体   English

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

[英]Strange behavior when overloading methods in Java

I came across this weird (in my opinion) behavior today. 我今天遇到了这种奇怪的(在我看来)行为。 Take this simple Test class: 拿这个简单的Test类:

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");
}
}

It behaves the way you expect, printing "List of Objects". 它的行为与您期望的一样,打印“对象列表”。 But if you change the following three lines: 但是如果你改变以下三行:

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

you will get "Object" instead. 你会得到“对象”。

I tried this a few other ways and got the same result. 我尝试了其他一些方法并获得了相同的结果。 Is this a bug or is it a normal behavior? 这是一个错误还是正常行为? And if it is normal, can someone explain why? 如果这是正常的,有人可以解释为什么吗?

Thanks. 谢谢。

It's a normal behaviour. 这是正常的行为。 List<String> is not a List<Object> , so method(Object) is the only applicable method. List<String>不是List<Object> ,因此method(Object)是唯一适用的方法。

If List<String> were a List<Object> , you would be able to violate type safety, for example, by adding Integer to the List<String> (and it can't be caught at runtime due to type erasure): 如果List<String>List<Object> ,则可以违反类型安全性,例如,通过将Integer添加到List<String> (并且由于类型擦除而无法在运行时捕获):

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

Also note that arrays have a different behaviour - String[] is an Object[] , because array knows its element type and throws a runtime exception if you try to put a wrong object into it. 另请注意,数组具有不同的行为 - String[]Object[] ,因为如果您尝试将错误的对象放入其中,则array知道其元素类型并抛出运行时异常。

This is normal behaviour, because when you define a signature with generics, you specify a single class. 这是正常行为,因为当您使用泛型定义签名时,您可以指定单个类。 (Unless you use wildcards , which you haven't, the link explains)... (除非您使用通配符 ,否则链接会解释)...

So List<String> is not a List<Object> . 因此List<String>不是List<Object> It is, however a List<? extends Object> 它是一个List<? extends Object> List<? extends Object> - give it a try and see. List<? extends Object> - 试一试看看。

Well this is expected - the list is not of type List<Object> . 这是预期的 - 列表不是List<Object>类型。 To get the results you are expecting use: 要获得您期望使用的结果:

public void method(List<?> o)

as a wild card, this will match your list. 作为外卡,这将匹配您的列表。

As expected because List<String> is not a List<Object> as stated in the other answer. 正如所料,因为List<String>不是List<Object>如另一个答案中所述。 To obtain the desired behavior, you need to use a wildcard: 要获得所需的行为,您需要使用通配符:

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

See also 也可以看看

You need to understand java generics. 你需要了解java泛型。 List<String> is not List<Object> . List<String>不是List<Object> Any simple way to explain why I cannot do List<Animal> animals = new ArrayList<Dog>()? 任何简单的方法来解释为什么我不能做List <Animal> animals = new ArrayList <Dog>()?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM