Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why generic version of Collection parameter is getting call

Tags:

java

generics

Here is one code segment

public class HelloWorld{

    public static void main(String[] args) { 
        GenericClass<Integer> test = new GenericClass<Integer>(); 
        test.method(new ArrayList<Integer> ()); 
    } 
}
class GenericClass<T> {
    public void overloadedMethod( Collection<?> o) { 
        System.out.println("overloadedMethod(Collection<?>)"); 
    } 
    public void overloadedMethod( List<Number> s) { 
        System.out.println("overloadedMethod(List<Number>)"); 
    } 
    public void overloadedMethod( ArrayList<Integer> i) { 
        System.out.println("overloadedMethod(ArrayList<Integer>)"); 
    }

    public void method(List<T> t) { 
        overloadedMethod(t) ; // which method is called? 
    }   
}

I am expecting it would call overloaded method with Arraylist parameter but Collection is getting called why?

like image 433
test Avatar asked Aug 23 '15 04:08

test


1 Answers

This exact code is used in an example in Angelika Langer's webpage on java generics

I'll post the explanation in case the page ever goes down:

The program prints:

overloadedMethod(Collection)

One might have expected that version for ArrayList would be invoked, but that again is the wrong expectation. Let us see what the compiler translates the generic class to.

Example (after type erasure):

public final class GenericClass {

    private void overloadedMethod( Collection o) {
        System.out.println("overloadedMethod(Collection<?>)");
    }
    private void overloadedMethod( List s) {
        System.out.println("overloadedMethod(List<Number>)");
    }
    private void overloadedMethod( ArrayList i) {
        System.out.println("overloadedMethod(ArrayList<Integer>)");
    }

    private void method(List t) {
        overloadedMethod(t) ;
    }

    public static void main(String[] args) {
        GenericClass test = new GenericClass();
        test.method(new ArrayList ());
    }
} 

One might mistakenly believe that the compiler would decide that the List version of the overloaded method is the best match. But that would be wrong, of course. The List version of the overloaded method was originally a version that takes a List as an argument, but on invocation a List is passed, where T can be any type and need not be a Number . Since T can be any type the only viable version of the overloaded method is the version for Collection .

In fact, if you comment out the Collection method you will get a compiler error because the List and ArrayList are too specific to fit for all the possible <T> types.

like image 53
dkatzel Avatar answered Nov 08 '22 22:11

dkatzel