Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
com
Programao em
50 .
J2SE
Tipos genricos
Helder da Rocha
Julho 2005
O que so os Genricos?
Recurso introduzido no Java 5.0
Sintaxe que permite restringir os tipos de dados aceitos por referncias genricas Permite verificao de tipo em tempo de compilao!
Exemplo: colees
Permitem agrupar objetos de diferentes tipos, devido sua interface genrica (baseada em Object)
interface List { public void add(Object item); public Object get(int index); public Iterator iterator(); ... } interface Iterator { public Object next(); ... }
Vantagem: aceita qualquer tipo Desvantagem: retorna tipo genrico e requer downcasting que s verificado em tempo de execuo
O Problema
Antes dos genricos, era preciso fazer coero (cast) para usar os dados recuperados de colees
Galinha rosalinda Object addParameter Object nextReturn
Heap
Fazenda fazenda = Fazenda.getInstance(); Galinha g1 = new Galinha(Chocagilda"); Galinha g2 = new Galinha(Cocotalva"); // galinhas entram no galinheiro g1.entrarNoGalinheiro(fazenda.getGalinheiro()); g2.entrarNoGalinheiro(fazenda.getGalinheiro()); Fazendeiro ze = new Fazendeiro(fazenda); Iterator galinhas = ze.pegarGalinhas(); while(galinhas.hasNext()) { Galinha galinha = (Galinha) galinhas.next(); }
class Galinha { public void entrarNoGalinheiro(List galinheiro) { galinheiro.add(this); } }
Galinha
O Problema (2)
E havia o risco do programador cometer um erro (j que no h verificao de tipos de objeto na compilao)
Raposa gargamel Object addParameter Object nextReturn
Heap
Raposa
g1.entrarNoGalinheiro(fazenda.getGalinheiro()); g2.entrarNoGalinheiro(fazenda.getGalinheiro()); ... // entra uma raposa!!! Raposa galius = new Raposa(Galius"); galius.assaltar (fazenda.getGalinheiro()); Fazendeiro ze = new Fazendeiro(fazenda); Iterator galinhas = ze.pegarGalinhas(); while(galinhas.hasNext()) { Galinha galinha = (Galinha) galinhas.next(); }
Referncias esto corretas: Trata-se de um Object! Mas no d para fazer cast de para uma referncia Galinha
import java.util.*; public class Galinheiro { private List galinhas; public Galinheiro(List list) { galinhas = list; } public GalinhaIterator iterator() { return new GalinhaIterator(galinhas.iterator()); } } public Galinha get(int idx) { No return (Galinha) galinhas.get(idx); } public void add(Galinha g) { galinhas.add(g); Galinheiro g = } new Galinheiro(new }
GalinhaIterator(Iterator it) { iterator = it; } public boolean hasNext() { return iterator.hasNext(); } public Galinha next() { return (Galinha)iterator.next(); }
Conserta-se a Raposa:
Definio de genricos
Sintaxe de declarao: trecho de java.util.List
public interface List<E> extends Collection<E> { void add(E element); E get(int index); Iterator<E> iterator(); boolean addAll(Collection<? extends E> c); <T> T[] toArray(T[] a); }
Conveno: defina parmetros de tipo com uma letra, de caixaalta (ex: T de tipo, V de valor, E de Elemento, K de key)
Sintaxe de uso
List<Number> numeros = new ArrayList<Number>(); numeros.add(new Integer(5)); numeros.add(new Double(3.14)); Number pi = numeros.get(1); Collection<Long> longs = new HashSet<Long>(); longs.add(123L); longs.add(0xBABEL); boolean success = numeros.addAll(longs); Number[] dummy = {}; Number[] array = numeros.toArray(dummy); for (Number n: array) { System.out.println(n); } 9
Compilao de genricos
Uma declarao de tipo genrico compilada e gera uma classe Java comum, como outra qualquer
No um template! No h gerao especial de cdigo. Informao de generics serve para compilao e apagada no bytecode final No aumenta o tamanho do cdigo: veja os arquivos .class gerados e compare: so iguais aos anteriores.
Em genricos:
Na declarao, parmetros formais de tipo descrevem os tipos que o genrico pode representar; Quando um tipo genrico usado, os argumentos passados (tipos) substituem os parmetros formais
Mtodos
interface Exemplo { int metodo(int x); } Exemplo e = ... int r = e.metodo(5); Declarao
Tipos Genricos
class ArrayList<E> implements List<E> { ... } List<Integer> lista = new ArrayList<Integer>();
11
Uso
Hierarquia de subtipos
Se X um subtipo de Y, e G um tipo genrico, no verdade que G<X> um subtipo de G<Y> Exemplo: o cdigo abaixo ilegal
List<Galinha> galinhas = new ArrayList<Galinha>(); galinhas.add(new Galinha(Cocogilda")); List<Object> objetos = galinhas; // ILEGAL! Causa erro de compilao Galinha[] vg = { new Galinha(Cocogilda") }; Object[] vo = vg;
Exemplo: o mtodo abaixo aceita colees que contenham qualquer tipo void printCollection(Collection<?> c) { ... } Limitaes
Colees de tipos desconhecidos podem ter seus componentes lidos, mas no pode receber novos componentes c.add(new Object()); // dentro do mtodo acima, ilegal Object obj = c.get(0); // legal, assumindo que o elemento 0 exista
13
Impondo limites
Pode-se impor limites aos curingas Limites superiores: <? extends T>
Aceita T e todos os seus descendentes Ex: se T for Collection, aceita List, Set, ArrayList, etc.
14
Variaes
Tipos genricos podem receber mais argumentos Exemplo: Map<K, V>
K = key, V = value Exemplo:
Map<String, ? extends Employee>
usa uma String como chave para elementos que podem ser quaisquer subclasses de Employee
15
Mtodos genricos
Usados quando existem dependncias entre o tipo de retorno e os parmetros Exemplo de sintaxe
mods <T1, T2> tipoRetorno nome(Item<T1>, T2) {...}
Exemplo
declarao
static <T> void arrayToCollection(T[] arr, Collection<T> col) { for (T obj: arr) { col.add(obj); } }
uso
Collection<Number> nums = new ArrayList<Number>(); arrayToCollection(array, nums);
16
Questo:
Quando usar mtodos genricos? Quando usar curingas?
18
Exemplo: pode-se passar para um mtodo que aceita Classe, qualquer Classe<Tipo>
Classe um tipo cru (raw type). parecido com Classe<?> mas no causa nenhuma verificao de preciso de tipos inseguro, portanto o compilador imprime um aviso (warning) que no pode garantir a preciso do cdigo Tipos crus existem apenas para garantir a compatibilidade reversa
19
Se todo o seu cdigo usar genricos, toda a verificao de tipos de referncia ser feita em tempo de compilao e no haver erro de cast
20
Equivalncia
O que voc acha que o trecho seguinte imprime?
List <String> strings = new ArrayList<String>(); List <Integer> integers = new ArrayList<Integer>(); System.out.println(strings.getClass().getName()); System.out.println(integers.getClass().getName()); System.out.println(strings.getClass() == integers.getClass());
O motivo
Todas as instncias de uma classe genrica tem a mesma classe em tempo de execuo, indepentemente dos parmetros de tipo passados
Casts e instanceof
Como classes de tipos diferentes so equivalentes, no faz sentido usar cast ou instanceof com tipos genricos O seguinte trecho ilegal (causa erro de compilao)
Collection cs = new ArrayList<String>(); if (cs instanceof Collection<String>) { ... }
O trecho abaixo causa aviso (warnings do compilador) j que a informao de cast no til para o sistema de tempo de execuo
Collection <String> cstr = (Collection<String>) cs;
Casts com variveis de tipo so inteis, uma vez que elas no existem em tempo de execuo (causa warning)
<T> T badCast(T t, Object o) { return (T)o; }
22
Arrays
O tipo dos componentes de um array de tipos genricos no pode ser uma varivel de tipo O seguinte trecho ilegal
List<String>[] lsa = new List<String>[10]; // ERRO!!
O seguinte trecho permitido, porm causa um aviso do compilador (pode causar erro de tempo de execuo)
List<String>[] lsa = new List<?>[10]; // advertncia! String s = lsa[0].get(0); // possvel erro runtime
O seguinte trecho legal, porm para extrair um String do array ser preciso usar cast
List<?>[] lsa = new List<?>[10]; // ok! String s = (String) lsa[0].get(0);
23
java.lang.Class
No Java 1.5, java.lang.Class genrico! Pode-se fazer
Class<String> c = String.class; Class<Pessoa> pc = Class.forName(Pessoa); Employee e = new Employee(); Class<Employee> = e.getClass();
Fontes de pesquisa
[1] Gilad Bracha, Generics in the Java Programming Language a.k.a The Generics Tutorial, Julho de 2004.
Distribudo com a documentao Java. A maior parte desta apresentao foi construdo com exemplos desse tutorial.
[2] James Gosling, Bill Joy, Guy Steele e Gilad Bracha, The Java Language Specification, 3rd Edition. Addison-Wesley, 2005 (disponvel em java.sun.com).
Tpicos de interesse: 4.4 Type Variables, 4.5 Parameterized Types, 4.6 Type Erasure, 4.7 Reifiable Types, 4.8 Raw Types, 4.9 Intersection Types, 8.1.2 Generic Classes and Type Parameters, 8.4.4 Generic Methods, 8.8.4 Generic Constructors, 9.1.2 Generic Interfaces (e vrios outros) www.langer.camelot.de/GenericsFAQ/JavaGenericsFAQ.html Contm uma investigao detalhada sobre os aspectos mais obscuros de Java Generics mindview.net/WebLog/log-0061 Discusso explorando as diferenas entre C++ Templates e Java Generics, procurando solues para os principais problemas
26