Programação. Java. com J2SE 50. Tipos genéricos. Helder da Rocha. Julho 2005

Documentos relacionados
TIPOS PARAMETRIZADOS CLASSES GENÉRICAS PARTE II

Prof. Fernando V. Paulovich 8 de novembro de SCC Programação Orientada a Objetos

API e Coleções Java. Sérgio Luiz Ruivace Cerqueira

Paradigmas da Programação PPROG GENÉRICOS. (Livro Big Java, Late Objects Capítulo 18) Nelson Freire (ISEP DEI-PPROG 2014/15) 1/23

Iteradores. Iteradores. Isabel Harb Manssour. Roteiro. Coleções

Desenvolvimento e Projeto de Aplicações Web

Coleções. João Paulo Q. dos Santos

JAVA COLLECTIONS API: LISTAS

Tipos genéricos (cont)

Coleções em Java. Prof. Gustavo Willam Pereira ENG10082 Programação II. Créditos: Prof. Clayton Vieira Fraga Filho

Profa. Thienne Johnson EACH/USP

12 Tipos Genéricos. Desenvolvimento OO com Java. Vítor E. Silva Souza

A Relação de Subtipo e Tipos Genéricos

Java Util Collections - Interfaces Interfaces definidas

Técnicas de Programação Avançada TCC Profs.: Anselmo Montenegro

Atividade 08 - Utilizando Collections - List

Orientação a Objetos AULA 09

Streams II. Overview. The notion of stream Java I/O stream hierarchy Files, and file access using streams Serialization

Programação Orientada a Objetos

Recapitulando. Construtores: (Overload assinatura) public Circle() {...} public Circle(double x, double y, double r) {... }

Programação Orientada a Objectos - P. Prata, P. Fazendeiro

Interfaces POO. Prof. Marcio Delamaro

Bruce Eckel, Thinking in Java, 4th edition, PrenticeHall, New Jersey, cf. José Valente de Oliveira 16-1

Java Collections Framework II

Técnicas de Programação Avançada TCC Profs.: Anselmo Montenegro

Collections Framework

Computação II Orientação a Objetos

Programação Orientada a Objetos

COLECÇÕES DE OBJECTOS EM JAVA6

Coleções. Profa. Thienne Johnson EACH/USP

Programação Java Aula 04

Aula 5 POO 1 Encapsulamento. Profa. Elaine Faria UFU

Computação II Orientação a Objetos

Generics POO. Prof. Marcio Delamaro

01/06/2016 INF1636 PROGRAMAÇÃO ORIENTADA A OBJETOS. Programa Capítulo 15. Coleções. A Interface List. A Classe LinkedList. Exercício.

Java API. Giuliana Silva Bezerra

A classe ArrayList. IFSC/Florianópolis - Programação Orientada a Objetos com Java - prof. Herval Daminelli

Programação por Objectos. Java

Aula 9 Herança. Prof. Jefersson Alex dos Santos

Generics. Byron Leite e Bruno Fernandes. Orientação a objetos com Java. 1 Generics

Programação OO em Java

Conceitos de Interface; classes abstratas; Diagrama de sequencia, Diagrama de atividades, classes aninhadas e Listas dinâmicas

Genéricos by Pearson Education do Brasil

Programação Java. - Herança e Polimorfismo - Marco Fagundes Marco Fagundes -

INF1636 PROGRAMAÇÃO ORIENTADA A OBJETOS

Apêndice A. Alguns construtores e métodos importantes e úteis da classe Vector são:

Coleções. Prof. Marcelo Roberto Zorzan

Coleções POO. Prof. Marcio Delamaro

Programação Orientada a Objectos - P. Prata, P. Fazendeiro. Hierarquia de classes e mecanismo de ligação

UNIVERSIDADE FEDERAL DO PARANÁ. CURSO: Ciência da Computação DATA: / / 2013 PERÍODO: 4 o.

Técnicas de Programação Avançada TCC Prof.: Anselmo Montenegro Conteúdo: Polimorfismo

Genéricos. Profa. Thienne Johnson EACH/USP

Métodos Genéricos. Prof.: Michele Nasu Tomiyama Bucci

Sistemas de Tipos. Prof. Alberto Costa Neto Linguagens de Programação. Departamento de Computação Universidade Federal de Sergipe

Programação Orientada a Objetos. Collections - Java

9 Classes Abstractas e Interfaces

Iterator. Professor: Hyggo Almeida

Java Standard Edition (JSE)

Programação Orientada a Objectos - P. Prata, P. Fazendeiro

Herança e Polimorfismo - Parte I -

Programação Orientada a Objectos - P. Prata, P. Fazendeiro

JAVA 1.5 na plataforma J2SE 5.0 Tiger Novas Construções, Sintaxe, Tipos e Polimorfismo

4 Conceito de Herança

Java na Prática. Célio Silva Aula 3

Programação Orientada a Objectos - P. Prata, P. Fazendeiro. Hierarquia de classes e mecanismo de ligação

Programação Orientada a Objetos

Programação com genéricos

Herança e Polimorfismo -Parte I - Mário Meireles Teixeira O exemplo DoME. Database of Multimedia Entertainment

O problema da herança múltipla e o uso de Interfaces. Herança múltipla. Interfaces. Definindo Interfaces 30/11/2016

Instituto Federal de Educação, Ciência e Tecnologia da Bahia Campus Irecê Disciplina: Linguagem Técnica II Prof o Jonatas Bastos

Collections. Programação Orientada por Objetos (POO) Centro de Cálculo Instituto Superior de Engenharia de Lisboa

Java 2 Standard Edition Classes internas

Herança e Polimorfismo (Universal)

Lista 05 Herança. public class PessoaFisica extends Pessoa { private String RG; public PessoaFisica(){ super(); } public String getrg(){ return RG; }

Computação II Orientação a Objetos

Tipos, Literais, Operadores

Tipos, Literais, Operadores

Programação II Java Collections Framework (JCF) Christopher Burrows

Programação Orientada a Objetos com Java. Prof. Júlio Machado

Java First-Tier: Aplicações. Herança: Simples Múltipla. Orientação a Objetos em Java (III) Problemas de Herança Múltipla.

Computação II - Java - Prova 1 Prof. Adriano Joaquim de Oliveira Cruz /05/13. Questão: Total Pontos: Gráu:

PCC104 - Projeto e Análise de Algoritmos

ArrayList. null. null. null ... ArrayList<Ponto2D>

Interfaces e polimorfismo

Linguagem de Programação Orientada a Objeto Polimorfismo, Classes Abstractas e Interfaces

Análise e Projeto Orientados por Objetos

Tratamento de Erro e Javadoc. Professor: Norton T. Roman

Programação Orientada a Objetos. Métodos e Atributos. Métodos. Métodos. Alexandre César Muniz de Oliveira. Parte III

Programação orientada a objetos em Java

Herança (parte 2) Redefinição de métodos AULA 11

Ficha Prática 10. António Nestor Ribeiro, Paulo Azevedo, Mário Martins PPIV (LESI) 2005/06

Exceções AULA 13. Ricardo Massa F. Lima Sérgio C. B. Soares

Computação II - Java - Teste 1.2 Prof. Adriano Joaquim de Oliveira Cruz 2015/04/27

Lista encadeada class No { Coleções. Enumeration. Lista encadeada (continuação) Enumeration Exemplo usando a classe Lista anterior

Java para Desktop. Programação Orientada à Objetos 2 JSE

Programação Orientada a Objetos

Transcrição:

Programação Java em com J2SE 50. Tipos genéricos Helder da Rocha Julho 2005

O que são os Genéricos? Recurso introduzido no Java 5.0 Sintaxe que permite restringir os tipos de dados aceitos por referências genéricas Permite verificação de tipo em tempo de compilação! Exemplo: coleções Permitem agrupar objetos de diferentes tipos, devido à sua interface genérica (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 genérico e requer downcasting que só é verificado em tempo de execução 2

O Problema Antes dos genéricos, era preciso fazer coerção (cast) para usar os dados recuperados de coleções Galinha rosalinda Object addparameter Object nextreturn Heap Galinha Referências são verificadas em tempo de compilação class Fazenda {... private List galinheiro = new ArrayList(); public List getgalinheiro() { return galinheiro; 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); 3

O Problema (2) E havia o risco do programador cometer um erro (já que não há verificação de tipos de objeto na compilação) 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()); Referências estão corretas: Trata-se de um Object! Mas não dá para fazer cast de para uma referência Galinha Fazendeiro ze = new Fazendeiro(fazenda); Iterator galinhas = ze.pegargalinhas(); while(galinhas.hasnext()) { Galinha galinha = (Galinha) galinhas.next(); class Raposa { public void assaltar(list lugar) { lugar.add(this); FALHA! Há uma raposa no meio das galinhas [java] Exception in thread "main" java.lang.classcastexception: Raposa Correto! List tem add(object) e Raposa é um Object 4

Solução sem usar genéricos Typesafe collection: padrão de design Apenas Galinhas são aceitas no galinheiro Para recuperar objetos, não é necessário usar cast! Mas Galinheiro não é List, E GalinhaIterator não é Iterator 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) { return (Galinha) galinhas.get(idx); public void add(galinha g) { galinhas.add(g); import java.util.*; public class GalinhaIterator { private Iterator iterator; GalinhaIterator(Iterator it) { iterator = it; public boolean hasnext() { return iterator.hasnext(); public Galinha next() { return (Galinha)iterator.next(); Não compila! Não requer cast! Galinheiro g = new Galinheiro(new ArrayList()); g.add(new Galinha("Frida")); // g.add(new Raposa( Galius )); Galinha frida = g.get(0); 5

Solução com genéricos (1) Genéricos permitem associar um tipo à referência Restringe tipos permitidos ao passado como parâmetro Permite verificação em tempo de compilação class Fazenda {... private List<Galinha> galinheiro = new ArrayList<Galinha>(); public List<Galinha> getgalinheiro() { return galinheiro; Parâmetro de tipo (type parameter) Isto não é um ArrayList de Object mas um ArrayList de Galinha class Galinha { public void entrarnogalinheiro(list<galinha> galinheiro) { galinheiro.add(this); Sintaxe básica: TipoGenerico<TipoEspecifico> 6

Solução com genéricos (2) Agora não precisamos mais do cast Fazendeiro ze = new Fazendeiro(fazenda); Iterator<Galinha> galinhas = ze.pegargalinhas(); while(galinhas.hasnext()) { Galinha galinha = galinhas.next(); // sem cast!!! Raposas também não entram mais Precisam especificar tipo de lugar. O compilador avisa (warning) sobre uso de objetos inseguros: [javac] Note: C:\usr\projects\Fragmentos.java uses unchecked or unsafe operations. Conserta-se a Raposa: Se a Raposa fosse esperta, declararia como <?> class Raposa { public void assaltar(list<object> lugar) { lugar.add(this); mas mesmo assim não iria funcionar! O compilador acusa o erro! [javac] C:\usr\projects\Fragmentos.java:16: assaltar(java.util.list<java.lang.object>) in Raposa cannot be applied to (java.util.list<galinha>) 7

Nova interface java.util.collection public interface Collection<E> extends Iterable<E> { int size(); boolean isempty(); boolean contains(object o); Iterator<E> iterator(); Object[] toarray(); <T> T[] toarray(t[] a); boolean add(e o); boolean remove(object o); boolean containsall(collection<?> c); boolean addall(collection<? extends E> c); boolean removeall(collection<?> c); boolean retainall(collection<?> c); void clear(); 8

Definição de genéricos Sintaxe de declaração: 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); Convenção: defina parâmetros 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

Compilação de genéricos Uma declaração de tipo genérico é compilada e gera uma classe Java comum, como outra qualquer Não é um template! Não há geração especial de código. Informação de generics serve para compilação e é apagada no bytecode final Não aumenta o tamanho do código: veja os arquivos.class gerados e compare: são iguais aos anteriores. Genéricos funcionam como estruturas que aceitam parâmetros em tempo de execução Uma razoável analogia é comparar com a passagem de argumentos para parâmetros em métodos 10

Uma boa analogia Em métodos Na declaração parâmetros formais de valor descrevem os valores que o método pode aceitar; Quando um método é chamado, os argumentos passados (valores e referências) substituem os parâmetros formais Em genéricos: Na declaração, parâmetros formais de tipo descrevem os tipos que o genérico pode representar; Quando um tipo genérico é usado, os argumentos passados (tipos) substituem os parâmetros formais Métodos interface Exemplo { int metodo(int x); Exemplo e =... int r = e.metodo(5); Declaração Uso Tipos Genéricos class ArrayList<E> implements List<E> {... List<Integer> lista = new ArrayList<Integer>(); 11

Hierarquia de subtipos Se X é um subtipo de Y, e G um tipo genérico, não é verdade que G<X> é um subtipo de G<Y> Exemplo: o código abaixo é ilegal List<Galinha> galinhas = new ArrayList<Galinha>(); galinhas.add(new Galinha( Cocogilda")); List<Object> objetos = galinhas; // ILEGAL! Ah, mas com arrays não seria! Galinha[] vg = { new Galinha( Cocogilda") ; Object[] vo = vg; Causa erro de compilação Sim, mas arrays são imutáveis; coleções não! Problemas poderiam acontecer se coleção crescesse objetos.add(new Raposa()); // ok, pois Raposa é Object Galinha gilda = galinhas.get(0); // Raposa fantasiada 12

Flexibilidade com curingas De acordo com a regra anterior: Collection<Object> não é supertipo de Collection<Integer> Collection<Object> só aceita componentes Object! O supertipo genérico verdadeiro é Collection<?>? é o tipo desconhecido O tipo Collection<?> portanto é uma Collection do desconhecido Exemplo: o método abaixo aceita coleções que contenham qualquer tipo void printcollection(collection<?> c) {... Limitações Coleções de tipos desconhecidos podem ter seus componentes lidos, mas não pode receber novos componentes c.add(new Object()); // dentro do método 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. Limites inferiores: <? super T> Aceita T e todos os seus ascendentes Ex: se T for ArrayList, aceita List, Collection, Object Exemplo: método que aceita qualquer Shape class Canvas { public void drawall(list<? extends Shape> shapes) { for(shape s: shapes) { s.draw(this); Shape Circle draw(canvas) draw(canvas) Rectangle draw(canvas) 14

Variações Tipos genéricos 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

Métodos genéricos Usados quando existem dependências entre o tipo de retorno e os parâmetros Exemplo de sintaxe mods <T1, T2> tiporetorno nome(item<t1>, T2) {... Exemplo declaração 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

Curingas vs. métodos genéricos Pode-se implementar com métodos genéricos o que se implementa com curingas. As implementações abaixo são equivalentes Collection original interface Collection<E> { public boolean containsall(collection<?> c); public boolean addall(collection<? extends E> c); Collection implementada com método genérico interface Collection<E> { public <T> boolean containsall(collection<t> c); public <T extends E> boolean addall(collection<t> c); Questão: Quando usar métodos genéricos? Quando usar curingas? Só use métodos genéricos quando não for possível usar curingas Se não existir dependência entre parâmetros e/ou tipos de retorno, deve-se preferir curingas 17

Genéricos estão para ficar Genéricos estão em toda a API Java Aprenda a usá-los. Não tente fugir deles! Familiarize-se com a sintaxe (vai ficar mais simples com o tempo e o costume) e evite abusar dela: quando algo puder ser feito de duas formas prefira sempre a mais simples Duas implementações equivalentes a) b) Qual você escolheria? public static <T> void copy(list<t> dest, List<? extends T> src) { public static <T, S extends T> void copy(list<t> dest, List<S> src) { Familiarize-se com a sintaxe. Use generics já! 99% das aplicações resolvem tudo com sintaxe simples Qual é o tipo de history? static List<List<? extends Shape>> history = new ArrayList<List<? extends Shape>>(); 18

Código legado em genéricos Como usar APIs e frameworks em código antigo, no seu código novo que usa genéricos? Não é preciso fazer nada de especial. Basta tratar o código como se fosse pré-java 5.0 Exemplo: pode-se passar para um método que aceita Classe, qualquer Classe<Tipo> Classe é um tipo cru (raw type). É parecido com Classe<?> mas não causa nenhuma verificação de precisão de tipos É inseguro, portanto o compilador imprime um aviso (warning) que não pode garantir a precisão do código Tipos crus existem apenas para garantir a compatibilidade reversa 19

Genéricos em código legado Como usar APIs novas (com genéricos) em código antigo? Isto já acontece se você compila seu código antigo que usa collections no Java 5.0 Você pode passar tipos crus para tipos genéricos checados sem causar erro de compilãção O compilador não tem como garantir a precisão dos tipos e avisa com um warning. Se todo o seu código usar genéricos, toda a verificação de tipos de referência será feita em tempo de compilação e não haverá erro de cast 20

Equivalência 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()); java.util.arraylist java.util.arraylist true O motivo Todas as instâncias de uma classe genérica tem a mesma classe em tempo de execução, indepentemente dos parâmetros de tipo passados Uma classe não é mais sinônimo de tipo Uma classe genérica pode ter muitos tipos 21

Casts e instanceof Como classes de tipos diferentes são equivalentes, não faz sentido usar cast ou instanceof com tipos genéricos O seguinte trecho é ilegal (causa erro de compilação) Collection cs = new ArrayList<String>(); if (cs instanceof Collection<String>) {... O trecho abaixo causa aviso (warnings do compilador) já que a informação de cast não é útil para o sistema de tempo de execução Collection <String> cstr = (Collection<String>) cs; Casts com variáveis de tipo são inúteis, uma vez que elas não existem em tempo de execução (causa warning) <T> T badcast(t t, Object o) { return (T)o; 22

Arrays O tipo dos componentes de um array de tipos genéricos não pode ser uma variável de tipo O seguinte trecho é ilegal List<String>[] lsa = new List<String>[10]; // ERRO!! O seguinte trecho é permitido, porém causa um aviso do compilador (pode causar erro de tempo de execução) List<String>[] lsa = new List<?>[10]; // advertência! String s = lsa[0].get(0); // possível erro runtime O seguinte trecho é legal, porém 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 é genérico! Pode-se fazer Class<String> c = String.class; Class<Pessoa> pc = Class.forName( Pessoa ); Employee e = new Employee(); Class<Employee> = e.getclass(); O método newinstance() agora retorna um objeto do tipo da classe onde é chamado Pessoa joao = pc.newinstance(); 24

Como começar a usar genéricos Explore a documentação Veja principalmente o pacote de coleções de Java: reveja as classes que você já usa e as novas assinaturas dos métodos Aplique genéricos no seu código Crie novos programas usando genéricos Altere programas existentes gradualmente Compile (javac) usando a opção Xlint para identificar trechos obsoletos No Ant, use <javac...> <compilerarg line= -Xlint...> 25

Fontes de pesquisa [1] Gilad Bracha, Generics in the Java Programming Language a.k.a The Generics Tutorial, Julho de 2004. Distribuído com a documentação Java. A maior parte desta apresentação foi construído com exemplos desse tutorial. [2] James Gosling, Bill Joy, Guy Steele e Gilad Bracha, The Java Language Specification, 3rd Edition. Addison-Wesley, 2005 (disponível em java.sun.com). Tópicos 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 vários outros) [3] Angelika Langer, The Generics FAQ. 2004-2005 www.langer.camelot.de/genericsfaq/javagenericsfaq.html Contém uma investigação detalhada sobre os aspectos mais obscuros de Java Generics [4] Bruce Eckel, Templates vs. Generics, 08/2004 mindview.net/weblog/log-0061 Discussão explorando as diferenças entre C++ Templates e Java Generics, procurando soluções para os principais problemas 2004-2005, Helder da Rocha www.argonavis.com.br 26