24

我正在尝试将排序列表作为 Java 中的一个简单练习来实现。为了使其通用,我有一个add(Comparable obj)这样我可以将它与任何实现 Comparable 接口的类一起使用。

但是,当我obj.compareTo(...)在代码中的任何地方使用时,我"unchecked call to compareTo(T) as a member of the raw type java.lang.Comparable"从编译器获得(带有-Xlint:unchecked选项)。代码工作得很好,但我不知道如何摆脱那个烦人的消息。

有什么提示吗?

4

3 回答 3

31

本质上,此警告表示Comparable对象不能与任意对象进行比较。Comparable<T>是一个泛型接口,其中 type 参数T指定该对象可以与之比较的对象的类型。

因此,为了Comparable<T>正确使用,您需要使您的排序列表通用,以表达您的列表存储可以相互比较的对象的约束,如下所示:

public class SortedList<T extends Comparable<? super T>> {
    public void add(T obj) { ... }
    ...
}
于 2011-01-28T16:19:59.040 回答
9

使用像Comparable方法参数这样的接口不会使您的类泛型,声明和使用泛型类型参数是您使其泛型的方式。

Quick-n-dirty 回答:您收到警告是因为您正在使用Comparable作为原始类型的泛型接口,而不是给它一个特定的类型参数,例如Comparable<String>.

要解决此问题,add()请通过指定类型参数来实现泛型:

<T extends Comparable<? super T>> add(T obj) { ... }

但是这个快速修复并不能解决你的班级不安全的普遍问题。毕竟,列表中的所有对象不应该是同一类型吗?这个add方法让你仍然可以将不同的类型放到同一个列表中。当您尝试比较异构类型时会发生什么(如何compareToObject实例与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; } 
}
于 2011-01-28T16:35:57.847 回答
1

您需要像这样“检查”或定义 Comparable 对象:

add(Comparable<Object> obj)
于 2011-01-28T16:17:47.127 回答