4

我在 Java7 中使用 Collections.sort() 遇到了(显然是臭名昭著的)IllegalArgumentException
多亏了所以我理解了原因,这基本上是(咳嗽)糟糕的代码。
问题是,我自己无法重现异常。我做了一些jdk源代码挖掘,并找到了哪个类抛出了那个异常。这个想法是创建相应的测试用例。

这里是代码,顺便说一下
<pride level="0" >

@Override
public int compareTo( Symbol other) {
    if( this.lastUse == 0) {
        if( other.lastUse != 0) return (int)( -DateMicros.ONE_DAY);
    } else if( other.lastUse == 0) {
        return ( int)DateMicros.ONE_DAY;
    }
    return ( int)( this.lastUse - other.lastUse);
}

</pride > 最重要的是,“lastUse”以微秒和毫秒(是混合的)为单位分配时间戳,这给出了极好的 int 溢出溢出

实际问题是:
什么值会导致此代码崩溃?得到一个适当的测试用例。

使用堆栈跟踪更新:

at java.util.ComparableTimSort.mergeHi(Unknown Source)
at java.util.ComparableTimSort.mergeAt(Unknown Source)
at java.util.ComparableTimSort.mergeCollapse(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at java.util.Collections.sort(Unknown Source)
4

3 回答 3

3

看起来崩溃是由整数溢出引起的,然而这不应该是。这被确定为 bug ,它也为您提供了解决方法。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7075600

试试这个作为临时修复:

Adding -Djava.util.Arrays.useLegacyMergeSort=true to my eclipse.ini does seem to have resolved the issue.

您可以在我发布的同一链接中找到此修复程序。

也可以访问这个http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6923200,这是在第一个链接之前报告的相同类型的错误,但是由于他们无法重复创建相同的问题,所以它被关闭了。

于 2012-10-23T22:05:44.160 回答
2

来自Java SE 7 和 JDK 7 的兼容性

领域: API:实用程序

概要:数组和集合的更新排序行为可能会引发 IllegalArgumentException

说明:java.util.Arrays.sort和(间接)使用的排序算法java.util.Collections.sort已被替换。如果新的排序实现IllegalArgumentException检测到Comparable that violates the Comparable contract. 之前的实现默默地忽略了这种情况。如果需要以前的行为,您可以使用新的系统属性java.util.Arrays.useLegacyMergeSort, 来恢复以前的合并排序行为。不兼容的性质:行为

射频:6804124

所以正确的实现应该像

  public int compareTo( Symbol other) {
        if( this.lastUse == other.lastUse) {
           return 0;
        } else if( other.lastUse>this.lastUse) {
            return 1;
        }
        return -1;
    }

参考

  1. 可比
于 2012-10-23T21:51:50.750 回答
1

不看堆栈跟踪本身就很难说。

但是文档提到方法本身可以抛出异常。

(可选)如果实现检测到列表元素的自然顺序被发现违反了 Comparable 合约

更新

看起来是因为您的对象不满足Comparable一致性要求:

当且仅当 e1.compareTo(e2) == 0 对于类 C 的每个 e1 和 e2 具有与 e1.equals(e2) 相同的布尔值时,才说类 C 的自然排序与 equals 一致。注意null 不是任何类的实例,即使 e.equals(null) 返回 false,e.compareTo(null) 也应该抛出 NullPointerException。

于 2012-10-23T21:44:48.923 回答