我正在尝试将排序列表实现为Java中的简单练习。为了使它具有通用性,我有add(Comparable obj)
所以我可以将它用于任何实现Comparable接口的类。
但是,当我在代码中的任何地方使用obj.compareTo(...)
时,我从编译器中获取"unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable"
(使用-Xlint:unchecked
选项)。代码工作正常,但我无法弄清楚如何摆脱那令人讨厌的消息。
任何提示?
答案 0 :(得分:28)
本质上,此警告表示Comparable
对象无法与任意对象进行比较。 Comparable<T>
是一个通用接口,其中类型参数T
指定可以与此对象进行比较的对象的类型。
因此,为了正确使用Comparable<T>
,您需要使排序列表具有通用性,以表达您的列表存储可以相互比较的对象的约束,如下所示:
public class SortedList<T extends Comparable<? super T>> {
public void add(T obj) { ... }
...
}
答案 1 :(得分:9)
使用Comparable
之类的接口作为方法参数不会使您的类具有通用性,声明和使用泛型类型参数就是如何使它成为通用的。
快速回答: 您收到警告是因为您使用Comparable
作为通用接口作为原始类型,而不是像Comparable<String>
那样给它一个特定的类型参数。
要解决此问题,请通过指定类型参数使add()
成为通用:
<T extends Comparable<? super T>> add(T obj) { ... }
但是这个快速修复程序无法解决您的课程不安全的一般问题。毕竟,列表中的所有对象不应该是同一类型的吗?此add
方法允许您将不同的类型放入同一列表中。当您尝试比较异构类型时会发生什么(您如何compareTo
Object
实例与Number
实例或String实例?您可以依赖类的用户来做正确的事情并确保他们只在列表中添加一种东西,但是泛型类将让编译器强制执行此规则。
更好的方法: 正确的解决方法是,您的排序列表类可能总体上是通用的,就像java.util
中的其他集合类一样。
你可能喜欢这样的东西:
public class SortedList<T extends Comparable<? super T>>
implements Iterable<T> {
...
public void add(T item) { ... }
public Iterator<T> iterator() { ... }
...
}
请注意,当类是通用的时,add
方法使用类形式类型参数,而不是声明自己的形式类型参数。
网上应该有很多关于如何创建泛型类的教程,但这里有一个简单的例子:
http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#FAQ002
class Pair<X,Y> {
private X first;
private Y second;
public Pair(X a1, Y a2) {
first = a1;
second = a2;
}
public X getFirst() { return first; }
public Y getSecond() { return second; }
public void setFirst(X arg) { first = arg; }
public void setSecond(Y arg) { second = arg; }
}
答案 2 :(得分:1)
您需要“检查”或定义Comparable对象,如下所示:
add(Comparable<Object> obj)