不,不检查类型是不行的
一个Number只提供了转换为图元的方法,每个图元都不足以给出准确的答案。
doubleValue 不起作用
static boolean wrongIsMultipleOfUsingDouble(Number a, Number b) {
return (a.doubleValue() % b.doubleValue()) == 0;
}
由于double只有53位精度,当输入是需要63位精度的long时,它会给出错误答案:
System.out.println(wrongIsMultipleOfUsingDouble(6969696969696969696L, 3L));
// prints `false`, but should be `true`
System.out.println(wrongIsMultipleOfUsingDouble(7777777777777777777L, 2L));
// prints `true`, but should be `false`.
longValue 不起作用
static boolean wrongIsMultipleOfUsingLong(Number a, Number b) {
return (a.longValue() % b.longValue()) == 0;
}
由于截断,显然它不起作用。
System.out.println(wrongIsMultipleOfUsingLong(5.0, 2.5));
// prints `false`, but should be `true`
System.out.println(wrongIsMultipleOfUsingLong(4.5, 2.0));
// prints `true`, but should be `false`.
类型检查仅适用于已知类型。
虽然 OP 喜欢避免类型检查,但这确实是接近可接受解决方案的唯一方法。
static boolean wrongIsMultipleOfUsingTypeChecking(Number a, Number b) {
// pseudo-code for simplicity
if (a, b instanceof (AtomicInteger | AtomicLong | Byte | Integer | Long | ...)) {
return (a.longValue() % b.longValue()) == 0;
} else if (a, b instanceof (Double | DoubleAccumulator | DoubleAdder | Float) {
return (a.doubleValue() % b.doubleValue()) == 0;
} else if (a, b instanceof (BigInteger | BigDecimal)) {
return a.remainder(b) == ZERO;
} else {
throw new RuntimeError("I give up");
}
}
这在大多数情况下都很好,但它仍然无法正常工作,因为它无法处理 Number 的第三方子类,例如 org.apache.commons.math4.fraction.Fraction?
仅限 JSON 数字?
现在 OP 声明使用 Number 是因为该数字来自 JSON。这些数字通常只有long 或double,因此类型检查方法就足够了。
不过,most popular libraries in Java 也支持将数字解释为 BigDecimal:
BigDecimal 涵盖了double 和long 的范围,并且有一个实际的.remainder() method 可以解决OP 的问题。如果我们只想使用单个类来执行算术,并且 BigDecimal 的价格不是一个大问题,那么这可能是一个可行的替代方案。