RowFilter.NumberFilter:无法处理“混合”具体数字类型
如果至少有一个值(RowFilter 中的值 == 值,条目中的值)是小数,则会发生这种情况。这是一个失败的测试:
@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));
}
输出是:
junit.framework.AssertionFailedError: [entry: 1.2] must be included [RowFilter: ComparisonType = AFTER, comparableValue: 1, comparableClass: class java.lang.Integer]
原因是 NumberFilter 会回退到通过 number.longValue() 比较数字,如果它们不是同一类(并且通过相互比较)
知道细节,测试失败并不令人惊讶(事后看来,从来没有想到这是一个问题;-)防御的一个级别是确保 - 在客户端代码中 - 要比较的数字相同班级。这并不总是可能的(想想fi:带有columnClass Number的tableColumn)所以我想知道是否/如何改进后备。像这样的事情:
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);
这样做可以使测试通过 - 我对隐藏的(阅读:我不知道:)陷阱有点警惕。非常欢迎任何警告/替代方案!
仅供参考:交叉发布到 OTN 的 Swing 论坛
按照上面概述的方式实施后续行动
,现在等待客户投诉 - 在这种情况下,我们将指责所有没有在这里警告我的人:-)
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 :-)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我没有更好的答案,但下面的例子说明了效果。特别是,基于
double
原语的RowFilter
是 装箱为Double
,生成具有values > 的预期tableau 1.
.相比之下,基于float
的则被装箱为Float
。由于类文字不匹配,include()
会比较long
值,意外地过滤了所有小数值
值
2.
.I don't have a better answer, but the example below illustrates the effect. In particular, a
RowFilter
based on adouble
primitive is boxed asDouble
, producing the expected tableau havingvalues > 1
. In contrast, the one based on afloat
is boxed asFloat
. Because the class literals do not match,include()
compares thelong
values, unexpectedly filtering all fractionalvalues < 2
.