【问题标题】:Java generics and the Number classJava 泛型和 Number 类
【发布时间】:2010-10-13 11:24:04
【问题描述】:

我想创建一个方法来比较一个数字,但可以有一个 Number 的任何子类的输入。

我已经研究过以下列方式执行此操作...

public static <T extends Number> void evaluate(T inputNumber) {
  if (inputNumber >= x) {
    ...
  }
}

在进行比较之前,我需要获取实际的基本体,Number 类具有为每个基本体检索它的方法,但我想要一种干净的方式来选择正确的那个。

这可能吗?

干杯

【问题讨论】:

标签: java generics numbers


【解决方案1】:

Number API 没有提供一种干净的方式来获取价值;你必须使用instanceof

一种解决方案是将值“折叠”成两种类型:longdouble。这样,您可以使用以下代码:

if( inputNumber instanceof Float || inputNumber instanceof Double ) {
    double val = inputNumber.doubleValue();
    ...
} else {
    long val = inputNumber.longValue();
    ...
}

请注意,这仅适用于标准数字类型,但Number 也由许多其他类型(AtomicIntegerBigDecimal)实现。

如果你想支持所有类型,一个技巧是使用BigDecimal

BigDecimal value = new BigDecimal( inputNumber.toString() );

这应该始终有效并为您提供最准确的结果。

【讨论】:

    【解决方案2】:

    不幸的是,如果不使用 if/else 块,就无法从包装类型中获取原始类型。

    问题是不可能以通用方式实现这样的方法。以下是在 Number 类中可以找到的一些看似可行的方法:

    public abstract X getPrimitiveValue();
    

    这样会很好,不是吗?但是这是不可能的。没有可能的 X 可以是对 intfloatdouble 等的抽象。

    public abstract Class<?> getCorrespondingPrimitiveClass();
    

    这也无济于事,因为无法实例化原始类。

    因此,您唯一能做的对所有类型都通用的事情就是使用longValue()doubleValue() 方法,但无论哪种方式,如果您处理错误的类型,您都会丢失信息。

    所以不:Java 编号层次结构不适合以通用方式解决此类问题。

    【讨论】:

      【解决方案3】:

      带有&lt;T extends Number&gt; 的方法总是很麻烦,因为你不能对数字做任何事情(所有的运算符都是为孩子定义的)。您需要为 Number 的每个子项执行大量 instanceof 并通过强制转换为子类型来处理这种情况。或者(我认为更好——Sun 就是这样做的)是只为每个子类型设置一个方法,可能在可能的情况下利用 +、-、> 等运算符的装箱/拆箱(所有包装器,而不是对于 BigInteger/BigDecimal 或任何自定义类型)。

      【讨论】:

        【解决方案4】:

        如果真的只是将参数与相同类型参数的另一个值进行比较,那么您可以执行以下操作(为简单起见,只需添加 T x

           public static <T extends Number & Comparable<? super Number>> int evaluate(T inputNumber, T x) {
                  if (inputNumber.compareTo(x) > 0) { ... }
           }
        

        【讨论】:

          【解决方案5】:

          在这种情况下,您可以使用没有泛型的普通方法

          【讨论】:

          • 因此,如果该方法是接受双精度或整数,那么我需要两个具有不同签名的方法,还是我遗漏了什么?
          • @Mr_R:如果您使用 Java 5,那么自动装箱会将其转换为都实现 Number 的 Double 和 Integer。
          • 利用多态性并简单地提供一个evaluate(Number) 方法
          【解决方案6】:

          始终可以选择使用模式接口处理未知数据。这就是 sorts 与 Comparator 接口的工作方式。您应该使用 evaluate(T number) 方法创建并添加作为方法参数功能接口 Evaluator 并确定方法外的评估逻辑。您还可以从帮助类创建一些示例,例如 Evaluators::IntegerEvaluator 它将适用于整数并将它们推荐给客户。 对不起我的英语

          【讨论】:

            猜你喜欢
            • 2013-08-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-12-24
            相关资源
            最近更新 更多