我正在尝试在Java中创建一个将对数字执行操作的泛型类。在以下示例中,添加如下:
public class Example <T extends Number> {
public T add(T a, T b){
return a + b;
}
}
原谅我的天真,因为我对Java Generics相对较新。此代码无法使用错误编译:
对于参数类型T,T
,运算符+未定义
我认为通过添加“extends Number”,代码将被编译。是否可以执行此Java或我是否必须为每个Number类型创建重写方法?
答案 0 :(得分:26)
Number没有与之关联的+运算符,也没有运算符重载。
但这会很好。
基本上,你要求java自动装载一个数字的目标,其中包括Integer,Float和Double,它们可以被自动装箱并且应用了一个加号运算符,但是,可能有任意数量的其他未知的数字后代无法自动装箱,直到运行时才能知道。 (该死的擦除)
答案 1 :(得分:20)
你的问题与泛型无关,而与运算符,基元与对象以及自动装箱有关。
想一想:
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中引入的一种hacky语法粘合剂,并且仅在某些具体类型中有效(在编译时):int-Integer例如。
在幕后,Java编译器正在重写最后一个语句(“我必须取消装箱a
和b
”才能将sum运算符应用于原始数据类型,并将结果装箱以将其分配给对象{ {1}}“)因此:
c
Java无法取消装箱 Number c = Integer.valueOf( a.intValue() + b.intValue() );
,因为它在编译时不知道具体类型,因此无法猜测其原始对应物。
答案 2 :(得分:5)
你可以做这样的事情
class Example <T extends Number> {
public Number add(T a, T b){
return new Double(a.doubleValue() + b.doubleValue());
}
}
答案 3 :(得分:2)
是的,内森是对的。如果你想要这样的东西,你必须自己写一下
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没有类型类(Haskell)或隐式对象(Scala),这个任务将是一个完美的用例......
答案 4 :(得分:1)
这个问题也有类似的问题,答案是你不能那样做。
您可以检查a和b是否为Long / Double / Integer / etc的实例。并将add方法委托给:
public Integer add(Integer a, Integer b) {
return a+b; // this actually uses auto boxing and unboxing to int
}
并且您需要为扩展Number的每种类型创建一个,因此这不可行。换句话说,不要将泛型用于数值运算。作为超类的数量非常有限。
答案 5 :(得分:0)
考虑Example<Number>
,+
将如何处理? add
甚至Number
之内都没有Integer
或类似内容。
更糟糕的是考虑final class FunkyNumber extends Number { ... weird stuff, no add op ... }
。
答案 6 :(得分:0)
即使是java运行时库也存在这个问题,处理基元的大多数方法都必须复制相同的功能。
最快的选择是为一种类型编写代码,然后复制它并替换类型以生成其他类型的方法。一个简短的脚本应该足以做到这一点。