Java中的可比较和比较器接口
我想写一个通用的Pair类,它有两个成员:key和value。 这个类的唯一要求是key和value都应该实现Comparable接口,否则Pair类不会接受它们作为类型参数。
首先,我这样编码:
public class Pair
但是JDK 1.6编译器会生成关于此的警告:
Comparable is a raw type. References to generic type Comparable should be parameterized
然后我尝试添加类型参数,现在代码如下所示:
public class Pair<T1 extends Comparable, T2 extends Comparable>
现在一切顺利,直到我尝试为Pair生成Comparator。(以下代码在Pair类中)
public final Comparator<Pair> KEY_COMPARATOR = new Comparator<Pair>() { public int compare(Pair first, Pair second) { *first.getKey().compareTo(second.getKey());* return 0; } };
代码first.getKey().compareTo(second.getKey());
会产生错误说:
The method compareTo(capture#1-of ? extends Object) in the type Comparable is not applicable for the arguments (T1)
任何人都知道这个错误消息是什么意思?
欢迎任何有关此主题的提示。
更新:
这是完整的代码:
public class Pair<T1 extends Comparable, T2 extends Comparable> { private T1 key; private T2 value; public static int ascending = 1; public final Comparator<Pair> KEY_COMPARATOR = new Comparator<Pair>() { public int compare(Pair first, Pair second) { int cmp = first.getKey().compareTo((T1)(second.getKey())); if (cmp > 0) return ascending; return -ascending; } }; }
@MarvinLabs你能解释一下为什么编译器无法确保将对象与同类型的其他对象进行比较的原因。 在上面的代码中, second.getKey()
返回T1类型,它与first.getKey()
类型相同
让我们先看一下界面设计。
public interface Comparable { public int compareTo(T o); }
我们必须说这是很典型的。 因此,如果我们的课程需要实现它,我们就这样做。
pubilc class ICanComparteWithMyself implements Comparable { public int compareTo(ICanComparteWithMyselfo) //code for compration }
当我们看到通用参数类型时,确定我们将要操作的内容,因此对于generics,我们以相同的方式操作
public class ICanCompareMyGeneric implements Comparable { public int compareTo(T o) //code for compration } }
在你的情况下,我们希望它确保generics参数实现是自己的Comparable,为此我们需要这样做
public class MyGenericCanCompareToItself> { }
我们可以看到,这是很常见的使用方法。 预期(或不是)的限制是我们可以处理为其自身类型实现Comparable的类。 如果我们有
public class ICanCompareStrings implements Comparable { public int compareTo(String o) //code for compration } }
因此,对于类MyGenericCanCompareToItself
作为generics参数,我们可以使用类public MyGenericCanCompareToItself
但不能使用ICanCompareStrings
。
编辑:
因此,当我们涵盖基础知识时,我们可以解决您的问题
您的class级描述如下所示
public class Pair
这没有太多的感觉,因为它与>
更不一样
这个描述说:
我是一个Pair类,它使用两个通用参数,可以使用我不知道的东西进行比较。
使用这段代码,你不能在通用参数不知道之前进展,然后在那里操作,最终得到这样的东西。
first.getKey.compareTo(null);
这就是为什么你编写的代码在你尝试强制转换时不能编译,期望的类型为null。
要更改它,您需要确定您的通用参数应具有可比性的类型。
例如,可以在itselft上进行比较
public class Pair
这个描述说:
我是一个使用两个参数的Pair类,每个参数都可以与自身进行比较。
这就是你可能正在寻找的东西,另外它们可以在一些可以超级T1或T2的东西上进行比较
public class Pair
这个描述说:
我是一个使用两个参数的Pair类,每个参数都可以与从它们传递的类进行比较。
我希望这可以帮助你使用generics;-)。
我会这样宣布我的课程:
public class Pair, T2 extends Comparable>
这意味着对象可以与相同类型的对象进行比较(您的错误意味着编译器无法确保将对象与同类型的其他对象进行比较)。
我编辑的代码编译正确:
public class Pair, T2 extends Comparable> { private T1 key; private T2 value; public T1 getKey() { return key; } public T2 getValue() { return value; } public final Comparator> KEY_COMPARATOR = new Comparator>() { public int compare(Pair first, Pair second) { return first.getKey().compareTo(second.getKey()); } }; public static void test() { Pair p1 = new Pair(); Pair p2 = new Pair(); p1.KEY_COMPARATOR.compare(p1, p2); } }
但是,您应该为比较器创建一个单独的类(或静态最终类),以便它更直观地使用,并且不会增加每个Pair实例的权重。
如果你知道之间的区别:
List
和
List
……会更容易。 基本上,它们是java中的两种不同类型(不是你认为的“相同”List类型)。
通用类型“逻辑”并不像你在脑海中想象的那样直截了当。
我认为你应该将你的“Pair”类声明如下:
public class Pair, T2 extends Comparable>
因为你已经使“T1”T2“具有可比性,你为什么要实现比较器呢?
如果你想使用“Collections.sort(myCollection,myComparator)”,那么你不必声明“T1”和“T2”是“可比的”……只要确保你的“KEY_COMPARATOR”接受它们即可。 ..
无论哪种方式,代码中都有冗余。