2023-05-03 11:06:20 +02:00
== Why is this an issue?
2023-07-20 09:21:35 +02:00
Assuming that a comparator or `compareTo` method always returns -1 or 1 if the first operand is less than or greater than the second is incorrect.
2021-04-28 16:49:39 +02:00
2023-07-20 09:21:35 +02:00
The specifications for both methods, `Comparator.compare` and `Comparable.compareTo`, state that their return value is "a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object."
Even if a specific comparator always returns -1, 0, or 1, this is only an implementation detail, not the API contract developers can rely on.
2021-04-28 18:08:03 +02:00
2023-07-20 09:21:35 +02:00
== How to fix it
2021-04-28 16:49:39 +02:00
2023-07-20 09:21:35 +02:00
Replace
- `== -1` with `< 0` (the first operand is less than the second)
- `== 1` with `> 0` (the first operand is greater than the second)
- `!= -1` with `>= 0` (the first operand is greater than or equal to the second)
- `!= 1` with `\<= 0` (the first operand is less than or equal to the second)
=== Code examples
==== Noncompliant code example
[source,java,diff-id=1,diff-type=noncompliant]
2021-04-28 16:49:39 +02:00
----
2023-07-20 09:21:35 +02:00
public class Main {
boolean isAGreaterThanB(Comparable<Integer> a, Integer b) {
return a.compareTo(b) == 1; // Noncompliant, check for constant return value
}
public static void main(String[] args) {
ByteComparator comparator = new ByteComparator();
if (comparator.compare((byte) 23, (byte) 42) == -1) { // Noncompliant, check for constant return value
System.out.println("23 < 42");
} else {
System.out.println("23 >= 42");
}
}
static class ByteComparator implements Comparator<Byte> {
@Override
public int compare(Byte a, Byte b) {
return a - b;
}
}
2021-04-28 16:49:39 +02:00
}
----
2023-07-20 09:21:35 +02:00
==== Compliant solution
2021-04-28 18:08:03 +02:00
2023-07-20 09:21:35 +02:00
[source,java,diff-id=1,diff-type=compliant]
2021-04-28 16:49:39 +02:00
----
2023-07-20 09:21:35 +02:00
public class Main {
boolean isAGreaterThanB(Comparable<Integer> a, Integer b) {
return a.compareTo(b) > 0; // Compliant, check for positive return value
}
public static void main(String[] args) {
ByteComparator comparator = new ByteComparator();
if (comparator.compare((byte) 23, (byte) 42) < 0) { // Compliant, check for negative return value
System.out.println("23 < 42");
} else {
System.out.println("23 >= 42");
}
}
static class ByteComparator implements Comparator<Byte> {
@Override
public int compare(Byte a, Byte b) {
return a - b;
}
}
2021-04-28 16:49:39 +02:00
}
----
2021-04-28 18:08:03 +02:00
2023-07-20 09:21:35 +02:00
== Resources
=== Documentation
* https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html#compareTo-T-[Java SE 8 API Specification: Comparable.compareTo]
* https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#compare-T-T-[Java SE 8 API Specification: Comparator.compare]
2021-04-28 18:08:03 +02:00
2021-09-20 15:38:42 +02:00
ifdef::env-github,rspecator-view[]
'''
== Implementation Specification
(visible only on this page)
2023-05-25 14:18:12 +02:00
=== Message
Only the sign of the result should be examined.
2021-09-20 15:38:42 +02:00
endif::env-github,rspecator-view[]