Genéricos Extensão à linguagem Java apresentada pelo JDK1.5 Permite reutilização de software com tipo seguro Permite abstrair do tipo de dados Exemplo: Desenvolver código para uma classe (por ex, uma pilha) de qualquer tipo de dados ou um método (por ex, imprimir elementos de um array) de qualquer tipo de dados 1
Construção de um método genérico Se pretendesse escrever um array de Integer e um array de Automovel e um array de String teria que desenvolver código para 3 métodos escreverarray( ): public static void escreverarray( Integer[] array) public static void escreverarray( Automovel[] array) public static void escreverarray( String[] array) Podemos substituí-los por este: public static <E> void escreverarray( E[] array) { for(e elem : array) System.out.println(elem); 2
Construção de um método genérico (cont) No exemplo anterior E designa-se por parâmetro tipo ou variável tipo, é o identificador que especifica o nome de um tipo genérico, obrigatòriamente referência A declaração de métodos genéricos tem uma secção de parâmetros tipo (1 ou mais, separados por, ) delimitada por < > que precede o tipo de retorno do método O tipo genérico pode ser usado em tipo de retorno tipo de parâmetro tipo de variáveis locais 3
Construção de um método genérico (cont) Construir um método que determina o maior de 3 objectos (todos diferentes). Seja o seguinte o código do método main( ) public static void main(string [] args) { Integer x,y,z; x=10;y=20;z=15; Automovel a1=new Automovel("11-11-aa", Fiat",1200,2005,12,20); Automovel a2=new Automovel("11-11-aa", Audi",1200,2005,12,20); Bicicleta b1=new Bicicleta( BMX","1234Maia"); System.out.println(maior(x,y,z)); System.out.println(maior(a1,a2,b1)); 4
Construção de um método genérico (cont) Como há que fazer comparações, os objectos que estiverem em jogo terão que implementar o interface Comparable<E> e portanto terão que definir código para o metodo compareto( ) public static <E extends Comparable<E>> E maior(e el1,e el2,e el3){ E max=el1; if(el2.compareto(max)>0) max=el2; if(el3.compareto(max)>0) max=el3; return max; 5
Construção de um método genérico (cont) Vejamos agora o código do método compareto( ) na classe Veiculo. Consideramos que a comparação era feita através da marca public int compareto(object obj) { Veiculo v=(veiculo)obj; return this.marca.compareto(v.marca); 6
Métodos genéricos (cont) Métodos genéricos podem ser sobrecarregados por outros métodos genéricos, (variando o nº de parâmetros) ou por métodos não genéricos. O compilador 1º procura aquele cujos argumentos são exactamente iguais aos da invocação, se não encontra, então procura se há algum que embora não exacto é aplicável. 7
Classes genéricas ou Classes parametrizaveis A declaração de uma classe genérica (assemelha-se a uma não genérica) faz-se colocando a seguir ao nome da classe uma secção de parâmetros tipo. Exemplo: public class Pilha<E> { private final int maxelem; // nº maximo de elementos private int topo; // posição do último elemento private E[] elementos // array que guarda os elementos da pilha 8
Classes genéricas ou Classes parametrizaveis //Construtores public Pilha() { this(10); public Pilha(int n){ maxelem=n > 0? n :10; topo= -1; //inicialmente vazia //elementos= new E[maxElem] dá erro de compilação // não admite new de um parâmetro tipo elementos=(e[]) new Object[maxElem]; 9
Classes genéricas ou Classes parametrizaveis public void push(e valor) throws ExcepcaoPilhaCheia{ if(topo==maxelem-1) throw new ExcepcaoPilhaCheia("Pilha cheia não é possível fazer push); elementos[++topo]=valor; public E pop() throws ExcepcaoPilhaVazia{ if(topo==-1) throw new ExcepcaoPilhaVazia("Pilha vazia não é possivel fazer pop"); return elementos[topo--]; 10
Classes de excepção usadas no exemplo class ExcepcaoPilhaCheia extends RuntimeException { public ExcepcaoPilhaCheia(String s){ super(s); class ExcepcaoPilhaVazia extends RuntimeException{ public ExcepcaoPilhaVazia(String s){ super(s); 11
Método main usado no exemplo public static void main(string [] args) { Pilha<Veiculo> p=new Pilha<Veiculo>(2); Automovel a1=new Automovel("11-11-aa","Fiat",1200,2005,12,20); Automovel a2=new Automovel("11-11-aa","Audi",1200,2005,12,20); Bicicleta b1=new Bicicleta("ZMX","1234AA"); try{ p.push(a1);p.push(a2);p.push(b1); catch(excepcaopilhacheia e){ System.out.println(e.getMessage()); System.out.println(p.pop()); // 12
Notas sobre Genéricos Uma classe genérica pode ser derivada de uma não genérica Uma classe genérica pode ser derivada de outra genérica Uma classe não genérica pode ser derivada de uma genérica Um método genérico numa subclasse pode reescrever um método genérico da super se ambos têm a mesma assinatura Numa classe os parâmetros tipo não podem ser usados em declarações estáticas da classe. 13
A classe Arrays Esta classe pertence ao package java.util, contem vários métodos para manipular arrays tais como ordenar e pesquisar. Todos os métodos são estáticos e os arrays a manipular podem ser de tipos primitivos ou de objectos. Principais métodos: Retorno boolean void void indice List Invocação do método Arrays.equals(array1,array2) Arrays.fill(array,valor) Arrays.sort(array) Arrays.binarySearch(array_ordenado,valor_a_procurar) Arrays.asList(array_de_objectos) 14
A classe Collections Esta classe pertence ao package java.util, consiste exclusivamente em métodos estáticos que operam polimorficamente sobre colecções ou devolvem colecções. Todos os métodos lançam a excepção NullPointerException se as colecções que lhes são fornecidas são null. Colecção é um conjunto de referências para objectos que são geralmente todos do mesmo tipo. Existem interfaces que declaram operações para serem realizadas genericamente em vários tipos de colecções, nomeadamente: Collection, Set, List, Queue, Map 15
A classe Collections Principais métodos: Retorno boolean void void indice List boolean int boolean objecto objecto void Invocação do método Collections.copy(lista_destino,lista_origem) Collections.fill(lista,valor) Collections.sort(lista) Collections.binarySearch(lista_ordenada,valor_a_procurar) Collections.reverse(lista) Collections.disjoint(lista1,lista2) Collections.frequency(lista, valor) Collections.addAll(lcolecçao,objectos_a_juntar) Collections.max(colecçao_de_objectos) Collections.min(colecçao_de_objectos) Collections.shuffle(lista) 16
Nota1: Para utilizar os métodos sort, binarysearch a classe dos objectos que constituem a lista devem implementar a interface Comparable e definir o método compareto(...) Nota2: A interface List é implementada por algumas classes, a saber: ArrayList LinkedList Vector Nota3: Auto boxing ocorre quando se juntam valores do tipo primitivo aos objectos destas classes, porque elas só guardam referências para objectos. De igual modo ocorre Auto unboxing quando se obtem um valor destas colecções 17