这是一个容器的实现,可以与具有兼容键的任何其他容器进行比较。我有一个奇怪的错误,使用Java中的泛型,任何想法?
private static class Container
<Key extends Comparable<? super Key>, Value>
implements Comparable<Container<? super Key, ?>>
{
public Key key;
public Value value;
public Container(Key k, Value v) {
key = k;
value = v;
}
public int compareTo(Container<? super Key, ?> o) {
return key.compareTo(o.key);
}
}
...
这是错误:
compareTo(capture#98 of ? super Key) in
java.lang.Comparable<capture#98 of ? super Key> cannot be applied to
(java.lang.Comparable<? super capture#822 of ? super Key>)
return key.compareTo(o.key);
^
1 error
答案 0 :(得分:5)
让我们从compareTo方法向后工作。您想要与容器进行比较,并且希望使用键进行比较(因此key.compareTo(o.key))。这意味着您的o
必须生成Key
,而您的key
必须消费Key
。第一部分意味着您的方法声明应为public int compareTo(Container<? extends Key, ?> o)
,这意味着您应该实现Comparable<Container<? extends Key, ?>>
。第二部分意味着您的Key
应该是Comparable<? super Key>
,这就是您拥有它的方式。
private static class Container<Key extends Comparable<? super Key>, Value>
implements Comparable<Container<? extends Key, ?>> {
public Key key;
public Value value;
public Container(Key k, Value v) {
key = k;
value = v;
}
public int compareTo(Container<? extends Key, ?> o) {
return key.compareTo(o.key);
}
}
编辑:
完全遵循以下评论,声明如下。注意调用compareTo的键中的翻转,以及Key
不再需要实现Comparable的方式。您只需要使用Container
来生成一些可以使用Key
private static class Container<Key, Value> implements
Comparable<Container<? extends Comparable<? super Key>, ?>> {
//fields and constructors...
public int compareTo(Container<? extends Comparable<? super Key>, ?> o) {
return -o.key.compareTo(key);
}
}
答案 1 :(得分:1)
您只是没有正确实现界面。您将Container
定义为实施Comparable<Pair<? super Key, Value>
。这意味着它必须声明一个方法:
public int compareTo(Comparable<Pair<? super Key, Value> o)
但是现在它没有,因为它缺少通配符。
广义上的问题在于您的通配符匹配。 ?
表示“匹配这些边界的任何类型”。重要的是,?
的不同实例可以是不同的具体类型;这就是“捕获”类型所指的内容。
如果您有任何想要“配对”的问号,您应该为该参数指定一个名称,以便您可以强制执行该身份(例如,为该方法引入一个通用参数)。每当你使用?
时,你基本上都会说“我不关心所有这个参数的具体类型是什么”,所以你不能执行任何操作完全依赖于匹配参数(例如赋值)。
编辑:从更具体的意义上说,我认为你的意图略有偏差。您尝试在特定Container
类型上声明Key
,与Key
的不同(超类)上的Container相比较。我不相信这一定是个好主意,因为它引入了一些不对称性。
例如,您正试图将Container<String>
与Container<Object>
进行比较。但是反过来做比较甚至不会编译。这种情况对您有效吗?我希望可比性是对称的,a.compareTo(b)
为1会让我感到困惑,但b.compareTo(a)
不会返回-1,而是拒绝编译。这就是为什么,例如Double实现Comparable<Double>
而不是Comparable<? super Double>
。
编辑以获得简单的答案:所以你应该摆脱那些通配符,因为它不可能与任意对象进行比较。因此,定义看起来像:
private static class Container
<Key extends Comparable<Key>, Value>
implements Comparable<Container<Key, ?>>
{
...
public int compareTo(Container<Key, ?> o) {
return key.compareTo(o.key);
}
}
答案 2 :(得分:0)
这很有效,但看起来像是黑客:
private static class Container
<K extends Comparable<? super K>, Value>
implements Comparable<Container<? extends Comparable<? super K>, ?>>
{
public K key;
public Value value;
public Container(K k, Value v) {
key = k;
value = v;
}
public int compareTo(Container<? extends Comparable<? super K>, ?> o) {
return -o.key.compareTo(key);
}
}
我当然更愿意写key.compareTo(o.key)
,但我没有设法为此编写必要的通用约束...... :(
答案 3 :(得分:-3)
出于某种原因,Eclipse在您创建Comparable
类型时插入“?super Type”但是没有意义(Type的哪个超类将在compareTo()
中起作用?)。
摆脱“超级”,它会编译。