Happens if at least one of the values (values == value in RowFilter, value in entry) is a decimal. Here's a failing test:
@Test
public void testRowFilterNumberMixCore() {
TestEntry entry = new TestEntry(1.2f);
RowFilter filter = RowFilter.numberFilter(ComparisonType.AFTER, 1, 0);
assertTrue(entry + "must be included " + filter, filter.include(entry));
}
The output is:
junit.framework.AssertionFailedError:
[entry: 1.2] must be included [RowFilter: ComparisonType = AFTER, comparableValue: 1, comparableClass: class java.lang.Integer]
The reason is that NumberFilter falls back to comparing the numbers by their number.longValue() if they are not the same class (and by that comparable to each other)
Knowing that detail, the test failure is not astonishing (in hind-sight, would have never thought of that being an issue ;-) One level of defense is to make sure - in client code - that the numbers to compare are of the same class. That's not always possible (think f.i.: a tableColumn with columnClass Number) So I'm wondering if/how to improve on the fallback. Something like:
if (one instanceof Comparable && one.getClass() == other.getClass()) {
// same class, use comparator
return ((Comparable) one).compareTo(other);
}
if (areIntegers(one, other)) {
// all integers, use longValue
return longCompare(one, other);
}
if (areDecimals(one, other)) {
// anything to do here?
}
// at last resort convert to BigDecimal and compare those:
BigDecimal bigOne = new BigDecimal(one.toString());
BigDecimal bigOther = new BigDecimal(other.toString());
return bigOne.compareTo(bigOther);
Doing so, makes the test pass - I'm a bit wary about hidden (read: unknown to me :) pitfalls. Any warnings/alternatives highly welcome!
FYI: cross-posted to OTN's Swing forum
Follow-up
implemented as outlined above, now waiting for clients to complain - in that case will point fingers to everybody who didn't warn me here :-)
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…