[英]Java generic captures and comparable
这是一个容器的实现,可以与具有兼容键的任何其他容器进行比较。 我在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
PECS:制作人延伸,消费者超级。
让我们从compareTo方法向后工作。 您想要与容器进行比较,并且希望使用键进行比较(因此key.compareTo(o.key))。 这意味着您的o
必须生成Key
,并且您的key
必须使用Key
。 第一部分意味着你的方法声明应该是public int compareTo(Container<? extends Key, ?> o)
,这意味着你应该实现Comparable<Container<? extends Key, ?>>
Comparable<Container<? extends Key, ?>>
。 第二部分意味着你的Key
应该是一个Comparable<? super 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。 你只需要一个可以生成一些可以使用Key
密钥的Container
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);
}
}
您只是没有正确实现接口。 您将Container
定义为实现Comparable<Pair<? super Key, Value>
Comparable<Pair<? super Key, Value>
。 这意味着它必须声明一个方法:
public int compareTo(Comparable<Pair<? super Key, Value> o)
但是现在它没有,因为它缺少通配符。
广义上的问题是你的通配符匹配。 的?
表示“匹配这些边界的任何类型”。 关键的是,不同的实例?
可以是不同的具体类型 ; 这就是“捕获”类型所指的内容。
任何时候你都有想要“配对”的问号,你应该给该参数一个名称,这样你就可以强制执行该身份(例如为该方法引入一个通用参数)。 每当你使用?
,你基本上说,“我完全不关心具体类型这个参数的是什么”,所以你不能执行依赖于精确匹配参数(如转让)的任何操作。
编辑:在更具体的意义上,我认为你的意图略有偏差。 您已尝试将特定Key
类型上的Container
声明为与另一个(超类) Key
上的Container相当。 我不相信这一定是个好主意,因为它引入了一些不对称性。
例如,您正在尝试创建它,以便可以将Container<String>
与Container<Object>
进行比较。 但是反过来做比较甚至不会编译 。 这种情况对您有效吗? 我希望可比性是对称的,并且让我a.compareTo(b)
困惑的是a.compareTo(b)
是1,但是b.compareTo(a)
不返回-1但反而拒绝编译。 这就是为什么,例如Double实现Comparable<Double>
而不是Comparable<? super 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);
}
}
这有效,但看起来像黑客:
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)
,但我没有设法写那个必要的通用约束...... :(
出于某种原因,Eclipse在创建Comparable
类型时插入“?super Type”但是没有意义(Type的哪个超类在compareTo()
?)。
只是摆脱“超级”,它将编译。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.