Tutorial de ejemplo de Java Generics – Método genérico, clase, interfaz
Java Genrics es una de las características más importantes introducidas en Java 5.
Si ha estado trabajando en las colecciones de Java y con la versión 5 o superior, estoy seguro de que la ha utilizado.
Genéricos en Java con clases de colección es muy fácil pero proporciona muchas más características que simplemente crear el tipo de colección.
Intentaremos aprender las características de los genéricos en este artículo. Comprender los genéricos puede resultar confuso a veces si usamos palabras de jerga, por lo que trataría de mantenerlo simple y fácil de entender.
Genéricos en Java
Se agregaron genéricos en Java 5 para proporcionar verificación de tipo en tiempo de compilación y eliminar el riesgo de ClassCastException
que era común durante el trabajo con clases de cobranza. Todo el marco de la colección se reescribió para usar genéricos para la seguridad de tipos. Veamos cómo los genéricos nos ayudan a usar clases de colección de forma segura.
El código anterior se compila bien pero arroja ClassCastException en tiempo de ejecución porque estamos tratando de convertir Object en la lista a String mientras que uno de los elementos es de tipo Integer. Después de Java 5, usamos clases de colección como se muestra a continuación.
Observe que en el momento de la creación de la lista, hemos especificado que el tipo de elementos en la lista será String. Entonces, si intentamos agregar cualquier otro tipo de objeto en la lista, el programa arrojará un error en tiempo de compilación. Observe también que en el bucle for, no necesitamos encasillar el elemento en la lista, por lo tanto, eliminamos la ClassCastException en tiempo de ejecución.
Clase genérica de Java
Podemos definir nuestras propias clases con tipo genérico. Un tipo genérico es una clase o interfaz que se parametriza sobre tipos. Usamos corchetes angulares (< >) para especificar el parámetro de tipo.
Para entender el beneficio, digamos tenemos una clase simple como:
Note que mientras usamos esta clase, tenemos que usar conversión de tipos y puede producir ClassCastException en tiempo de ejecución. Ahora usaremos la clase genérica de Java para reescribir la misma clase que se muestra a continuación.
Observe el uso de la clase GenericsType en el método principal. No es necesario que realice una conversión de tipos y podemos eliminar ClassCastException en tiempo de ejecución. Si no proporcionamos el tipo en el momento de la creación, el compilador producirá una advertencia de que «GenericsType es un tipo sin formato.
Referencias al tipo genérico GenericsType < T > debería ser parametrizado ”. Cuando no proporcionamos el tipo, el tipo se convierte en Object
y, por lo tanto, permite tanto String y objetos Integer. Pero siempre debemos tratar de evitar esto porque tendremos que usar la conversión de tipos mientras trabajamos en tipos sin procesar que pueden producir errores en tiempo de ejecución.
@SuppressWarnings("rawtypes")
anotación para suprimir la advertencia del compilador, consulte el tutorial de anotaciones de Java. También observe que es compatible con el autoboxing de Java.
Interfaz genérica de Java
La interfaz comparable es un gran ejemplo de genéricos en interfaces y está escrito como:
De manera similar, podemos crear interfaces genéricas en java. También podemos tener varios parámetros de tipo como en la interfaz del mapa. ganancia también podemos proporcionar un valor parametrizado a un tipo parametrizado, por ejemplo new HashMap<String, List<String>>();
es válido.
Tipo genérico de Java
Denominación de tipo genérico de Java la convención nos ayuda a comprender el código fácilmente y tener una convención de nomenclatura es una de las mejores prácticas del lenguaje de programación Java. Así que los genéricos también vienen con sus propias convenciones de nomenclatura. Por lo general, los nombres de los parámetros de tipo son letras mayúsculas simples para que sean fácilmente distinguibles de las variables de Java. Los nombres de parámetros de tipo más utilizados son:
- E – Elemento (utilizado ampliamente por Java Collections Framework, por ejemplo, ArrayList, Set, etc.)
- K – Key ( Usado en el mapa)
- N – Número
- T – Tipo
- V – Valor (usado en el mapa)
- S, U, V etc. – 2do, 3er, 4to tipos
Método genérico de Java
A veces no queremos que se parametrice toda la clase, en ese caso, podemos crear el método genérico de Java. Dado que el constructor es un tipo especial de método, también podemos usar tipos genéricos en constructores.
Aquí hay una clase que muestra un ejemplo de un método genérico de Java.
Observe el método isEqual firma que muestra la sintaxis para utilizar tipos genéricos en métodos. Además, observe cómo utilizar estos métodos en nuestro programa java. Podemos especificar el tipo al llamar a estos métodos o podemos invocarlos como un método normal. El compilador de Java es lo suficientemente inteligente como para determinar el tipo de variable que se utilizará, esta función se llama inferencia de tipo.
Parámetros de tipo acotado de Java Generics
Supongamos que queremos restringir el tipo de objetos que se pueden usar en el tipo parametrizado, por ejemplo en un método que compara dos objetos y queremos asegúrese de que los objetos aceptados sean Comparables. Para declarar un parámetro de tipo acotado, enumere el nombre del parámetro de tipo, seguido de la palabra clave extiende, seguido de su límite superior, similar al método de abajo.
El La invocación de estos métodos es similar al método ilimitado, excepto que si intentamos usar cualquier clase que no sea Comparable, arrojará un error en tiempo de compilación.
Los parámetros de tipo limitado se pueden usar con métodos así como clases e interfaces.
Java Generics también admite varios límites, es decir, < T extiende A & B & C >. En este caso, A puede ser una interfaz o una clase. Si A es de clase, B y C deberían ser una interfaz. No podemos tener más de una clase en varios límites.
Genéricos y herencia de Java
Sabemos que La herencia de Java nos permite asignar una variable A a otra variable B si A es una subclase de B. Así que podríamos pensar que cualquier tipo genérico de A puede asignarse al tipo genérico de B, pero no es el caso. Veamos esto con un programa simple.
No se nos permite asignar la variable MyClass < String > a MyClass < Objeto > variable porque no están relacionadas, de hecho MyClass < T > padre es Object.
Clases genéricas de Java y subtipificación
Podemos subtipificar una clase o interfaz genérica extendiéndola o implementándola. La relación entre los parámetros de tipo de una clase o interfaz y los parámetros de tipo de otra está determinada por las cláusulas extend e implementa.
La relación de subtipo se conserva siempre que no cambiemos el argumento de tipo, a continuación se muestra un ejemplo de varios parámetros de tipo.
Los subtipos de List < String > puede ser MyList < String, Object >, MyList < Cadena, entero > y así sucesivamente.
Comodines genéricos de Java
El signo de interrogación (?) Es el comodín en genéricos y representa un tipo desconocido. El comodín se puede utilizar como tipo de parámetro, campo o variable local y, a veces, como tipo de retorno. No podemos usar comodines mientras invocamos un método genérico o instanciamos una clase genérica. En las siguientes secciones, aprenderemos sobre comodines delimitados superiores, comodines delimitados inferiores y captura de comodines.
9.1) Comodines delimitados superiores de Java Generics
Los comodines delimitados superiores se utilizan para relajar el restricción sobre el tipo de variable en un método. Supongamos que queremos escribir un método que devolverá la suma de números en la lista, por lo que nuestra implementación será algo como esto.
Ahora el problema con La implementación anterior es que no funcionará con List of Integers o Doubles porque sabemos que List < Integer > y List < Los dobles > no están relacionados, aquí es cuando un comodín delimitado superior es útil. Usamos comodines genéricos con la palabra clave extendida y la clase o interfaz de límite superior que nos permitirá pasar argumentos de límite superior o sus tipos de subclases.
La implementación anterior se puede modificar como el programa siguiente.
Es similar a escribir nuestro código en términos de interfaz, en el método anterior podemos usar todos los métodos de la clase de límite superior Número. Tenga en cuenta que con la lista delimitada superior, no se nos permite agregar ningún objeto a la lista excepto nulo. Si intentamos agregar un elemento a la lista dentro del método de suma, el programa no se compilará.
9.2) Java Generics Unbounded Wildcard
A veces tenemos una situación en la que queremos que nuestro método genérico funcione con todos los tipos, en este caso, se puede utilizar un comodín ilimitado. ¿Es lo mismo que usar <? extiende el objeto >.
Podemos proporcionar List < String > o List < Integer > o cualquier otro tipo de argumento de lista de objetos para el método printData. Al igual que en la lista de límite superior, no podemos agregar nada a la lista.
9.3) Java Generics Comodín delimitado inferior
Supongamos que queremos agregar enteros a una lista de enteros en un método, podemos mantener el tipo de argumento como List < Integer > pero estará ligado a Integers, mientras que List < Number > y List < El objeto > también puede contener enteros, por lo que podemos usar un comodín de límite inferior para lograr esto. Usamos comodines genéricos (?) Con super palabra clave y clase de límite inferior para lograr esto.
Podemos pasar límite inferior o cualquier supertipo de límite inferior como argumento, en este caso, el compilador Java permite agregar un límite inferior tipos de objetos enlazados a la lista.
Subtipado usando genéricos comodín
Borrado de tipos genéricos de Java
Genéricos en Java se agregó para proporcionar verificación de tipo en tiempo de compilación y no tiene uso en tiempo de ejecución, por lo que el compilador de Java usa la función de borrado de tipo para eliminar todo el código de verificación de tipo genérico en el código de bytes e insertar conversión de tipo si es necesario. El borrado de tipo asegura que no se creen nuevas clases para tipos parametrizados; en consecuencia, los genéricos no incurren en gastos generales de ejecución.
Por ejemplo, si tenemos una clase genérica como la siguiente;
El compilador de Java reemplaza el parámetro de tipo limitado T con la primera interfaz vinculada, Comparable , como el siguiente código:
Preguntas frecuentes sobre genéricos
12.1) ¿Por qué usamos genéricos en Java?
Los genéricos proporcionan una sólida verificación de tipos en tiempo de compilación y reducen el riesgo de ClassCastException y conversión explícita de objetos.
12.2) ¿Qué es T en genéricos?
Usamos < T > para crear una clase, interfaz y método genéricos. La T se reemplaza con el tipo real cuando la usamos.
12.3) ¿Cómo funcionan los genéricos en Java?
El código genérico garantiza la seguridad de los tipos. El compilador usa el borrado de tipo para eliminar todos los parámetros de tipo en el tiempo de compilación para reducir la sobrecarga en tiempo de ejecución.
Genéricos en Java – Lecturas adicionales
Eso es todo para los genéricos en java, java Los genéricos son un tema realmente extenso y requiere mucho tiempo para comprenderlo y usarlo de manera efectiva. Esta publicación aquí es un intento de proporcionar detalles básicos de genéricos y cómo podemos usarla para extender nuestro programa con seguridad de tipos.