I came across this weird (in my opinion) behavior today. Take this simple Test class:
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.
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):
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.
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>
. It is, however a List<? extends Object>
- give it a try and see.
Well this is expected - the list is not of type List<Object>
. To get the results you are expecting use:
public void method(List<?> o)
as a wild card, this will match your list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With