我已经阅读了几个关于泛型方法的页面,并对它们有一些掌握,但我仍然不理解它们。所以说我有一种方法来乘以两个数字并返回产品:
public double multiply(SomeNumberVariableType x, SomeNumberVariableType y){
return x * y;
}
如何使用有界泛型只允许数字类型作为参数?
答案 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();
}
允许任意两个数字,例如整数和长整数。