【问题标题】:Comparison method violates its general contract! Java 7 only比较法违反其总约!仅限 Java 7
【发布时间】:2011-10-21 12:42:18
【问题描述】:

我知道这个问题已经有一段时间了,并检查了我能得到的所有以前的答案,但这个仍然不起作用。

对象“船员”代表具有等级和其他物品的船员。比较应该通过比较'assigned_rank',一个int值,如果这个值在两个实例中相等,那么'is_trainer',一个布尔值,应该会有所不同。

只要在 java

java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:714)
at java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:451)
at java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:376)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:182)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
at dormas_flightlog.Query.getCrew(Query.java:714)

这里是来源,其中一些潜在危险的部分已经被注释掉了,但它仍然不起作用:

public class crew implements Serializable, Comparable<crew> {

private static final long serialVersionUID = 36L;
private int flightID = 0;
private int assigned_rank = 25;
private boolean is_trainer = false;
...


@Override
public int compareTo(crew him) {

    int myRank = this.getAssigned_rank();
    int hisRank = him.assigned_rank;

    if (this == him) {
        return 0;
    }
    if (myRank > hisRank) {
        return 1;
    }
    if (myRank < hisRank) {
        return -1;
    }
    if (myRank == hisRank) {
//            if (is_trainer && !o.is_trainer) {
//                i = 1;
//            }
//            if (!is_trainer && o.is_trainer) {
//                i = -1;
//            }
//            if (is_trainer && o.is_trainer) {
//                i = 0;
//            }
//            if (!is_trainer && !o.is_trainer) {
//                i = 0;
//            }
        return 0;
    }

    return 0;
}

@Override
public int hashCode() {
    int hash = 7;
    hash = 31 * hash + this.assigned_rank;
    hash = 31 * hash + (this.is_trainer ? 1 : 0);
    return hash;
}

@Override
public boolean equals(Object o) {

    if (this == o) {
        return true;
    }


    int myRank = this.getAssigned_rank();
    int hisRank = 0;

    if (o instanceof crew) {
        crew him = (crew) o;
        hisRank = him.assigned_rank;
    } else {
        return false;
    }

    if (myRank > hisRank) {
        return false;
    }
    if (myRank < hisRank) {
        return false;
    }
    if (myRank == hisRank) {
//            if (is_trainer && !o.is_trainer) {
//                i = 1;
//            }
//            if (!is_trainer && o.is_trainer) {
//                i = -1;
//            }
//            if (is_trainer && o.is_trainer) {
//                i = 0;
//            }
//            if (!is_trainer && !o.is_trainer) {
//                i = 0;
//            }
        return true;
    }

    return false;
}

}

实现 equals() 只是为了解决这个问题。给定的异常带有或不带有 equals()。我看不到 compareTo 方法是如何违反其合同的。非常感谢任何帮助......有一天这段代码必须与java 7一起使用,我不知道如何...... 谢谢

【问题讨论】:

  • 你能显示你正在排序的代码吗?
  • 那么assigned_rank和getAssigned_rank()有什么区别?
  • 类似问题问here
  • 你有没有找到真正的解决方案(除了像 naresh 建议的那样抑制警告)?在我的案例中,我遇到了类似代码的相同问题。我开始认为这是库代码中的错误。
  • 您的代码看起来不错。您是否有一些发生这种情况的示例对象(或者最好是整个最小示例)?

标签: java-7 compareto


【解决方案1】:

看到这个:

来自http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#source

区域:API:实用程序概要:更新了数组和 集合可能会抛出 IllegalArgumentException

描述:java.util.Arrays.sort 和 (间接)由 java.util.Collections.sort 替换。新的 如果检测到 sort 实现可能会抛出 IllegalArgumentException 违反 Comparable 合同的 Comparable。以前的 执行默默地忽略了这种情况。如果上一个 行为是需要的,您可以使用新系统 属性 java.util.Arrays.useLegacyMergeSort,恢复以前的 合并排序行为。

不兼容的性质:行为

RFE:6804124

更多详细信息,请查看错误数据库reference here

【讨论】:

  • 对,但是 compareTo 的实现如何违反合同?
  • 如果您举一个例子,说明 OP 的代码违反了 Comparable 所要求的非自反性、传递性和诸如此类的要求,这将非常有帮助。链接的文档只是说其中一定有一个错误。也许我在这里有点傻,但我只是没有看到。
【解决方案2】:

也许您只有通过Collections.sort(...) 比较的NaN 值,这对我来说一直是个问题,即使正确实现了compare(obj1, obj2) 方法,我也遇到了这个异常!检查一下!

【讨论】:

  • 那是我的问题。谢谢! :)
【解决方案3】:

我能够解决这个错误,因为它是 jdk7 中的一个错误。

在这里我找到了解决方案:

"Comparison method violates its general contract!" - TimSort and GridLayout

基本上我只需要添加

JAVA_OPTS="$JAVA_OPTS -Djava.util.Arrays.useLegacyMergeSort=true"

给我的老板

【讨论】:

  • 这不是jdk7的bug,而是你代码的bug。 ;-) 它违反了比较方法的必要条件。
  • 在没有给出任何解释的情况下提到错误在 jdk7 中而被否决。
  • 哈哈,你的 cmets 给了我很好的笑声。我也投了反对票。 useLegacyMegaSort 是一种临时解决方法(不是解决方案),旨在向后兼容 Java
【解决方案4】:

很遗憾,没有一种解决方案适用于 Android。 TimSort 在 Android 的 ViewGroup 中深入使用,与在 Java 7 和 8 下显示的 addChildrenForAccessibility 相关。任何比较均不涉及用户代码。

从其他报告来看,这与通常使用的具有重叠项目的 RelativeLayout 有关。例如,出现在 Image 上的 TextView 或同一位置的两个项目,您一次只能设置一个可见。 https://code.google.com/p/android/issues/detail?id=55933

我还没有找到解决该错误的任何方法。您不能在 Android Studio 或 Eclipse 中设置 -Djava 选项(至少我能找到)。强制使用 Java 1.6 应该可以,但不能。似乎亚马逊较新的 Fire 平板电脑和手机对这个漏洞的敏感程度远高于其他设备。

有传言称 Java 9 将有一个修复,例如运行时选项,但由于存在多年的错误,我怀疑它是否会得到修复——尤其是考虑到甲骨文和谷歌之间的敌意。任何是的,也许这个错误在Android代码中真的很深,应该在那里修复。有超过 10 亿台设备,对于所有现有设备来说,这并不是一个可行的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 2018-03-05
    相关资源
    最近更新 更多