Genéricos en Java

Genéricos significa tipos parametrizados . La idea es permitir que el tipo (entero, string, etc., y tipos definidos por el usuario) sea un parámetro para métodos, clases e interfaces. Utilizando Generics, es posible crear clases que trabajen con diferentes tipos de datos. Una entidad como clase, interfaz o método que opera en un tipo parametrizado es una entidad genérica.

¿Por qué genéricos?

El Objeto es la superclase de todas las demás clases, y la referencia de Objeto puede referirse a cualquier objeto. Estas características carecen de seguridad de tipo. Los genéricos agregan ese tipo de característica de seguridad. Discutiremos ese tipo de característica de seguridad en ejemplos posteriores.

Los genéricos en Java son similares a las plantillas en C++. Por ejemplo, clases como HashSet, ArrayList, HashMap, etc., usan genéricos muy bien. Existen algunas diferencias fundamentales entre los dos enfoques de los tipos genéricos. 

Tipos de genéricos de Java

Método genérico: el método genérico de Java toma un parámetro y devuelve algún valor después de realizar una tarea. Es exactamente como una función normal, sin embargo, un método genérico tiene parámetros de tipo que son citados por el tipo real. Esto permite utilizar el método genérico de una manera más general. El compilador se ocupa del tipo de seguridad que permite a los programadores codificar fácilmente, ya que no tienen que realizar largas conversiones de tipos individuales.

Clases genéricas: una clase genérica se implementa exactamente como una clase no genérica. La única diferencia es que contiene una sección de parámetros de tipo. Puede haber más de un tipo de parámetro, separados por una coma. Las clases que aceptan uno o más parámetros se conocen como clases parametrizadas o tipos parametrizados.

Clase genérica 

Al igual que C++, usamos <> para especificar tipos de parámetros en la creación de clases genéricas. Para crear objetos de una clase genérica, usamos la siguiente sintaxis. 

// To create an instance of generic class 
BaseType <Type> obj = new BaseType <Type>()

Nota: En el tipo de parámetro no podemos usar primitivas como ‘int’, ‘char’ o ‘double’.

Java

// Java program to show working of user defined
// Generic classes
  
// We use < > to specify Parameter type
class Test<T> {
    // An object of type T is declared
    T obj;
    Test(T obj) { this.obj = obj; } // constructor
    public T getObject() { return this.obj; }
}
  
// Driver class to test above
class Main {
    public static void main(String[] args)
    {
        // instance of Integer type
        Test<Integer> iObj = new Test<Integer>(15);
        System.out.println(iObj.getObject());
  
        // instance of String type
        Test<String> sObj
            = new Test<String>("GeeksForGeeks");
        System.out.println(sObj.getObject());
    }
}
Producción

15
GeeksForGeeks

También podemos pasar múltiples parámetros de tipo en clases genéricas. 

Java

// Java program to show multiple
// type parameters in Java Generics
  
// We use < > to specify Parameter type
class Test<T, U>
{
    T obj1;  // An object of type T
    U obj2;  // An object of type U
  
    // constructor
    Test(T obj1, U obj2)
    {
        this.obj1 = obj1;
        this.obj2 = obj2;
    }
  
    // To print objects of T and U
    public void print()
    {
        System.out.println(obj1);
        System.out.println(obj2);
    }
}
  
// Driver class to test above
class Main
{
    public static void main (String[] args)
    {
        Test <String, Integer> obj =
            new Test<String, Integer>("GfG", 15);
  
        obj.print();
    }
}
Producción

GfG
15

Funciones genéricas: 

También podemos escribir funciones genéricas que se pueden llamar con diferentes tipos de argumentos según el tipo de argumentos pasados ​​al método genérico. El compilador maneja cada método.

Java

// Java program to show working of user defined
// Generic functions
  
class Test {
    // A Generic method example
    static <T> void genericDisplay(T element)
    {
        System.out.println(element.getClass().getName()
                           + " = " + element);
    }
  
    // Driver method
    public static void main(String[] args)
    {
        // Calling generic method with Integer argument
        genericDisplay(11);
  
        // Calling generic method with String argument
        genericDisplay("GeeksForGeeks");
  
        // Calling generic method with double argument
        genericDisplay(1.0);
    }
}
Producción

java.lang.Integer = 11
java.lang.String = GeeksForGeeks
java.lang.Double = 1.0

Los genéricos solo funcionan con tipos de referencia: 

Cuando declaramos una instancia de un tipo genérico, el argumento de tipo pasado al parámetro de tipo debe ser un tipo de referencia. No podemos usar tipos de datos primitivos como int , char.

Test<int> obj = new Test<int>(20); 

La línea anterior da como resultado un error de tiempo de compilación que se puede resolver usando contenedores de tipo para encapsular un tipo primitivo. 

Pero las arrays de tipo primitivo se pueden pasar al parámetro de tipo porque las arrays son tipos de referencia.

ArrayList<int[]> a = new ArrayList<>();

Los tipos genéricos difieren según sus argumentos de tipo: 

Considere el siguiente código Java.

Java

// Java program to show working
// of user-defined Generic classes
  
// We use < > to specify Parameter type
class Test<T> {
    // An object of type T is declared
    T obj;
    Test(T obj) { this.obj = obj; } // constructor
    public T getObject() { return this.obj; }
}
  
// Driver class to test above
class Main {
    public static void main(String[] args)
    {
        // instance of Integer type
        Test<Integer> iObj = new Test<Integer>(15);
        System.out.println(iObj.getObject());
  
        // instance of String type
        Test<String> sObj
            = new Test<String>("GeeksForGeeks");
        System.out.println(sObj.getObject());
        iObj = sObj; // This results an error
    }
}

Producción: 

error:
 incompatible types:
 Test cannot be converted to Test 

Aunque iObj y sObj son de tipo Test, son las referencias a diferentes tipos porque sus parámetros de tipo difieren. Los genéricos agregan seguridad de tipo a través de esto y evitan errores.

Parámetros de tipo en los genéricos de Java

Las convenciones de nomenclatura de parámetros de tipo son importantes para aprender a fondo los genéricos. Los parámetros de tipo comunes son los siguientes:

  • T-Tipo
  • E – Elemento
  • K – Clave
  • N – Número
  • V-Valor

Ventajas de los genéricos: 

Los programas que usan Generics tienen muchos beneficios sobre el código no genérico. 

1. Reutilización de código: podemos escribir un método/clase/interfaz una vez y usarlo para cualquier tipo que queramos.

2. Seguridad de tipos: los genéricos cometen errores que aparecen en tiempo de compilación que en tiempo de ejecución (siempre es mejor conocer los problemas en su código en tiempo de compilación en lugar de hacer que su código falle en tiempo de ejecución). Suponga que desea crear una ArrayList que almacene el nombre de los estudiantes, y si por error el programador agrega un objeto entero en lugar de una string, el compilador lo permite. Pero, cuando recuperamos estos datos de ArrayList, causa problemas en tiempo de ejecución.

Java

// Java program to demonstrate that NOT using
// generics can cause run time exceptions
  
import java.util.*;
  
class Test
{
    public static void main(String[] args)
    {
        // Creatinga an ArrayList without any type specified
        ArrayList al = new ArrayList();
  
        al.add("Sachin");
        al.add("Rahul");
        al.add(10); // Compiler allows this
  
        String s1 = (String)al.get(0);
        String s2 = (String)al.get(1);
  
        // Causes Runtime Exception
        String s3 = (String)al.get(2);
    }
}

Producción :

Exception in thread "main" java.lang.ClassCastException: 
   java.lang.Integer cannot be cast to java.lang.String
    at Test.main(Test.java:19)

¿Cómo resuelven los genéricos este problema? 

Al definir ArrayList, podemos especificar que esta lista solo puede tomar objetos String.

Java

// Using Java Generics converts run time exceptions into 
// compile time exception.
import java.util.*;
  
class Test
{
    public static void main(String[] args)
    {
        // Creating a an ArrayList with String specified
        ArrayList <String> al = new ArrayList<String> ();
  
        al.add("Sachin");
        al.add("Rahul");
  
        // Now Compiler doesn't allow this
        al.add(10); 
  
        String s1 = (String)al.get(0);
        String s2 = (String)al.get(1);
        String s3 = (String)al.get(2);
    }
}

Producción: 

15: error: no suitable method found for add(int)
        al.add(10); 
          ^

3. No se necesita la conversión de tipo individual: si no usamos genéricos, entonces, en el ejemplo anterior, cada vez que recuperamos datos de ArrayList, tenemos que encasillarlos. El encasillamiento en cada operación de recuperación es un gran dolor de cabeza. Si ya sabemos que nuestra lista solo contiene datos de strings, no necesitamos encasillarlos cada vez.

Java

// We don't need to typecast individual members of ArrayList
  
import java.util.*;
  
class Test {
    public static void main(String[] args)
    {
        // Creating a an ArrayList with String specified
        ArrayList<String> al = new ArrayList<String>();
  
        al.add("Sachin");
        al.add("Rahul");
  
        // Typecasting is not needed
        String s1 = al.get(0);
        String s2 = al.get(1);
    }
}

4. Los genéricos promueven la reutilización del código: con la ayuda de los genéricos en Java, podemos escribir código que funcionará con diferentes tipos de datos. Por ejemplo,

public <T> void genericsMethod (T data) {...}

Aquí, hemos creado un método genérico. Este mismo método se puede utilizar para realizar operaciones en datos enteros, datos de string, etc.

5. Implementación de algoritmos genéricos: mediante el uso de genéricos, podemos implementar algoritmos que funcionan en diferentes tipos de objetos y, al mismo tiempo, también son seguros para los tipos.

Este artículo es una contribución de Dharmesh Singh . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo y enviarlo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks. Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *