Java/Genéricos: diferenças entre revisões

[edição verificada][revisão pendente]
Conteúdo apagado Conteúdo adicionado
m <source> -> <syntaxhighlight> (phab:T237267)
 
Linha 7:
 
Na documentação <code>[https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html java.util.ArrayList]</code> há as seguintes assinaturas de método que utilizam o tipo genérico '''E'''.
<sourcesyntaxhighlight lang="Java">
public boolean add(E e)
public E get(int index)
</syntaxhighlight>
</source>
 
É convencionado o identificador '''E''' para elementos, '''K''' para chaves, '''V''' para valores e '''T''' para tipos, porém não há obrigatoriedade no uso. Pode-se utilizar qualquer identificador válido no parâmetro de tipo.
Linha 17:
No código abaixo temos a definição da classe <code>java.util.ArrayList</code> e da interface <code>java.util.List</code>, ambas com o parâmetro de tipo definidos com o tipo genérico '''E'''.
 
<sourcesyntaxhighlight lang="Java">
//Declarações parciais para evidenciar apenas os conceitos apresentados.
class ArrayList<E> {...}
 
interface List<E> {...}
</syntaxhighlight>
</source>
 
'''Argumento de tipo''' é o tipo especificado, entre o par de chevrons, na declaração de um tipo (chamada de construtor ou variável de referência) que substituirá o tipo genérico.
No código abaixo o tipo genérico '''E''' foi substituído, em tempo de compilação, pelo argumento de tipo '''String'''. Com isso o tipo da variável na lista de parâmetros do método <code>boolean add(E e)</code> foi alterado de <code>E e</code> para <code>String e</code> e o tipo de retorno do método <code>E get(int index)</code> foi de <code>E</code> para <code>String</code>.
 
<sourcesyntaxhighlight lang="Java" highlight="1-3">
List<String> lista = new ArrayList<String>();
lista.add("Elemento");
String elemento = lista.get(0);
System.out.println(elemento);
</syntaxhighlight>
</source>
<pre>
Elemento
Linha 39:
Para declarar-se classe ou interface com referências de tipos genéricos, basta especificar o tipo a ser substituído no parâmetro de tipo.
 
<sourcesyntaxhighlight lang="Java">
class Objeto<T> {
T objeto;
Linha 51:
}
}
</syntaxhighlight>
</source>
 
Ao utilizar-se uma classe ou interface que utiliza tipos genéricos basta enviar no argumento de tipo o tipo desejado. No código abaixo <code>String</code> foi definido como o tipo na variável de referência (<code>Objeto<String> obj</code>) e na chamada do construtor (<code>new Objeto<String>()</code>).
 
<sourcesyntaxhighlight lang="Java" highlight="1">
Objeto<String> obj = new Objeto<String>();
obj.setObjeto("Uma string qualquer.");
System.out.println(obj.getObjeto());
</syntaxhighlight>
</source>
<pre>
Uma string qualquer.
Linha 66:
Pode-se definir mais de um tipo de parâmetro. Para tal, é necessário separá-los com vírgula e não utilizar o mesmo tipo já utilizado.
 
<sourcesyntaxhighlight lang="Java">
class Par<K, T> {
K chave;
Linha 96:
}
}
</syntaxhighlight>
</source>
<pre>
42 é a resposta para o universo.
Linha 102:
 
A partir do Java SE 7 pode-se utilizar o operador diamante, que nada mais é que o argumento de tipo sem tipo especificado na chamada do construtor. Em tempo de compilação o argumento de tipo do construtor será inserido em correspondência ao argumento de tipo do tipo da variável.
<sourcesyntaxhighlight lang="Java">
Par<Integer, String> teste = new Par<>();
</syntaxhighlight>
</source>
 
É possível definir uma classe ou interface com tipos genéricos em parâmetros de tipo.
 
<sourcesyntaxhighlight lang="Java" highlight="1">
Par<Integer, Objeto<String>> par = new Par<>(52, new Objeto<>());
par.getObjeto().setObjeto("objeto");
System.out.println(par.getChave() + ": " + par.getObjeto().getObjeto() + "\n");
</syntaxhighlight>
</source>
<pre>
52: objeto
Linha 119:
É possível repassar o parâmetro de tipo definido em uma classe como argumento de tipo para referências de tipo genérico. No código abaixo a classe '''Colecao''' foi definida com o tipo '''T''' em seu parâmetro de tipo. O tipo '''T''' é então utilizado como argumento de tipo da variável de referência <code>List<T> lista</code>.
 
<sourcesyntaxhighlight lang="Java" highlight="1-2,4,8">
class Colecao<T> {
List<T> lista;
Linha 139:
}
}
</syntaxhighlight>
</source>
<pre>
[5.4, 3.43]
Linha 151:
 
No código abaixo, '''T''' é restringido à '''CharSequence''' ou suas classes implementadoras.
<sourcesyntaxhighlight lang="Java" line start="6" highlight="1">
class Teste<T extends CharSequence> {
public static void main(String[] args) {
Linha 164:
}
}
</syntaxhighlight>
</source>
<pre>
Ex
Linha 190:
Para isso basta inserir o parâmetro de tipo antes do tipo de retorno.
 
<sourcesyntaxhighlight lang="Java" highlight="1">
<T> void metodo () {}
</syntaxhighlight>
</source>
 
No código abaixo o tipo genérico, definido como <code>T</code>, é utilizado no tipo de retorno e no tipo do parâmetro na lista de parâmetros da declaração de método. Em tempo de compilação, o tipo <code>T</code> será convertido no tipo do argumento do método chamador, no caso abaixo como o argumento do método é do tipo <code>String</code> ('''"Exemplo"''') logo o tipo definido será <code>String</code>.
 
<sourcesyntaxhighlight lang="Java" highlight="7">
class Teste {
public static void main(String[] args) {
Linha 207:
}
}
</syntaxhighlight>
</source>
<pre>
Exemplo
Linha 215:
Para manter-se a compatibilidade com versões anteriores ao Java SE 5, a partir do lançamento da referida versão foi permitido que argumentos de tipo possam ser omitidos, são os chamados '''Tipos Crus'''.
 
<sourcesyntaxhighlight lang="Java">
//Tipo parametrizado.
Set<Double> conjunto;
Linha 221:
//Tipo cru.
Set conjunto;
</syntaxhighlight>
</source>
 
Em tempo de compilação os tipos crus são convertidos para o tipo <code>Object</code>.
 
<sourcesyntaxhighlight lang="Java" highlight="1, 3" start="7" line>
List lista = new ArrayList();
lista.add(5.5);
int i = (int) lista.get(0);
System.out.println(i);
</syntaxhighlight>
</source>
5.5