2010-10-06 40 views
29

我想创建一个Java中的泛型类,它将对数字执行操作。在下面的例子,此外,如下:我可以在Number基类上进行算术运算吗?

public class Example <T extends Number> { 

    public T add(T a, T b){ 
     return a + b; 
    } 

} 

请原谅我的幼稚,因为我是比较新的Java的泛型。此代码无法编译与错误:

The operator + is undefined for the argument type(s) T, T

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

+1

如果你想要做这种事情,可能希望查看Scala或Groovy。他们有运算符重载和域特定的语言功能:) – 2010-10-09 18:54:10

回答

26

号码没有与其关联的+运算符,也不可以,因为没有运算符重载。

这将是很好,虽然。

基本上,你要求java自动载入Number的一个加号,后者恰好包含Integer,Float和Double,可以自动加载并应用一个加号运算符,但是,可能有任何数量的其他未知的Number后裔不能被自动装箱,并且直到运行时才能知道。 (该死的擦除)

+3

“可能有任何数量的其他未知的数字后代不能自动复制,”如BigInteger和BigDecimal都扩展了Number。 – Powerlord 2010-10-06 14:53:37

+0

我想,如果Number有.add(a,b).sub(a,b).mult(a,b)...我们可以简单地使用它们,所以使用泛型,可能是由NumberHero实现的接口IntegerHero可以扩展一个类似Integer的类(因为我们不能扩展最终类),可以做到这一点吗? – 2015-12-22 19:05:27

0

考虑Example<Number>+将如何工作?没有addNumber或类似的Integer

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

1

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

您可以检查a和b是长/双/整数/等的实例。并委派附加到类似的方法:

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

而且你需要创建一个为每个扩展号码类型,所以这不是真的可行。换句话说,不要使用泛型进行数字操作。作为超类的数量相当有限。

17

你的问题并没有真正涉及到泛型,而是涉及到操作符,基元对象和自动装箱。

想想这个:

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,并且只能在编译时使用一些具体的类型:int-Integer。

在幕后,Java编译器被改写最后一条语句(“我一定要拆箱ab与原始数据类型应用和运营商,以及框中的结果将它指定对象c”)这样的:

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

Java无法取消装箱Number,因为它不知道在编译时的具体类型,因此它不能猜测它的原始对应物。

2

是的,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没有类型类(哈斯克尔)或隐式对象(斯卡拉),这个任务将是一个完美的使用情况...

3

你可以做这样的事情

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

即使Java运行时库有这个问题,大多数的处理原语的方法有重复相同的功能。

最快的选择是为一种类型编写代码,然后复制它并替换类型以生成其他类型的方法。一个简短的脚本应该足以做到这一点。