Buscar

apostila javaoo 2.0

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 44 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 44 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 44 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Projeto Fábrica de Programador – Módulo 2 
www.fabricadeprogramador.com.br 
Sumário 
1 ORIENTAÇÃO AO ALUNO ............................................................................................. 3 
2 CLASSES E OBJETOS .................................................................................................. 3 
2.1 Propriedades ............................................................................................................ 3 
2.2 Métodos ................................................................................................................... 4 
3 MÉTODOS GETTERS E SETTERS ............................................................................... 5 
4 RELACIONAMENTOS ENTRE OBJETOS DO TIPO “TEM UM” ..................................... 5 
5 HERANÇA - RELACIONAMENTO DE OBJETOS DO TIPO “É UM” ............................. 10 
5.1 Instanciando Polimorficamente .............................................................................. 17 
5.2 Fazendo Conversões (Casting) .............................................................................. 18 
5.3 Sistema de Cadastro de Pessoas .......................................................................... 19 
6 MÉTODOS E PROPRIEDADES ESTÁTICAS ............................................................... 20 
7 SOBRECARGA E SOBRESCRITA DE MÉTODOS ...................................................... 22 
7.1 Sobrescrevendo o Método toString() ...................................................................... 23 
7.2 Sobrescrevendo o Método equals(Object obj) ........................................................ 24 
7.3 Utilizando a IDE para Gerar o Método Equals e Hashcode .................................... 24 
7.4 HashCode .............................................................................................................. 25 
7.5 A Palavra Reservada This ...................................................................................... 25 
8 CONSTRUTORES ........................................................................................................ 26 
8.1 Construtor Sobrecarregado .................................................................................... 26 
8.2 Sobrecarregando o Construtor de Cidade .............................................................. 28 
8.3 Lembrando dos Estáticos ....................................................................................... 28 
9 SOBRECARGA DE CONSTRUTORES ........................................................................ 29 
10 MÉTODOS SOBRECARREGADOS ............................................................................. 29 
11 CLASSES ABSTRATAS ............................................................................................... 30 
12 INTERFACES ............................................................................................................... 31 
12.1 Implementando as Interfaces ................................................................................. 32 
13 GENÉRICOS - UM GERENCIADOR DE REGISTROS GENÉRICO ............................. 37 
14 TRABALHANDO COM COLEÇÕES ............................................................................. 38 
14.1 List ......................................................................................................................... 39 
14.2 Exemplo de Uso da Interface List com ArrayList .................................................... 39 
14.3 Set ......................................................................................................................... 40 
14.4 Map ........................................................................................................................ 41 
15 EXCEPTIONS ............................................................................................................... 41 
15.1 Lançando uma Exception Unchecked (Não verificadas) ......................................... 42 
15.2 Lançando uma Exception Checked (Verificadas) ................................................... 43 
 
Versão: 2.0 
2ª Edição 
Projeto Fábrica de Programador – Módulo 2 
www.fabricadeprogramador.com.br Página: 3 
 
1 ORIENTAÇÃO AO ALUNO 
Este material é continuação do módulo 1 do projeto Fábrica de Programador, nosso foco é 
ensinar os conceitos práticos de Orientação a Objetos de modo didático, com uma linguagem 
menos formal para auxiliar os desenvolvedores iniciantes a darem seus primeiros passos de 
modo prático e rápido, sem a necessidade de um embasamento teórico aprofundado. Logo, 
este material não foca os conceitos teóricos da computação. Para você se aprofundar na 
teoria da computação recomendamos que leia livros voltados para esse fim. 
 
2 CLASSES E OBJETOS 
No modulo 1 (Java e Algoritmos) vimos os conceitos básicos de classe como sendo a estrutura 
básica dos objetos. Se você ainda tem dúvidas sobre o que são classe e objetos 
recomendamos a leitura da matéria do módulo 1. 
O que precisamos entender, é que um sistema é composto por vários objetos. Um objeto é 
uma instância da classe e cada objeto ocupa um espaço na memória podendo ser acessado 
por meio das variáveis de referência. As variáveis de referência guardam o endereço do objeto 
e funciona com um controle remoto onde podemos acessar seus métodos e propriedades de 
acordo de suas visibilidades. 
 
 
 
 
 
 
 
2.1 Propriedades 
Os objetos possuem propriedades que servem para definir ou armazenar as características, 
campos ou atributos do objeto. No caso de um cliente, por exemplo, temos as propriedades: 
nome, CPF e RG. 
Exemplo de classe Cliente em Java 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 4 
Neste exemplo criamos a classe Cliente e instanciamos dois objetos com o comando new, no 
qual, cada objeto é uma cópia da classe na memória, com a mesma estrutura da classe. Os 
dados dos objetos são definidos no objeto. O objeto que possui nome “Jão da Silva” é 
totalmente independente do objeto que possui o nome “Maria da Silva”, embora os dois 
objetos vieram da mesma classe, eles não se conhecem por que estão em posições de 
memória diferentes. 
 
2.2 Métodos 
Os métodos como já vimos no modulo 1, são as funções que o objeto realiza. Um objeto 
Calculadora pode possuir os métodos: somar(), multiplicar(), subtrair (), e dividir(). 
 
Exemplo de criação de método 
class Calculadora{ 
public double somar(double n1, double n2){ 
return n1+n2; 
} 
} 
 
Exemplo de invocação por meio de um objeto instanciado 
public class ProgramaPrincipalMetodos { 
public static void main(String[] args) { 
Calculadora c = new Calculadora(); 
System.out.println(c.somar(10, 20)); 
} 
} 
 
Representação gráfica da classe (UML) 
O diagrama de classes é um dos diagramas da UML (Unified Modeling Language ou 
Linguagem de Modelagem Unificada) que é uma linguagem visual utilizada para modelar 
softwares que utilizam o padrão orientação a objetos. 
Voltando a classe Cliente podemos fazer sua representação gráfica utilizando o diagrama 
como abaixo. 
Diagrama de Classe 
 
Código Java 
public class Cliente { 
private String nome; 
private String cpf; 
private String rg; 
} 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 5 
3 MÉTODOS GETTERS E SETTERS 
No módulo 1 estudamos sobre os métodos encapsuladores getters e setters. Estes métodos 
são encapsuladores de propriedades e servem para atribuição (set) e acesso (get) às 
mesmas. 
 
Exemplo 
public class Cliente { 
private String nome; 
public String getNome() { 
return nome; 
} 
public void setNome(String nome) { 
this.nome = nome; 
} 
}Normalmente utilizamos os métodos getters e setters com modificadores de acesso público e 
das propriedades privadas. O modificador de acesso público permite a variável de instância a 
acessar o método e o modificador de acesso privado proíbe o acesso da propriedade pela 
instância. Para acessar uma propriedade privada somente um método da própria classe pode 
fazê-lo. 
Cliente cliente = new Cliente(); 
//Atribuindo o nome 
cliente.setNome("Jão da Silva"); 
//Acessando o nome 
System.out.println(cliente.getNome()); 
 
4 RELACIONAMENTOS ENTRE OBJETOS DO TIPO “TEM UM” 
É muito comum termos que relacionar os objetos de um sistema. Um sistema em 
funcionamento nada mais é que um conjunto de objetos trocando mensagens entre si. Em um 
corpo humano os órgãos se comunicam entre si, onde cada um faz a sua função. Um software 
não é diferente, pois precisamos arquitetar e estruturar nossos objetos de modo que eles se 
comuniquem e sirvam uns aos outros. 
Pensemos em um caso: Para definirmos uma cidade para um cliente como faríamos? Fácil, 
basta acrescentarmos um campo ou propriedade chamado Cidade na classe Cliente do tipo 
String. Certo? Sim, pode ser, mas na maioria dos casos uma cidade será um objeto a parte e 
independente do cliente, então, neste caso, ao invés de colocarmos um atributo ou 
propriedade do tipo String em nosso Cliente nós colocaremos uma propriedade do tipo cidade 
que ainda iremos construir. Podemos dizer que o cliente “tem uma” cidade vinculada a ele. 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 6 
Classe Cliente sem Relacionamento com Classe Cliente tem Relacionamento com 
Classe Cidade Classe Cidade 
public class Cliente { 
private String nome; 
private String cpf; 
private String rg; 
 
} 
 private String cidade; 
public class Cidade { 
private String nome; 
private String uf; 
} 
public class Cliente { 
private String nome; 
private String cpf; 
private String rg; 
 //getters and Setters 
} 
 private Cidade cidade; 
No primeiro caso, não teríamos o reaproveitamento das cidades e necessitaríamos sempre 
repetir o nome de uma mesma cidade várias vezes para clientes diferentes. 
 
Exemplo 
Cliente jao = new Cliente(); 
jao.setNome("Jão"); 
jao.setCidade("Campo Grande"); 
 
Cliente maria = new Cliente(); 
maria.setNome("Maria"); 
maria.setCidade("Campo Grande"); 
No segundo caso podemos construir apenas um objeto Cidade e reutilizá-lo em vários 
clientes. Na verdade, quem se relaciona são os objetos, porém, é na classe que escrevemos 
isso. Basicamente, o que devemos fazer é “setar” uma instância de Cidade na propriedade 
cidade do Cliente. 
 
Cidade cg = new Cidade(); 
cg.setNome("Campo Grande"); 
cg.setUf("MS"); 
 
Cliente jao = new Cliente(); 
jao.setNome("Jão"); 
jao.setCidade(cg);//Relacionamento com objeto Cidade 
 
Cliente maria = new Cliente(); 
maria.setNome("Maria"); 
maria.setCidade(cg);//Relacionamento com objeto Cidade 
 
Diagrama de Classe da UML 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 7 
 
No mundo real, vários clientes do sistema podem ter nascido em uma cidade. Na memória 
podemos imaginar vários objetos do tipo Cliente e vários objetos do tipo Cidade onde uma ou 
mais instâncias de clientes podem estar vinculados a uma mesma instância de cidade. 
 
Ao acessar um objeto tipo Cidade que está relacionado com um objeto tipo Cliente podemos, 
a partir da instância do Cliente, navegar no objeto Cidade porque a propriedade cidade nada 
mais é que uma referência para um objeto do tipo Cidade. Com o método getCidade() 
acessamos esta referência que foi “setada” para o cliente da instância jao. 
//Imprimindo dados da cidade do jao 
System.out.println(jao.getCidade().getNome() + " " + 
jao.getCidade().getUf()); 
 
Podemos, ainda, pensar na possibilidade de representarmos os estados de uma cidade como 
sendo objetos a parte. Ao invés de termos uma propriedade String uf, poderíamos ter uma 
propriedade do tipo Estado vinculado ao tipo Cidade, no qual, teríamos uma classe para 
representá-lo como no diagrama de classe abaixo: 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 8 
 
Na memória, agora temos um objeto do tipo Estado relacionado ao objeto do tipo Cidade. 
 
Criação Classe Estado Alteração da Classe Cidade 
public class Estado { 
 
 private String nome; 
private String uf; 
//getters and setters 
} 
public class Cidade { 
 
private String nome; 
private Estado estado; 
 //getters and setters 
} 
 
Agora nosso programa principal deve ser alterado para que possamos utilizar a propriedade 
UF em um objeto do tipo Estado e não mais diretamente na cidade como estava. Assim, já 
iremos corrigir o erro gerado: The method setUf(String) is undefined for the type Cidade, 
dizendo que não existe mais o método setUf(String) na cidade. 
Com uma instância de estado basta “setarmos” ele na cidade em sua nova propriedade de 
relacionamento estado. Para imprimir o estado da cidade do cliente, utilizamos a navegação 
por meio do método get. Primeiro acessamos o cliente, depois a cidade do cliente e por fim o 
estado da cidade conforme o código abaixo: 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 9 
1. public class ProgramaPrincipal { 
2. 
3. public static void main( String[] args ) { 
4. //Construção do Objeto Estado 
5. Estado ms = new Estado(); 
6. ms.setNome("Mato Grosso do Sul"); 
7. ms.setUf("MS"); 
8. 
9. //Construção do Objeto Cidade 
10. Cidade cg = new Cidade(); 
11. cg.setNome("Campo Grande"); 
12. //Relacionamento com o objeto Estado 
13. cg.setEstado(ms); 
14. 
15. Cliente jao = new Cliente(); 
16. jao.setNome("Jão da Silva"); 
17. jao.setCpf("999999999-99"); 
18. //Relacionamento com objeto Cidade 
19. jao.setCidade(cg); 
20. 
21. //Imprimindo dados da cidade do jao 
22. System.out.println(jao.getCidade().getNome()+ " " + 
 jao.getCidade().getEstado().getUf() + 
23. " "+ jao.getCidade().getEstado().getNome()); 
24. } 
25. } 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 10 
5 HERANÇA - RELACIONAMENTO DE OBJETOS DO TIPO “É UM” 
Em muitos casos, podemos ter 
a necessidade de trabalhar 
com classes mais genéricas e 
classes mais específicas. 
Vamos pensar na seguinte 
situação: 
Uma empresa necessita de 
um sistema de cadastros que 
possa ter o cadastro de várias 
pessoas, tais como Clientes, 
Fornecedores e Funcionários. 
Estes três tipos de cadastros 
possuem campos em comum 
(mais genéricos) e campos 
específicos que fazem parte 
exclusivamente daquele 
cadastro. Nós ainda não 
estamos trabalhando com tela 
em Java neste ponto do 
estudo, mas fizemos um 
rascunho (protótipo) quando 
estávamos conversando com 
o cliente, levantando suas 
necessidades (levantamento 
de requisitos) e pudemos 
observar que o cliente deseja 
algo semelhante às telinhas ao 
lado. 
O que vemos em comum 
nestes cadastros solicitados 
por nosso cliente? 
Primeiramente, que todos os 
cadastros, podemos 
considerar, são de uma 
mesma família mais genérica de objetos que podemos chamar de Pessoa. Podemos ver que 
todos, por se tratarem de pessoa, possuem um campo (propriedade) nome e também cidade, 
independente se é Cliente, Fornecedor ou Funcionário. Entre os cadastros temos uma 
variação de campos, em que cada formulário, além dos campos em comum, possui campos 
específicos, como no caso do funcionário que possui praticamente os mesmos campos de 
cliente, exceto um novo campo chamado cargo.Nesta situação vamos trabalhar com um tipo de relacionamento chamado de Herança ou 
relacionamento “É um”. Neste tipo de relacionamento nós criamos classes que conterão 
propriedades e métodos mais genéricos. Essas classes servem de “superclasse” ou classe 
base, para que outras possam estender, ou seja, esta classe contém propriedades e métodos 
que podem ser herdados. 
 As classes mais específicas ou classes filhas possuem a palavra reservada extends para 
especificar qual será sua classe base. Em outras palavras, as classes filhas que estendem as 
superclasses “esticam” a classe base por meio do extends. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 11 
A classe base ou superclasse tem suas características e a classe filha herda suas 
características e também adiciona novas propriedades e métodos específicos dela. Na 
instância do objeto da classe filha podemos ver os métodos e propriedades que foram 
estendidos. Senão existisse herança, nós teríamos que criar vários campos ou propriedades 
repetidas em cada classe. 
Classes sem Herança – Tentativa 1 
 
Desta forma, criamos uma classe individual para cada Cadastro sem herança e sem a 
reutilização de campos. 
public class Cliente{ 
private String nome; 
private String cpf; 
private String rg; 
private Cidade cidade; 
} 
public class Fornecedor{ 
private String nome; 
private String 
razaSocial; private 
String cnpj; private 
Cidade cidade; 
} 
Public class Funcionario{ 
private String nome; 
private String cpf; 
private String rg; 
private String cargo; 
private Cidade cidade; 
} 
 
Classes com Herança sendo 1 classe Genérica e 3 Específicas – Tentativa 2 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 12 
Desta forma, criamos uma classe Pessoa contendo os campos 
comuns para todos dos cadastros. Mas ainda parece que 
ficaram campos repetidos em Cliente e Funcionario. Não 
poderíamos colocar RG e CPF em Pessoa, senão 
comprometeríamos o Fornecedor que é Pessoa Jurídica. 
public class Pessoa { 
private String nome; 
private Cidade cidade; 
//getters e setters 
} 
public class Cliente 
extends Pessoa{ 
private String cpf; 
private String rg; 
} 
public class Fornecedor 
extends Pessoa { 
private String razaSocial; 
private String cnpj; 
} 
public class Funcionario 
extends Pessoa{ 
private String cpf; 
private String rg; 
private String cargo; 
} 
 
Classes com Herança com mais classes Genéricas e Específicas – Tentativa 3 
Deste jeito, pensamos de forma mais genérica ainda, criando uma classe Pessoa e classes 
filhas Pessoa Física e Pessoa Jurídica. Agora as classes Cliente e Funcionário estendem 
da classe PessoaFisica e a classe Fornecedor estende da classe PessoaJuridica. Assim, 
até se precisarmos em outras partes do sistema futuramente representar clientes do tipo 
PessoaJuridica com este modelo teremos mais suporte para isso. 
 
 
Classe mais Genérica Classes Filhas mais Específicas, mas ainda são Genéricas 
para suas filhas 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 13 
public class Pessoa { 
private String nome; 
private Cidade cidade; 
//getters e setters 
 
} 
public class 
PessoaFisica extends 
Pessoa { 
 
private String cpf; 
private String rg; 
//getters e setters 
 
} 
 
 
public class PessoaJuridica 
extends Pessoa { 
 private String cnpj; 
 private String razaSocial; 
 //getters e setters 
 
} 
 
Classes Filhas das Filhas ainda mais Específicas 
public class Cliente 
extends PessoaFisica{ 
//Todos campos comuns 
//Foram herdados 
} 
public class Fornecedor 
extends PessoaJuridica { 
//Todos campos comuns foram 
//herdados 
} 
public class Funcionario 
extends PessoaFisica { 
//Todos campos comuns 
//Foram herdados 
private String cargo; 
} 
 
Programa Principal 
Crie um programa principal para testar o acesso à propriedade nome a partir da instância de 
Cliente. 
public class ProgramaPrincipalCliente { 
 public static void main(String[] args) { 
Cliente cli = new Cliente(); 
cli. ??? // O que será que vai aparecer depois do ponto? 
} 
} 
Observe a diferença entre o ponto de vista do objeto e da classe. 
 
Do ponto de Vista do Objeto 
Acessando os métodos Get e Set do ponto de vista do objeto, ou seja, da instância em um 
Programa Principal, por exemplo, a IDE deve mostrar os métodos herdados e acessíveis. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 14 
 
Do ponto de Vista da Classe 
Se tentarmos acessar as propriedades privadas da classe base pela classe filha, acreditando 
que ela estará acessível, então nos deparamos com a situação de que isso não é possível. A 
Herança respeita os modificadores de acesso das propriedades, e isso só seria possível se 
nossa propriedade não fosse private e sim protected. Ao deixarmos uma propriedade 
protected estamos permitindo que a mesma seja acessível diretamente pelas classes filhas, 
livres de ter que acessar pelos métodos encapsuladores, como se a propriedade tivesse sido 
declara dentro da própria classe filha. 
A figura abaixo ilustra os métodos acessíveis pela classe Cliente. Vemos que possuem 
métodos getters e setters de Object, Pessoa e PessoaFisica. 
 
Tudo estende de java.lang.Object 
A classe java.lang.Object é a classe base padrão do Java, tudo estende de Object mesmo se 
não colocarmos o comando extends Object. Só podemos herdar uma classe por vez, não 
havendo herança múltipla como em outras linguagens, ou seja, cada classe filha só pode ter 
uma classe base e essa classe base também pode ter outra classe base e assim por diante 
até chegar no topo da hierarquia que é a classe Object. 
 
 
 
 
 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 15 
 
Protected do ponto de vista da classe 
Se colocarmos na propriedade nome da classe Pessoa o modificador protected, podemos 
acessá-lo diretamente pela classe filha. Faça a seguinte experiência, na classe Cliente, 
adicione um método calcularPontuacao para tentarmos acessar de dentro do método a 
propriedade nome da classe Pessoa. 
public class Pessoa { 
protected String nome; 
 
} 
public class Cliente extends 
PessoaFisica{ 
public void calculaPontuacao(){ 
} 
} 
 
 
Na IDE (Eclipse ou Netbeans) você já pode ver que isso é possível utilizando o recurso de 
auto complete (ctrl+ espaço) como na imagem abaixo. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 16 
 
Assim, podemos acessar essa propriedade de forma direta para atribuirmos um valor ou para 
recuperarmos seu valor para impressão. Uma forma utilizada também é por meio do comando 
this ficando this.nome. 
 
Protected do ponto de vista da instância 
Podemos acessar da instância uma propriedade protected diretamente? Resposta: Vai 
depender dos pacotes. Se a classe que possui a instância de Cliente como o 
ProgramaPrincipal estiver no mesmo pacote que a classe Cliente então sim, a propriedade 
fica de livre acesso, podendo ser acessada diretamente como se ela fosse do modificador 
default. E as classes estiverem em pacotes diferentes então não é possível acessar a 
propriedade protected, precisando, assim, utilizar os métodos encapsuladores getters e 
setters. 
Instância em classe no mesmo pacote Instância em classe em pacote diferente 
 
Neste exemplo, podemos ver claramente a 
possibilidade de acesso da propriedade nome 
pela instância de cliente noprograma principal. 
Para ficar fácil de entender pense que do ponto 
de vista da instância a regra é a mesma do 
modificador default. 
Mova a classe Pessoa que possui a 
propriedade protected para um pacote 
diferente, “temp”, por exemplo. 
 
package br.com.fabricadeprogramador 
.temp; 
//imports aqui 
public class Pessoa { 
protected String nome; 
//restante da classe aqui 
} 
Na instância tente acessar 
Veja que aparecem os métodos, mas não a 
propriedade nome. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 17 
5.1 Instanciando Polimorficamente 
É possível declarar uma variável do tipo mais genérico apontando para um objeto de uma 
classe filha bem mais específico? Sim, a isso chamamos de atribuições polimórficas. Veja no 
exemplo abaixo. 
package br.com.fabricadeprogramador.sistemacadastro; 
import br.com.fabricadeprogramador.temp.Pessoa; 
public class ProgramaPrincipalPolimorfismo { 
public static void main(String[] args) { 
Object objeto = new Funcionario(); 
Pessoa pessoa = new Funcionario(); 
PessoaFisica pessoaFisica = new Funcionario(); 
Funcionario funcionario = new Funcionario(); 
} 
} 
Quando uma classe filha estende uma classe base, dizemos que um objeto da classe filha “é 
um (a)” do objeto classe base. 
Exemplo 
Podemos declarar variáveis de um tipo mais genérico para armazenar referências a objetos 
mais específicos. Uma variável do tipo Object pode apontar para um objeto do tipo Funcionario 
porque o mesmo passa no teste “é um”, ou seja, um funcionário “é um” Object, mesmo que 
não herda diretamente, mas no topo da hierarquia sabemos que tudo herda de Object. Uma 
variável do tipo Pessoa pode apontar para um objeto Funcionario porque funcionário “é uma” 
Pessoa. Uma variável do tipo PessoaFisica pode apontar para um objeto do tipo Funcionario 
porque funcionário “é uma” PessoaFisica. Uma variável do tipo Funcionario pode apontar 
para um objeto Funcionario porque funcionário “é um” Funcionario. 
A figura abaixo mostra que todos podem apontar para um Funcionário, porém, os que estão 
mais abaixo ou específicos podem ver mais detalhes do objeto, porque a variável de 
referência limita o acesso as propriedades e métodos do objeto de acordo com seu tipo. 
Um tipo Object embora aponte para um objeto Funcionario não pode ter acesso a tudo do 
funcionário, podendo acessar apenas o que corresponde ao tipo Object. Um objeto funcionário 
é constituído de várias partes, sendo a parte de Object, a parte de Pessoa, a parte de 
PessoaFisica e a parte de Funcionario. A soma destas heranças é o funcionário completo, 
mas quem pode ter acesso completo é apenas uma referência do tipo Funcionario. A variável 
do tipo Object é a mais limitada quanto ao acesso ao objeto Funcionário e a variável do tipo 
Funcionário é a mais completa. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 18 
 
5.2 Fazendo Conversões (Casting) 
É possível fazermos conversões de tipos desde que os objetos sejam da mesma família. Em 
nosso exemplo anterior temos uma instância de funcionário sobre uma referência do tipo 
Object. O Objeto instanciado e do tipo Funcionário, mas a referência declarada foi do tipo 
Object, então essa variável de referência mesmo podendo acessar o objeto, está limitada pelo 
seu tipo declarado não podendo acessar tudo de um objeto Funcionario. 
Mas será possível a variável do tipo Object invocar o método setCargo(String)? Sim, se 
fizermos uma conversão ou casting. Fazer um casting na variável Object objeto para o tipo 
Funcionário é como “esticar” a capacidade dela para que ela possa acessar o objeto completo. 
O que estamos fazendo é tornando a visão de variável que é mais genérica em uma “lupa” 
para ver os detalhes de um objeto mais específico. Veja: 
 
“Setando” um cargo no funcionário fazendo casting 
((Funcionario)objeto).setCargo("Motorista"); 
 
“Getando” o cargo do funcionário 
objeto.getCargo(); 
Se tentarmos acessar diretamente o método getCargo na variável que fizemos o casting, não 
teremos acesso e receberemos a seguinte mensagem: 
The method getCargo() is undefined for the type Object 
Isso porque o casting não altera o tipo original da variável mantendo como sendo do tipo 
Object. Para acessarmos o método getCargo temos que fazer novamente um casting da 
seguinte forma: 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 19 
((Funcionario)objeto).getCargo(); 
Assim como podemos “esticar” a visibilidade também podemos “encolher”. Para um objeto do 
tipo Funcionário podemos fazer um casting para torná-lo de o tipo mais Genérico como: 
Funcionario funcionario = new Funcionario(); 
((PessoaFisica) funcionario).setCpf("99009"); 
 
5.3 Sistema de Cadastro de Pessoas 
Um exemplo de uso de atribuições polimórficas seria criarmos um sistema de cadastro 
Genérico, no qual podemos passar por parâmetro uma instância de qualquer objeto da família 
de Pessoa, ou seja, qualquer objeto de uma classe que estenda da classe Pessoa. No 
exemplo abaixo a variável genérica Pessoa recebe um objeto como parâmetro e o armazena 
em um vetor Genérico de Pessoa. 
public class SistemaCadastro { 
Pessoa pessoas[] = new Pessoa[3]; 
int numEntradas = 0; 
/** Entrada Generica 
 * @param pessoa 
 */ 
public void cadastrar (Pessoa pessoa){ 
if(numEntradas < pessoas.length){ 
pessoas[numEntradas] = pessoa; 
numEntradas++; 
} 
} 
} 
 
Agora na hora de imprimir teremos que utilizar a técnica de conversão para imprimir os dados 
específicos de um objeto Pessoa. Como nosso vetor de pessoas é genérico e armazena 
vários tipos de pessoas diferentes, como Cliente, Fornecedor e Funcionário então temos que 
utilizar o instanceof para verificar qual o tipo do objeto da referência para realizar a conversão 
e acessar as propriedades específicas. 
/** 
* Impressao de forma especifica 
*/ 
public void imprimir (){ 
for (int i = 0; i < pessoas.length; i++) { 
System.out.println(pessoas[i].getNome()+ ""); 
 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 20 
 
//Funcionario 
if(pessoas[i] instanceof Funcionario){ 
 
//casting 
Funcionario func = (Funcionario) pessoas[i] ; 
System.out.print(func.getSalario() + " " + func.getCargo()); 
} 
//Faça para Cliente 
//Faça para Fornecedor 
} 
} 
 
Convertendo de String para Inteiro 
Quando os objetos não são da mesma família hierárquica não podemos utilizar a mesma 
técnica de casting. É possível fazermos uma conversão de uma String para número inteiro 
então? Da seguinte forma, não. 
String numeroStr = "10"; 
Integer n = (Integer)numeroStr; 
A solução para este caso é a chamada a um o método static de conversão parseInt da classe 
Integer ou chamada de um construtor especial que suporta uma entrada String. 
String numeroStr = "10"; 
Integer n1 = Integer.parseInt(numeroStr); 
Integer n2 = new Integer(numeroStr); 
 
6 MÉTODOS E PROPRIEDADES ESTÁTICAS 
Um método estático é um método que não está ligado a instância do objeto. Para invocar um 
método estático basta colocarmos o nome da classe, um ponto e nome do método como: 
Integer.parseInt("10"); 
 
Uma propriedade estática é uma propriedade da classe e não do objeto. Isso quer dizer que 
o valor dela não pode ser diferente para cada instância. Para toda instância de Integer a 
propriedade MAX_VALUE sempre terá o mesmo valor. 
Integer maximoInt = Integer.MAX_VALUE; 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 21 
As propriedades estáticas não servem para manter o ”estado” do objeto. Entende-se por 
estado do objetoos valores atribuídos em suas propriedades para uma determinada instância. 
No exemplo abaixo os objetos estão com estados diferentes porque suas propriedades não 
são estáticas e os dados atribuídos são diferentes. 
Funcionario jao = new Funcionario(); 
jao.setNome("Jão da Silva"); 
jao.setCargo("Cientista da Computação"); 
 
Funcionario maria = new Funcionario(); 
maria.setNome("Maria da Silva"); 
maria.setCargo("Analista de Sistemas"); 
 
Em nosso caso, será comum utilizarmos métodos estáticos em nossa aplicação para criarmos 
classes com métodos utilitários. 
Exemplo 
public class ValidacaoUtil { 
public static void validarCpf(String cpf) { 
//implementação aqui 
} 
public static void validarCnpj(String cnpj) { 
//implementação aqui 
} 
public static void validarEmail(String email) { 
//implementação aqui 
} 
} 
A invocação dos métodos estáticos não necessita de instância. 
public static void main(String[] args) { 
ValidacaoUtil.validarCnpj("10.797.626/0001-88"); 
ValidacaoUtil.validarCpf("905.044.567-92"); 
ValidacaoUtil.validarEmail("contato@htcursos.com"); 
} 
O main é estático! O método principal public static void main(String[] args) é estático, por se 
tratar de um método principal não sendo necessário a JVM instanciar um objeto do nosso 
programa principal para invoca-lo. Um método estático somente pode alterar valores de 
variáveis também estáticas. O código abaixo não pode irá funcionar por que a propriedade 
não é estática e está tentando ser acessar por um método estático. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 22 
public class ValidacaoUtil { 
String cpf; //propriedade não estática 
public static void validarCpf(String cpf) { 
 
//Cannot make a static reference to the non-static field numero 
this.cpf =cpf; 
} 
} 
Ao utilizarmos métodos estáticos, também não utilizamos a palavra reservada this, porque ela 
quer dizer “esta instância atual” e com os métodos estáticos não estamos trabalhando com a 
instância. Certo? 
O código abaixo pode ser feito. 
public class ValidacaoUtil { 
static String cpfEstatico; 
// propriedade estática 
public static void validarCpf(String cpf) { 
cpfEstatico = cpf; 
} 
} 
 
 
7 SOBRECARGA E SOBRESCRITA DE MÉTODOS 
Em Java vimos que a classe mais genérica é a java.lang.Object. A classe Object do java 
possui vários métodos implementados, abaixo vamos listar dois deles: toString( ) e equals( 
Object obj). 
public String toString() {} 
Retorna uma String representando 
uma versão texto do objeto. 
Ao tentarmos imprimir uma variável de 
instancia do objeto o método toString é 
invocado automaticamente. 
Por padrão o método retorna uma 
String com uma referência ao objeto 
como: 
br.com.fabricadeprogramador.sist
emacadastro.Cliente@13d9c02 
Exemplo de chamada: 
Cliente cli = new Cliente(); 
System.out.println(cli); 
 
System.out.println(cli.toString()); 
public boolean equals(Object obj) {} Este método verifica se o objeto atual é 
igual ao outro passado no parâmetro. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 23 
Exemplo de chamada: 
1. Cliente cli1 = new Cliente(); 
2. cli1.setNome("jão"); 
3. 
4. Cliente cli2 = new Cliente(); 
5. cli2.setNome("jão"); 
6. 
7. boolean iguais = cli2.equals(cli1); 
8. System.out.println(iguais); 
Seu critério de igualdade é a referência, 
ou seja, somente se os objetos 
estiverem na mesma posição de 
memória, então, serão considerados 
iguais. 
No exemplo ao lado temos 2 clientes 
com o mesmo nome, porém em objetos 
diferentes, ou seja, em posições 
diferentes de memória, logo o retorno 
será false na comparação da linha 7. 
 
Os métodos da classe base Object que acabamos de estudar já possuem uma implementação 
padrão. Mas seria possível modificarmos essa implementação? E se quisermos considerar 
que duas instâncias diferentes de objetos do tipo Cliente com o mesmo CPF sejam 
considerados clientes iguais, mesmo que estão em posições de memória diferentes? Neste 
caso nós temos que modificar o método equals da classe Object, porém se fosse possível 
fazer isso diretamente na classe Object nós comprometeríamos todos os objetos do sistema 
porque todos herdam de Object. 
Então será possível modificarmos somente o método toString da classe Cliente para fazer 
essa adaptação para nossa necessidade específica? Sim, é possível, isso é conhecido como 
sobrescrita de método, ou seja, escrever uma “por cima” ou sobre do método herdado da 
classe base na classe filha. 
 
7.1 Sobrescrevendo o Método toString() 
public class Cliente extends PessoaFisica{ 
public String toString() { 
return getNome() + " "+ getCpf(); 
} 
//demais métodos 
} 
Desta forma agora ao executarmos o código abaixo a saída será o nome e o CPF 
concatenados do objeto Cliente. 
Cliente cli1 = new Cliente(); 
cli1.setNome("jão"); 
cli1.setCpf("999.999.999-99"); 
 
System.out.println(cli); 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 24 
7.2 Sobrescrevendo o Método equals(Object obj) 
Queremos que o critério de comparação seja o CPF e o RG do cliente, ou seja, se dois clientes 
com mesmo CPF e RG são comparados pelo método equals então o retorno deve ser true. 
public class Cliente extends PessoaFisica{ 
 public boolean equals(Object obj) { 
 
//Se os objetos estiverem na mesma posição de memória 
if (this == obj) 
return true; 
 
 //Convertendo (casting) o tipo Object para o tipo PessoaFisica 
PessoaFisica outro = (PessoaFisica) obj; 
//se não forem iguais retorna falso 
if(!cpf.equals(outro.cpf)) 
return false; 
//se não forem iguais retorna falso 
if(!rg.equals(outro.rg)) 
return false; 
//se não passou 
return true; 
} 
 
 public String toString() 
return getNome() + " "+ getCpf(); 
} 
} 
 
7.3 Utilizando a IDE para Gerar o Método Equals e Hashcode 
Melhorando o método hashcode e equals de Cliente utilizando a ferramenta da IDE eclipse 
ou Netbeans. No eclipse o acesso é pelo menu source / generator hashcode and equals. 
 
public boolean equals(Object obj){ 
 
if (this == obj) 
return true; 
if (obj == null) 
return false; 
if (getClass() != obj.getClass()) 
return false; 
 
PessoaFisica other = (PessoaFisica)obj; 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 25 
if (cpf == null) { 
if (other.cpf != null) 
 return false; 
} else if (!cpf.equals(other.cpf)) 
return false; 
 
 
if (rg == null) { 
if (other.rg != null) 
return false; 
} else if (!rg.equals(other.rg)) 
return false; 
return true; 
} 
 
7.4 HashCode 
Muito usado nas estruturas de dados que iremos ver mais a frente, mas, por esse momento, 
precisamos entender que este é um número que representa um objeto toda vez que os valores 
de suas propriedades estipuladas no método estiverem iguais, o mesmo hashcode deve ser 
gerado, neste exemplo quando uma pessoa possuir o mesmo RG e o mesmo CPF um código 
de hashcode será gerado idêntico porque o método utiliza dos dados destas propriedades 
para dar origem ao número de hashcode. Em estrutura de armazenamento HashMap e 
HashSet iremos ver isso na prática. 
 
public int hashCode() { 
final int prime = 31; 
int result = 1; 
result = prime * result + ((cpf == null) ? 0 : cpf.hashCode()); 
result = prime * result + ((rg == null) ? 0 : rg.hashCode()); 
return result; 
} 
 
7.5 A Palavra Reservada This 
A palavra reservada this sempre será usada dentro da classe para fazer referência à instância 
atual. Noexemplo anterior no trecho de código abaixo podemos ler: “se a referência da 
instância atual (this) for igual a referência à instância obj então return true”. 
if (this == obj) 
return true; 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 26 
8 CONSTRUTORES 
Os construtores são como um método chamado somente no momento de construirmos um 
objeto. Um objeto é construído quando é alocado na memória. Não iremos tratá-lo como 
método por não acessarmos pela variável de referência por meio do operador de acesso 
ponto. Mas tem uma sintaxe parecida com a de um método, exceto por não possuir tipo de 
retorno. O construtor sempre leva o nome da Classe. O construtor é chamado por meio do 
operador new. Exemplo: new Cliente(); 
 
Construtor Padrão 
Este é o construtor sem parâmetros de entrada. Todo construtor ao ser chamado executa 
primeiro o construtor da classe base. O objeto vai sendo construído de cima para baixo, ou 
seja, primeiro o construtor da classe Object é executado e depois o construtor das classes 
filhas na ordem da herança. A chamada super() invoca o construtor da classe base. Mesmo 
se não escrevermos um construtor padrão na classe, o compilador irá escrever no bytecode 
gerado, mesmo que não apareça em nosso código fonte, exceto quando nós escrevermos 
algum construtor sobrecarregado, que veremos logo a frente. 
public class Pessoa { 
protected String nome; 
private Cidade cidade; 
public Pessoa() { 
super(); 
} 
} 
 
Chamada ao construtor padrão de Pessoa 
Pessoa pessoa = new Pessoa(); 
 
8.1 Construtor Sobrecarregado 
É um construtor que possui parâmetros de entrada, ou seja, uma nova versão de um 
construtor. Podemos criar várias versões de construtores, em que cada versão suporta tipos 
diferentes de entradas como parâmetros. No exemplo abaixo temos o construtor padrão e um 
construtor sobrecarregado que suporta uma String e uma Cidade como entrada, sendo o 
primeiro para iniciar o objeto com um valor “setado” nas propriedades nome e cidade de 
Pessoa. 
Sobrecarregando o construtor de Pessoa 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 27 
public class Pessoa { 
protected String nome; 
private Cidade cidade; 
public Pessoa() { 
super(); 
} 
public Pessoa(String nome, Cidade cidade) { 
super(); 
this.nome = nome; 
this.cidade = cidade; 
} 
} 
 
Exemplo de chamada 
new Pessoa("Jão", new Cidade()); 
 
Se ao instanciarmos um objeto da classe Cliente já quisermos informar o seu nome? Temos 
que criar um construtor sobrecarregado na classe Cliente. 
public class Cliente extends PessoaFisica{ 
public Cliente() { 
super(); 
} 
public Cliente(String nome) { 
//Método Herdado 
setNome(nome); 
} 
} 
 
Agora já podemos fazer a chamada ao construtor sobrecarregado da forma abaixo. 
new Cliente("Jão"); 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 28 
8.2 Sobrecarregando o Construtor de Cidade 
public class Cidade { 
private String nome; 
private Estado estado; 
 
 public Cidade() { 
super(); 
} 
public Cidade(String nome) { 
super(); 
this.nome = nome; 
} 
public Cidade(String nome, Estado estado) { 
super(); 
this.nome = nome; 
this.estado = estado; 
} 
} 
 
Agora com o construtor sobrecarregado podemos, no momento da construção do objeto 
Pessoa, já passarmos dois objetos como parâmetro de entrada, sendo uma instância de String 
e uma instância de Cidade. 
Pessoa pessoa = new Pessoa("Jão", new Cidade(“Campo Grande”)); 
 
8.3 Lembrando dos Estáticos 
Agora como já conhecemos o uso dos construtores vamos utilizá-lo combinando com uma 
propriedade estática para armazenar a quantidade de clientes que já foram instanciados. 
public class Cliente extends PessoaFisica{ 
private static int quantidadeCliente=0; 
 
public Cliente() { 
quantidadeCliente++; 
} 
public static int getQuantidadeCliente() { 
return quantidadeCliente; 
} 
} 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 29 
 
Imprimindo o número de instâncias de Objetos cliente 
package br.com.fabricadeprogramador.sistemacadastro.construtores; 
import br.com.fabricadeprogramador.sistemacadastro.Cliente; 
public class ProgramaPrincipalClientes { 
public static void main(String[] args) { 
new Cliente(); 
new Cliente(); 
new Cliente(); 
System.out.println(Cliente.getQuantidadeCliente()); 
} 
} 
 
9 SOBRECARGA DE CONSTRUTORES 
Exemplos de uso de construtores sobrecarregados nos tipos básicos do Java. 
Construtores sobrecarregado do tipo java.lang.Integer 
//Construtor sobrecarregado parâmetro String 
Integer numero1 = new Integer("10"); 
//Construtor sobrecarregado parâmetro int 
Integer numero2 = new Integer(10); 
 
Alguns construtores Sobrecarregados do java.lang.String 
String texto1 = new String(); 
String texto2 = new String(new byte[3]); 
String texto3 = new String(new char[3]); 
String texto4 = new String("Fábrica de Programador"); 
String texto5 = new String(new StringBuffer()); 
 
10 MÉTODOS SOBRECARREGADOS 
Assim como sobrecarregamos os construtores também sobrecarregamos os métodos. Ao 
sobrecarregarmos os métodos temos que tomar o cuidado para sempre deixar o modificador 
de acesso com o mesmo nível ou mais alto. Um método private não pode ser sobrescrito. Se 
o método for default, o mesmo pode ser sobrescrito por default ou por public. Se o método 
for public não pode ser sobrescrito por default. 
public class ValidacaoUtil { 
 static String cpfEstatico; // propriedade não estática 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 30 
public static void validarCpf(String cpf) { 
//valida CPF com os pontos (mascara) 
} 
public static void validarCpf(Integer cpf){ 
//valida CPF sem os pontos (mascara) 
} 
} 
11 CLASSES ABSTRATAS 
Classes abstratas são classes que possuem métodos abstratos, ou seja, apenas a declaração 
do método sem sua implementação. Quando uma classe possui um método abstrato então a 
classe vira abstrata. Uma classe abstrata não pode ser instanciada, por que possuem 
métodos sem implementação. Declaramos um método abstrato quando não queremos uma 
implementação genérica padrão. Desta forma as classes filhas são obrigadas a implementar 
o método abstrato. Dizemos que as classes filhas assinam um contrato onde elas concordam 
em implementar os métodos abstratos da classe base abstrata. No exemplo abaixo vamos 
mostrar um caso, no qual definimos que uma classe que estende de Funcionário deve possuir 
uma implementação específica para o método calculoSalario. Assim a classe filha Analista e 
Diretor devem implementar o método abstrato conforme seu tipo específico. 
public abstract class Funcionario extends PessoaFisica { 
private String cargo; 
public String getCargo() { 
return cargo; 
} 
public void setCargo(String cargo) { 
this.cargo = cargo; 
} 
public abstract double calculoSalario(); 
} 
Agora a classe que estende funcionário deve implementar o método abstrato da classe base. 
Um Analista que é um Funcionário que tem seu cálculo de salário diferente de um diretor com 
5% a mais de diferença do salário base. 
public class Analista extends Funcionario{ 
public double calculoSalario() { 
return getSalario() + (getSalario()*5/100); 
} 
} 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 31 
Um Diretor é um Funcionário e logo deve implementar o método abstrato da classe base com 
10% a mais de diferençado salário base. 
public class Diretor extends Funcionario { 
public double calculoSalario() { 
return getSalario() + (getSalario()* 10/100); 
} 
} 
 
12 INTERFACES 
As interfaces nos permitem definir apenas o padrão de funcionamento ou comportamento dos 
objetos. Ela é uma classe 100% abstrata não tendo propriedades e nem métodos concretos 
(não abstratos). Usamos interfaces quando queremos trabalhar de forma mais genéricas na 
família dos objetos sem entrar nos detalhes da implementação. Como analogia podemos 
pensar nos componentes de um carro do mundo real. Eles são todos baseados em interfaces. 
A interface Roda do carro diz que a rodas são de 4 furos e seu tamanho é 15. Existem vários 
modelos de rodas para esse carro. A interface é o modelo de encaixe que define o padrão e 
a roda propriamente dita é a implementação da interface. Podemos trocar de roda quando 
quisermos desde que obedeça esse padrão estabelecido pela interface Roda. Assim é para 
todos os componentes do carro, podemos trocar de som, trocar de volante, de rodas e de 
peças porque o modelo dos componentes foi padronizado em interfaces. Isso garante que 
podemos trocar de fabricante de pneus, de sons e etc. 
Em nosso sistema vamos criar um Interface que irá padronizar um Pedido de um sistema de 
pedidos. Nesta interface iremos apenas definir ou declarar os métodos que o sistema de 
pedidos deve possuir. Com o código abaixo iremos construir a Interface Pedido, ou seja, o 
padrão que uma implementação de Pedido deve assumir. 
public interface Pedido { 
 
public Integer getCodigo() 
 
public Double calcularValorTotal() 
public void adicionarItem(ItemPedido itemPedido); 
public void removerItemPedido(ItemPedido itemPedido); 
public void imprimirItens(); 
public ItemPedido[] ordenarItensPedidos(); 
public ItemPedido[] getItensPedidos(); 
} 
 
Um pedido será constituído de vários itens que iremos chamar de ItemPedido. Vários objetos 
podem ser considerados como Itens a serem pedidos em sistema comercial. Por exemplo, 
em uma escola podemos ter objetos Livros e Cursos que podem compor um Pedido que é 
uma compra. Em uma pizzaria podemos ter Pizza, Refrigerante, Sucos como sendo itens do 
Pedido e assim por diante. Na maioria das vezes neste caso uma classe Produto poderia ser 
utilizada para representar os itens de um Pizzaria de forma mais genérica. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 32 
Vamos criar uma Interface para definir a representação de um Item de um Pedido. 
public interface ItemPedido { 
//utilizado para garantir uma ordenação 
public Integer getCodigo() ; 
public void setCodigo(Integer codigo); 
public Double getValor() ; 
public void setValor(Double valor); 
public String getDescricao() ; 
public void setDescricao(String descricao); 
} 
Com esta interface nós garantimos alguns métodos para cada ItemPedido. 
 
12.1 Implementando as Interfaces 
Vamos agora fazer a implementação da interface ItemPedido. Esta interface faz com que um 
objeto possa possuir o comportamento padrão de um itemPedido. Um exemplo de item que 
pode compor um pedido é um Curso. Então façamos a classe Curso implementar a Interface 
ItemPedido por meio da palavra reservada implements. 
public class Curso implements ItemPedido { 
 
// propriedade para os métodos definidos na interface 
private Integer codigo; 
private Double valor; 
private String descricao; 
// Propriedade especificas 
private String conteudo; 
private String publicoAlvo; 
private String cargaHoraria; 
public Integer getCodigo() { 
return codigo; 
} 
public void setCodigo(Integer codigo) { 
this.codigo = codigo; 
} 
 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 33 
public Double getValor() { 
return valor; 
} 
public void setValor(Double valor) { 
this.valor = valor; 
} 
public String getDescricao() { 
return descricao; 
} 
public void setDescricao(String descricao) { 
this.descricao = descricao; 
} 
 //Outros métodos aqui 
} 
 
Um outro exemplo de um ItemPedido pode ser um Livro. 
import java.util.Date; 
public class Livro implements ItemPedido { 
//propriedade para os métodos definidos na interface 
private Integer codigo; 
private Double valor; 
private String descricao; 
// Propriedade especificas 
private String autor; 
private String editora; 
private Date dataPublicacao; 
 
public Integer getCodigo() { 
return codigo; 
} 
public void setCodigo(Integer codigo) { 
this.codigo = codigo; 
} 
 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 34 
public Double getValor() { 
return valor; 
} 
public void setValor(Double valor) { 
this.valor = valor; 
} 
public String getDescricao() { 
return descricao; 
} 
public void setDescricao(String descricao) { 
this.descricao = descricao; 
} 
 //Outros métodos aqui 
} 
 
Agora vamos implementar o Pedido utilizando uma classe PedidoImpl, em que o sufixo Impl 
é apenas uma abreviação de Implementação como convenção. A classe que implementa a 
interface decide como trabalhar os métodos. 
public class PedidoImpl implements Pedido { 
private Integer codigo; 
private Date data; 
private Cliente cliente; 
private ItemPedido itens[]; 
 
public Integer getCodigo() { 
// Implementação aqui 
} 
public Double calcularValorTotal() { 
// Implementação aqui 
} 
public void adicionarItem(ItemPedido itemPedido) { 
// Implementação aqui 
} 
public void removerItemPedido(ItemPedido itemPedido) { 
// Implementação aqui 
} 
public void imprimirItens() { 
// Implementação aqui 
} 
public ItemPedido[] ordenarItensPedidos() { 
// Implementação aqui 
} 
public ItemPedido[] getItensPedidos() { 
// Implementação aqui 
} 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 35 
// Outros métodos aqui 
} 
 
Programa Principal de exemplo para construção de um Pedido 
public class ProgramaPrincipalPedido { 
 
public static void main(String[] args) { 
Pedido pedido = new PedidoImpl(); 
 
int codigoItem = 1; 
 
ItemPedido livro = new Livro(); 
livro.setCodigo(codigoItem); 
livro.setValor(120.50); 
livro.setDescricao("Livro de Java"); 
 
ItemPedido curso1 = new Curso(); 
curso1.setCodigo(++codigoItem); 
curso1.setDescricao("Desenvolvimento para Android"); 
ItemPedido curso2 = new Curso(); 
curso2.setCodigo(++codigoItem); 
curso2.setDescricao("Fábrica de Programador"); 
 
pedido.adicionarItem(livro); 
pedido.adicionarItem(curso1); 
pedido.adicionarItem(curso2); 
 
pedido.imprimirItens(); 
 
double total = pedido.calcularValorTotal(); 
System.out.println(total); 
 
pedido.removerItemPedido(curso1); 
double novoTotal = pedido.calcularValorTotal(); 
System.out.println(novoTotal); 
pedido.ordenarItensPedidos(); 
pedido.imprimirItens(); 
} 
} 
 
Anônimos - Um gerenciador de Registros Genérico 
Uma classe anônima pode ser construída a partir de uma instância de um objeto que é 
construído de forma oculta ao tentarmos iniciar uma Interface. Podemos alterar o 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 36 
ProgramaPrincipalPedido para incluir um objeto que não possui uma classe, porém ele 
implementa a interface ItemPedido. Um objeto anônimo com referência. 
ItemPedido curso2 = new Curso(); 
curso2.setCodigo(++codigoItem); 
curso2.setDescricao("Fábrica de Programador"); 
 
//Construção de um objeto anonimo do tipo ItemPedido 
ItemPedidoitemAnonimo = new ItemPedido() { 
public void setValor(Double valor) { 
//Implementação do anonimo aqui 
} 
public void setDescricao(String descricao) { 
//Implementação do anonimo aqui 
} 
public void setCodigo(Integer codigo) { 
//Implementação do anonimo aqui 
} 
public Double getValor() { 
//Implementação do anonimo aqui 
return null; 
} 
public String getDescricao() { 
//Implementação do anonimo aqui 
return null; 
} 
public Integer getCodigo() { 
//Implementação do anonimo aqui 
return null; 
} 
}; 
pedido.adicionarItem(livro); 
pedido.adicionarItem(curso1); 
pedido.adicionarItem(curso2); 
pedido.adicionarItem(itemAnonimo); 
 
Construindo a instância de um objeto anônimo e já passando como parâmetro no 
método sem referência 
pedido.adicionarItem(new ItemPedido() { 
public void setValor(Double valor) { 
//Implementação do anonimo aqui 
} 
 
 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 37 
public void setDescricao(String descricao) { 
//Implementação do anonimo aqui 
} 
public void setCodigo(Integer codigo) { 
//Implementação do anonimo aqui 
} 
public Double getValor() { 
//Implementação do anonimo aqui 
return null; 
} 
public String getDescricao() { 
//Implementação do anonimo aqui 
return null; 
} 
public Integer getCodigo() { 
//Implementação do anonimo aqui 
return null; 
} 
}); 
 
13 GENÉRICOS - UM GERENCIADOR DE REGISTROS GENÉRICO 
A interface genérica Gerenciador Registro padroniza o comportamento de um objeto que tem 
a função de gerenciar registros. Essa interface garante que se o objeto terá um a função de 
gerenciar registro em um arquivo de texto, um vetor ou até mesmo em um banco de dados, 
ele deverá realizar no mínimo os métodos que estão declarados nela. 
public interface GerenciadorRegistro<T> { 
public void salvar(T obj); 
public void excluir(T obj); 
public void pesquisar(T obj); 
public void imprimirTodos(); 
} 
 
Conforme falamos, este gerenciador define as operações básicas de um gerenciador de 
registros onde podemos utilizar esta interface para construir um Gerenciador de registro de 
Pedido, de Clientes, Cidades, Estados e etc. 
O tipo parametrizado <T> quer dizer que o tipo do objeto que o método deverá suportar com 
parâmetro de entrada e de retorno vai ser definido pela classe que implementar a interface. 
Uma classe pode dizer que <T> é Cidade por exemplo desde modo: 
GerenciadorRegistro<Cidade>, ou dizer que é Estado, GerenciadorRegistro<Estado>, ou 
Pedido como: GerenciadorRegistro<Pedido>. O que precisamos entender é que o <T> é que 
faz a classe ficar genérica. 
Exemplo de implementação para um Gerenciador de Registros (GR) de Cidades 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 38 
public class GRCidade implements GerenciadorRegistro<Cidade> { 
public void salvar(Cidade obj) { 
// Implementação aqui 
} 
public void excluir(Cidade obj) { 
// Implementação aqui 
} 
public void pesquisar(Cidade obj) { 
// Implementação aqui 
} 
public void imprimirTodos() { 
// Implementação aqui 
} 
} 
No exemplo acima o GRCidade que define qual será a estrutura de armazenamento e 
independente disso deve possuir os métodos da interface implementados para garantir seu 
funcionamento como Gerenciador de Registros. 
 
14 TRABALHANDO COM COLEÇÕES 
Estrutura da API do java para tratar coleções de objetos. 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 39 
14.1 List 
Uma lista dinâmica de objetos organizada em vetor e acessível por meio de índices que aceita 
objetos duplicados. Na API () padrão do Java iremos utilizar várias classes que utilizam tipos 
genéricos como uma lista de objetos da Interface List<E>. 
java.util.List<E> é uma interface que possui uma implementação padrão em java 
java.util.ArrayList<E>. Esta interface define o comportamento padrão de uma Lista Dinâmica. 
Um ArrayList nos permite armazenar objetos em um Array Dinâmico de objetos, ou seja, a 
alocação do objeto na posição do vetor é dinâmica na qual o ArrayList que controla o número 
de posições. No exemplo abaixo podemos ver que da interface java.util.List estende outra 
Interface chamada Collection. Isso quer dizer que a classe que implementar List<E> deverá 
também implementar os métodos herdados de Collection. 
public interface List<E> extends Collection<E> { 
int size(); 
boolean isEmpty(); 
boolean add(E e); 
//Outros métodos declarados aqui 
} 
 
14.2 Exemplo de Uso da Interface List com ArrayList 
Um ArrayList é uma lista, portanto podemos fazer a atribuição polimórfica declarando uma 
variável do tipo da Interface apontando para uma instância de ArrayList. 
public class ProgramaPrincipalArrayList { 
public static void main(String[] args) { 
 
List<Cliente> clientes = new ArrayList<Cliente>(); clientes.add(new 
Cliente()); 
 
Cliente clienteAcessado = clientes.get(0); 
 
Cliente clienteRemovido = clientes.remove(0); 
} 
} 
 
Adicionando mais objetos na lista 
clientes.add(new Cliente("Jão")); 
clientes.add(new Cliente("Maria")); 
clientes.add(new Cliente("Maria")); 
clientes.add(new Cliente("José")); 
 
Iterando sobre o Set por meio do índice 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 40 
for (int i = 0; i < clientes.size(); i++) { 
Cliente cliente = clientes.get(i); 
System.out.println(cliente.getNome()); 
} 
 
Iterando sobre o Set por meio do objeto Iterator 
for (Iterator iterator = clientes.iterator(); iterator.hasNext();) { 
Cliente cliente = (Cliente) iterator.next(); 
System.out.println(cliente.getNome()); 
} 
 
Iterando sobre o Set por meio do For Each 
for (Cliente cliente : clientes) { 
System.out.println(cliente.getNome()); 
} 
 
14.3 Set 
Não permite registros duplicados. Utilize os métodos equals e hashcode para definir o critério 
de igualdade. Sua organização não permite acesso por índice. 
Adicionando no conjunto 
//Atribuindo os nomes em um conjunto 
Set<String> nomes = new HashSet<String>(); 
nomes.add("Maria"); 
nomes.add("José"); 
nomes.add("Maria"); 
 
Verificando se um objeto está no conjunto 
//verificando se contam um objetos no conjunto 
boolean contem = nomes.contains("Maria") ; 
System.out.println("Contem Maria? " + contem ); 
 
Removendo do conjunto 
//removendo objeto do conjunto 
nomes.remove("Maria"); 
 
Iterando sobre o Set por meio do For Each 
for (String nome : nomes) { 
System.out.println(nome); 
} 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 41 
Iterando sobre o Set por meio do objeto Iterator 
Iterator<String> iterador = nomes.iterator(); 
while (iterador.hasNext()) { 
String nome = (String) iterador.next(); 
System.out.println(nome); 
} 
 
14.4 Map 
Armazena os elementos na forma de pares chaves/valor. As chaves são exclusivas não 
podendo ser duplicadas. Os acessos aos objetos são feitos pela chave que são únicas. 
public class ProgramaPrincipalMap { 
public static void main(String[] args) { 
Map<String, String> linguagensProgramacao = new 
HashMap<String,String>(); 
 
linguagensProgramacao.put("Java", "Web, Móvel e Desktop"); 
 linguagensProgramacao.put("PHP", "Web"); 
 linguagensProgramacao.put("Java Script", "Web Navegador de Internet"); 
} 
} 
 
Removendo do Map por meio da chave 
linguagensProgramacao.remove("PHP"); 
 
Imprimindo por meio da chave 
//Imprimindo por meio de chave 
System.out.println(linguagensProgramacao.get("Java"));Imprimindo por meio de um conjunto de chaves 
//Imprimindo por meio de um Set de Chaves 
Set<String> keys = linguagensProgramacao.keySet(); 
for (String k : keys) { 
System.out.println(linguagensProgramacao.get(k)); 
} 
 
15 EXCEPTIONS 
Quando executamos um método ou um construtor algo perigoso pode acontecer. Uma 
exceção é um objeto java contendo informação de um erro ocorrido em tempo de execução. 
Ao tentarmos realizar um cálculo aritmético por exemplo 10/0. O que acontece? Uma exceção. 
Um objeto de exceção é instanciado automaticamente pela JVM e enviado para nosso 
método. Existem exceções que a JVM lança automaticamente e outras que são lançadas 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 42 
programaticamente, ou seja, um método via programação a instância um objeto de exceção 
e lança. 
Vamos entender um pouco mais: 
 
Na API do Java temos uma família que forma uma hierarquia de classes com Exceções 
nativas. Na figura acima temos um exemplo de como essa é a estrutura dessa herança. 
A classe mais genérica que corresponde a família das Exceptions é Throwable. Logo, temos 
a Exception e RuntimeException. Podemos classificá-las em dois grupos: 
1. Grupo das filhas diretamente de Exception (Checked) 
2. Grupo das filhas de RuntimeException (Uncheck) 
 
15.1 Lançando uma Exception Unchecked (Não verificadas) 
Este tipo de exceção ocorre por alguma falha na lógica de programação. Como exemplo, 
pense em um vetor que possui apenas três posições e o código tenta acessar uma posição 
que não existe. O Compilador não verifica esse tipo de situação e quando rodarmos o 
programa em tempo de execução uma exceção será lançada. Uma exceção é um objeto 
derivado ou herdado da classe java.lang.Exception. Este objeto contém várias informações 
sobre o erro ocorrido. 
No caso abaixo será lançada uma exceção na linha 7 ao tentar atribuir um valor na posição 3 
do vetor que não existe pois o mesmo tem apenas 3 posições sendo 0, 1 e 2. 
1. public class ProgramaPrincipalException { 
2. public static void main(String[] args) { 
 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 43 
3. int [] vetor = new int[3]; 
4. vetor[0]=10; 
5. vetor[1]=20; 
6. vetor[2]=30; 
7. vetor[3]=40; 
8. } 
9. } 
10. 
 
A Exception lançará uma mensagem como: 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 
at 
br.com.fabricadeprogramador.sistemacadastro.sobrescrita.ProgramaPrincipalE
xception.main(ProgramaPrincipalException.java:7) 
java.lang.ArrayIndexOutOfBoundsException: 3 
 
15.2 Lançando uma Exception Checked (Verificadas) 
Uma exceção Verificada é uma classe que estende diretamente da classe base 
java.lang.Exception, logo este método não é da família de RuntimeException. 
 
Criando uma classe CPFInvalidException derivada de java.lang.Exception. 
Essa classe será utilizada para lançar um objeto Exception contendo informação sobre um 
CPF Inválido. Iremos utilizar esse um objeto dessa classe em um método de validação de 
CPF. 
public class CPFInvalidException extends Exception { 
 
//Construtor padrão 
public CPFInvalidException() { 
//passando para o construtor sobrecarregado da classe base 
uma mensagem 
//padrão 
super("CPF inválido!"); 
} 
 
} 
Em nossa classe ValidacaoUtil vamos implementar uma simples validação que verifica se o 
CPF informado no parâmetro é válido ou não. 
Consideramos que para ser válido o CPF o mesmo deve conter 11 dígitos e se isso não for 
verdade então um objeto da classe CPFInvalidException será instanciado (new) e lançado 
(throws). Para isso ser possível devemos declarar na assinatura do método que ele poderá 
fazer o lançamento throws CPFInvalidException. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 44 
//Na assinatura do método temos que declarar um possível lançamento de 
Exception do tipo CPFInvalidException 
public static void validarCpf(String cpf) throws CPFInvalidException { 
if(cpf.length()!=11){ 
//Instânciando e lançando uma Exception 
throw new CPFInvalidException(); 
} 
} 
Uma verificação consiste em tratar a Exception. Temos basicamente duas formas de tratar a 
Exception, sendo uma delas usando o try – catch, no qual nós “pegamos” o objeto da exceção 
lançada e outra através de uma redeclaração throws onde dizermos que não queremos 
“pegar” o objeto Exception lançado. 
Agora vamos programar no programa principal uma chamada ao método validarCpf que deve 
ser verificado. É agora que acontece a verificação, quando formos invocar o método que diz 
que pode lançar uma Exception. Ao tentar invocar o método sem fazer a verificação o 
compilador avisa. 
public class ProgramaPrincipalException2 { public 
static void main(String[] args) { 
ValidacaoUtil.validarCpf("905.098.531-90"); 
} 
} 
Uma mensagem do 
compilador diz que a 
exceção deve ser 
manipulada: 
Unhandled exception type 
CPFInvalidException 
Forma 1 
public class ProgramaPrincipalException2 { public 
static void main(String[] args) { 
try { 
ValidacaoUtil.validarCpf("905.098.531-90"); 
} catch (CPFInvalidException e) { 
//Tratamento da Exception 
e.printStackTrace(); 
} 
} 
} 
Uma forma de fazer o 
tratamento é “pegar” o 
objeto por meio da 
estrutura try-cath. O try 
tenta executar o método e 
se a exceção for lançada 
pelo método validarCpf 
então o catch recebe como 
parâmetro o objeto o 
CPFInvalidException que 
foi lançado. A variável 
(CPFInvalidException e) é 
um parâmetro do bloco 
cath funcionando como 
uma referência ao objeto 
CPFInvalidException 
lançada. 
Forma 2 
public class ProgramaPrincipalException2 { 
public static void main(String[] args) 
throws CPFInvalidException { 
ValidacaoUtil.validarCpf("905.098.531-90"); 
} 
Uma outra forma é 
redeclarar na assinatura 
do método main que 
possui uma chamada ao 
método validarCpf 
informando que o método 
não vai “pegar” a exceção. 
Projeto Fábrica de Programador – Módulo 2 
 
www.fabricadeprogramador.com.br Página: 45 
} throws 
CPFInvalidException 
 
Parabéns pela conclusão de mais uma fase do projeto Fábrica de Programador! No próximo 
módulo iremos aprender a fazer aplicações mais interessantes, voltadas para Web.

Outros materiais