Adam Crume
Adam Crume

Reputation: 15844

Unable to call generic method with wildcard

I have a class defined like so:

public class Test {
    static <T> List<Class<T>> filter(List<Class<T>> input) {
        // code here
    }

    public static void main(String[] args) {
        List<Class<? extends Throwable>> list =
            new ArrayList<Class<? extends Throwable>>();
        filter(list);
    }
}

The filter method call in main gives the following compile error:

The method filter(List<Class<T>>) in the type Test is not applicable for the
arguments (List<Class<? extends Throwable>>)

I don't understand why <T> doesn't bind to <? extends Throwable>. Are there any generics gurus who can help me?

Upvotes: 3

Views: 1667

Answers (3)

Tom Hawtin - tackline
Tom Hawtin - tackline

Reputation: 147164

I believe the problem here is that there is no type for ? that would do.

Consider if we, for simplicity, replaced Class with AtomicReference.

static <T> void filter(List<AtomicReference<T>> input) {
    T value = input.get(0).get();
    input.get(1).set(value);
}

If the input consisted of an AtomicReference<Integer> and an AtomicReference<String> we would be in trouble.

The underlying problem that pointers to pointers in the presence of polymorphism is difficult. Without generics we can just hand wave. With generics we need to actually mean something.

Upvotes: 4

mjalil
mjalil

Reputation: 361

you can also write main as below :

public static void main(String[] args) {
    List<Class<Throwable>> list =
        new ArrayList<Class<Throwable>>();
    filter(list);
}

Upvotes: 0

skaffman
skaffman

Reputation: 403581

Ah, the joys of generic signatures.

You can fix it by declaring the parameter as:

static <T> List<Class<T>> filter(List<Class<? extends T>> input) {
    // code here
}

As to exactly why, I'm not sure. Too many compilation problems with generics are fixed by trying various things until the red line goes away. Not satisfying.

Upvotes: 4

Related Questions