Conceitos avançados de programação - INF

Propaganda
Especialização em web com interfaces
ricas
Conceitos avançados de programação
Prof. Fabrízzio Alphonsus A. M. N. Soares
[email protected] [email protected]
Instituto de Informática
Universidade Federal de Goiás
Aula 2
25 de maio de 2012
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
1/103
Conceitos avançados
Nesta aula conheceremos elementos interessantes para auxílio
na programação Java.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
2/103
Conceitos
Elementos que serão aprendidos nesta aula:
TypeCast e InstanceOf
Tipos genéricos (Generics)
Encaixotamento (Boxing) e Envelopadores (Wrappers)
Coleções, etc
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
3/103
TypeCast I
Quando lidamos com linguagens de programação fortemente
tipadas como Java, nos confrontamos muitas vezes com a necessidade de variar de um tipo de dado para outro.
Há casos, também, em que até mesmo o compilador não compreende que tipo de dado estamos atribuindo a uma variável.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
4/103
TypeCast II
Em Java, nós podemos fazer uso do que chamamos de indução
de tipo ou typecast.
O typecast dita ao compilador como tal dado deve ser interpretado e manipulado.
Essa indução de tipo ou typecast pode ser implícita ou explícita.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
5/103
TypeCast III
O typecast implícito é feito automaticamente pelo compilador
quando um tipo de dado pode ser facilmente manipulado no
lugar de outro tipo de dado.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
6/103
TypeCast IV
O typecast explícito é feito diretamente no algorítmo para indicar ao compilador qual a forma de interpretação de um dado
quando ele entende que há ambiguidade ou formatos incompatíveis.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
7/103
TypeCast V
O typecast explícito é dado sempre dentro de parênteses que
sempre vem antes do dado a ser induzido. Ex.: (int) var1,
(float) var2, (Object) var3, ...
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
8/103
TypeCast de Tipos Primitivos I
O typecast de dados primitivos é dado basicamente em questão
de seu consumo de memória. Se tentamos designar um tipo de
dado que consome menos memória para um que consome mais
memória, o typecast é realizado implicitamente.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
9/103
TypeCast de Tipos Primitivos II
No exemplo abaixo, atribuimos um dado inteiro (varInt) a uma
variável do tipo float (varFloat).
1
2
3
4
5
6
7
8
9
public class ExemploTypecast1 {
public static void main(String[] args) {
float varFloat;
int varInt;
varInt = 200;
varFloat = varInt;
System.out.println(varFloat);
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
10/103
TypeCast de Tipos Primitivos III
O contrário não se aplica. Tentar atribuir um tipo de dado
maior para um tipo de dado menor irá resultar em um erro de
tipos incompatíveis (type mismatch).
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
11/103
TypeCast de Tipos Primitivos IV
Para demonstrar isso, usaremos dois tipos de dados inteiros.
Porém, iremos atribuir um inteiro longo (que consome mais
memória) a um dado inteiro que consome menos. Nesse caso,
somos obrigados a usar typecast explícito.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
12/103
TypeCast de Tipos Primitivos V
1
2
3
4
5
6
7
8
9
public class ExemploTypecast2 {
public static void main(String[] args) {
long varLong;
int varInt;
varLong = 200;
varInt = (int) varLong;
System.out.println(varInt);
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
13/103
TypeCast de Classes e Objetos I
Typecast também pode ser usado em Classes e Objetos.
Sempre e uma classe for genérica, ela poderá receber qualquer
tipo de objeto que será feito o typecast implicitamente.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
14/103
TypeCast de Classes e Objetos II
Exemplo
Por exemplo, vamos utilizar a classe TV abaixo.
1
2
3
4
5
6
7
8
9
10
11
12
13
public class TV {
int tamanho;
int canal;
int volume;
boolean ligada;
public TV(int tamanho, int canal, int volume, boolean ligada
) {
this.tamanho = tamanho;
this.canal = canal;
this.volume = volume;
this.ligada = ligada;
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
15/103
TypeCast de Classes e Objetos III
Agora, vamos instanciar uma variável da classe genérica Object
com a classe TV.
1
2
3
4
5
6
7
8
public class ExemploTypecast3 {
public static void main(String[] args) {
Object obj = new TV(29, 1, 0, false);
System.out.println("A variável obj é "
+ obj.getClass());
}
}
Como podemos perceber, o resultado de getClass da variável
obj não é sua classe original (Object), mas sua instância: class
TV.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
16/103
TypeCast de Classes e Objetos IV
Agora, não será possível criar uma cópia desse objeto para uma
variável do mesmo tipo de sua instância. Neste caso, devemos
fazer o typecast explícito da classe.
1
2
3
4
5
6
7
8
9
10
11
public class ExemploTypecast4 {
public static void main(String[] args) {
Object obj = new TV(29, 1, 0, false);
TV tv = (TV) obj;
TV tv2 = new TV(29, 1, 0, false);
System.out.println("A variável tv é cópia de obj" +
"\nobj: " + obj.toString() +
"\ntv: " + tv.toString());
System.out.println("TV2 é outro objeto: " + tv2.toString
());
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
17/103
TypeCast de Classes e Objetos V
O resultado do código acima seria algo como:
1
2
3
4
A variável tv é cópia de obj
obj: TV@12345f
tv: TV@12345f
TV2 é outro objeto: TV@abcde1
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
18/103
InstanceOf I
No exemplo anterior, se tentássemos atribuir obj diretamente a
tv ocorreria um erro de tipos incompatíveis (type mismatch).
Quando lidamos com classes, podemos testar qual seu tipo de
instancia usando o operador instanceof.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
19/103
InstanceOf II
Instanceof indica se um objeto (já instanciado) pertence a uma
classe.
O uso de instanceof é: objeto instanceof nomeDaClasse.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
20/103
InstanceOf III
Para melhorar o exemplo anterior, usaremos instanceof antes de
atribuirmos obj a tv.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ExemploTypecast {
public static void main(String[] args) {
Object obj = new TV(29, 1, 0, false);
TV tv = null;
if (obj instanceof TV) {
tv = (TV) obj;
}
TV tv2 = new TV(29, 1, 0, false);
System.out.println("A variável tv é cópia de obj" +
"\nobj: " + obj.toString() +
"\ntv: " + tv.toString());
System.out.println("TV2 é outro objeto: " + tv2.toString
());
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
21/103
Tipos Genéricos I
O que são tipos genéricos?
Generics, ou programação genérica, serve para determinar para
o compilador, qual tipo de classe deve ser interpretada.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
22/103
Tipos Genéricos II
Por exemplo, vamos imaginar que será criada uma classe chamada Aparelho que irá conter um objeto de alguma outra classe.
Para que essa classe possa aceitar qualquer tipo de classe, devemos fazer uso de generics.
Generics é indicado como um identificador entre os sinais de
maior e menor < > .
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
23/103
Criar classes usando generics I
Para criar uma classe usando generics, basta que logo após o
nome da classe coloquemos o indicador genérico. Esse indicador genérico é simplesmente uma letra na qual será substituída
dentro da classe no momento da execução.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
24/103
Criar classes usando generics II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Aparelho <T> {
T objeto;
public Aparelho(T objeto) {
this.objeto = objeto;
}
public T getObjeto() {
return objeto;
}
public void setObjeto(T objeto) {
this.objeto = objeto;
}
}
Como a letra T identifica um tipo genérico, ela será substituída
por qualquer classe.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
25/103
Criar classes usando generics III
Vamos imaginar agora que temos duas classes distintas. A classe
TV:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TV {
int tamanho;
int canal;
int volume;
boolean ligada;
public TV(int tamanho, int canal, int volume, boolean ligada
) {
this.tamanho = tamanho;
this.canal = canal;
this.volume = volume;
this.ligada = ligada;
}
// métodos get e set
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
26/103
Criar classes usando generics IV
E a classe radio:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Radio {
public static int AM = 1;
public static int FM = 2;
private float frequencia;
private int volume;
private int banda;
public Radio(float frequencia, int volume, int banda) {
this.frequencia = frequencia;
this.volume = volume;
this.banda = banda;
}
// métodos get e set
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
27/103
Instanciar uma classe genérica I
Se fossemos criar um programa que usa as duas classes de aparelhos acima, faríamos:
1
2
3
4
5
6
7
8
public class MinhaClasse {
public static void main(String[] args) {
Aparelho<TV> aparelho1 = new Aparelho<TV>(new TV(29, 0,
0, false));
Aparelho<Radio> aparelho2 = new Aparelho<Radio>(new
Radio(88.1f, 0, Radio.FM));
System.out.println(aparelho1.getObjeto().getClass());
System.out.println(aparelho2.getObjeto().getClass());
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
28/103
Instanciar uma classe genérica II
Perceba o seguinte: sem o uso de generics, o compilador não
conseguiria saber qual a diferença entre aparelho1 e aparelho2,
pois ele os trataria da mesma forma. Nesse caso, seria obrigatório o uso de typecast para determinar ao compilador que dado
está sendo processado.
Se pensarmos em uma aplicação muito grande, além de ficar
cansativo ter que usar typecast toda vez que fossemos usar
um aparelho, seria muito provável que erraríamos em algum
momento.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
29/103
Instanciar uma classe genérica III
Java usa uma pequena convenção de nomenclatura para as letras de identificação de generics (que são vastamente utilizadas
no Framework de coleções Java), sendo:
E Elemento
K Chave
N Número
T Tipo
V Valor
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
30/103
Generics é um assunto bastante extenso com vários tópicos
que podem ser abordados, dentre os quais podemos citar:
Multiplos tipos genéricos. Ex.: <T, E, N>;
Tipos genéricos limitados. Ex.: <U extends Number>;
Wildcards;
e Subtipos;
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
31/103
Exemplo mais robusto I
Iremos criar duas classes, a primeira “Obj” contém dois métodos
(add e get) que recebem e retornam um tipo “Integer”.
1
2
3
4
5
6
7
8
9
10
11
public class Obj {
private Integer i;
public void add(Integer i){
this.i = i;
}
public Integer get(){
return this.i;
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
31/103
Exemplo mais robusto II
A segunda classe utiliza a classe Obj para “guardar” um objeto:
1
2
3
4
5
6
7
8
9
10
11
public class UsaObj {
public static void main(String[] args) {
Obj integerObj = new Obj();
integerObj.add(new Integer(10));
Integer someInteger = (Integer)integerObj.get();
System.out.println(someInteger);
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
32/103
Exemplo mais robusto III
O exemplo abaixo irá causar erro:
1
2
3
4
5
6
7
8
9
10
11
public class UsaObj {
public static void main(String[] args) {
Obj stringObj = new Obj();
stringObj.add("Teste");
String someString = (String)stringObj.get();
System.out.println(someString);
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
33/103
Exemplo mais robusto IV
No caso acima, somente é possível colocar em Obj um objeto
do tipo Integer, agora veremos como tipos genéricos pode nos
ajudar quando queremos colocar um Integer ou uma String na
classe Obj por exemplo. Vamos recriar o cenário anterior com
a utilização de tipos genéricos.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
34/103
Usando Generics I
Veja que agora o tipo de objeto que será armazenado é representado pela letra T, que também deverá ser informado quando
uma instância de Obj for criada.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
35/103
Usando Generics II
1
2
3
4
5
6
7
8
9
10
11
public class ObjGen<T>{
private T t; // T é o tipo do objeto
public void add(T t){
this.t = t;
}
public T get(){
return this.t;
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
36/103
Usando Generics III
Agora vamos criar uma classe que utiliza a classe ObjGen.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class UsaObjGen {
public static void main(String[] args) {
ObjGen<Integer> integerObj = new ObjGen<Integer>();
integerObj.add(new Integer(10));
Integer someInteger = (Integer)integerObj.get();
System.out.println(someInteger);
ObjGen<String> stringObj = new ObjGen<String>();
stringObj.add("Teste");
String someString = (String)stringObj.get();
System.out.println(someString);
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
37/103
Generics como tipo mínimo I
Podemos utilizar um “tipo mínimo” para garantir um tipo obrigatório quando criamos classes genéricas.
1
2
3
4
5
6
public class ObjMin <T extends Runnable> {
void inicia(T t){
new Thread(t).start();
}
}
Aqui estamos definindo que o tipo do objeto (T) deve ser no
mínino um “Runnable”.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
38/103
Generics como tipo mínimo II
Criaremos agora uma classe chamada Programa que implementa
Runnable e utiliza o ObjMin.
1
2
3
4
5
6
7
8
9
10
11
12
public class Programa implements Runnable {
public static void main(String[] args){
ObjMin<Programa> o = new ObjMin<Programa>();
o.inicia(new Programa());
}
public void run(){
System.out.println("ola");
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
39/103
Boxing, Unboxing e Autoboxing I
O que é boxing?
Em certas situações, é mais conveniente utilizar objetos no lugar
de tipos primitivos (byte, short, int, long, float, double, boolean
e char).
Assim, para cada tipo primitivo, foi criado uma classe Wrapper
(Byte, Short, Integer, Long, Float, Double, Boolean e Character) que serve para “encaixotar” (boxing) o tipo primitivo.
Boxing consiste em inserir um tipo primitivo dentro de um objeto, de forma que o valor primitivo possa ser usado como um
objeto.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
40/103
Boxing, Unboxing e Autoboxing II
Vejamos este Exemplo:
1
Integer i = new Integer(100);
Vemos neste exemplo que o tipo primitivo int de valor ’100’ é
inserido no construtor de Integer, que é a classe wrapper (empacotadora) associada.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
41/103
Wrappers I
Tabela de Tipos primitivos e Classes Wrappers
Lógico
Caractere
Inteiro
Inteiro
Inteiro
Inteiro
Ponto Flutuante
Ponto Flutuante
Tipo primitivo
boolean
char
byte
short
int
long
float
double
Classe Wrapper
Boolean
Character
Byte
Short
Integer
Long
Float
Double
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
Super Classe
Object
Object
Number
Number
Number
Number
Number
Number
42/103
Wrappers II
Classes Wrappers possuem métodos públicos disponíveis na subclasse Object, devemos dar um maior destaque para os métodos
equals(Object) e toString, o primeiro é utilizado para comparações enquanto que o segundo permite que o conteúdo de um
objeto seja representado em formato de texto.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
43/103
Wrappers III
Classes derivadas da subclasse Number possuem vários métodos para devolverem um tipo primitivo, tais como: byteValue(),
shortValue(), intValue(), longValue(), doubleValue(), floatValue().
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
44/103
Wrappers IV
Alem disso a as classes derivadas de Number possuem também
o método comparareTo(Object) que faz comparações entre objetos wrapper.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
45/103
Quais as vantagens de usar tipos
primitivos? I
Tipos primitivos são bem rápidos
Consomem pouca memória
Além de permitirem operações mais complexas
São bastantes eficientes em laços e expressões
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
46/103
Usando Wrappers I
Para criar objetos Integer ,Double , etc.
Basta apenas chamar :
1
2
Integer i = new Integer();
Double d = new Double();
Para fazer obter uma valor encapsulado basta apenas:
1
2
float f = real.FloatValue();
double d = inteiro.doubleValue();
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
47/103
Autoboxing I
A criação das classes wrapper resolveram vários problemas, porém a conversão entre tipo primitivo para objeto (boxing) e
objeto para primitivo (unboxing) se tornou uma tarefa trivial e
tediosa. A solução surgiu a partir do JDK 1.5.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
48/103
Autoboxing II
A Sun resolveu este problema através do autoboxing, que consiste no boxing automático, ou seja, na conversão automática
pelo compilador de tipo primitivo para objeto.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
49/103
Autoboxing III
Além do autoboxing, existe o autounboxing, que é a conversão automática de objeto para tipo primitivo. Assim, fecha-se
o ciclo: a conversão de tipo primitivo para tipo wrapper é automática (autoboxing) e o retorno também é automático (autounboxing), facilitando o uso de um e outro, como se fossem
equivalentes.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
50/103
Autoboxing IV
Vejamos o exemplo:
1
2
3
4
5
6
7
8
9
10
11
12
public class TesteAutoboxing {
public static void main(String[] args) {
Integer a = 2; // autoboxing
Integer b = 2; // equivale a Integer b = new Integer(2);
a++; // autounboxing e autoboxing
b++; // autounboxing e autoboxing
// int x = a.intValue(); // para jdk < 1.5, isto era
necessário
// int y = b.intValue();
// System.out.println(x+y); // a linha abaixo é equivalente
a esta
System.out.println(a+b);
// graças a autounboxing
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
51/103
Autoboxing V
Note neste exemplo:
O compilador ’sabe’ que a atribuição ’Integer a = 2’ são
de tipos diferentes, por isso é necessário autoboxing - a
conversão implícita pelo compilador de int para Integer.
A soma de objetos não é definida, por isso ’a’ e ’b’ são
convertidos implicitamente pelo compilador para int;
Em geral, o código-fonte fica mais curto e operações de
conversões triviais são criadas implicitamente pelo
compilador.
Você pode utilizar os operadores de incremento em
objetos, como se fossem tipos primitivos;
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
52/103
Exemplos de Autoboxing I
Autoboxing ou autounboxing ocorre sempre que houver a necessidade de conversão de tipos primitivos em objetos e vice-versa.
Isto se aplica em várias situações [3]: comparação, atribuição,
em estruturas de repetição, etc. Veremos a seguir um exemplo
de cada situação.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
53/103
Autoboxing em atribuição I
Veja no exemplo abaixo a utilização de autoboxing e autounboxing na atribuição de variáveis e passagem de parâmetros para
métodos:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class AutoboxingEmAtribuicao {
private static double soma(double x, double y) { //
autounboxing
return x+y;
}
public static void main(String[] args) {
Double a = 1.0; //autoboxing
Double b = 1.0; // autoboxing
Double resultado = soma(a,b); // autounboxing
Boolean imprimir = true; ///autoboxing
if (imprimir) // autounboxing
System.out.println("resultado: "+resultado); //autounboxing
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
54/103
Autoboxing em atribuição II
Note a atuação do autoboxing/autounboxing neste exemplo:
Na atribuição de valores double para tipos objeto Double;
Na passagens de parâmetros do método soma. Note que
o método soma recebe como parâmetros dois tipos
primitivos double e foram passados dois objetos Double
’a’ e ’b’.
Na atribuição do valor booleano ’true’ à variável do tipo
objeto Boolean;
No uso de um tipo objeto Boolean na condição do ’if’;
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
55/103
Autoboxing em comparação I
Comparações podem ser realizadas através do operador ’==’
ou pelo método ’equals’; o primeiro, quando é aplicado entre
objetos, compara se as variáveis referenciam o mesmo objeto,
enquanto que o segundo avalia se os objetos possuem o valor
significativamente iguais.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
56/103
Autoboxing em comparação II
Veremos no código-fonte de exemplo a seguir, que as comparações entre tipos diferentes podem ser realizadas:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class AutoboxingEmComparacao {
public static void main(String[] args) {
Integer a = new Integer(2);
Integer b = new Integer(2);;
int c = 2;
// compara se a e b referenciam o mesmo objeto:
if (a == b)
System.out.println("Comparação 1: a e b são os mesmos
objetos");
// compara se a e b possuem o mesmo valor:
if (a.equals(b))
System.out.println("Comparação 2: a e b tem valores iguais")
;
// a é convertido para tipo primitivo
// os dois valores são comparados como tipos primitivos
if (a == c)
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
57/103
Autoboxing em comparação III
17
System.out.println("Comparação 3: a e c tem valores iguais")
;
18
19
20
21
22
23
24
// c é convertido para objeto
// os dois valores são comparados como objetos
if (a.equals(c))
System.out.println("Comparação 4: a e c tem valores iguais")
;
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
58/103
Autoboxing em comparação IV
Note a atuação do autoboxing/autounboxing neste exemplo:
Na comparação entre tipos diferentes (objeto e tipo
primitivo);
No comportamento diferente na comparação com ’==’
ou ’equals’;
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
59/103
Autoboxing em laço de repetição for I
A partir do jdk 1.5, surgiu uma melhoria na estrutura de repetição for, chamado de ’for melhorado’ ou ’enhanced for’. Através
do novo for, é possível percorrer toda uma array ou conjunto
(veremos mais detalhadamente sobre isso depois) de forma bem
fácil, sem necessitar criar contadores ou índices.
1
for (Tipo item: array_ou_conjunto)...
Onde:
Tipo - é uma classe ou algum tipo primitivo;
item - é a variável que receberá um elemento do array ou
conjunto em cada iteração (loop);
array_ou_conjunto - é uma array ou conjunto contendo
vários elementos;
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
60/103
Autoboxing em laço de repetição for II
Veremos o uso do ’for melhorado’ neste exemplo a seguir. Note
que iremos percorrer uma array de tipos primitivos char e uma
array (objeto) de inteiros (Integer):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import java.util.ArrayList;
public class AutoboxingEmRepeticaoFor {
public static void main(String[] args) {
char[] ola = {’o’, ’l’, ’a’};
// percorre a array ola
for (Character letra: ola) // autoboxing
System.out.println(letra);
// esta é um array com vários elementos inteiros;
// veremos esta sintaxe quando for estudado "Genericos"
ArrayList<Integer> numerospares = new ArrayList<Integer>();
// inclui objetos inteiros no array
numerospares.add(new Integer(2));
numerospares.add(new Integer(4));
numerospares.add(new Integer(6));
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
61/103
Autoboxing em laço de repetição for III
17
18
19
20
21
22
23
numerospares.add(new Integer(8));
// realiza o autounboxing de cada elemento Integer
for (int i: numerospares)
System.out.println(i);
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
62/103
Autoboxing em laço de repetição for IV
Note neste exemplo:
O for melhorado percorre a array de tipos primitivos char,
realizando o autoboxing de cada um de seus elementos,
atribuindo a variável ’letra’, que é do tipo objeto
Character;
A sintaxe ArrayList<Integer> numerospares = new
ArrayList<Integer>(), tem o seguinte significado: crie
uma array de objetos Integer, associando à varíavel
numerospares, que por sua vez é uma ’array de Integer’;
O for melhorado percorre a array de Integer, realizando o
autounboxing de cada um de seus elementos, atribuindo a
variável ’i’, que é do tipo primitivo int;
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
63/103
Coleções I
Um dos conceitos mais difundidos entre todas as linguagens de
programação é o conceito de array.
Embora seja a base de muita coisa nem sempre trabalhar com
arrays diretamente é uma boa ideia.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
64/103
Coleções II
O Java Collections Framework é um conjunto de classes desenhados para superar as limitações dos arrays e aumentar a
capacidade do programador para trabalhar com coleções de objetos.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
65/103
Coleções III
Com classes de alto nível como estas é possível implementar
padrões como Produtor-Consumidor sem esforço. Ou escolher
a implementação mais eficiente sem a implementar.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
66/103
Sobre Arrays I
Um array, em java, é um objeto que agrega outros objetos que
compartilham um supertipo comum e aos quais nos podemos
referir por um índice (ou seja, um numero inteiro).
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
67/103
Sobre Arrays II
Arrays em java são imutáveis o que significa que para criar
um array menor ou maior baseando-nos num que já existe é
necessário criar um novo array e fazer uma cópia, elemento a
elemento do antigo para o novo.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
68/103
Sobre Arrays III
Arrays são muito uteis para substituir condições de seleção,
como vemos no exemplo a seguir:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// sem array
public String getDayOfWeek(int weekDayOrdinal){
switch(weekDayOrdinal){
case 1: return "Domingo";
case 2: return "Segunda-Feira";
case 3: return "Terça-Feira";
case 4: return "Quarta-Feira";
case 5: return "Quinta-Feira";
case 6: return "Sexta-Feira";
case 7: return "Sábado";
}
}
// com array
public String getDayOfWeek(int weekDayOrdinal){
return WEEK_DAY_NAMES[weekDayOrdinal-1];
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
69/103
Sobre Arrays IV
Esta é uma situação simples que pode não parecer muito vantajosa ainda para mais quando seria necessário inicializar o array
( embora, essa inicialização seria feita apenas uma vez em toda
a vida do programa).
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
70/103
Sobre Arrays V
A razão para que o Array seja um objeto pouco maleável é de
eficiência. Mas java oferece um recurso muito mais poderoso
que permite ao programador não usar arrays se não quiser : o
Java Collections Framework (JCF).
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
71/103
Java Collections Framework I
O Java Collections Framework é um conjunto de interfaces e
classes que permitem uma vasta gama de opções na hora de
trabalhar com agregações de objetos. A recente (Java 5) introdução de tipos genéricos e de coleções desenhadas para ambientes concorrentes não devem deixar dúvidas a ninguem, que
em Java, usar arrays não é o padrão a seguir.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
72/103
Java Collections Framework II
Os algoritmos existentes relativos a coleções são amplamente
divulgados e estudados. A eficiência é a prioridade ao trabalhar
com grandes coleções de objetos. Por esse motivo, o JCF é
bastante flexível e vasto. Esses algoritmos são tão importantes
que obrigam todos os objetos a seguir contratos bem definidos.
O primeiro e mais importante deles é o contrato de definição de
igualdade.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
73/103
Definindo igualdade com equals I
Em Java o operador de igualdade == não determina se os objetos são iguais, apenas se as variáveis de referencia a eles são
iguais. Duas variáveis de referencia a objetos podem referenciar
objetos iguais ou não.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
74/103
Definindo igualdade com equals II
Para resolver o problema todos os objetos em Java definem o
método equals(). Este método é definido em Object - a classe
mãe de todas as classes - e como tal o método é onipresente na
linguagem.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
75/103
Definindo igualdade com equals III
Por padrão, este método apenas verifica se as referências dos
objetos são iguais. Ou seja, por padrão, um objeto só é igual
a outro se a variável de referencia é a mesma. Isso garante
que objeto quando igual tem as mesma características, mas
muitas vezes necessitamos que a igualdade seja determinada
pelas características em si e não pela referência do objeto.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
76/103
Definindo igualdade com equals IV
Para conseguirmos isso basta sobre-escrever o método equals()
no nosso objeto. Para fazermos isso temos que seguir algumas
regras:
1
2
3
4
O resultado de invocar equals() para os mesmos dois
objetos, sempre retorna o mesmo resultado
independentemente de quando essa invocação é feita.
null nunca é igual a nenhum objecto
Um objeto é igual a si próprio. Ou seja, a.equals(a) tem
que ser verdade.
A ordem da invocação para dois objetos não importa. Se
a.equals(b) é verdade então também tem que ser verdade
que b.equals(a)
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
77/103
Definindo igualdade com equals V
5
Se a.equals(b) e b.equals(c) são verdade então também
tem que ser verdade que a.equals(c)
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
78/103
Definindo igualdade com equals VI
Esta regras traduzem as propriedades do método equals(). Se
o método não tem estas propriedades ele não está bem implementado. A saber:
1
equals() é Consistente
2
e é consistente com null
3
equals() é Reflexivo
4
equals() é Simétrico
5
equals() é Transitivo
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
79/103
HashCode I
Hash é um código desenvolvido em criptografia. Função de
Hash é um mecanismo que baseado numa entrada produz um
código de hash (hashCode). Funções de Hash não são reversiveis e sempre produzem o mesmo resultado para a mesma
entrada. Contudo não são obrigadas a produzirem códigos diferentes para entradas diferentes ( ou seja, não são injetivas).
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
80/103
HashCode II
Por outro lado, funções de hash produzem códigos do mesmo
tamanho para entradas de tamanhos aleatoriamente diferentes.
Estas propriedades são extremamente uteis já que pela simples
comparação do código de hash poderemos saber se dois objetos
são diferentes. Atenção para o fato que elas não revelam se
os objetos são iguais, mas na maioria dos casos ser diferente é
mais importante que ser igual.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
81/103
HashCode III
Sabendo disto, à semelhança de equals() Object também define o método hashCode() que não é mais que uma função de
hash aplicada ao próprio objeto. É fácil de compreender que
se alteramos o mecanismo padrão de verificação de igualdade,
temos também que alterar o mecanismo padrão de produção do
código de hash.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
82/103
HashCode IV
Isso nos leva à regra de consistência que diz que: Sempre que
sobrescrever equals() sobrescreva também hashCode() de forma
compatível. De forma compatível significa que : Se a.equals(b)
é verdade então também é verdade que a.hashCode()==b.hashcode()
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
83/103
HashCode V
Existem muitas formas de redefinir o calculo do código de hash.
Da mais simples e com pior performance que é fazer todos os
objetos terem o mesmo código até à mais complexa de deixar
todos os objetos terem um código diferente.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
84/103
HashCode VI
Embora seja teoricamente possível ter uma função de hash tão
eficiente que produz um código diferente para cada objeto diferente, na prática nos encontramos limitados já que o código
tem que caber num int (32 bits).
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
85/103
HashCode VII
Então temos que vier com fato que nossas funções de hash vão
produzir código iguais em algum ponto. A isso se chama Colisão
de Hash. O objetivo é diminuir as colisões, ou seja diminuir a
frequencia com que dois objetos diferentes produzem o mesmo
código de hash. Quanto menos colisões, mais eficiente é a nossa
função de hash.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
86/103
HashCode VIII
A função de hash mais simples é a operação de ou-exclusivo
(XOR) que em Java se representa pelo operador .̂
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
87/103
Coleções e Mapas I
São classes voltadas para estruturas de dados,
pertencentes ao pacote java.util:
Conjuntos
Conjuntos
ordenados
Mapas
Mapas Ordenados e
listas.
É largamente utilizado em programas: quem não precisa
de um vetor, uma lista ou conjunto?
Melhora a performance e a qualidade: evita ’reinventar’ a
roda;
Estimula o reuso;
São conhecidos também como conjuntos;
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
88/103
Organização em Interfaces e Classes I
O conjunto de classes java para coleções (Java Collection Framework) é composto de várias interfaces (I), e classes concretas
(C). A seguir mostramos estas classes no formato hierárquico
em árvore:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Collection (I)
Set (I)
HashSet (C)
Sorted Set (I)
TreeSet(C)
List (I)
ArrayList (C)
Vector (C)
LinkedList (C)
Queue (I)
...
Map (I)
HashMap (C)
Hashtable (C)
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
89/103
Organização em Interfaces e Classes II
15
16
SortedMap (I)
TreeMap (C)
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
90/103
Definindo cada uma das implementações
I
1
Coleções
Collection: interface que define operações comuns de
coleções. Esta interface possui duas sub-interfaces - Set
(Conjunto) e List (Lista);
2
Conjuntos
Set: implementação de Collection, que modela um
conjunto de elementos únicos;
HashSet: implementação de Set, modela conjuntos não
ordenados;
SortedSet: implementação de Set, modela conjuntos
ordenados;
3
Listas
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
91/103
Definindo cada uma das implementações
II
List: modela listas de dados, onde os elementos
(repetidos ou não) estão ordenados;
ArrayList: usa métodos não-sincronizados e Vector utiliza
métodos sincronizados (synchronized)
Vector: é apropriado para uso em multithread, porém é
mais lento que ArrayList;
LinkedList: é uma Lista, onde os elementos estão
ligados. Tem uma inserção e deleção muito mais rápidos
que ArrayList e Vector.
4
Mapas
Map: modela mapeamentos entre chaves não-repetidas a
valores;
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
92/103
Definindo cada uma das implementações
III
HashMap: subclasse de Map, modela mapas não
classificados, com métodos não-sincronizados;
Hashtable: subclasse de Map, modela mapas não
classificados, com métodos sincronizados;
SortedMap: modela mapas classificados;
5
Filas
Queue: é uma interface, que modela filas,
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
93/103
Definindo cada uma das implementações
IV
Não confunda array (criados com []) com as classes ArrayList
ou Vector!
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
94/103
Exemplo comparativo entre array e
ArrayList I
Veja a tabela comparativa
array
não tem dimensão dinâmica
suporta tipos primitivos
não é uma classe
não suporta métodos
possui atributo length
ArrayList
tem dimensão dinâmica
não suporta tipos primitivos diretamente
é uma classe
suporta métodos
não possui atributo length
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
95/103
Exemplo comparativo entre array e
ArrayList II
Veja o exemplo abaixo, comparando array e ArrayList:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import java.util.ArrayList;
public class ComparandoArrayEArrayList {
public static void main(String[] args) {
// inicialização:
String[] ola1 = new String[3];
ArrayList<String> ola2 = new ArrayList<String>();
// atribuição
ola1[0] = "o"; ola1[1] = "l"; ola1[2] = "a";
ola2.add("o"); ola2.add("l"); ola2.add("a"); ola2.add("!");
// percorrendo com for
for (String s: ola1)
System.out.print(s);
System.out.println();
for (String s: ola2)
System.out.print(s);
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
96/103
Exemplo comparativo entre array e
ArrayList III
18
19
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
97/103
Interface Collection I
A interface Collection define várias operações básicas e operações entre coleções. Vejamos sua implementação:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public interface Collection<E> extends Iterable<E> {
// Operações Básicas
int size();
boolean isEmpty();
boolean contains(Object element);
boolean add(E element);
boolean remove(Object element);
Iterator<E> iterator();
// Operações em massa
boolean containsAll(Collection<?> c);
boolean addAll(Collection<? extends E> c);
boolean removeAll(Collection<?> c);
boolean retainAll(Collection<?> c);
void clear();
// Operações de array
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
98/103
Interface Collection II
18
19
20
Object[] toArray();
<T> T[] toArray(T[] a);
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
99/103
Interface Iterator I
Uma interface bastante importante é a interface Iterator, que
permite navegar (iterar) pelos vários elementos de uma coleção.
1
2
3
4
5
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
Note que a interface Iterator é bastante simples, um Iterator é
obtido da própria coleção através do método iterator() e depois
podemos navegar pela coleção por meio dos métodos hasNext(),
next() e remove();
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
100/103
Exemplo simples I
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import java.util.*;
public class TesteArray {
public static void main(String[] args) {
ArrayList<String> a1 = new ArrayList<String>();
ArrayList<String> a2 = new ArrayList<String>();
a1.add("a");
a1.add("b");
a1.add("c");
a2.add("d");
a2.add("e");
a2.add("f");
Iterator i1 = a1.iterator();
Iterator i2 = a2.iterator();
// imprime a1
while (i1.hasNext()) {
System.out.println(i1.next());
}
// imprime a2
while (i2.hasNext()) {
System.out.println(i2.next());
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
101/103
Exemplo simples II
21
22
23
}
}
}
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
102/103
Exercício
1
2
Criando somente uma instância auxiliar de ArrayList,
adicione os elementos de a2 em a1, de forma mesclada,
ou seja, seu resultado final deverá ser: a, d, b, e, c, f.
Imprima o novo a1 resultante.
Sem criar novas instâncias de ArrayList, adicione os
elementos de a1 no final de a2 e imprima o novo a2
resultante.
Prof. Fabrízzio Alphonsus A. M. N. Soares | Conceitos avançados de programação
103/103
Download