如何在JDK 1.8中为java.lang.Number编写泛型

时间:2015-03-04 04:03:02

标签: java generics numbers

我有这样的代码,我喜欢使它适用于byte,short,int,long,float和double:

// IF I past in List<Long> it should return List<Long>.
public static <T extends Number> List<T> noneNegativeInts(List<T> numbers) {
        List<T> values = new LinkedList<>();
        for (T num : numbers) {
            values.add((T) Math.abs(num.doubleValue())); // !! Compiler error here.
        }
        return values;
    }

此外,此代码如下:

public static <T extends Number> T abs(T number) {
    if(number instanceof Double){
        Double val=number.doubleValue();
        return (T)(val <= 0.0D) ? 0.0D - val : val;
    }
    if(number instanceof Float){
        Float val=number.floatValue();
        return (T)(val <= 0.0F) ? 0.0F - val : val;
    }
}

如何更改这些代码?

2 个答案:

答案 0 :(得分:1)

问题是没有通用Math.abs功能。 Math.abs需要特定类型,例如doubleint等。因此,您被迫将您的通用类型转换为特定类型,例如double,并且一旦您完成转换,不能再把它变得通用了。

因此,您可以采用与Number interface相同的模式,并为每种数字类型创建单独的方法。例如:

public static <T extends Number> List<Integer> nonNegativeInts(List<T> numbers) {
    // ...
}

public static <T extends Number> List<Double> nonNegativeDoubles(List<T> numbers) {
    // ...
}

// etc.

答案 1 :(得分:1)

尝试使用upper bounded wildcard,如此:

import java.util.Arrays;
import java.util.List;
import java.util.LinkedList;

public class A {
    public static List<? extends Number> noneNegativeInts(List<? extends Number> numbers) {
        List<Number> values = new LinkedList<>();
        for (Number num : numbers) {
            values.add(Math.abs(num.doubleValue()));
        }
        return values;
    }

    public static void main(String[] args) {
        System.out.println(noneNegativeInts(Arrays.asList(new Integer[] {2,3,4,5,-1})));
        System.out.println(noneNegativeInts(Arrays.asList(new Double[] {2.,3.,4.,5.,-1.})));
        System.out.println(noneNegativeInts(Arrays.asList(new Byte[] {2,3,4,5,-1})));
        // etc.
    }
}

当您想要创建一个可以跨多个Collection类型工作的方法时,上边界通配符非常有用,这些类型的参数化类型与超类相关,例如:List<Integer>List<Double>等。这些类型没有直接的超类,除了通配符,它​​允许你表达一个&#34;伪超类&#34;所有这些Collection类型基于其参数化类型的超类Number。然后,您的方法将适用于您指定的边界下存在的任何类。