Generic methods. Multiple arguments match

sedni :

I cant figure out why does this code work without error.

static <T> int compare(T t1, T t2) {
    return 0;
}

public static void main(String[] args) {
    compare(new Thread(), new StringBuilder());
}

Because when we have something like this:

static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
    return;
}

public static void main(String[] args) {
    fromArrayToCollection(new Thread[] {}, new ArrayList<StringBuilder>()); // error
}

We have an error. Why doesn't compiler check match of both arguments in first example? Sorry for stupid question.

Zabuza :

Generics are invariant

Generics are invariant, not covariant.

This means that, while you can do something like this:

Dog dog = new Dog();
Animal animal = dog; // Dog works for Animal, classes are covariant

You can not do this:

List<Dog> dogs = List.of(new Dog());
List<Animal> animals = dogs; // Error, generics are invariant

So List<Dog> is not of type List<Animal>. But Dog is of type Animal.

Of course this makes sense, since animals would accept Cats, but dogs not.


Explanation

In your first code, you did not specify the type to use, such as:

compare<Foo>(...)

so you let the compiler deduce the type. It searches a type which Thread and StringBuilder have in common, which is Object.

So T resolves to Object there, which is fine:

static int compare(Object t1, Object t2) {
    return 0;
}

In your second example it can not pick Object, because Collection<Object> behaves different to Collection<StringBuilder>, since generics are invariant. So it is unable to find a type that matches, thus an error occurs.

Also see Why are arrays covariant but generics are invariant?.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=74425&siteId=1