2011-12-20 24 views
5

Quiero escribir un método genérico en Java, como a continuación:Cómo escribir un método genérico en Java para apoyar la comparación y operaciones aritméticas

public <T extends Number & Comparable<T>> void test(T[] a){ 
    T b=a[0]; 
    if(a[0]>0){ 
     a[0]*=a[0]; 
     b+=a[1]; 
    } 
} 

Luego, más tarde, puedo suministrar, ya sea Integer[] o Double[] u otros Number subtipos al método. Pero el código que probé arriba me da errores.

Por favor, ayúdame. Gracias.

+0

¿Cuál es el problema que está tratando de resolver? Java no es compatible con este tipo de operación genérica. Si entendimos el caso de uso, tal vez podríamos sugerir opciones alternativas. Por ejemplo, creo que nunca es una buena idea utilizar matrices de clases de contenedor (como 'Integer []') en lugar de matrices de primitivas (como 'int []'). ¿Hay alguna razón por la que necesites 'Integer' o' Double' en lugar de 'int' o' double'? –

+0

@DanielPryden: Estoy tratando de resolver: escriba un método que acepte int [], float [], o double [] y dentro del cual necesite hacer una comparación y aritmética, luego devuelva el mismo tipo de matriz int [], o flotar [], o doble []. –

+0

Entonces lo mejor que puede hacer es factorizar sus cálculos reales en un método que opera en un 'double []' y devuelve un 'double []' (ya que 'double' es más ancho que tanto' int' como 'float') Aún necesitará tener dos métodos adicionales para soportar los argumentos 'int []' y 'float []'. –

Respuesta

3

No se puede hacer esto en Java con genéricos. Eso es un beneficio de C++, por ejemplo.

De alguna manera puede definir esto como "extraño", porque es posible utilizar operadores en los envoltorios primitivos de Java. Pero eso se debe a que no puede usar operadores en java.lang.Number, la superclase de las envolturas primitivas.

Algunos recursos:

+0

OK, ahora entiendo la razón. Pero, ¿cómo reutilizar el código si quiero que mi método funcione para Integer [], Double [], Float []? –

+1

Esa es la parte molesta de Java Generics: simplemente no puede. Lo único que puede intentar es usar siempre el doble y convertir los datos antes y después del uso hacia y desde el doble. –

5

todos los tipos (incluyendo la inferida tipos genéricos) excepto las primitivas son Objetos que no admiten operaciones aritméticas (las clases contenedoras usan boxing/unboxing para obtener el comportamiento conocido de pseudocódigo)

y tipo borrado hace que el código compilado use moldes para obtener el comportamiento correcto (es decir durante el tiempo de ejecución, la JVM no sabe qué tipo se pasó para conocer el comportamiento correcto de boxeo/desempaquetado)

la única solución (real) es proporcionar implementaciones para todas las primitivas que desee admitir

+0

gracias por la respuesta. ¿Hay alguna forma más corta y elegante de hacer este otro otro código de replicación? –

+0

@littleEinstein: si solo quiere hacer comparaciones, puede usar el método ['compareTo()' de 'Comparable '] (http://docs.oracle.com/javase/6/docs/api/java/ lang/Comparable.html # compareTo (T)). Pero no puede realizar operaciones aritméticas en instancias 'Number' en Java. –

+0

@DanielPryden: a la derecha. Pero hacer aritmética es imprescindible para mi método. ¿Tiene una buena solución en este caso sin escribir código repetitivo? –

1

tienes Comparable, por lo que si tiene una zero, a[0]>0 podría ser sustituido por a[0].compareTo(zero) > 0 (no, yo creo que es < 0, nunca puedo recordar). Pero ahora nos hemos quedado sin cosas útiles desde Double y similares.

Si Double y sus amigos no eran java.lang.Comparable, podríamos suministrar el nuestro java.util.Comparator. Es decir, tomamos la implementación de la comparación fuera del objeto de datos. También podemos hacer esa suma y multiplicación.

public interface Testor<T> { // Choose a better name... 
    boolean isStriclyPositive(T value); 
    T add(T lhs, T rhs); 
    T square(T value); 
} 

static final Testor<Integer> INTEGER_TESTOR = new Testor<>() { // Java SE 7 diamond. 
    public boolean isStriclyPositive(Integer value) { return value > 0; } 
    public Integer add(Integer lhs, Integer rhs) { return lhs + rhs; } 
    public Integer square(Integer value) { return value*value; } 
} 
// ... same for Double, etc.; can't use an enum :(... 

test(new Integer[] { 42, 1972, 86 }, INTEGER_TESTOR); 

public <T> void test(T[] a, Testor<T> testor) { 
    T b = a[0]; 
    if (testor.isStrictlyPositive(a[0])) { 
     a[0] = testor.square(a[0]); 
     b = testor.add(b, a[1]); 
    } 
} 

Nota para cosas como Short, sumando dos de ellos le dará una int.

(Usual descargo de responsabilidad de desbordamiento de pila:. No tanto como trató de compilar el código)

Cuestiones relacionadas