【问题标题】:Generic method for number types数字类型的通用方法
【发布时间】:2023-03-30 19:42:01
【问题描述】:

有什么方法可以让泛型方法使用它的类型参数,就好像它是一个数字一样?例如,考虑一个方法,它接受任何数字并在保持输入类型的同时返回其值的两倍。

static <T> T foo(T number)  {
    return number*2;
}

这不会编译,因为没有为 Tint 定义 *。将T 更改为&lt;T extends Number&gt; 没有帮助,转换(T)2 也无法编译。

【问题讨论】:

  • 简短回答是否定的。你最终会做大量的 case 语句来检查各种可能的类型。
  • @DavidWallace 真可惜,我确信必须有一种优雅的方法来解决这个问题。:(

标签: java


【解决方案1】:

泛型仅适用于对象。可以使用IntegerDouble 等类,但不能将泛型与基元一起使用。

【讨论】:

  • 谢谢,我忘了。但是仍然可以将 Integer 乘以 2 并将结果分配给 Integer 变量,对吧?
【解决方案2】:

我的回答是基于How to add two java.lang.Numbers?

您可以将值转换为已知的数字类型并在计算后将其转换回来,但这可能会导致(可重复的)舍入错误。

static <T> T foo(T anyNumber)  {
    BigDecimal result = new BigDecimal(anyNumber.doubleValue()).multiply(new BigDecimal(2));
    if (result instanceof Byte) {
        return (Byte) c.byteValueExtract();
    } else if (result instanceof Double) {
        return (Double) c.doubleValue();
    } else if (result instanceof Float) {
        return (Float) c.floatValue();
    } else if (result instanceof Integer) {
        return (Integer) c.intValue();
    } else if (result instanceof Long) {
        return (Long) c.longValue();
    } else if (result instanceof Short) {
        return (Short) c.shortValueExtract();
    } else if (result instanceof BigDecimal) {
        return result;
    } else {
        throw new NotImplementedException();
    }
}

【讨论】:

  • 第二行的 a 和 b 是什么?此外,问题仍然存在 - 当返回类型为 T 时,我无法返回 Byte。
  • @user1859055:对不起,我搞砸了变量。现在已经修好了。
  • BigDecimal 算术并不总是给出与DoubleFloat 算术相同的结果。所以这会对某些操作给出不同的答案。当然,乘以 2 不是这样的操作;但我认为 OP 想要一些通用的东西。此外,BigDecimal 的除法可能会出现问题。
  • @DavidWallace:是的,我提到了舍入误差,还会出现什么其他问题?
  • 基本上,每当您进行BigDecimal 除法时,您都需要指定您希望如何进行舍入——小数位数和方向。如果您不这样做,您几乎总是会收到ArithmeticException。因此,如果 OP 的方法涉及除法,则需要进行一些超出您在这里所做的特殊处理。此外,通过在方法的第一行调用doubleValue(),如果您的参数是long,您可能会损失很多精度。
【解决方案3】:

没有办法做运算符重载,例如:

T number = new T();
number * 5;

在 Java 中。我不知道为什么,但你就是不能。相反,尝试做;

static <T> T foo(T number)  {
    return new T(number.getInt()*2);
}

或类似的东西。希望能帮助到你。 "+" operator for Java-classes

编辑: 为了扩展 cmets 中提到的有关使用 Integer i = 5; 的内容,这是 Java 的一个称为自动装箱/拆箱的功能。当你这样做时:

Integer i = 5;
i = i * 4;
int n = i;

Java 真的在做:

Integer i = new Integer(5);
i = new Integer(i.intValue() * 4);
int n = i.intValue();

【讨论】:

  • 你不能实例化一个泛型类型。
  • 很公平,我注意到我还假设 number 是一个 int。我将保存此页面并在几秒钟内修复它,但现在认为此示例已损坏。
  • 你可能误解了我的意思。 T 不是我的自定义类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 2012-02-04
  • 1970-01-01
  • 2022-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多