Genéricos em Java

O Genéricos Java a programação é introduzida no J2SE 5 para lidar com objetos com segurança de tipo. Torna o código estável detectando bugs em tempo de compilação.

Antes dos genéricos, podemos armazenar qualquer tipo de objeto na coleção, ou seja, não genérico. Agora, os genéricos forçam o programador Java a armazenar um tipo específico de objetos.

Vantagem dos genéricos Java

Existem principalmente 3 vantagens dos genéricos. Eles são os seguintes:

1) Segurança de tipo: Podemos conter apenas um único tipo de objetos em genéricos. Não permite armazenar outros objetos.

Sem Genéricos, podemos armazenar qualquer tipo de objeto.

 List list = new ArrayList(); list.add(10); list.add('10'); With Generics, it is required to specify the type of object we need to store. List list = new ArrayList(); list.add(10); list.add('10');// compile-time error  

2) A conversão de tipo não é necessária: Não há necessidade de tipificar o objeto.

Antes de Generics, precisamos digitar cast.

 List list = new ArrayList(); list.add('hello'); String s = (String) list.get(0);//typecasting After Generics, we don't need to typecast the object. List list = new ArrayList(); list.add('hello'); String s = list.get(0);  

3) Verificação em tempo de compilação: Ele é verificado em tempo de compilação para que o problema não ocorra em tempo de execução. A boa estratégia de programação diz que é muito melhor lidar com o problema em tempo de compilação do que em tempo de execução.

 List list = new ArrayList(); list.add('hello'); list.add(32);//Compile Time Error  

Sintaxe usar coleção genérica

 ClassOrInterface  

Exemplo usar genéricos em java

 ArrayList  

Exemplo completo de genéricos em Java

Aqui estamos usando a classe ArrayList, mas você pode usar qualquer classe de coleção, como ArrayList, LinkedList, HashSet, TreeSet, HashMap, Comparator etc.

 import java.util.*; class TestGenerics1{ public static void main(String args[]){ ArrayList list=new ArrayList(); list.add('rahul'); list.add('jai'); //list.add(32);//compile time error String s=list.get(1);//type casting is not required System.out.println('element is: '+s); Iterator itr=list.iterator(); while(itr.hasNext()){ System.out.println(itr.next()); } } }  

 import java.util.*; class TestGenerics1{ public static void main(String args[]){ ArrayList list=new ArrayList(); list.add('rahul'); list.add('jai'); //list.add(32);//compile time error String s=list.get(1);//type casting is not required System.out.println('element is: '+s); Iterator itr=list.iterator(); while(itr.hasNext()){ System.out.println(itr.next()); } } }  
Teste agora

Saída:

 element is: jai rahul jai  

Exemplo de genéricos Java usando mapa

Agora vamos usar elementos de mapa usando genéricos. Aqui, precisamos passar chave e valor. Vamos entender isso com um exemplo simples:

 import java.util.*; class TestGenerics2{ public static void main(String args[]){ Map map=new HashMap(); map.put(1,&apos;vijay&apos;); map.put(4,&apos;umesh&apos;); map.put(2,&apos;ankit&apos;); //Now use Map.Entry for Set and Iterator Set<map.entry> set=map.entrySet(); Iterator<map.entry> itr=set.iterator(); while(itr.hasNext()){ Map.Entry e=itr.next();//no need to typecast System.out.println(e.getKey()+&apos; &apos;+e.getValue()); } }} </map.entry></map.entry> 
Teste agora

Saída

 1 vijay 2 ankit 4 umesh  

Classe genérica

Uma classe que pode se referir a qualquer tipo é conhecida como classe genérica. Aqui, estamos usando o parâmetro de tipo T para criar a classe genérica de tipo específico.

Vamos ver um exemplo simples para criar e usar a classe genérica.

Criando uma classe genérica:

 class MyGen{ T obj; void add(T obj){this.obj=obj;} T get(){return obj;} }  

O tipo T indica que pode se referir a qualquer tipo (como String, Integer e Employee). O tipo especificado para a classe será usado para armazenar e recuperar os dados.

Usando classe genérica:

Vamos ver o código para usar a classe genérica.

 class TestGenerics3{ public static void main(String args[]){ MyGen m=new MyGen(); m.add(2); //m.add(&apos;vivek&apos;);//Compile time error System.out.println(m.get()); }}  
Teste agora

Saída

 2  

Parâmetros de tipo

As convenções de nomenclatura dos parâmetros de tipo são importantes para aprender completamente os genéricos. Os parâmetros de tipo comuns são os seguintes:

  1. T - Tipo
  2. E - Elemento
  3. K - Chave
  4. N - Número
  5. V - Valor

Método Genérico

Assim como a classe genérica, podemos criar um método genérico que pode aceitar qualquer tipo de argumento. Aqui, o escopo dos argumentos é limitado ao método onde é declarado. Ele permite métodos estáticos e não estáticos.

Vamos ver um exemplo simples de método genérico java para imprimir elementos de array. Estamos usando aqui E para denotar o elemento.

 public class TestGenerics4{ public static void printArray(E[] elements) { for ( E element : elements){ System.out.println(element ); } System.out.println(); } public static void main( String args[] ) { Integer[] intArray = { 10, 20, 30, 40, 50 }; Character[] charArray = { &apos;J&apos;, &apos;A&apos;, &apos;V&apos;, &apos;A&apos;, &apos;T&apos;,&apos;P&apos;,&apos;O&apos;,&apos;I&apos;,&apos;N&apos;,&apos;T&apos; }; System.out.println( &apos;Printing Integer Array&apos; ); printArray( intArray ); System.out.println( &apos;Printing Character Array&apos; ); printArray( charArray ); } }  
Teste agora

Saída

 Printing Integer Array 10 20 30 40 50 Printing Character Array J A V A T P O I N T  

Curinga em Java Genéricos

O ? (ponto de interrogação) representa o elemento curinga. Significa qualquer tipo. Se escrevermos , significa qualquer classe filha de Number, por exemplo, Integer, Float e double. Agora podemos chamar o método da classe Number através de qualquer objeto da classe filho.

Podemos usar um curinga como tipo de parâmetro, campo, tipo de retorno ou variável local. No entanto, não é permitido usar um curinga como argumento de tipo para uma invocação de método genérico, criação de uma instância de classe genérica ou um supertipo .

Vamos entender pelo exemplo abaixo:

 import java.util.*; abstract class Shape{ abstract void draw(); } class Rectangle extends Shape{ void draw(){System.out.println(&apos;drawing rectangle&apos;);} } class Circle extends Shape{ void draw(){System.out.println(&apos;drawing circle&apos;);} } class GenericTest{ //creating a method that accepts only child class of Shape public static void drawShapes(List lists){ for(Shape s:lists){ s.draw();//calling method of Shape class by child class instance } } public static void main(String args[]){ List list1=new ArrayList(); list1.add(new Rectangle()); List list2=new ArrayList(); list2.add(new Circle()); list2.add(new Circle()); drawShapes(list1); drawShapes(list2); }}  

Saída

 drawing rectangle drawing circle drawing circle  

Curingas com limite superior

O objetivo dos curingas com limite superior é diminuir as restrições em uma variável. Ele restringe o tipo desconhecido a um tipo específico ou um subtipo desse tipo. É usado declarando o caractere curinga ('?') seguido pela palavra-chave extends (no caso de classe) ou implements (no caso de interface), seguida por seu limite superior.

Sintaxe

 List  

Aqui,

? é um caractere curinga.

estende , é uma palavra-chave.

Número , é uma classe presente no pacote java.lang

Suponha que queremos escrever o método para a lista de Number e seus subtipos (como Integer, Double). Usando Lista é adequado para uma lista do tipo Number ou qualquer uma de suas subclasses, enquanto Lista funciona apenas com a lista do tipo Number. Então, Lista é menos restritivo do que Lista .

Exemplo de curinga de limite superior

Neste exemplo, estamos usando curingas de limite superior para escrever o método para Lista e Lista.

 import java.util.ArrayList; public class UpperBoundWildcard { private static Double add(ArrayList num) { double sum=0.0; for(Number n:num) { sum = sum+n.doubleValue(); } return sum; } public static void main(String[] args) { ArrayList l1=new ArrayList(); l1.add(10); l1.add(20); System.out.println(&apos;displaying the sum= &apos;+add(l1)); ArrayList l2=new ArrayList(); l2.add(30.0); l2.add(40.0); System.out.println(&apos;displaying the sum= &apos;+add(l2)); } }  
Teste agora

Saída

 displaying the sum= 30.0 displaying the sum= 70.0  

Curingas ilimitados

O tipo curinga ilimitado representa a lista de um tipo desconhecido, como List. Esta abordagem pode ser útil nos seguintes cenários: -

  • Quando o método fornecido é implementado usando a funcionalidade fornecida na classe Object.
  • Quando a classe genérica contém métodos que não dependem do parâmetro de tipo.

Exemplo de curingas ilimitados

 import java.util.Arrays; import java.util.List; public class UnboundedWildcard { public static void display(List list) { for(Object o:list) { System.out.println(o); } } public static void main(String[] args) { List l1=Arrays.asList(1,2,3); System.out.println(&apos;displaying the Integer values&apos;); display(l1); List l2=Arrays.asList(&apos;One&apos;,&apos;Two&apos;,&apos;Three&apos;); System.out.println(&apos;displaying the String values&apos;); display(l2); } }  
Teste agora

Saída

 displaying the Integer values 1 2 3 displaying the String values One Two Three  

Curingas com limite inferior

O objetivo dos curingas com limite inferior é restringir o tipo desconhecido a um tipo específico ou um supertipo desse tipo. É usado declarando o caractere curinga ('?') seguido pela palavra-chave super, seguida por seu limite inferior.

Sintaxe

 List  

Aqui,

? é um caractere curinga.

super , é uma palavra-chave.

Inteiro , é uma classe wrapper.

Suponha que queremos escrever o método para a lista de Inteiros e seu supertipo (como Número, Objeto). Usando Lista é adequado para uma lista do tipo Integer ou qualquer uma de suas superclasses, enquanto Lista funciona apenas com a lista do tipo Integer. Então, Lista é menos restritivo do que Lista .

Exemplo de curinga de limite inferior

Neste exemplo, estamos usando curingas de limite inferior para escrever o método para Lista e Lista.

 import java.util.Arrays; import java.util.List; public class LowerBoundWildcard { public static void addNumbers(List list) { for(Object n:list) { System.out.println(n); } } public static void main(String[] args) { List l1=Arrays.asList(1,2,3); System.out.println(&apos;displaying the Integer values&apos;); addNumbers(l1); List l2=Arrays.asList(1.0,2.0,3.0); System.out.println(&apos;displaying the Number values&apos;); addNumbers(l2); } }  
Teste agora

Saída

 displaying the Integer values 1 2 3 displaying the Number values 1.0 2.0 3.0