我在Java7中使用Collections.sort()得到了(显然是臭名昭着的)IllegalArgumentException
多亏了我理解原因,这基本上是(咳嗽)糟糕的代码
问题是,我无法自己重现异常。我做了一些jdk源代码挖掘,并找到了哪个类抛出异常。我们的想法是创建相应的测试用例。
顺便说一句,这是代码
<骄傲等级=" 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)
答案 0 :(得分: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
,这与第一个链接之前报告的错误类型相同,但由于无法重复创建相同的问题,因此已关闭。
答案 1 :(得分:2)
来自Java SE 7 and JDK 7 Compatibility
区域:API:实用工具
概要:数组和集合的更新排序行为可能会抛出IllegalArgumentException
说明:java.util.Arrays.sort
和({间接)java.util.Collections.sort
使用的排序算法已被替换。如果新排序实现检测到IllegalArgumentException
,则可能会抛出Comparable that violates the Comparable contract
。以前的实现默默地忽略了这种情况。
如果需要先前的行为,则可以使用新的系统属性java.util.Arrays.useLegacyMergeSort
来恢复先前的mergesort行为。
不相容的性质:行为
RFE:6804124
所以正确的实现应该像
public int compareTo( Symbol other) {
if( this.lastUse == other.lastUse) {
return 0;
} else if( other.lastUse>this.lastUse) {
return 1;
}
return -1;
}
参考文献
答案 2 :(得分:1)
如果不看堆栈跟踪本身就很难分辨。
但是docs提到方法本身可以抛出异常。
(可选)如果实现检测到列表元素的自然顺序违反了Comparable合同
<强>更新强>
看起来好像是因为您的对象无法满足Comparable
一致性要求:
当且仅当e1.compareTo(e2)== 0与c1的每个e1和e2的e1.equals(e2)具有相同的布尔值时,C类的自然排序被认为与equals一致。请注意,null不是任何类的实例,并且e.compareTo(null)应该抛出NullPointerException,即使e.equals(null)返回false。