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.
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 Cat
s, but dogs
not.
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?.
I'd like to add that a simple change in the second code snippet would correct the error:
static <T> void fromArrayToCollection(T[] a, Collection<? extends T> c) { ... }
^
Now, the Java compiler will infer the Object
again:
fromArrayToCollection(new Thread[]{}, new ArrayList<StringBuilder>());
Also, you can add the type argument explicitly:
Main.<Object>fromArrayToCollection(new Thread[]{}, new ArrayList<StringBuilder>());
^
T => Object
:
static void fromArrayToCollection(Object[] a, Collection<? extends Object> c) { ... }
Further reading: Upper Bounded Wildcards.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With