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,'vijay'); map.put(4,'umesh'); map.put(2,'ankit'); //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()+' '+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('vivek');//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:
- T - Tipo
- E - Elemento
- K - Chave
- N - Número
- 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 = { 'J', 'A', 'V', 'A', 'T','P','O','I','N','T' }; System.out.println( 'Printing Integer Array' ); printArray( intArray ); System.out.println( 'Printing Character Array' ); 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('drawing rectangle');} } class Circle extends Shape{ void draw(){System.out.println('drawing circle');} } 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('displaying the sum= '+add(l1)); ArrayList l2=new ArrayList(); l2.add(30.0); l2.add(40.0); System.out.println('displaying the sum= '+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('displaying the Integer values'); display(l1); List l2=Arrays.asList('One','Two','Three'); System.out.println('displaying the String values'); 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('displaying the Integer values'); addNumbers(l1); List l2=Arrays.asList(1.0,2.0,3.0); System.out.println('displaying the Number values'); addNumbers(l2); } } Teste agora Saída
displaying the Integer values 1 2 3 displaying the Number values 1.0 2.0 3.0