I need some help from you, since I just can't tackle that problem regarding generics. I have the following method given by some API:
Now I'm implementing my own A that happens to have this structure:
It works just fine, if I invoke the operation like:
But since object Impl (or rather the constructors of Impl1, Impl2, ...) are somewhat complex, I want to hide them in a static factory method (and anyways only reveal what is needed outside, i.e. interface A):
A call to operation would look like this and work just fine:
But if I mix the "flavors" now (i.e. operation(Impl.flavorX(), Impl.flavorY());), eclipse yields the following error:
The method operation(A<? super T>, A<? super T>) in the type Test is not applicable for the arguments (A<Integer>, A<Double>)
Probably I miss a central characteristic of generics ... But why does it work with the concrete Impl1<T> class, but not with the interface A<T>? After working all day on that problem, I can't think straight anymore, when it comes to generics
Type inference sometimes does not work well when the result of a genericly typed method is directly used as the parameter of another method (or constructor).
You can solve this in (at least) two ways:
1) create temporary variables:
2) make the type explicit on the static method call:
This syntax of putting the generic type right before the method call will tell the compiler to use <T> as the generic type instead of trying to guess for itself.
Michael Ka wrote:The following call still cases the same problem:
Well, that's kind of obvious. Your operation signature:
Now can you find a type T of which both Integer and Double are super types? I certainly can't. Don't you mean <? extends T>?
Joined: Jun 24, 2009
Rob Prime wrote:Now can you find a type T of which both Integer and Double are super types?
True, I can not. And I guess my example works just because I'm ignoring the unchecked warning and generics are no subject to the runtime environment, right?
But I was being stupid. The operation() in the context above is Predicates#or(Predicate...) of Google collections. But on a collection of type, I'd never check for different types, anyways (like Predicates.or(Predicates.equalTo(new Date()), Predicates.equalTo(new String()));) because my collection is of a specific supertype.
Michael Ka wrote:Predicate.or(Predicate.equalTo(new Date()), Predicate.equalTo(new String()));
That could work though, if you ensure that the two calls to Predicate.equalTo return a Predicate<Object>.
Joined: Jun 24, 2009
I deliberately chose the equalTo from Predicates to make a point because it returns actually Predicat<T> (unlike e.g. isNull which is in fact Predicate<Object>). So it's a no go and I have to be careful with usage of these composite methods ...
But you can still make the method return a Predicate<Object>, and there are even two ways:
In the first example you're forcing T to be Object, and since a Date is an Object it won't complain. In the second example, you're passing Object as T so the result will also be Predicate<Object>.
But yes, these methods do not return Predicate<Object> out of their own. You'll have to force the compiler.