Paradigmas da Programação
PPROG
GENÉRICOS
(Livro Big Java, Late Objects – Capítulo 18)
Nelson Freire (ISEP–DEI-PPROG 2014/15)
1/23
Genéricos
Sumário
Noção de Genérico
Interesse dos Genéricos
Tipos Parametrizados
Implementação
Classe Genérica
Método Genérico
Genéricos e Herança
Tipos Wildcard
Type Erasure
Contexto Estático
Bibliografia
Nelson Freire (ISEP–DEI-PPROG 2014/15)
2/23
Noção de Genérico
Genéricos
1/2
Genéricos
Facilidade do Java
Java 5 (2004)
Atual
Java 8 (2014)
Permite construção
Tipos
Classes
Interfaces
Para funcionarem com objetos de vários tipos.
Métodos
Construções designadas
Genéricas
Exemplos
Tipos genéricos
Classes genéricas
Interfaces genéricas
Métodos genéricos
Nelson Freire (ISEP–DEI-PPROG 2014/15)
3/23
Noção de Genérico
Genéricos
2/2
Tipos e Métodos Genéricos
Têm um/mais parâmetros de tipo genérico
// genérico = não concreto ; Ex: tipo E
Funcionam como variáveis
// análogo aos parâmetros de métodos
Passagem de tipos … concretos
// Ex: tipo String
Exemplos
Exemplo
Classe
Genérica
Declaração ... com tipo(s) genérico(s)
public class ArrayList<E> ...
// E: parâmetro de tipo genérico
Uso ... com vários tipos referência
concretos
(Instâncias de tipo genérico)
ArrayList<Figura> f
ArrayList<Pessoa> p
// <...> parêntesis angulares
// Variável
Interface
Genérica
public interface Map<K,V>
Método
Genérico
public static void shuffle(List<?> list)
// K e V: parâmetros de tipo genérico
// Classe Collections
Map<Integer,String>
Map<Departamento,
List<Empregado> >
Collections.shuffle(f)
Collections.shuffle(p)
// ?: parâmetro de tipo genérico = qualquer tipo
Nelson Freire (ISEP–DEI-PPROG 2014/15)
4/23
Interesse dos Genéricos
Genéricos
1/2
Programação mais segura
Mais robusta
Figura
area()
Reduzir possibilidade de erros de execução
Devido a excessivos downcastings
Retangulo
area()
Problema
Exemplo
Circulo
area()
// Contentor que permite guardar objetos de qualquer tipo
List figuras = new ArrayList();
// Elementos tipo Object
// Preenchimento do contentor
figuras.add( new Circulo() );
figuras.add( new Rectangulo() );
figuras.add( new Pessoa() );
// Adicionado objeto não Figura
// Compilador aceita qualquer objeto
// Varrimento do contentor para mostrar áreas
for( Object obj : figuras )
System.out.println(((Figura) obj).area() );
Downcasting do objeto Pessoa provoca erro de execução
programação insegura
Nelson Freire (ISEP–DEI-PPROG 2014/15)
5/23
Interesse dos Genéricos
Genéricos
2/2
Programação mais segura
Solução
Exemplo
Usando tipo genérico ArrayList<E>
// Contentor para guardar apenas objetos tipo Figura
List<Figura> figuras = new ArrayList();
// Elementos tipo Figura
// Preenchimento do contentor
figuras.add( new Circulo() );
figuras.add( new Rectangulo() );
figuras.add( new Pessoa() );
// ERRO de COMPILAÇÃO
// Compilador só aceita objetos Figura
// Varrimento do contentor para mostrar áreas
for( Figura figura : figuras )
System.out.println( figura.area() );
Não há downcasting
programação segura
Figura
area()
Retangulo
area()
Nelson Freire (ISEP–DEI-PPROG 2014/15)
Circulo
area()
6/23
Tipo Parametrizado
Genéricos
1/2
Definição
Tipo obtido por instanciação do tipo genérico, substituindo os parâmetros de tipo genérico (ex: E)
por tipos referência concretos (ex: String)
Exemplo
Interface List genérica
Tipo Genérico
( Ex: List<E> )
instanciado
Tipo Parametrizado
( Ex: List<String> )
substituído
(Parâmetro Tipo Genérico)
public interface List<E> … {
(Parâmetro Tipo Concreto)
public interface List<String> … {
…
…
boolean add(E e);
boolean add(String e)
}
}
Instanciação de Tipo Genérico
Tipos Concretos
Só tipos referência
// tipos primitivos são ilegais
Nelson Freire (ISEP–DEI-PPROG 2014/15)
7/23
Tipo Parametrizado
Genéricos
2/2
Pode ser usado
Declarações
Variáveis … locais/atributos
Parâmetros … de métodos/construtores
Tipos de retorno … de métodos
public class DemoUsoTipoParametrizado {
…
private List<String> variavel;
…
public DemoUsoTipoParametrizado(List<String> lista){ … }
…
public void metodo1(List<Pessoa> lista){ … }
…
public List<String> metodo2(){
…
List<String> lista = new ArrayList();
…
}
}
Uso de Tipo Parametrizado
Nelson Freire (ISEP–DEI-PPROG 2014/15)
8/23
Implementação de Classe Genérica
Genéricos
Parâmetros de Tipo Genérico (1/2)
Declaração
A seguir ao nome da classe
Entre parêntesis angulares // < ... >
1/2
public class ArrayList<E> … {
…
public boolean add(E e){…}
}
Declaração de ArrayList Genérico
Especifica variáveis ... de instância
Uma por parâmetro de tipo genérico
Separadas por vírgulas
Nome de variáveis
Pode ser qualquer
Por convenção
Letra maiúscula
Nome de Variável
Tipo Genérico
public class HashMap<K,V> … {
…
public V put(K key, V value){…}
}
Declaração de HashMap Genérico
Significado
E
Tipo de elemento de uma coleção
K
Tipo key num mapa
V
Tipo value num mapa
T
Tipo genérico
S, U
Tipos genéricos adicionais
Convenção Java
Nelson Freire (ISEP–DEI-PPROG 2014/15)
9/23
Implementação de Classe Genérica
Genéricos
2/2
Parâmetros de Tipo Genérico (2/2)
Usados
Parâmetro de tipo genérico no cabeçalho da classe
Só contexto de instância
Ilegal em contexto estático
Atributos de instância
Variáveis estáticas
Construtores
Métodos estáticos
Classe internas estáticas
Tipos de Parâmetros
Corpo
Métodos de instância
Tipo de Parâmetro
Tipo de Retorno
Corpo
public class DemoClasseGenerica<T> {
…
private T variavel;
…
public DemoClasseGenerica(T obj){…}
…
public void metodo1(T obj){…}
Classes internas
public T metodo2(){…}
public T metodo3(T obj) {…}
Não-estáticas
…
private class classeInterna<T> … {…}
}
Exemplos de Uso de Parâmetro de Tipo Genérico
Nelson Freire (ISEP–DEI-PPROG 2014/15)
10/23
Implementação de Método Genérico
Genéricos
1/2
Método Genérico
Método com um/mais parâmetros de tipo genérico
Implementação de Método Genérico
Tipo de Classe
Tipo de Método
Instância
Classe Genérica
Classe Não-Genérica
(sem parâmetros de tipo genérico)
Nelson Freire (ISEP–DEI-PPROG 2014/15)
Parâmetros de Tipo Utilizáveis
Próprios
Cabeçalho da classe
Classe (estático)
Próprios
Instância
Próprios
Classe (estático)
Próprios
11/23
Implementação de Método Genérico
Genéricos
2/2
Método Genérico de Classe Não-Genérica
Especifica tipo genérico próprio
Declaração
Antes do tipo de retorno
Exemplo
Método de classe
public class Servicos {
…
public static <T> void
…
}
}
imprimir( T[] vetor ) {
Método que imprime qualquer tipo de vetor
Invocação
Chamada convencional
Exemplo
Servicos.imprimir( nomes );
// String[] nomes
Não é preciso … indicar o tipo concreto do parâmetro de tipo genérico
Compilador deduz o tipo referência concreto // tipos primitivos ilegais
Nelson Freire (ISEP–DEI-PPROG 2014/15)
12/23
Genéricos e Herança
Genéricos
1/2
Herança em Parâmetros de Tipo Concreto
Não implica herança de classes parametrizadas
Figura
area()
Exemplo
ArrayList<Figura> e ArrayList<Retangulo>
Não existe relação de herança entre arraylists
Retangulo
area()
Circulo
area()
Retangulo é subtipo de Figura
Parâmetros de tipo estão relacionados por herança
Não é possível:
ArrayList<Retangulo> listaRetangulos = new ArrayList();
ArrayList<Figuras> listaFiguras = listaRetangulos;
// Ilegal
Justificação
Caso contrário
Possível adicionar objetos de tipos não relacionados por herança a contentor
Exemplo
ArrayList<Figura> figuras = new ArrayList<>();
ArrayList<Retangulo> retangulos = new ArrayList<>();
...
figuras = retangulos;
// Se fosse legal ...
figuras.add( new Circulo() );
// ... era possível adicionar um circulo ... aos retangulos
Nelson Freire (ISEP–DEI-PPROG 2014/15)
13/23
Genéricos e Herança
Genéricos
2/2
Implicações da Limitação
Exemplo
public class MinhaLista<E> {
…
public MinhaLista(List<E> lista){…}
…
}
Tipo Parametrizado
MinhaLista<Figura>
Figura
area()
Parâmetro List<E>
Permite Passagem
Listas de tipo E
Retangulo
area()
Circulo
area()
Exemplo
new MinhaLista( new ArrayList<Figura>() )
Não Permite Passagem
Listas de subtipos/supertipos de E
Exemplo
new MinhaLista( new ArrayList<Circulo>() )
Ultrapassar Limitação
Tipos Wildcard
Nelson Freire (ISEP–DEI-PPROG 2014/15)
14/23
Tipos Wildcard
Genéricos
1/5
Interesse
Restringir os tipos concretos passados através de parâmetros genéricos
Tipos Wildcard
Nome
Sintaxe
Significado
Obs
Wildcard com restrição inferior
? extends B
Qualquer tipo/subtipo de B
(limitado ao tipo e subtipos de
B)
? = qualquer tipo
extends = tipo/subtipo
B = classe/interface
Wildcard com restrição superior
? super B
Qualquer tipo/supertipo de B
super = tipo/supertipo
Wildcard sem restrições
?
Qualquer tipo
Tipo Wildcard
Tipo desconhecido
// não é preciso conhecer tipo específico
Exemplo
public class ArrayList<E> … {
…
public ArrayList(Collection<? extends E> c) { … }
}
Construtor
Cria arraylist com elementos de c
Não precisa de saber ... tipo específico dos elementos de c
Permite elementos de c do tipo/subtipo de E
Nelson Freire (ISEP–DEI-PPROG 2014/15)
15/23
Tipos Wildcard
Genéricos
2/5
Wildcard com Restrição Inferior
Restrição inferior do tipo limitado ao tipo e subtipos
Nome
Sintaxe
Wildcard com restrição inferior
? extends B
Significado
Qualquer tipo/subtipo de B
Obs
? = qualquer tipo
extends = subtipo
B = classe/interface
Exemplo
public class ArrayList<E> … {
…
public ArrayList(Collection<? extends E> c) { … }
}
Construtor
Não precisa de saber tipo específico de elementos de c
Permite elementos de c do tipo/subtipo de E
Figura
Retangulo
Circulo
Exemplo - ArrayList<Figura>
List<Figura> listaFiguras = new ArrayList(listaCirculos);
List<Circulo> listaCirculos = new ArrayList();
...
List<Figura> listaFiguras = new ArrayList(listaRetangulos);
List<Retangulo> listaRetangulos = new ArrayList();
Nelson Freire (ISEP–DEI-PPROG 2014/15)
16/23
Tipos Wildcard
Genéricos
3/5
Wildcard com Restrição Superior
Restrição superior do tipo limitado ao tipo e supertipos
Nome
Sintaxe
Wildcard com restrição superior
? super B
Significado
Qualquer tipo/supertipo de B
Obs
? = qualquer tipo
super = supertipo
B = classe/interface
Exemplo
public class ArrayList<E> … {
…
public void sort(Comparator<? super E> c){ … }
}
Método sort
Não precisa de saber tipo específico de objetos comparáveis
Permite objeto Comparator de tipo/supertipo de E
Exemplo
Figura
ArrayList<Circulo>
Comparator<Circulo>
Retangulo
Circulo
Comparator<Figura>
Figura = supertipo de Circulo
Compara objetos tipo Figura Compara objetos tipo Circulo
Nelson Freire (ISEP–DEI-PPROG 2014/15)
17/23
Tipos Wildcard
Genéricos
4/5
Wildcard sem Restrição
Nome
Sintaxe
Significado
Wildcard sem restrições
?
Qualquer tipo
Exemplo
public class ArrayList<E> … {
…
public boolean removeAll(Collection<?> c)
}
Método removeAll
Remove todos elementos armazenados em c
Não precisa de saber tipo específico dos elementos de c
Permite elementos de c de qualquer tipo
Nota
Collection<Object>
Não equivalente a Collection<?>
Só permite coleção com elementos tipo Object
Nelson Freire (ISEP–DEI-PPROG 2014/15)
18/23
Tipos Wildcard
Genéricos
5/5
Tipos de Declarações de Restrições:
Um Tipo
Múltiplos Tipos
Declarações de Um Tipo
Exemplos
<?>
<? extends E>
<? super T>
Declarações de Múltiplos Tipos
Tipos ligados
Carater &
Exemplo
<? extends Comparable<E> & Measurable>
Nelson Freire (ISEP–DEI-PPROG 2014/15)
// tipos de interfaces
19/23
JVM Substitui Parâmetros de Tipo (Type Erasure)
Genéricos
1/2
Máquina Virtual do Java (JVM)
Não trabalha com
Tipos genéricos
Métodos genéricos
Razão
Genéricos mais recentes que a JVM
Substitui parâmetros de tipo
Por tipos não parametrizados
Pelo tipo
Object
// se não houver restrições
Da restrição
Exemplos
ArrayList<E>
E substituído por Object
ArrayList ... com elementos de tipo Object
// resulta numa classe normal
<E extends Measurable>
E substituído por Measurable
Problema
Introduz limitações nos genéricos
Nelson Freire (ISEP–DEI-PPROG 2014/15)
20/23
Genéricos
JVM Substitui Parâmetros de Tipo (Type Erasure)
2/2
Limitações
Impossível construir objetos de tipo genérico
Exemplos
new E()
// Se E substituído por Objet new Object() – nem sempre desejável
// Alternativa: ArrayList<E>
new E[20]
// Array de tipo genérico
Construção de array de tipo genérico
Limitação pode ser ultrapassada
Usando técnica Reflection
JVM
Guarda objeto Class
Por cada classe carregada
Objeto Class tem
Informação sobre uma classe
Métodos para construir novos objetos dessa classe
Dado um array a de tipo genérico
Class objCA = a.getClass();
// obter objeto Class do array
Class objCE = objCA.getComponentType(); // obter objeto Class elementos
Object[] novoArray = Array.newInstance(objCE, tamanho);
Nelson Freire (ISEP–DEI-PPROG 2014/15)
// criar array
21/23
Contexto Estático
Genéricos
Parâmetros de Tipo Genérico de uma Classe
São variáveis de instância
Não podem ser usados em contexto estático
Variáveis estáticas
Métodos estáticos
// alternativa: adicionar parâmetros de tipo genérico
Classes internas estáticas
// alternativa: adicionar parâmetros de tipo genérico
Nelson Freire (ISEP–DEI-PPROG 2014/15)
22/23
Genéricos
Bibliografia
Livro
Big Java, Late Objects
Cay S. Horstmann
2013
John Wiley & Sons
Tutorial
http://docs.oracle.com/javase/tutorial/java/generics/
Nelson Freire (ISEP–DEI-PPROG 2014/15)
23/23