Reputation: 65
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.
Upvotes: 4
Views: 90
Reputation: 16226
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.
Upvotes: 2
Reputation: 25903
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?.
Upvotes: 5