我的方法如何接受任何类型的Number作为方法参数? (Java泛型)

时间:2017-03-13 14:27:38

标签: java generics

我的CustomNumber类扩展了Number类(实现了所有方法,但未在此处列出)。该类有一个除法方法,它应该如下工作:我可以给它任何类型的Number参数,并且总是得到一个没有精度损失的计算。这就是我考虑双重价值的原因。但在这种情况下,我不能用其他任何东西来调用这个方法,而是Double Objects。我怎样才能制作这种方法,可能全班100%通用?

Error from server: code=1500 [Replica(s) failed to execute write] message="Operation failed - received 0 responses and 1 failures" info={'required_responses': 1, 'consistency': 'LOCAL_ONE', 'received_responses': 0, 'failures': 1}

3 个答案:

答案 0 :(得分:0)

在这方面,Java非常烦人。

他们在教条上不允许运算符重载(尽管Scala有它),因此您被迫将/编码为名为divide或类似的方法,依此类推。

有关更多细节,请参阅如何实现BigInteger等任意精度库,并根据该解决方案建立解决方案。

Java中的一个加分点,您可能会使用BigDecimal并完全取消您的想法。虽然在使用它执行复杂数学运算时最终得到的代码实际上是不可读的。 (因此我采用C ++和JNI)。

答案 1 :(得分:0)

如果这是你正在尝试的,它不起作用:

    CustomNumber<Integer> quotient = division(5, 3);

我们收到“类型不匹配:无法从CustomNumber<Double>转换为CustomNumber<Integer>”。原因很明显。即使你试图划分的数字被自动编码到Integer

直接的解决方案是完全放弃泛型:

public class CustomNumber extends java.lang.Number {

    // ...

    public static CustomNumber division(Number a, Number b) {
        return new CustomNumber(a.doubleValue() / b.doubleValue());
    }
}

现在我们没有问题:

    CustomNumber quotient = division(5, 3);
    System.out.println(quotient);

在您的课程中使用适当的toString方法,应该打印:

1.6666666666666667

答案 2 :(得分:0)

java.lang.Number提供的方法很少。例如,分部对每种类型都没有做同样的事情。 1.0d/2.0d0.5d1/20。因此,您必须决定自己在做什么。另请注意,double并不完全代表long,或者说BigInteger

要将各种形式的数字映射到您的常用解释,您需要一个适配器层。可能有多种方法来映射数字类型。

public interface CustomNumber<THIS extends CustomNumber<THIS>> {
    THIS divide(THIS other);
}

public final class LongNumber extends CustomNumber<LongNumber> {
    // (Note, you don't actually need to overload this,
    //    but it does prevent the likes of LongNumber.of(aDouble).)
    public static LongNumber of(Long value) {
        return new LongNumber(value);
    }
    public static LongNumber of(AtomicLong value) {
        return new LongNumber(value);
    }

    private final Number value;

    private LongNumber(Number value) {
        this.value = value;
    }

    @Override public LongNumber divide(LongNumber other) {
        return this.longValue() / other.longValue();
    }
}

你可能想要一个适用于相同类型的适配器,比如银行家&#39;四舍五入。我甚至不想考虑如何实现它。或完全饱和算术。所以这里是一个保留替代实现的标志(仍然按零除):

    @Override public SignPreservingLongNumber divide(
        SignPreservingLongNumber other
    ) {
        long dividend = this.longValue();
        long divisor = other.longValue();
        return (
            dividend == Long.MIN_VALUE &&
            divisor == -1
        ) ? Long.MAX_VALUE : dividend/divisor;
    }