【问题标题】:Java Generic Type NumberJava 通用类型编号
【发布时间】:2013-12-28 21:59:40
【问题描述】:

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

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

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

【问题讨论】:

  • The type of each of the operands of a multiplicative operator must be a type that is convertible (§5.1.8) to a primitive numeric type, or a compile-time error occurs.
  • 您想使用哪些数字类型作为参数?我不认为你可以使用有界泛型本身,但这看起来是一个可以使用多态来解决的问题。

标签: java generics numbers


【解决方案1】:

也许这是你的意图:

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

虽然我还必须说,使用 Number 代替具体的不可变值类型(如 java 原语 double)可能不太健康,因为在上面的示例中,参数甚至可以是不同的类型,例如 Integer 和 Double .

注意:

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

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

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

【讨论】:

    【解决方案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)。 (这件事也不会长久。)

    如果你真的下定决心,你可以编写自己的数字类并使用多态性。否则使用重载或(最好)坚持一种类型。

    【讨论】:

    • 我赞成泛型仅与对象相关的说法。
    【解决方案3】:

    您可以通过编码&lt;T extends Number&gt; 为您的类型指定一个绑定

    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();
    }
    

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

    【讨论】:

    • 当方法被调用时,我想在参数中使用 int 变量或 double 变量。这只能让我使用数字对象
    • @Dando18 Java 泛型只是对象。
    • 请在我编辑的答案中考虑我关于参数类型相等性的附加评论。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多