6

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.

Sep
  • 61
  • 1

5 Answers5

12

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.

axtavt
  • 239,438
  • 41
  • 511
  • 482
6

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.

brabster
  • 42,504
  • 27
  • 146
  • 186
1

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.

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
0

As expected because List<String> is not a List<Object> as stated in the other answer. 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

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
0

You need to understand java generics. List<String> is not List<Object>. Any simple way to explain why I cannot do List<Animal> animals = new ArrayList<Dog>()?

Community
  • 1
  • 1
fastcodejava
  • 39,895
  • 28
  • 133
  • 186