如何用Java编写支持比较和算术运算的泛型方法

如何用Java编写支持比较和算术运算的泛型方法,java,generics,Java,Generics,我想用java编写一个通用方法,如下所示: public <T extends Number & Comparable<T>> void test(T[] a){ T b=a[0]; if(a[0]>0){ a[0]*=a[0]; b+=a[1]; } } 公共无效测试(T[]a){ tb=a[0]; 如果(a[0]>0){ a[0]*=a[0]; b+=a[1]; } } 然后,我可以为该方法提供

我想用java编写一个通用方法,如下所示:

public <T extends Number & Comparable<T>> void test(T[] a){
    T b=a[0];
    if(a[0]>0){
        a[0]*=a[0];
        b+=a[1];
    }
}
公共无效测试(T[]a){
tb=a[0];
如果(a[0]>0){
a[0]*=a[0];
b+=a[1];
}
}
然后,我可以为该方法提供
Integer[]
Double[]
或其他
Number
子类型。但是我上面尝试的代码给了我错误


请帮帮我。谢谢。

在Java中使用泛型无法做到这一点。这是C++的一个好处。 在某种程度上,您可以将其定义为“奇怪”,因为在Java的基本包装器上使用操作符是可能的。但这是因为不能在
java.lang.Number
上使用运算符,这是基本包装器的超类

一些资源:

除原语外的所有类型(包括推断的泛型类型)都是不支持算术运算的对象(包装器类使用装箱/拆箱来获得已知的psuedo行为)

类型擦除使编译后的代码使用强制转换来获得正确的行为(即,在运行时,JVM不知道传递了什么类型,需要知道哪些类型才能获得正确的装箱/取消装箱行为)


唯一的(真正的)解决方案是为您想要支持的所有原语提供实现

您已经有了可比的,因此如果我们有一个
a[0]>0
可以被
a[0]替换。相比(零)>0
(不,我想它是
<0
,我永远记不起来了)。但是现在我们已经用完了
Double
之类的有用的东西

如果
Double
和朋友不
java.lang.Compariable
我们可以提供自己的
java.util.Compariator
。也就是说,我们在数据对象之外实现比较。我们也可以做加法和乘法

public interface Testor<T> { // Choose a better name...
    boolean isStriclyPositive(T value);
    T add(T lhs, T rhs);
    T square(T value);
}

static final Testor<Integer> INTEGER_TESTOR = new Testor<>() { // Java SE 7 diamond.
    public boolean isStriclyPositive(Integer value) { return value > 0; }
    public Integer add(Integer lhs, Integer rhs) { return lhs + rhs; }
    public Integer square(Integer value) { return value*value; }
}
// ... same for Double, etc.; can't use an enum :( ...

test(new Integer[] { 42, 1972, 86 }, INTEGER_TESTOR);

public <T> void test(T[] a, Testor<T> testor) {
    T b = a[0];
    if (testor.isStrictlyPositive(a[0])) {
        a[0] = testor.square(a[0]);
        b = testor.add(b, a[1]);
    }
}
公共接口测试或{//选择一个更好的名称。。。
布尔值为三次正(T值);
T添加(T左侧,T右侧);
T平方(T值);
}
static final Testor INTEGER_Testor=new Testor(){//JavaSE7菱形。
公共布尔值为三次正(整数值){返回值>0;}
公共整数加法(整数lhs,整数rhs){返回lhs+rhs;}
公共整数平方(整数值){返回值*值;}
}
// ... 双人等同。;无法使用枚举:(。。。
test(新的整数[]{421972,86},Integer_TESTOR);
公共无效测试(T[]a,Testor Testor){
tb=a[0];
if(testor.isStrictlyPositive(a[0])){
a[0]=testor.square(a[0]);
b=testor.add(b,a[1]);
}
}
注意:对于
Short
,将其中两个求和将得到
int


(通常的堆栈溢出免责声明:与其说是尝试编译代码,不如说是尝试编译代码。)

谢谢你的回答。有没有更简短、更优雅的方法来完成其他复制代码?@littleEinstein:如果你只想进行比较,你可以使用。但是你不能在Java中的
Number
实例上执行算术。@DanielPryden:对。但是我的方法必须要做算术。你有好的解决方案吗@littleEinstein:正如我在对你的问题的评论中所说的,我们需要的是对你的用例的解释。你为什么要这样做?你能把所有的东西都翻过来,比如说,
翻一番
,然后使用它吗?(
double
可以保存除
long
之外的任何其他数值类型的所有值,而不会丢失精度。)好的,现在我明白了原因。但是如果我希望我的方法能够处理整数[]、双精度[]、浮点[],那么如何实际重用代码?这是Java泛型中令人恼火的部分:你根本不能。你唯一可以尝试的是始终使用double,并在使用前后将数据转换为double。你试图解决的问题是什么?Java不支持这种泛型操作。如果我们理解这个用例,也许我们可以建议替代选项例如,我发现使用包装类数组(如
Integer[]
)而不是原语数组(如
int[]
)从来都不是一个好主意。你需要
Integer
Double
而不是
int
Double
有什么原因吗?@DanielPryden:我正在尝试解决:编写一个接受int[]、float[]或Double[]的方法,并在其中进行一些比较和运算,然后返回相同类型的数组int[]、float[]或Double[]。然后,您最好将实际计算结果分解成一个方法,该方法使用
double[]
操作,并返回
double[]
(因为
double
int
float
都宽)。您仍然需要另外两个方法来支持
int[]
float[]
参数。