使用泛型参数与静态compareObject方法

时间:2008-11-05 21:12:55

标签: java generics

我想从这个通用实用程序方法中删除所有“未经检查”的警告(具有许多类似方法的较大类的一部分)。在紧要关头,我可以使用@SuppressWarnings(“unchecked”),但我想知道我是否可以正确使用泛型来避免警告。

该方法旨在允许调用者通过传递给compareTo来比较两个对象,但是如果对象是字符串则以不区分大小写的方式执行它。

public static int compareObject(Comparable o1, Comparable o2)
{
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

这是我第一次(不正确)尝试解决方案。参数工作正常,但是行o1.compareTo(o2)有一个编译错误“Comparable类型中的方法compareTo(capture#15-of?)不适用于参数(Comparable”。

public static int compareObject(Comparable<?> o1, Comparable<?> o2)
{
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

有什么建议吗?

5 个答案:

答案 0 :(得分:2)

我刚试过这个:

public static <T extends Comparable> int compareObject(T o1, T o2) {
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

它编译,但在compareTo()调用上给出了未经检查的强制警告 我尝试将其更改为

public static <T extends Comparable<T>> int compareObject(T o1, T o2) {

并且字符串检查无法编译(“不可转换的类型:found:T,required:String”)。不过,我认为这一定很接近。


编辑:正如评论中所指出的,这是一个bug in javac。第二种形式确实是正确的,但目前不会编译。看起来很疯狂,这是没有警告的代码:

public static <T extends Comparable<T>> int compareObject(T o1, T o2) {
    if (((Object) o1 instanceof String) && ((Object) o2 instanceof String))
        return ((String) (Object)o1).toUpperCase().compareTo(((String) (Object)o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

正如您所看到的,唯一的区别是Object的所有冗余演员表。

答案 1 :(得分:1)

以下是您要找的内容:

public static <T extends Comparable<T>> int compareObject(T o1, T o2) {
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

答案 2 :(得分:1)

我希望你知道这里的许多方法确实改变了方法的语义。使用原始方法,您可以比较不同类型的对象(如果允许),但使用

public static <T extends Comparable<T>> int compareObject(T o1, T o2)

你不能再进行这种比较了。允许这样做的变体是

    public static int compareObject2(Comparable<Object> o1, Comparable<Object> o2) {
    if (((Object) o1 instanceof String) && ((Object) o2 instanceof String))
        return ((String) (Object)o1).toUpperCase().compareTo(((String) (Object)o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

(我为所提到的javac bug插入了变通方法。)但这并没有增强类型安全性或任何东西,因此在这种情况下,最好使用更易理解的非泛型方法并使用@SuppressWarnings("unchecked") 。有过度使用仿制药这样的事情。

答案 3 :(得分:0)

以下内容如何:

  public static <T extends Comparable<T>> int compareObjects(T o1, T o2)
  {
    return o1.compareTo(o2);
  }

  public static int compareObjects(String o1, String o2)
  {
    return o1.compareToIgnoreCase(o2);
  }

缺点是当使用恰好是Strings的对象调用compareObjects()时,编译器会将您的调用绑定到第一个函数,并且最终会进行区分大小写的比较。

答案 4 :(得分:-1)

您是否测试过以下内容?

public static <T> int compareObject(Comparable<T> o1, Comparable<T> o2)
{
    if ((o1 instanceof String) && (o2 instanceof String))
        return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase());
    else
        return o1.compareTo(o2);
}

我认为它应该可以正常工作。