You're simply not implementing the interface correctly. You define Container
as implementing Comparable<Pair<? super Key, Value>
. That means that it must declare a method:
public int compareTo(Comparable<Pair<? super Key, Value> o)
but right now it doesn't, because it's missing the wildcard.
The problem in a broader sense is with your wildcard matching. The ?
means "any type that matches these bounds". Critically, different instances of ?
can be different concrete types; this is what the "capture of" types refer to.
Any time that you have question marks that you want to "pair up" at all, you should give that parameter a name so you can enforce the identity (e.g. introduce a generic parameter for the method). Whenever you use a ?
, you're essentially saying that "I don't care at all what the concrete type of this parameter is", so you can't perform any operations that depend on matching parameters exactly (such as assignment).
Edit: in a more specific sense I think your intentions are slightly off. You've tried to declare a Container
on a particular Key
type as comparable to a Container on a different (superclass) of Key
. I'm not convinced this is necessarily a good idea, as it introduces some asymmetry.
For instance, you're trying to make it so a Container<String>
can be compared against a Container<Object>
. But doing the comparison the other way round wouldn't even compile. Does this situation seem valid to you? I'd expect comparability to be symmetric, and it would confuse me that a.compareTo(b)
is 1, but b.compareTo(a)
doesn't return -1 but instead refuses to compile. This is why, for example Double implements Comparable<Double>
and not Comparable<? super Double>
.
EDIT for plain answer: So you should get rid of those wildcards, as it's not going to be possible to compare against an arbitrary object. Thus the definition would look like:
private static class Container
<Key extends Comparable<Key>, Value>
implements Comparable<Container<Key, ?>>
{
...
public int compareTo(Container<Key, ?> o) {
return key.compareTo(o.key);
}
}