java.lang.Comparable#compareTo
method states as first provision
The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compare- To(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception if and only if y.compareTo(x) throws an exception.)
and according Joshua Bloch in Effective Java in item 12
This trick works fine here but should be used with extreme caution. Don’t use it unless you’re certain the fields in question are non-negative or, more generally, that the difference between the lowest and highest possible field values is less than or equal to Integer.MAX_VALUE (231-1). The reason this trick doesn’t always work is that a signed 32-bit integer isn’t big enough to hold the difference between two arbitrary signed 32-bit integers. If i is a large positive int and j is a large negative int, (i - j) will overflow and return a negative value. The resulting compareTo method will return incorrect results for some arguments and violate the first and second provisions of the compareTo contract. This is not a purely theoretical problem: it has caused failures in real systems. These failures can be difficult to debug, as the broken compareTo method works properly for most input values.
With integers overflow you can violate the first provision and I can't find how, this example shows how the first provision would be violated:
public class ProblemsWithLargeIntegers implements Comparable<ProblemsWithLargeIntegers> {
private int zas;
@Override
public int compareTo(ProblemsWithLargeIntegers o) {
return zas - o.zas;
}
public ProblemsWithLargeIntegers(int zas) {
this.zas = zas;
}
public static void main(String[] args) {
int value1 = ...;
int value2 = ...;
ProblemsWithLargeIntegers d = new ProblemsWithLargeIntegers(value1);
ProblemsWithLargeIntegers e = new ProblemsWithLargeIntegers(value2);
if (!(Math.signum(d.compareTo(e)) == -Math.signum(e.compareTo(d)))){
System.out.println("hey!");
}
}
So I want a value1
and a value2
for getting that? Any idea? Or Joshua was wrong?
Well, this violates the general contract to start with. For example, take value1 = Integer.MIN_VALUE
and value2 = 1
. That will report that Integer.MIN_VALUE > 1
, effectively.
EDIT: Actually, I was wrong - it's easy to violate the first provision:
int value1 = Integer.MIN_VALUE;
int value2 = 0;
You'll get a negative result for both comparisons, because Integer.MIN_VALUE - 0
== 0 - Integer.MIN_VALUE
.