我可以在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编译器正在重写最后一条语句(“我必须解开a
和b
以将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的方法。 一个简短的脚本应该足以做到这一点。