Java方法中的多个类型参数,包括现有的类和原始数据类型

Xer*_*erz 6 java oop adapter dynamic-proxy

我有一个带有以下代码的类,在这里我希望使用任何代表数字的类/类型都是琐碎的。我发现自己定义了大量的方法,如下所示:

public class Range {
    private BigDecimal inferior = new BigDecimal(0);
    private BigDecimal superior = new BigDecimal(1);

    public Range(BigDecimal inferior, BigDecimal superior) {
        if (inferior.compareTo(superior) == -1) {
            this.inferior = inferior;
            this.superior = superior;
        }
    }
    public Range(int inferior, int superior) {
        this(new BigDecimal(inferior), new BigDecimal(superior));
    }
    public Range(Integer inferior, Integer superior) {
        this(new BigDecimal(inferior), new BigDecimal(superior));
    }
    public Range(float inferior, float superior) {
        this(new BigDecimal(inferior), new BigDecimal(superior));
    }
    public Range(double inferior, double superior) {
        this(new BigDecimal(inferior), new BigDecimal(superior));
    }
}
Run Code Online (Sandbox Code Playgroud)

我什至没有写所有可能的组合!例如,采用浮点数和双精度数的整数,或者采用int和BigDecimal的整数。

如何以一种干净的方式实现这一点,以便有一些参数对于已经预定义的甚至是原语的多个类/数据类型有效?我已经考虑过适配器和代理,但是我经常发现自己不理解这些解释,并且无法弄清楚它们是否适合我的用例,以及如何适应-这个问题可能已经在SO上得到了回答,但是至少可以我想看看是否有人可以根据这个特定示例向我解释。

rge*_*man 5

使用构建器模式。创建一个嵌套静态类,该类接受两个数字中每个数字的不同数据类型。byte从到 的原始类型long将被扩展为long, 和floatto doubleBigIntegers 可以转换为BigDecimals,并且BigDecimal引用将被复制。

public static class Builder {
    BigDecimal first;
    BigDecimal second;

    public void setFirst(long value) { first = new BigDecimal(value); }
    public void setFirst(double value) { first = new BigDecimal(value); }
    public void setFirst(BigInteger value) { first = new BigDecimal(value); }
    public void setFirst(BigDecimal value) { first = value; }
    public void setSecond(long value) { second = new BigDecimal(value); }
    public void setSecond(double value) { second = new BigDecimal(value); }
    public void setSecond(BigInteger value) { second = new BigDecimal(value); }
    public void setSecond(BigDecimal value) { second = value; }
    public Range build() {
        if (first == null || second == null) {
            throw new IllegalArgumentException("Must supply both values.");
        }
        return new Range(first, second);
    }
}
Run Code Online (Sandbox Code Playgroud)

构建器模式允许在构建所需的对象之前进行验证,并且它绕过了尝试覆盖每种可能的组合时可能发生的“构造函数爆炸”。对于n 个可能的类型,您有 2 * n 个构建器 setter 方法,而不是n 2 个构造函数。

我将 包括在内long,尽管出于double精确原因可以合法地将其扩展为 s ,因为有非常高的类型值long无法精确表示为doubles

然后,你的构造函数变成:

public Range(BigDecimal first, BigDecimal second) {
    if (first.compareTo(second) < 0) {
        this.inferior = first;
        this.superior = second;
    }
    else {
        this.inferior = second;
        this.superior = first;
    }
}
Run Code Online (Sandbox Code Playgroud)

我更改了== -1to< 0以匹配compareTo合同,并添加了else在需要时切换它们的情况。


men*_*urg 2

使用类别Number

public Range(Number inferior, Number superior)
Run Code Online (Sandbox Code Playgroud)

Integer, Long, Double- 它们都是 的子类Number

或者,使用泛型:

public class Range<T> {
    private T inferior;
    private T superior;

    public Range(T inferior, T superior) {
        this.inferior = inferior;
        this.superior = superior;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

Range<Long> rangeLong = new Range<>(0L, 1000000000L);
Range<Double> rangeDouble= new Range<>(0d, 457.129d);
Run Code Online (Sandbox Code Playgroud)