metodos - pila generica java
¿Cuál es este uso de genéricos en Java? X.<Y> método() (5)
Como han aclarado las otras respuestas, es para ayudar al compilador a descubrir qué tipo de genérico desea. Por lo general, es necesario cuando se utilizan los métodos de la utilidad Collections
que devuelven algo de un tipo genérico y no reciben parámetros.
Por ejemplo, considere los métodos Collections.empty*
, que devuelven una colección vacía. Si tiene un método que espera un Map<String, String>
:
public static void foo(Map<String, String> map) { }
No puedes pasarle directamente Collections.emptyMap()
. El compilador se quejará incluso si sabe que espera un Map<String, String>
:
// This won''t compile.
foo(Collections.emptyMap());
Tiene que declarar explícitamente el tipo que desea en la llamada , que creo que se ve bastante feo:
foo(Collections.<String, String>emptyMap());
O puede omitir esa declaración de tipo en la llamada de método si asigna el valor de retorno de emptyMap
a una variable antes de pasarla a la función, lo que creo que es bastante ridículo, porque parece innecesario y muestra que el compilador es realmente inconsistente: a veces hace inferencia de tipos en métodos genéricos sin parámetros, pero a veces no:
Map<String, String> map = Collections.emptyMap();
foo(map);
Puede que no parezca algo muy importante, pero cuando los tipos genéricos comienzan a ser más complejos (por ejemplo, Map<String, List<SomeOtherGenericType<Blah>>>
), un tipo de inicio desea que Java tenga una inferencia de tipo más inteligente (pero, como no lo hace, uno probablemente comenzará a escribir nuevas clases donde no sea necesario, solo para evitar todas esas cosas feas <>
= D).
He leído todo el libro de SCJP6 Sierra y Bates, obtuve un 88% del examen.
Pero aún así, nunca supe cómo funciona este tipo de código, ya que no se explica en el capítulo de genéricos:
Collections.<TimeUnit>reverseOrder()
¿Qué es este tipo de uso de genéricos? Lo descubrí en algún código pero nunca leí nada al respecto. Me parece que permite dar alguna ayuda a la inferencia de tipos. He intentado buscar sobre eso pero no es tan fácil de encontrar (¡y ni siquiera está en el libro / examen de SCJP!)
Entonces, ¿alguien me puede dar una explicación adecuada de cómo funciona, cuáles son todos los casos de uso, etc.?
Gracias
Gracias por las respuestas, pero esperaba más detalles :) así que si alguien quiere agregar alguna información adicional:
¿Qué pasa con los casos más complejos como
- Usando un tipo declarado en clase, ¿puedo hacer algo como
Collections.<T>reverseOrder()
por ejemplo? - Usando se
extends
,super
? - Utilizando
?
- Dando al compilador solo una ayuda parcial (es decir,
O.manyTypesMethod<?,MyHelpTypeNotInfered,?,?,?,?,?>()
)
En este caso, es una forma de decirle al método reverseOrder qué tipo de ordenación se debe imponer al objeto, según el tipo que especifique. El comparador necesita obtener información específica sobre cómo ordenar las cosas.
Es una especificación de tipo explícita de un método genérico. Siempre puedes hacerlo, pero en la mayoría de los casos no es necesario. Sin embargo, en algunos casos es obligatorio si el compilador no puede inferir el tipo genérico por sí solo.
Vea un ejemplo hacia el final de la página del tutorial .
Actualización: solo el primero de tus ejemplos es válido. El argumento de tipo explícito debe ser, bueno, explícito, por lo que no se permiten comodines, extends
ni super
. Además, o bien especificas cada argumento de tipo explícitamente o ninguno de ellos; es decir, el número de argumentos de tipo explícito debe coincidir con el número de parámetros de tipo del método llamado. Se permite un parámetro de tipo como T
si está bien definido en el alcance actual, por ejemplo, como un parámetro de tipo de la clase envolvente.
Solo una pequeña adición a las otras respuestas.
Al obtener el error de compilación correspondiente:
Mientras que el enfoque de casting "tradicional"
(Comparator<TimeUnit>) Collections.reverseOrder()
Se ve similar al enfoque genérico.
Collections.<TimeUnit>reverseOrder()
Por supuesto, el enfoque de casting no es seguro para el tipo (posible excepción de tiempo de ejecución), mientras que el enfoque genérico crearía un error de compilación, si hay un problema. Por lo tanto, se prefiere el enfoque genérico, por supuesto.
Usted es 100% correcto, es para ayudar con la inferencia de tipos. La mayoría de las veces no es necesario hacer esto en Java, ya que puede inferir el tipo (incluso desde el lado izquierdo de una tarea, lo cual es bastante bueno). Esta sintaxis se trata en el tutorial de genéricos en el sitio web de Java.