问题
有人可以用简单的语言解释我,为什么这个代码会抛出异常,"比较方法违反了它的一般合同!",我该如何修复它?
private int compareParents(Foo s1, Foo s2) {
if (s1.getParent() == s2) return -1;
if (s2.getParent() == s1) return 1;
return 0;
}
#1 热门回答(214 赞)
你的比较器不可传递。
LetA
是B
的父代,而B
是C
的父代。自A > B
和B > C
,那么一定是A > C
的情况。但是,如果在3b585291和C
上调用比较器,它将返回零,即A == C
。这违反了合同,因此抛出异常。
图书馆检测到这个并让你知道,而不是表现得不正常,这是相当不错的。
满足compareParents()
中的传递性要求的一种方法是遍历getParent()
链,而不是仅仅查看直接祖先。
#2 热门回答(32 赞)
只是因为这是我在谷歌搜索这个错误时得到的,我的问题是我有
if (value < other.value)
return -1;
else if (value >= other.value)
return 1;
else
return 0;
thevalue >= other.value
应该(显然)实际上是value > other.value
,你实际上可以用相同的对象返回0。
#3 热门回答(19 赞)
违反合同通常意味着比较器在比较对象时没有提供正确或一致的值。例如,你可能希望执行字符串比较并强制将空字符串排序到最后:
if ( one.length() == 0 ) {
return 1; // empty string sorts last
}
if ( two.length() == 0 ) {
return -1; // empty string sorts last
}
return one.compareToIgnoreCase( two );
但是这忽略了一个和两个都是空的情况 - 在这种情况下,返回错误的值(1而不是0来显示匹配),并且比较器报告为违规。应该写成:
if ( one.length() == 0 ) {
if ( two.length() == 0 ) {
return 0; // BOth empty - so indicate
}
return 1; // empty string sorts last
}
if ( two.length() == 0 ) {
return -1; // empty string sorts last
}
return one.compareToIgnoreCase( two );