我可以在Number基类上进行算术运算吗?

我正在尝试在Java中创build一个将执行数字操作的generics类。 在下面的例子中,添加如下:

public class Example <T extends Number> { public T add(T a, T b){ return a + b; } } 

原谅我的天真,因为我是相对较新的Javagenerics。 此代码无法编译的错误:

运算符+对于参数typesT,T是未定义的

我认为,增加“扩展数字”的代码将编译。 是否有可能做这个Java,或者我将不得不为每个数字types创build重写的方法?

数字没有与它关联的+操作符,也不可以,因为没有操作符重载。

这将是很好,但。

基本上,你要求java自动化一个数字的副本,其中包括整数,浮点数和双精度,可以被自动装箱,并且应用了一个加号运算符,然而,可能有任何数量的其他未知的后代号码不能被自动装箱,直到运行时才能知道。 (该死的删除)

你的问题并没有真正涉及到generics,而是涉及到操作符,原始对象和自动装箱。

想想这个:

 public static void main(String[] args) { Number a = new Integer(2); Number b = new Integer(3); Number c = a + b; } 

以上不编译

 public static void main(String[] args) { Integer a = new Integer(2); Integer b = new Integer(3); Number c = a + b; } 

上面编译的,但仅仅是因为自动装箱 – 这是Java 5中引入的一种怪异的语法粘合,只能在编译时使用一些具体的types:int-Integer。

在幕后,Java编译器正在重写最后一条语句(“我必须解开ab以将sum操作符与原始数据types一起使用,然后将结果分配给对象c ”):

  Number c = Integer.valueOf( a.intValue() + b.intValue() ); 

Java不能解开一个Number因为它不知道在编译时的具体types,因此它不能猜测它的原始对应。

你可以做这样的事情

  class Example <T extends Number> { public Number add(T a, T b){ return new Double(a.doubleValue() + b.doubleValue()); } } 

是的,Nathan是对的。 如果你想要这样的东西,你必须自己写

 public class Example <T extends Number> { private final Calculator<T> calc; public Example(Calculator<T> calc) { this.calc = calc; } public T add(T a, T b){ return calc.add(a,b); } } public interface Calculator<T extends Number> { public T add(T a, T b); } public class IntCalc implements Calculator<Integer> { public final static IntCalc INSTANCE = new IntCalc(); private IntCalc(){} public Integer add(Integer a, Integer b) { return a + b; } } ... Example<Integer> ex = new Example<Integer>(IntCalc.INSTANCE); System.out.println(ex.add(12,13)); 

太糟糕的Java没有types类(Haskell)或隐式对象(Scala),这个任务将是一个完美的用例…

这个问题也有类似的问题,答案是你不能这样做。

你可以检查a和b是一个Long / Double / Integer /等的实例。 并将添加委托给如下方法:

 public Integer add(Integer a, Integer b) { return a+b; // this actually uses auto boxing and unboxing to int } 

而且您需要为扩展Number的每个types创build一个,所以这不是真的可行。 换句话说,不要使用generics进行数字操作。 作为超类的数量相当有限。

考虑Example<Number> ,将如何工作呢? Number没有add或类似的东西,甚至没有Integer类似的东西。

更糟糕的是考虑到final class FunkyNumber extends Number { ... weird stuff, no add op ... }

即使是Java运行时库也有这个问题,大多数处理基元的方法都必须重复相同的function。

最快的select是为一个types编写代码,然后复制它并replacetypes以生成其他types的方法。 一个简短的脚本应该足以做到这一点。