Genéricos (postagem 1 de 2)
Autor: Gustavo | Publicado: 2015-03-30T10:41:00-03:00


Genéricos



&nbsp; &nbsp; &nbsp;Nesta
postagem e na próxima, falarei sobre genéricos. Muito utilizada em ,conjuntos,
fazendo com que o programador defina já de início qual tipo de
elemento será armazenado na sua lista. Os genéricos são fáceis de
serem utilizados, basta colocar um sinal de menor que “&lt;” &nbsp;o elemento e depois o sinal de maior que “&gt;” .

&nbsp; &nbsp; &nbsp;Antes
de java 5 onde foi iniciado a parte de genéricos as declarações de uma lista eram da seguinte forma:



  ArrayList
lista
= new
ArrayList();



&nbsp; &nbsp; &nbsp;Ao
nos depararmos com este tipo de lista, não temos como saber que tipo
de elementos são armazenados (String, Integers, Log, Object...) Mas
agora seus problemas acabaram, ao se deparar com uma lista a partir
no java 5 possivelmente terá o seu código a seguinte síntase.



ArrayList&lt;String&gt;
lista
= new
ArrayList&lt;String&gt;();



&nbsp; &nbsp; &nbsp;A
declaralção de genéricos em uma lista é totalmente facultativo.
Não acontecerá nenhum erro com a falta desta declaração, contudo
você terá que aturar os&nbsp;warnings de compilação que&nbsp;ocorrerão ao compilar sua
aplicação. Sem contar que
você terá mais preocupações em seus códigos pois, pela não
de definição de
que tipo
a lista irá armazenar, ela
poderá aceitar tudo o que quiserem colocar.



Por
exemplo:

   ArrayList&lt;String&gt;
listaGen
= new
ArrayList&lt;String&gt;();

   ArrayList
lista
= new
ArrayList();

   listaGen.add("teste
1");//ok

   lista.add("teste
1");//ok

   listaGen.add(2);//erro
de
compilacao

   lista.add(2);//ok

   listaGen.add(new
Surfista());//erro
de
compilacao

   lista.add(new
Surfista());//ok



&nbsp; &nbsp; &nbsp;Podemos
ver que a lista que não possui a definição de genéricos &lt;String&gt;
listaGen fornecendo uma segurança muito maior a partir do
momento que tentamos colocar um inteiro ou uma instância de Surfista
em sua lista mas o compilador impede que isso ocorra acusando erro na
compilação com a seguinte stackTrace.



in
the type ArrayList&lt;String&gt; is not applicable for the arguments
(int)

 The
method add(String) in the type ArrayList&lt;String&gt; is not
applicable for the arguments (Surfista)



&nbsp; &nbsp; &nbsp;Em
quanto isso a outra lista criada sem a utilização de genéricos,
aceita qualquer tipo de elemento, uma vez que não foi definido em
nenhum momento qual tipo de elemento deverá ser armazenado nesta
lista.

&nbsp; &nbsp; &nbsp;A
grande vantagem da utilização de genéricos é que tiramos aquela
responsabilidade de nós termos que saber se o tipo do conjuntos que
temos está adeguado ao tipo do elemento que desejamos adicionar a
lista. Colocamos toda esta responsabilidade para o compilador afinal
uma vez que esta responsabilidade pode ser autimatizada, porque não
o fazer não é mesmo? É exatamente isso que ocorre ao tentarmos
adicionar na lista listaGen o
item de valor igual a 2. Uma vez que o compilador verifica que a
lista deveria apenas receber valores texto (string), o compilador
acusa erro de compilação ao tentar adicionar qualquer outro tipo de
elemento que não seja texto e desta vez a classe não compila em
quanto o erro não for corrigido.

&nbsp; &nbsp; &nbsp;Mas
está enganado se os benefícios acabam por aí.

 Da
mesma forma que existem benefícios para inserir elementos em um
conjunto genérico, o mesmo ocorre a partir do momento em que
desejamos obter um elemento da lista,&nbsp;&nbsp; &nbsp; &nbsp;Diferente das listas
não-genéricas, uma lista genérica não percisa converter um
elemento quando for atribui-lo a uma  outra variável na aplicação.

&nbsp; &nbsp; &nbsp;Continuando
com exemplos a partir dos já demonstrados acima deste post:



   String
teste1
= listaGen.get(0);//ok

   teste1
= lista.get(0);//erro
de compilação



&nbsp; &nbsp; &nbsp;Definimos
uma variável String e atribuimos a ela o valor do primeiro elemento
da lista genérica listaGen
assim como já era esperado, a atribuição é feita normalmente sem
a necessidade de uma conversão. Isto porque o compilador já sabe
que a lista é composta de valores String, o que não ocorre ao
tentarmos realizar o mesmo procedimento com a lista não-genérica
obtendo o erro abaixo:



Unresolved
compilation problem: 


 Type
mismatch: cannot convert from Object to String



&nbsp; &nbsp; &nbsp;Isso
mesmo, como não definimos que tipo de elemento nossa lista possui, o
compilador espera um tipo Object
 logo poderíamos consertar este problema de 2 maneiras:


Defnindo
 a lista como String por meio dos genéricos




Realizarmos
 a atribuição a uma variável Object

Object
 teste3
 = lista.get(0);





&nbsp; &nbsp; &nbsp;O
mesmo ocorreria se defniirmos uma lista genérica com valores de um
tipo de objeto como Surfista por exemplo:



public
static
void
main(String
args[]) {

List&lt;Surfista&gt;
toReturn
t
=new
ArrayList&lt;Surfista&gt;();



 t.addAll(listaDeSurfistas());

//
ou

 t.add(Surfista.listaDeSurfistas
().get(0));//apenas
um elemento

//
ou

 Surfista
s = Surfista.listaDeSurfistas
().get(0);//apenas
um elemento



}

public
static
List&lt;Surfista&gt; listaDeSurfistas() {

  List&lt;Surfista&gt;
toReturn
= new
ArrayList&lt;Surfista&gt;();

  toReturn.add(new
Surfista("Gabriel
Medina",
"Medina",
19, 1));

  toReturn.add(new
Surfista("Miguel
Pupo",
"Dropador",
21, 2));

  toReturn.add(new
Surfista("Adriano
Souza",
"Rasgador",
26, 3));

  toReturn.add(new
Surfista("Raone
Monteiro",
"Monteiro",
30, 4));

  toReturn.add(new
Surfista("Alejo
Muniz",
"novato",
23, 5));

  toReturn.add(new
Surfista("Felipe
Toledo",
"cacula",
18, 6));

  return
toReturn;

}







&nbsp; &nbsp; &nbsp;Para
finalizar esta nossa introdução a genéricos falaremos sobre o
código acima, onde poderemos definir o tipo de retorno com uma lista
com genéricos. Este método deverá por sua sempre retornar uma
lista deste tipo ou irá ocorrer erro de compilação assim como
ocorre nos outros casos ja descritos.




Trabalhando
com códigos genéricos e não genéricos



&nbsp; &nbsp; &nbsp;Como
já comecei  dizendo na introdução, a utilização de genéricos é
opcional apesar de recomendada. Foi  e ainda é tratada como opcional
por motivos óbvios, caso o desenvolvedor tivesse muito código da
sua aplicação na versão anterior a 5, a refatoração de toda sua
aplicação iria ser algo muito custoso e a empresa da época Sun
levou isso em consuderação para implementar algo que não fosse
acarretar problemas entre versões.

&nbsp; &nbsp; &nbsp;Isso
faz com que em alguns momentos nós precisemos dispor de conhecimento
para trabalhar com as duas versões ao mesmo tempo pois diferente do
que mostramos até agora, onde os erro acorreram durante a
compilação, muitos erros relacionados a genéricos acontecem em
tempo de execução conforme mostramos abaixo:.



public
class
TestandoGenericos {



 public
static
void
main(String... args)
{

  ArrayList&lt;String&gt;
listaGen
= new
ArrayList&lt;String&gt;();

  ArrayList
lista
= new
ArrayList();

  listaGen.add("teste
1");//
ok

  lista.add("teste
1");//
ok

  //
listaGen.add(2);//erro
de
compilacao

  lista.add(2);//
ok

  //
listaGen.add(new Surfista());//erro
de
compilacao

  lista.add(new
Surfista());//
ok



  List&lt;Integer&gt;
nums
= new
ArrayList&lt;Integer&gt;(); //
versao5

  nums.add(5);//
versao5

  List
numsV4
= new
ArrayList();//
versao4

  numsV4.add(new
Integer(5));//
versao4

  System.out.println("comecando
classe testando array");

  System.out.println(nums);//
OK

  System.out.println(numsV4);//
ok

  Adiciona
ad
= new
Adiciona();

  ad.somaItemInt(nums,
"
genérica ");

  ad.somaItemInt(numsV4,
"
não genérica ");

  System.out.println(nums);//
OK

  System.out.println(numsV4);//
ok

  System.out.println("ATE
AQUI TUDO BEM!!");

  System.out.println("E
AQUI?");

  ad.somaItemString(nums,
"
genérica ");

  ad.somaItemString(numsV4,
"
não genérica ");

  System.out.println(nums);//
OK

  System.out.println(numsV4);//
ok

  System.out.println("Total
?");

  System.out.println(ad.calculaItem(nums,
"generica"));//
OK

  System.out.println(ad.calculaItem(numsV4,
"não
generica"));//
ok

  System.out.println(nums);//
OK

  System.out.println(numsV4);//
ok



 }

}



class
Adiciona {

 void
somaItemInt(List
lista,
String tentativa)
{

  try{

   lista.add(2);//
versao5

   lista.add(3);//
versao5

   lista.add(7);//
versao5

  }catch(Exception
e){System.out.println("somaItemInt:
tentativa - "
+ tentativa);}

 }

 void
somaItemString(List
lista,
String tentativa)
{

  try{

  lista.add("texto");//
versao4

  }catch(Exception
e){System.out.println("somaItemString:
tentativa -"
+ tentativa);}

 }



 int
calculaItem(List
lista,
String tentativa)
{

  int
total
= 0;

  Iterator
it
= lista.iterator();

   try
{

    while
(it.hasNext())
{

    total
+= ((Integer) it.next()).intValue();

    }

   }
catch
(Exception e)
{

   System.out.println("calculaItem:
tentativa -"
+ tentativa);

   }

  return
total;

  }

 }



Saida:

comecando
classe testando array

[5]

[5]

[5,
2, 3, 7]

[5,
2, 3, 7]

ATE
AQUI TUDO BEM!!

E
AQUI?

[5,
2, 3, 7, texto]

[5,
2, 3, 7, texto]

Total
?

calculaItem:
tentativa -generica

17

calculaItem:
tentativa -não generica

17

[5,
2, 3, 7, texto]

[5,
2, 3, 7, texto]





&nbsp; &nbsp; &nbsp;Podemos
concluir
de
acordo com o código
acima que
as
listas que são declardas com genéricos, não aceitam outro tipo de
elemento que não seja o definido na declaração, caso contrário,
qualquer elemento é inserido na lista acusando warning
de
compilação. Estas mensgens de atenção feitas pelo compilador
podem inclusive serem ocultadas caso compile sua class utilizando a
flag -Xlint:unchecked.



&nbsp; &nbsp; &nbsp;Mais
adiante vemos um
método
que possui dois parâmentro, onde
o
primeiro é uma lista não
genérica e
o segundo
uma
variável de
texto
que está
apenas servindo para
identificarmos em que momento o
método
será
chamado.
Vemos
que mesmo
tendo definido uma
lista com genéricos, definindo com elementos inteiros, a partir do
momento em
que
a
execução
entra no
método com
lista não genérica,
qualquer
elemento
é
adicionado
a lista
mesmo
a lista tendo sua definição genérica for a do método.O método
somaItemString
ignora e adiciona
um elemento texto em uma que
deveria conter apenas inteiros,
ocasionando erro no próximo método calculaItem
que
tenta somar os valores de todos os elementos da lista passada
como paramentro, deparando
com um elemento texto e
gerando
erro de execução conforme alertado anteriomente pelo
compilador.

&nbsp; &nbsp; &nbsp;Poderiamos
nos precaver deste
erro
definindo o método da seguinte forma::



void
somaItemString(List&lt;Integer&gt;
lista,
String tentativa)






https://github.com/gmachado1/blog/tree/branche1/GenericosEConjuntos