Reputation: 589
I have faced following situation:
import com.google.common.base.Optional;
public class CovarianceTest {
class Race {
}
class Dog<Race> {
}
public Optional<Dog<? extends Race>> getDog() {
Dog<? extends Race> dogWithSomeRace = new Dog();
return Optional.of(dogWithSomeRace);
}
}
Situation like this causes compilation problem. The IDE says:
Incompatible types.
Required: Optional<Dog<? extends Race>>
Found: Optional<? extends Dog<? extends Race>
Which is clearly wrong.
Could someone explain why this is happening?
Upvotes: 1
Views: 236
Reputation: 10505
This is your code:
Dog<Race>
) is a type parameter that you will use for further parametrization of class Dog
.Dog<? extends Race> dogWithSomeRace = new Dog();
this is considered as not best practice.I believe the code below is what you are trying to do. Use T as type parameter. Here we go:
import com.google.common.base.Optional;
public class CovarianceTest {
class Race {
}
class Dog<T> {
void whatever(T t) {
System.out.println(t);
}
}
public Optional<Dog<? extends Race>> getDog() {
Dog<? extends Race> dogWithSomeRace = new Dog<Race>();
return Optional.of(dogWithSomeRace);
}
public static void main(String[] args) {
System.out.println((new CovarianceTest()).getDog().isPresent());
System.out.println((new CovarianceTest()).getDog().get().getClass());
}
}
This prints nicely:
true
class CovarianceTest$Dog
Upvotes: 2
Reputation: 1890
It seems you confused the class' generic type declaration with the boundary declaration of a generic type argument.
In your case:
class Race {}
class Dog<Race> {} // "Race" is declared as a generic type in dog. It's not referring to your Race class in any way.
Your definition of Dog
is equivalent to
class Dog<E> {}
If you want to set a subclass of Race
to be a generic boundary for Dog
, then do for example
class Dog<E extends Race> {}
You could also refine the method's generic declarations:
public Optional<Dog<? extends Race>> // this could be shortend to Dog<?>, because Dog's boundary is already limited to Race in the class signature
getDog() {
Dog<? extends Race> dogWithSomeRace // This can be shortend aswell to Dog<?>
= new Dog(); // Missing type declaration in the constructor call
return Optional.of(dogWithSomeRace);
}
Upvotes: 2