2011-12-29 52 views
9

Me gustaría agregar genéricamente números en java. Me encuentro con dificultades porque la clase Numbers en realidad no admite lo que quiero hacer. Lo que he intentado hasta ahora es esto:Java Generics y sumar números juntos

public class Summer<E extends Number> { 


    public E sumValue(List<E> objectsToSum) { 
     E total = (E) new Object(); 
     for (E number : objectsToSum){ 
      total += number; 
     } 
     return null; 

    } 

Obviamente, esto no funcionará. ¿Cómo puedo corregir este código para que me den una lista de <int> o <long> o lo que sea y devolver la suma?

+1

¿Qué sucede si tiene una lista que contiene diferentes subclases numéricas? P.ej. 'Arrays.asList (5L, 1e100, 42)'? – kan

+0

Duplicado de http://stackoverflow.com/questions/285754/java-using-generics-to-implement-a-class-that-operates-on-different-kinds-of-nu –

+0

@kan - Yo esperaría que Obtendría un error ya que no son todos de tipo E, ¿verdad? –

Respuesta

11

Con el fin de calcular una suma de forma genérica, es necesario proporcionar dos acciones:

  • Una manera de suma cero artículos
  • Una manera de resumir dos artículos

En Java, se hazlo a través de una interfaz. Aquí hay un ejemplo completo:

import java.util.*; 

interface adder<T extends Number> { 
    T zero(); // Adding zero items 
    T add(T lhs, T rhs); // Adding two items 
} 

class CalcSum<T extends Number> { 
    // This is your method; it takes an adder now 
    public T sumValue(List<T> list, adder<T> adder) { 
     T total = adder.zero(); 
     for (T n : list){ 
      total = adder.add(total, n); 
     } 
     return total; 
    } 
} 

public class sum { 
    public static void main(String[] args) { 
     List<Integer> list = new ArrayList<Integer>(); 
     list.add(1); 
     list.add(2); 
     list.add(4); 
     list.add(8); 
     CalcSum<Integer> calc = new CalcSum<Integer>(); 
     // This is how you supply an implementation for integers 
     // through an anonymous implementation of an interface: 
     Integer total = calc.sumValue(list, new adder<Integer>() { 
      public Integer add(Integer a, Integer b) { 
       return a+b; 
      } 
      public Integer zero() { 
       return 0; 
      } 
     }); 
     System.out.println(total); 
    } 
} 
+0

+1 porque es más específico que la respuesta aceptada. Sin embargo, realmente no resuelve el problema en cuestión, ya que ahora el problema está en escribir un sumador "genérico". – Stefan

+0

@Stefan It * es * un sumador genérico como se obtiene, al menos en Java con sus reglas de borrado de tipo. No hay otra forma de suministrar la primitiva de suma en Java que no sea a través de una interfaz de algún tipo. – dasblinkenlight

+0

Aún debe proporcionar una implementación de un sumador para cada tipo de número, tal como lo haría para su verano. Me atrevería a decir que este problema ni siquiera es resuelto en una forma genérica (como en una implementación, no como en Java generics), ya que podría haber nuevos tipos de números, etc. – Stefan

1

El número no admite ninguna operación, por lo que debe convertir los valores a los tipos necesarios. p.ej. Si Number es un BigDecimal, no hay un operador +=.

3

Como la clase de número no expone la interfaz para realizar cálculos, la única manera de resolver este problema es crear clases que encapsulan las operaciones requeridas para cada tipo numérico compatible. Que en tu clase necesitarás usar un tipo específico.

0

Debe verificar el tipo de tiempo de ejecución (por ejemplo, usando instanceof) y convertirlo al tipo conocido y hacer la operación de adición apropiada. No estoy seguro de cuál será el tipo de resultado, teniendo en cuenta que la lista podría contener muchos tipos de números diferentes.

+0

Y posiblemente incluso desconocido (al momento de escribir) Tipos de números. – Stefan

1

El número tiene intValue(), floatValue(), doubleValue(), longValue y shortValue(). Elige uno y úsalo. Por ejemplo,

double total; 
total += number.doubleValue(); 

return total; 

Además, los genéricos de java no son de ninguna manera equivalentes a las plantillas de C++. No puede asignar nuevas instancias de un tipo genérico java. Esto nunca puede trabajar:

E hoot = (E) new Object(); 

Por último, long, short, int, double, y float no son los tipos de clases; ellos son tipos primitivos. Como tales, no están disponibles para su uso con los genéricos de Java.

+0

¿Qué pasa con BigDecimal (también es un número)? Ninguna función devolverá el valor "correcto" en muchos casos. – Stefan