繁体   English   中英

Java 通用型号

[英]Java Generic Type Number

我已经阅读了几页关于泛型方法的页面,并且对它们有所了解,但我仍然不理解它们。 所以说我有一种方法可以将两个数字相乘并返回乘积:

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

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

也许这是您的意图:

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

尽管我也必须说,用Number代替诸如Java原始double这样的具体不可变值类型的一般用法可能不太健康,因为在上面的示例中,参数甚至可以是不同的类型,例如Integer和Double。

注意:

我确认,自变量可以是上面给出的签名的不同类型。 因此,波希米亚的答案是错误的。 我刚刚测试了它(但之前已经知道了)。 编译器仅保证两个参数的类型均为Number,其他都没有。

为了声明相同的参数类型,编译器需要自引用泛型。 Number-class无法满足此功能(不幸的是,<N扩展Number <N >>是不可能的)。 这就是为什么我认为整个数字方法并不真正健康。 这是每个人都可以执行的测试代码:

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

通常,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 )。 (对此也不会渴望。)

如果确实有决心,则可以编写自己的数字类并使用多态。 否则,请使用重载或(最好)使用一种类型。

您可以通过编码<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();
}

它允许任何两个数字,例如Integer和Long。

这是什么

import java.util.function.BinaryOperator;
public class GenericArithmetic {

    public static <T extends Number> BinaryOperator<T> get_multiplier(T t1){
        BinaryOperator<Integer> intMultiper = (i1, i2) -> i1 * i2;
        BinaryOperator<Float> floatMultiper = (i1, i2) -> i1 * i2;

        // should cache
        switch (t1.getClass().getName()) {
            case "java.lang.Integer":
                return (BinaryOperator<T>) intMultiper;
            case "java.lang.Float":
                return (BinaryOperator<T>) floatMultiper;
            default:
                return null;
        }
    }

    public static <T extends Number> Number multiply(T x, T y) throws Exception{
        var multiplier = get_multiplier(x);
        var res = multiplier.apply(x, y);
        return res;
    }


    public static void main(String[] args) throws Exception{
        var a1 = 3;
        var a2 = 5;

        var res = multiply(a1, a2);
        System.out.println(res);

        var b1 = 2.0f;
        var b2 = 3.0f;
        var res2 = multiply(b1,b2);
        System.out.println(res2);   
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM