0

I have a method which takes a Collection<Object> where the Object can be a String or CustomClass. It then takes each element of the collection and passes it to a method with an argument of Object like so:

public void foo(Collection<Object> c) {
    for(Object o : c)
        bar(o);
}

public void bar(Object o) {
    if(o instanceof String || o instanceof CustomClass) {
        ...
    }
}

bar works fine when I pass it a String or CustomClass, but when I try to pass a NavigableSet<String> to foo I get cannot find symbol; symbol : method foo(java.util.NavigableSet<java.lang.String>).

However if I change the the argument type in foo to Collection<String> it works fine, but this means I need to make a new foo(Collection<CustomClass>) method which will involve repeating code. Is there a way around this?

bountiful
  • 814
  • 1
  • 8
  • 22
  • 1
    It's because [a `Collection` is not a `Collection`](http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicit) – assylias Jul 17 '12 at 09:59

2 Answers2

5

Collection<String> is not a subtype of Collection<Object>, therefore the compiler doesn't find any compatible methods. Put

public <T> void foo(Collection<T> c) {
  for (T o : c) bar(o);
}
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
0

The inheritance relationship between T<A> and T<B> is is called "generic covariance". It is not as simple as, if A inherits from B, then T<A> inherits from T<B>, because the type parameter may be "in" or "out" (as C# would put it).

See for example http://www.ibm.com/developerworks/java/library/j-jtp01255/index.html or java generics covariance or http://etymon.blogspot.co.uk/2007/02/java-generics-and-covariance-and.html

Marko's suggestion is the simplest fix for your problem.

Community
  • 1
  • 1
Rich
  • 15,048
  • 2
  • 66
  • 119