Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.

Prévia do material em texto

Program
ação Orientada a Objetos e Estrutura de Dados 
Fábio da Silva Souza
Rolfi Cintas Gomes Luz 
Organizador:
Adilson da Silva
Fábio da Silva Souza
Rolfi Cintas Gomes Luz 
Organizador:
Adilson da Silva
GRUPO SER EDUCACIONAL
PROGRAMAÇÃO 
ORIENTADA 
A OBJETOS E 
ESTRUTURA DE 
DADOS 
PROGRAMAÇÃO 
ORIENTADA 
A OBJETOS E 
ESTRUTURA DE 
DADOS 
SER_Capa e Contra-Programação Orientada a Objetos e Estrutura de Dados.indd 1,3SER_Capa e Contra-Programação Orientada a Objetos e Estrutura de Dados.indd 1,3 27/01/2023 12:10:3327/01/2023 12:10:33
Programação 
Orientada a Objetos 
e Estrutura de Dados
© by Ser Educacional
Todos os direitos reservados. Nenhuma parte desta publicação poderá ser 
reproduzida ou transmitida de qualquer modo ou por qualquer outro meio, 
eletrônico ou mecânico, incluindo fotocópia, gravação ou qualquer outro 
tipo de sistema de armazenamento e transmissão de informação, sem prévia 
autorização, por escrito, do Grupo Ser Educacional.
Imagens e Ícones: ©Shutterstock, ©Freepik, ©Unsplash.
Diretor de EAD: Enzo Moreira.
Gerente de design instrucional: Paulo Kazuo Kato.
Coordenadora de projetos EAD: Jennifer dos Santos Sousa.
Equipe de Designers Instrucionais: Gabriela Falcão; José Carlos Mello; Lara 
Salviano; Leide Rúbia; Márcia Gouveia; Mariana Fernandes; Mônica Oliveira 
e Talita Bruto.
Equipe de Revisores: Camila Taís da Silva; Isis de Paula Oliveira; José Felipe 
Soares; Nomager Fabiolo Nunes.
Equipe de Designers gráficos: Bruna Helena Ferreira; Danielle Almeida; 
Jonas Fragoso; Lucas Amaral, Sabrina Guimarães, Sérgio Ramos e Rafael 
Carvalho.
Ilustrador: João Henrique Martins.
SOUZA, Fábio da Silva. / LUZ, Rolfi Cintas Gomes.
Organizador: SILVA, Adilson.
Programação Orientada a Objetos e Estrutura de Dados:
Recife: Digital Pages e Grupo Ser Educacional - 2022.
187 p.: pdf
ISBN: 978-65-81507-81-7
1. Programação 2. Sistemas 3. Objetos.
Grupo Ser Educacional
Rua Treze de Maio, 254 - Santo Amaro
CEP: 50100-160, Recife - PE
PABX: (81) 3413-4611
E-mail: sereducacional@sereducacional.com
Iconografia
Estes ícones irão aparecer ao longo de sua leitura:
ACESSE
Links que 
complementam o 
contéudo.
OBJETIVO
Descrição do conteúdo 
abordado.
IMPORTANTE
Informações importantes 
que merecem atenção.
OBSERVAÇÃO
Nota sobre uma 
informação.
PALAVRAS DO 
PROFESSOR/AUTOR
Nota pessoal e particular 
do autor.
PODCAST
Recomendação de 
podcasts.
REFLITA
Convite a reflexão sobre 
um determinado texto.
RESUMINDO
Um resumo sobre o que 
foi visto no conteúdo.
SAIBA MAIS
Informações extras sobre 
o conteúdo.
SINTETIZANDO
Uma síntese sobre o 
conteúdo estudado.
VOCÊ SABIA?
Informações 
complementares.
ASSISTA
Recomendação de vídeos 
e videoaulas.
ATENÇÃO
Informações importantes 
que merecem maior 
atenção.
CURIOSIDADES
Informações 
interessantes e 
relevantes.
CONTEXTUALIZANDO
Contextualização sobre o 
tema abordado.
DEFINIÇÃO
Definição sobre o tema 
abordado.
DICA
Dicas interessantes sobre 
o tema abordado.
EXEMPLIFICANDO
Exemplos e explicações 
para melhor absorção do 
tema.
EXEMPLO
Exemplos sobre o tema 
abordado.
FIQUE DE OLHO
Informações que 
merecem relevância.
SUMÁRIO
UNIDADE 1
Objetivos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 11
Introdução � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 12
Introdução à orientação a objetos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 13
Objetivos e vantagens da poo � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 14
Modelos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �14
Bibliotecas de operações � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �16
Tipos de Dados Primitivos (Representação) � � � � � � � � � � � � � � � � � � � � � � � �16
A classe String � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 20
Variáveis � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 23
Operadores lógicos relacionais e comparadores em java � � � � � � � � � 23
Executando o java � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 30
Inserido Classes � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �33
Operadores lógicos e negação em java � � � � � � � � � � � � � � � � � � � � � � � � � � 34
Estrutura de decisão em java � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 38
Estrutura de repetição em java � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �42
Terminologia da programação orientada a objetos � � � � � � � � � � � � � 44
Instanciando um objeto � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �47
UNIDADE 2
Objetivos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 51
Introdução � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 52
Classes, pacotes, objetos, atributos, métodos, construtores, 
palavra-chave this e sobrecarga � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 53
Classes � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 53
Pacotes � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 55
Objetos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 57
Atributos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 58
Métodos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 60
Construtores � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 63
Palavra-chave This � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 67
Sobrecarga � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 68
Instanciação e referências de objetos � � � � � � � � � � � � � � � � � � � � � � � � � � �70
Envio de mensagens � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 72
Ciclo de vida de um objeto � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 73
Abstração e encapsulamento � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �76
Abstração � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 76
Encapsulamento � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 78
Estruturas compostas homogêneas � � � � � � � � � � � � � � � � � � � � � � � � � � � � 83
Vetor � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 83
Vetor orientado a objetos � � � � � � � � � � � � � � � � � � � � � � � � � � � 89
Matriz � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 92
Estruturas comportamentais heterogêneas � � � � � � � � � � � � � � � � � � � 94
Instanciação � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 94
Atribuição � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 95
Tipos abstratos de dados � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 97
Tipos de armazenamento � � � � � � � � � � � � � � � � � �� � � � � � � � � 98
Coleções � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 99
UNIDADE 3
Objetivos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 103
Introdução � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 104
Herança � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �105
Utilização de herança � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 105
Palavra-chave super � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 109
Criação e uso de hierarquia de classes � � � � � � � � � � � � � � � � � � � � � � � � � � 111
Classes e subclasses � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 113
Classes abstratas e interfaces � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 113
Classes abstratas � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �114
Interfaces � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 117
Relacionamento entre classes � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 121
Associação � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 121
Composição � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 127
Agregação � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �133
Polimorfismo � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 134
Introdução ao polimorfismo � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 134
Polimorfismo na prática � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �135
Ligação dinâmica (dynamic binding) � � � � � � � � � � � � � � � � � � � � � � � � � � � 138
Tratamento de exeções � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 140
Evitando e capturando exceções � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 140
UNIDADE 4
Objetivos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 143
Introdução � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 144
Algoritmos recursivos � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �145
Técnicas de ordenação � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �146
Método Bubble Sort � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 147
Método Insertion Sort � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 149
Método Selection Sort � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 150
Estruturas Lineares � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 151
Listas � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 151
Lista Estática � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 152
Lista Ligada � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 152
Lista Duplamente Ligada � � � � � � � � � � � � � � � � � � � � � � � � � � � 156
Código Lista Duplamente Ligada � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 158
Lista Collection � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 158
Pilhas � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �160
Código da Pilha de Alocação Estática � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 162
Filas – implementações � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 163
Collection Class Queue – Fila dinâmica � � � � � � � � � � � � � � � � � � � � � � � � � � � � 168
Árvores e suas generalizações � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �170
Terminologia da estrutura Árvore � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 174
Nó � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 174
Node – Implementação dinâmica � � � � � � � � � � � � � � � � � � 176
Vetor – Implementação sequencial � � � � � � � � � � � � � � � � � 177
Árvores binárias � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 178
Tipos de Árvores binárias � � � � � � � � � � � � � � � � � � � � � � � � � � � 179
Árvores de busca � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 182
Árvore binária e de busca � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 183
Referências � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � 185
Apresentação
Olá, aluno(a). Seja bem-vindo(a) à disciplina!
Nessa disciplina será abordada a Programação Orientada a 
Objetos (POO), utilizando a linguagem de programação JAVA. Tam-
bém serão apresentados conceitos de POO e conceitos e estruturas 
de dados usadas para a manipulação e armazenamento de dados. 
Dentre essas estruturas apresentadas, vamos encontrar os 
vetores, as matrizes e as árvores. Para essas estruturas, serão apre-
sentadas formas de ordenação de dados. 
Antes de começarmos, lembre-se que muitas dessas estru-
turas possuem formatos diferenciados que contribuem em diversas 
áreas, como redes, hardware, banco de dados, Sistemas de Infor-
mação e negócios, entre outros.
No decorrer do conteúdo, todos os conceitos de orientação a 
objetos serão abordados de forma simplificada para que você possa 
absorver facilmente os temas abordados no material.
Dito isto, desejo a você boa leitura e bons estudos!
Autoria
Fábio da Silva Souza 
O professor Fábio da Silva Souza é tecnólogo em Gestão da Tecno-
logia da Informação pela Faculdade Tecnológica de Guaratinguetá 
(Fatec). Formou-se no ano de 2017 e, desde então, atua como pro-
gramador e analista de sistemas.
Currículo Lattes
http://lattes.cnpq.br/0316083306850058
Rolfi Cintas Gomes Luz 
O professor Rolfi Cintas Gomes Luz é mestre (2012) em Ensino de 
Ciências pela Universidade Cruzeiro do Sul. É graduado (2008) em 
Ciência da Computação pela mesma instituição. Atua há duas déca-
das na área da computação como analista de sistemas, passando por 
empresas nacionais e multinacionais, e possui uma década atuando 
no ensino superior.
Currículo Lattes
http://lattes.cnpq.br/0778971556248045
Organizador
Adilson da Silva
O professor Adilson da Silva é formado em Ciência da Computação 
pela Universidade Católica de Pernambuco (1995), possui especiali-
zação em Tecnologia da Informação pela UFPE (Universidade Fede-
ral de Pernambuco) e MBA em Gestão de Pessoas por Competências 
pela faculdade Santa Maria. Também tem especialização em Meto-
dologias Ativas da Educação e Mestrado em Engenharia de Software 
pelo C.E.R.S.A.R., além de possuir certificação Scrum Master. 
Atua na área de informática há mais de trinta anos, como Analista de 
Sistemas e como professor de disciplinas como Algoritmo, Banco de 
dados, Gestão de projetos, Gestão ágil e Segurança da Informação. 
Currículo Lattes
http://lattes.cnpq.br/7221002795193400
UN
ID
AD
E
1
Objetivos
 ◼ Apresentar as características de Programação Orientada a Objetos.
 ◼ Introduzir a linguagem Java para Programação Orientada a Objetos.
 ◼ Entender os conceitos da Programação Orientada a Objetos.◼ Compreender como surgiu o paradigma de Programação 
Orientada a Objetos.
12
Introdução
Caro(a) aluno(a), como vai?
A partir de agora veremos a Programação Orientada a Obje-
tos. Dessa forma, falaremos sobre os objetivos esperados e quais as 
vantagens de utilizá-la. Além disso, apresentaremos os principais 
conceitos de orientação a objetos e a algumas das suas implemen-
tações em JAVA. 
Veremos também como podemos executar os programas em 
JAVA usando o Netbean. Assim, discutiremos a aplicação de alguns 
conceitos de lógica de programação em Java, como o uso de opera-
dores (Lógicos e aritméticos). Trataremos também das estruturas 
condicionais e das estruturas de repetição que podem ser usadas. 
Por fim, apresentaremos algumas terminologias usadas no para-
digma de orientação a Objetos.
Pensando nisso, até o final desse material, discutiremos:
1. características da Programação Orientada a Objetos;
2. uso da Linguagem JAVA na ferramenta NetBeans;
3. uso de estruturas condicionais e de estruturas de repetição 
em JAVA;
4. conceitos de Programação Orientada a Objetos.
Destaco que a Programação Orientada a Objetos é o paradig-
ma de programação mais utilizado atualmente no desenvolvimento 
de sistemas, trazendo um aumento de produtividade com a utiliza-
ção de reuso de código. E, para que você possa se inserir no merca-
do, é necessário ter uma boa base nesse paradigma, e é o que essa 
disciplina lhe dará. 
Dito isto, vamos iniciar nossos estudos. 
13
Introdução à orientação a objetos
Caro(a) aluno(a), é notório que computadores estão presentes no 
cotidiano e servem para automatizar e agilizar a execução de tarefas 
simples ou complexas. Mas, um computador não é capaz de efetuar 
qualquer tarefa sem um software, pois é através dele que se proces-
sam as informações. 
Nos primórdios da computação, um programa de computador 
era escrito de maneira sequenciada, com suas funções uma abaixo da 
outra e seguindo esta sequência até o final. Dentro da sequência, o pro-
grama trabalhava diante de seleções que executavam uma sequência 
com base em condições (if ou else) verdadeiras (true) ou falsas (false) 
ou diante de repetições que executassem tal sequência enquanto a 
condição fosse verdadeira (iterações: for, foreach, do e while).
Em síntese, a Programação Orientada a Objetos (POO) con-
siste no desenvolvimento de sistemas computacionais utilizan-
do linguagens de programação que suportam orientação a objetos 
por meio de classes e seus atributos e métodos, introduzindo uma 
abordagem na qual o(a) programador(a) visualiza o programa em 
execução como uma coleção de objetos cooperantes que se comuni-
cam por mensagens. Em outras palavras, podemos dizer que a POO 
procura atender aos requisitos do(a) cliente através de funções 
encontradas dentro dos objetos criados.
É importante destacarmos que cada um dos objetos é ins-
tância de uma classe e todas as classes formam uma hierarquia de 
classes unidas via relacionamento de herança, como apontado na 
página 4 do livro Introdução ao Paradigma de Orientação a Objetos, 
publicado em 1996 e escrito por Carlos Kamienski.
Uma das características da Programação Orientada a Objetos, 
como o próprio nome sugere, é o uso de objetos, em vez de funções 
ou procedimentos, para a construção do programa. Eles se comuni-
cam mediante mensagens e cada objeto é uma instância de classe, 
possibilitando que o programa seja escrito sem a necessidade de se 
seguir uma sequência e que um método seja executado em qualquer 
parte da classe, desde que no padrão aceito pela linguagem.
14
Objetivos e vantagens da poo
A Programação Orientada a Objetos tem por objetivo melhorar a 
produtividade dos(as) programadores(as) no desenvolvimento de 
sistemas, possibilitando a construção de sistemas robustos com 
menos linhas de código, de modo que trechos de códigos sejam rea-
proveitados. A POO é vantajosa porque:
 • possibilita a reutilização de código, sendo essa sua maior van-
tagem ao permitir que um(a) programador(a) escreva menos 
linhas, já que um trecho de código pode ser reutilizado inú-
meras vezes em qualquer parte do sistema;
 • possibilita que a aplicação seja escalável, fazendo com que ela 
cresça de acordo com as necessidades que surgem no decorrer 
do desenvolvimento ou mesmo diante da necessidade de im-
plantar novas funcionalidades;
 • além disso, a manutenção do sistema é feita de forma simpli-
ficada, rápida e eficiente.
Modelos
Para programar utilizando a orientação a objetos, é necessário criar 
classes que, em muitos casos, são só modelos de entidades e, para 
que se possa representar dados a partir das classes, é necessária a 
criação de objetos e/ou instanciação destas classes.
Além disso, a criação de um objeto, ou sua instanciação, é ne-
cessária para que se possa ter a representação de dados e a manipu-
lação das informações e executar operações contidas na classe. 
No exemplo: “Livro livro = new Livro();”, a primeira parte antes do 
igual indica que se está referenciando na memória do sistema opera-
cional o objeto denominado “livro”, que tem o tipo Livro, e a segun-
da parte é a criação da instância através da palavra-chave “new”.
EXEMPLO
15
Já Na página 14 do livro Introdução à Programação Orienta-
da a Objetos usando JAVA, editado em 2011, o autor Rafael Santos 
afirma que:
as classes são estruturas das linguagens de 
programação orientadas a objetos para con-
ter, para determinado modelo, os dados que 
devem ser representados e as operações que 
devem ser efetuadas com estes dados (SAN-
TOS, 2011). 
Além disso, os dados contidos na classe são atributos do 
objeto e as classes são abstrações do mundo real no mundo vir-
tual. Na programação, tais classes também são chamadas de 
modelos (models), representações de objetos, pessoas, tarefas 
e processos, usados no dia a dia, não necessariamente diante de 
um computador. 
Para melhor exemplificar isso, o Diagrama 1 representa um 
modelo de abastecimento num posto de combustível.
Diagrama 1 - modelo de abastecimento em posto de combustível
 Fonte: editorial Digital Pages (2020).
16
O modelo anterior traduz o processo num posto de combustí-
vel, onde o frentista ou caixa recolhe dados, como tipo de com-
bustível, valor total pago, quantidade de litros, preço por litro 
e tipo de pagamento. Esses dados possuem comportamentos 
usados, por exemplo, para fechamento de caixa, determinar 
qual combustível é o mais vendido, se é necessária a compra de 
mais combustível, dentre outros trâmites relativos a um posto 
de combustível.
Bibliotecas de operações
Caro(a) aluno(a), é preciso que você saiba que nem todo mode-
lo possui dados e operações, visto que eles podem incluir ape-
nas dados ou operações. Lembre-se que modelos que contêm 
só dados são pouco usados, pois não faz sentido ter um modelo 
cujas informações não são manipuláveis. Já modelos que pos-
suem só operações são mais encontrados, sendo denominados 
bibliotecas de operações, criadas para manipulação de dados 
de outras classes.
Tipos de Dados Primitivos (Representação)
Em Sistemas de Informação, muito se fala sobre dados, informa-
ção e conhecimento. Nesse cenário, a computação, de forma geral, 
refere-se à informação e ao conhecimento. Previsão ou tendências, 
por sua vez, são tratadas na Inteligência de Negócios, ou BI (Busi-
ness Intelligence). Já os dados podem ser um conjunto de bits, uma 
palavra, uma letra, um número, ou podem assumir algum valor sem 
significado aparente.
DICA
17
EXEMPLO
EXEMPLO
EXEMPLO
Por exemplo, o abacate, R$ 5,00, 1 kg.
Além disso, a informação é a união de diversos dados que 
possuem sentido ou significado. 
Por exemplo: “hoje, 1 kg do abacate está custando R$ 5,00 reais”.
Já o conhecimento é a relação dos dados e das informações, 
constituindo uma ação, aplicação ou saber em diversas áreas do co-
nhecimento, geralmente empregada quando se cruzam valores.
Por exemplo: “há dez anos, no mês de dezembro, 1 kg do abacate 
custava R$ 5,00 reais”.
Por fim, os dados,em Estrutura de Dados, são trabalhados 
como forma primordial de computar ou solucionar problemas do 
mundo real, visando atender às regras de negócio, ou seja, às regras 
do mundo real que devem ser incorporadas no mundo computacio-
nal ou atividades empresariais que utilizam esses dados como ca-
deia de valor do negócio.
É importante destacarmos ainda que a escolha do tipo de dado 
em Estrutura de Dados leva em consideração alguns aspectos, como:
18
 • identificador - nome pelo qual a estrutura será identificada. 
Geralmente, possui ligação com sua aplicação no mundo real.
 • tipo de armazenamento - define se serão armazenadas le-
tras, números, valores lógicos etc.
 • velocidade em inserir dados - a velocidade é medida, geral-
mente em milissegundos, e pode variar dependendo do tipo de 
estrutura escolhida.
 • algoritmo de ordenação e localização de dados - existem 
muitos algoritmos específicos para cada tipo de estrutura que 
dependem muito da sua aplicação. 
Às vezes, possuem estruturas que demoram mais para or-
denar, mas que, por outro lado, são mais velozes para localizar os 
dados. Assim, através do tipo de aplicação de dados, verifica-se qual 
o melhor formato de dados para tanto. Nesse contexto, surgem os 
tipos de dados primitivos, que orientam ao programador a estrutura 
mais adequada para aplicação na regra de negócio.
É importante destacarmos que, em Java, há poucos tipos de 
dados primitivos, também conhecidos como nativos ou básicos. Eles 
são parte da linguagem, portanto, suas nomenclaturas são pala-
vras-chaves e não são instâncias de outras classes. Assim, cada tipo 
tem limitações, ocupando valores específicos em memória. 
Para que você possa entender o que estamos tratando, abaixo, na 
Tabela 1, constam as especificações dos tipos primitivos em JAVA. Veja:
Tabela 1.- Tipos Primitivos em JAVA
boolean
byte
true ou false
Entre -128 e 127
O valor 
booleano
assume valores 
true ou false
Números 
inteiros de 8 
bits de precisão
8
8
true
108
Tipo
primitivo Valores Observações
Bits em
memória Exemplo
19
Fonte: editorial Digital Pages (2020).
Caro(a) aluno(a), é necessário que você saiba que, para o 
tipo char, cada número de 0 a 65535 é um dos caracteres na ta-
bela ASCII (American Standard Code for Information Interchange), 
sigla em inglês para Código Padrão Americano para o Intercâm-
bio de Informação. Para que você entenda o que estamos deta-
lhando, o código a seguir dá um melhor entendimento sobre o 
tipo char.
float
long
char
double
int
short
Entre 1.40239846e-46 e
3.40282347e+38
Entre
-9.223.372.036.854.775.808 e
+9.223.372.036.854.775.807
Entre 0 e 65535
Entre
4.94065645841246544e-324
e 1.7976931348623157e+308
Entre -2.147.483.648 e
+2.147.483.647
Entre -32768 e 32767
Pontos flutuantes
de precisão sim-
ples, usados para
representar valo-
res decimais
Números inteiros 
de 64 bits de 
precisão
Na teoria, char 
armazena
números inteiros 
de 16 bits de
 precisão, mas,
na prática, é utili-
zado para 
para qualquer
caractere 
alfanumérico
(char = character)
Pontos 
flutuantes de 
precisão dupla, 
usados para 
representar
valores decimais
Números inteiro 
de 32 bits de 
precisão
Números inteiros 
de 16 bits de 
precisão
32
64
16
64
32
16
34897.75
7234829
s
34897.75
1000
1000
20
EXEMPLO
public class ExemploCharASCII { 
public static void main(String args[]) { 
char caractereJ = 74;
char caractereA = 65; 
char caractereV = 86;
System.out.println(caractereJ + “” + caractereA + “” + caractereV + 
“” + caractereA ) ;
}
}
Como você deve ter percebido, no código há três atri-
butos do tipo char e cada um representa uma letra. Assim, 
para escrever a palavra JAVA utilizando char, é preciso usar 
aspas vazias para dizer ao Java que se está concatenando e não 
somando, pois, como char é inteiro, sem + “” + a linguagem 
entenderia que os valores estão somados em vez de concate-
nados. Assim, executando o código anterior, a saída no con-
sole seria “JAVA”.
A classe String
Em Java, para atribuir qualquer texto no lugar de um array de char 
(char []), usa-se a classe String. Isso porque, por ser uma classe, 
String não é um tipo primitivo, apesar de não precisar ser instancia-
da. De acordo com Santos (2011), embora não seja preciso declarar 
um array de char, o conceito de String é que a instância possui zero 
ou mais caracteres do tipo char, enfileirados em ordem de leitura (da 
esquerda para direita). Veja:
21
EXEMPLO
public class testePalavra {
 public static void main(String args[]) {
 //Usando array de char
 char [] tipoChar = {‘p’,’a’,’l’,’a’,’v’,’r’,’a’};
 //usando classe String sem instanciá-la String classeString = 
“Palavra”;
//usando a classe String, instanciando-a
 String classeString2 = new String (“Palavra”);
}
}
No exemplo a cima, usando char, é preciso criar um array e 
cada letra precisa ser passada por aspas simples, enquanto na classe 
String é possível passar diretamente entre aspas duplas ou por parâ-
metro entre aspas duplas ao instanciar a classe String. 
Perceba que, no código anterior, o mais comum é fazer 
“String nomeVariavel = “palavra”;” em vez de “String nomeVaria-
vel = new String(“palavra”);”. 
É importante destacarmos que o tamanho de uma String depende 
da quantidade de memória disponível no sistema, ou seja, ela consome 
poucos ou muitos bits de memória conforme o tamanho do texto.
Além do que detalhamos, é preciso que você saiba que a classe 
String tem métodos essenciais que auxiliam no desenvolvimento de 
trabalho com textos. Alguns dos métodos, e para que eles servem, são:
 • length - regressa à quantidade exata de caracteres con-
tidos em uma String. Este método, além de caracteres 
visíveis, também retorna espaços, quebras de linhas, 
22
tabulações etc. É importante destacarmos que o método 
lengh não aceita parâmetros.
 • charAt - volta ao caractere que está numa posição do texto. 
Para execução do método, é necessário que se passe um valor 
inteiro como argumento.
 • getChars - retrocede a caracteres partindo de uma posi-
ção inicial até outra. Exige que se passe por quatro parâ-
metros, posição inicial (srcBegin), posição final (srcEnd), 
destino (dest) e posição do início do destino (dstBegin). 
Para tanto, é preciso criar um array de char como destino 
passado como parâmetro.
 • replace - substitui caractere ou texto e possui como parâme-
tro dois argumentos. O primeiro é o caractere ou texto a ser 
substituído e o segundo, o caractere ou texto substituto.
 • toUpperCase - deixa todo o texto maiúsculo e não 
aceita parâmetros.
 • toLowerCase - deixa todo o texto minúsculo e não 
aceita parâmetros.
 • trim: remove espaços contidos no início e/ou no final 
de um texto, exceto entre duas palavras. Também não 
aceita parâmetros. 
A classe String é imutável, não sendo possível alterá-la após cria-
da. Por outro lado, uma variável da classe String também admite a 
junção de textos, denominada como concatenação. A concatenação 
é feita utilizando o operador de adição (+) que junta dois ou mais 
textos em um. Ela só é possível porque, na concatenação, é criado 
um novo objeto temporário da classe String, posteriormente asso-
ciado à referência da variável criada.
DICA
23
Variáveis
No algoritmo e na computação, temos as variáveis, que são definidas 
como espaço em memória que possui um identificador e pode alo-
car dados. Como nos tipos de dados primitivos que compõem a cadeia 
(inteiro, real e lógico), nas linguagens de programação, temos tipos 
primitivos mais específicos, em que cada linguagem possui seu tipo 
primitivo, porém, algumas linguagens possuem um padrão.
Para que você não tenha dúvidas, já lhe adianto que, nesta disci-
plina, será utilizada a linguagem Java nos exemplos e, nessa linguagem, 
para definir uma variável, usa-se o conceito de declaração de variável.
É importantedestacarmos que Java é uma linguagem de pro-
gramação simples, portável, gratuita, robusta e com bibliotecas para 
aplicações, além de ser possível executá-la em um terminal Unix ou 
MS-DOS. Por ser multiplataforma, é utilizada para desenvolvimen-
to de sistemas web, mobile ou desktop e possui frameworks fáceis de 
utilizar e também há integração fácil com o banco de dados.
Esta linguagem também é fortemente tipada, ou seja, ao de-
clarar atributos ou variáveis, declara-se também o tipo de dado (nu-
mérico, texto, booleano, entre outros). Grosso modo, diz-se que, 
para um campo do tipo primitivo int (numérico), não é possível 
atribuir um caractere não inteiro entre 0 e 9. Isso porque os tipos de 
dados primitivos são palavras-chaves reservadas pela linguagem de 
programação e não se pode utilizá-las como nome para uma variável.
Operadores lógicos relacionais 
e comparadores em java
Os fluxos de um programa são baseados em operadores lógicos e ló-
gicos relacionais. Eles servem para que, durante a execução de um 
trecho do código e segundo a condição, o programa faça algo ou, em 
uma iteração, ele execute aquilo até que a condição seja cumprida ou 
enquanto ela for válida. Dessa maneira, os operadores lógicos rela-
cionais em Java retornam o valor booleano true ou false e são listados 
a seguir, junto com seu uso para verificação.
24
 ◼ == (igual): se dois valores são iguais. Se o valor à esquerda e 
o valor à direita foram iguais, o resultado é true, do contrário 
é false.
 ◼ != ( ): se dois valores são diferentes. Se o valor à esquerda 
for diferente do valor à direita, o resultado é true, do con-
trário é false.
 ◼ > (maior): se um valor é maior que o outro. Se o valor à es-
querda for maior que o valor à direita, o resultado é true, do 
contrário é false.
 ◼ < (menor): se um valor é menor que o outro. Se o valor à es-
querda for menor que o valor à direita, o resultado é true, do 
contrário é false.
 ◼ >= (maior ou igual): se um valor é maior ou igual ao outro. 
Se o valor à esquerda for maior ou igual ao valor à direita, o 
resultado é true, do contrário é false.
 ◼ <= (menor ou igual): se um valor é menor ou igual ao outro. 
Se o valor à esquerda for menor ou igual ao valor à direita, o 
resultado é true, do contrário é false. 
É importante destacarmos que os operadores anteriores são uti-
lizados para comparar valores nativos numéricos, inclusive o tipo char:
 public class TesteOperadoresLogicos { 
 public static void main(String args[]) {
 int numeroComparado = 18;
 if (15 == numeroComparado) { 
 System.out.println(“os números são iguais”);
 } else {
EXEMPLO
25
 System.out.println(“os números são diferentes”);
 }
 If (21 != numeroComparado) { 
 System.out.println(“os números são diferentes”);
 } else {
 System.out.println(“os números são iguais”);
 }
 If (33 > numeroComparado) {
 System.out.println(“o número é maior que o número comparado”);
 } else {
 System.out.println(“o número é menor que o número comparado”);
 }
 if (19 < numeroComparado) {
 System.out.println(“o número é menor que o número comprado”);
 } else {
 System.out.println(“o número é menor que o número comprado”); 
 } 
 if ( 18 >= numeroComparado) {
 System.out.println(“o número é maior ou igual ao número comparado”);
 } else {
 System.out.println(“o número é menor que o número comparado”);
 }
26
EXEMPLO
 if (18 <= numeroComparado) {
 System.out.println(“o número é menor ou igual ao número comparado”);
 } else {
 System.out.println(“o número é maior que o número comparado”);
 }
 }
}
E, caso seja necessário comparar Strings ou objetos, se usa o 
método equals, como neste exemplo da classe String:
 public class ComparaPalavra {
 public static void main(String args[]) { String palavra1 = “Palavra”;
 String palavra2 = “Palavra”;
 If (palavra1.equals(palavra2)) { 
 System.out.println(“As palavras são iguais”);
 } else {
 System.out.println(“As palavras são diferentes”);
 }
 }
 }
27
EXEMPLO
Perceba que, no exemplo anterior, a palavra1 é igual à pala-
vra2, portanto, ao executar o código, é exibido no console o resulta-
do “As palavras são iguais”.
Ao utilizar o método equals da classe String, todos os caracteres da 
palavra precisam estar na mesma sequência, inclusive os espaça-
mentos. Isso porque o método também diferencia se o caractere é 
maiúsculo ou minúsculo. Então, “Arroz com Feijão” não é a mesma 
coisa que “Arroz coM feijão” ou “Arroz comFeijão”. Assim, para sa-
ber se uma String é igual a outra, sem distinguir caracteres maiús-
culos e minúsculos, é utilizado o equalsIgnoreCase.
É importante você saber que todas as classes possuem o mé-
todo equals (herdado da classe Object) e, para customizá-lo, é pre-
ciso sobrescrevê-lo utilizando a annotation @Override acima do 
método, veja:
public class Livro { 
private long id;
private String nomeAutor; 
private int anoLancamento; 
private String titulo;
public String getNomeAutor() { 
return nomeAutor;
}
DICA
28
public void setNomeAutor(String nomeAutor) { 
this.nomeAutor = nomeAutor;
}
public int getAnoLancamento() { 
return anoLancamento;
}
public void setAnoLancamento(int anoLancamento) { 
this.anoLancamento = anoLancamento;
}
public String getTitulo() {
return titulo;
}
public void setTitulo(String titulo) { 
this.titulo = titulo;
}
 
@Override
public boolean equals(Object obj) { 
if (this == obj)
return true; 
if (obj == null)
return false;
if (getClass() != obj.getClass()) 
return false;
Livro other = (Livro) obj;
29
if (anoLancamento != other.anoLancamento) 
return false;
if (nomeAutor == null) {
if (other.nomeAutor != null) 
return false;
} else if (!nomeAutor.equals(other.nomeAutor)) 
return false;
if (titulo == null) {
 if (other.titulo != null)
 return false;
} else if (!titulo.equals(other.titulo)) 
return false;
return true;
}
}
No exemplo acima, o método equals foi sobrescrito com a 
annotation @Override. No código, o objeto passado pelo parâmetro 
“(Object obj)” é do tipo Object e não do tipo Livro, isso acontece por-
que todas as classes herdam direta ou indiretamente a classe Object, 
sendo ela a base para todas as demais. Em seguida, como no código 
do exemplo, é feita a conversão explícita do objeto genérico para o 
tipo Livro (Livro other = (Livro) obj;).
Ele também confere cada atributo da classe Livro, com ex-
ceção do id, algo que foi feito de forma proposital, pois, se ele 
fosse verificado também, conforme a circunstância, haveria dois 
objetos Livros com o mesmo autor, mesmo título e mesmo ano de 
lançamento, mas com o id diferente, fazendo que o método equals 
retorne false.
30
Lembre-se que o id é utilizado para aplicações em banco de 
dados, logo, ao averiguar se um objeto já existe no banco, não se 
considera o id, pois assim é evitada a duplicidade de dados, já que os 
demais atributos seriam iguais. Não obstante, isso depende da regra 
de negócio.
Executando o java
Após a instalação do JDK e do Netbeans, abra o Netbeans. Clique em 
Arquivo e, logo em seguida, clique em Novo Projeto, e aparecerá a 
tela representada na Figura 1:
Figura 1 - Ambiente Netbeans: tela inicial de Novo Projeto
Fonte: editorial Digital Pages (2019).
Logo depois, na tela do Novo Projeto, clique em Java, Aplica-
ção Java e Próximo, e aparecerá a tela conforme a Figura 2:
31
Figura 2 - Ambiente Netbeans: criando Nova Aplicação do Projeto
Fonte: editorial Digital Pages (2019).
Nessa etapa, escreva o Nome do Projeto (todo exemplo e 
programa que serão desenvolvidos na disciplina será um Projeto 
Novo). A localização física padrão do projeto é na pasta Documentos\
NetBeansProjects do Usuário local. Deixe selecionadoCriar Classe 
Principal, assim:
Figura 3 - Ambiente Netbeans: tela inicial de Desenvolvimento
Fonte: editorial Digital Pages (2019).
32
EXEMPLO
Na área de desenvolvimento, temos o botão Play, que é o bo-
tão que inicia o comando de execução do projeto e o faz na parte de 
baixo da área de desenvolvimento. Fique tranquilo(a), pois, na dis-
ciplina, será fornecido o código para execução das estruturas.
Atente-se ao fato de que todo nome do programa deve-
rá (neste primeiro momento) ser o nome do projeto. Logo, veja o 
exemplo a seguir.
public class prjOla {
 public static void main(String []args)
 {
 System.out.println(“Olá”);
 }
}
O nome do projeto, ao criar um novo, é prjOla. O Java é case 
sensitive, isto é, ele diferencia letras maiúsculas e minúsculas. En-
tão, prjOLA é diferente de PRJOLA e diferente de prjola. Por isso, no-
mes de programas, projetos e comandos devem seguir exatamente 
como estão escritos no material.
No comando anterior, para poder executar, cole o código e di-
gite play. Lembre-se que os comandos em Java funcionam via blo-
cos, que são as aberturas e fechamentos de chaves.
O principal método a ser executado no projeto é o public static 
void main que, ao ser iniciado, irá apresentar na tela a palavra “Olá” 
através do comando System.out.println().
A seguir, estão exemplos do uso de tipos primitivos em ope-
ração matemática e demonstração em tela.
33
EXEMPLO
 public class prjSoma {
 public static void main(String []args)
 {
 int numA = 5; int numB = 6;
 int result = numA + numB;
 System.out.println(“O resultado de A + B :” + result);
 }
}
Inserido Classes
Caro(a) aluno(a), para inserir mais uma classe no projeto, clique 
com o botão direito do mouse em cima do pacote, como na Figura 4.
Figura 4 - Ambiente Netbeans: criando uma nova Classe no Projeto (passo 1)
Fonte: editorial Digital Pages (2019).
34
Logo em seguida, aparecerá a janela da Figura 5. Neste mo-
mento, somente escreva o nome da classe e clique em Finalizar.
Figura 5 - Ambiente Netbeans: criando uma nova Classe no Projeto (passo 2)
Fonte: editorial Digital Pages (2019).
Operadores lógicos e negação em java
Os operadores lógicos seguem a mesma ideia que os lógicos relacio-
nais e auxiliam na execução de processos diante de circunstâncias 
para tomada de decisões, em que duas ou mais condições são consi-
deradas e retornam um valor booleano true ou false. Há apenas dois 
operadores lógicos:
 • && (dois “e comercial”): a pronúncia correta é and e a tradu-
ção para o português é “e”. É utilizado para comparar duas ou 
mais condições e todas precisam ser verdadeiras.
 • || (duas vezes o símbolo pipe, localizado no mesmo botão que 
a contra-barra “\”, próximo à letra Z no teclado): a pronúncia 
correta é or e a tradução para o português é “ou”. É utiliza-
do para comparar duas ou mais condições em que pelo menos 
uma delas precisa ser verdadeira. 
35
EXEMPLO
public class OperadorLogico {
public static void main(String args[]) { 
 int resultado1 = 15 + 12;
 int resultado2 = 22 + 33;
 if (resultado1 == 27 && resultado2 == 55) {
 System.out.println(“As condições foram atendidas”);
 } else {
 System.out.println(“As condições não foram atendidas”);
 }
 if (resultado1 > 27 || resultado2 == 55) { 
 System.out.println(“Uma ou outra condição foi atendida”);
 } else {
 System.out.println(“Nenhuma das condições foi atendida”); 
 }
}
}
No exemplo acima, a primeira condição (primeiro if) é 
que o resultado1 precisa ser igual a 27 e o resultado2, igual a 55. 
Como ambas as comparações são verdadeiras, ao executar o có-
digo, para a primeira condição é exibido o texto “As condições 
foram atendidas”.
Já na segunda condição, o resultado1 precisa ser maior que 27 
e o resultado2, igual a 55. Assim, a primeira condição não é atendi-
da, pois resultado1 é igual a 27 e não maior. Já a segunda condição 
é atendida, pois o resultado2 é igual a 55. Como o operador lógico é 
36
EXEMPLO
“ou” e só uma condição precisa ser verdadeira, ao executar a segun-
da condição, o texto exibido é “Uma ou outra condição foi atendida”.
A negação é utilizada para negar (inverter) um valor boolea-
no, seja ele verdadeiro (true) ou falso (false). A negação utiliza o sinal 
! (exclamação) e sua denominação é not (não). Dessa maneira, toda 
comparação retorna um valor booleano, assim, a negação impacta 
diretamente no valor booleano, em que o verdadeiro vira falso e o 
falso vira verdadeiro.
public class ComparaPalavra {
public static void main(String args[]) { 
 int resultado1 = 15 + 12;
 int resultado2 = 22 + 33;
 if (!(resultado1 == 28) && resultado2 == 55) { 
 System.out.println(“As condições foram atendidas”);
 } else {
 System.out.println(“As condições não foram atendidas”);
 }
 if (!(resultado1 > 27 || resultado2 == 55)) {
 System.out.println(“Uma ou outra condição foi atendida”);
 } else {
 System.out.println(“Nenhuma das condições foi atendida”);
 }
}
} 
37
Como você já deve ter percebido, um programa de compu-
tador segue a mesma regra da matemática, processando primeiro 
o conteúdo interno dentro dos parênteses e, depois, o que está fora 
dos parênteses. Pensando nisso, o raciocínio para o operador de ne-
gação parece um pouco complicado em um primeiro momento e, 
por isso, ele foi separado em tópicos para melhor entendimento. 
Observando o código anterior, na primeira condição, se tem:
!(resultado1 == 28) && resultado2 == 55
 • Dentro dos parênteses resultado1 == 28. O resultado dá o valor 
booleano false, já que o resultado1 é igual a 27, e não 28.
 • O sinal de negação está negando o resultado dentro dos parênteses. 
Desse modo, o resultado vira true já que é false (inverso de false);
 • Depois, se tem a comparação “resultado2 == 55”, o que resul-
ta em true.
 • Então, aparecem dois valores booleanos –true: o “!(resultado 1 == 
28)” é verdadeiro e o “resultado2 == 55” também. Como o compa-
rador lógico neste caso é “&&” (e), todas as condições precisam ser 
verdadeiras, o que realmente acontece. Assim sendo, para a primeira 
condição, é exibido no terminal “As condições foram atendidas”.
Já para a segunda condição, se tem o seguinte cenário:
!(resultado1 > 27 || resultado2 == 55)
 • Dentro dos parênteses, há duas comparações de operadores 
lógicos de comparação e o operador lógico “||” (ou).
 • O resultado1 é igual a 27, e não maior, logo, o resultado é false.
 • O resultado2 é igual a 55, logo, o resultado é true.
 • A condição interna dentro dos parênteses volta true, porque 
apenas uma das comparações precisa retornar true.
 • O sinal de negação está negando esse resultado. Como ele é 
true, o resultado final é false.
 • Portanto, o resultado exibido no terminal é “Nenhuma das 
condições foi atendida”.
38
Estrutura de decisão em java
Um programa de computador trabalha constantemente em cima de 
decisões que são executadas a partir dos valores booleanos true e false. 
Além disso, os comandos if-else permitem que um comando ou bloco 
seja executado diante de uma comparação lógica. Assim, a instrução 
if-else possui uma estrutura básica que pode ser observada na Figura 6.
Figura 6 - Exemplo de condição IF-ELSE *
 Fonte: editorial Digital Pages (2020).
Como você deve ter observado, na figura 6 se tem a declaração 
do tipo primitivo boolean, com referência na memória chamada de 
“verdadeiro”, ou seja, o valor booleano possui valor true. Além disso, 
na estrutura if-else, a primeira condição, destacada em vermelho e na 
qual está o if, só é executada caso a condição dentro dos parênteses for 
verdadeira (true). Na hipótese da primeira condição ser false, é execu-
tada a condição dentro de else, destacada em cinza. Assim, em uma es-
trutura if-else, se não houver uma condição a ser executada dentro da 
condição else, ela não é obrigatória e nem é declarada,contendo apenas 
o if. Em alguns casos, há N condições em uma estrutura if-else, que é, 
então, denominada de if-else aninhada, como na figura 7.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
39
Figura 7 - Exemplo de decisão IF, ELSE E IF-ELSE *
Fonte: editorial Digital Pages (2020).
Como você pôde perceber, na figura 7, há uma instrução 
if-else aninhada, composta por vários blocos de instruções if-else. 
Se a primeira condição, destacada em vermelho, for true, as demais 
não são executadas. Mas, caso seja false, é apurada a segunda condi-
ção, destacada em verde e, se ela for true, as demais abaixo não são 
examinadas. E, caso seja false, é verificada a terceira condição, des-
tacada em bordô. Isso acontece até a condição em laranja e a última 
condição só é executada se a condição em laranja não for true. Para 
comparação de casos mais simples, é possível fazer uso do operador 
ternário. A sintaxe do operador ternário é: “condiçãoBooleana? se-
Verdade : seFalso;”.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
40
Figura 8 - Exemplo de SWITCH-CASE *
Fonte: editorial Digital Pages (2020).
Na figura 8, em azul, está o condicionador ternário e, em ver-
de, a expressão que resulta em um valor booleano true ou false. Se a 
expressão booleana for true, é executado o trecho entre ? (interro-
gação) e : (dois-pontos), destacado em vermelho. 
Mas, caso a expressão booleana seja false, é executado o tre-
cho após os: (dois-pontos), destacado em laranja. O operador ter-
nário é similar a uma expressão if-else simples.
Similar à um if-else aninhado, há o switch-case, utilizado para 
uma expressão que possui diversas possibilidades, como na figura 9.
Figura 9 - Exemplo de SWITCH-CASE *
Fonte: editorial Digital Pages (2020).
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
41
Diferentemente do if-else aninhado, o switch-case não para de 
ser executado até que a última condição não seja validada, exceto se 
usada a palavra-chave “break”. Na figura 9, há um switch-case e cada 
bloco possui a palavra-chave “break” para que, quando a condição for 
correspondida, o bloco de código switch-case seja interrompido.
Destacada em amarelo, a palavra-chave “default” é executa-
da quando nenhuma das condições é correspondida. Não obstante, 
há outras observações importantes quanto ao switch-case:
 • a palavra-chave “default” não é obrigatória e não precisa ter um 
break, afinal, não há mais condições a serem comparadas e, por con-
sequência, não há necessidade de interromper o bloco switch-case.
 • caso o bloco do switch-case não possua default, o último case 
não têm necessidade de ter break.
 • caso duas ou mais condições executem o mesmo processo, 
elas são alinhadas abaixo uma da outra sem expressão. Veja 
na Figura 10 que, na parte destacada em cinza, caso a variável 
número1 seja 8, 9 ou 10, é exibido no console o texto “O núme-
ro é 8, 9 ou 10”; e se não for nenhuma destas opções, é exibido 
no console “O número não é 8, 9 ou 10”;
Figura 10 - Exemplo de SWITCH-CASE ANINHADO *
Fonte: editorial Digital Pages (2020).
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
42
 • O switch-case também é designado para comparar valo-
res numéricos de, no máximo, tipo int, que variam entre 
-2147483648 e 2147483647. Somente a partir do Java 7, é 
possível trabalhar com Strings, portanto, tipos boolean, long, 
float e double não funcionam.
Estrutura de repetição em java
Além da estrutura de decisão, o sistema conta com estruturas de repetição 
que só param por uma condição programada, como se nota na Figura 11.
Figura 11 - Exemplo de Estrutura de repetição *
Fonte: editorial Digital Pages (2020).
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
43
Como você deve ter percebido, na Figura 11 há quatro tipos de 
estruturas de repetição:
 • o for, destacado em cinza, realiza uma tarefa enquanto a 
condição for verdadeira. Na figura 10, a variável i é decla-
rada no próprio escopo da condição, mas poderia ser de-
clarada fora. A estrutura for é lida da seguinte maneira: 
“enquanto a condição for verdadeira, execute a tarefa”. 
Cada trecho é separado por ponto e vírgula. Assim, no pri-
meiro ponto e vírgula consta a declaração da variável e a 
atribuição de um valor a ela. No segundo, há a condição e, 
no terceiro, a incrementação.
 • o do-while, destacado em bordô, executa uma tarefa enquanto 
a condição for verdadeira. A estrutura é lida da seguinte ma-
neira: “execute a tarefa, enquanto a condição for verdadeira”. 
A variável foi declarada fora da iteração, pois, se fosse decla-
rada dentro, ela seria criada novamente a cada iteração. Den-
tro do bloco do, é concretizada a incrementação e, dentro do 
while, a condição é verificada.
 • o while, destacado em vermelho, faz uma tarefa enquanto a 
condição for verdadeira. A estrutura é lida da seguinte ma-
neira: “enquanto a condição for verdadeira, execute a ta-
refa”. A variável é declarada fora do escopo do while, pois, 
se fosse declarada dentro, ela seria criada a cada iteração. 
Assim, a verificação e o incremento se dão dentro do escopo 
do while.
 • o último, embora seja similar ao for, é conhecido como forEa-
ch. Ele é utilizado para percorrer arrays e, a cada valor contido 
no array, ele promove uma tarefa. A estrutura forEach é inter-
pretada da seguinte maneira: “a cada dado, execute a tarefa”. 
O forEach não possui contador porque um array possui chave e 
valor, em que a chave é o índice e o valor é o dado em si. Logo, 
ele percorre o índice do array.
Embora while e do-while sejam similares, o while só executa 
se a condição for true, enquanto o do-while executa ao menos uma 
vez, mesmo que a condição seja false.
44
EXEMPLO
public class ExemploRepeticao {
public static void main(String args[]) {
int j = 0; 
do {
 System.out.println( “ O valor de J é “ + j );
} while (j != 0);
 int k = 0; 
while (k != 0) {
System.out.println( “ O valor de k é “ + k );
}
 }
}
Observe que, nesse exemplo, o do-while é executado uma vez, 
enquanto o while não é executado.
Terminologia da programação orientada 
a objetos
No mundo de orientação a objetos, assim como em outras áreas, 
existem terminologias utilizadas nas linguagens orientadas a ob-
jetos, tais como:
 • objetos - são instâncias de classes que possuem estado e 
comportamento. O estado é representado pelos campos (atri-
butos) daquele objeto, que podem ser modificados ao longo 
do tempo. Já os comportamentos são os métodos, compostos 
45
por um conjunto de instruções, com a característica de alterar 
o estado do objeto.
 • classes - são estruturas de um objeto (model) que contêm 
atributos e métodos. Todo objeto é uma instância pertencente 
à classe e toda classe precisa de um nome único no pacote em 
que se encontra. Seguindo a convenção de código, uma classe 
é declarada usando UpperCamelCase.
 • atributos - são as propriedades (variáveis) que descrevem o 
objeto. Em uma linguagem fortemente tipada, precisam ser 
de um tipo, seja ele primitivo ou de outra classe. Em uma lin-
guagem fracamente tipada, o tipo não importa, pois a lin-
guagem consegue se arranjar com o tipo de dado presente 
naquele atributo.
 • variáveis - são nomes atribuídos ao endereço de memória do 
computador utilizado para armazenamento de tipos de dados do 
programa executado. Possuem esse nome porque variam duran-
te a execução, não sendo um valor fixo. Seguindo a convenção de 
código, são declaradas usando LowerCamelCase e devem iniciar 
por uma letra (de a-z),underline (_) ou cifrão ($). É importante 
que você nunca inicie o nome de uma variável com números. 
Uma variável global pode ser acessada por qualquer método na 
classe e é declarada no cabeçalho da classe. Já uma variável local 
é visível apenas pelo método que está executando.
 • constantes - possuem as mesmas características de uma va-
riável, mas são imutáveis durante a execução do programa. 
Seguindo a convenção de códigos, uma constante é declarada 
usando UpperCase.
 • escopo - trata-se do local em que uma variável é acessada. Há 
dois tipos de escopo, o global e o local. Uma variável declarada 
no cabeçalho de uma classe possui o escopo global, ou seja, 
pode ser acessada por qualquer método de uma classe. Já uma 
variável local, declarada dentro de um método, tem o escopo 
local e só é acessada dentro daquele método, não sendo possí-
vel utilizá-la em outro método.
46
 • métodos e mensagens - os métodos são processos exe-
cutados a fim de realizar alguma operação relacionada ao 
objeto a que ela pertence. Eles se comunicam por meio de 
mensagens que podem ou não conter dados. Já as mensa-
gens são as informações contidas dentro dos parênteses 
dos métodos, batizados como parâmetros. A declaração de 
um método, seguindo a convenção de códigos, é escrita em 
LowerCamelCase.
 • herança - admite que um objeto herde as mesmas carac-
terísticas de outro objeto, facilitando o desenvolvimento 
e reaproveitando o código já existente. Uma classe Equi-
pamento Eletronico, por exemplo, possui característi-
cas (como marca, modelo, altura, largura, profundidade 
e preço), comportamentos (como liga e desliga) e outras 
duas classes, TV e Rádio, que apresentam as mesmas ca-
racterísticas que o equipamento, fazendo com que herdem 
esses atributos.
 • ocultação de informação (privacidade) - termo manifesto 
como Information Hiding, que provê a ocultação de informa-
ções desnecessárias, permitindo a visibilidade de itens es-
senciais da classe. Assim, a privacidade é controlada pelos 
três tipos de modificadores para atributos e métodos: pu-
blic, protected e private ou, respectivamente, visível a todas 
as classes de qualquer pacote; visível a todas as classes do 
mesmo pacote exceto em caso de herança visível por classes 
que a herdam em pacotes diferentes; e visível apenas pela 
própria classe.
 • encapsulamento de dados - muitos autores afirmam que o 
encapsulamento é utilizado para a proteção de dados, o que de 
fato acontece. Porém, a ideia é que esses dados sejam acessí-
veis diante dos métodos disponíveis naquela classe, denomi-
nados de getters e setters. Contudo, há outras formas de acesso 
a estes dados.
 • polimorfismo - em POO, possibilita que uma classe herde 
outra de maneira que seus comportamentos sejam similares, 
47
mas distintos. Um exemplo é a classe animal, na qual quase 
todos os animais têm o comportamento de emitir som, mas 
cada espécie emite um som particular.
 • identação - a identação (ou endentação) é o termo atribuído 
ao código-fonte de um programa, que auxilia na identificação 
de hierarquia de blocos de instrução, tornando o código mais 
“limpo” e de fácil entendimento. A identação não é obrigató-
ria na programação, mas sua prática é essencial. 
Um sistema computacional é gerado com objetivo de solucionar 
problemas cotidianos e a orientação a objetos é destinada a geren-
ciar a complexidade na solução dos problemas com um conjunto de 
objetos. Assim, baseados em objetos reais, os objetos criados são 
compostos por características e comportamentos, além de serem 
únicos na memória do sistema.
Instanciando um objeto
Para criar um objeto na memória do sistema, é preciso declarar o 
tipo do objeto seguido de um nome. Isso faz com que o programa 
reserve um espaço na memória do computador e, mediante o nome 
do objeto, se obtém acesso aos dados armazenados no objeto. No 
entanto, isso não é suficiente para que se trabalhe com o objeto, já 
que ele possui somente uma referência na memória.
Para que as informações do objeto sejam acessíveis, é ne-
cessário que ele seja instanciado e, para isso, emprega-se a pa-
lavra-chave “new” seguida do construtor da classe. Lembre-se 
que toda classe tem seu construtor, que não precisa ser declara-
do, mas, conforme a necessidade, é criado da maneira que me-
lhor convém.
DICA
48
DICA
Figura 12 - Exemplo de Instanciação *
Fonte: editorial Digital Pages (2020).
Devem ser utilizados ao longo da unidade, sejam gráficos, mapas 
mentais e/ou conceituais, fluxogramas, organogramas, tabelas e 
quadros, além de imagens que ilustrem graficamente o texto. Para 
esse fim se utilize de programas como canva.com, Lucidchart.com, 
pixabay e freepic. Ao inseri-lo, não esqueça de referenciar a fonte e 
colocar a legenda.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
Construtor padrão
Construtor da classe Car
Nova instância do objeto Car
Construtor customizado
com parâmetros
Referência do
objeto em
memória
49
Caro(a) aluno(a), neste material, discutimos o surgimento da pro-
gramação orientada a objetos, sua referência com modelos de en-
tidades e explicamos que, para programar, é preciso representar 
objetos por meio de classes que contêm estados e comportamentos 
de um objeto.
Além disso, explicamos que a POO melhora a produtividade dos(as) 
programadores(as), permitindo a reutilização de códigos e é de fácil 
manutenibilidade, além de ser escalável. 
Sobre a linguagem de programação Java, ressaltamos que ela é 
100% orientada a objetos e que funciona em diversos dispositivos 
e sistemas operacionais diferentes, sendo fortemente tipada, pos-
suindo tipos primitivos e uma classe diferenciada chamada String 
para trabalhar com caracteres alfanuméricos, mas que não precisa 
ser instanciada, além de haver vários métodos internos essenciais 
para um(a) programador(a) trabalhar com os caracteres.
Também foram abordados operadores lógicos, operadores lógicos 
relacionais, negação, comparadores de classes, estruturas de deci-
são e repetição. E, ao final, foram abordados conceitos da orientação 
a objetos, incluindo objetos, classes, atributos, variáveis, constan-
tes, escopos, métodos e mensagens, herança e encapsulamento.
Lembre-se de estudar antes e depois da sua aula, aproveite o mo-
mento com o(a) docente para tirar todas as suas dúvidas. 
Até breve!
SINTETIZANDO
UN
ID
AD
E
2
Objetivos
 ◼ Apresentar as características de Programação Orientada a Objetos.
 ◼ Compreender como surgiu o paradigma de Programação 
Orientada a Objetos.
 ◼ Introduzir a linguagem Java para Programação Orientada a Objetos. 
 ◼ Entender os conceitos da Programação Orientada a Objetos.
 ◼ Apresentar as estruturas de dados compostas homogêneas 
e heterogêneas.
 ◼ Apresentar os tipos abstratos de dados.
52
Introdução
Olá, aluno(a), como vai?
Vamos iniciar mais uma etapa de estudos e, a partir de agora, 
veremos os principais conceitos de atributos e métodos, entenden-
do a ocultação das informações através do encapsulamento. Além 
disso, serão apresentados os conceitos de instâncias, referências e 
como as classes enviam mensagens. 
Destaco que, neste material, será explicado qual o ciclo de 
vida de um objeto. Também apresentaremos o conceito de estrutura 
compostas homogêneas e heterogêneas.
Dito isto, desejo a você boa leitura e bons estudos!
53
Classes, pacotes, objetos, atributos, 
métodos, construtores, palavra-chave 
this e sobrecarga
Classes
A programação orientada a objetos demanda que, ao desenvolver 
um programa de computador, constantemente, sejam utilizadas 
classes, com as quais fazemos a representação de uma entidade, 
seja ela real ou abstrata. A declaração de uma classe é simples, con-
forme a sintaxe expressa na figura 1:
Figura 1 - Sintaxe básica de uma classe*
Fonte: Editorial Digital Pages, 2020.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponívelno seu Ambiente Virtual de Aprendizagem (AVA)�
54
Como você deve ter percebido, na figura 1 temos o modifica-
dor de acesso da classe que determina a visibilidade da classe, e que 
pode ser public, protected, private ou default. 
Os modificadores de acesso são palavras-chaves reservadas pela 
linguagem, e devem ser escritos com caracteres minúsculos. 
Os modificadores protected e private são raramente usados, e 
só são possíveis através de classes aninhadas.
No contexto da programação em Java, o modificador de acesso de-
fault não deve ser declarado, sendo oculto.
Além dos modificadores de acesso, temos o nome da clas-
se, que deverá ser único no pacote e seguir a convenção de códigos. 
Além disso, ela deve ser declarada em CammelCase, seguindo padrão 
UpperCamelCase, seu nome deverá ser um substantivo e ter relação 
com o que ela realmente propõe, sendo simples e objetivo.
Fique atento(a), pois as declarações de atributos e métodos 
devem ser realizadas dentro do escopo da classe. Importante res-
saltar que:
 • toda classe deve possuir a palavra-chave class declarada entre 
o modificador de acesso e o nome da classe;
 • toda classe deve estar contida em um pacote. Isso porque, 
mesmo que ele não seja definido, por padrão, a classe estará 
em um pacote default.
DEFINIÇÃO
VOCÊ SABIA?
55
Pacotes
Caro(a) aluno(a), ao programar fazendo uso da orientação a objetos, 
utilizamos pacotes (packages). Pensando nisso, mesmo que eles não 
sejam definidos, as classes devem estar dentro de um pacote default 
do próprio Java. 
Lembre-se: pacotes são utilizados a fim de estruturarmos melhor 
o sistema desenvolvido, facilitando a localização de tipos, evitando 
conflitos de nomes e controlando o acesso.
Ao trabalharmos com pacotes diferentes do default, temos 
que declarar, na estrutura da classe, a palavra-chave packages, se-
guida do nome do pacote. Carvalho e Teixeira (2012, p. 36) definem 
pacotes como sendo um envoltório de classes, um guarda classes e 
outros pacotes. Dessa maneira, podemos visualizar os pacotes como 
diretórios, ou pastas, nos quais podemos guardar arquivos (classes) 
e outros diretórios (pacotes).
Veja o exemplo da declaração de uma classe com pacote:
package modelos; 
public class Pessoa { 
 private String nome;
}
Se declarado, o pacote deve estar na primeira linha de código.
DICA
DICA
56
Mendes (2009, p. 79) diz que os nomes de pacotes, por reco-
mendação, mas não obrigatoriamente, devem ser declarados utili-
zando o nome do domínio reverso da empresa. 
Imagine a seguinte situação: uma empresa com domínio www.mi-
nhaempresa.com.br está desenvolvendo o projeto farmacêutica, 
portanto, durante o desenvolvimento do projeto, ao criar o pacote 
interfaces, deve ser utilizado o nome br.com.minhaempresa.far-
maceutica.interfaces.
É importante destacarmos que o uso de pacotes é útil para re-
solver problemas com a importação de classes que possuem nomes 
iguais. E, por convenção, os pacotes devem possuir nomenclaturas 
que usam letras minúsculas e sem caracteres especiais. Veja um 
exemplo de estrutura de pacotes de um sistema na figura 2:
Figura 2 - Exemplo de estrutura de pacotes
Fonte: Editorial Digital Pages, 2020.
EXEMPLO
57
Como você deve ter percebido, na figura 2 temos vários pa-
cotes do projeto fictício denominado gtc. e, em cada pacote, há um 
tipo de classe que corresponde ao que ela faz. Além disso, todos os 
pacotes após o .gtc. estão dentro do primeiro pacote gtc.
Objetos
Inicialmente, é necessário que você saiba que os objetos são todas 
as entidades que podem ser modeladas (podendo ser concretas 
ou não) e que possuem estado e comportamento. Além disso, o 
estado de um objeto é o conjunto das características que ele pos-
sui e que podem ser modificadas. Já o comportamento é definido 
pelas ações que modificam o estado do objeto. Veja um exemplo 
na figura 3:
Figura 3 - Exemplo de classe com estado, comportamento e outro objeto*
Fonte: Editorial Digital Pages, 2020.
Para que você entenda, na figura 3 temos duas classes que são 
representações do objeto carro e fabricante. Destacado em cinza, 
temos o estado da classe, que são os seus atributos e, em vermelho, 
temos o comportamento que são os métodos que alteram o estado 
da classe. Observe que o objeto carro, possui como atributo o objeto 
fabricante, que também possui estado e comportamento.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
58
Atributos
Os atributos são as características que um objeto possui. Dessa manei-
ra, podemos entender que um atributo é a representação de um dado 
ou informação de estado do objeto e cada objeto de uma classe pos-
sui seu valor próprio. Existem dois tipos de atributos na programação 
orientada a objetos: os atributos de objetos e os atributos de classes.
Os atributos de objetos são os que descrevem os valores daque-
le objeto, em que cada instância possui a sua particularidade. Já os 
atributos de classe são os valores compartilhados entre todas as 
instâncias do objeto.
Em Java, por se tratar de uma linguagem fortemente tipada, 
ao declarar um atributo, precisamos dizer de qual tipo é aquele atri-
buto. Veja a sintaxe básica para declaração de atributos na figura 4:
Figura 4 - Exemplo de declaração de atributos em classe*
Fonte: Editorial Digital Pages, 2020.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
Indica que o atributo é da classe
Indica que o atributo é da classe
Indica que o atributo é 
da classe
Indica que o atributo é da classe
Tipo de dado: primitivo ou outro projeto
Nome do atributo
Indica que o atributo é da classe
DEFINIÇÃO
59
Observando a figura 4, podemos fazer algumas observações:
 • os atributos possuem modificadores de acesso, que podem 
ser private, protected, public ou default, e que determinam 
a visibilidade do atributo. Lembre-se que os modificadores 
são palavras-chave da linguagem e são declarados em le-
tras minúsculas.
 • a palavra-chave static é reservada da linguagem e deve ser 
declarada em letras minúsculas. É utilizada para informar 
que aquele atributo é de classe, portanto, todas as instân-
cias da classe possuem o mesmo valor e, se em algum mo-
mento ele for alterado, todas as instâncias passarão a ter o 
novo valor.
 • o tipo do dado é uma característica das linguagens forte-
mente tipadas como o Java, em que é necessário declarar 
qual é o tipo do atributo, que pode ser primitivo ou um outro 
objeto (classe).
 • por último, temos o nome do atributo que deve ser único na 
classe. Seguindo a convenção de códigos, ele deve ser declara-
do utilizando LowerCamelCase.
Uma observação importante a se fazer sobre os atributos de 
classe é que, para acessá-los, não é necessário instanciar o obje-
to, porém a classe precisa estar visível a outra classe e o atributo 
precisa ter o modificador public, protected ou default. Caso contrário, 
eles devem ser acessados por métodos também declarados como 
estáticos, por exemplo, os métodos getters e setters. Para acessar o 
atributo estático da classe, precisamos fazer referência ao objeto, 
seguido do atributo. 
Carro.quantidadeVendida; ou Carro.getQuantidadeVendida();.
EXEMPLO
60
Métodos
Os métodos são estruturas contidas dentro de classes que são utili-
zadas para realizar operações. Eles, geralmente, alteram o estado de 
um objeto, porém podem ser utilizados para realizar qualquer fun-
ção (não demandando, necessariamente, a alteração de um objeto, e 
podendo apenas retornar um dado qualquer).
Dependendo do que o método faz, se ele é utilizado por vá-
rias classes e não realiza operações específicas com atributos de 
uma classe (como calcular dois valores), ele pode se conter apenas 
dentro de classes que não possuem atributos, sendo essas classes 
denominadas bibliotecas de operações. Veja como é a sintaxe da de-
claraçãode métodos, na figura 5:
Figura 5 - Sintaxe básica de método*
Fonte: Editorial Digital Pages, 2020.
Dentro da classe mostrada na figura 5, temos:
 • em azul escuro, os modificadores de acesso aos métodos, que 
podem ser public, protected, private ou default.
 • em rosa, o modificador static que possibilita utilizar o método 
da classe sem a necessidade de instanciá-la.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
61
 • em vermelho, duas informações. A primeira está na parte de cima, 
onde se indica a palavra int. Isso quer dizer que o método deve-
rá retornar algum dado que represente o tipo int (qualquer valor 
dentro da faixa de -2147483648 a 2147483647). Depois, temos a 
palavra-chave return, que retorna um resultado entre os números 
inteiros. Um método pode retornar qualquer tipo de dado, seja ele 
primitivo ou não, além de poder não retornar nada, sendo que o 
tipo de retorno deve ser void e não possuir a palavra-chave return.
 • em verde, os nomes dos métodos. Diferente dos atributos, 
podemos possuir vários métodos com o mesmo nome, porém 
eles precisam possuir uma assinatura diferente. Lembre-se 
que a assinatura de um método é composta por nomes e parâ-
metros. Assim, a possibilidade de criar dois ou mais métodos 
com mesmo nome e assinaturas diferentes é chamada de so-
brecarga de métodos. Seguindo a convenção de códigos Java, 
os nomes de métodos devem ser declarados usando LowerCa-
melCase e representar um verbo.
 • em azul, os parâmetros. Eles precisam estar dentro dos parên-
teses do método. A quantidade de argumentos passados por pa-
râmetros podem ser nenhuma ou várias, e de diferentes tipos de 
dados ou objetos. Os parâmetros, se declarados, devem possuir 
tipo e nome, assim como fazemos para declarar atributos na 
classe. Esses parâmetros devem ser informações que são utiliza-
das dentro do método, e não estão acessíveis fora do seu escopo.
 • em laranja, o escopo do método que está entre as chaves. Nele 
são realizadas as operações, declaradas variáveis e, se neces-
sário, enviado o retorno de que o método necessita. Lembre-
-se que toda variável declarada ou objeto instanciado dentro 
do escopo do método é acessível somente dentro do método e 
não pode ser reutilizado em outro método.
A invocação de um método é feita, geralmente, de forma ex-
plícita a partir de outros trechos de códigos. Esses trechos podem 
estar dentro de outros métodos (um método chamando o outro) que 
está dentro da própria classe ou a partir de outras classes. Veja o 
exemplo da figura 6:
62
Figura 6 - Sintaxe para invocação de métodos*
Fonte: Editorial Digital Pages, 2020.
Como você pode observar na figura 6, temos o método main da 
classe Start declarado em cinza. Ele é um método padrão da linguagem 
Java, que é utilizado para dar o pontapé inicial na aplicação. Esse método 
sempre será public static void e deve possuir como parâmetro um array de 
argumentos do tipo String, que pode ser ou não passado durante a inicia-
lização da aplicação. Para esse caso, os parâmetros não são obrigatórios 
e nome args pode ser qualquer outro, porém deve ser um array, ou seja, 
possuir os colchetes declarados após o nome do parâmetro. O método 
main não possui retorno, já que o retorno esperado é void.
Assim, com base na figura 5, a invocação do método realizada 
na figura 6 é feita de duas maneiras diferentes, conforme explica-
remos a seguir.
 • A primeira maneira está destacada em amarelo, e é feita sem a ne-
cessidade de criar uma instância do objeto ExemploMetodo. Isso 
só é possível graças ao método ter sido declarado com modificador 
static, o que não funcionaria para o método subtrair. Para fins didá-
ticos e uma melhor visualização da declaração de um método, foram 
separados cada trecho, porém o correto é declarar da seguinte ma-
neira: NomeClasse.nomeMetodo(tipoAtributo nomeAtributo);.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
63
DICA
 • A segunda maneira está destacada em laranja e só é possível 
após a instanciação da classe ExemploMetodo, destacada em 
roxo. Isso permite que os métodos estáticos e não estáticos do 
objeto exemplo fiquem acessíveis. Assim como foi feito para a 
primeira maneira, a declaração foi separada em trechos para 
melhor visualização e o correto é instanciaObjeto.nomeMe-
todo(tipoAtributo nomeATributo);.
Os parâmetros passados ao invocar cada método são núme-
ros inteiros, assim como é esperado pelos métodos na classe Exem-
ploMetodo. Eles devem ser passados na mesma ordem em que a 
assinatura do método se encontra. Ou seja, se um método aguarda 
argumentos do tipo int e boolean em sua respectiva ordem, não se 
pode passar os argumentos boolean e int (de forma invertida), ou 
deixar de passar um dos parâmetros.
Construtores
Construtores são métodos especiais chamados através do uso da 
palavra-chave new. São usados quando desejamos criar uma ins-
tância de classe.
Um construtor não precisa ser declarado, mas, dependendo do con-
texto, pode ser essencial que ele seja, pois é por meio dele que pode-
mos, por exemplo, inicializar uma variável ou executar um método 
antes de fazer uso do objeto.
Por meio da criação de construtores podemos garantir que 
o código que eles contêm será executado antes de qualquer outro 
código em outros métodos, já que uma instância de uma classe só 
pode ser usada depois de ter sido criada com new, o que causará a 
execução do construtor (SANTOS, 2013).
64
Quando os atributos (primitivos ou de classe) são inicializa-
dos, mas não receberam uma programação durante sua estruturação, 
iniciam-se automaticamente com valores default listados a seguir.
 • Tipo boolean: inicializados com valor false, por padrão.
 • Tipo byte, char, int, long e short: inicializados com valor 0 (zero).
 • Tipo float e double: inicializados com valor 0.0 (zero ponto zero).
 • Instâncias de classes: inicializadas com valor null.
Para que você entenda o que estamos tratando, sugiro que veja o 
exemplo de uma classe sem um construtor definido: 
 public class BrinquedoAPilha {
private int quantidadePilha;
}
Uma referência com valor null não estará acessível a menos 
que ela seja inicializada através do uso da palavra-chave new.
No exemplo do código anterior, ao instanciar o objeto, o 
construtor default será executado, porém nada de mais acontecerá. 
Mas, supondo que a quantidade mínima de pilhas sejam duas, po-
demos declarar o construtor para atribuir o valor dois sempre que o 
objeto for instanciado. Veja o exemplo do que estamos falando:
public class BrinquedoAPilha {
 public Brinquedo () {
 this.quantidadePilha = 2;
 }
 private int quantidadePilha;
}
EXEMPLO
65
No exemplo do código anterior, foi declarado o construtor 
padrão que atribui o valor dois ao atributo quantidadePilha sempre 
que o objeto seja instanciado. Isso porque, se isso não fosse feito, o 
valor sempre se iniciaria como sendo zero.
O construtor, embora seja um método, possui suas particula-
ridades o que o diferencia dos demais métodos. São elas:
 • o construtor não precisa ser declarado. Se não declarado, o 
compilador usa o construtor default da classe. Assim, o cons-
trutor default é assinado pelo nome da classe e sem argumen-
tos como parâmetros;
 • o construtor sempre possui o mesmo nome da classe à qual 
ele pertence;
 • o construtor não tem nenhum tipo de retorno e não deve ser 
declarado como void;
 • o construtor pode receber todos os modificadores de aces-
so, porém não é muito comum encontrar construtores com 
modificadores de acesso private. Isso ocorre porque acaba 
não sendo usual uma classe conter um construtor com essa 
característica, a menos que ele seja chamado a partir de ou-
tros construtores com modificador de acesso public, protec-
ted ou default;
 • o construtor só pode ser chamado a partir da declaraçãoda 
palavra-chave new, que é utilizada somente quando dese-
jamos instanciar um novo objeto. Porém, dentro da própria 
classe, se não desejamos criar uma instância nova do mesmo 
objeto, mas sim trabalhar com o construtor, devemos fazer o 
uso da palavra-chave this.
Uma classe pode possuir vários construtores com assina-
turas diferentes, assim como os métodos comuns. Porém, ao de-
clarar um construtor com assinaturas diferentes do default, e para 
garantir que o código funcionará corretamente, é importante a 
66
EXEMPLO
criação explícita do construtor default, pois alguns frameworks 
podem fazer uso deles.
public class BrinquedoAPilha {
 public Brinquedo () { } //Construtor default
 public Brinquedo (int quantidadePilha) { //Construtor com assinatura
diferente
this.quantidadePilha = quantidadePilha;
 }
 private int quantidadePilha;
}
O modificador default é similar ao protected, porém a diferença está 
no contexto de herança. Dessa maneira, o protected permite que 
classes em diferentes pacotes herdem atributos protected, já o de-
fault só permite herança por classes que estejam no mesmo pacote. 
Perceba que, no exemplo do código anterior, o construtor default foi 
desenvolvido simplesmente por ter sido criado um outro construtor 
com assinatura diferente.
SAIBA MAIS
67
Palavra-chave This
A palavra-chave this (traduzida do inglês como “este”) só pode ser 
utilizada para referenciar a própria instância do objeto criado, seus 
atributos e métodos. Além disso, não funciona com atributos e mé-
todos com modificador static, já que eles pertencem à classe e não 
ao objeto. Portanto, quando estamos nos referindo a um atributo ou 
método correspondente ao objeto, devemos fazer uso do this. Veja o 
exemplo na figura 7:
Figura 7 - Exemplo do uso da palavra-chave this
Fonte: Editorial Digital Pages, 2020.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
68
Observe que, na figura 7, temos o Método Main que inicia-
liza a aplicação e, ao executá-lo, estamos instanciando um objeto 
da mesma classe. Ao criar o objeto na linha sete (destacada em cin-
za), estamos chamando o construtor declarado na linha 11 (também 
destacado em cinza) que, posteriormente, chama o construtor da 
linha 17 (destacado em vermelho) por meio da palavra-chave this, 
apresentada na linha 13.
Perceba que o construtor, que possui o parâmetro int, 
possui a variável declarada com nome de contador, nome se-
melhante ao atributo do objeto. Para distingui-los, usamos a 
palavra-chave this, em que this.contador pertence ao atributo 
do objeto, e o que não faz uso da palavra-chave this pertence à 
variável do método.
Importante salientar que o fato de chamar o construtor den-
tro da própria classe, por meio da palavra-chave this, não significa 
que estamos instanciando um novo objeto e nem é possível fazer 
uso da sintaxe new this();.
Sobrecarga
A sobrecarga é a denominação da possibilidade de se ter dois ou mais 
métodos com o mesmo nome. Isso só é possível graças aos métodos 
possuírem assinaturas que são consideradas pelo nome e argumen-
tos passados em seus parâmetros.
Alguns escritores defendem que o tipo de retorno faz parte da 
assinatura, mas, segundo Santos (2013), o tipo de retorno do mé-
todo não é considerado parte da assinatura. Essa afirmação é com-
provada quando se tenta criar métodos com retornos diferentes, 
porém com nome e tipos de parâmetros iguais, na mesma ordem. 
Ela pode ser útil e evita que o método seja escrito com numeradores, 
por exemplo: metodo1, metodo2 etc. 
69
EXEMPLO
Um exemplo detalhado pode ser visto na figura 8:
Figura 8 - Sobrecarga de métodos
Fonte: Editorial Digital Pages, 2020.
Conforme pode ser visto na figura 8, possuímos dois métodos com 
o mesmo nome, porém com assinaturas diferentes. Observe que, na 
chamada dos métodos, os parâmetros correspondem à quantidade 
e tipos de atributos contidos dentro dos parâmetros em respectivas 
ordens. O primeiro método pagarPrestacao tem somente dois pa-
râmetros, dos tipos string e double. Já o segundo possui três parâ-
metros, um do tipo int, outro do tipo string e outro do tipo double. É 
importante destacarmos que é indispensável respeitar a ordem dos 
parâmetros já é suficiente para que o compilador entenda a assina-
tura do método e saiba qual deles deverá ser executado. Isso porque, 
se durante a chamada de um dos métodos essa ordem de atributos 
fosse invertida, passando tipos de dados diferentes do esperado, o 
código não funcionaria.
70
Instanciação e referências de objetos
A possibilidade de criar um programa de computador com base em 
objetos, concretos ou não, facilita o cotidiano do(a) programador(a). 
Isso porque é mais fácil criar programas com estruturas que façam 
algo com um objeto, do que programas que sigam uma estrutura 
(programação estrutural).
Cada objeto é uma instância de classes e, para serem aces-
síveis, devem possuir referências na memória do sistema e, além 
disso, as referências de um objeto são, basicamente, variáveis de 
sistema que possuem o tipo da classe. Veja o exemplo da figura 9, 
sobre referência e instanciação:
Figura 9 - Exemplo de referência e instanciação*
Fonte: Editorial Digital Pages, 2020.
Para instanciar um objeto, precisamos fazer a declaração utilizan-
do a palavra-chave new, seguido do construtor da classe. Isso é suficien-
te para que criemos uma instância, porém, para que possamos trabalhar 
com essa instância, é necessário atribuí-la a uma referência do tipo da 
classe, na memória do sistema. Então poderemos fazer uso do objeto.
No exemplo da figura 9, temos duas classes. Na classe Exem-
ploReferencia, instanciamos o objeto da classe Carro na referência 
carro, para que só então tenhamos acesso a seus atributos e métodos.
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
71
Pensando nisso, destacado em cinza na linha quatro, fizemos 
referência da classe Carro à memória do sistema com o nome carro. 
Ou seja, nesse ponto estamos dizendo ao compilador que reserve na 
memória um espaço para um objeto do tipo Carro e que essa refe-
rência terá nome de carro.
O nome da referência pode ser qualquer um, porém cabe ao(à) 
programador(a) seguir a convenção de códigos, que diz que de-
vemos declarar um nome que realmente corresponda ao que a 
referência possui em si, a fim de deixar o código mais legível 
aos humanos.
No caso da figura 9, a referência carro está nula, já que ainda 
não temos um objeto criado para ela. Depois, na linha sete estamos 
atribuindo, nessa referência (em cinza), um novo objeto da classe 
Carro (em laranja) e, por isso, fazemos uso da palavra-chave new 
seguido do construtor default da classe Carro.
Somente após termos atribuído o objeto na referência criada 
em memória é que podemos inserir informações, como é feito nas 
linhas 10 e 11 por meio dos métodos set, ou obter informações, como 
é feito na linha 17 por meio dos métodos get.
Essa forma de inserir informações, ou recuperar informações, 
por meio dos métodos get e set, é chamada de encapsulamento de 
dados, pois seus atributos estão declarados com modificador de 
acesso private.
DICA
DEFINIÇÃO
72
Envio de mensagens
A programação orientada a objetos promove a comunicação de um 
objeto com outro. Esta comunicação provém da troca de mensagens 
que poderá ter ou não um retorno.
Segundo Batista e Moraes (2013, p. 59), as mensagens são 
formadas por três elementos:
 • emissor - objeto que envia a mensagem;
 • receptor - objeto que recebe a mensagem;
 • especificação de serviço - o método deverá ser executado e, 
se contiver parâmetros, eles devem ser enviados juntos.
Veja um exemplo da troca de mensagens na figura 10:
Figura 10 - Exemplo de troca de mensagens entre objetos
Fonte: Editorial Digital Pages, 2020.
No exemplo da figura 10, o emissorPessoa especifica qual 
serviço deseja que o receptor Lâmpada execute. Portanto, nesse 
exemplo, a mensagem enviada por Pessoa seria: Lampada.acen-
der(); ou Lampada.apagar();.
73
Importante observar que a mensagem enviada deverá sempre ser 
algo que o outro objeto sabe executar e, se possuir parâmetros, eles 
devem ser enviados junto com a mensagem.
Ciclo de vida de um objeto
Todo objeto criado em Java possui um ciclo de vida, que está subdi-
vidido em três fases distintas.
 • Criação de objetos: o fato de referenciar o objeto não significa 
que estamos criando o objeto. Isso porque todo objeto é criado 
a partir do momento em que se utiliza a palavra-chave new 
seguida do construtor da classe.
 • Acessibilidade do objeto: o objeto só estará acessível a partir 
do momento em que ele é atribuído a uma referência de uma 
variável. Ele pode perder a referência e ficar inacessível nos 
seguintes casos:
• caso o objeto seja substituído por outro objeto: o novo obje-
to ganha a sua referência e o anterior a perde;
• caso a referência a qual o objeto pertence seja atribuída à 
palavra-chave null.
 • Descarte de objeto: Java conta com o Garbage Collector (co-
letor de lixo), que remove da memória do sistema todo obje-
to inacessível. Ele é executado em segundo plano juntamente 
com a aplicação Java, portanto, não há como prever quando o 
Garbage Collector entrará em cena e nem mesmo saber quais 
objetos foram coletados, sendo possível apenas saber quan-
tos objetos podem ser coletados.
Veja um exemplo do ciclo de vida do objeto na figura 11:
DICA
74
Figura 11 - Exemplo de ciclo de vida de objetos*
Fonte: Editorial Digital Pages, 2020.
Conforme você deve ter observado, no exemplo da figura 11, 
temos as seguintes informações:
 • em cinza, temos a criação da referência do objeto na memória;
 • em laranja, a criação de um novo objeto;
 • em marrom, a atribuição de um objeto em uma referência já criada.
Por outro lado, destrinchando o código da figura 11, temos as 
seguintes anotações:
 • na linha quatro, estamos criando a referência em memória 
denominada carro para algum objeto do tipo Carro, mas, até 
esse momento, não possuímos nenhum objeto;
* Caro(a) aluno(a), para uma melhor visualização da figura, sugerimos que 
acesse o material disponível no seu Ambiente Virtual de Aprendizagem (AVA)�
75
 • já na linha sete, estamos criando um objeto do tipo Carro, mas 
não o estamos atribuindo a nenhuma referência, portanto ele 
está inacessível, podendo ser removido pelo Garbage Collector;
 • na linha dez, estamos criando um novo objeto do tipo Carro 
e o atribuindo à referência criada na linha quatro, portanto, 
a partir deste momento a referência carro possui um objeto 
do tipo Carro. Perceba que, até este momento, dois objetos 
foram criados, um acessível e outro inacessível;
 • na linha 13, estamos criando a referência em memória, cha-
mada carro2, para o objeto do tipo Carro. Nessa linha, a re-
ferência e a criação do objeto são feitas juntas, portanto, até 
essa linha temos dois objetos acessíveis e um objeto inaces-
sível, totalizando três objetos do tipo Carro;
 • na linha 16, é atribuído um novo objeto à referência carro2, 
portanto, o objeto que estava vinculado a ela agora já não está 
mais acessível, estando disponível para o Garbage Collector. 
Até o momento criamos quatro objetos, dois estão acessí-
veis e dois não estão acessíveis;
 • na linha 19, é atribuída a palavra-chave null à referência carro, 
tornando o objeto que estava atribuído a ela inacessível e dis-
ponível ao Garbage Collector. Dessa maneira, até o momento 
foram criados quatro objetos, um está acessível pela refe-
rência carro2 e três inacessíveis;
 • da linha 22 a linha 30, estamos fazendo uma iteração que vai de zero 
a nove (i começa com zero e vai até nove, que é menor que dez), 
portanto, o código dentro de sua estrutura é realizado dez vezes;
 • na linha 25, há a criação da referência carro3 e a atribuição de 
um novo objeto a essa referência, logo são criados dez obje-
tos, mas apenas um está acessível (o último);
 • na linha 28, acontece algo parecido com o caso anterior, po-
rém a referência em memória já está criada. Até a sua primeira 
iteração, a referência está nula e, a partir da segunda iteração, 
o objeto é substituído e fica disponível apenas o último objeto 
criado. No total, também são dez objetos criados.
76
Podemos dizer que, nas condições anteriores, até a linha 19, pos-
suíamos apenas quatro objetos, em que apenas um estava acessível. 
Mas, durante a iteração, foram criados 20 objetos do tipo Carro, mas 
apenas dois deles estão acessíveis, um atribuído à referência carro3 
e outro à referência carro. Então, após a conclusão da iteração, fo-
ram criados 24 objetos, mas apenas três estavam acessíveis, sendo 
que 21 deles podem ser coletados, a qualquer momento, pelo Gar-
bage Collector. 
Abstração e encapsulamento
Programar orientado a objetos faz com que o(a) programador(a) 
desenvolva um sistema com base em objetos, abstraindo as infor-
mações relevantes para o desenvolvimento. Essas informações, de-
pendendo das circunstâncias, necessitam de uma certa proteção, 
deixando acessível apenas aquilo que realmente interessa ou evi-
tando que os atributos sejam acessados de forma direta, seja para 
alterar ou obter as informações. Assim, vamos discutir as particula-
ridades de cada um dos temas.
Abstração
De modo geral, segundo Moreira Neto (2009, p. 9), a abstração con-
siste em compreender um sistema, seja ele concreto ou não, criando 
um modelo documentado e padronizado que reflita seu comporta-
mento, ou para utilizar em uma definição mais específica no desen-
volvimento de software.
Este conceito se dá ao fato de poder representar um objeto real 
utilizando uma classe. Ele possui essa denominação devido à pos-
sibilidade de abstrair propriedades e funcionalidades em métodos. 
DICA
77
REFLITA
Para entender o que estamos tratando, observe a figura abaixo:
Figura 12 - Exemplo para abstração de propriedades e funcionalidades
Fonte: Adobe Stock. Acesso em: 08 jun. 2020.
Analisando a figura 12, podemos observar as propriedades e 
funcionalidades, sendo:
 • propriedades: marca, modelo, ano de fabricação, ano do mo-
delo, quantidade de lugares, quantidade de portas, cor etc.;
 • funcionalidades: acelerar, trocar de marcha, abastecer, trocar 
pneus, calibrar pneus, substituir estepe, inclinar bancos, ligar e des-
ligar a lanterna, o farol, ligar/desligar o limpador de para-brisa etc.
Como você deve ter percebido, são inúmeras possibilidades de abs-
trações de dados e funcionalidades de um objeto, mas será que de-
vemos incluir todas as possibilidades em nosso sistema? 
Bom, a resposta para esta pergunta é: depende. A abstração acon-
tece para definirmos o modelo de um objeto no sistema. Dessa ma-
neira, se uma informação ou funcionalidade for irrelevante para o 
sistema, ela não precisa estar presente, pois não terá nenhuma uti-
lidade. Além disso, ter essas funcionalidades inúteis pode consumir 
memória ou processamento, deixando o sistema mais pesado. Dessa 
maneira, tudo depende do modelo de negócio aplicado ao sistema.
78
Encapsulamento
O termo encapsulamento, para a linguagem de programação orienta-
da a objetos, determina a disposição para acesso de métodos ou atri-
butos em uma classe pública. Isso possibilita a ocultação de atributos, 
tornando acessíveis via métodos apenas aqueles que realmente pre-
cisam ser acessados. Moreira Neto (2009, p. 73) diz que os atributos 
de um objeto podem ser escondidos de outros objetos por uma inter-
face pública de métodos, de modo a impedir acessos indevidos.
O encapsulamento de dados só é possível graças aos modificadores 
de acesso para membros de classes, conforme pode ser visto no quadro 1:
Quadro 1 - Modificadores de acesso para membros de classe
Fonte: Adaptado de Moreira Neto, 2009, p. 73.
Perceba que, no quadro 1, temos as declarações sobre os mo-
dificadores de acesso que determinam a visibilidadede um atributo 
ou método. Para o cenário private, apenas a classe à qual o atribu-
to/método pertence é visível e acessível. Um atributo/método- sem 
declaração de modificador (<none>) é denominado default e a sua 
visibilidade é permitida apenas pela própria classe ou classes que 
estão no mesmo pacote.
Atributos/métodos declarados como protected são similares 
aos que não possuem declaração, porém são acessíveis também por 
classes que os herdam, mesmo que em diferentes pacotes. Assim, 
atributo/método com modificadorpublic têm sua visibilidade a par-
tir de qualquer classe e independe do pacote em que ele se encontra.
private
<none>
protected
public
*
*
*
*
*
*
*
*
* *
Modificador Própria classe Classes do mesmo pacote
Subclasses
(herança)
Universo 
(qualquer classe)
79
Com essa visão sobre a visibilidade dos atributos e métodos, 
podemos enxergar a importância de encapsular os atributos. Vamos 
a um exemplo:
Maria possui R$ 300,00 em sua conta bancária, logo o atributo saldo 
é igual a R$ 300,00. Mas, supondo que Maria vá fazer um saque e 
que, chegando no caixa eletrônico, ela solicite o valor de R$ 400,00. 
Dessa maneira, sem uma proteção adequada ao atributo saldo, ela 
poderia realizar o saque e ficar com saldo de R$ -100,00. Então, em 
um acesso de maneira direta a esse atributo, além da possibilidade 
de sacar um valor indisponível, também há a possibilidade de que o 
saldo seja alterado diante de qualquer lugar, por qualquer circuns-
tância, seja atribuindo um valor a mais ao que já se tem, ou dimi-
nuindo o valor existente. Veja o exemplo em código na figura 13:
Figura 13 - Exemplo de classes com atributos sem encapsulamento
Fonte: Editorial Digital Pages, 2020.
EXEMPLO
80
Observando a figura 13, temos três classes. As classes Pessoa 
e ContaCorrente estão sem encapsulamento, ou seja, seus atribu-
tos estão todos públicos e acessíveis de qualquer lugar. Já na classe 
ExemploEncapsulamento, temos o método main que é executado 
para inicializar a aplicação Java e, ao executá-la, criamos, na me-
mória, a referência contaCorrente com a instância do objeto do tipo 
ContaCorrente, que por sua vez instancia o objeto Pessoa em seu 
atributo pessoa.
Para acessar os atributos de pessoa, precisamos apenas utilizar a 
referência contaCorrente, depois a referência pessoa e depois seu 
atributo. Com isso, conseguimos acesso direto a esse dado, podendo 
alterá-lo a qualquer momento.
Ainda considerando o exemplo de Maria, vamos ao atri-
buto saldo. Veja que foi atribuído o valor de R$ 300,00 e, pos-
teriormente, foi feita a retirada de R$ 400,00, deixando o valor 
do saldo negativo (R$ -100,00). Poderíamos validar se há sal-
do suficiente na conta para realizar o saque, mas isso deve-
rá ser um serviço da classe ContaCorrente e não da classe 
ExemploEncapsulamento.
DICA
81
Agora, para a segurança da aplicação, vamos a um exem-
plo de uma estrutura com os dados encapsulados, apresentado 
na figura 14:
Figura 14 - Exemplo de classes com atributos encapsulados
Fonte: Editorial Digital Pages, 2020.
Observe que nesse novo caso nas classes Pessoa e ContaCor-
rente os atributos possuem encapsulamento, ou seja, seus atributos 
só estão acessíveis via métodos disponíveis na própria classe.
Dessa maneira, ao executar a aplicação, o método main irá 
instanciar o objeto da classe ContaCorrente na referência de me-
mória contaCorrente, igual na figura 13, porém os acessos aos dados 
só são possíveis por meio dos métodos contidos na própria classe.
Lembre-se que, para atribuirmos/acessarmos a variável 
nome, da classe Pessoa, precisamos utilizar o método getPes-
soa da classe ContaCorrente, que irá obter o objeto pessoa e então 
fazer uso do método setNome da classe Pessoa, passando como 
parâmetro o texto desejado. Nesse momento, quem é responsá-
vel pela atribuição do nome é a classe Pessoa, não mais a classe 
ExemploEncapsulamento.
82
Observe que temos, na classe ContaCorrente, os métodos 
realizarSaque, consultarSaldo e depositar. Eles serão responsáveis 
pelos serviços. Inclusive, o primeiro método deverá validar se há 
saldo suficiente para saque. Perceba, ainda, que não é mais possível 
alterar o valor do saldo diretamente, a menos que utilizemos um dos 
métodos responsáveis pelo serviço.
É muito comum declarar métodos dos tipos getters e setters 
para retornar o valor de um atributo, ou modificá-los (até porque, 
geralmente as IDEs fornecem essa funcionalidade). Por padrão, para 
obter informações de atributos, com exceção do tipo boolean, deve-
-se prefixar o nome do atributo com a palavra get (obter), seguindo 
o padrão LowerCamelCase. Assim, quando o tipo for boolean o pre-
fixo é is. Veja alguns exemplos:
 • no atributo name do tipo String, seu método recebe 
getName();
 • no atributo birthday do tipo Date, seu método recebe 
getBirthday();
 • no atributo active do tipo boolean, seu método recebe 
isActive();
 • no atributo alive do tipo boolean, seu método recebe isAlive().
Para alterar atributos, sem exceções, devemos prefixar os 
atributos com a palavra set (pôr), seguindo o padrão LowerCamel-
Case. Veja alguns exemplos:
 • no atributo name do tipo String, seu método recebe setName();
 • no atributo birthday do tipo Date, seu método recebe 
setBirthday();
 • no atributo active do tipo boolean, seu método recebe 
setActive();
 • no atributo alive do tipo boolean, seu método recebe 
setAlive().
83
DICA
Observe que os nomes dos métodos e os atributos foram escritos em 
inglês, isso não é uma obrigatoriedade, mas possibilita uma leitura 
mais fácil do código, justamente pela utilização dos padrões da con-
venção de códigos e em virtude das palavras-chaves serem sempre 
em inglês.
Estruturas compostas homogêneas
As estruturas compostas homogêneas são aquelas que podem 
receber diversos valores do mesmo tipo. Os principais repre-
sentantes dessa estrutura são os vetores e as matrizes. Vamos 
conhecê-los.
Vetor
O vetor é um tipo de estrutura de dados composto por várias instân-
cias do mesmo tipo e o identificador somente diferencia seu índice, 
como endereçamento. Ou seja, nada mais é do que um tipo primitivo 
com profundidade. Veja um exemplo:
String nome[] = new String[3]; nome[0]=“José”;
nome[1]=“Paulo”;
nome[2]=“João”;
EXEMPLO
84
EXEMPLO
Observe que iniciamos a estrutura do vetor com os colchetes, 
após o nome da variável. Após isso, usamos o comando new, que 
é um comando que instancia o objeto string. Temos o valor 3 entre 
colchetes que significa 3 “variáveis” do tipo string, com o identifi-
cador nome[ ]. Os números entre os colchetes significam sua iden-
tificação numérica, que vai até dois. Além disso, temos três variáveis 
com os ids 0, 1 e 2, e essa identificação numérica, ou id, são as pro-
fundidades do vetor. No caso, o id 0 conta como variável, por isso, 
vai até o id 2.
É importante que você saiba o que significa:
Instância: é uma convenção da programação orientada a ob-
jetos, que cria instâncias ou cópias de objetos ou programas dentro 
do programa atual.
Atribuição: é uma característica das variáveis. Elas recebem 
valores predeterminados pelo(a) programador(a) ou por intermé-
dio de funções que captam valores dos usuários do programa. Abai-
xo, seguem alguns exemplos de atribuição em vetor.
 • Atribuição por valores predeterminados pelo programador: 
nome[0]=“Rolfi”;
 • Atribuição por valores que o usuário irá inserir:
nome[1]=javax.swing.JOptionPane.showMessageDialog(null, 
“Digite seu nome”);
 • Atribuição por variáveis ou por outro vetor: 
nome[0]=outronome;
nome[0]=nome[1];
85
EXEMPLO
Além disso:
Operação aritmética: é um conjunto de instruções que pro-
movem operações aritméticas em variáveis. Por exemplo:
float nota[]=new float[4]; 
float media; 
nota[0]=7.5f; 
nota[1]=10.0f; 
nota[2]=8.0f; 
nota[3]=10.0f;
media=(nota[0] + nota[1] + nota[2] + nota[3])/4;
Navegação: é utilizado para navegar no vetor, pode-se cha-
mar pelo id ou fazer um loop navegando por todos os ids. Nos co-
mandosapresentados a seguir, o vetor nome está sendo impresso, 
um a um, na tela. Veja:
 • Navegando pelo id: 
System.out.println(nome[0]);
 • Navegando em todo o vetor:
for(int contador=0; contador < nome.length; contador++)
{
System.out.println(nome[contador]);
}
86
O comando abaixo, que é o for-each, é um dos principais co-
mandos de navegação de objetos e estruturas de dados:
for(int aux: vetor)
{
System.out.println(aux);
}
Esse loop navega nas posições do vetor e passa seus valores, um a 
um, na variável aux.
Ordenação: é um conjunto de instruções que visa ordenar 
uma estrutura de dados, nesse caso, o vetor. Abaixo, segue um dos 
formatos mais tradicionais de ordenação de vetor.
1 for(int contadorL=0; contadorL< vetor.length ; 
contadorL++)
2 {
3 for(int contadorC=contadorL+1; contadorC< vetor.length; 
conta- dorC++)
4 {
5 if(vetor[contadorL]> vetor[contadorC])
6 {
 int aux= vetor[contadorL];
 vetor[contadorL]=vetor[contadorC];
 vetor[contadorC]=aux;
10 }
11 }
12 }
DICA
87
Esse algoritmo é o Método Bolha, ou Bubble Sort, um algorit-
mo de ordenação tradicional que busca o menor elemento da lista, 
posicionando ao topo de forma ordenada. Primeiramente, busca-se 
o menor valor, navegando no vetor através dos índices contadorL e 
contador. Ao encontrar um valor maior, faz-se a troca, “descendo” 
o valor maior e “subindo” o valor menor.
Por exemplo: valores 9, 0, -1 para os endereços 0, 1 e 2 do vetor.
Tabela 1 - Exemplo dos valores iniciais vetor em memória
Fonte: Editorial Digital Pages, 2019.
Primeiramente, o algoritmo verifica se o vetor na posição 0 é maior 
que o vetor na posição 1, ou seja, se 9 > 0. Nesse caso, é maior, então, troca-
-se o menor pelo maior através das navegações dos índices. Faz-se a pri-
meira troca de 9 por 0, usando a variável auxiliar, como nas linhas abaixo:
7 int aux=vetor[contadorL];
8 vetor[contadorL]=vetor[contadorC];
9 vetor[contadorC]=aux;
O aux recebe o maior valor, que é o valor 9, pois o contadorL 
nesse primeiro momento é 0, e o vetor na posição 0 recebe o valor 
de vetor na posição 1, que é o valor de contadorC, recebendo, assim, 
o valor 0. O vetor na posição 1 recebe o valor de aux.
Tabela 2 - Exemplo da primeira troca no vetor
Fonte: Editorial Digital Pages, 2019.
Continuando o loop, o contadorL na posição 0 verifica se exis-
te um outro valor menor dentro do vetor, encontra na posição 2 o 
valor -1, e faz a troca pelo valor menor. Logo, todos os valores do 
vetor são percorridos, como na tabela 3.
Valor 9 0 -1
Índice vetor[0] vetor[1] vetor[2]
Valor 0 9 -1
Índice vetor[0] vetor[1] vetor[2]
88
Tabela 3 - Exemplo da Segunda Troca no Vetor
Fonte: Editorial Digital Pages, 2019.
Após o primeiro item (o índice 0) possuir o menor valor do 
vetor, a segunda etapa é passar para verificar se o índice 1 possui o 
menor valor. Na primeira varredura entre índice 1 com o valor de 9, 
verifica-se se o próximo índice, o 2, é maior com o valor de 0. Nesse 
caso, faz-se a troca, obtendo-se o resultado exibido na tabela 4.
Tabela 4 - Exemplo da segunda troca no vetor
Fonte: Editorial Digital Pages, 2019.
Como não existem valores para serem verificados, finaliza-se 
a ordenação do vetor.
Aplicação: um vetor pode ser usado como lista ou estruturas que 
envolvam listas, como lista de compras, lista de clientes, lista de CEPs etc.
Para que você veja, na prática, o que estamos tratando, abaixo 
temos um exemplo do código do vetor estruturado.
No código a seguir, temos um exemplo de vetor em formato estru-
turado, ou seja, digitado diretamente da função main. Esse comando 
cria um vetor na linha 9 com dados predeterminados e na linha 11 ele 
ordena esses valores de forma crescente. Após a ordenação, tem-se 
a impressão na linha 20.
Valor -1 9 0
Índice vetor[0] vetor[1] vetor[2]
Valor -1 0 9
Índice vetor[0] vetor[1] vetor[2]
EXEMPLO
89
Figura 15 - Exemplo de vetor em formato estruturado
Fonte: Editorial Digital Pages, 2019.
Vetor orientado a objetos
Os vetores orientados a objetos são vetores que, tradicionalmen-
te, podem ser criados em qualquer local da classe. Porém, quando 
abordamos o paradigma de orientação a objetos dentro do conceito 
de vetor, temos que criar duas classes, uma será o tads propriamen-
te dito, a classe vetorOO, que é chamado como estrutura de dados 
dentro da classe Prj_VetorOO.
Já empregando os conceitos de orientação a objetos dentro da 
classe VetorOO, observamos o tratamento de dados através do uso 
de métodos ou funções, diferente do exemplo acima, em que todo o 
tratamento está dentro da função main.
90
Figura 16 - Exemplo do tratamento de dados através do uso de métodos ou funções
Fonte: Editorial Digital Pages, 2019.
Como você pode perceber, a classe Prj_VetorOO possui a instan-
ciação da classe VetorOO em vet e, dentro da própria vet, temos a função 
set, valor que insere valores nas posições determinadas da função.
Também para inserir valores usamos o inserir que, através de 
uma sequência estipulada na linha 39, apenas recebe os dados e ve-
rifica, de acordo com o número de inserções, se poderá ser inserido.
Além disso, o construtor da linha 26 inicia-se recebendo um 
valor para aprofundar o vetor no valor desejado.
As funções getValor e setValor são funções de captura e envio 
de dados em qualquer estrutura. Assim, o getSize retorna a quan-
tidade de itens inseridos, enquanto a getMax retorna a capacidade 
máxima de itens que podem ser inseridos. O remover retira itens do 
vetor diminuindo o getSize e o método sort ordena os itens do vetor.
Dessa maneira, quando tratamos de orientação a objetos, 
nesse caso, temos todos os comportamentos dos dados dentro de 
um vetor, que, no caso, seria a linha 5 private int vetor, que cria o ve-
tor como private para que nenhuma classe externa possa acessá-la 
diretamente, somente a partir dos métodos citados anteriormente.
91
Figura 17 - Exemplo de comportamentos dos dados dentro de um vetor
Fonte: Editorial Digital Pages, 2019.
92
Matriz
Matriz é uma estrutura homogênea de dados que permite organizar 
os dados em formato de linhas e colunas, e sua indexação é pelo en-
dereço de linhas e colunas, semelhante à estrutura de um vetor, mas 
com formato bidimensional, podendo assumir mais de duas dimen-
sões. Dependendo da linguagem de programação podem assumir 
até 17 dimensões, por exemplo:
String nomes[][]=new String[2][3]; nomes[0][0]=”Rolfi”;
nomes[0][1]=”Ana”;
nomes[0][2]=”Maria”;
nomes[1][0]=”João”;
nomes[1][1]=”Pedro”;
nomes[1][2]=”Paula”;
Em estrutura de memória, ficaria ilustrado da seguinte forma:
Tabela 5 - Exemplo em Memória de Matriz
Fonte: Editorial Digital Pages, 2019.
Observe que as colunas são de, no máximo, três itens. Conta-
-se o 0 e temos 0, 1, 2, totalizando três colunas. Nas linhas, temos 
dois de tamanho. Conta-se o 0 e temos 0 e 1, como no vetor.
Dito isto, vamos entender alguns temas relacionados às matrizes.
Atribuição: as atribuições em matrizes funcionam da seguin-
te forma: 
nomes[índice da linha][índice da coluna]=valor do tipo 
da coluna.
Linhas
Colunas
0
"Rolfi"
"João"
1
"Ana"
"Pedro"
2
"Maria"
"Paula"
93
Por exemplo:
nomes[0][0]=”Rolfi”;
Operação aritmética com matriz: as operações aritméticas, 
assim como nas variáveis e vetores, também funcionam da mesma 
forma na matriz. Deve-se primeiramente fazer referência da posi-
ção que se deseja trabalhar e submetê-la às operações matemáticas.
Por exemplo:
float notas[][]=new float[2][2]; notas[0][0]=10f;
 notas[0][1]=5.5f;
 notas[1][0]=6.0f;
 notas[0][1]=8.0f;
float medias =(notas[0][0] + notas[0][1] + notas[1][0] + no-
tas[1][1])/notas.length;
Navegação: para navegar na matriz, pode-se chamar pelo id da 
linha e da coluna ou fazer um loop, navegando por todos os ids. Neste 
comando, a matriz nomes está sendo impressa, um a um, na tela.
 • Navegando pelo id: 
System.out.println(nomes[0][0]);
 • Navegando em toda a matriz, porém, deve ser feito um laço 
para a linha e coluna:
for(int contadorL=0;contadorL < 2; contadorL++) {
 for(int contadorC=0; contadorC < 3; contadorC++) {
 System.out.println( nomes[ contadorL ] [ contadorC ] );
 }
}
Ou pelo comando abaixo, que é o for-each (um dos principais 
comandos de navegação de objetos e estruturas de dados):
for(String linha[]: nomes) {
 for(String coluna: linha) {
 System.out.println(coluna);
 }
}
94
Esse loop navega nas posições da matriz, passando seus va-
lores, um a um, na variável coluna, que recebe, da variável linha, 
a linha com os valores da matriz nomes. Assim, para cada dimen-
são, deve-se ter um loop. Nesse caso, temos duas dimensões, então, 
usa-se dois loops.
Estruturas comportamentais heterogêneas
As estruturas heterogêneas consistem em estruturas que podem re-
ceber diversos tipos primitivos com um objetivo em comum. Nesse 
aspecto, temos os conceitos de registro e campo.
Por um lado, o campo é um tipo primitivo com identificador 
que possui uma característica única que, quando linkada a outros 
campos, produzem um significado ou conjunto de informações. Já o 
registro é uma informação de um determinado objeto ou entidade 
que possui diversos campos.
Na maioria das literaturas, usa-se o C para explicar a es-
trutura heterogênea, pois, por não ser orientado a objetos, conse-
gue-se distinguir nitidamente a estrutura heterogênea. Temos o 
seguinte código:
struct Estudante { int ID;
char nome[50]; int idade;
float media;
};
Em que cada estudante adicionado seria um registro 
em memória.
Instanciação
Tendo-se o C, uma struct ou estrutura, a instanciação corresponde às 
estruturas de dados heterogêneos, que possuem diversos atributos 
95
(variáveis primitivas) com identificador e tipo primitivo. Logo, sua 
instanciação ou cópia, é como no exemplo apresentado abaixo.
struct Estudante est1;
Atribuição
Em structs, temos dois tipos de atribuição, são eles:
 • struct Estudante est1 = {1,”João”,23,10};
ou
 • struct Estudante est2;
est2.ID =2; 
strcpy(est2.nome , “Pedro”); 
est2.idade=30; 
est2.media=7.5;
As operações, impressões e acessos são através do ponto, 
como foi apresentado no exemplo anterior.
Em Java, temos diversas formas de trabalhar uma estrutura 
heterogênea que difere do C. Lembre-se que uma estrutura consiste 
em uma classe ou objeto. E, além disso, que um objeto é a principal 
entidade de uma estrutura de programação, orientada a objetos que 
possuem propriedades e ações,como também podem assumir ca-
racterísticas de uma situação real, uma regra de negócio ou entidade 
em geral. Veja o exemplo:
public class Estudante {
 int ID; 
String nome; 
int idade; 
float media;
}
96
public class Exemplo {
 public static void main(String []args)
{
 Estudante est1=new Estudante(); 
 est1.ID = 1;
 }
}
Observe que, no exemplo acima, o código está muito próximo 
da struct. No caso do Java, também funciona, porém, nos conceitos 
de orientação a objetos, está fora de padrão e convenção.
No exemplo abaixo, segue o código no formato ideal para 
orientação a objeto, pois usa-se o conceito de encapsulamento, que 
é o uso das funções sets e gets para gerenciar as variáveis ou atri-
butos da estrutura. Para alterar valores, usa-se o set e o nome da 
variável. Veja:
private int idade;
public void setIdade(int aux) { 
 this.idade = aux;
}
Toda variável, ou tipo primitivo, dentro de um objeto que 
será aproveitado em outras classes deve ser private. Mas, caso não 
tenha uma palavra reservada como public, o compilador entende 
como public por default.
Observe que, nesse momento, o nome da função assumiu o 
nome da variável, acrescentando a palavra set como convenção de 
alteração. Assim, para captar valores, usa-se o get, como na função 
a seguir: 
public int getIdade(){
return this.idade;
}
97
Abaixo, a classe exemplo seria o formato em que a instan-
ciação está correta dentro dos padrões OO. Na linha 6, atribui-se o 
valor 1 para a variável ID, através do método setID; na linha 8, veri-
fica-se o valor atribuído no ID através do método getID. Veja:
Figura 18 - Classe Exemplo
Fonte: Editorial Digital Pages, 2019.
Instanciação: diferentemente do C, o Java é orientado a obje-
tos. Por isso, tudo que é desenvolvido em Java e que tenha interação 
com dados primitivos, geralmente, é um objeto.
No código abaixo, tem-se a classe estudante, que é instan-
ciada através da palavra new:
Estudante est=new Estudante();
Tipos abstratos de dados
Os tipos abstratos de dados (TADs) são estruturas que correspon-
dem ao funcionamento de estruturas do mundo real, como pilha, 
fila, lista, árvore, grafos ou qualquer estrutura que organize, de for-
ma singular, uma coleção de dados. De acordo com Lafore (2004):
o significado de Tipo Abstrato de Dados é mais 
estendido quando aplicado a estruturas de 
dados como pilhas e filas. Como em qualquer 
classe, significa que os dados e as operações 
podem ser executados neles, mas, neste con-
texto, até os fundamentos de como os dados 
são armazenados tornam-se invisíveis para o 
usuário (LAFORE, 2004, p. 187).
98
Em algumas situações, os TADs podem ser confundidos com 
estruturas heterogêneas. Porém, o objetivo deles é possuir em si 
uma coleção de dados ou objetos, além de se responsabilizar com a 
sua organização e tratamento, como: inserção, deleção, ordenação, 
busca e endereçamento.
Lembre-se: um TADs em si gerencia sua própria coleção. 
Em termos de códigos, em Java ou em qualquer outra 
linguagem de programação, o TADs não envolve comandos 
complexos e, sim, uma lógica bem definida que faz com que os 
dados sejam organizados dependendo de sua estrutura. Veja 
os comandos:
Lista: comporta-se como uma lista do mundo real, que rece-
be valores e remove em sequência ou por posições.
Pilha: comporta-se como uma organização de pilha, como 
em pilha de livros, em que o primeiro valor que se insere é o último 
a ser removido.
Fila: comporta-se como uma organização de fila, como uma 
fila de banco, em que o primeiro valor que entra é o primeiro valor 
que será removido.
Tipos de armazenamento
Os tipos de armazenamento em TADs podem variar entre di-
nâmico e estático. O estático possui capacidade limitada, ou 
estática, de posições. Já o armazenamento dinâmico possui 
capacidade de alocação por demanda, ou seja, quando existe a 
necessidade de inserir algum valor, ele se adapta a uma nova 
quantidade de valores.
DICA
99
Na capacidade estática, tem-se a vantagem de saber a quantidade 
de valores. Porém, não podendo ser alterada sua capacidade, faz 
com que seja um formato de armazenamento muito específico, de-
pendendo da regra.
Coleções
Os TADs são muito utilizados em diversas linguagens, porém, em 
Java, existem algumas bibliotecas prontas para os principais TADs, 
dentro de orientação a objetos, chamadas de pacotes.
O pacote que contém alguns dos principais TADs é o java.util, 
que possui o collection frameworks, classes e interfaces que pos-
suem, prontos, os TADs que não necessariamente precisariam ser 
reescritos, apenas instanciados para uso. As collections são divididas 
em conjuntos, listas e mapas.
Figura 19- As interfaces da collection
Fonte: Adaptada de Oracle, 2019. Acesso em: 20 maio 2022.
CURIOSIDADE
100
As listas trabalham em formatos sequenciais de inserção e 
remoção. Por serem sequenciais, a busca de dados torna-se mais 
lenta. Além disso, os conjuntos trabalham em formatos algorít-
micos para inserção, tornando mais lenta a inserção. Assim, a 
busca, a navegação e a remoção, porém, tornam-se mais velozes. 
Por fim, os mapas trabalham organizando os dados juntamente 
com seus índices, tornando mais complexa a programação. Po-
rém, sua busca é veloz. 
Na figura 20, observa-se as classes que podem ser instancia-
das para estrutura de dados das collections, dos grandes eixos list e 
queue (“sequência”) e set (“conjunto”). Veja.
Figura 20 - Classes collections
Fonte: Editorial Digital Pages, 2020.
101
Caro(a) aluno(a), chegamos ao final desta etapade estudos. Nesse 
material estudamos sobre a estrutura de classes. Além disso, apren-
demos que atributos e métodos devem estar dentro das classes e que 
atributos e métodos, com o modificador static, podem ser acessados 
sem a instanciação de um objeto. Isso porque eles são atributos e 
métodos da classe e não dos objetos. Além disso, se o atributo static 
for alterado, isso é refletido em todos os objetos instanciados.
Aprendemos também que podemos criar métodos com o mesmo 
nome, mas que possuam assinaturas distintas. Essas assinaturas são 
compostas pelo nome e atributos do método e devemos sempre res-
peitar a ordem dos atributos, passando os tipos de dados corretamente.
Também discutimos o fato de que os construtores são métodos es-
peciais que não precisam ser declarados, não possuem tipo de re-
torno e devem conter o mesmo nome que a classe. Além disso, você 
pôde perceber que não é muito viável utilizar métodos construtores 
com modificadores private, protected ou default, já que o primeiro 
não é acessível por nenhuma outra classe, e o segundo é apenas por 
classes do mesmo pacote, ou através de herança.
Aprendemos que referência e instanciação são coisas distintas. 
Enquanto a referência é apenas a declaração que poderá conter um 
objeto referenciado à memória, a instanciação é a criação do ob-
jeto. Para podermos fazer uso do objeto, ele deverá ser atribuído a 
uma referência.
Além disso, vimos a abstração das informações contidas em um 
objeto e a importância da omissão dessas informações a quaisquer 
classes, tornando o acesso a elas possíveis apenas através de méto-
dos específicos na própria classe que os contém.
Até aqui estudamos as estruturas compostas homogêneas, co-
nhecidas como vetores e matrizes, além das estruturas compostas 
heterogêneas, conhecidas como structs ou objetos dependendo da 
linguagem de programação.
SINTETIZANDO
102
Antes de finalizarmos o nosso material, analisamos os conceitos 
de TADs, que são tipos abstratos de dados, ou seja, uma estrutura 
que se comporta com características e padrões do mundo real para 
tratamento de dados, como lista, pilha e fila. Vimos esses conceitos 
dentro da linguagem Java, em que, na própria linguagem, foi pos-
sível visualizar uma API que contém uma collection framework (que 
possui diversas estruturas prontas para uso), fazendo com que o 
desenvolvedor foque na regra de negócio.
Lembre-se de estudar antes e depois da sua aula, aproveite o mo-
mento com o(a) docente para tirar todas as suas dúvidas.
Até breve!
UN
ID
AD
E
3
Objetivos
 ◼ Aprender conceitos de herança e sua utilização.
 ◼ Entender como se dá a criação e o uso da hierarquia de classes. 
 ◼ Aprender a criar e utilizar classes abstratas e interfaces.
 ◼ Aprender sobre os conceitos dos relacionamentos entre as 
classes e os tipos existentes.
104
Introdução
Olá, tudo bem? A partir de agora veremos o conceito de he-
rança e, além disso, vamos entender como são criadas as hierarquias 
de classes. Você também aprenderá sobre como utilizar as classes 
abstratas e as interfaces. E, antes de finalizarmos esse material, ve-
remos os relacionamentos entre as classes e os tipos existentes. 
Dito isto, convido você, aluno(a) EAD, a conhecer os temas 
citados de forma descomplicada e muito intuitiva conforme abor-
daremos neste material. Boa leitura e bons estudos!
105
Herança
Caro(a) aluno(a), inicialmente é preciso que você entenda que a reu-
tilização de classes por meio da herança é uma das características da 
programação orientada a objetos. O mecanismo de herança permite a 
reutilização dos atributos e métodos de uma classe em outra, assim, 
mesmo que não seja declarado explicitamente, todas as classes em 
Java são dispostas de forma hierárquica. Dessa maneira, classes her-
dadas são chamadas de superclasse e possuem atributos e métodos 
mais generalizados, já classes herdeiras são chamadas de subclasse e 
possuem atributos e métodos mais específicos. Além disso, podemos 
encontrar outras nomenclaturas para esses termos, assim, super-
classes podem ser referidas como classes pai ou classes mãe e, ana-
logamente, subclasses também podem ser chamadas de classes filha.
Utilização de herança
Para utilizar a herança, a subclasse deve conter a palavra-chave 
“extends”, depois da declaração de seu nome, seguido do título da 
superclasse, por exemplo: 
public class ClasseHerdeira extends ClasseHerdada {}. 
Dessa maneira, a empregabilidade da herança se dá ao fato de po-
der dizer “é um”, na qual um objeto “é um” tipo de outro objeto. Dito isso, 
analisaremos o diagrama de classes para entendermos melhor, veja.
Diagrama 1: Diagrama de Classes sem Uso de Herança
Fonte: Editoria Digital Pages (2020).
106
Observando o diagrama, verificamos que as classes Alu-
no e Professor são duas entidades distintas, embora ambas 
possuam alguns atributos em comum, como nome, dataNas-
cimento, cpf, endereco e telefone. Dessa forma, de acordo com 
o diagrama anterior, precisamos criar duas classes. Observe o 
exemplo a seguir. 
Figura 1 - Declaração de classes sem herança
Fonte: Editoria Digital Pages (2020).
Note que, na implementação das classes, ambas compar-
tilham atributos em comum. Diante desse cenário, a aplicação de 
herança para as duas classes é possível, uma vez que todo profes-
sor e aluno são pessoas. Nesse caso, precisamos criar uma terceira 
classe para utilizarmos o conceito de herança; uma classe que seja 
genérica e contenha atributos e métodos úteis às outras duas classes 
filhas. Assim, criaremos uma repartição denominada Pessoa e ela 
conterá os atributos que são comuns entre as subclasses menciona-
das, veja abaixo.
import java.util.Date;
import java.util.List;
public class: Aluno {
 private String nome;
 private Date datanascimento;
 private String cpg;
 private String endereco;
 private String telefone;
 private List(string) cursos;
 private double notas:[];
 public( double : obternota(){
 int qtdnotas = this.notas.length;
 double totalnotas = 0;
 for( int i=o; |< qtdnotas| i++) {
 totalnotas == this.notas[]i];
 }
 return totalNotas();
 }
 // 
}
import java.util.Date;
import java.util.List;
public class: Aluno {
 private String nome;
 private Date datanascimento;
 private String cpg;
 private String endereco;
 private String telefone;
 private List(string) cursos;
 private double notas:[];
 public( double : obterSalario(){
 return this.salario;
 }
 // 
}
107
Diagrama 2 - Diagrama de Classe com Uso de Herança
Fonte: Editorial Digital Pages (2022).
No diagrama apresentado, podemos observar a super-
classe denominada Pessoa e suas subclasses Aluno e Professor. 
Observe que Aluno e Professor possuem uma ligação com a su-
perclasse Pessoa por meio de uma seta. No diagrama, isso indi-
ca que as subclasses Aluno e Professor herdarão os atributos da 
superclasse Pessoa.
Nesse sentido, precisamos criar três classes para simbolizar 
corretamente o diagrama apresentado. Assim, Aluno e Professor se-
rão subclasses que se estenderão à Pessoa, veja.
108
Figura 2 - Declaração de classes com herança
Fonte: Editorial Digital Pages (2020).
Note que a superclasse Pessoa é declarada normalmente, 
apesar de poder ser apresentada como classe abstrata. Já as classes 
filhas (Aluno e Professor) possuem a palavra-chave extends, segui-
da do nome da superclasse. Por meio da utilização da palavra-cha-
ve, comunicamos que os atributos e os métodos contidos em Pessoa 
também estão contidos em Aluno e Professor e poderão ser aces-
sados normalmente, desde que declarados como public. Já o termo 
protected permite acesso por meio da herança, ou default, se estive-
rem no mesmo pacote.
109
DICA
Um detalhe importante é que os atributos das três classes 
estão declarados com o modificador de acesso private. Isso indica 
que eles só poderão ser acessados pela própria classe e que, mesmo 
diante da herança, os atributos dePessoa não estarão acessíveis di-
retamente por Aluno e Professor. Nesse sentido, os objetos possui-
rão os atributos que herdaram e poderão acessá-los por meio dos 
métodos getters e setters, ou outros meios que possibilitem a ma-
nipulação dos dados. Caso sua intenção, seja de que as subclasses 
possuam acesso direto aos atributos e métodos da classe mãe, eles 
devem ser declarados como protected ou public. 
Os métodos getters e setters não foram declarados para esse exemplo 
como forma de simplificação, mas saiba que eles precisam ser exter-
nados, caso deseje realizar o encapsulamento de dados. Lembre-se 
que os métodos getters e setters são utilizados para essa finalidade.
Outro ponto importante é que a programação Java só permite 
herança simples entre as classes, ou seja, subclasses só podem her-
dar uma única superclasse. Já uma superclasse pode ser herdada por 
inúmeras outras subclasses.
Por fim, quando não é definido uma herança por meio da pala-
vra-chave extends, indiretamente a classe herdará a classe Object. Isso 
porque a classe Object é uma classe genérica que contém o construtor 
default “public Object()” e onze métodos, cujos mais comumente utili-
zados são os getClass(), equals(), hash-Code() e toString().
Palavra-chave super
Para acessarmos os atributos e métodos do próprio objeto, fazemos 
uso da palavra-chave this. Mas, se quisermos acessar os atributos 
do objeto herdado, podemos fazer uso da palavra-chave super. Pen-
sando nisso, a palavra-chave super deve ser utilizada para acessar 
110
DICA
os atributos e métodos da superclasse, desde que eles não tenham 
sido declarados como modificadores de acesso private.
Assim, o uso da palavra-chave super segue algumas regras de 
utilização diante da subclasse. Veja:
 • para chamar o construtor da superclasse, basta declarar a pala-
vra-chave super, seguido dos argumentos dentro dos parênte-
ses, caso o construtor da superclasse possua. Exemplo: super();
 • a chamada do construtor da superclasse só poderá ser feita dentro de 
construtores da subclasse e deverá ser a primeira linha do construtor;
 • caso haja hierarquia de classes, por exemplo, A herda B que 
herda C, e a chamada de construtor deverá ser em cascata, ou 
seja, A chama construtor da classe B que chama o construtor 
da classe C;
 • o construtor padrão da superclasse será chamado automati-
camente caso não seja feito uma declaração explícita, ou seja, 
mesmo que não declarado, o construtor da subclasse chamará 
o construtor da superclasse;
 • desde que o modificador de acesso permita, métodos exis-
tentes na superclasse podem ser executados fazendo uso 
da palavra-chave super, seguido do ponto e o nome do 
método com seus parâmetros caso existam. Exemplo: su-
per.somar(int numero1, int numero2);. O mesmo acontece 
com os atributos.
O uso da palavra-chave super não é obrigatório, desde que ambas 
as classes não possuam métodos ou atributos com o mesmo nome. 
Mas, caso essa duplicidade ocorra e o método não seja sobrescrito, a 
não utilização do super desencadeará a execução do método da sub-
classe, enquanto o método da superclasse será ignorado. 
111
DICA
Como essa condição não é usual, é difícil encontrar có-
digos que façam uso da palavra-chave super. Dessa forma, 
quando não há “duplicidade” na subclasse, a palavra-cha-
ve this pode ser utilizada para chamar métodos e atributos 
da superclasse (exceto para o construtor da superclasse, que 
sempre será super). Isso ocorre devido ao sistema Java, que 
“procura” métodos e atributos automaticamente, de forma 
hierárquica, começando pela subclasse até a última super-
classe. Assim, caso o atributo ou método não seja encontra-
do em nenhuma das classes da hierarquia, haverá um erro de 
compilação do projeto.
Criação e uso de hierarquia de classes
Exceto a classe Object, todas as classes em Java são subclasses 
e, mesmo quando não há uma declaração explícita de heran-
ça, a classe herda a classe Object. Por esse motivo, Object é a 
classe mais genérica em Java, ou seja, é superclasse de todas 
as demais. 
Nesse seguimento, a hierarquia permite que uma subclas-
se se estenda à apenas uma superclasse, enquanto uma classe 
mãe pode se estender a inúmeras outras classes filha. Dessa ma-
neira, se estruturarmos um sistema de empresa, podemos ates-
tar essa estrutura. 
Lembre-se que a hierarquia de classes possibilita a criação de ca-
tegorias com funções mais comuns, assim como permite a criação 
de classes mais especializadas que herdem essas características e 
funcionalidades específicas. 
112
Diagrama 3 - Diagrama de Classe: Exemplo de Hierarquia
 Fonte: Editorial Digital Pages (2020).
O diagrama apresentado é um exemplo de representação de 
herança e associação, que demonstra as hierarquias das classes, des-
de a mais especializada até a mais genérica. Observe que as classes 
interligadas pela seta indicam que o objeto herda atributos e méto-
dos de forma hierárquica. E, como sabemos, as subclasses mais espe-
cializadas possuem atributos e métodos mais específicos do objeto, 
enquanto as superclasses são genéricas e possuem atributos e mé-
todos gerais, que servem às subclasses. Por fim, as classes que estão 
interligadas pela linha indicam que o objeto está associado ao outro 
113
e apontam que um objeto contém outro. Essa associação é um rela-
cionamento, mas não indica hierarquia. Um exemplo é que a classe 
Colaborador possui todos os atributos e métodos contidos em Pessoa 
Fisica, Pessoa e Object.
À vista disso, é preciso apontar que a classe Object contém ape-
nas métodos sem atributos. Esses métodos são genéricos e podem ser 
chamados ou sobrescritos por qualquer classe. Assim, com base no 
diagrama, a classe Fornecedor pode chamar o método clone da clas-
se Object, já que a classe Fornecedor herda PessoaJuridica, que herda 
Pessoa que, por sua vez, herda Object. Por esse motivo, como mencio-
nado, todas as classes possuem os métodos contidos em Object.
Classes e subclasses
Não há como fugir da hierarquia de classes, já que todas elas her-
dam de Object. Contudo, podemos limitar que uma classe não seja 
superclasse de uma classe filha. Essa limitação é feita pelo uso da 
palavra-chave final após a palavra-chave class. 
Isso é feito geralmente por razões de segurança 
e eficiência. Muitas das classes da biblioteca pa-
drão do Java são finais, por exemplo java.lang.
System e java.lang.String. Todos os métodos [...] 
são implicitamente finais.” (BEDER, 2014, p. 66). 
Portanto, classes declaradas como final não podem ser her-
dadas por outras.
Classes abstratas e interfaces
Planejar um sistema é uma tarefa árdua e deve ser feita de maneira 
minuciosa por um engenheiro de software, já que determinar quais 
classes serão utilizadas e identificar suas relações de herança é uma 
das partes mais trabalhosas do processo. Lembre-se que a determi-
nação das classes que serão exclusivamente superclasses e que não 
serão utilizadas para serem instâncias pode influenciar em como o 
software será desenvolvido.
114
Por esse motivo, classes determinadas exclusivamente como 
superclasses podem e devem ser declaradas como abstratas. Essas 
servem como um guia para a programação, contendo apenas atribu-
tos e métodos que devem ser implementados nas subclasses. Assim, 
além das classes abstratas, Java permite a criação de interfaces que 
contenham métodos sem corpo. Dessa maneira, diferentemente das 
hierarquias, uma classe Java pode implementar várias interfaces.
Classes abstratas
Classes abstratas, além de não poderem ser instanciadas, possibi-
litam a criação de assinaturas de métodos, declarados como abs-
tract. Elas não possuirão chaves com escopo, devem ser finalizadas 
com ponto e vírgula e não podem ser declaradas como private. Além 
disso, elas obrigarão as subclasses a implementarem o método, de-
vendo ou não o sobrescrever, fazendo uso da annotation @Override. 
A declaração de classes e métodos abstratos também deve possuir 
modificadores abstract após o modificador de acesso daclasse ou 
método. Para que você entenda o que estamos explicando, a seguir 
veremos as diferenças em suas declarações.
Primeiro, vamos aos exemplos das declarações de classes 
normais, sem uso do abstract:
 public class Combustivel { 
 private int litrosDisponiveis;
 public void abastecerReservatorio(int litros) {
 this.litrosDisponiveis += litros;
 }
 public int getLitrosDisponiveis(){
 return this.litrosDisponiveis;
 }
 }
 public class Etanol extends Combustivel {
115
 public void printLitrosDisponiveis() { 
System.out.println(getLitrosDisponiveis() + “ Litros de 
Etanol”);
 }
 }
 public class Gasolina extends Combustivel {
 public void printLitrosDisponiveis() { 
 System.out.println(getLitrosDisponiveis() + “ Litros de 
Gasolina”);
 }
 }
Note que as classes Etanol e Gasolina se estendem à classe 
Combustível, e que ela não possui nenhum método abstrato. Assim, 
se executarmos o código com as três classes declaradas dessa ma-
neira, ambas poderão ser instanciadas, todavia, como a classe Com-
bustivel não deve ser um objeto e sim uma superclasse, ela poderá 
ser declarada como abstract, além de conter uma assinatura abstrata 
para o método printLitrosDisponiveis, presente nas duas subclas-
ses. Veja a seguir.
public abstract class Combustivel { 
 private int litrosDisponiveis;
 public void abastecerReservatorio(int litros) {
 this.litrosDisponiveis += litros;
 }
 public int getLitrosDisponiveis(){
 return this.litrosDisponiveis;
 }
 public abstract void printLitrosDisponiveis();
}
116
Observe, ainda, que a classe Combustivel possui o modifi-
cador abstract, impossibilitando que a classe seja instanciada, mas 
permitindo-a conter métodos abstratos, como o caso do método 
printLitrosDisponiveis, finalizado com ponto e vírgula e sem esco-
po, diferentemente de um método comum. Dessa maneira, teremos:
public class Etanol extends Combustivel {
@Override
public void printLitrosDisponiveis() { System.out.println(-
getLitrosDisponiveis() + “ Litros de Etanol”);
}
}
public class Gasolina extends Combustivel { @Override
public void printLitrosDisponiveis() { System.out.println(-
getLitrosDisponiveis() + “ Litros de Gasolina”);
}
}
Observe também que as classes Etanol e Gasolina possuem, 
obrigatoriamente, o método printLitrosDisponiveis, que está decla-
rado como abstract na classe Combustível.
Nesse sentido, uma informação importante sobre as classes 
abstratas é que seus construtores e atributos não podem ser decla-
rados como abstract. Mesmo que a classe abstrata não possa ser ins-
tanciada, a subclasse pode chamar o construtor da classe mãe para 
inicializar atributos, ou executar métodos normalmente, como é 
feito para casos comuns.
Por último, a diferença da declaração de um método abstrato 
ou não é que o método declarado como abstrato deve ser implemen-
tado (escrito) pela subclasse, enquanto os métodos normais devem 
ser herdados pela subclasse. Ainda assim, pode haver hierarquia de 
classes abstratas, assim como em classes normais. Todavia, apenas 
a classe que não for abstrata deverá implementar os métodos.
117
Interfaces
Uma classe em Java não pode estender (herdar) duas ou mais clas-
ses, o que limita as implementações funcionais de alguns objetos. 
Contudo, é possível executar em uma classe, seja abstrata ou não, 
diversas interfaces que contenham assinaturas de métodos.
Assim como uma classe abstrata, uma interface não pode 
ser instanciada, e todos os seus métodos devem ser implicitamente 
abstract e public. Além disso, se houverem campos, eles serão con-
siderados static e final, devendo ser inicializados na sua declaração 
(SANTOS, 2011).
Se uma classe for declarada como abstrata, sem variáveis e 
com apenas métodos abstratos e/ou constantes, o ideal é transfor-
má-la em interface. Lembre-se que interfaces não podem ser ins-
tanciadas, assim como as classes abstratas, e possuem seus métodos 
com modificadores de acesso public e modificadores abstract, de for-
ma implícita, dispensando declarações. Embora não seja possível de-
clarar atributos nas interfaces, é possível declaração de constantes.
Embora Java não permita herança múltipla entre as classes, 
isso não ocorre com as interfaces, ou seja, é possível uma interfa-
ce estender diversas outras. Da mesma forma, uma classe abstrata 
pode implementar interfaces, porém apenas a próxima subclasse 
mais especializada e não abstrata da hierarquia implementará os 
métodos dela.
Assim, veremos como é a usabilidade de interfaces: 
public interface AtivarDesativar {
 void ativar(); 
 void desativar();
}
Primeiro, criamos uma interface que ativará ou desativará 
alguma coisa em nosso sistema. Essa “coisa” pode ser um objeto 
que nos faça sentido utilizar ou eliminar. Assim, geralmente, a ati-
vação ou desativação de um objeto é utilizada em banco de dados 
para a exclusão lógica de um registro.
118
DICA
public interface VivoMorto {
 void vivo(); 
 void morto();
}
Depois, criamos uma outra interface como exemplo, que ser-
ve para “definir” se um ser está vivo ou morto.
public interface CalcularIdade {
 int calcularIdade();
}
Por último, uma interface será utilizada para calcular a idade 
de algo ou de alguém.
Note que, em todas as interfaces, sua composição é iniciada pelo 
modificador de acesso public, seguido da palavra-chave interface e 
nome. Assim, no escopo da interface temos métodos com assinatura 
e tipo de retorno, embora pudéssemos ter declarado constantes no 
escopo da interface. Lembre-se que todo método declarado sempre 
será public e abstract, e as constantes sempre serão static e final (fa-
tor que determina que o atributo é uma constante).
Agora, veremos como fazer a implementação de interfaces 
em classes: 
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class Pessoa implements AtivarDesativar, VivoMorto, 
CalcularIdade {
119
private String nome; 
private boolean ativo; 
private boolean vivo; 
private Date nascimento; 
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
} 
public Date getNascimento() {
return nascimento;
}
public void setNascimento(Date nascimento) {
this.nascimento = nascimento;
}
public boolean isAtivo() {
return ativo;
}
public boolean isVivo() {
return vivo;
}
@Override
public int calcularIdade() {
GregorianCalendar hoje = new GregorianCalendar();
GregorianCalendar nascimento = new GregorianCalendar();
nascimento.setTime(this.nascimento);
120
int anoAtual = hoje.get(Calendar.YEAR);
int anoNascimento = nascimento.get(Calendar.YEAR); 
return new Integer(anoAtual-anoNascimento);
}
@Override
public void vivo() {
this.vivo = true;
}
@Override
public void morto() {
this.vivo = false;
}
@Override
public void ativar() {
this.ativo = true;
}
@Override
public void desativar() {
this.vivo = false;
}
}
Perceba que, na declaração da classe possuímos a palavra-
-chave implements, seguida dos nomes das interfaces. E, no de-
correr do escopo da classe, possuímos os métodos existentes nas 
interfaces e, acima de cada método, a annotation @Override, à qual 
se refere ao método sobrescrito nessa classe.
Agora, veja a diferença entre classes abstratas e interfaces.
121
Quadro 1 - Diferenças entre classe abstrata e interface
 Fonte: Editorial Digital Pages (2020).
Relacionamento entre classes
Além da ligação entre heranças, há mais três tipos de rela-
cionamento entre classes, classificados como: associação, 
composição e agregação. Esses relacionamentos não indicam 
hierarquia, uma vez que, nesse caso, podemos dizer que um 
objeto “tem um” outro objeto, mas não que um objeto “é um” 
outro objeto.
Associação
A associação é um relacionamento estrutural entre duas classes que 
especifica quais são os objetos conectados entre si. Isso possibilita 
que, por meiodos vínculos do relacionamento, um objeto invoque 
estados e comportamentos de outros objetos. 
Veja o exemplo a seguir.
InterfacesClasses abstratas
Não permite herança múltipla
Deve possuir a palavra-chave class
Permite a declaração de atributos
Métodos podem ser public e abstract
Pode conter métodos abstratos
Possui construtores
Métodos não abstratos podem 
ser estáticos
Permite herança múltipla
Deve possuir a palavra-chave interface
Não permite a declaração de atributos
Métodos são public e abstract
Só possui métodos abstratos
Não possui construtores
Por conter apenas métodos abstra-
tos, não é possível declarar métodos 
estáticos
122
Diagrama 4 - Diagrama de Classe – Associação entre Classes
Fonte: Editorial Digital Pages (2020).
No diagrama representado, a classe Pessoa poderá possuir 
uma lista de objetos do tipo Automóvel, por isso está representa-
da pelo 0..*, que indica que uma pessoa poderá ter nenhum ou vá-
rios automóveis. Em contrapartida, todo automóvel deve pertencer 
à apenas uma pessoa, por isso do lado da entidade Pessoa temos o 
valor 1. Nesse caso, o relacionamento entre as classes será visível 
apenas na classe Pessoa, que conterá a lista de carros. Assim, para 
utilizarmos esse tipo de relacionamento na programação, devemos 
trabalhar com arrays, que são listas de objetos do mesmo tipo.
Assim, veja na prática a declaração das classes do Diagrama 4. 
Nesse sentido, iniciaremos pela classe Carro, já que a classe Pessoa 
terá um array dela:
public class Carro { 
private String placa; 
private String marca;
private String modelo; 
private String classi;
private short anoFabricacao; 
private short anoModelo;
public String getPlaca() {
return placa;
}
123
public void setPlaca(String placa) {
this.placa = placa;
}
public String getMarca() {
return marca;
}
public void setMarca(String marca) {
this.marca = marca;
}
public String getModelo() {
return modelo;
}
public void setModelo(String modelo) {
this.modelo = modelo;
}
public String getClassi() {
return classi;
} 
public void setClassi(String classi) {
this.classi = classi;
}
public short getAnoFabricacao() {
return anoFabricacao;
}
public void setAnoFabricacao(short anoFabricacao) {
this.anoFabricacao = anoFabricacao;
}
124
public short getAnoModelo() {
return anoModelo;
}
public void setAnoModelo(short anoModelo) {
this.anoModelo = anoModelo;
}
}
 Agora, veremos a declaração da classe Pessoa: public class 
Pessoa {
public Pessoa() {
if(this.carros == null ) {
this.carros = new Carro[0];
}
}
private String nome;
private long cpf;
private Carro [] carros; 
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public long getCpf() {
return cpf;
}
public void setCpf(long cpf) {
125
this.cpf = cpf;
}
public Carro[] getCarros() {
return carros;
}
public void setCarros(Carro[] carros) {
this.carros = carros;
}
}
 Perceba que, na classe Pessoa, possuímos um array de obje-
tos da classe Carro (Carro [] carros;). Isso indica que a classe Pessoa 
“tem um” objeto do tipo array de Carro, mas não necessariamente 
significa que seja obrigatório ter um objeto carro dentro do array do 
objeto da classe Pessoa. Assim, para evitarmos NullPointerExcep-
tion, devemos inicializar o array, conforme feito no construtor da 
classe Pessoa (note que todo array também é um tipo de objeto, ou 
seja, é uma lista).
NullPointerException é uma exceção gerada pelo sistema quando 
se tenta acessar um objeto em memória que ainda não foi instan-
ciado (ou inicializado). O significado é que o objeto está nulo e não 
possui um valor definido naquele momento. A classe de exceção é a 
java.lang.NullPointerException. Geralmente ocorre exceção quan-
do um objeto não é inicializado, todavia, isso não se aplica aos ti-
pos primitivos.
Dessa forma, para entendermos como funciona o relaciona-
mento das categorias, nesse caso, vamos à um exemplo de imple-
mentação de um código que manipule ambas as classes:
DEFINIÇÃO
126
public class Start {
public static void main(String[] args) { 
Carro carro1 = new Carro();
carro1.setAnoFabricacao((short) 2010);
carro1.setAnoModelo((short) 2011);
carro1.setMarca(“Marca 1”);
carro1.setModelo(“Modelo 1”); 
carro1.setClassi(“77784646846HHjJ46468764”); 
carro1.setPlaca(“AAA-1234”);
Carro carro2 = new Carro(); 
carro2.setAnoFabricacao((short) 2010);
carro2.setAnoModelo((short) 2011);
carro2.setMarca(“Marca 2”);
carro2.setModelo(“Modelo 2”); 
carro2.setClassi(“748XJS684633jJ46AA3889”); 
carro2.setPlaca(“BBB-4321”);
Pessoa pessoa = new Pessoa(); 
pessoa.setNome(“Fulano da Silva Beltrano”);
pessoa.setCpf(00011122233);
Carro [] carros = {carro1, carro2}; 
pessoa.setCarros(carros);
for(Carro carro : pessoa.getCarros()) { 
System.out.println(“O veículo “ + carro.getModelo()
 + “ pertence ao “ + pessoa.getNome());
}
System.out.printf( “%s tem %d %s”,
pessoa.getNome(), pessoa.getCarros().length,
pessoa.getCarros().length > 1 ? “carros” : “carro”
);
}
}
127
Observe que são instanciados dois objetos do tipo Carro e um 
objeto do tipo Pessoa. Posteriormente, foi declarado um array de 
objetos Carro, adicionando os dois objetos Carro ao array, em se-
guida fazendo set do array de Carros, relacionando-os à Pessoa. 
Por último, iteramos todos os carros contidos dentro do ar-
ray, escrevendo no terminal pelo comando System.out.println o 
modelo do carro e o nome do dono. Finalizando, escrevemos no ter-
minal o nome da pessoa e quantos carros ela possui, fazendo uso do 
operador condicional ternário, que é composto pela condição ? ex-
pressão1 : expressão2, bastante similar à uma função if else simples.
Composição
A composição, segundo (BEDER, 2014), é um relacionamento com 
características “todo-parte”; assim, uma classe só tem sentido em 
sua existência (parte), se outra classe existir (todo). Veja o exemplo.
Diagrama 5 - Diagrama de classes – Associação e Composição entre Classes
Fonte: Editorial Digital Pages (2020).
128
No diagrama de classes apresentado, as classes Cliente e Pe-
dido estão associadas de forma simples. Nesse sentido, um cliente 
pode ter nenhum ou vários pedidos, assim como os pedidos só per-
tencem a um cliente. Depois, temos a composição entre Pedido, que 
é o “todo”, e o ItemPedido, considerado a “parte”, isto é, que não 
pode existir sem a presença de um Pedido. Note, ainda, que a ligação 
entre as classes Pedido e ItemPedido é feita por meio da linha com 
o “diamante” escuro e que, obrigatoriamente, o pedido deverá ter 
pelo menos um itemPedido. Seguindo a mesma lógica, portanto, o 
itemPedido pertence a apenas um requerimento.
Veja, na prática, a declaração das classes do Diagrama 5. Des-
taco que iniciaremos pelo ItemPedido, necessário para a construção 
do Pedido, veja:
public class ItemPedido {
public ItemPedido () {
this.quantidade = 1;
}
public ItemPedido(String descricao, int quantidade, double 
valorUnitario)}
{
this.descricao = descricao; 
this.setQuantidade(quantidade); 
this.setValorUnitario(valorUnitario);
}
private String descricao; 
private int quantidade; 
private double valorUnitario; 
public String getDescricao() {
return descricao;
}
129
public void setDescricao(String descricao) {
this.descricao = descricao;
}
public int getQuantidade() {
return quantidade;
} 
Public void setQuantidade(int quantidade) {
If(quantidade > 01) {
this.quantidade = quantidade;
} else {
This.quantidade = 1;
}
} 
public double getValorUnitario() {
return valorUnitario;
}
public void setValorUnitario(double valorUnitario) { 
if(valorUnitario > 0) {
this.valorUnitario = valorUnitario;
} else {
This.valorUitario = 0;
}
}
public void addQuantidade(int quantidade) {
this.quantidade += quantidade;
}
@Override
130
public int hashCode() {
final int prime = 31; int result = 1;
result = prime * result + ((descricao == null) ? 0 : descri-
cao. hashCode());
result = prime * result + quantidade;long temp;
temp = Double.doubleToLongBits(valorUnitario); 
result = prime * result + (int) (temp ^ (temp >>> 32)); 
return result;
} 
@Override
public boolean equals(Object obj) { 
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
ItemPedido other = (ItemPedido) obj;
if (descricao == null) {
if (other.descricao != null)
return false;
} else if (!descricao.equals(other.descricao))
return false;
if (quantidade != other.quantidade)
return false;
if (Double.doubleToLongBits(valorUnitario) != Double.
double- ToLongBits(other.valorUnitario))
return false; 
131
return true;
}
}
Observe que nessa classe possuímos dois construtores, um 
que já inicializa a quantidade igual a 1 e outro que permite a inserção 
das informações sem precisar fazer os setters. Além disso, no encap-
sulamento dos dados, verificamos se a quantidade inserida é maior 
que zero, já que não faz sentido um item de pedido zerado ou com 
quantidade negativa. Isso é feito, também, para o valor unitário. Re-
pare que sobrescrevemos os métodos equals e hashCode existentes 
na classe Object. Esses métodos serão essenciais para a funcionali-
dade de adição do novo item na classe Pedido. Todavia, não se preo-
cupe quanto à sobrescrita destes métodos, pois, possivelmente sua 
IDE o fará automaticamente.
Dito isto, agora, veremos a classe Pedido:
import java.util.Date; 
import java.util.HashSet; 
import java.util.Set; 
public class Pedido {
public Pedido () {
this.itemPedidos = new HashSet<ItemPedido>();
}
private Date dataPedido;
private String formaPagamento; 
private Set<ItemPedido> itemPedidos; 
public Date getDataPedido() {
return dataPedido;
}
public void setDataPedido(Date dataPedido) {
this.dataPedido = dataPedido;
132
}
public String getFormaPagamento() {
return formaPagamento;
}
public void setFormaPagamento(String formaPagamento) {
this.formaPagamento = formaPagamento;
}
public Set<ItemPedido> getItemPedidos() {
return itemPedidos;
}
public void addItemPedido(ItemPedido item) { 
if(this.itemPedidos.contains(item)) {
this.itemPedidos.stream()
.filter(oneItem -> oneItem.equals(item))
.forEach(oneItem -> oneItem.addQuantidade(item.
getQuantidade()));
} else {
this.itemPedidos.add(item);
}
}
public float getTotalPedido() { 
float total = 0;
for(ItemPedido item : itemPedidos) {
total += item.getValorUnitario() * item.
getQuantidade();
}
return total;
}
}
133
Nessa classe, para o ItemPedido, fizemos uso da interface 
Set, que é uma collection que não permite duplicidade de dados. Nes-
se sentido, por ser uma interface, também fizemos a implementação 
da classe HashSet. Em seguida, como não é permitida a duplicidade 
de dados no método addItemPedido, verificamos se o item já existe 
na lista. Caso exista, fazendo uso de uma expressão lambda, procu-
ramos o item em questão e adicionamos à quantidade existente à 
nova, por meio do método addQuantidade.
Perceba que isso só é possível graças aos métodos equals e hash-
Code existentes no item do pedido. Lembre-se que o hashCode utiliza 
um cálculo matemático para determinar um valor àquele atributo e, 
caso um dos atributos possua valores diferentes, ele não será conside-
rado igual e executará a condição else, adicionando o item à lista.
Agregação
A agregação é similar à associação e sua diferença é apenas conceitual. Nesse 
sentido, a agregação não é perceptível e, caso existam dúvidas entre agre-
gação e associação, opte sempre pela associação (KNOERNSCHILD, 2001).
Assim, Beder afirma que:
a agregação é um relacionamento com carac-
terísticas ‘todo-parte’ [...] menos intenso, po-
dendo haver um certo grau de independência 
entre eles. Ou seja, a existência do objeto ‘par-
te’ faz sentido mesmo sem a existência do ob-
jeto ‘todo’ (BEDER, 2014, p. 39).
Para entendermos o conceito em maior profundidade, obser-
ve o diagrama a seguir.
 Diagrama 6 - Diagrama de Classes – Agregação entre Classes
Fonte: Editorial Digital Pages (2020).
134
Observando o diagrama, note que um time pode ter um ou vários 
atletas, e o atleta pode ou não ter um time (o que significa que o 
atleta pode existir sem a necessidade da presença de um time). Nes-
se contexto, há exclusividade, ou seja, embora o atleta só possa es-
tar associado a um único time, ele pode existir sem a existência de 
um time propriamente dito.
Polimorfismo
Introdução ao polimorfismo
A palavra polimorfismo vem do grego poli morfos, cujo significado 
pode ser traduzido como “o que possui várias formas”. Em infor-
mática, na programação, esse significado não é muito diferente:
polimorfismo (“muitas formas”) permite a ma-
nipulação de instâncias de classes que herdam de 
uma mesma classe ancestral de forma unificada: 
podemos escrever métodos que recebam instân-
cias de uma classe C, e os mesmos métodos serão 
capazes de processar instâncias de qualquer classe 
que herde da classe C, já que qualquer classe que 
herde de C é-um-tipo-de C. (SANTOS, 2011, p. 140).
Isso significa que, por exemplo, as subclasses Professor e 
Aluno, por serem tipos de Pessoa, estendem a superclasse Pes-
soa e podem executar métodos que sejam declarados na classe 
Pessoa ou em sua superclasse. Nesse caso, o objeto mais es-
pecializado transforma-se em um objeto genérico de qualquer 
nível acima da sua hierarquia. Em outras palavras, em Java, to-
dos os objetos podem ser tratados como se fossem objetos de 
uma superclasse.
DICA
135
Polimorfismo na prática
O Diagrama 7 apresenta um exemplo da situação supracitada.
Diagrama 7 - Diagrama de Classes: exemplo de polimorfismo
 Fonte: Editorial Digital Pages (2020).
A classe Pessoa tem atributos comuns para qualquer pessoa 
e a declaração de seu método obterNomeCompleto sugere que este 
também é comum a qualquer pessoa. Como as classes Professor e 
Aluno são tipos de pessoa, elas estendem a classe Pessoa e, conse-
quentemente, herdam seus atributos e método. Agora, em relação à 
implementação dessas classes, observe as Figuras 3 e 4.
Figura 3 - Implementação da classe Pessoa
Fonte: Editorial Digital Pages (2020).
136
Figura 4 -Implementação das classes Aluno e Professor.
 .Fonte: Editorial Digital Pages (2020).
De modo geral, não há novidade alguma até o momento: sim-
plesmente, aplicou-se o conceito de herança. Agora, é necessário 
explorar a manipulação dessas classes, criando uma classe que con-
tenha o método main para que seja possível executar o conteúdo e 
entender o conceito de polimorfismo, veja um exemplo.
public class Start {
public static void main(String[] args) { 
Pessoa pessoa = new Pessoa(); 
Aluno aluno = new Aluno();
Professor professor = new Professor(); 
pessoa.setNome(“João”); 
pessoa.setSobrenome(“da Silva”);
aluno.setNome(“Ana”); 
aluno.setSobrenome(“de Oliveira Lima”); 
aluno.setTurma(“6º B”); 
professor.setNome(“Guilherme”); 
professor.setSobrenome(“Nascimento”); 
professor.setSalario(4389.33); 
imprimeNomeCompleto(pessoa); 
imprimeNomeCompleto(aluno); 
imprimeNomeCompleto(professor);
137
}
public static void imprimeNomeCompleto(Pessoa pessoa) {
 System.out.println(pessoa.obterNomeCompleto());
}
}
No código apresentado, ocorreu a criação de três objetos:
 • objeto pessoa do tipo Pessoa;
 • objeto aluno do tipo Aluno;
 • objeto professor do tipo Professor.
Posteriormente, houve a inserção dos valores dos atributos 
para os respectivos objetos. Ao final, chamou-se o método impri-
meNomeCompleto, que espera receber um objeto do tipo Pessoa. 
Por três vezes este método foi chamado e um objeto diferente foi 
passado em cada chamada. Como o parâmetro do método espera um 
objeto do tipo Pessoa, ao passar os objetos aluno e professor, não há 
erro de compilação, uma vez que estes são subclasses da superclasse 
Pessoa: dessa maneira, de acordo com o conceito de herança, ambos 
não deixam de ser objetos da superclasse.
Caso não houvesse polimorfismo, ao passar os objetos do tipo 
Aluno e Professor por parâmetro ao método imprimeNomeCompleto,haveria um erro de compilação. Com o polimorfismo, porém, os obje-
tos aluno e professor, “transformam-se” em um objeto do tipo Pes-
soa: ao executar-se a aplicação, o resultado é apresentado conforme 
o esperado, posto que ambos os objetos têm os mesmos atributos e 
método herdados da classe Pessoa. Observe o resultado a seguir.
Figura 5 - Resultado da execução da classe Start- exemplo do polimorfismo
Fonte: Editorial Digital Pages (2020).
138
Santos, em seu livro “Introdução à programação orientada a 
objetos usando Java”, de 2011, ressalta que “as regras de cast entre 
instâncias de classes não permitem a conversão de classes mais ge-
néricas para classes mais específicas, nem de classes que não este-
jam em uma hierarquia de herança” (p. 145).
Em outras palavras, se, por exemplo, o parâmetro do método 
imprimeNomeCompleto fosse do tipo Professor, não seria possível 
passar os objetos do tipo Aluno e Pessoa por parâmetro, visto que 
Pessoa é mais genérico que Professor e a conversão do objeto mais 
genérico para o mais específico não é possível.
Por sua vez, o tipo Aluno está no mesmo nível hierárquico que 
Professor, visto que ambos herdam de Pessoa. Como são dois objetos 
diferentes por estarem no mesmo nível hierárquico, a classe Aluno não 
é um tipo de Professor, embora ambos sejam um tipo de Pessoa.
Ligação dinâmica (dynamic binding)
A ligação dinâmica está muito relacionada aos conceitos do po-
limorfismo e herança. Nesse caso, uma subclasse tem métodos 
herdados da superclasse e os sobrescreve da melhor maneira para 
realizar suas operações. E, somente durante a execução e utilizando 
conceitos do polimorfismo, o Java toma a decisão de qual método 
deve ser usado: se o da subclasse ou de uma das superclasses de ní-
veis acima. Para entender o que estamos tratando, veja:
a implementação do polimorfismo pode exi-
gir facilidades proporcionadas pela ligação 
dinâmica. De um modo geral, uma ligação 
(binding) é uma associação, possivelmente, 
entre um atributo e uma entidade ou entre 
uma operação e um símbolo. Uma ligação é 
dita estática se ocorre em tempo de compila-
ção [...] e não é mais modificada durante toda 
a execução do programa. A ligação dinâmica 
é feita em tempo de execução ou pode ser al-
terada no decorrer da execução do programa 
(KAMIENSKI, 1996, p. 15).
139
Pode-se afirmar, portanto, que a ligação dinâmica aconte-
ce apenas durante a execução do programa, quando o próprio Java 
toma a decisão de qual método de qual classe deve ser usado. Já a li-
gação estática é aquela executada diretamente, quando não há apli-
cação do polimorfismo. Assim, observe o Diagrama 8 que representa 
uma hierarquia entre as classes.
Diagrama 8 - Diagrama de Classe: Hierarquia de Classes.
Fonte: Editorial Digital Pages (2020).
Como você deve ter percebido, o diagrama apresenta uma es-
trutura longa de hierarquia, na qual as classes Gato, Tigre e Leão 
são as mais especializadas, e as demais, acima, são sucessivamen-
te mais genéricas – até a primeira do topo, que é a classe Object do 
próprio Java.
140
DICA
Tratamento de exeções
No desenvolvimento de software, uma exceção não é algo que ocor-
re de forma rara. Exceções, na verdade, são eventos que, por algum 
motivo – neste caso, uma condição excepcional –, geram erros no 
sistema, os quais podem ou não ser esperados.
Em muitos dos casos, exceções ocorrem quando o progra-
mador se esquece de inicializar um objeto ou encontra erros du-
rante a conversão, ou casting, de objetos.
Se essas exceções ocorrerem e o devido tratamento para o caso não 
for realizado, o sistema provavelmente será interrompido naquele 
ponto e não executará o processamento restante.
Ricarte (2001, p. 29) diz que “para cada exceção que pode 
ocorrer durante a execução do código, um bloco de ações de trata-
mento (um exception handler) deve ser especificado. O compilador 
Java verifica e reforça que toda exceção ‘não-trivial’ tenha um blo-
co de tratamento associado”. Em muitos casos, as exceções podem 
ser evitadas de forma simples, apenas utilizando condicionadores 
como if-else ou operador ternário, por exemplo. Em alguns contex-
tos, porém, o ideal é capturar e tratar a exceção utilizando o bloco 
try-catch; e, em determinados casos, até mesmo lançar a exceção 
para o método acima da pilha de chamadas.
Evitando e capturando exceções
A forma mais comum para evitar uma exceção é realizar verifica-
ções no objeto antes de utilizá-lo para seu propósito. Um exemplo 
muito comum é checar se o objeto não está nulo, o que evita erros 
de NullPointerException. Assim, a captura de exceção é feita com os 
141
blocos try-catch, que também podem possuir o finally. Além disso, é 
possível ter na estrutura vários catches que capturam um tipo espe-
cífico de exceção. Sua estrutura pode ser da seguinte maneira: 
try {
// Código que implementa alguma função no sistema, que 
pode gerar
alguma exceção
} catch (Exception e) {
// Trecho no qual é feita a captura da exceção
} finally {
// Se declarado, o finally será sempre executado, indepen-
dentemente se gerou ou não uma exceção
}
O bloco try-catch-finally precisa estar dentro do escopo de um mé-
todo e não há necessidade de implantá-lo em locais nos quais pos-
sivelmente não haverá erros.
Caro(a) estudante. Chegamos ao final de mais uma etapa de estudos. 
Nesse módulo, aprendemos sobre a usabilidade da herança e qual é 
a melhor forma de implementá-la entre as classes. Além disso, dis-
cutimos a utilização da palavra-chave super, que permite chamar 
diretamente métodos e atributos das superclasses (desde que não 
sejam privates).
VOCÊ SABIA?
SINTETIZANDO
142
Também vimos como funciona a hierarquia entre as classes e como 
o Java trabalha para tratar sobre esse assunto, além de observarmos 
como é a forma correta de implementação de hierarquia.
Um outro ponto estudado, referiu-se à utilização das classes abs-
tratas e interfaces, além das principais diferenças entre elas. Vimos 
também que a herança múltipla entre classes em Java não é pos-
sível, mas que essa regra não ocorre entre interfaces. Além disso, 
embora não seja possível que uma subclasse se estenda à mais de 
uma classe mãe, aprendemos que uma classe pode implementar 
inúmeras interfaces.
Por fim, estudamos que, além da herança, as classes possuem rela-
cionamentos classificados em três tipos: agregação, composição e 
associação. Lembre-se que esses relacionamentos só são possíveis 
quando podemos dizer que um objeto “tem um”, mas não “é um”.
Esperamos ter contribuído com o seu aprendizado.
Até a próxima!
UN
ID
AD
E
4
Objetivos
 ◼ Entender o conceito de recursividade.
 ◼ Entender os algoritmos de ordenação e conhecer o código dos 
algoritmos mais usados.
 ◼ Conhecer estruturas de dados: listas, filas, pilhas e árvores.
 ◼ Conhecer algumas implementações em Java dessas estruturas.
144
Introdução
Olá, aluno(a). Como vai? Chegamos a mais uma etapa de estudos e, 
nesse momento, serão apresentados a você os conceitos de algorit-
mos recursivos e algoritmos de ordenação. E, para implementar es-
ses conceitos, apresentaremos códigos Java usando vetores.
Veremos também o conceito de recursividade e a implemen-
tação de algoritmos recursivos. Discutiremos sobre os algoritmos 
mais conhecidos de ordenação de vetores, mostrando o código de 
alguns desses algoritmos.
Antes de finalizarmos este material, veremos os conceitos de es-
trutura de dados conhecidos como Lista, Filas, Pilhas e Árvores, apre-
sentando parte dos códigos desenvolvidos para o uso desses conceitos.
Dito isto, convido você a conhecer os temas citados de forma des-
complicada e muito intuitiva, conforme abordaremos neste material.
Boa leitura e bons estudos!
145
Algoritmos recursivos
Alguns problemas exigem que sejam trabalhados laços de repeti-
ções para executar as mesmas instruções em quantidades estabe-
lecidas ou esperadas. Dessa maneira, os algoritmos recursivos são 
uma espécie de loop que possuem um critério de parada. Porém o 
mesmo algoritmo“chama a si mesmo com argumentos tratados”.
Figura 1 - Exemplo de algoritmo recursivo
Fonte: Comitê Editorial Digital Pages (2019).
Caro(a) aluno(a), para que você entenda o que abordamos até agora, 
o programa a seguir imprime do 10 ao 1 na tela. Veja!
O método da linha 4, chamado recursão, é iniciado pelo método 
main, que é o primeiro método a ser executado da classe da linha 16. 
Dessa maneira, ao ser iniciado, passa-se o parâmetro 10. Esse algo-
ritmo faz a contagem regressiva de 10 até 1, chamando a si mesmo 
class Recursao {
 public static void repercusao(int contador){
 System.out.print(contador);
 contador = contador--1
 
 if (contador == 0) {
 return;
 }
 //chamando novamente
 repercusao(contador);
 
 }
 
 public static void main(string[] args) {
 repercusao(10);
 }
}
EXEMPLO
146
decrementando -1 da variável contador. Mas, caso não tivesse um 
critério de parada, esta recursão na linha 9 com a condição conta-
dor==0, a execução se estenderia até o travamento do computador, 
pois ele chamaria a si mesmo perpetuamente, como se fosse um 
loop. Porém, dentro dele, deve ter um critério de parada geralmente 
com o comando return, como na linha 10.
Resumindo, a recursão nada mais é do que uma função que chama 
ela mesma, recebendo um argumento e repassando o mesmo argu-
mento tratado, com um critério de parada dentro da própria função.
Figura 2 - Exemplo de recursão
Fonte: Comitê Editorial Digital Pages (2019).
É importante destacarmos que o fatorial é um exemplo clás-
sico de recursão, onde seu critério de parada, geralmente, vem no 
início da função e a chamada de si mesmo, ou recursão, acontece na 
mesma linha do return, como na linha 7. O resultado da nova cha-
mada é multiplicado ao argumento inicial decrementando 1.
Técnicas de ordenação
A ordenação é um dos métodos de Estrutura de Dados que visa or-
denar dados desordenados. E, para isso, existem muitas formas:
class Fatorial {
 public static int fatorial(int n){
 if (n== 1) {
 return n;
 }
 Return (fatorial(n-1)*n);
 
 }
 
 public static void main(Sstring[] args) {
 System.out.println(factorial(6));
 }
}
147
 • selection sort;
 • insertion sort;
 • quick sort;
 • merge sort;
 • heap sort;
 • radix sort (LSD);
 • radix sort (MSD);
 • std::sort (intro sort);
 • std::stable_sort (adaptive merge sort);
 • shell sort;
 • bubble sort;
 • cocktail shaker sort:
 • gnome sort;
 • bitonic sort;
 • bogo sort.
O que diferencia esses métodos é o tempo para ordenação e 
a forma de troca dos dados. Alguns usam recursão, outros somente 
loops ou a mescla entre eles. Como você pode perceber, não existe 
uma forma única de resolver um problema, porém sempre deve ser 
observado se o algoritmo se encaixa nas regras de negócio. Pensan-
do nisso, abaixo você irá conhecer os mais tradicionais: bubble sort, 
insertion sort, e quick sort. Vamos lá!
Método Bubble Sort
O método Bubble Sort, ou “método bolha”, tem por objetivo a ordenação 
dos dados a partir de 2 em 2, trocando sempre o maior valor pelo menor 
148
valor e percorrendo o vetor por diversas vezes. O nome deste algoritmo 
remete à ideia de que os dados se comportam como “bolhas” dentro de 
um tanque e, embora seja simples, não é tão eficiente quanto outros algo-
ritmos de ordenação quando os dados estão totalmente desorganizados.
Na classe Bubble Sort, por exemplo, temos a função main na 
linha 24, que inicia um vetor com valores desordenados e envia esse 
vetor para o método Bubble Sort na linha 25.
Assim, ao chamar o método na linha 25, inicia-se a ordena-
ção a partir da linha 2 onde este método possui dois loops: um que 
percorre todos os índices e o segundo loop que percorre até o pe-
núltimo. Perceba que a troca dos dados é feita após a verificação da 
linha 5 no if que verifica se o valor do índice -1 é maior que o valor 
do índice do atual. Ou seja, a troca é feita de 2 em 2.
Após a ordenação, o programa volta para a função main, execu-
tando a linha 26, chamando outra função que é a imprimir, e execu-
ta-se o bloco da linha 16, fazendo uma impressão for-each em tela do 
vetor ordenado, diferente de uma variável que precisa ser uma variável 
global. Observe que, ao executar o código, não precisamos receber o ve-
tor ordenado, ele se ordena pelo endereço de memória, fazendo apenas 
a referência dele, conseguimos fazer a impressão do vetor ordenado.
Figura 3 - Exemplo de Método Bubble Sort
Fonte: Comitê Editorial Digital Pages (2019).
package bubblesort;
public class BubbleSort {
 public static void main(String args[]) {
 int[] v = {5, 2, 4, 3, 0, 9, 7, 8, 1, 6};
 BubbleSort bs = new BubbleSort();
 bs.ordenar(v);
 for(int num : v) {
 System.out.print(num + " ");
 }
 }
public void ordenar(int[] v) {
 // for utilizado para controlar a quantidade de 
vezes que o vetor será ordenado.
 for(int i = 0; i < v.length - 1; i++) {
 // for utilizado para ordenar o vetor.
 for(int j = 0; j < v.length - 1 - i; j++) {
 /* Se o valor da posição atual do vetor for 
maior que o proximo valor,
 então troca os valores de lugar no vetor. */
 if(v[j] > v[j + 1]) {
 int aux = v[j];
 v[j] = v[j + 1];
 v[j + 1] = aux;
 }
 }
 }
 }
}
149
EXEMPLO
Método Insertion Sort
O método Insertion Sort é um algoritmo de ordenação que per-
corre o vetor da esquerda para a direita, trazendo os menores 
valores para a esquerda e, assim, inicia as trocas a partir do se-
gundo elemento.
Considere um vetor de 5 posições vetor[]=new [] {7,6,4,2,9}; 
1º - 7-6-4-2-9 – desordenado;
2º - 6-7-4-2-9 – a primeira troca do segundo elemento pelo 
primeiro;
3º - 4-6-7-2-9 – a terceira troca, empurrando os elementos maio-
res para a direita e os menores para a esquerda;
4º - 2-4-6-7-9 – a quarta troca, empurrando os elementos maio-
res para a direita e os menores para a esquerda, fazendo o 2 ser o 
primeiro item do vetor;
5º - 2-4-6-7-9, no caso do 9, como é um elemento maior que o 7, 
ele permanece no mesmo local, retornando o vetor ordenado.
Observe no código a seguir que, na linha 23, o método main 
inicia um vetor desordenado e passa, via parâmetro, para a função 
insertion sort na linha 2. Assim, o primeiro loop percorre o vetor e o 
segundo percorre da esquerda para a direita, ordenando os valores. 
Após a ordenação, chama-se o método imprimir para mostrar o ve-
tor ordenado.
150
Figura 4 - Exemplo de Método Insertion Section
Fonte: Comitê Editorial Digital Pages (2019).
Método Selection Sort
O método Selection Sort busca no vetor o menor valor entre todos 
os elementos e o insere na primeira posição após a verificação. 
Esse tipo de método é diferente do Bubble Sort, que faz a troca pelo 
maior ou menor por meio do insert de forma ordenada para todos 
os elementos.
Figura 5 - Exemplo do método Selection Sort
Fonte: Comitê Editorial Digital Pages (2019).
1 class BubblesortExemplo {
2 public static void bubblesort(int[] array) {
3 for(int i=0; i < array.length; i++){
4 for(int j=1; j < (array.length-1); j++){
5 if(array[j-i] > array[j]){
6 int aux = array[j-1];
7 array[j-1] = array[j];
8 array[j] = aux;
9 }
10
11 }
12 }
13
14 }
15
16 private static void imprimir(int vetor[])
17 {
18 for(int aux: vetor)
19 {
20 System.out.println(aux);
21 }
22 }
23 public static void main(String[] aux){
24 int array[] = new int[200,0,-20,-11];
25 bubblesort(array);
26 imprimir(array);
27 }
28 }
public static void selectionSort(int[] vetor) { 
 for (int i = 0; i < vetor.length; i++) {
 
 int i_menor = i;
 for (int j = i + 1; j < vetor.length; j++)
 if (vetor[j] < vetor[i_menor])
 i_menor = j;
 
 int aux = v[i];
 vetor[i] = v[i_menor];
 vvetor[i_menor]= aux;
 } 
}
151
Estruturas Lineares
As estruturas lineares são estruturas que agrupam dados em se-
quência ou em uma ordem pré-determinada. Por exemplo, em se 
tratando da ordenação em Lista sequencial FIFO (First in First Out – o 
primeiro que entra é o primeiro que sai) e LIFO (Last in First Out – o 
último que entra é o primeiro que sai), porém sua retirada pode ser 
tanto em sequência como de forma desordenada, por prioridade etc.
Dessa maneira, as estruturas lineares mais utilizadas são: 
lista, pilha e fila que implementam o vetor dentro de suas estruturas 
de acordo com seu comportamento. Perceba que o armazenamento 
tem sua implementação diferenciada no código.
É importante destacarmos que, quando se fala em Listas, 
no geral, implementa-se a estrutura primitiva do vetor, que é uma 
estrutura sequencial indexada com o mesmo tipo. E quando se im-
plementa uma estrutura em vetor por herança, absorve a maior ca-
racterística do vetor à sua limitação quanto ao tamanho.
Assim, a limitação, quanto ao tamanho do vetor, faz com que 
as estruturas possam ser divididas em duas formas de alocação: a es-
tática e a dinâmica. A alocação estática faz com que qualquer estrutu-
ra tenha um tamanho máximo para inserção de elementos, forçando 
o programador a usar soluções paliativas para manter a estrutura em 
vetor. Já a alocação dinâmica é uma estrutura que não implementa o 
vetor, porém implementa o conceito de No, onde é possível alterar 
sua estrutura de acordo com a necessidade do(a) programador(a).
Dito isto, a partir de agora, vamos detalhar as estruturas li-
neares mais utilizadas: a lista, a pilha e a fila. Vamos lá!
Listas
Inicialmente, é necessário destacarmos que as listas são estruturas 
que alocam, de forma sequencial, os dados. Temos as listas estáti-
cas, que implementam o vetor, e a lista dinâmica, que são as listas 
ligadas e duplamente ligadas, tratando-se do Java Collections da 
interface List.
152
EXEMPLO
Lista Estática
A Lista Estática implementa o vetor, podendo ser de forma estrutu-
rada ou objeto. Tanto uma quanto a outra são fixas a seus tamanhos 
e requerem soluções paliativas após o tamanho máximo ser utiliza-
do. A grande vantagem da lista estática ou do uso do vetor na estru-
tura é a capacidade de indexação dos elementos, fazendo com que a 
individualização de cada um seja mais efetiva. Diferente de outras 
estruturas em que é necessário navegar na estrutura para acessar 
os valores.
Observe o código a seguir:
System.out.println( vetor[11]); // 
Neste código a partir do índice 11, busca-se o valor do vetor na po-
sição 11.
Lista Ligada
É um tipo de dado abstrato que se comporta como o conceito de 
Lista, mas implementa o Objeto No ou Node.
 ◼ No ou Node
O No ou Node é um objeto que faz autorreferência, tendo um for-
mato em que pode ter de 0 a n itens lincados.
Em relação ao conceito de No, entende-se que os itens podem 
ser inseridos e removidos em qualquer local da estrutura, podendo 
aumentá-los e diminuí-los conforme a necessidade. Sua navegação 
ocorre por meio da referência do objeto denominado próximo, aces-
sado por meio do método getProximo().
153
O construtor na linha 6 é uma função que recebe como parâmetro o valor 
a ser alocado e a referência do objeto que será próximo do objeto atual.
Na linha 3, armazena-se o próximo item que, para acessá-lo, 
é preciso usar o método getProximo() e, para setar a referência do 
próximo No, usa-se o método setProximo(). Além disso, as funções 
setValor() e getValor() armazenam os valores a serem alocados.
Dessa maneira, ao tratar-se da Lista ou qualquer outra estru-
tura de dados, deve-se, obrigatoriamente, implementar o código do 
No para ser referenciado na estrutura.
Figura 6 - Implementação do código No
Fonte: Comitê Editorial Digital Pages (2019).
É importante destacarmos que a Lista Ligada é uma estrutura 
que implementa o Node e cada elemento dela consiste em um Node, 
que possui em si mesmo a referência de seu próximo, possibilitando 
uma capacidade N de armazenar e diminuir itens conforme a neces-
sidade. Possui como principal objeto o próximo que armazena o en-
dereço do próximo objeto e o valor que armazena os valores alocados.
CURIOSIDADE
class No {
 private No proximo;
 private int valor;
 No(int v, No n) {
 valor = v;
proximo = n;
 }
 public int setValor() {
return valor;
 }
 public int getValor() {
return valor;
 }
 public void setProximo(No aux) {
proximo = aux;
 }
 public No getProximo() {
 return proximo;
 }
}
154
Figura 7 - Implementação do Node na estrutura de Lista ligada
 Fonte: Comitê Editorial Digital Pages (2019).
Para que você entenda o que estamos abordando, sugiro 
que observe a seguinte estrutura de Lista Ligada apresentada na 
figura 8.
Figura 8 - Estrutura de Lista Ligada
 Fonte: Comitê Editorial Digital Pages (2019).
O primeiro No é o início do No, trazendo em si a referência 
do próximo No, que seria o que armazena o -1. Para percorrer os 
nos, usa-se o método getProximo(), e, no seu retorno, usa-se o ge-
tProximo() do outro No. Assim, chega-se ao ultimoNo que, ao usar o 
getProximo() do ultimoNo, ele retornará null, caracterizado, assim, 
por ser o último No da estrutura.
 ◼ Inserção
Inserção dos elementos 5 e 7 nas extremidades ocorre após, primei-
ramente, os Nos com os valores serem criados e depois inseridos nas 
extremidades. No caso do 5 que está alocado no início, apenas irá 
setar como seu próximo, o primeiroNo, fazendo, desse modo, o se-
gundo No da estrutura. No exemplo da inserção no último No, temos 
ele setando o seu objeto próximo para o novo No, tornando o novo 
No o último, e ele o penúltimo No da lista.
valor próximo
nullprimeiroNo
0 -1
primeiroNo
10 20
null
ultimoNo
155
Figura 9 - Inserção dos elementos 5 e 7 nas extremidades
 Fonte: Comitê Editorial Digital Pages (2019).
 ◼ Busca de um elemento
A busca em uma estrutura de Lista Ligada se dá pela navegação da 
função getProximo(), que sempre irá fornecer o endereço do próxi-
mo No e, ao chegar no final, ele irá retornar null. Assim, o algoritmo 
faz um loop entre os getProximo() e confere o valor do No aux com 
o valor pesquisado, retornando true, independente se localizou ou 
não o item na lista.
Figura 10 - Busca de um elemento em uma estrutura de Lista Ligada
 Fonte: Comitê Editorial Digital Pages (2019).
 ◼ Remoção de um elemento
Para remover um elemento no No, usa-se o mesmo conceito da 
busca, ou seja, um loop para achar o No que contém o valor a ser 
removido. Assim, ao achar o No e criar um objeto temporário cha-
mado atual, é necessário fazer uma busca pelo seu No anterior. E, ao 
localizar, armazená-lo em aux e fazer a referência de aux na função 
setProximo() no valor do próximo de atual. Perceba que o No que ar-
mazena o 0 é lincado ao No que armazena o 10 e, automaticamente, 
o No que armazena o -1 é retirado da Lista.
05 -1 10
null
primeiroNo
20
ultimoNo
null
0 -1 10 75
primeiroNo
20
ultimoNo
0 -1 10 20
null
primeiroNo ultimoNo
aux
156
Figura 11 - Remoção de um elemento no No
 Fonte: Comitê Editorial Digital Pages (2019).
Lista Duplamente Ligada
A Lista Duplamente Ligada é uma evolução da Lista Ligada, pois a 
mesma apenas armazena o endereço do seu próximo e, caso ultra-
passe para o próximo na navegação, não consegue fazer o caminho 
de volta entre os Nodes.
O armazenamento do endereço se dá nos objetos próximo e 
anterior do Node, como nas figuras a seguir.
Figura 12 - Armazenamento do endereço
Fonte: Comitê Editorial Digital Pages (2019).
Figura 13 - Exemplo de referenciação
 Fonte: Comitê Editorial Digital Pages (2019).
-15 100 20 7
null
atual
primeiroNo ultimoNo
-15 100 20 7
null
atual
aux
primeiroNo ultimoNo
0 105 20 7
null
aux
ultimoNoprimeiroNo
próximovaloranterior
null
null
Node
nullnull
Primeiro nó Útimo nó
0 -1 10 20
157
 ◼ Inserção de um elemento
A inserção dos valores 5 e 7 nas extremidades se dá, primeiramente, 
pela criação do Node comos valores e, depois, são apontadas suas 
referências aos elementos da estrutura.
Figura 14 - Inserção de um elemento
 Fonte: Comitê Editorial Digital Pages (2019).
 ◼ Remoção de um elemento
Na primeira estrutura do algoritmo, é percorrido o elemento que se 
busca apagar e se armazena o endereço do No no objeto atual. Após 
localizar o objeto a ser removido, faz-se uma nova varredura, per-
correndo o objeto anterior ou atual, e armazena a referência em aux. 
Dessa maneira, ao localizar o aux, coloca-se o endereço do próximo 
No do atual em aux, liga-se o aux com o próximo do atual e, auto-
maticamente, o atual sai de memória.
Figura 15 - Remoção de um elemento
 Fonte: Comitê Editorial Digital Pages (2019).
null null
nullnull
Primeiro nó
Primeiro nó
Útimo nó
Útimo nó
5
5
-1
0
10
-1 20
20 7
10 7
null
null
null
null
null
null
Primeiro nó
Primeiro nó
Atual
Aux
Aux
Atual
Excluído -1
Primeiro nó
Útimo nó
Útimo nó
Útimo nó
5
5
5
-1
0
0
10
-1
-1
20
20
20 7
10
10
7
7
158
Código Lista Duplamente Ligada
A Lista Duplamente Ligada segue alguns padrões da Lista Ligada. 
Primeiramente, usa-se a classe Node, onde contém as referências 
anteriores e posteriores do No atual.
Na linha 3, o objeto autorreferenciável próximo aloca o en-
dereço do próximo No e o objeto autorreferenciável anterior aloca o 
endereço do No anterior para o primeiro No de uma estrutura. Dessa 
maneira, o item anterior será null enquanto o último No e o endere-
ço do próximo será null.
Figura 16 - Código da Lista Duplamente Ligada
Fonte: Comitê Editorial Digital Pages (2019).
Lista Collection
A lista desenvolvida no formato estático implementa a interface 
Collection, no código a seguir (linha 3), e importa o pacote util.Col-
lection que contém as classes que podem ser implementadas da Col-
lection como: Vector, ArrayList e LindekList, os quais fazem parte do 
formato sequencial ou linear de alocação dinâmica.
class Node {
 private Node proximo, anterior;
 private int valor;
 Node(int auxvalor, Node auxprox, Node auxant) {
 valor = auxvalor;
 proximo = auxprox;
 anterior = auxant;
 }
 public void setValor(int aux) { valor = aux; }
 
 public int getValor() { return valor; }
 
 public void setProximo(Node aux) { proximo = aux; }
 
 public Node getProximo() { return proximo; }
 
 public void setAnterior(Node aux) { anterior = aux; }
 
 public Node getAnterior() { return anterior; }
}
159
Figura 17 - Lista Collection
 Fonte: Comitê Editorial Digital Pages (2019).
160
DICA
Dessa maneira, na linha 11, utiliza-se o LinkedList e na ins-
tanciação poderia ser usado qualquer Collection sequencial, como 
Vector ou ArrayList, seguindo o código, usa-se o <Integer>. Com esse 
formato, coloca-se o tipo do primitivo ou objeto que irá ser utilizado 
na estrutura e, neste caso, o objeto col recebe somente valores do 
tipo inteiro.
Quando se usa a interface Collection, as funções são padroni-
zadas independente da estrutura utilizada, como:
 • Add – insere elementos;
 • Remove – remove elementos;
 • Constains – busca elementos na estrutura.
No código visto nas linhas 9 e 11, faz-se a instanciação. Já nas linhas 
13 e 14 são inseridos 100 valores na estrutura dentro do loop e a im-
pressão da estrutura é feita nas linhas 16 e 20, com a impressão via 
for-each na função “imprimir”.
Pilhas
A TAD (Tipo Abstrato de Dados) Pilha é uma variação da Lista Linear 
que possui características semelhantes a uma “pilha” do mundo 
real. Ela armazena os valores inseridos no formato de LIFO - Last in 
First Out (O último que entra é o primeiro a sair).
Como uma “Pilha de livros”, onde o primeiro a ser empi-
lhado é o último a ser acessado, segue um exemplo de empilha-
mento de dados.
161
Diagrama 1 - Exemplo de Empilhamento de Dados
Fonte: Comitê Editorial Digital Pages (2019).
A Pilha possui as seguintes operações:
 • push( X) – aloca ou adiciona o valor na estrutura Pilha;
 • pop() – desempilha ou remove o valor do topo da Pilha, retor-
nando o valor pela função;
 • peek() – acessa o topo da Pilha sem removê-lo;
 • isEmpty() – retorna o estado atual da Pilha se possuir itens 
alocados false, mas, se não possuir, retorna true;
 • isFull() – retorna true se a Pilha está com todos os espaços 
alocados, porém, para Pilhas que são de alocação dinâmica, 
não possui a função; isFull(), – somente as Pilhas que imple-
mentam o vetor.
162
Código da Pilha de Alocação Estática
Figura 18 - Código da Pilha com Alocação Estática
Fonte: Comitê Editorial Digital Pages (2019).
Observa-se na linha 5 o Construtor que recebe o tamanho máxi-
mo da Pilha para poder colocar os itens e, a partir daí, ele implementa 
um vetor com esse tamanho máximo e, a partir do momento que ele 
tem tamanho máximo, ele tem aquela quantidade de itens para poder 
colocar dentro do nosso vetor que está sendo implementado na Pilha.
Já na linha 10 temos a função isEmpty que verifica se o topo = 
-1. Isso significa que se o topo for -1 ela está vazia, então vai retornar 
true. Na linha 14 temos os isFull, ele verifica se a Pilha está cheia, ou 
seja, se o topo é equivalente ao número da quantidade de elementos do 
vetorPilha.length (o atributo que retorna o tamanho máximo do vetor).
O peek nada mais é do que o retorno do valor que está no índice topo 
da pilha na linha 18. Por outro lado, o método push tem a função de 
adicionar itens dentro da pilha, incrementando o topo e atribuindo 
valor na Pilha no índice topo. Já o método pop é a função para remo-
ver itens da Pilha, fazendo decremento no topo.
1 public class Pilha {
2 private int vetorPilha[];
3 private int topo;
4 // Inicia a pilha com Tamanho max
5 public Pilha(int max) {
6 vetorPilha = new int[max];
7 topo = -1;
8 }
9 // Verificação se existem Valores na Pilha
10 public boolean isEmpty() {
11 return (topo == -1);
12 }
13 // Retorna se a pilha está cheia ou não
14 public boolean isFull() {
15 return (topo == vetorPilha.length -1);
16 }
17 // Retorna o topo da pilha
18 public int pick() {
19 return vetorPilha[topo];
20 }
21 //Adicionar valor na pilha
22 public void push(int j) {
23 if (isFull()) {
24 topo++;
25 vetorPilha[topo] = j;
26 }
27 }
28 //Excluir valor da pilha
29 public int pop() {
30 return vetorPilha[topo--];
31 }
32 }
DEFINIÇÃO
163
Figura 19 - Código que usa a classe Pilha como estrutura de dados para ser implementada
Fonte: Comitê Editorial Digital Pages (2019).
Filas – implementações
As Filas são estruturas de dados ou TADs que armazenam no for-
mato FIFO. First-in-first-out, ou simplesmente FIFO, significa que o 
elemento que é inserido é o primeiro a ser removido, analogamente 
a uma fila de banco ou qualquer fila do mundo real.
Tabela 1 - A estrutura Fila
 Fonte: Comitê Editorial Digital Pages (2019).
class PrjPilha {
 public static void main(String[] args){
 Pilha pilha = new Pilha(5);
 
 pilha.push(10);
 pilha.push(20);
 pilha.push(30);
 pilha.push(40);
 
 System.out.println("valor do jogo"+pilha.pick());
 System.out.println("Está Vazia:"+pilha.isEmpty());
 System.out.println("Está cheia:"+pilha.isFull());
 while (!pilha.isEmpty()) {
 System.out.print(pilha.pop());
 }
 }
}
164
Os comportamentos padronizados da Fila são:
 • Queue(objeto) – insere o elemento objeto ou valor na Fila;
 • deQueue() – remove os elementos da Fila conforme ordem 
de entrada;
 • Peek() – assim como a Pilha, a Fila trabalha o conceito de 
topo, que nada mais é do que o elemento em evidência na es-
trutura (no caso da Fila, é o primeiro elemento que foi inseri-
do, enquanto, na Pilha, é o último elemento que foi inserido);
 • isEmpty() – é a função que retorna true para uma estrutura 
vazia e false para uma estrutura que já contém pelo menoso 
primeiro elemento inserido;
 • isFull() – é uma função que retorna booleano, ou seja, true 
para uma estrutura completa ou cheia e false caso possa inse-
rir mais elementos, considerando uma Fila de alocação está-
tica que possui tamanho fixo.
O código a seguir demonstra a aplicação do vetor[] no com-
portamento de uma Fila que implementa o formato FIFO. Além 
disso, a classe FilaEstática é uma estrutura que dá permissão para 
outros programas acessarem como objeto uma fila estática (estru-
tura com tamanho fixo) com tamanho passado via construtor. Per-
ceba que, na linha 7, tem-se o construtor que inicia a estrutura Fila 
com o tamanho passado pelo(a) programador(a).
As funções isEmpty e isFull retornam resultados booleanos, respec-
tivamente, se a estrutura está vazia e se a estrutura está cheia.
A função peek retorna a posição do elemento corrente da es-
trutura, que é sempre a posição 0 do vetor, pois, tratando-se da 
aplicação da FIFO, a posição mais importante da estrutura é o pri-
meiro elemento, como se vê na figura 20.
DICA
165
Figura 20 - Aplicação do Vetor
Fonte: Comitê Editorial Digital Pages (2019).
A função enQueue, ou enfileirar, recebe por parâmetro o 
argumento valor que insere no vetor privado o elemento na po-
sição qtdElementos, variável que controla a posição de quan-
tidades de elementos na fila. Ele se inicia com -1 e, conforme 
aumenta o número de elementos, incrementa e, quando remove 
elementos, decrementa, controlando a quantidade de elementos 
da Fila, o que o torna o principal parâmetro para saber se a Fila 
está cheia ou não.
1 public class FilaEstatica {
2 private int[] vFila;
3 private int qtdElementos;
4 
5 // Construção da fila Estática som tamanho fixo
6 public FilaEstatica(int tamanho) {
7 vFila = new int[tamanho];
8 qtdElementos = -1;
9 }
10 //Verificação se está vazia
11 public boolean isEmpty() {
12 return (qtdElementos == -1);
13 }
14 //Verificação se está cheia
15 public boolean isFull() {
16 return (qtdElementos == vFila.length - 1) ? true : false;
17 }
18 // Topo da fila
19 public int peak() {
20 return (!isEmpty()) ? vFila[0] : -1;
21 }
22 //Adicionar elementos FIFO
23 public void enQueue(int valor) {
24 if (!isFull()) {
25 qtdElementos++;
26 vFila[qtdElementos] = valor;
27 }
28 }
166
Figura 21 - Função enQueue
Fonte: Comitê Editorial Digital Pages (2019).
A função deQueue, ou desenfileirar, tem por responsabilidade 
o comportamento de retirar o elemento do vetor Fila e fazer com 
que todos os elementos avancem uma posição por meio do loop da 
linha 35. Já na linha 33, retorna o valor do primeiro elemento e in-
crementa a quantidade de elementos da Fila na linha 34.
A impressão da Fila se dá na função imprimir, que se refere aos 
valores da linha 47 no loop for-each. A classe Prj_FilaEstatica aplica a 
estrutura FilaEstatica e utiliza como estrutura de dados, assim, na linha 
5 se faz a instanciação, das linhas 6 a 9 se faz a inserção de elementos na 
Fila e na linha 11 se faz uma remoção e a impressão do valor da Fila.
Na inserção, são adicionados os elementos -1, 25, 5 e 7, res-
pectivamente. No caso da organização FIFO, o primeiro elemento 
se torna o -1 e, ao verificar seu peek ou removê-lo, será trabalhada 
sempre a primeira posição do vetor que no caso é 0 e está armaze-
nando nesse primeiro momento o -1.
Para a remoção, chama-se a função deQueue, na linha 11. Pri-
meiro, remove-se o elemento dentro da estrutura, juntamente com 
o incremento da quantidade de elementos da Fila e, após isso, retor-
na no System.out.println() o número -1. Assim, automaticamente, a 
estrutura dos dados muda dentro da Fila, mudando de -1, 25, 5 e 7 
para 25, 5 e 7, tornando agora o 25 o valor da primeira posição.
30 //Remover elementoi FIFO
31 public int deQueue() {
32 if (!isEmpty()){
33 int removido = vFila[0];
34 qtdElementos--;
35 for (int i = 0; i < qtdElementos; i++)
36 vFila[i] = vFila[i + 1];
37 return removido;
38 } else {
39 return -1;
40 }
41 }
42 //Impressão dos valores da Fila
43 public void imprimir()
44 {
45 for(int aux: vFila)
46 System.out.println(aux);
47 }
48 }
167
DICA
Figura 22 - Função deQueue
 Fonte: Comitê Editorial Digital Pages (2019).
De maneira geral, nessa classe que implementa a alocação 
estática existem algumas desvantagens: uma delas é a questão de 
inserção de elementos ultrapassarem o tamanho máximo do estipu-
lado na criação. Nesse caso, uma solução paliativa seria armazenar 
os itens em um objeto auxiliar e reinstanciar o objeto atual com um 
valor máximo maior em tempo de execução e, assim, inserir nova-
mente na estrutura os valores antigos e novos. No entanto, torna-se 
ineficiente, pois se trata de mais processamento para a aplicação e, 
dependendo do tamanho da nova estrutura, demora demais.
Para aplicações de pequeno porte, que não exijam volumes altos de 
informação, pode ser trabalhada a Fila estática. Uma grande vanta-
gem de trabalhar com o formato estático, tanto Pilha quanto Fila, é 
a própria aplicação do vetor que torna o código mais simples de ser 
implementado e reconhecido.
168
Collection Class Queue – Fila dinâmica
A Fila dinâmica é uma estrutura de dados que implementa os concei-
tos da Fila estática. A diferença se dá, conceitualmente, no tamanho 
máximo: como na estática, temos o tamanho fixo da estrutura na 
dinâmica. Nela os elementos podem ser inseridos e removidos sem 
a estrutura ter um tamanho fixo, tornando a Fila dinâmica em um 
formato melhor para trabalhar em tempo de execução, isso quando 
não se sabe a quantidade de elementos que deverão ser inseridos.
Além disso, é importante saber que a interface Queue está 
dentro da API Collection, implementando a alocação dinâmica com 
Node; possui diversas funções já embutidas nela, por exemplo, add, 
remove e peek – funções que poderiam ser implementadas na mão, 
mas, nesse formato, já estão prontas na interface, otimizando a 
produtividade ao programar. Nos imports desse projeto temos, nas 
linhas 2 e 3, a primeira referência à Fila dinâmica do projeto, onde 
se instancia, na linha 8, a interface Queue com o LinkedList e com o 
tipo Integer, que armazena números inteiros.
Das linhas 11 a 13, adicionam-se os valores 1, 2 e 3 por meio da 
própria função add da LinkedList. Assim, a linha 15 remove um item 
da Fila, a linha 16 retorna a quantidade de elementos dentro da Fila 
e a linha 17 retorna o valor booleano para a busca do valor 1 dentro da 
Fila com a função contains. É importante destacarmos que, no uso da 
Fila, são demonstradas, no programa, duas formas de navegar nos 
elementos dela nas linhas 19 a 22 e 24 a 29.
Figura 23 - Interface Queue
 Fonte: Comitê Editorial Digital Pages (2019).
169
Na primeira solução, que está nas linhas 19 a 22, utili-
za-se a função toAr- ray(), que retorna um vetor da fila e o ar-
mazena no vaux[] e, no loop, faz a varredura pelo vaux. Nessa 
solução ocorre a transformação de um objeto da API em vetor e 
pode-se manipulá-lo.
Já a segunda solução, a mais ideal, é usar o Padrão de Proje-
to Iterator. Os Designers Patterns (Padrões de Projeto) são soluções 
padronizadas para problemas recorrentes da programação. Em al-
gumas linguagens, deve-se implementar do zero e seguir apenas o 
conceito, mas, no caso do Java e de algumas outras linguagens, há o 
código pronto, sendo um deles o Iterator.
O Iterator é um padrão de projeto que, por meio do conceito de 
orientação a objetos, encapsula a estrutura de dados como uma co-
leção de elementos e permite percorrer todos da estrutura, ou seja, 
um padrão de solução para navegação em estruturas que não per-
mitem indexação, como o vetor, que, ao informar a posição, retorna 
o elemento vetor[posição]. O for-each é uma das variações de Itera-
tor, porém possui algumas funções queprecisam ser invocadas para 
uso, como na linha 1 se importa o Iterator.
Observe que, na linha 24, o Iterator deve ser instanciado com 
o nome do objeto que será percorrido com o “.iterator()”, onde as 
classes da API Collection implementam essa solução. Após ser ins-
tanciado, cria-se um objeto Iterator da estrutura de dados com o 
nome filaIterator.
No loop da linha 27, a filaIterator.hasNext() retorna true, en-
quanto houver elementos para navegação na estrutura, e seu acesso 
é por meio da função. next(), que retorna o elemento atual do objeto 
e aponta para o próximo da estrutura, caso houver; e retorna false 
caso não tenha, encerrando assim o laço de repetição, como se ob-
serva na figura 24.
DEFINIÇÃO
170
Figura 24 - O padrão Iterator
Fonte: Comitê Editorial Digital Pages (2019).
Árvores e suas generalizações
A Árvore é um tipo de estrutura abstrata de dados que comporta-se de 
forma semelhante a uma árvore, empregando conceitos de raiz e folhas. 
Também emprega em si fortemente o conceito de Node, ou Nó, como 
elemento em nível hierárquico. Lembre-se que, na hierarquia, comu-
mente os nós podem assumir representações como pai, filhos e irmãos.
O principal Nó da estrutura da Árvore é a raiz, o Nó inicial que 
dá acesso aos demais elementos da estrutura, ou seja, é o ponto ini-
cial em uma navegação e, a partir dele, pode-se navegar nos filhos 
e conjuntos de pais e filhos, chamados de conjuntos não vazios ou 
subárvores, como Node 1, Node 2 e Node n.
Diagrama 2 – A estrutura Node
Fonte: Comitê Editorial Digital Pages (2019).
NODE 1 NODE 2 NODE N
NODE RAIZ
171
De acordo com critérios de armazenamento, as árvores po-
dem formar ordenação de valores e elementos que façam com que 
alguns Nós sejam armazenados mais à direita ou à esquerda. No 
diagrama a seguir, tem-se a árvore Exemplo e inicia-se da Raiz de 
árvore que chama-se Node Raiz. Observe!
Diagrama 3 – Node Raiz
 Fonte: comitê editorial Digital Pages (2019).
Como você pode perceber, os filhos de Node Raiz são Node 1 e Node 
2; os filhos de Node 1 são Node 3 e 4 e, obviamente, o Node 1 é pai desses 
Nodes e o filho de Node 2 é o Node 5, tornando o Node 2 pai de Node 5.
A leitura dessa Árvore sempre indica o nome do pai e o nome dos 
filhos e vice-versa.
Observe que, após os filhos dos filhos, não há mais Nodes. 
Nessa situação, ocorre o conceito de folha, nomenclatura para as 
extremidades da estrutura da Árvore, onde muitos algoritmos utili-
zam o Node folha para fazer aplicações dentro da Árvore.
Filho de Node 2
Node
RaizRAIZ DA ÁRVORE
Fo
lh
as
FILHOS DE NODE RAIZ
FILHOS DE NODE 1
Node 1
Node 3 Node 4 Node 5
Node 2
DICA
172
As Árvores podem ser classificadas em hierárquica, diagra-
ma de inclusão, parênteses aninhados e representação encadeada, 
como se observa nos diagramas 4, 5, 6, 7 e figura 25.
Diagrama 4 - Árvore Hierárquica
 Fonte: Comitê Editorial Digital Pages (2019).
Diagrama 5 – Exemplo de Inclusão
 Fonte: Comitê Editorial Digital Pages (2019).
Figura 25 – Prênteses aninhados
 Fonte: Comitê Editorial Digital Pages (2019).
A
B C D
E F G H
I
A
B
HD I
E
G
C
F
(A (B (E)) (C (F) (G)) (D (H (I))))
173
Diagrama 6 - Adaptação do formato Árvore pra representação aninhada
 Fonte: Comitê Editorial Digital Pages (2019).
Diagrama 7 - Adaptação do formato Árvore para representação encadeada
 Fonte: Comitê Editorial Digital Pages (2019).
Pode-se observar que a representação do diagrama 5, passando para 
o formato da representação encadeada, ficaria como o diagrama 6.
12
10 15
1613
12
10
13 16
15
CURIOSIDADE
174
Terminologia da estrutura Árvore
As Árvores possuem várias propriedades e características que mui-
tos algoritmos utilizam para poder efetuar operações como bus-
ca, inserção, remoção, ordenação e classificação. Dito isto, abaixo 
abordaremos suas principais terminologias.
Nó
Estrutura referenciável que armazena valores dentro de uma árvo-
re, a qual possui apenas um pai, podendo possuir vários “irmãos”. 
Ela nunca apresenta dois pais ou ligação com seu irmão. Pensando 
nisso, abaixo listamos suas principais terminologias.
 • Arco – também chamado de vértice ou ligação, é o caminho 
entre dois Nós pais até os filhos.
 • Raiz – é o primeiro elemento Node ou Nó, que dá acesso a to-
dos os elementos da árvore.
 • Altura ou profundidade – é o nível do Nó folha ou terminal, 
somando +1.
 • Chave – é denominado chave o elemento que propõe valor ao 
elemento Nó. Em diversas situações a própria chave do Nó é 
seu valor.
 • Floresta – conjunto de 0 ou mais árvores.
 • Sub árvore – são conjuntos de Nós pais após a Raiz, poden-
do ser consideradas quaisquer Nós contendo sequência de 
outros Nós.
 • Pai – é o Nó que possui filhos ou irmãos. Assim, não sendo 
Raiz, não poderá ser folha, mas, sendo Raiz e não tendo filhos, 
não poderá ser pai, pois ele mesmo é a folha.
 • Filho – é o Nó que possui pai, podendo possuir irmãos ou ser 
um Nó folha.
175
 • Rótulo – nome do Nó, geralmente seu dado, valor ou elemento.
 • Grau de saída – número de filhos linkados a ele.
 • Grau de uma árvore – é o maior número de filhos de um Nó 
em toda a árvore.
 • Folha – são Nós que não possuem filhos, ou seja, possuem 
grau de saída 0, também chamados de Node terminal.
 • Nó interno – todos os Nós que possuem filhos ou grau de saí-
da maior ou igual a 1, ou seja, que não são um Nó terminal.
 • Caminho na árvore – é a interligação de Nós consecutivos, 
que traz a relação de hierarquia, por exemplo: “é pai de” ou “é 
filho de”. É o caminho do Nó Raiz até determinado Nó dentro 
da Árvore.
 • Comprimento do caminho – é o número de arco/vértice ou de 
ligações entre um Nó e outro.
 • Nível de um Nó – é a quantidade de arcos da Raiz até o Nó 
específico; no caso, a Raiz tem 0 arcos, seu nível é 0; sendo 
que um filho da Raiz possui um arco, então teria nível 1, e 
assim sucessivamente.
Veja a seguir exemplos de valores para cada propriedade da Árvore.
Nó: são todos os elementos Nós da estrutura.
Raiz: A.
Chave: do Nó A o valor é A, do Nó B o valor é B e, assim, sucessiva-
mente, pois o exemplo não deu uma identificação específica para 
cada Nó.
Grau de saída: A = 3, B = 1, C = 2, H = 1, E = 0 e I = 0.
EXEMPLO
176
Grau de uma Árvore: 3, pois A possui 3 filhos e os demais possuem 2 
e 1, que são inferiores.
Folhas ou Nó terminal: E, F, G e I.
Nó interno: A, B, C, D e H, ou seja, Nós que não são folhas.
Comprimento do caminho: A até G é 2 e A até I é 3.
Nível de um Nó: A = 0, B = 1, G = 2 e I = 3.
Altura ou profundidade: Último nível, que é 3 + 1 = 4.
Node – Implementação dinâmica
Nos comandos que implementam a Árvore, tem-se a classe Node 
como classe principal, por ser referenciável e ser moldada ao for-
mato de qualquer topologia, estrutura ou formas de organização.
Essa classe tem como regra armazenar o endereço do Node da 
esquerda e da direita, formando, assim, uma ligação entre os filhos 
para, a partir da ligação com eles, navegar por toda a estrutura.
No código a seguir tem-se o atributo-chave, que armazena a 
informação ou dado do elemento Node como Object, fazendo com que 
possa receber diversos valores. Porém, de forma geral, utiliza-se o 
Integer ao invés de Object na linha 2, como nos exemplos anteriores.
Figura 26 - Atributo-chave
 Fonte: Comitê Editorial Digital Pages (2019).
177
A seguir, há uma referência visual da classe Node, em que se 
observa onde estão sendo feitas as referências à classe da direita, da 
esquerda e à chave no meio. 
Figura 27 - Classe Node
Fonte: Comitê Editorial Digital Pages (2019).
Vetor – Implementação sequencial
Nem todas as Árvores trabalham com conceito de Node. Em alguns 
casos, pode-se implementar conceitos de Árvore de forma sequen-
cial, em que as chaves das Árvores são armazenadas em vetor e os 
seus filhos representam sempre um múltiplo do seu índice dentro 
do vetor. A fórmula para acesso aos filhos é utilizada por meio de 
seus índices: para acessar os filhos à direita, 2 * índice, e para osfilhos à esquerda, 2 * índice + 1. Veja um exemplo!
Diagrama 8 - Implementação Sequencial
 Fonte: Comitê Editorial Digital Pages (2019).
CHAVEESQUERDA DIREITA
1
3
65
2
4 null
vet[0]
1
vet[3]
4
vet[3]
4
vet[1]
2
vet[5]
6
vet[5]
6
vet[4]
5
vet[4]
5
vet[2]
3
vet[2]
3
vet[6]
null
vet[6]
null
178
Árvores binárias
Uma Árvore binária, ou binary tree, é uma aplicação de estrutura de 
Árvore com regras específicas, a saber:
 • o Nó só pode ter de 0 até 2 filhos;
 • os dois filhos de uma Árvore binária são chamados de filho à 
esquerda e filho à direita;
 • as subárvores de uma árvore binária são subárvores da direita 
ou da esquerda;
 • o filho à esquerda de um Nó tem o valor da chave menor que 
seu pai, já o filho à direita possui o valor da chave maior ou 
igual a seu pai;
 • uma Árvore vazia não contém elementos;
 • todos os elementos da Árvore são Nós e arcos.
Diagrama 9 - Árvore Binária
 Fonte: Comitê Editorial Digital Pages (2019).
5
7
64
3
2 8
Chave ou informação
Filhos à esquerda Filhos à direita
179
Tipos de Árvores binárias
 ◼ Árvore estritamente binária
Quando todos os Nós da Árvore possuem dois filhos ou zero sen-
do terminais.
Diagrama 10 – Exemplo de Árvore Estritamente Binária
 Fonte: Comitê Editorial Digital Pages (2019).
 ◼ Árvore binária completa ou cheia
São Árvores nas quais o último nível é uma subárvore vazia e, por 
esse motivo, possui a menor altura e todo o Nó termina no mesmo 
nível. A altura dessa Árvore pode ser calculada por fórmula.
Diagrama 11 - Exemplo de Árvore Binária Completa
 Fonte: Comitê Editorial Digital Pages (2019).
1
3
5
7
2
4
6
180
 ◼ Árvore binária balanceada
Esses tipos de Árvores são estruturas que têm como base a altura 
das subárvores em 1 e, a cada operação na árvore, tem-se seu balan-
ceamento, tornando a altura da Árvore sempre em 1.
Diagrama 12 - Exemplo de Árvore Binária Balanceada
 Fonte: Comitê Editorial Digital Pages (2019).
 ◼ Percurso na Árvore
Uma Árvore possui diversos tipos de elementos e organizações e, 
dependendo da forma que se armazenam os valores, ela pode pos-
suir formatos distintos. Porém não há uma indexação para que sai-
bamos os elementos ou estruturas que ela possui, ou seja, apenas 
por meio de uma visita ou percurso na estrutura pode-se saber 
quais elementos e chaves (dados) ela apresenta.
Existem algumas formas de percorrer os elementos de uma 
Árvore, que são:
 • pré-ordem;
 • in-ordem;
 • pós-ordem.
A travessia em pré-ordem, ou pré-fixa, inicia-se pela Raiz e 
percorre os Nós e subárvores à esquerda para depois fazer o mesmo 
percurso. Observe!
1
3
65
2
4
181
 Figura 28 - A travessia em pré-ordem
Fonte: Comitê Editorial Digital Pages (2019).
Já a travessia em in-ordem, ou intra-ordem, percorre a su-
bárvore à esquerda e, ao chegar na folha, volta para a Raiz e, em 
seguida, visita a subárvore à direita, assim como o respectivo código 
em Java para o percurso.
Figura 29 – A travessia in-ondem
Fonte: Comitê Editorial Digital Pages (2019).
B
C
E
D
F G
I
H
J
3º
6º
5º
4º
7º
8º
9º
2º
1º
B
C
E
D
F G
I
H
J
3º
6º
5º
4º
7º
8º
9º
2º
1º
182
Por fim, a travessia em pós-ordem, ou pós-fixa, percorre a 
subárvore à esquerda, depois a subárvore à direita e a Raiz. Por últi-
mo, o respectivo código em Java para o percurso.
Figura 29a - A travessia em pós-ordem
Fonte: Comitê Editorial Digital Pages (2019).
Figura 29b - A travessia em pós-ordem
 Fonte: Comitê Editorial Digital Pages (2019).
Árvores de busca
Uma das maiores aplicações e usos da estrutura Árvore é a bus-
ca. Há diversos algoritmos que organizam a estrutura de Árvores 
para maximizar a varredura e melhorar a eficiência do percurso 
na Árvore ao localizar um valor ou chave. A principal árvore para 
essa função é a árvore binária de busca, a qual, a partir de seu 
formato de organização, também possui variações. Veja a seguir 
cada uma delas.
B
C
E
D
F G
I
H
J
3º
6º
5º
4º
7º
8º
9º
2º
1º
183
 • Árvore 2-3: implementa a árvore binária, porém, na sua inser-
ção, em vez de armazenar apenas uma chave, pode armazenar 
um intervalo de chaves ou duas chaves, fazendo com que o Node 
possua dois atributos-chave para armazenar valores de um va-
lor inferior até um superior. Também nos links dos próximos 
filhos não se tem apenas o direito e esquerdo, mas também o 
filho do “meio”, tornando a árvore ternária, em vez de binária. 
Lembre-se que, a cada inserção, um Nó filho pode possuir mais 
de um valor na chave e, nesse intervalo, possuir filhos à direita, 
esquerda e meio, tornando a busca mais veloz por não precisar 
entrar em novos Nós pais para se aprofundar na Árvore.
 • Árvore AVL: é uma árvore de busca balanceada, ou seja, bus-
ca minimizar as comparações entre seus Nós rotacionando ou 
balanceando a árvore a cada inserção ou remoção, trazendo 
sempre o melhor formato entre os Nós da estrutura e tornando 
as alturas das subárvores à direita e à esquerda bem próximas.
 • Árvore rubro-negra: possui diversas funções já embutidas 
nela, como add, remove, contains, entre outras. Essas fun-
ções, que poderiam ser implementadas à mão, mas que nesse 
formato já estão prontas na classe Tree, fazem com que se ga-
nhe produtividade ao programar.
 • Árvore splay: é um tipo de árvore binária que transforma os 
Nós acessados em Raízes por meio de rotações, fazendo com 
que os elementos mais acessados tornem-se mais rapida-
mente localizáveis na busca.
Árvore binária e de busca
A Árvore de busca binária (abb) é uma aplicação da estrutura Ár-
vore que armazena suas chaves de forma que, a partir da Raiz, 
todos os elementos menores que sejam alocados na subárvore es-
querda e todos os elementos maiores sejam alocados na subárvore 
da direita, fazendo com que as buscas não dependam de algorit-
mos complexos, mas apenas de comparações entre maior ou me-
nor até o Nó terminal.
184
Caro(a) aluno(a), caso queira conhecer um pouco mais sobre Árvore 
binária, sugerimos que acesse: https://joaoarthurbm.github.io/eda/
posts/bst/.
Caro(a) aluno(a), chegamos ao final da nossa jornada de estudos. 
Neste material, aprendemos sobre o uso de algoritmos recursivos 
e a sua implementação. Além disso, apresentamos o código de al-
guns desses algoritmos. Vimos também os algoritmos de ordenação 
e como são implementados em vetores. Em seguida, entramos na 
área de Estrutura de Dados, apresentando várias estruturas dife-
rentes e os conceitos usados na criação delas.
Ao longo do nosso material, você deve ter aprendido que os códigos 
apresentados e as dicas de páginas que apresentam a implemen-
tação de várias dessas estruturas podem ajudar a entender melhor 
como elas funcionam.
Dito isto, sugerimos que tente implementar esses algoritmos usan-
do a linguagem Java. Lembre-se que apresentamos a Classe Collec-
tion para algumas dessas estruturas.
Esperamos ter contribuído com o seu aprendizado. Sucesso!
DICA
SINTETIZANDO
185
Referências
UNIDADE 1
FUGERY, Sergio. Programação Orientada a Objetos: Conceitos e 
técnicas. Editora Érica. 2014.
KAMIENSKI, C. A. . Introdução ao Paradigma de Orientação a Obje-
tos. Centro Federal de Educação Tecnológica da Paraíba - Diretoria 
de Ensino - Coordenação de Informática, 1996.
LAFORE, R. Estrutura de dados e algoritmos em Java. Rio de Janei-
ro: Ciência Moderna, 2004.
PROGRAMAÇÃO Orientada a Objetos (Parte 12): a classe Object e 
seus métodos. Postado por Carlos Emilio Padilla Severo. (10min. 
11s.). son. color. port. Disponível em: <https://www.youtube.com/
watch?v=2ob3rYxpUlE>. Acesso em: 03 jun. 2020.
SANTOS, Rafael. Introdução à programação orientada a objetos 
usando JAVA. 4. reimp. Rio de Janeiro: Elsevier, 2011.
UNIDADE 2
BATISTA, R. S.; MORAES, R. A. Introdução à programação orientada 
a objetos. Teresina: Instituto Federal de Educação, Ciência e Tecno-
logia do Piauí - IFPI, 2013. 
CARVALHO, V. A.; TEIXEIRA, G. F. Programação orientada a objetos: 
curso técnico em informática. Colatina: Instituto Federal de Educa-ção, Ciência e Tecnologia do Espírito Santo – IFES, 2012. Disponível 
em: <http://redeetec.mec.gov.br/images/stories/pdf/eixo_infor_
comun/tec_inf/081112_progr_obj.pdf>. Acesso em: 08 jun. 2020.
MENDES, D. R. Programação Java com ênfase em orientação a ob-
jetos. -. São Paulo: Novatec, 2009.
MOREIRA NETO, O. Entendendo e dominando o Java. 3. ed. São 
Paulo: Digerati, 2009. 
SANTOS, R. Introdução à programação orientada a objetos usando 
Java. 2. ed. São Paulo: Elsevier, 2013.
186
LAFORE, R. Estrutura de dados e algoritmos em Java. Rio de Janei-
ro: Ciência Moderna, 2004.
ORACLE. Tecnologias Java. 2019. Disponível em: <https://www.
oracle.com/br/java/technologies/>. Acesso em: 25 mar. 2019.
TIOBE. TIOBE index for march 2019. Disponível em: <https://www.
tiobe.com/tiobeindex/>. Acesso em: 25 mar. 2019.
UNIDADE 3
BEDER, D. M. Introdução à programação orientada a objetos em Java. 
1. ed. São Paulo: EDUFSCar. 2014. Disponível em: <http://livresaber.
sead.ufscar.br:8080/ jspui/bitstream/123456789/2659/1/SI_Ednal-
do_ProgramacaoOrientadaObj_2. pdf> Acesso em 14 abr. 2020.
CURSO de Java 42: orientação a objetos: palavra-chave final. Pos-
tado por: Loia- ne Groner. (12min. 0s.). son. color. port. Disponível 
em: <https://youtu.be/858FJ6D- QRVg>. Acesso em: 16 jun. 2020.
JAVA8 - aula 2 -expressão lambdas. Postado por eXcript. (5min. 
44s.). son. color. port. Disponível em: <https://www.youtube.com/
watch?v=4EyhqB-JIXs&list=PLes- CEcYj003SbwnNhQ9eyF7I-
jPlEK0uVg&index=2>. Acesso em: 16 jun. 2020.
KAMIENSKI, C. A. . Introdução ao Paradigma de Orientação a Obje-
tos. Centro Federal de Educação Tecnológica da Paraíba - Diretoria 
de Ensino - Coordenação de Informática, 1996.
KNOERNSCHILD, K. Java design: objects, UML, and process. 1. ed. 
Indianópolis: Pearson Education Corporate, 2001.
RICARTE, I. L. M. Programação orientada a objetos: uma aborda-
gem com Java. Campinas: Unicamp, 2001. Disponível em: <http://
www.dca.fee.unicamp.br/cur- sos/PooJava/Aulas/poojava.pdf>. 
Acesso em: 10 jun. 2020. 
SANTOS, R. Introdução à programação orientada a objetos usando 
Java. Rio de Janeiro: Elsevier, 2011.
UNIDADE 4
BEDER, D. M. Introdução à programação orientada a objetos em Java. 
1. ed. São Paulo: EDUFSCar. 2014. Disponível em: <http://livresaber.
187
sead.ufscar.br:8080/jspui/bitstream/123456789/2659/1/SI_Ednal-
do_ProgramacaoOrientadaObj_2.pdf> Acesso em 14 abr. 2020.
CURSO de Java 42: orientação a objetos - palavra-chave final. Pos-
tado por: Loiane Groner. (12min. 0s.). son. color. port. Disponível 
em: <https://www.youtube.com/watch?v=858FJ6DQRVg>. Acesso 
em: 16 jun. 2020.
JAVA8 - aula 2 - expressão lambdas. Postado por eXcript. (5min. 44s.). 
son. color. port. Disponível em: <https://www.youtube.com/watch?-
v=4EyhqB-JIXs&list=PLes-CEcYj003SbwnNhQ9eyF7IjPlEK0uVg&in-
dex=2>. Acesso em: 16 jun. 2020.
KNOERNSCHILD, K. Java design: objects, UML, and process. 1. ed. In-
dianópolis: Pearson Education Corporate, 2001.
SANTOS, R. Introdução à programação orientada a objetos usando 
Java. Rio de Janeiro: Elsevier, 2011.

Mais conteúdos dessa disciplina