Você está na página 1de 188

Java

A Linguagem

Igor Borlot Borba


Igor@igorborba.com.br
Objetivos

 Apresentar os conceitos de orientação a objetos, suas


vantagens em relação ao paradigma procedural,
conduzindo os participantes a pensar em seus projetos
sobre esse paradigma.
 Apresentar a linguagem JAVA, ensinando os seus conceitos,
suas vantagens, as boas práticas de programação e
convenções de códigos utilizadas.
 Utilizar a plataforma Netbeans como IDE, mostrando suas
características e facilidades para utilizar qualquer outra
biblioteca disponível, baseando-se na sua API.
2
Agenda

 O que é Java?
 Variáveis primitivas
 Controle de fluxo
 Orientação a objetos
 Arrays
 Modificadores de acesso

3
Agenda

 Enumerados
 Controlando os Erros com Exceções
 O pacote java.lang
 A API de Coleções
 O pacote java.io
 Threads

4
Agenda

O que é Java?

5
O que é Java?

 Java é uma linguagem de programação e uma


plataforma de computação lançada pela
primeira vez pela Sun Microsystems em 1995.
 É a tecnologia que capacita muitos programas
da mais alta qualidade, como utilitários, jogos e
aplicativos corporativos, entre muitos outros, por
exemplo.
6
O que é Java?

 O Java é executado em mais de 850 milhões

de computadores pessoais e
em bilhões de dispositivos
em todo o mundo, inclusive
telefones celulares e
dispositivos de televisão.

7
O que é Java?

8
O que é Java?

 Palavras reservadas pelo compilador Java:

9
O que é Java?

 Convenções de Código
 Classes e Interfaces
▪ Devem começar com a primeira letra maiúscula.
▪ Exemplos: Coil, Slab, SlabFurnace.
 Métodos
▪ Devem começar com a primeira letra minúscula.
▪ Exemplos: getSlab, setCoil, processSlab.

10
O que é Java?

 Convenções de Código
 Variáveis
▪ Devem começar com a primeira letra minúscula.
▪ Exemplos: coil, slab, slabCode.
 Constantes
▪ Devem começar com TODAS as letras maiúsculas.
▪ Exemplos: SLAB_WIDTH, COIL_MAX_WITH.

11
O que é Java?

 Comentários em Java:

 /* */  Comentário em bloco;
 //  Comentário em linha;
 /** */  Comentário de Javadoc.

Javadoc  é o recurso de
documentação do Java.
12
O que é Java?

 Como é executada uma aplicação em Java?

13
Agenda

Variáveis primitivas

14
Variáveis primitivas

 Dentro de um bloco podemos declarar variáveis e usá-


las.
 Em Java, toda variável tem um tipo que não pode
ser mudado, uma vez que declarado:

tipoDaVariavel nomeDaVariavel;

int idade;
idade = 15;
15
Variáveis primitivas

 Boolean: Não é um valor numérico, só


admite os valores true ou false.
 Char: Usa o código UNICODE e cada

caractere ocupa 16 bits.

16
Variáveis primitivas

 Inteiros:
Diferem nas precisões e podem ser
positivos ou negativos.
 Byte: 1 byte.
 Short: 2 bytes.
 Int: 4 bytes.
 Long: 8 bytes.

17
Variáveis primitivas

 Reais em ponto flutuante: igual ao inteiros


também diferem nas precisões e podem ser
positivos ou negativos.
 Float: 4 bytes.
 Double: 8 bytes.

18
Variáveis primitivas

 Momento de reflexão:
 Isto funciona?
▪ int valor = 10;
▪ short valor2 = valor;

 Isto funciona?
▪ float valor = 10;
▪ double valor2 = valor;

19
Variáveis primitivas

 Casting e promoção:
 Precisamos que um número quebrado seja
arredondado e armazenado num número inteiro.
 Para fazer isso sem que haja erro de compilação, é
preciso dizer ao programa que o número
quebrado seja moldado (casted) como um
número inteiro.
 Esse processo recebe o nome de casting.
20
Variáveis primitivas

 Exemplos de casting:
▪ int valor = 10;
▪ short valor2 = (short)valor;

 Exemplos de promoção: Conversão Explícita

▪ float valor = 10;


▪ double valor2 = valor;

Conversão Implícita

21
Variáveis primitivas

 Valor padrão de cada tipo:

22
Variáveis primitivas

23
Variáveis primitivas

 Vamos apreciar as variáveis?!

24
Agenda

Controle de Fluxo

25
Controle de Fluxo

 É a habilidade de ajustar a maneira como um programa realiza


suas tarefas.
 Por meio de instruções especiais, chamadas comandos, essas
tarefas podem ser executadas seletivamente, repetidamente ou
excepcionalmente.
 Se não fosse o controle de fluxo, um programa poderia executar
apenas uma única seqüência de tarefas, perdendo completamente
uma das características mais interessantes da programação: a
dinâmica.
26
Controle de Fluxo

 Podemos classificar os comandos aceitos pela


linguagem Java em basicamente quatro categorias:
Comando Palavras-Chave
Tomada de decisões if-else, switch-case
Laços ou repetições for, while, do-while
Apontamento e tratamento try-catch-finally, throw
de exceções
Outros break, continue, label:,
return

27
Controle de Fluxo

 if-else

if ([condição]) {
[comando] // Executado se a condição for aceita.
}

if ([condição 1])
[comando 1]
else if ([condição 2])
[comandos 2])
....
else
[comando n]
28
Controle de Fluxo

 if-else (exemplo)

int salario = 15;


boolean condicao = (salario > 1000);

if (condicao) {
System.out.println(“Merece aumento”);
}
else {
System.out.println(“Merece trabalhar mais!”);
}
29
Controle de Fluxo
 switch-case

switch([expressão]) {
case [constante 1]:
[comando 1]
break;
...
case [constante n]:
[de comando n]
break;
default:
[comando]
}
30
Controle de Fluxo

 switch-case (exemplo)

int opcao = 2;
System.out.print("valor de op eh: "+opcao);

switch (opcao) {
case 1:
System.out.println("case 1: op="+opcao);
break;

default:
System.out.println("default: opcao não está no limite 1..3");
}
31
Controle de Fluxo

 for

for ([expressão 1]; [condição]; [expressão 2])


{
[comando]
}

32
Controle de Fluxo

 for (exemplo)

int[] v = new int[10];

v[2] = 20; v[3] = 30; v[4] = 90;

for (int i=0; i < v.length; i++)


{
System.out.println("V["+i+"]="+v[i]);
}
33
Controle de Fluxo

 while

[expressão 1]
while ([condição]) {
[comando]
[expressão 2]
}

34
Controle de Fluxo

 while (exemplo)

double a, b, x=1.5, erro = 0.05;


a = 1; b = 2; // 1 < (raiz de 2) < 2
while( (b-a) > erro ) {
x = (a+b)/2;
if (x*x < 2) // x < raiz de 2
a = x;
else // x >= raiz de 2
b = x;
}
System.out.println("Valor aproximado de raiz quadrada de 2: " + x);
35
Controle de Fluxo

 do-while

do
{
[comando]
} while([condição]);

36
Controle de Fluxo

 do-while

int i =0;

do {
System.out.println(”o valor da variável i: " + i);
i++;
} while (i < 5);

37
Controle de Fluxo

 break
 O comando break é usado para interromper a execução de um dos
laços de iteração vistos abaixo ou de um comando switch.

for(int var1 =0; var1 < 5 ; var1++)


{
for(int var2=0 ; var2 < 5 ; var2++)
{
if (var2 == 2) { break; }
System.out.println(“var1:” + var1 + “, var2:”+ var2);
}
}

38
Controle de Fluxo

 continue
 O comando continue tem a função de pular direto para final do
laço, mas em vez de interromper o laço como no break, ele
continua executando o próximo passo do laço.

for(int var1 =0; var1 < 5 ; var1++)


{
for(int var2=0 ; var2 < 5 ; var2++)
{
if (var2 == 2) { continue; }
System.out.println(“var1:” + var1 + “, var2:”+ var2);
}
}
39
Controle de Fluxo

 return
 O comando return tem a função de retornar o valor de uma
variável ou a referência de um objeto quando um método exige
algum tipo de retorno.
 Podemos utilizá-lo para finalizar a execução imediata de um bloco.

public void verificaSituacao()


{
boolean t = true;
System.out.println(”Antes do retorno.");
if(t) { return }; // aplica o retorno
System.out.println(”Isto não executará.");
}
40
Variáveis primitivas

 Vamos treinar o controle de fluxo?

X 41
Agenda

Orientação a Objetos

42
Orientação a Objetos

É uma maneira de programar que ajuda na


organização e resolve muitos dos problemas
enfrentados pela programação procedural.
 A orientação a objetos vai te ajudar em muito

em se organizar e escrever menos, além de


concentrar as responsabilidades nos pontos
certos, flexibilixando sua aplicação,
encapsulando a lógica de negócios.
43
Orientação a Objetos

 Encapsulamento

 Em programação orientada a objetos


significa separar o programa em
partes, o mais isoladamente
possível.
 A idéia é tornar o software mais
flexível, fácil de modificar e de criar
novas implementações.
44
Orientação a Objetos

 Como declarar uma classe em Java?

public class Carro Declaração da Classe


{
public int codigo;
Declaração dos
public String modelo; Atributos de uma
public String placa; Classe
public String marca;
public java.util.Date dataFabricacao;
public java.util.Date dataVenda;
}
45
Orientação a Objetos

 Como declarar uma classe em Java?


 Uma classe pode ser composta de:
▪ Atributos;
▪ Métodos de Acesso;
▪ Construtor;
▪ Métodos (sobrescritos ou sobrecarregados).

46
Orientação a Objetos

 Como instanciar uma classe em Java?


 Similarmente a outras linguagens, temos:

Carro ferrari = new Carro();


ferrari.modelo = “F55”;
Atribuição de Valores
ferrari.marca = “FIAT”;
ferrari.codigo = 350;

47
Orientação a Objetos

 Para que criar métodos em uma


classe?
 A funções declaramos e utilizamos em
outras linguagens são chamadas de
métodos no Java.
 Criamos um método para que possa
executar uma atividade pré-definida,
específica dado ao contexto de negócio.
48
Orientação a Objetos

 Sobrecarga? O que é isso?


 Sobrecarga é uma característica
presente nas linguagens orientadas a
objeto;
 Permite criar variações de métodos e
construtores de uma classe no qual o
que os diferencia são seus argumentos
quanto a quantidade e seus tipos.
49
Orientação a Objetos

 Declaração de métodos em uma classe


public class Carro Sobrecarga (variação) de métodos
{
private double velocidade;
public void aumentarVelocidade(double velocidade) {
this.velocidade = velocidade;
}
public void aumentarVelocidade(String marca, double velocidade) {
this.velocidade = velocidade; this.marca = marca;
}
}
50
Orientação a Objetos

 Declaração de construtores em uma classe

public class Carro


{ Sobrecarga (variação) de construtores

public Carro() { }
public Carro(int codigo, String modelo)
{
this.codigo = codigo;
this.modelo = modelo;
}
}
51
Orientação a Objetos

 Visão 1 – Aplicação baseada em camadas

52
Orientação a Objetos

 Visão 2 – Aplicação baseada em camadas

Apresentação

Modelo
Negócio

Acesso à Dados

53
Orientação a Objetos

 Vamos montar nosso primeiro lego?

54
Orientação a Objetos

 Herança
 Enquanto programamos em Java, há a necessidade de
trabalharmos com várias classes.
 Muitas vezes, classes diferentes tem características
comuns, então, ao invés de criarmos uma nova classe
com todas essas características usamos as
características de um objeto ou classe já existente.
 Ou seja, herança é, na verdade, uma classe derivada de
outra classe.

55
Orientação a Objetos

 Herança

Super-classe
Conta (classe-base ou classe-pai)

É um(a)

Subclasse
ContaCorrente ContaPoupanca (classe-derivada ou classe-filha)

56
Orientação a Objetos

 Herança
 A herança no código fonte Java é representada pelo uso do
termo extends.
 Exemplificando, temos:

public class Conta { … }

public class ContaCorrente extends Conta { … }

public class ContaPoupanca extends Conta { … }

57
Orientação a Objetos

 Dica importante!
 Utilize os temos this e super para acesssar e
ser mais seletivo para com os métodos
disponíveis na classe pai ou filha.

Use o termo super para


acessar os membros da classe
Conta superior, excluindo da lista os
membros da classe filha.
É um(a)

Use o termo this para acessar


ContaCorrente ContaPoupanca os membros de uma classe.
58
Orientação a Objetos

 Sobrescrevendo métodos
 Muitas vezes não queremos utilizar o comportamento implementado
em um método encontrado na super-classe, logo sobrescrevemos
este método na subclasse.

Super-classe
Conta (classe-base ou classe-pai)

É um(a)

Subclasse
ContaCorrente ContaPoupanca (classe-derivada ou classe-filha)

59
Orientação a Objetos

 Sobrescrevendo métodos (exemplo)

public class Conta {



public void zerarSaldo() { this.saldo = 0 };
}
public class ContaCorrente extends Conta {

@Override
public void zerarSaldo() { this.saldo -= this.saldo * 0.3 };
}
60
Orientação a Objetos

 Associação
 É um vínculo que permite aos objetos de uma ou mais classes se
relacionem;
 É possível que um objeto invoque comportamentos e estados de
outros objetos.
 As associações podem ser:
▪ unárias – a associação ocorre entre objetos de uma mesma classe.
▪ binárias – a associação ocorre entre dois objetos de classes
distintas.
▪ múltiplas - a associação ocorre entre mais de dois objetos de
classes distintas.
61
Orientação a Objetos

 Associação (exemplos)
 Associação unária:  Associação binária:

filho de
Pessoa
- pai 1
1
*
Pessoa 1

- filho
TipoPessoa

62
Orientação a Objetos

 Associação (exemplos)
 Associação múltipla:

Pessoa
1
1 1

1 * *

TipoPessoa Departamento Dependente

63
Orientação a Objetos

 Agregação
 Tipo de relacionamento com características todo-parte,
onde existe um grau de coesão entre o todo e as partes
menos intenso, podendo haver certo grau de
independência entre eles.

Pessoa TipoPessoa

Não é necessário ter o tipo de pessoa


para que uma pessoa exista. 64
Orientação a Objetos

 Composição
 Tipo de relacionamento com características todo-parte, onde
existe um alto grau de coesão entre o todo e as partes, com
total grau de dependência entre eles (todo e as partes).
 Desta forma, se o todo não existir, as partes também não
existirão.
 Um exemplo de composição é a mão:
▪ Uma mão é composta por dedos. Os dedos compõem a mão.
▪ Não há lógica em existir um dedo sem mão, porém pode-se
ter uma mão sem um ou mais dedos.
65
Orientação a Objetos

 Composição
 Podemos observar que a composição impõe
obrigatoriedade:

Pessoa TipoPessoa

É necessário ter o tipo de


pessoa para que uma pessoa
exista.
66
Orientação a Objetos

 Como que representamos as associações, composições ou


agregações no código fonte em Java?

public class TipoPessoa { … }

public class Pessoa {


private TipoPessoa tipoPessoa = new TipoPessoa();
}

public class Pessoa {


Inicialize somente
private TipoPessoa tipoPessoa = null; quando necessário.
} 67
Orientação a Objetos

 Interfaces
 Uma interface pode definir uma série de
métodos, mas nunca conter
implementação deles.
 Ela só expõe o que o objeto deve fazer,
e não como ele faz, nem o que ele tem.
 Como ele faz vai ser definido em uma
implementação dessa interface (classe).

68
Orientação a Objetos

 Interfaces

<<interface>> Interface
(Não pode ser instanciada,
ObjetoGrafico somente implementada)
É um(a)

<<classe>> <<classe>>
Classe concreta
(classe que implementará
Pincel Caneta os métodos abstratos)

69
Orientação a Objetos

 Declarando uma interface


 Deveremos utilizar a palavra chave interface para declarar uma
interface.

public interface UsuarioAutenticavel()


{
bool autenticar();
Permissao[] obterPermissoes();
bool checarPermisssao();
}

70
Orientação a Objetos

 Como implementar uma interfaca?

public class UsuarioFuncionario implements UsuarioAutenticavel {


bool autenticar() { … //implementação …}
Permissao[] obterPermissoes(); { … //implementação …}
bool checarPermisssao(); { … //implementação …}
}

public class UsuarioDiretor implements UsuarioAutenticavel {


bool autenticar() { … //implementação …}
Permissao[] obterPermissoes(); { … //implementação …}
bool checarPermisssao(); { … //implementação …}
} 71
Orientação a Objetos

 Dica importante!
 Podemos identificar se um classe é uma
instância de um determinado tipo (classe
ou interface).
 Exemplificando abaixo, temos:

if (ContaCorrente instanceof Conta)


Conta {

É um(a) }

ContaCorrente ContaPoupanca
72
Orientação a Objetos

 Vamos complicar mais um pouco?

73
Agenda

Arrays

74
Arrays

 Podemos utilizar uma variável para armazenar e


manipular uma lista de dados de forma mais
eficiente;
 Este tipo de variável é chamado de array;
 Um array armazena múltiplos itens de dados do
mesmo tipo em um bloco contínuo de memória,
dividindo-o em certa quantidade de “casas”.

75
Arrays

 Declara-se um array usando ao menos uma das


seguintes formas:

//declaração
int[] idades;
ou
//declarando e construção de um objeto de array
int idades[] = new int[100];

76
Arrays

 Podemos criar um array informando diretamente


os dados:

//declaração de um array de inteiros com 6 itens


int[] idades = { 1, 2, 3, 10, 25, 90 };
ou
int[] idades = new int[] { 1, 2, 3, 10, 25, 90 };

77
Arrays

 Podemos acessar os elementos de um array


usando uma das seguintes formas:
5 +
int[] numeros = new int[] { 10, 20, 30, 40, 50 };
v a
for (int numero : numeros)
Ja
{
System.out.println(String.format("teste: %s", numero));
}

78
Arrays

 Ou você quer usar ainda esta?

int[] numeros = new int[] { 10, 20, 30, 40, 50 };

for (int i = 0; I < numeros.length; i++)


{ Nos dá o tamanho
de um Array
int numero = numeros[i];
System.out.println(String.format("teste: %s", numero));
}

79
Arrays
numeros

Array de 1
dimensão
80
Arrays

 Arrays Multidimensionais

 São implementados como arrays dentro de arrays;


 São criados adicionando-se mais um conjunto de colchetes após o nome

do array declarado:

// array inteiro de 512 x 128 elementos


int[][] twoD = new int[512][128];
// array de caracteres de 8 x 16 x 24
char[][][] threeD = new char[8][16][24];
// array de String de 4 linhas x 2 colunas
String[][] dogs = {{ "terry", "brown" }, { "Kristin", "white" }};
81
Arrays

Array de 2
dimensões

82
Agenda

Modificadores de Acesso

83
Modificadores de Acesso

 Os modificadores de acesso são palavras-chave que


modificam a forma como podem ser acessadas as
classes, métodos ou variáveis. São eles:
 private
 protected
 public
 static

84
Modificadores de Acesso

 O modificador private
 O modificador de acesso private quando aplicado
a um atributo ou a um método indica que os
mesmos só podem ser acessados de dentro da
classe que os criou (encapsulamento).

85
Modificadores de Acesso

 O modificador private
 Uma classe que herde de uma superclasse com
atributos declarados como private só poderá ter
acesso a eles através dos métodos públicos da
própria superclasse, caso contrário, não haverá
acesso a estes atributos.

86
Modificadores de Acesso
public class Circulo {
private float raio;
Circulo() { setRaio( 3.0 ); }
void setRaio( float r ) { raio = r; }
}
public class Pneu extends Circulo {
public static void main(String[] args) {
Pneu p = new Pneu();
p.raio = 10.0; //Erro de compilação. O Atributo raio é privado da classe Circulo
p.setRaio(10.0);
}
} 87
Modificadores de Acesso

 O modificador protected
 A instrução protected indica que o método ou a
variável assim declarada possa ser acessada
somente dentro do pacote em que está contida
através de uma subclasse.

88
Modificadores de Acesso

 O modificador public
 A instrução public indica que a classe, método ou
variável assim declarada possa ser acessada em
qualquer lugar e a qualquer momento da
execução do programa.

89
Modificadores de Acesso

 Quadro comparativo para não


esquecer:

private default protected public


Mesma classe S S S S
Mesmo pacote S S S S
Pacotes diferentes N N S S
(sendo subclasses)

Pacotes diferentes (não N N N S


sendo subclasses)

90
Modificadores de Acesso

 O modificador static
 A instrução static serve:
▪ Na declaração de uma variável dentro de uma classe,
para se criar uma variável que poderá ser acessada por
todas as instâncias de objetos desta classe como um
variável comum.
▪ A variável criada será a mesma em todas instâncias e
quando seu conteúdo é modificado numas das
instâncias, o será em todas instâncias;
▪ Na declaração de um método que deve ser acessado
diretamente na classe e não nas suas instâncias.
91
Modificadores de Acesso

 O modificador static
public class Circulo Valor único para todas as
{ instâncias de uma classe.

public static float raio;


Circulo() { setRaio( 3.0 ); }
void setRaio( float r ) { raio = r; }

public static void processaCalculoDiametro()


{
//lógica para processamento do calculo Permite acesso sem
} instanciar uma classe
} 92
Enumerados

 Dica importante!
 Se uma classe não necessita de ser
estendida use final.
 Melhorará o tempo de performance
de programa referente a checagem
das subclasses da classe onde for a
aplicada o termo final.

93
Modificadores de Acesso

 O modificador static
 A sintaxe da chamada de qualquer atributo ou método é:

<<Nome da Class>>.<<nome do atributo estático>>

<<Nome da Class>>.<<nome do método estático>>

 Diante disso, temos:

Circulo.raio = 10.4f;
Circulo.processaCalculoDiametro();
94
Modificadores de Acesso

 O modificador abstract
 A instrução abstract serve para:
▪ Declarar métodos abstratos, ou seja, métodos que deverão
ser desenvolvidos/implementados nas subclasses.
▪ Quando a classe que contiver métodos abstratos for herdada,
os referidos métodos deverão ser implementados, caso
contrário, a classe que extendeu deverá ser declarada como
abstrata.
▪ Declarar classes abstratas que se desenvolvem num(as)
subclasse(s).
95
Modificadores de Acesso

 O modificador abstract
 A instrução abstract serve para: (continuação)
▪ Classes abstratas são aquelas que não estão totalmente
implementadas/descritas.
▪ Uma classe abstrata não pode ser instanciada e é amplamente
usada nas interfaces.
▪ Uma classe é considerada abstrata se contiver pelo menos um
método abstrato. Um método abstrato tem a seguinte característica:
void getName( );
▪ Caso o método tenha as chaves características {}, o mesmo não
mas será considerado abstrato, embora não tenha código dentro
das chaves. 96
Orientação a Objetos

 O modificador abstract

<<abstract>>
Classe abstrata
(não pode ser instanciada,
ObjetoGrafico somente estendida)

É um(a)

Classe concreta
<<concrete>> <<concrete>> (classe que realmente
Pincel Caneta implementará os métodos
abstratos)

97
Modificadores de Acesso
 O modificador abstract
public abstract class ObjetoGrafico {
// declaração de campos
// declaração de métodos não abstratos
public abstract void desenhe();
} Ao estender a classe
abstratar a classe concreta
public class Princel extends ObjetoGrafico { deverá implementar todos
@Override os métodos abstratos.
public void desenhe() {
//executa a lógica de desenho
}
}
98
Modificadores de Acesso

 O modificador final
 A instrução final indica que a classe, método ou
variável assim declarada têm uma única atribuição
que se mantém constante, ou seja, não pode ser
alterada no decorrer do processamento.
 Este modificador declara o que chamamos, em
programação, de constante.

99
Modificadores de Acesso

 O modificador final

Classe final
<<final>>
(Somente pode ser instanciada,
ObjetoGrafico logo não pode ser extendida)

É um(a)

<<concrete>> <<concrete>>
Pincel Caneta

100
Modificadores de Acesso

 O modificador final: A classe não pode ser


estendida.
public final class ObjetoGrafico {
private final int posicaoInicial = 16;
// declaração de campos
A variável é imutável
// declaração de métodos não abstratos
public void desenhe()
{
// lógica desenho
}
}

101
Agenda

Enumerados

102
Enumerados

 Uma enumeração é um tipo especial de classe que é


introduzida pela palavra-chave enum e um nome de
tipo;
 Assim como todas as classes as chaves { e } delimitam o

corpo da declaração enum.


 Entre as chaves contém uma lista de constantes de

enumeração separadas por vírgulas.


 Cada identificador em um enum deve ser único.

103
Enumerados

 Como todas as classes, os tipos enum são tipos por referência.


 Uma declaração do tipo enum pode opcionalmente incluir
construtores, campos e métodos.
 Características da classe enum:
 Tipos enum são implicidamente final.

 Constantes enum são implicidamente static.

 Se tentar criar um objeto de um tipo enum irá resultar em


erro de compilação.

104
Enumerados

 A declaração de um enumerado ocorre da seguinte


forma:

//declaração de um enumerado
public enum SituacaoMotorEnum {
LIGADO,
DESLIGADO,
STANDBY;
}
105
Enumerados

 O uso de um enumerado se dá da seguinte forma:

SituacaMotorEnum situacao = SituacaoMotorEnum.LIGADO;

//utilizamos o enumerado para


//dar maior naturalidade ao programa
if (situacao == SituacaoMotorEnum.LIGADO)
{
//motor está ligado
}
106
Enumerados

 Como eu uso o enumerado


como um constante?
 Crie uma variável privada;
 Declare um construtor com um
argumento;
 Crie o método de acesso;
 Se aplicável, sobrescreva o método
toString().
107
Enumerados

 Vamos adicionar mais um peça no nosso quebra-


cabeça?

108
Agenda

Controlando os Erros
com Exceções

109
Controlando os Erros com Exceções

 O que é uma exceção?


 O termo exception é um trmo
diminutivo de evento excepcional.
 Uma exception é um evento que
ocorre durante a execução de um
programa no qual romple o fluxo
normal das instruções de um
programa.

110
Controlando os Erros com Exceções

 Hierarquia de exceções

111
Controlando os Erros com Exceções

 Exceções checadas
 São consideradas exceções checadas todas as classes que
extendem de java.lang.Exception;
 São chamadas de checadas, pois o compilador verificará a
sua aplicabilidade ao longo do código fonte.
 Exceções não-checadas
 São consideradas exceções checadas todas as classes que
extendem de java.lang.RuntimeException ou
java.lang.Error.
 Este tipo de exceção não é checado pelo compilador.
112
Controlando os Erros com Exceções

 Lançando Exceções

public void executarRegraNegocio(int entrada) throws new Exception


{
int parametro = 10;
Propaga a exceção para
quem chamou este
if (entrada > parametro) método.

{
throw new Exception(“O valor é maior que o limite máximo!”);
}
Lança a exceção.
}
113
Controlando os Erros com Exceções

 try { … } catch { … } finally { … }

try {
declarações; Exceção mais específica
} catch (tipoExcecao1 identificador1) {
declarações;
} catch (tipoExcecao2 identificador2) {
declarações;
}
Exceção menos específica
...
} finally {
declarações;
}
114
Controlando os Erros com Exceções

 try { … } catch { … } finally { … }


 Precisa incluir ao menos uma cláusula catch ou cláusula finally;
 Pode conter múltiplas cláusulas de catch mas somene uma
cláusula finally;
 A declaração try é executada até que uma exceção seja lançada
ou completar com sucesso.
 Um erro de compilação ocorrerá se o código incluido dentro da
declaração try nunca lançar ao menos uma das exceções
checadas.
 Se uma exceção for lançada, cada clásula catch é inspecionada e
chaveada para o tipo da exceção no qual pode ser atribuída.
115
Controlando os Erros com Exceções

 try { … } catch { … } finally { … } (exemplo)

try {  
    // cria reader, processa arquivo e tudomais  
}  
catch (Exception e) {  
    // oooops  
} finally {  
    if (reader != null) {  
        try {  
            reader.close();  
        }  
        catch (Exception e) {  
            // outro ooops  
        }  
    }  
} 116
Controlando os Erros com Exceções

 Vantagens de Exceções
 Separação do gerenciamento de erro do código “regular”.
 Propagação dos erros ao longo da pilha de chamadas (Call
Stack);
 Agrupamento e diferenciação dos tipos de erro;
 Melhora a qualidade do código tornando a leitura do código
fonte mais natural.
 Desvantagens de Exceções

 Para cada exceção lançada, um novo objeto de representação


da exceção é criado.

117
Controlando os Erros com Exceções

 Quando uma método é chamado…

main
Chamada
ao método
Método com um
gerenciador de exceção
Chamada
ao método
Método sem um
gerenciador de exceção
Chamada
Método onde ao método
ocorreu o erro
118
Controlando os Erros com Exceções

 … pode ocorrer uma exceção!

main

Captura qualquer Método com um


exceção lançada gerenciador de exceção
Procura o
Passa a execeção gerenciador de exceção
Método sem um apropriado
para o método que
gerenciador de exceção
o chamou
Procura o
Método onde gerenciador de exceção
Lança a exceção apropriado
ocorreu o erro
119
Controlando os Erros com Exceções

 Como criar a minha classe de exceções?


<<classe>>
java.lang.Exception

É um
<<classe>>
com.acme.AppException

É um É um

<<classe>> <<classe>>
com.acme.DAOException com.acme.ControlException

120
Controlando os Erros com Exceções

 Como criar a minha classe de exceções?

//exceção base da aplicação


public class AppException extends java.lang.Exception { … }

public class DAOException extends com.acme.AppException { … }

public class ControlException extends com.acme.AppException { … }

O para criação de exceções é necessário


edtender de uma determinada classe de exceção.

121
Controlando os Erros com Exceções

 Vamos fazer um test-drive?

122
Agenda

O pacote java.lang

123
O pacote java.lang

 Já usamos, por diversas vezes, as classes String e


System.
 Vimos o sistema de pacotes do Java e nunca

precisamos incluir um import dessas classes.


 Isso ocorre porque elas estão dentro do pacote

java.lang, que é automaticamente importado para


você.
 É o único pacote com esta característica.

124
O pacote java.lang

 A classe System:
 A classe System possui uma série de atributos e métodos
estáticos.
 Já usamos o atributo System.out, para imprimir conteúdo.
 Ela também possui o atributo in, que lê da entrada padrão,
porém só consegue captar bytes:

int i = System.in.read();

125
O pacote java.lang

 A classe System:
 Temos outros métodos interessantes como:

System.exit(0);
A classe Runtime

▪ A classe Runtime possui um método para fazer uma chamada


ao sistema operacional e executar algum programa:
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("dir");

126
O pacote java.lang

 Integer e classes wrappers:


 Uma pergunta bem simples que surge na cabeça de todo
programador ao aprender uma nova linguagem é:

“Como transformamos um número


em String e vice-versa?”

127
O pacote java.lang

 Integer e classes wrappers:


 O jeito mais simples de transformar um número em String é
concatená-lo da seguinte maneira:

int i = 100;
String s = "" + i;
System.out.println(s); Ao concatenar um valor
numérico com uma
String.
double d = 1.2;
String s2 = "" + d;
System.out.println(s2);
128
O pacote java.lang

 Integer e classes wrappers:


 No entanto, para transformar a String em um número inteiro
utilizamos o método estático da classe Integer:
Método da classe
wrapper.
String s = "101";
int i = Integer.parseInt(s);

 As classes Double, Short, Long, Float contêm o mesmo tipo de


método, como parseDouble e parseFloat que retornam um double e
float respectivamente.
129
O pacote java.lang

 Integer e classes wrappers:


 Essas classes também são muito utilizadas para fazer o wrapping
(embrulho) de tipos primitivos como objetos, pois referências e tipos
primitivos são incompatíveis.
 Imagine que precisamos passar como argumento um inteiro para o nosso
guardador de objetos. Um inteiro não é um Object, como fazer?

int i = 5; Passagem do primitivo


inteiro.
Integer x = new Integer(i);
int numeroDeVolta = x.intValue();
130
O pacote java.lang

 Autoboxing no Java 5.0 (ou superior):


 Esse processo de wrapping (boxing) e unwrapping (unboxing)
é entediante.
 O Java 5.0 em diante traz um recurso chamado de
autoboxing, que faz isso sozinho para você, custando
legibilidade:
▪ Integer x = 5;
▪ int y = x;

 No Java 1.4 o código acima é inválido.


131
O pacote java.lang

 Autoboxing no Java 5.0 (ou superior):


 Você pode fazer todos os tipos de operações matemáticas
com os wrappers, porém corre o risco de tomar um
NullPointerException;
 Você pode fazer o autoboxing diretamente para Object
também, possibilitando passar um tipo primitivo para um
método que receber Object como argumento:
 Object o = 5;

132
O pacote java.lang

 Usando java.lang.String
 Variáveis do tipo String guardam referências a objetos, e
não um valor, como acontece com os tipos primitivos.
 Podemos criar uma String utilizando o termo new:
String x = new String(”programa");
String y = new String(”prog java 01");

133
O pacote java.lang

 Qual é a forma correta de


compararmos 2 Strings?

if (x == y)
{
System.out.println("referência para o mesmo objeto");
} else {
System.out.println("referências para objetos diferentes!");
}

134
O pacote java.lang

 Qual é a forma correta de compararmos 2


Strings?

if (x.equals(y))
{
System.out.println("consideramos iguais no critério de
igualdade");
} else {
System.out.println("consideramos diferentes no
critério de igualdade");
}
135
O pacote java.lang

 Alguns métodos interessantes da classe String:


 split:
▪ Divide os termos dado o separador informado.

String frase = "java é demais";


String palavras[] = frase.split(" "); O separador é um
espaço em branco.

String frase = ”001|JOSE LUIZ|01012011";


String palavras[] = frase.split(”|"); O separador é uma
barra vertical.

136
O pacote java.lang

 Vamos treinar alguns aspectos de strings?

137
O pacote java.lang

 A class java.lang.Math
 Na classe Math, existe uma série de métodos estáticos
que fazem operações com números como, por exemplo:
▪ Arredondar(round);
▪ Tirar o valor absoluto (abs);
▪ Tirar a raiz(sqrt);
▪ Calcular o seno(sin).

138
O pacote java.lang

 A class java.lang.Math
 Exemplificando o seu uso, temos:

double d = 4.6;
Arredondar um valor
long i = Math.round(d); para cima.

int x = -4;
int y = Math.abs(x); Obter o valor absoluto.

139
O pacote java.lang
 A class java.lang.Math
 No Java 5.0, podemos tirar proveito do import static aqui:

import static java.lang.Math.*;

 Isso elimina a necessidade de usar o nome da classe, sob o custo de


legibilidade:

double d = 4.6;
long i = round(d);
Observe que não é necessário mais
mencionar o nome da classe, somente
int x = -4; seus métodos estáticos.
int y = abs(x);
140
O pacote java.lang

 Vamos treinar alguns a API de matemática do


Java?

141
Agenda

A API de Coleções

142
A API de Coleções

 Como vimos em arrays, manipulá-las é bastante


trabalhoso. Essa dificuldade aparece em diversos
momentos:
 Não podemos redimensionar um array em Java;
 É impossível buscar diretamente por um determinado
elemento cujo índice não se sabe;
 Não conseguimos saber quantas posições do array já
foram populadas sem criar, para isso, métodos auxiliares.

143
A API de Coleções

 Além dessas dificuldades que os arrays apresentavam,


faltava um conjunto robusto de classes para suprir a
necessidade de estruturas de dados básicas, como listas
ligadas e tabelas de espalhamento.
 Com esses e outros objetivos em mente, a Sun criou um
conjunto de classes e interfaces conhecido como Collections
Framework, que reside no pacote java.util desde o Java2
1.2.
 A API do Collections é robusta e possui diversas classes que
representam estruturas de dados avançadas.
144
A API de Coleções

 Hierarquia das Interfaces de Coleções:

145
A API de Coleções

 Lists (ou Listas)

146
A API de Coleções

 Listas
 Uma lista é uma coleção que permite elementos duplicados e
mantém uma ordenação específica entre os elementos.
 Em outras palavras, você tem a garantia de que, quando
percorrer a lista, os elementos serão encontrados em uma
ordem pré-determinada, definida na hora da inserção dos
mesmos.
 Ela resolve todos os problemas que levantamos em relação ao
array (busca, remoção, tamanho “infinito”,...). Esse código já
está pronto!

147
A API de Coleções

 Listas
 A API de Collections traz a interface java.util.List, que especifica o
que uma classe deve ser capaz de fazer para ser uma lista.
 Há diversas implementações disponíveis, cada uma com uma
forma diferente de representar uma lista.
 A implementação mais utilizada da interface List é a ArrayList,
que trabalha com um array interno para gerar uma lista.
 Ela é mais rápida na pesquisa do que sua concorrente, a LinkedList,
que é mais rápida na inserção e remoção de itens nas pontas.

148
A API de Coleções

 Utilizando uma lista


ContaCorrente c1 = new ContaCorrente();
c1.deposita(100 );
...
ContaCorrente c3 = new ContaCorrente(); Uso da classe
c3.deposita(300 );
List contas = new ArrayList();
contas.add(c1);
contas.add(c3);
Uso da interface
contas.add(c2);
149
A API de Coleções

 Acessando os elementos de uma lista


for (int i = 0; i < contas.size(); i++)
{
ContaCorrente cc = (ContaCorrente) contas.get(i);
System.out.println(cc.getSaldo());
}

Obtém o tamanho
de uma lista
Obtém o item contido na lista
dado o índice informado

150
A API de Coleções

 Acessando os elementos de uma lista de uma forma mais


natural:
for (Object item : contas)
{
ContaCorrente cc = (ContaCorrente)item;
System.out.println(cc.getSaldo());
}

Usamos o outro tipo Acesso direto ao


declaração do for item da coleção
151
A API de Coleções

 Utilizando uma lista com Generics


ContaCorrente c1 = new ContaCorrente();
c1.deposita(100 );
ContaCorrente c2 = new ContaCorrente();
c2.deposita(200 );
ContaCorrente c3 = new ContaCorrente(); Uso da classe
c3.deposita(300 );
List<ContaCorrente> contas = new ArrayList<ContaCorrente>();
contas.add(c1);
contas.add(c3); Uso da interface
contas.add(c2); 152
A API de Coleções

 Map (ou Dicionários)


 Muitas vezes queremos acessar rapidamente um objeto
dado alguma informação sobre ele.
 Um exemplo seria, dada a placa do carro, obter todos os
carros.
 Poderíamos utilizar uma lista para isso e percorrer todos
os seus elementos, mas isso pode ser péssimo para a
performance, mesmo para listas não muito grandes.

153
A API de Coleções

 Map (ou Dicionários)


 Um mapa é composto de um conjunto de associações entre um
objeto chave a um objeto valor.
 É equivalente ao conceito de dicionário.
 Algumas linguagens, como Perl ou PHP, possuem um suporte
mais direto a mapas, onde são conhecidos como matrizes/arrays
associativas.
 java.util.Map é um mapa, pois é possível usá-lo para mapear uma
chave a um valor, por exemplo: mapeie à chave “empresa” o valor
“igorborba”, ou então mapeie à chave “rua” ao valor “Vergueiro”.
 Semelhante a associações de palavras que podemos fazer em
154
A API de Coleções

 Map (ou Dicionários)

155
A API de Coleções
 Utilizando uma estrutura Map:

//Criando uma instancia de HashMap possibilita construirmos um dicionário


Map dicionario = new HashMap();

//Agora adicionamos vários pares de hosts e Ips


dicionario.put("www.sbc.org.br", "143.54.83.4");
dicionario.put("www.usp.br", "143.107.253.62");

if (dicionario.containsKey(“www.usp.br”)
{
//executa rotina se verdadeiro
}
156
A API de Coleções
 Utilizando uma estrutura Map com Generics:

//Criando uma instancia de HashMap possibilita construirmos um dicionário


Map<String, String> dicionario = new HashMap<String, String>();

//Agora adicionamos vários pares de hosts e Ips


dicionario.put("www.sbc.org.br", "143.54.83.4");
dicionario.put("www.usp.br", "143.107.253.62");

if (dicionario.containsKey(“www.usp.br”)
{
//executa rotina se verdadeiro
}
157
A API de Coleções

 Set (ou Conjuntos)


 Os objetos do grupo Set têm o objetivo de não permitir a
duplicação de elementos.
 Estes objetos tratam os elementos como se fossem parte de
um conjunto matemático, no qual independente da ordem em
que elementos são acrescentados eles nunca serão duplicados.
 Conjuntos são extensamente usados pra representação de
dados.
 Como vimos na escola, conjuntos podem ser vazios, mas não
infinitos, visto que sua representação seria impossível.
158
A API de Coleções

 Set (ou Conjuntos)


 O tamanho de um conjunto pode variar dinamicamente, não sendo
necessário prover seu tamanho, alem disso objetos em conjunto
geralmente não são ordenados explicitamente, assim sendo a ordem
que foi inseridos não é mantida internamente.
 Conjuntos em Java são encapsulados por uma instância de uma das
classes que implementam Set.
 Declara vários métodos que possibilitam: a inclusão e remoção de
objetos na coleção, além de também permitirem a verificação do
tamanho do conjunto (isto é quantos elementos ele contém), dentre
outros

159
A API de Coleções

 Set (ou Conjuntos)

160
A API de Coleções
 Utilizando uma estrutura Set:

//criando o objeto Set


Set cores = new HashSet();
//adicionando elementos ao objeto
cores.add("azul");
cores.add("amarelo");
//criando o objeto iterator para poder percorrer o Set
Iterator it = cores.iterator();
//imprimindo os objetos
while (it.hasNext()) {
String cor = (String) it.next();
System.out.println(cor);
}
161
A API de Coleções
 Utilizando uma estrutura Set com Generics:

//criando o objeto Set


Set<String> cores = new HashSet<String>();
//adicionando elementos ao objeto
cores.add("azul");
cores.add("amarelo");
//criando o objeto iterator para poder percorrer o Set
Iterator it = cores.iterator();
//imprimindo os objetos
while (it.hasNext()) {
String cor = (String) it.next();
System.out.println(cor);
}
162
A API de Coleções

 Ordenação em Coleções
 A classe Collections traz um método estático sort que recebe um
List como argumento e o ordena por ordem crescente.

List lista = new ArrayList();


lista.add(”Igor");
lista.add(”Vitor");
lista.add(”José");

System.out.println(lista); //repare que o toString de ArrayList foi sobrescrito!


Collections.sort(lista);
System.out.println(lista);
163
A API de Coleções
 Mas quando eu quero ordenar uma coleção de objetos
complexos?
 A classe que representa o objeto contido na coleção, nete caso chama-se
ContaCorrente, deverá implementar a interface Comparable ou utilizar a
interface Comparator.
 Quando você quiser:
▪ Criar diversos tipos de ordenção para uma coleção dado um tipo de
objeto, utilize Comparator;
▪ Caso exista somente um tipo de ordenação e esta seja a padrão
utilize Comparable;
▪ Dica: Se estiver utilizando banco de dados, tente utilizar a ordenação
presente na linguagem SQL antes de construir os objetos que
representem as linhas do resultado de sua consulta. 164
A API de Coleções

 Mas quando eu quero ordenar uma coleção de objetos


complexos?

ContaCorrente c1 = new ContaCorrente();


c1.deposita(500);
… // {n contas-corrente }
List<ContaCorrente> contas = new ArrayList<ContaCorrente>();
contas.add(c1); …
Collections.sort(contas); // qual seria o critério para esta ordenação?

165
A API de Coleções

 Utilizando a interface Comparable<?>

public class ContaCorrente implements Comparable<ContaCorrente> {



@Override
public int compareTo(ContaCorrente t) {
if (this.codigo < t.codigo) { return -1; }
if (this.codigo > t.codigo) { return 1; }
return 0; Se -1  Item é menor que o outro
Se 1  Item é maior que outro
} Se 0  Item é igual ao outro
}
166
A API de Coleções

 Mas quando eu quero ordenar uma coleção de objetos


complexos?

ContaCorrente c1 = new ContaCorrente();


c1.deposita(500);
… // {n contas-corrente }
List<ContaCorrente> contas = new ArrayList<ContaCorrente>();
contas.add(c1); …
Collections.sort(contas, new ContaCorrenteComparator()); // qual
seria o critério para esta ordenação?

167
A API de Coleções

 Utilizando a interface Comparator<?>

public class ContaCorrenteComparator implements


Comparator<ContaCorrente> {
@Override
public int compare(ContaCorrente t, ContaCorrente t1) {
if (t.getCodigo() < t1.getCodigo()) { return -1; }
if (t.getCodigo() > t1.getCodigo()) { return 1; }
return 0; Se -1  Item é menor que o outro
} Se 1  Item é maior que outro
Se 0  Item é igual ao outro
} 168
A API de Coleções

 Vamos exercitar os conceitos da API de Coleções?

169
Agenda

O pacote java.io

170
O pacote java.io
 A parte de controle de entrada e saída de dados (conhecido como
I/O) é orientada a objetos e usa os principais conceitos mostrados
até agora: interfaces, classes abstratas e polimorfismo.
 A idéia atrás do polimorfismo no pacote java.io é de utilizar fluxos de
entrada (InputStream) e de saída (OutputStream) para toda e
qualquer operação, seja ela relativa:
 A um arquivo;
 Um campo blob do banco de dados;
 A uma conexão remota via sockets, ou;
 Até mesmo às entrada e saída padrão de um
programa(normalmente o teclado e o console).
171
O pacote java.io
 Hierarquia de Classes de Java IO (Entrada)

172
O pacote java.io
 Hierarquia de Classes de Java IO (Saída)

173
O pacote java.io
 Hierarquia de Classes de Java IO (Leitores / Escritores)

174
O pacote java.io
 Como ler o conteúdo de um arquivo .txt?
class TestaEntrada {
public static void main(String[] args) throws IOException {
InputStream is = new FileInputStream(”c:\\arquivo.txt");
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);

String s = br.readLine();
while (s != null) {
String linha = br.readLine();
}
}
}
175
O pacote java.io
 Como escrever um conteúdo em um arquivo .txt?
class TestaSaida {

public static void main(String[] args) throws IOException {


OutputStream os = new FileOutputStream("saida.txt");
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(”igorborba");
bw.close();
}

176
O pacote java.io

 Como excluir um arquivo?


java.io.File arquivo = new java.io.File("/Users/igor/meuarquivo.txt");

If (arquivo.exists())
{
arquivo.delete();
}

177
O pacote java.io

 Como listar o conteúdo de um diretório?


File diretorio = new File("/Users/igor/");

if (diretorio.exists() && diretorio.isDirectory()) {


File[] arquivos = diretorio.listFiles();
for (File arquivo : arquivos) {
String rotulo = arquivo.isDirectory() ? "Diretório: " : "Arquivo:”;
System.out.println(rotulo + arquivo.getName());
}
}

178
O pacote java.io

 Vamos manipular o sistema de arquivos?

179
Agenda

Threads

180
Programação Concorrente com
Threads
 A necessidade de se fazer várias coisasde forma
simultânea, ao mesmo tempo, paralelamente, aparece
frequentemente na computação.
 Para vários programas distintos, normalmente o próprio

sistema operacional gerencia isso através de vários


processos em paralelo.
 Em um programa só (um processo só), se queremos

executar tarefas em paralelo, normalmente falamos de


Threads.

181
Programação Concorrente com
Threads
 Em Java, usamos a classe Thread do pacote java.lang para
criarmos linhas de execução paralelas.
 Existem basicamente duas abordagens para a implementação

das threads na JVM:


 Utilização de mecanismos nativos de operação do sistema
operacional;
 Implementação completa da operação thread na JVM.
 Em ambos os casos, a operação das mesmas é obtida através de
uma fatia de tempo fornecida pelo S.O. ou pela JVM.
 Isto cria um paralelismo virtual!

182
Programação Concorrente com
Threads
 Quais são estados de uma Thread?

new

program start thread


l ock Th
un nal l th rea
sig alAl runnable et dc
n as om
k
sig ple
ait te
s
await

w
sleep
interval

a ck
expires

lo

waiting terminated
time
waiting
183
Programação Concorrente com
Threads
 Como definir uma Thread?
 Uma tarefa, para ser excutada em uma nova Thread, deve
implementar a interface Runnable.

<<interface>>
java.lang.Runnable

<<class>> <<class>> <<class>>


ProcessaArquivo ProcessEnvMensagem ProcessaRecMensagem

184
Programação Concorrente com
Threads

 Como definir uma Thread?

public class Tarefa implements Runnable {

@Override
public void run() {
System.out.println("tarefa executada!");
System.out.println("Id Thread:" + Thread.currentThread().getId());
}

}
185
Programação Concorrente com
Threads
Criado um grupo
 Como executar uma Thread? de Threads

ThreadGroup tg = new ThreadGroup("tarefas");

System.out.println(Thread.currentThread().getId());
Criação deum
for(int i = 0; i < 100; i++) nova Thread
{
Thread t = new Thread(tg, new Tarefa());
t.start();
} Inicia a Thread
Instância da classe que
implementa Runnable
186
Programação Concorrente com
Threads
 Vamos colocar nossas Threads para correr?

187
Java
A Linguagem

Igor Borlot Borba


Igor@igorborba.com.br

Você também pode gostar