Java通用类型编号

时间:2013-12-28 21:59:41

标签: java generics numbers

我已经阅读了几个关于泛型方法的页面,并对它们有一些掌握,但我仍然不理解它们。所以说我有一种方法来乘以两个数字并返回产品:

public double multiply(SomeNumberVariableType x, SomeNumberVariableType y){
    return x * y;
}

如何使用有界泛型只允许数字类型作为参数?

3 个答案:

答案 0 :(得分:2)

也许这是你的意图:

public static <N extends Number> double multiply(N x, N y){
    return x.doubleValue() * y.doubleValue();
}

虽然我还必须说一般使用Number而不是像java原始double这样的具体不可变值类型可能不那么健康,因为在上面的例子中,参数甚至可以是不同的类型,例如Integer和双。

<强>注意:

我确认,参数可以是不同类型,如上面给出的签名。所以波希米亚人的答案是错误的。我刚刚测试过它(但之前已经知道了)。编译器只保证两个参数都是Number类型,没有别的。

为了断言相同的参数类型,编译器需要自引用泛型。 Number-class不满足此功能(遗憾的是,&lt; N extends Number&lt; N&gt;&gt;)是不可能的。这就是为什么我认为整数方法不是很健康。这里是每个人都可以执行的测试代码:

Integer x = Integer.valueOf(10);
Double y = new Double(2.5);
System.out.println(multiply(x, y));
// Output: 25.0

答案 1 :(得分:2)

通常,Java泛型不适合数学。

在Java中:

  • 泛型只是对象。
  • 对象没有数学运算符。

看起来您可以对对象执行数学运算,因为您可以执行以下操作:

Integer a = 1;
Integer b = 2;
Integer c = a + b;

但这仅仅是因为自动装箱。实际发生的是编译器用以下代码替换该代码:

Integer a = new Integer(1);
Integer b = new Integer(3);
Integer c = Integer.valueOf(a.intValue() + b.intValue());

使用泛型,您可以指定一个绑定,以便您的类型必须是Number或其子类型:

static <N extends Number> N multiply(N n1, N n2) {
    return n1 * n2; // but you cannot do this because the type is not known
                    // so the compiler cannot do autoboxing
}

如果知道超类型,你可以调用它们的方法,这样就可以按照指出的方式执行此操作:

static <N extends Number> double multiply(N n1, N n2) {
    return n1.doubleValue() * n2.doubleValue();
}

但这与以下内容没有什么不同:

static double multiply(double n1, double n2) {
    return n1 * n2;
}

除了通用版本可以,例如,将BigDecimal作为参数,当然不会提供可靠的结果(参见BigDecimal#doubleValue)。 (对此事也不会长。)

如果你真的认定你可以编写自己的数字类并使用多态。否则使用重载或(最重要的是)坚持一种类型。

答案 2 :(得分:1)

您可以通过编码<T extends Number>为您的类型指定绑定

public static double <T extends Number> multiply(T x, T y){
    return x.doubleValue() * y.doubleValue();
}

将Number类型限制为相同的类型,例如Integer和Integer,但不是Integer和Long。

但你根本不需要泛型:

public static double multiply(Number x, Number y){
    return x.doubleValue() * y.doubleValue();
}

允许任意两个数字,例如整数和长整数。