Você está na página 1de 285

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.

com
julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 2

LISTA DE FIGURAS

Figura 7.1 – Exemplo tabelas livro e editora .............................................................7


Figura 7.2 – Estrutura JDBC .....................................................................................9
Figura 7.3 – Papel do Driver Manager.......................................................................10
Figura 7.4 – Classes e Interfaces do arquivo rt.jar ....................................................11
Figura 7.5 – Criando uma tabela ...............................................................................13
Figura 7.6 – Criando uma tabela - Parte 2 ................................................................13
Figura 7.7 – Tabela TAB_COLABORADOR ..............................................................14
Figura 7.8 – Criando uma sequência ........................................................................14
Figura 7.9 – Criando uma sequência – Parte 2 .........................................................15
Figura 7.10 – Botão para executar os comandos SQL ..............................................16
Figura 7.11 – Resultado da execução do comando select ........................................17
Figura 7.12 – Resultado da execução .......................................................................17
Figura 7.13 – Resultado da alteração do registro na tabela ......................................20
Figura 7.14 – Atualização de um registro da tabela TAB_COLABORADOR.............20
Figura 7.15 – Criando um novo projeto Java.............................................................21
Figura 7.16 – Criando uma pasta para o driver do Oracle – Parte 1 .........................22
Figura 7.17 – Criando uma pasta para o driver do Oracle – Parte 2 .........................22
Figura 7.18 – Adicionando o driver do Oracle no projeto ..........................................23
Figura 7.19 – Processo transacional .........................................................................48
Figura 7.20 – Exemplo de transação atômica. ..........................................................49
Figura 7.21 – Camada de acesso a dados da aplicação (DAO). ...............................52

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 3

LISTA DE QUADROS

Quadro 7.1 – Classe e Interfaces do JDBC...............................................................10


Quadro 7.2 – Operadores lógicos .............................................................................19
Quadro 7.3 – JDBC Drivers e URL String. ................................................................26

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 4

LISTA DE TABELAS

Tabela 7.1 – TABELA WHERE CONDICAO1 ...........................................................18

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 5

SUMÁRIO

7 ACESSO AO BANCO DE DADOS .........................................................................6


7.1 Introdução ...........................................................................................................6
7.1 Java Database Connectivity ................................................................................8
7.2 Banco de dados oracle e comandos sql ..............................................................12
7.2.1 Cadastrando informações na tabela .................................................................15
7.2.2 Leitura de dados de uma tabela .......................................................................17
7.2.3 Atualizando valores na tabela ..........................................................................20
7.2.4 Remoção de registros de uma tabela (Delete) .................................................21
7.2.5 Conectando a base de dados...........................................................................21
7.2.6 Statements .......................................................................................................26
7.2.7 CallableStatement ............................................................................................31
7.3 Controle transacional...........................................................................................48
7.3.1 Transação ........................................................................................................48
7.4 Design patterns ...................................................................................................51
7.4.1 Data Access Object (DAO) ...............................................................................52
7.4.2 DAO Factory.....................................................................................................65
7.4.3 Abstract Factory ...............................................................................................68
7.4.4 Singleton ..........................................................................................................71
REFERÊNCIAS .........................................................................................................74

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 6

7 ACESSO AO BANCO DE DADOS

7.1 Introdução

A maioria dos sistemas precisa armazenar dados e informações para serem


recuperados posteriormente. Por exemplo, um sistema bancário precisa registrar
várias informações, entre eles os saques e depósitos para manter o saldo da conta
atualizada. Um sistema de vendas online deve armazenar todos os dados de seus
clientes, produtos, fornecedores, vendas etc.

Uma solução é armazenar as informações em arquivos textos e planilhas.


Porém, por se tratar de uma grande quantidade de informações, é difícil de manter o
gerenciamento dos dados, e com certeza qualquer acesso a essas informações será
com pouca performance e utilizando bastante processamento. Outra opção é utilizar
sistemas especializados no armazenamento de dados que oferecem mais
funcionalidades e recursos avançados, como backup e buscas mais eficientes. Esses
sistemas são conhecidos como: Sistemas Gerenciadores de Banco de Dados –
SGBD.

Um Sistema de Gerenciamento de Banco de Dados é um conjunto de


programas de computador responsáveis pelo gerenciamento de uma base de dados.
Seu principal objetivo é retirar da aplicação cliente a responsabilidade de gerenciar o
acesso, manipulação e a organização dos dados. O SGBD disponibiliza uma interface
para que seus clientes possam realizar as operações de inclusão, alteração, exclusão
e consulta de dados.

Os principais SGBDs utilizados nas empresas aplicam o Modelo Relacional


para armazenar informações, e a linguagem SQL é utilizada para realizar as
operações nas bases de dados.

Os principais SGBDs utilizados no mercado são:

 Oracle Database.

 Microsoft SQL Server.

 PostgreSQL.

 Sysbase.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 7

 MySQL Server.

 Apache Derby.

O Modelo Relacional é um modelo de dados baseados em entidades e


relacionamentos. Uma tabela armazena as informações relevantes da entidade. A
atribuição de valores de uma entidade constrói um registro da tabela. A relação
determina como cada registro da tabela se associa a registros de outras tabelas. Uma
tabela é formada por registros (linhas) e os registros são formados por campos
(colunas).

A figura abaixo exemplifica duas tabelas: Livro e Editora.

Figura 7.1 – Exemplo tabelas livro e editora


Fonte: Fiap (2016)

A tabela TAB_LIVRO armazena as informações: ISBN, nome, número de


páginas e código da editora. Ela possui três registros (linhas): Aprenda Java, SQL
Básico e Banco de Dados. Já a tabela TAB_EDITORA armazena somente o código
da editora e o nome. E possui somente dois registros, Editora FIAP e Editora Nova.
Perceba que a coluna COD_EDITORA da tabela TAB_LIVRO armazena o
relacionamento dos livros com a editora. Por exemplo, o livro Aprenda Java possui a
editora de código 1, ou seja, a Editora FIAP.

As tabelas normalmente têm uma chave primária, que é um identificador único


que garante que nenhum registro será duplicado. No nosso exemplo, a coluna ISBN
da tabela TAB_LIVRO e o COD_EDITORA da tabela TAB_EDITORA são as colunas
que armazenam a chave primária de suas respectivas tabelas.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 8

Structured Query Language (SQL) ou Linguagem de Consulta Estruturada é


uma linguagem internacional de pesquisa declarativa padrão para banco de dados
relacional, através dela os principais SGBDs interagem com os bancos de dados.

Alguns dos principais comandos SQL para a manipulação de dados são:


INSERT (inserção), UPDATE (atualização), SELECT (consulta), DELETE (exclusão).
O SQL possibilita também criar tabelas, relações, controle de acesso etc.

Os sistemas desenvolvidos na plataforma Java comunicam-se com o SGBD e


manipulam seus dados utilizando a API Java DataBase Connectivity (JDBC).

7.1 Java Database Connectivity

O Java Database Connectivity é uma API (Application Programming Interface),


um conjunto de regras que permite uma padronização no acesso aos diversos SGDBs
disponíveis no mercado. Para evitar que cada banco tenha a sua própria API, o Java
Database Connectivity (JDBC) revela um conjunto de interfaces bem definidas que
devem ser implementadas pelas empresas fornecedoras de SGDB e que deseja ser
compatível à plataforma Java.

Dessa forma, são os SGDBs que se adaptam à plataforma Java, através da


implementação de um JDBC, e não o contrário. Com essa padronização, o
desenvolvedor não precisa se preocupar caso precise alterar um sistema para
suportar um novo Banco de Dados (SGDB), como existe essa padronização, basta
trocar as bibliotecas de acesso de um banco de dados pelo outro. Todo o código
implementado para sistema será o mesmo, pois as duas bibliotecas de acesso aos
bancos de dados seguem os mesmos padrões.

Essas bibliotecas de classes que permitem a integração de um SGDB à


aplicação Java são chamadas de Driver. Geralmente, as empresas fornecedoras de
SGDBs oferecem o driver de conexão que seguem às especificações JDBC.

A figura abaixo apresenta a estrutura JDBC:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 9

Figura 7.2 – Estrutura JDBC


Fonte: Fiap (2016)

Na figura é possível observar que a estrutura de classes é a mesma,


independentemente do SGDB que será utilizado (Oracle, Microsoft, Sybase). Nesta
estrutura, uma das poucas classes que é implementada é a DriverManager,
responsável por identificar o conjunto de bibliotecas (driver) que será utilizada: Oracle
Driver, JDBC-ODBC Driver, Sybase Driver.

No quadro abaixo são apresentadas as principais interfaces e a classe principal


que são utilizadas para acesso ao banco de dados através dos padrões JDBC:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 10

Quadro 7.1 – Classe e Interfaces do JDBC


Fonte: Fiap (2016)

As classes para a manipulação de um Banco de Dados estão no pacote


java.sql. Para se conectar a um Banco de Dados (SGDB) é preciso solicitar a abertura
de uma conexão com o Banco de Dados utilizando o Driver Manager, o gerenciador
de drivers. Caso o Driver Manager consiga estabelecer uma conexão com o SGDB,
um objeto do tipo java.sql.Connection é retornado, caso contrário, uma exceção é
gerada.

O Driver Manager é responsável por encontrar o driver que será utilizado na


aplicação. Quando uma implementação (driver) é carregada, ela é registrada
utilizando o Driver Manager. A partir do Driver Manager serão criadas as conexões
para a base de dados utilizando o método getConnection() que recebe uma String que
identifica qual banco de dados vamos conectar.

Figura 7.3 – Papel do Driver Manager


Fonte: Fiap (2016)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 11

Após a conexão, é possível utilizar os objetos do tipo java.sql.Statement,


java.sql.PreparedStatement, java.sql.CallableStatement para executar comandos
SQL no SGDB, que veremos adiante.

Todas as interfaces e classes da estrutura do JDBC podem ser encontradas no


arquivo rt.jar, contido no pacote JDK do Java:

Figura 7.4 – Classes e Interfaces do arquivo rt.jar


Fonte: Fiap (2016)

Desenvolver sistemas que acessam banco de dados segue alguns passos em


comum, independentemente da linguagem de programação. Podemos fazer uma
analogia para entender esses passos: para realizar um telefonema é preciso
primeiramente ter o número de telefone da pessoa com a qual queremos conversar.
Assim, podemos discar o número em um aparelho telefônico. Se o destinatário estiver
disponível, ele atenderá a ligação e assim a conexão estará feita. Depois disso, é
possível transmitir informações. No final, vamos desligar a ligação, finalizando a
conexão.

Para a comunicação de um sistema a um banco de dados, o processo é o


mesmo: primeiro, é necessário ter o “número” do banco de dados destinatário,
considerando o endereço de IP (Internet Protocol) como endereço físico e a porta
como endereço lógico. Com o banco disponível, vamos obter uma conexão para
realizar a comunicação. Através da conexão é possível enviar comandos SQL
(Structured Query Language), que serão executados no banco de dados. Por fim, a
conexão é fechada, encerrando-se o processo.

Outro ponto importante no processo da comunicação com o banco de dados é


o tratamento dos possíveis problemas que podem ocorrer. Assim como em uma
ligação, problemas de conexão e comunicação podem acontecer, a diferença é que

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 12

na ligação existe a ação direta do usuário, já na programação o próprio programa deve


prever e tratar as possíveis situações de erro.

Agora que sabemos os passos para a conexão e comunicação com o banco de


dados, vamos criar uma base de dados e uma tabela. Para isso, vamos utilizar o banco
de dados Oracle e a ferramenta Oracle Developer.

7.2 Banco de dados oracle e comandos sql

Vamos começar com o banco de dados. Primeiro vamos nos conectar à base
de dados Oracle utilizando a ferramenta Oracle Developer.

Conecte a base de dados utilizando as seguintes configurações. Depois de


conectado, é o momento de criar a primeira tabela para armazenar os dados dos
colaboradores de uma empresa, a qual deverá conter as seguintes colunas:

 CODIGO_COLABORADOR: chave primária da tabela, campo obrigatório e


com valores únicos.

 NOME: nome do colaborador.

 EMAIL: e-mail do funcionário.

 SALARIO: valor do salário do colaborador.

 DATA_CONTRATACAO: data de contratação.

Para isso, podemos criar a tabela utilizando os comandos SQL (CREATE


TABLE) ou realizá-la de forma visual, através do Oracle Developer.

Vamos utilizar a forma visual. Primeiro, procure a área de conexões no Oracle


Developer, do lado esquerdo, clique com o botão direito do mouse em cima de
“Tabelas” e escolha a opção “Nova Tabela”, conforme a figura abaixo:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 13

Figura 7.5 – Criando uma tabela


Fonte: Fiap (2016)

Agora, configure a nova tabela com o nome TAB_COLADORADOR e adicione


as colunas, conforme a figura abaixo:

Figura 7.6 – Criando uma tabela - Parte 2


Fonte: Fiap (2016)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 14

Configure o nome e o tipo de dado de cada coluna. Observe que a coluna


CODIGO_COLABORADOR está marcada como chave primária e a coluna NOME
está marcada como obrigatória. Foram definidos também os tamanhos para cada uma
as colunas, menos a coluna de data. Finalize clicando no botão OK.

Dentro da área de conexão, na área de tabelas, procure pela tabela


TAB_COLABORADOR, e dê dois cliques para visualizá-la:

Figura 7.7 – Tabela TAB_COLABORADOR


Fonte: Fiap (2016)

Pronto! A tabela está criada! Agora vamos criar uma sequence para gerar os
valores do código do colaborador. Para isso, vá novamente à área de conexões e
procure por “Sequências”, clique com o botão direito do mouse e escolha a opção
“Nova Sequencia”, conforme a figura abaixo:

Figura 7.8 – Criando uma sequência


Fonte: Fiap (2016)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 15

Configure o nome da sequência como SQ_COLABORADOR e nas


propriedades faça a sequência começar com 1 e incrementar de 1 em 1.

Figura 7.9 – Criando uma sequência – Parte 2


Fonte: Fiap (2016)

Agora sim, estamos prontos para começar! O próximo passo é conhecer alguns
comandos básicos para a manipulação de informações da tabela.

As operações básicas para manipular os dados de uma tabela são: inserir,


consultar, alterar e remover. Essas operações são realizadas através de uma
linguagem denominada SQL (Structured Query Language). Essa linguagem oferece
quatro comandos básicos que formam o CRUD: Create (inserir), Read (consultar),
Update (alterar) e Delete (remover).

7.2.1 Cadastrando informações na tabela

Através do comando INSERT é possível cadastrar um registro em uma tabela.


Podemos utilizá-la de duas formas:

A primeira é informando somente os valores para as colunas, assim, a ordem


dos valores será inserida na ordem das colunas na tabela:

INSERT INTO TABELA VALUES (VALOR1, VALOR2, VALOR3, ...);

A segunda é informando a coluna e os valores que serão cadastrados:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 16

INSERT INTO TABELA (COLUNA1, COLUNA2, COLUNA3, ...) VALUES


(VALOR1, VALOR2, VALOR3, ...);

O resultado final é o mesmo, o mais indicado é utilizar a segunda opção, pois


caso a estrutura da tabela seja alterada, os valores ainda serão inseridos nas colunas
corretas.

INSERT INTO TAB_COLABORADOR (CODIGO_COLABORADOR, NOME,


EMAIL, SALARIO, DATA_CONTRATACAO) VALUES (SQ_COLABORADOR
.NEXTVAL, ‘Thiago’ , ‘thiagoyama@gmail.com’ , 1500, TO_DATE (‘10/10;2010’ ,
‘dd/mm/yyy’));

O código abaixo apresenta um exemplo de cadastro de um registro na tabela


TAB_COLABORADOR:

Note que utilizamos a sequência SQ_COLABORADOR para gerar um novo


código para o registro. (SQ_COLABORADOR.NEXTVAL).

Outro detalhe é a função TO_DATE, que converte um texto para uma data:
TO_DATE(‘10/10/2010’,’dd/mm/yyyy’). O primeiro valor é a String que será convertida
para data e o segundo é o formato (máscara) da data que foi informada:

 DD – Day (dois dígitos para o dia).

 MM – Month (dois dígitos para mês).

 YYYY – Year (quatro dígitos para o ano).

Para executar um comando SQL no Oracle SQL Developer, utilize o botão


execute ou o atalho CTR + ENTER:

Figura 7.10 – Botão para executar os comandos SQL


Fonte: Fiap (2016)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 17

7.2.2 Leitura de dados de uma tabela

Para recuperar os registros de uma ou mais tabelas utilizamos o comando


SELECT. A sua sintaxe básica é:

SELECT COLUNA1, COLUNA2 FROM TABELA;

A primeira parte da instrução especifica as colunas que queremos recuperar


(SELECT COLUNA1, COLUNA2), a segunda parte define a tabela (FROM TABELA).
Dessa forma, esse comando recupera as colunas especificadas de todos os registros
armazenados na tabela.

É possível utilizar o caractere “*” (asterisco) para retornar todas as colunas de


uma tabela:

SELECT * FROM TABELA;

O exemplo abaixo recupera as colunas NOME e EMAIL de todos os registros


da tabela TAB_COLABORADOR:

SELECT NOME, EMAIL FROM TAB_COLABORADOR;

Resultado da execução do comando SQL:

Figura 7.11 – Resultado da execução do comando select


Fonte: Fiap (2016)

Para recuperar todas as colunas da tabela podemos utilizar o comando:

SELECT * FROM TAB_COLABORADOR;

O resultado da execução será:

Figura 7.12 – Resultado da execução


Fonte: Fiap (2016)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 18

Por enquanto, a nossa busca sempre retorna todos os registros. Imagine se


uma tabela armazena milhares de registros ou se precisamos recuperar um registro
específico da tabela. Por exemplo: um colaborador pelo seu código, ou todos os
colaboradores que recebem um salário maior do que um determinado valor.

Para isso, precisamos adicionar filtros nas nossas buscas. Esses filtros
permitem recuperar os registros de acordo com condições, além de trazer registros
mais específicos, também utiliza menos capacidade processamento. Observe o
exemplo abaixo:

 Buscar todos os colaboradores contratados em um determinado ano.

 Buscar todos os colaboradores que têm um salário menor do que um valor.

 Buscar todos os colaboradores que foram contratados em um ano


específico e têm um salário menor do que um valor.

Dessa forma, precisamos colocar mais uma cláusula no comando SELECT: a


cláusula WHERE:

SELECT * FROM TABELA WHERE CONDICAO1;

Para criar uma condição, precisamos utilizar os operadores relacionais:

Tabela 7.1 – TABELA WHERE CONDICAO1

Fonte: Fiap (2016)

Exemplos:

 Buscar todos os colaboradores que têm salário maior do que R$1.000,00:

SELECT * FROM TAB_COLABORADOR WHERE SALARIO > 1000;

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 19

 Buscar o colaborador que possui o código igual a 1:

SELECT * FROM TAB_COLABORADOR WHERE


CODIGO_COLABORADOR = 1;

 Buscar todos os colaboradores que possuem o nome igual a “Thiago”:

SELECT * FROM TAB_COLABORADOR WHERE NOME = 'Thiago';

Às vezes são necessárias duas condições para filtrar uma busca. Por exemplo:
buscar todos os colaboradores que têm o salário menor do que R$ 1.500,00 e que
foram contratados antes do ano 2000. Para isso, será necessário utilizar os
operadores lógicos:

Quadro 7.2 – Operadores lógicos


Fonte: Fiap (2016)

Exemplos:

 Buscar todos os colaboradores que têm um salário menor do que


R$3.000,00 e foram contratados antes do dia 10/10/2015:

SELECT * FROM TAB_COLABORADOR WHERE SALARIO < 3000


AND DATA_CONTRATACAO < TO_DATE('10/10/2015','dd/mm/yyyy');

 Buscar todos os colaboradores que têm um salário menor do que


R$3.000,00 ou foram contratados antes do dia 10/10/2015:

SELECT * FROM TAB_COLABORADOR WHERE SALARIO < 3000 OR


DATA_CONTRATACAO < TO_DATE('10/10/2015','dd/mm/yyyy');

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 20

7.2.3 Atualizando valores na tabela

Para atualizar os valores de um registro de uma tabela, precisamos utilizar o


comando UPDATE. Esse comando permite a alteração do conteúdo de um ou mais
campos (colunas) pertencentes a um ou mais registros (linhas) de uma tabela.

A sintaxe básica é:

UPDATE TABELA SET COLUNA1 = NOVO_VALOR1, COLUNA2 =


NOVO_VALOR2 WHERE CONDIÇÃO.

A cláusula WHERE é utilizada para restringir os registros que serão alterados,


pois caso não seja utilizada a cláusula WHERE, todos os registros serão alterados.

Exemplo:

UPDATE TAB_COLABORADOR SET NOME = 'Thiago Yamamoto' WHERE


CODIGO_COLABORADOR = 1;

No exemplo acima, o colaborador com o código igual a 1 teve o seu nome


alterado para ‘Thiago Yamamoto’. Após a execução do comando UPDATE, foi
realizado uma busca (SELECT) para visualizar a alteração na tabela.

Figura 7.13 – Resultado da alteração do registro na tabela


Fonte: Fiap (2016)

É possível alterar várias colunas em um mesmo comando UPDATE, basta


separar as colunas por vírgula:

UPDATE TAB_COLABORADOR SET EMAIL = 'thiago@fiap.com.br',


SALARIO = 2000 WHERE CODIGO_COLABORADOR = 1;

O comando acima altera as colunas EMAIL e SALARIO do colaborador com


código igual a 1. O resultado da alteração pode ser visualizado na figura abaixo:

Figura 7.14 – Atualização de um registro da tabela TAB_COLABORADOR


Fonte: Fiap (2016)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 21

7.2.4 Remoção de registros de uma tabela (Delete)

Para remover um registro de uma tabela é utilizado o comando delete:

DELETE FROM TABELA WHERE CONDIÇÃO;

Esse comando também precisa de condição, pois sem ela, todos os registros
da tabela serão apagados.

Exemplo:

DELETE FROM TAB_COLABORADOR WHERE CODIGO_COLABORADOR


= 1;

No exemplo acima foi removido o registro que possui o


CODIGO_COLABORADOR igual a 1. Agora que conhecemos um pouco dos
comandos básicos do SQL, vamos começar a programação Java!

7.2.5 Conectando a base de dados

Primeiro, vamos criar um novo projeto para manipular a base de dados. Para
isso, vá à opção “File” do menu e escolha “New” e depois “Java Project”, conforme a
figura abaixo:

Figura 7.15 – Criando um novo projeto Java


Fonte: Fiap (2016)

Dê um nome ao projeto e finalize o processo.

O próximo passo é configurar o ambiente. Como explicado anteriormente,


precisamos do driver JDBC do banco de dados Oracle. Dessa forma, vamos adicionar
o arquivo .jar no nosso projeto.

Para isso, crie uma pasta chamada lib e adicione o driver do Oracle, conforme
os seguintes passos:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 22

Crie uma nova pasta dentro do projeto.

Figura 7.16 – Criando uma pasta para o driver do Oracle – Parte 1


Fonte: Fiap (2016)

Dê um nome para a pasta (como sugestão “lib”) e finalize o processo.

Figura 7.17 – Criando uma pasta para o driver do Oracle – Parte 2


Fonte: Fiap (2016)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 23

Agora copie o driver do Oracle para dentro da pasta e adicione no build path do
projeto, para que as classes e interfaces do driver fiquem disponíveis para o uso
dentro do projeto. Para adicionar no build path, clique com o botão direito do mouse
no driver e escolha: “Build Path” -> “Add to Build Path”, conforme a figura abaixo:

Figura 7.18 – Adicionando o driver do Oracle no projeto


Fonte: Fiap (2016)

Agora sim, estamos prontos para começar a desenvolver!

Primeiro vamos estabelecer uma conexão com a base de dados. Precisamos


criar um objeto do tipo Connection que representará a conexão. Depois, estaremos
aptos a realizar qualquer operação (Cadastrar, Atualizar, Apagar e Buscar) na base
de dados.

Abaixo, apresentamos uma classe de teste que realiza a conexão com o banco
de dados:

package br.com.fiap.teste;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class TesteView {

public static void main(String[] args) {


try {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 24

//Registra o Driver

Class.forName("oracle.jdbc.driver.OracleDriver");

//Abre uma conexão


Connection conexao =
DriverManager.getConnection(

"jdbc:oracle:thin:@192.168.60.15:1521:ORCL", "OPS$PF0392",
"123456");

System.out.println("Conectado!");

//Fecha a conexão
conexao.close();

//Tratamento de erro
} catch (SQLException e) {
System.err.println("Não foi possível
conectar no Banco de Dados");
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.err.println("O Driver JDBC não foi
encontrado!");
e.printStackTrace();
}
}
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 25

O primeiro passo para obtermos uma conexão é registrar o driver que será
utilizado. Depois, através do método DriverManager.getConnection() obtemos uma
conexão com o banco de dados. Os parâmetros desse método são:

 A URL para acessar o banco de dados.

 Usuário do banco de dados.

 Senha do banco de dados.

Após obter a conexão é possível enviar qualquer comando SQL para realizar
alguma operação no banco de dados. Veremos isso daqui a pouco. Depois de enviar
as instruções, devemos fechar a conexão utilizando o método close().

Observe que foi realizado o tratamento de dois possíveis erros. O catch do


SQLException trata o erro de conexão com o banco de dados. Já a exceção
ClassNotFoundException pode ocorrer quando a aplicação não encontra o driver do
oracle.

Agora vamos discutir um pouco sobre cada uma das classes e interfaces que
iremos utilizar para se conectar e realizar as operações na base de dados:

DriverManager:

Determina qual driver de conexão será utilizado. Funciona como uma ponte
entre o JDBC e o driver escolhido.

Quando escrevemos o código Class.forName("localização do driver");


estamos definindo a classe (e seu pacote) principal da biblioteca do driver. Esta
informação pode ser obtida na documentação do fabricante do driver.

Nas versões atuais do Java não é necessário realizar esse processo, pois a
partir da String de conexão a JVM reconhece qual driver deve ser utilizado.

Connection:

Interface do JDBC que representa a conexão com a base de dados. Através do


método getConnection() da classe DriverManager podemos obter um objeto do tipo
da interface Connection que representa a conexão. Esse método recebe três
parâmetros: a URL de conexão, usuário e senha para acesso ao banco.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 26

A URL de conexão também é definida pelo fabricante do SGDB, seguindo o


padrão JDBC. Abaixo, é apresentada um quadro com as principais classes do driver
e URL de conexão para os principais SGDBs:

Quadro 7.3 – JDBC Drivers e URL String.


Fonte: Fiap (2016)

7.2.6 Statements

Para executar comandos SQLs no SGBDR, existem três objetos do tipo


Statement:

 Statement: Utilizado para executar um comando SQL estático.

 Prepared Statement: Utilizado para executar um comando SQL que recebe


um ou mais parâmetros.

 Callable Statement: Utilizado para chamar stored procedures ou functions.

Os principais métodos destas implementações são:

 executeUpdate: executa um comando SQL(INSERT, UPDATE, DELETE)


e retorna o número de linhas afetadas.

 executeQuery: executa um comando SQL(SELECT) e retorna o(s)


resultado(s) através de um objeto do tipo ResultSet.

Para recuperar o objeto do tipo Statement, utilizamos o método


createStatement() da interface Connection:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 27

Exemplos:

Inclusão:

Statement stmt = conexao.createStatement();


stmt.executeUpdate("INSERT INTO
TAB_COLABORADOR(CODIGO_COLABORADOR, NOME, EMAIL, SALARIO,
DATA_CONTRATACAO) VALUES (SQ_COLABORADOR.NEXTVAL, 'Leandro',
'leandro@gmail.com', 1500,
TO_DATE('10/12/2009','dd/mm/yyyy'))");

Alteração:

Statement stmt = conexao.createStatement();


stmt.executeUpdate("UPDATE TAB_COLABORADOR SET SALARIO =
5000 WHERE CODIGO_COLABORADOR = 1");

Exclusão:

Statement stmt = conexao.createStatement();


stmt.executeUpdate("DELETE FROM TAB_COLABORADOR WHERE
CODIGO_COLABORADOR = 1");

Busca:

Statement stmt = conexao.createStatement();


ResultSet rs = stmt.executeQuery("SELECT * FROM
TAB_COLABORADOR");

Observe que os comandos SQL são estáticos, ou seja, os valores já estão


definidos diretamente na String. Quando precisamos de comandos SQL configuráveis,
devemos utilizar a interface PreparedStatement.

Dessa forma, podemos parametrizar o comando SQL com o ponto de


interrogação ?, através dos métodos setXXX() é possível atribuir valores a esses
parâmetros, evitando assim ataques do tipo SQL Injection.

É indicado utilizar o PreparedStatement para manipular a base de dados,


sempre que possível, pois proporciona melhor performance e clareza do código fonte.
Para obter o objeto PreparedStatement utilizamos o método prepareStatement() da
interface Connection.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 28

Exemplo:

PreparedStatement stmt = conexao.prepareStatement("INSERT


INTO TAB_COLABORADOR(CODIGO_COLABORADOR, NOME, EMAIL, SALARIO,
DATA_CONTRATACAO) VALUES (SQ_COLABORADOR.NEXTVAL, ?, ?, ?,
?)");
stmt.setString(1, "Thiago"); //Primero parâmetro (Nome)
stmt.setString(2, "thiago@gmail.com");//Segundo parâmetro
(Email)
stmt.setDouble(3, 5000); //Terceiro parâmetro (Salário)
//Instancia um objeto do tipo java.sql.Date com a data
atual
java.sql.Date data = new java.sql.Date(new
java.util.Date().getTime());
stmt.setDate(4,data);//Quarto parâmetro (data contratação)

stmt.executeUpdate();

Observe que no lugar dos valores dos parâmetros foi adicionado o ponto de
interrogação ?, para posteriormente adicionarmos valores a eles através dos métodos
setXXX, dependendo do tipo de dado. Esse método recebe dois parâmetros: o
primeiro é a posição do sinal ?, que inicia-se em 1, já o segundo é o valor que será
atribuído a essa posição.

Para cada uma das operações do SQL é possível utilizar o


PreparedStatement:

Alteração:

PreparedStatement stmt = conexao.prepareStatement("UPDATE


TAB_COLABORADOR SET SALARIO = ? WHERE CODIGO_COLABORADOR =
?");
stmt.setDouble(1, 5000);
stmt.setInt(2, 100);
stmt.executeUpdate();

Exclusão:

PreparedStatement stmt = conexao.prepareStatement("DELETE


FROM TAB_COLABORADOR WHERE CODIGO_COLABORADOR = ?");
stmt.setInt(1, 1);
stmt.executeUpdate();

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 29

Busca:

PreparedStatement stmt = conexao.prepareStatement("SELECT


* FROM TAB_COLABORADOR WHERE NOME = ?");
stmt.setString(1, "Thiago");
ResultSet result = stmt.executeQuery();

Agora que aprendemos como executar os principais comandos SQL através da


linguagem Java, vamos abordar como recuperar as informações através da interface
ResultSet.

ResultSet:

A interface ResultSet é responsável pelo conjunto de registros retornados de


um comando SELECT do SQL. Através desse tipo de objeto podemos navegar por
seus registros de forma sequencial, dessa forma, precisamos chamar o método next
para mover o cursor para o próximo registro. Esse método retorna false quando não
conseguir ir para o próximo registro, que caracteriza o final dos dados. Inicialmente o
cursor está posicionado antes do primeiro registro.

As colunas do registro podem ser acessadas através de um índice que


representa a posição da coluna (inicia em 1) ou através do próprio nome da coluna.

Principais métodos:

 next: move o cursor para a próxima linha.

 getInt: retorna os dados da coluna designada como um int do Java.

 getString: retorna os dados da coluna designada como uma String do


Java.

 getBoolean: retorna os dados da coluna designada como um boolean do


Java.

 getDouble: retorna os dados da coluna designada como um double do


Java.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 30

Exemplo:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TesteView {

public static void main(String[] args) {


try {
//Registra o Driver
Class.forName("oracle.jdbc.driver.OracleDriver");

//Abre uma conexão


Connection conexao = DriverManager.getConnection(
"jdbc:oracle:thin:@oracle.fiap.com.br:1521:ORCL",
"OPS$PF0392", "123456");

System.out.println("Conectado!");

PreparedStatement stmt = conexao.prepareStatement("SELECT


* FROM TAB_COLABORADOR WHERE NOME = ?");
stmt.setString(1, "Thiago");
ResultSet result = stmt.executeQuery();

//Percorre todos os registros encontrados


while (result.next()){
//Recupera os valores de cada coluna
int codigo =
result.getInt("CODIGO_COLABORADOR");
String nome = result.getString("NOME");
String email = result.getString("EMAIL");
double salario = result.getDouble("SALARIO");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 31

java.sql.Date data =
result.getDate("DATA_CONTRATACAO");
//Exibe as informações do registro
System.out.println(codigo + " " + nome + " " +
email + " " + salario + " " + data);
}

//Fecha a conexão
conexao.close();

//Tratamento de erro
} catch (SQLException e) {
System.err.println("Não foi possível conectar no
Banco de Dados");
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.err.println("O Driver JDBC não foi
encontrado!");
e.printStackTrace();
}
}
}

7.2.7 CallableStatement

Utilizado para chamar stored procedures ou functions de forma padronizada


para todas as bases de dados. É possível chamar uma stored procedure utilizando ou
não parâmetro de resultado.

Sintaxe básica para chamada de stored procedure:

 Com parâmetro de resultado:


CallableStatement cs = conexao.prepareCall("{call proc(?)}");

 Sem parâmetro de resultado:


CallableStatement cs = conexao.prepareCall("{call proc()}");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 32

Para definir os parâmetros de entrada utilizamos o mesmo padrão do


PreparedStatement, já para os parâmetros de saída são definidos através do método
registerOutParameter.

Exemplo de chamada de uma Stored Procedure com parâmetros de entrada e


saída:

//Cria o CallableStatement
CallableStatement cs = conexao.prepareCall("{call
SP_Contar_Colaboradores(?,?)}");

//Define o tipo do parâmetro de saída (primeiro ?)


cs.registerOutParameter(1, java.sql.Types.INTEGER);

//Define o valor do parâmetro de entrada (segundo ?)


cs.setDouble(2, 1500);

//Executa a procedure
cs.executeUpdate();

//Recupera o valor do parâmetro de saída


int total = cs.getInt(1);
System.out.println("Total de colaboradores com salário
maior que 1500: " + total);

Exemplo de uma Stored Procedure que retorna o resultado de um SELECT:

//Cria o CallableStatement
CallableStatement cs = conexao.prepareCall("{call
SP_Retornar_Todos_Colaboradores(?,?)}");

//Define o valor do parâmetro de entrada


cs.setDouble(1,1500);

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 33

//Define o tipo do parâmetro de saída


cs.registerOutParameter(2, OracleTypes.CURSOR);

//Executa a procedure
cs.execute();

//Recupera o valor do parâmetro de saída


ResultSet cursor = (ResultSet) cs.getObject(2);

//Percorre todos os registros encontrados


while (cursor.next()){
//Recupera os valores de cada coluna
int codigo = cursor.getInt("CODIGO_COLABORADOR");
String nome = cursor.getString("NOME");
System.out.println(codigo + " " + nome);
}

Agora que estudamos as principais Classes e Interfaces do JDBC, vamos


implementar o nosso exemplo!

Aproveitando as tabelas e o projeto criados anteriormente, vamos começar


desenvolvendo o Java Bean Colaborador que irá representar a nossa tabela do
banco de dados.

Essa classe deve possuir atributos que representam cada coluna da tabela.
Utilizamos o encapsulamento, deixando os atributos com o modificador de acesso
private e disponibilizamos os métodos assessores (gets e sets). Foi implementado
também o construtor padrão e com parâmetros. Para armazenar a data de contratação
utilizamos a classe java.util.Calendar.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 34

package br.com.fia.bean;
import java.util.Calendar;
public class Colaborador {

private int codigo;

private String nome;

private String email;

private double salario;

private Calendar dataContratacao;

public Colaborador(int codigo, String nome, String


email, double salario,
Calendar dataContratacao) {
super();
this.codigo = codigo;
this.nome = nome;
this.email = email;
this.salario = salario;
this.dataContratacao = dataContratacao;
}
public Colaborador() {
super();
}

public int getCodigo() {


return codigo;
}

public void setCodigo(int codigo) {


this.codigo = codigo;

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 35

public String getNome() {


return nome;
}

public void setNome(String nome) {


this.nome = nome;
}

public String getEmail() {


return email;
}

public void setEmail(String email) {


this.email = email;
}

public double getSalario() {


return salario;
}

public void setSalario(double salario) {


this.salario = salario;
}

public Calendar getDataContratacao() {


return dataContratacao;
}

public void setDataContratacao(Calendar


dataContratacao) {
this.dataContratacao = dataContratacao;
}
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 36

Essa classe possui grande importância por facilitar o processo de passagem


de valores do banco de dados para a aplicação Java e vice-versa.

Agora vamos criar uma classe que será responsável por fornecer uma conexão
com o banco de dados. Observe que para cada operação no banco de dados
(INSERT, UPDATE, SELECT e DELETE) foi necessário primeiro obter uma conexão.
Com essa classe, não vamos precisar escrever código repetido, utilizando assim os
conceitos de orientação a objetos.

package br.com.fiap.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;

public class EmpresaDBManager {

public static Connection obterConexao() {


Connection conexao = null;
try {

Class.forName("oracle.jdbc.driver.OracleDriver");

conexao = DriverManager.getConnection(

"jdbc:oracle:thin:@oracle.fiap.com.br:1521:ORCL",
"OPS$XXXX", "XXXXX");

} catch (Exception e) {
e.printStackTrace();
}
return conexao;
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 37

Observe que essa classe possui somente um método estático que cria e retorna
uma conexão com o banco. O método é estático para não precisar de uma instância
para ser invocada, bastando referenciá-la através do nome da classe:
EmpresaDBManager.obterConexao();

Agora estamos prontos para desenvolver a classe Java responsável pela


manipulação da tabela TAB_COLABORADOR. A classe possui a nomenclatura
ColaboradorDAO, pois segue um padrão de projeto chamado de DAO (Data Access
Object), que é responsável pelo código de acesso aos dados, centralizando assim a
implementação dessa responsabilidade no projeto.

Vamos falar sobre Padrões de Projetos, suas implementações e benefícios um


pouco mais para frente no curso.

Crie a classe ColaboradorDAO, conforme a listagem abaixo:

package br.com.fiap.dao;

public class ColaboradorDAO {

private Connection conexao;

A classe DAO deve possuir um atributo para armazenar o objeto que representa
a conexão com o banco de dados.

Agora vamos desenvolver o primeiro método que será responsável por


cadastrar um colaborador na base de dados. Para isso, ele deve receber um objeto
do tipo Colaborador para ser inserido no banco:

public class ColaboradorDAO {

private Connection conexao;

public void cadastrar(Colaborador colaborador) {


PreparedStatement stmt = null;

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 38

try {
conexao = EmpresaDBManager.obterConexao();
String sql = "INSERT INTO
TAB_COLABORADOR(CODIGO_COLABORADOR, NOME, EMAIL, SALARIO,
DATA_CONTRATACAO) VALUES (SQ_COLABORADOR.NEXTVAL, ?, ?, ?,
?)";
stmt = conexao.prepareStatement(sql);
stmt.setString(1, colaborador.getNome());
stmt.setString(2, colaborador.getEmail());
stmt.setDouble(3,
colaborador.getSalario());
java.sql.Date data = new
java.sql.Date(colaborador.getDataContratacao().getTimeInMillis
());
stmt.setDate(4, data);

stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 39

Primeiro, obtemos a conexão com o banco de dados através do método


obterConexao() da classe EmpresaDBManager. Depois, definimos em uma String o
comando SQL. Criamos o PreparedStatement e passamos os valores para cada um
de seus parâmetros. Por fim, executamos o comando no Banco de dados. Utilizamos
o bloco Try-catch para tratar possíveis exceções e no bloco finally (que sempre é
executado) fechamos o PreparedStatement e a conexão.

Não se esqueça dos imports! Um atalho do eclipse é o CTR + SHIF + o, para


fazer o import automático.

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import br.com.fiap.bean.Colaborador;
import br.com.fiap.jdbc.EmpresaDBManager;

Após implementar uma funcionalidade no DAO, é indicado desenvolver uma


classe de teste, para verificar se está tudo correto.

Para isso, crie uma classe com o método main, conforme a listagem abaixo:

package br.com.fiap.teste;

import java.util.Calendar;

import br.com.fiap.bean.Colaborador;
import br.com.fiap.dao.ColaboradorDAO;

public class TesteCadastro {

public static void main(String[] args) {


//Instancia o DAO
ColaboradorDAO dao = new ColaboradorDAO();

//Instancia o Colaborador
Colaborador colaborador = new Colaborador();

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 40

colaborador.setNome("Pedro");
colaborador.setEmail("pedro@fiap.com.br");
colaborador.setSalario(5000);

colaborador.setDataContratacao(Calendar.getInstance());

//Cadastra no banco de dados


dao.cadastrar(colaborador);

System.out.println("Cadastrado!");
}

Essa classe cria uma instância da classe ColaboradorDAO e do Colaborador.


E através do método cadastrar do ColaboradorDAO é realizado o cadastro no banco
de dados.

Execute e verifique no banco de dados se o colaborador foi cadastrado com


sucesso!

Agora vamos implementar a próxima funcionalidade no DAO: Listar. Para isso,


volte à classe ColaboradorDAO e crie o novo método:

public List<Colaborador> listar() {


//Cria uma lista de colaboradores
List<Colaborador> lista = new
ArrayList<Colaborador>();
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conexao = EmpresaDBManager.obterConexao();
stmt = conexao.prepareStatement("SELECT *
FROM TAB_COLABORADOR");
rs = stmt.executeQuery();

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 41

//Percorre todos os registros encontrados


while (rs.next()) {
int codigo =
rs.getInt("CODIGO_COLABORADOR");
String nome = rs.getString("NOME");
String email = rs.getString("EMAIL");
double salario =
rs.getDouble("SALARIO");
java.sql.Date data =
rs.getDate("DATA_CONTRATACAO");
Calendar dataContratacao =
Calendar.getInstance();

dataContratacao.setTimeInMillis(data.getTime());
//Cria um objeto Colaborador com as
informações encontradas
Colaborador colaborador = new
Colaborador(codigo, nome, email, salario, dataContratacao);
//Adiciona o colaborador na lista
lista.add(colaborador);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
stmt.close();
rs.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return lista;
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 42

Esse método retorna uma lista com todos os colaboradores cadastrados. Não
se esqueça de adicionar os imports do List, ArrayList e ResultSet:

import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

Para cada registro no ResultSet é instanciado um objeto Colaborador para


armazenar as informações encontradas. Esse objeto é adicionado à lista que será
retornada.

Agora vamos para a classe de teste! Para ficar mais organizado, criaremos uma
nova classe de teste que será responsável pelo teste da listagem:

package br.com.fiap.teste;

import java.util.List;
import br.com.fiap.bean.Colaborador;
import br.com.fiap.dao.ColaboradorDAO;

public class TesteListagem {

public static void main(String[] args) {

ColaboradorDAO dao = new ColaboradorDAO();

List<Colaborador> lista = dao.listar();


for (Colaborador item : lista) {
System.out.println(item.getCodigo() + " " +
item.getNome() + " " + item.getEmail() + " " +
item.getSalario() + " " +
item.getDataContratacao().getTime());
}
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 43

Essa classe instanciará o ColaboradorDAO e chamar o método listar() para


receber a lista de colaboradores cadastrados no banco de dados. Depois,
implementamos um laço de repetição foreach para percorrer toda a lista e imprimir os
valores dos atributos do colaborador.

A próxima funcionalidade será remover um colaborador da base de dados:

public void remover(int codigo){


PreparedStatement stmt = null;

try {
conexao = EmpresaDBManager.obterConexao();
String sql = "DELETE FROM TAB_COLABORADOR
WHERE CODIGO_COLABORADOR = ?";
stmt = conexao.prepareStatement(sql);
stmt.setInt(1, codigo);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

Esse método, que deve ser implementado na classe ColaboradorDAO, recebe


o código do colaborador que será excluído do banco de dados.

A nova classe de teste pode ser escrita dessa forma:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 44

package br.com.fiap.teste;

import br.com.fiap.dao.ColaboradorDAO;

public class TesteRemocao {

public static void main(String[] args) {


ColaboradorDAO dao = new ColaboradorDAO();
//Remove o colaborador com código 1
dao.remover(1);
}

A classe de teste instancia o ColaboradorDAO para chamar o método remover,


passando o ID do colaborador que será excluído do banco de dados.

Para finalizar o CRUD precisamos implementar o método de atualização.


Porém, antes vamos desenvolver o método buscar por código, para recuperar o
colaborador que será atualizado.

Na classe ColaboradorDAO adicione o método buscarPorId que recebe o


código do colaborador:

Colaborador colaborador = null;


PreparedStatement stmt = null;
ResultSet rs = null;
try {
conexao = EmpresaDBManager.obterConexao();
stmt = conexao.prepareStatement("SELECT *
FROM TAB_COLABORADOR WHERE CODIGO_COLABORADOR = ?");
stmt.setInt(1, codigoBusca);
rs = stmt.executeQuery();
if (rs.next()){

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 45

int codigo =
rs.getInt("CODIGO_COLABORADOR");
String nome = rs.getString("NOME");
String email = rs.getString("EMAIL");
double salario =
rs.getDouble("SALARIO");
java.sql.Date data =
rs.getDate("DATA_CONTRATACAO");
Calendar dataContratacao =
Calendar.getInstance();

dataContratacao.setTimeInMillis(data.getTime());
colaborador = new Colaborador(codigo,
nome, email, salario, dataContratacao);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
stmt.close();
rs.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return colaborador;
}

Observe que após a execução da Query é acionado o método next() do


ResultSet para verificar se existe algum registro, em caso positivo, são recuperados
todos os valores do registro e instanciado um Colaborador para armazenar essas
informações.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 46

Agora, o último método, o de atualização:

public void atualizar(Colaborador colaborador){


PreparedStatement stmt = null;

try {
conexao = EmpresaDBManager.obterConexao();
String sql = "UPDATE TAB_COLABORADOR SET
NOME = ?, EMAIL = ?, SALARIO = ?, DATA_CONTRATACAO = ? WHERE
CODIGO_COLABORADOR = ?";
stmt = conexao.prepareStatement(sql);
stmt.setString(1, colaborador.getNome());
stmt.setString(2, colaborador.getEmail());
stmt.setDouble(3,
colaborador.getSalario());
java.sql.Date data = new
java.sql.Date(colaborador.getDataContratacao().getTimeInMillis
());
stmt.setDate(4, data);
stmt.setInt(5, colaborador.getCodigo());

stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 47

Foram adicionados na query todos os atributos do Colaborador para ser


atualizado, menos o código, pois ele nunca deve ser alterado. Não se esqueça de
adicionar a cláusula WHERE para modificar somente o colaborador correto.

A classe de teste deve primeiro recuperar um colaborador, utilizando o método


buscarPorId, depois devemos alterar os valores dos atributos do colaborador e
chamar o método atualizar:

package br.com.fiap.teste;

import br.com.fiap.bean.Colaborador;
import br.com.fiap.dao.ColaboradorDAO;

public class TesteAlteracao {

public static void main(String[] args) {

ColaboradorDAO dao = new ColaboradorDAO();


//Recupera o colaborador com código 1
Colaborador colaborador = dao.buscarPorId(1);
//Imprime os valores do colaborador
System.out.println(colaborador.getCodigo() + " "
+ colaborador.getNome() + " " +
colaborador.getEmail() + " "
+ colaborador.getSalario() + " "
+
colaborador.getDataContratacao().getTime());
//Altera os valores de alguns atributos do
colaborador
colaborador.setSalario(1500);
colaborador.setEmail("teste@fiap.com.br");
//Atualiza no banco de dados
dao.atualizar(colaborador);
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 48

7.3 Controle transacional

Toda comunicação com banco de dados requer cuidados com acessos


paralelos e integridade dos dados. Para isso, todo SGBD e linguagem de
programação possuem tratamento específico para permitir a segurança e integridade
dos dados, assim como no JDBC.

7.3.1 Transação

Uma transação é uma unidade que preserva a consistência de informações no


banco de dados.

Podemos dizer também que transações são unidades atômicas de operações:


“Em ciência da computação, uma transação atômica é uma operação, ou conjunto de
operações, em uma base de dados, ou em qualquer outro sistema computacional, que
deve ser executada completamente em caso de sucesso, ou ser abortada
completamente em caso de erro”.

Figura 7.19 – Processo transacional


Fonte: Fiap (2016)

Um exemplo clássico da necessidade de uma “transação atômica” é a


transferência entre duas contas bancárias. No momento de uma transferência de
valores de uma conta A para uma conta B, que envolve pelo menos uma operação de
ajuste no saldo para cada conta, dessa forma, as duas contas devem sofrer alteração
no saldo ou nenhuma das duas contas. Caso o computador responsável pela
operação é desligado no meio da operação, é esperado que o saldo de ambas as
contas não tenha se alterado. Neste caso, são utilizados sistemas que suportam
transações atômicas.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 49

Figura 7.20 – Exemplo de transação atômica.


Fonte: Fiap (2016)

Uma transação pode ser representada pela sigla ACID:

 Atomicidade(Atomicity): atômico, tudo (commit) ou nada (rollback).

 Consistência(Consistency): toda transação executada deve seguir as


regras de integridade do banco de dados, mantendo assim a consistência
da base de dados.

 Isolamento(Isolation): garante que nenhuma transação seja interferida por


outra até que esta seja completada.

 Durabilidade(Durability): garante que as informações gravadas no banco


de dados durem de forma imutável até que outra transação de atualização
ou remoção a afete.

As operações possíveis para o controle transacional são: COMMIT e


ROLLBACK:

 COMMIT: todas as operações envolvidas em uma unidade de processo


executam com sucesso, efetivando assim as alterações na base de dados.

 ROLLBACK: todas as operações envolvidas em uma unidade de processo


não executam corretamente, não efetuando assim as operações das
transações na base de dados.

Por padrão, toda conexão com JDBC está configurada para realizar o COMMIT
automaticamente, ou seja, o COMMIT é realizado de forma automática após a
execução de um comando SQL.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 50

Para desabilitar essa configuração, utilizamos o método


setAutoCommit(false), da interface Connection.

Exemplo:

try {
//Desabilita o autocommit
conexao.setAutoCommit(false);

//Primeira transação - Atualiza o salário


PreparedStatement stmt =
conexao.prepareStatement("UPDATE TAB_COLABORADOR SET SALARIO =
? WHERE CODIGO_COLABORADOR = ?");
stmt.setDouble(1, 5000);
stmt.setInt(2, 1);
stmt.executeUpdate();

//Segunda transação - Atualiza o e-mail


PreparedStatement stmt2 =
conexao.prepareStatement("UPDATE TAB_COLABORADOR SET EMAIL = ?
WHERE CODIGO_COLABORADOR = ?");
stmt2.setString(1, "teste@teste.com.br");
stmt2.setInt(2, 1);
stmt2.executeUpdate();

//Efetiva as duas transações


conexao.commit();

} catch (SQLException se) {


//Não efetiva as duas transações
conexao.rollback();
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 51

No exemplo acima é possível observar que desabilitamos o COMMIT


automático através da instrução conexao.setAutoCommit(false), dessa forma, todo
comando que modifica a base de dados (atualização, inclusão e exclusão) só será
efetivado caso o comando COMMIT seja chamado. Assim sendo, as duas instruções
de atualização só serão efetivadas caso não ocorram erros, após o comando
conexao.commit().

Caso ocorra algum erro, o comando conexao.rollback() é executado para


desfazer as transações e assim não modificar as informações do banco de dados.

7.4 Design patterns

Um Padrão de Projeto de Software, também conhecido pelo termo em inglês


Design Pattern, descreve uma solução geral reutilizável para um problema recorrente
no desenvolvimento de sistemas. Não é um código final, é uma descrição ou modelo
de como resolver o problema que ocorre em vários sistemas de diferentes áreas de
atuação ou plataforma de desenvolvimento.

Foram desenvolvidos vários padrões de projetos, o livro que tornou os padrões


mais populares e conhecidos foi escrito por quatro autores e se chama Design
Patterns: Elements of Resuable Object-Oriented Software. Os autores desses
livros são conhecidos como “Gangue dos Quatro” (Gang of Four) ou simplesmente
“GOF”.

Utilizar padrões de projetos na implementação de um programa implica em


algumas vantagens como:

 Facilidade de comunicação: os padrões possuem nomes, os quais


descrevem uma solução que deve ser de conhecimento entre os
desenvolvedores.

 Credibilidade: padrões de projetos são utilizados constantemente nas


implementações de sistemas, dessa forma, são amplamente testadas e
aprovadas.

 Facilidade de manutenção: além do desenvolvimento, a manutenção é


outra etapa da vida de um sistema que devemos nos preocupar. Padrões

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 52

de projetos tendem a reduzir o acoplamento entre os componentes, o que


facilita a manutenção de um sistema.

A seguir, veremos os principais Desing Patterns para implementação do


backend de um sistema.

7.4.1 Data Access Object (DAO)

Esse padrão de projeto abstrai e encapsula todo o acesso à base de dados. A


ideia é criar uma classe Java que separa totalmente a lógica de acesso e manipulação
de dados da aplicação. Essa classe denominada DAO é a camada que separa a
aplicação do banco de dados, ela possui todo o código de acesso ao banco de dados,
tornando mais fácil os testes e manutenção.

Dessa forma, devemos desenvolver uma classe DAO para cada entidade, a fim
de separar a responsabilidade do acesso à base de dados da entidade a seus
respectivos DAOs:

Figura 7.21 – Camada de acesso a dados da aplicação (DAO).


Fonte: Fiap (2016)

O exemplo implementado acima já está utilizando o padrão DAO. Foi


desenvolvida uma classe chamada ColaboradorDAO, que possui os métodos que
realizam as operações no banco de dados.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 53

O código abaixo apresenta o exemplo completo da classe ColaboradorDAO:

package br.com.fiap.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import br.com.fiap.bean.Colaborador;
import br.com.fiap.jdbc.EmpresaDBManager;

public class ColaboradorDAO {

private Connection conexao;

public void cadastrar(Colaborador colaborador) {


PreparedStatement stmt = null;

try {
conexao = EmpresaDBManager.obterConexao();
String sql = "INSERT INTO
TAB_COLABORADOR(CODIGO_COLABORADOR, NOME, EMAIL, SALARIO,
DATA_CONTRATACAO) VALUES (SQ_COLABORADOR.NEXTVAL, ?, ?, ?,
?)";
stmt = conexao.prepareStatement(sql);
stmt.setString(1, colaborador.getNome());
stmt.setString(2, colaborador.getEmail());
stmt.setDouble(3,
colaborador.getSalario());

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 54

java.sql.Date data = new


java.sql.Date(colaborador.getDataContratacao().getTimeInMillis
());
stmt.setDate(4, data);

stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

public List<Colaborador> listar() {


//Cria uma lista de colaboradores
List<Colaborador> lista = new
ArrayList<Colaborador>();
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conexao = EmpresaDBManager.obterConexao();
stmt = conexao.prepareStatement("SELECT *
FROM TAB_COLABORADOR");
rs = stmt.executeQuery();

//Percorre todos os registros encontrados


while (rs.next()) {
int codigo =
rs.getInt("CODIGO_COLABORADOR");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 55

String nome = rs.getString("NOME");


String email = rs.getString("EMAIL");
double salario =
rs.getDouble("SALARIO");
java.sql.Date data =
rs.getDate("DATA_CONTRATACAO");
Calendar dataContratacao =
Calendar.getInstance();

dataContratacao.setTimeInMillis(data.getTime());
//Cria um objeto Colaborador com as
informações encontradas
Colaborador colaborador = new
Colaborador(codigo, nome, email, salario, dataContratacao);
//Adiciona o colaborador na lista
lista.add(colaborador);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
stmt.close();
rs.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return lista;
}

public void atualizar(Colaborador colaborador){


PreparedStatement stmt = null;

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 56

try {
conexao = EmpresaDBManager.obterConexao();
String sql = "UPDATE TAB_COLABORADOR SET
NOME = ?, EMAIL = ?, SALARIO = ?, DATA_CONTRATACAO = ? WHERE
CODIGO_COLABORADOR = ?";
stmt = conexao.prepareStatement(sql);
stmt.setString(1, colaborador.getNome());
stmt.setString(2, colaborador.getEmail());
stmt.setDouble(3,
colaborador.getSalario());
java.sql.Date data = new
java.sql.Date(colaborador.getDataContratacao().getTimeInMillis
());
stmt.setDate(4, data);
stmt.setInt(5, colaborador.getCodigo());

stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

public void remover(int codigo){


PreparedStatement stmt = null;

try {
conexao = EmpresaDBManager.obterConexao();

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 57

String sql = "DELETE FROM TAB_COLABORADOR


WHERE CODIGO_COLABORADOR = ?";
stmt = conexao.prepareStatement(sql);
stmt.setInt(1, codigo);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

public Colaborador buscarPorId(int codigoBusca){


Colaborador colaborador = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conexao = EmpresaDBManager.obterConexao();
stmt = conexao.prepareStatement("SELECT *
FROM TAB_COLABORADOR WHERE CODIGO_COLABORADOR = ?");
stmt.setInt(1, codigoBusca);
rs = stmt.executeQuery();

if (rs.next()){
int codigo =
rs.getInt("CODIGO_COLABORADOR");
String nome = rs.getString("NOME");
String email = rs.getString("EMAIL");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 58

double salario =
rs.getDouble("SALARIO");
java.sql.Date data =
rs.getDate("DATA_CONTRATACAO");
Calendar dataContratacao =
Calendar.getInstance();

dataContratacao.setTimeInMillis(data.getTime());
colaborador = new Colaborador(codigo,
nome, email, salario, dataContratacao);
}

} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
stmt.close();
rs.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return colaborador;
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 59

Para utilizar o DAO, basta instanciar a classe e invocar os seus métodos:

public static void main(String[] args) {

ColaboradorDAO dao = new ColaboradorDAO();

List<Colaborador> lista = dao.listar();

Outra boa prática na implementação do padrão de projeto DAO é a utilização


de interfaces. Dessa forma, a aplicação pode referenciar a interface ao invés da
classe, diminuindo assim o acoplamento. Utilizar interface, permite a criação de
diferentes implementações que podem ser trocadas sem a necessidade de grandes
alterações no código da camada de negócio ou apresentação.

O exemplo abaixo apresenta a implementação do ColaboradorDAO utilizando


uma interface e a implementação para o banco de dados Oracle:

Interface que define as funcionalidades do DAO:

package br.com.fiap.dao;

import java.util.List;
import br.com.fiap.bean.Colaborador;

public interface ColaboradorDAO {

public void cadastrar(Colaborador colaborador);

public List<Colaborador> listar();

public void atualizar(Colaborador colaborador);

public void remover(int codigo);

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 60

public Colaborador buscarPorId(int codigoBusca);


}

Classe que implementa as funcionalidades definidas na interface:

package br.com.fiap.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import br.com.fiap.bean.Colaborador;
import br.com.fiap.jdbc.EmpresaDBManager;

public class OracleColaboradorDAO implements


ColaboradorDAO {

private Connection conexao;

public void cadastrar(Colaborador colaborador) {


PreparedStatement stmt = null;

try {
conexao = EmpresaDBManager.obterConexao();
String sql = "INSERT INTO
TAB_COLABORADOR(CODIGO_COLABORADOR, NOME, EMAIL, SALARIO,
DATA_CONTRATACAO) VALUES (SQ_COLABORADOR.NEXTVAL, ?, ?, ?,
?)";
stmt = conexao.prepareStatement(sql);
stmt.setString(1, colaborador.getNome());
stmt.setString(2, colaborador.getEmail());

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 61

stmt.setDouble(3,
colaborador.getSalario());
java.sql.Date data = new
java.sql.Date(colaborador.getDataContratacao().getTimeInMillis
());
stmt.setDate(4, data);

stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

public List<Colaborador> listar() {


//Cria uma lista de colaboradores
List<Colaborador> lista = new
ArrayList<Colaborador>();
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conexao = EmpresaDBManager.obterConexao();
stmt = conexao.prepareStatement("SELECT *
FROM TAB_COLABORADOR");
rs = stmt.executeQuery();

//Percorre todos os registros encontrados


while (rs.next()) {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 62

int codigo =
rs.getInt("CODIGO_COLABORADOR");
String nome = rs.getString("NOME");
String email = rs.getString("EMAIL");
double salario =
rs.getDouble("SALARIO");
java.sql.Date data =
rs.getDate("DATA_CONTRATACAO");
Calendar dataContratacao =
Calendar.getInstance();

dataContratacao.setTimeInMillis(data.getTime());
//Cria um objeto Colaborador com as
informações encontradas
Colaborador colaborador = new
Colaborador(codigo, nome, email, salario, dataContratacao);
//Adiciona o colaborador na lista
lista.add(colaborador);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
stmt.close();
rs.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return lista;
}

public void atualizar(Colaborador colaborador){

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 63

PreparedStatement stmt = null;

try {
conexao = EmpresaDBManager.obterConexao();
String sql = "UPDATE TAB_COLABORADOR SET
NOME = ?, EMAIL = ?, SALARIO = ?, DATA_CONTRATACAO = ? WHERE
CODIGO_COLABORADOR = ?";
stmt = conexao.prepareStatement(sql);
stmt.setString(1, colaborador.getNome());
stmt.setString(2, colaborador.getEmail());
stmt.setDouble(3,
colaborador.getSalario());
java.sql.Date data = new
java.sql.Date(colaborador.getDataContratacao().getTimeInMillis
());
stmt.setDate(4, data);
stmt.setInt(5, colaborador.getCodigo());

stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

public void remover(int codigo){


PreparedStatement stmt = null;

try {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 64

conexao = EmpresaDBManager.obterConexao();
String sql = "DELETE FROM TAB_COLABORADOR
WHERE CODIGO_COLABORADOR = ?";
stmt = conexao.prepareStatement(sql);
stmt.setInt(1, codigo);
stmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

public Colaborador buscarPorId(int codigoBusca){


Colaborador colaborador = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conexao = EmpresaDBManager.obterConexao();
stmt = conexao.prepareStatement("SELECT *
FROM TAB_COLABORADOR WHERE CODIGO_COLABORADOR = ?");
stmt.setInt(1, codigoBusca);
rs = stmt.executeQuery();

if (rs.next()){
int codigo =
rs.getInt("CODIGO_COLABORADOR");
String nome = rs.getString("NOME");
String email = rs.getString("EMAIL");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 65

double salario =
rs.getDouble("SALARIO");
java.sql.Date data =
rs.getDate("DATA_CONTRATACAO");
Calendar dataContratacao =
Calendar.getInstance();

dataContratacao.setTimeInMillis(data.getTime());
colaborador = new Colaborador(codigo,
nome, email, salario, dataContratacao);
}

} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
stmt.close();
rs.close();
conexao.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return colaborador;
}
}

7.4.2 DAO Factory

Trata-se de uma fábrica de DAOs para um tipo específico de banco de dados.


Esse padrão de projetos é recomendado quando não há previsão de mudar o banco
de dados da aplicação, ou seja, se o sistema utiliza o banco de dados MySQL e não
há previsão de trocar o banco de dados, esse padrão é o mais recomendado. Existem
outros padrões mais indicados quando há a possibilidade da troca do banco de dados,
que veremos a seguir.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 66

A ideia do DAOFactory é centralizar a criação dos objetos DAOs, desta forma,


se a aplicação precisar de um objeto ColaboradorDAO, o DAOFactory irá prover
através de um método estático. Abaixo é apresentado um exemplo de implementação
do DAOFactory que está em uma aplicação que possui dois DAOs:

Primeiro vamos implementar os DAOs do Colaborador e Cargo:

Interface CargoDAO e classe OracleCargoDAO, que implementa a interface:

public interface CargoDAO {

public List<Cargo> listar();

public void cadastrar(Cargo cargo);

public class OracleCargoDAO implements CargoDAO {

@Override
public List<Cargo> listar() {
//Implementação
}

@Override
public void cadastrar(Cargo cargo) {
//Implementação

Interface ColaboradorDAO e classe OracleColaboradorDAO, que implementa


a interface:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 67

public interface ColaboradorDAO {

public List<Colaborador> listar();

public void cadastrar(Colaborador colaborador);

public class OracleColaboradorDAO implements


ColaboradorDAO {

public List<Colaborador> listar(){


//Implementação
}

public void cadastrar(Colaborador colaborador){


//Implementação
}

Agora vamos implementar o DAOFactory, a fábrica que fornece as instâncias


dos DAOs:

package br.com.fiap.factory;

import br.com.fiap.dao.CargoDAO;
import br.com.fiap.dao.ColaboradorDAO;
import br.com.fiap.dao.OracleCargoDAO;
import br.com.fiap.dao.OracleColaboradorDAO;

public abstract class DAOFactory {

public static CargoDAO getCargoDAO(){


return new OracleCargoDAO();
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 68

public static ColaboradorDAO getColaboradorDAO(){


return new OracleColaboradorDAO();
}

Note que a classe acima possui dois métodos estáticos que fornecem as
instâncias dos DAOs. Para sua utilização, basta invocar esses métodos:

import java.util.List;

import br.com.fiap.bean.Colaborador;
import br.com.fiap.dao.ColaboradorDAO;
import br.com.fiap.factory.DAOFactory;

public class TesteDAOFactory {

public static void main(String[] args) {


ColaboradorDAO dao =
DAOFactory.getColaboradorDAO();
List<Colaborador> lista = dao.listar();
}

7.4.3 Abstract Factory

Ao contrário do DAO Factory, estre padrão de projetos é indicado quando é


preciso suportar vários bancos de dados, pois permite criar implementações de DAOs
para cada banco de dados e prover o DAO correto de acordo com a necessidade.

Exemplo: um sistema utiliza o banco de dados Oracle e SQL Server e é possível


que no futuro passe a utilizar também DB2 para suportar um determinado módulo que
foi adquirido pela empresa. Nesse cenário é justificada a utilização de uma estrutura

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 69

que permite suportar diversos tipos de bancos de dados e estar preparado para
suportar novos tipos.

A implementação desse padrão de projetos começa pelos DAOs. Se a


aplicação precisa suportar o Oracle e o SQL Server, por exemplo, é necessário criar
uma interface que define as funcionalidades e implementá-la em duas classes, uma
específica que acessa o banco de dados Oracle e outra que acessa o banco de dados
SQL Server.

Depois de desenvolvida a estrutura do DAO, devemos implementar a Fábrica


de DAOs que é uma classe abstrata (não pode ser instanciada) que deve possuir um
método estático que retorna uma instância da Fábrica de DAO de acordo com o Banco
de dados escolhido.

Exemplo: Primeiro definimos as interfaces do DAO, por exemplo, podemos ter


as interfaces ColaboradorDAO e CargoDAO. Para cada interface, devemos
implementar a classe que acessa o banco de dados Oracle e outro para o SQL. Assim,
teremos as classes OracleColaboradorDAO e SQLColaboradorDAO para a interface
ColaboradorDAO e OracleCargoDAO e SQLCargoDAO para a interface CargoDAO.

Agora precisamos desenvolver o Abstract DAO Factory que será responsável


por fornecer a instância da fábrica de DAO, de acordo com o banco escolhido:

package br.com.fiap.factory;

import br.com.fiap.dao.CargoDAO;
import br.com.fiap.dao.ColaboradorDAO;

public abstract class DAOFactory {

//Constanstes que definem os tipos de Data Source


suportados
public static final int SQL_SERVER = 1;
public static final int ORACLE = 2;

//Atributos que armazenam as instancias de cada


Fábrica

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 70

private static DAOFactory oracleDAOFactory;


private static DAOFactory sqlDAOFactory;

//Método que retorna a instancia de uma fábrica de


acordo com o banco
public static DAOFactory getDAOFactory(int banco){
switch (banco) {
case SQL_SERVER:
if (sqlDAOFactory == null)
sqlDAOFactory = new SQLDAOFactory();
return sqlDAOFactory;
case ORACLE:
if (oracleDAOFactory == null)
oracleDAOFactory = new
OracleDAOFactory();
return oracleDAOFactory;
default:
return null;
}
}

//Assinaturas de métodos que retornam a instancia do


DAO
public abstract CargoDAO getCargoDAO();
public abstract ColaboradorDAO getColaboradorDAO();

Foram definidas duas constantes, uma para cada banco de dados suportado
pela aplicação. Dois atributos armazenam suas respectivas fábricas de DAO, uma
para cada banco. O método getDAOFactory() recebe o valor de uma das constantes
que representam o banco de dados para devolver a instância da fábrica correta.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 71

Após a classe abstrata criada, é preciso criar duas classes para estender a
DAO Factory, uma para cada tipo de fábrica. Assim, temos o SQLDAOFactory e o
OracleDAOFactory. Nestas classes implementamos os métodos que retornam as
instâncias dos DAOs, de acordo com seu banco de dados.

Para utilizar o DAO Factory, basta invocar o método que recupera a instância
da fábrica, informando o banco de dados escolhido:

package br.com.fiap.teste;

import java.util.List;

import br.com.fiap.bean.Colaborador;
import br.com.fiap.dao.ColaboradorDAO;
import br.com.fiap.factory.DAOFactory;

public class TesteDAOFactory {

public static void main(String[] args) {


ColaboradorDAO dao =
DAOFactory.getDAOFactory(DAOFactory.ORACLE).getColaboradorDAO(
);
List<Colaborador> lista = dao.listar();
}

7.4.4 Singleton

O objetivo desse padrão de projetos é gerar somente uma instância da classe.


Esse padrão oferece um ponto de acesso global, no qual todos podem acessar a
instância da classe através desse ponto de acesso. A classe Singleton deve gerenciar
a própria instância e evitar que qualquer outra classe cria uma instancia dela.

Assim, a classe Singleton deve possuir um construtor privado (private) a fim de


evitar que outras classes a instancie. Essa classe também deve possuir um método
estático que devolve a instância da própria classe Singleton. Esse método deve validar
se já existe uma instância da classe, caso não exista, ela deve criar uma nova, caso

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 72

contrário, deve retornar à instância existente. Para determinar se existe ou não a


instância da classe, é preciso criar um atributo estático para armazená-la, conforme o
exemplo abaixo:

package br.com.fiap.singleton;

import java.sql.Connection;

public class ConnectionManager {

//Atributo que armazena a única instancia de


ConnectionManager
private static ConnectionManager instance;

//Construtor privado
private ConnectionManager(){}

public static ConnectionManager getInstance(){


if (instance == null){
instance = new ConnectionManager();
}
return instance;
}

public Connection getConnection(){


//Implementação
}

A classe ConnectionManager possui uma variável privada e estática que se


autorreferencia, esse atributo que armazenará a única instância da classe
ConnectionManager. O construtor possui o modificador de acesso private, dessa
forma, nenhuma outra classe tem acesso ao construtor, não permitindo a sua
instanciação.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 73

Para acessar a instância da classe ConnectionManager é preciso utilizar o


método getInstance(), esse método gerencia a existência da única instância de
ConnectionManager; valida se o atributo instance está vazio, e caso esteja, é criada
a instância de ConnectionManager, atribuída a variável instance e retornado em
seguida. Caso o atributo instance já possua um objeto, o método retorna o próprio
objeto existente.

Para utilizar a classe ConnectionManager, devemos utilizar o método


getInstance(), conforme o exemplo abaixo:

public class OracleColaboradorDAO implements


ColaboradorDAO {

public List<Colaborador> listar(){


Connection conexao =
ConnectionManager.getInstance().getConnection();
//Implementação
}

public void cadastrar(Colaborador colaborador){


Connection conexao =
ConnectionManager.getInstance().getConnection();
//Implementação
}

Note que não é possível instanciar o ConnectionManager de outra maneira, a


não ser utilizando o método estático getInstance().

Dessa forma, finalizamos o acesso ao banco de dados utilizando a linguagem


de programação Java. Vimos alguns dos principais padrões de projetos utilizados no
mercado e focado na implementação da camada de acesso a dados de uma
aplicação.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Acesso ao Banco de Dados Página 74

REFERÊNCIAS

BARNES, David J. Programação Orientada a Objetos com Java: Uma introdução


Prática Utilizando Blue J. São Paulo: Pearson, 2004.

CADENHEAD, Rogers; LEMAY, Laura. Aprenda em 21 dias Java 2 Professional


Reference. 5.ed. Rio de Janeiro: Elsevier, 2003.

DEITEL, Paul; DEITEL Harvey. Java Como Programar. 8.ed. São Paulo: Pearson,
2010.

HORSTMANN, Cay; CORNELL, Gary. Core Java. Volume I Fundamentos. 8.ed. São
Paulo: Pearson 2009.

SIERRA, Kathy; BATES, Bert. Use a cabeça! Java. Rio de Janeiro: Alta Books, 2010.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com
julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 2

LISTA DE FIGURAS

Figura 6.1 – The Hierarchy of Exception Classes .....................................................9


Figura 6.2 – Streams .................................................................................................21
Figura 6.3 – Arquivos textos ......................................................................................21
Figura 6.4 – Exemplo de arquivo texto ......................................................................22
Figura 6.5 – Exemplo de pasta raiz do programa ......................................................23
Figura 6.6 – O resultado da execução.......................................................................24
Figura 6.7 – Classes..................................................................................................27
Figura 6.8 – Classe abstrata no diagrama de classes ...............................................35
Figura 6.9 – Representação de um diagrama de classes .........................................37
Figura 6.10 – Os métodos e atributos estáticos em um diagrama de classe
representados com um sublinhado ...........................................................................43
Figura 6.11 – Exemplo de criação de uma interface no eclipse ................................45
Figura 6.12 – Definindo pacote e nome.....................................................................46
Figura 6.13 – Representação de uma interface no diagrama de classes..................46
Figura 6.14 – A representação de uma implementação ............................................48
Figura 6.15 – Utilização de interfaces .......................................................................48
Figura 6.16 – Exemplo de duas classes que implementam uma mesma interface ...49

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 3

LISTA DE QUADROS

Quadro 6.1 – Resumo das exceções no Java ...........................................................8


Quadro 6.2 – Os principais métodos da classe File ..................................................28
Quadro 6.3 – Principais características da palavra-chave final .................................40

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 4

LISTA DE TABELAS

Tabela 1.1 – Exemplo de tabela a ser utilizado. .......................................................9

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 5

LISTA DE CÓDIGOS-FONTE

Código Fonte 1.1 – Exemplo de código-fonte HTML. ...............................................8

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 6

SUMÁRIO

6 EXCEPTIONS E CONCEITOS AVANÇADOS DE ORIENTAÇÃO A OBJETOS ....7


6.1 Tratamento de exceções .....................................................................................7
6.2 Classificação .......................................................................................................8
6.3 Captura e Tratamento de Exceções ....................................................................10
6.4 Propagação de exceções – Throws ....................................................................16
6.5 Criação de exceções ...........................................................................................18
6.6 Acesso a arquivos ...............................................................................................20
6.7 Polimorfismo ........................................................................................................31
6.8 Classe abstrata ...................................................................................................33
6.9 Modificador final ..................................................................................................37
6.10 Modificador static...............................................................................................40
6.11 Constantes ........................................................................................................43
6.12 Interfaces:..........................................................................................................44

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 7

6 EXCEPTIONS E CONCEITOS AVANÇADOS DE ORIENTAÇÃO A


OBJETOS

6.1 Tratamento de exceções

Durante a execução de um programa é possível que algumas exceções ou


erros aconteçam. Exceções e erros são problemas que podem ocorrer ao executar
algum comando.

Abaixo estão listados alguns problemas mais comuns:

 Falha na aquisição de algum recurso:


o Exemplo: abrir um arquivo, conectar com o banco de dados ou
acessar um web service.
 Tentativa de realizar algo impossível:
o Exemplo: divisão de um número por zero, acessar uma posição de
um array que não existe.
 Outras condições inválidas:
o Exemplo: evocar um método de um objeto que não foi instanciado,
realizar um cast inválido.
Esses eventos não esperados geralmente interrompem o fluxo da execução do
código. O tratamento de exceções permite verificar erros sem prejudicar o fluxo do
programa, por exemplo, um programa que lê dois números para realizar uma divisão.
O usuário pode inserir o número zero como divisor, assim, o programa lançará uma
exceção, já que não é possível dividir um número por zero. Dessa forma, ao invés da
exceção interromper o programa, podemos tratar esse possível cenário e pedir para
o usuário inserir um outro número válido.

Em linhas gerais, o fluxo para o tratamento de exceções no Java ocorre em três


passos:

 Uma exceção é lançada: um comando do código dispara uma condição


inesperada de erro.
 A exceção é capturada: em algum ponto do código, podemos adicionar
um comando para capturar a possível exceção.
 O tratamento de erro é realizado: após a captura da exceção, o
tratamento de erro adequado é executado.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 8

Realizando o tratamento das exceções, o programa consegue continuar a


execução normalmente. Exceções não capturadas provocam a finalização do
programa.

6.2 Classificação

Uma exceção é um objeto do tipo Exception. No polimorfismo, um objeto do


tipo Exception pode ser qualquer instância de uma subclasse de Exception.

Dentro da plataforma Java, podemos classificar as exceções em:

 Checked: exceção que deve ser tratada ou relançada pelo desenvolvedor,


geralmente herda da classe Exception.

 Unchecked: exceção que pode ser tratada ou relançada pelo


programador. Essa exceção é gerada pelo código mal escrito, caso a
exceção não for tratada, ela será automaticamente relançada. Geralmente
esse tipo de exceção herda de RuntimeException.

 Error: erro crítico, utilizado pela JVM para indicar que existe um problema
que não permite a execução do programa continuar.
O quadro abaixo apresenta um resumo das exceções no Java:

Quadro 6.1 – Resumo das exceções no Java


Fonte: Elaborado pelo autor (2017)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 9

A figura abaixo apresenta a hierarquia de classes de exceções do Java. Além


das exceções existentes na plataforma, podemos criar as nossas próprias exceções,
sejam elas checked (filhas de exception) ou unchecked (filhas de RuntimeException):

Figura 6.1 – The Hierarchy of Exception Classes


Fonte: Elaborado pelo autor (2017)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 10

A classe Throwable possui duas subclasses: Exception e Error.

Exception é a classe base para as subclasses de exceções checked e


unchecked, exceções que devem ou podem ser tratadas. Já a classe Error é a base
para as classes de exceções que não podem ser tratadas.

Agora vamos descrever algumas das exceções mais comuns, existentes na


plataforma Java:

 ArithmeticException: exceção unchecked que ocorre quando alguma


operação aritmética é inválida, operação esta que não pode ser resolvida,
como é o caso da divisão de um número por zero.

 ArrayIndexOutOfBoundsException: também é uma exceção do tipo


unchecked, ou seja, o desenvolvedor não é obrigado a tratar a exceção.
Esta exceção acontece quando tentamos acessar uma posição inválida de
um array. Uma posição inválida é uma posição que não existe, como uma
posição negativa ou um valor igual ou maior que o tamanho do vetor.
Lembre-se que o índice do vetor sempre começa em zero, ou seja, não
existe posição negativa e o último elemento de um array está posicionado
no tamanho do vetor menos um.

 NullpointerException: uma exceção unchecked, mais conhecida e


comum durante desenvolvimento. Ocorre na tentativa de acessar um
objeto que ainda não foi instanciado. Por exemplo, quando tentamos
acessar o método size() de um ArrayList que ainda não foi instanciado.

 FileNotFoundException: uma exceção checked, que precisamos tratar


quando tentamos acessar um arquivo que não foi encontrado.

 NumberFormatException: exceção que ocorre quando tentamos


transformar uma string inválida em algum tipo numérico. Esta exceção não
precisa ser tratada. (unchecked)

6.3 Captura e Tratamento de Exceções

Para tratar as exceções (checked ou unchecked) em tempo de execução, elas


devem ser capturadas e tratadas. O java possui duas estruturas importantes para o
tratamento de exceções:

 try-catch
 try-catch-finally

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 11

Estas duas estruturas têm a finalidade de separar o código que executa as


tarefas desejadas, das rotinas de tratamento das exceções:

try{
//Código
}catch(Exceção){
//Tratamento da exceção
}

O bloco try possui o código que pode gerar uma exceção, ou seja, este trecho
de código será monitorado pela JVM. Se um erro for gerado, o fluxo da execução é
desviado para o bloco catch, para o tratamento do erro. O uso do try indica que o
código está tentando realizar algo “perigoso”, passível de erro.

O bloco catch só é executado se uma exceção for gerada. Caso nenhuma


exceção seja lançada, a execução pula o bloco catch e continua normalmente. Se
uma exceção for lançada, o bloco try é finalizado e o fluxo de execução procura por
um bloco catch adequado para tratar a exceção, depois de executar o bloco catch, a
execução continua na primeira instrução após o último bloco catch.

Podemos adicionar vários blocos catch para capturar diferentes tipos de


exceções:

try{
//Código
}catch(Exceção 1){
//Tratamento da exceção 1
}catch(Exceção 2){
//Tratamento da exceção 2
}catch(Exceção 3){
//Tratamento da exceção 3
}

Dessa forma, somente o primeiro catch que se encaixar com o tipo da exceção
lançada será executado. Os catchs são testados de cima para baixo, um por um, por
isso, as exceções mais específicas devem ser colocadas nos primeiros catchs,
sempre obedecendo à ordem: das exceções mais específicas para as mais genéricas.

A exceção Exception é a mais genérica possível, pois todas as exceções


(checked ou unchecked) são filhas dela. Portanto, a captura dessa exceção deve ser
colocada no último catch, pois ela captura qualquer tipo de exceção que for lançada.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 12

Se nenhum catch conseguir capturar a exceção lançada, ela não será tratada,
como se não existisse o bloco try-catch.

Vamos desenvolver um exemplo: Ler dois números para dividir um pelo outro:

Scanner sc = new Scanner(System.in);

//Lê os dois números


int numero1 = sc.nextInt();
int numero2 = sc.nextInt();

//Realiza a divisão
int divisao = numero1/numero2;

//Exibe o resultado
System.out.println("O resultado é: " + divisao);

sc.close();

O código é bem simples, porém pode lançar uma exceção, caso o segundo
número informado pelo usuário for zero. Caso isso aconteça, o erro gerado será:

2
0
Exception in thread "main" java.lang.ArithmeticException: / by
zero
at br.com.fiap.tds.View.main(View.java:16)

A exceção ArithmeticException foi lançada, pois não é possível realizar uma


divisão por zero. Podemos perceber que essa exceção é unchecked, já que não fomos
obrigados a tratá-la.

Vamos realizar uma pequena alteração no código, para realizar o tratamento


da exceção:

Scanner sc = new Scanner(System.in);

// Lê os dois números
int numero1 = sc.nextInt();
int numero2 = sc.nextInt();

try {
// Realiza a divisão
int divisao = numero1 / numero2;
// Exibe o resultado
System.out.println("O resultado é: " + divisao);
} catch (ArithmeticException e) {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 13

System.err.println("Erro ao dividir!");
}
sc.close();

Dessa vez, adicionamos um bloco try-catch para capturar a exceção. Caso o


usuário insira um divisor igual a zero, a divisão vai gerar a ArithmeticException. Dessa
forma, o fluxo da execução será desviado para o bloco catch, (o código que imprime
o resultado não será executado) onde será exibida a mensagem de erro.

O resultado da execução do programa, com o divisor igual a zero:

2
0
Erro ao dividir!

Se o programa rodar sem lançar exceção, o resultado será exibido e o bloco


catch não será executado.

Dentro do bloco catch podemos recuperar a exceção gerada, através do


parâmetro. No exemplo acima, a exceção é recuperada no parâmetro com o nome
“e”.

A classe Throwable possui alguns métodos que podem exibir informações dos
erros gerados. Portanto, por herança, a exceção ArithmeticException também possuí
esses métodos:

 printStackTrace() – imprime a pilha de erro encontrada na exceção, nesta


pilha, podemos verificar o número da linha e classe onde a exceção foi
gerada;
 getMessage() – retorna uma mensagem contento a lista de erros
armazenadas em uma exceção.
No exemplo abaixo, vamos imprimir o StackTrace e a mensagem de erro da
exceção:

int[] array = new int[2];

try {
//Tenta acessar uma posição inexistente do vetor
array[2] = 10;
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("Mensagem de erro: " +
e.getMessage());

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 14

e.printStackTrace();
}

Dessa vez, a exceção será gerada quando tentamos acessar uma posição
inválida de um array: ArrayIndexOutOfBoundsException.

No bloco catch, utilizamos o método getMessage() e printStackTrace(), o


resultado será:

Mensagem de erro: 2
java.lang.ArrayIndexOutOfBoundsException: 2
at br.com.fiap.tds.View.main(View.java:10)

A mensagem possui o valor do índice inválido que tentamos acessar no array.


O printStackTrace imprime o rastro da pilha e exibe a exceção, a classe e a linha que
gerou a exceção: View.java:10. Classe View, linha 10.

Observe que utilizamos o System.err para exibir a mensagem de erro. Essa


classe é utilizada para exibir os erros em um programa Java. A saída de mensagem
possui a cor vermelha na visualização de mensagem. Podemos enviar o fluxo de saída
para um arquivo de log, enquanto que o fluxo de saída padrão de um System.out é a
tela da aplicação.

Além do bloco try-catch, podemos utilizar o bloco try-catch-finally para tratar


as exceções. O terceiro bloco finally é opcional e é utilizado quando sempre
precisamos executar um código, independentemente se aconteceu ou não uma
exceção:

 Se uma exceção for lançada: o fluxo de execução passa do bloco try


para o bloco catch adequado e após a sua execução, o bloco finally será
processado.
 Se não for gerado uma exceção: após executar todo o bloco try, o bloco
finally será processado.
O bloco finally não é obrigatório e quando usado deve sempre ser colocado no
final do último bloco catch.

Formato geral:

try {
//Fluxo normal que pode gerar uma exceção
} catch (Exception e) {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 15

//Fluxo alternativo, para tratamento da exceção


} finally{
//Fluxo normal,que sempre será executado
}

Um exemplo clássico da utilização do bloco finally é o fechamento da conexão


com o banco de dados. Sempre devemos fechar a conexão, independentemente da
concretização ou não da operação no banco.

Voltando ao primeiro exemplo, vamos tratar as exceções de divisão por zero e


entrada de dados inválida, quando o usuário digita um número inválido, como uma
letra. Também vamos adicionar um bloco finally para exibir uma mensagem para o
usuário e fechar o objeto scanner.

Scanner sc = new Scanner(System.in);


try {
// Lê os dois números
int numero1 = sc.nextInt();
int numero2 = sc.nextInt();
// Realiza a divisão
int divisao = numero1 / numero2;
// Exibe o resultado
System.out.println("O resultado é: " + divisao);
} catch (ArithmeticException e) {
System.err.println("Erro ao dividir!");
} catch (InputMismatchException e) {
System.err.println("Erro de entrada de dados!");
} finally{
System.out.println("Finalizando a execução do
programa!");
sc.close();
}

Dessa forma, temos três possíveis fluxos de execução:

 Sem gerar exceção, a saída será:


2
2
O resultado é: 1
Finalizando a execução do programa!

 Exceção causada pela divisão por zero, a saída será:


2
0
Erro ao dividir!Finalizando a execução do programa!

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 16

 Exceção causada pelo valor inserido inválido, a saída será:


a
Erro de entrada de dados!Finalizando a execução do
programa!

Observe que todos os fluxos sempre executam o bloco finally.

6.4 Propagação de exceções – Throws

Um método pode optar por não tratar a exceção e simplesmente propagá-la,


ou melhor, delegar para o método que a chamou. Dessa forma, podemos notificar o
método que invocou outro método, que alguma exceção ocorreu. Por exemplo, vamos
criar uma classe chamada Calculadora que será responsável por implementar as
operações aritméticas, entre eles a divisão:

public class Calculadora {

public int dividir(int n1, int n2){


return n1/n2;
}

Esse método pode lançar uma exceção, caso o valor de n2 for zero. Podemos
utilizar o try-catch para tratar a exceção, porém quem chamar o método dividir não
saberá se a operação ocorreu de forma correta ou se aconteceu algum erro:

public int dividir(int n1, int n2) {


try {
return n1 / n2;
} catch (ArithmeticException e) {
e.printStackTrace();
}
return 0;
}

Dessa forma, a melhor maneira de tratar a exceção é não tratar. Neste caso,
devemos somente propagar a exceção, notificando assim que algum problema
aconteceu na execução. Para isso, devemos adicionar na assinatura do método o
throws, junto da exceção que queremos propagar:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 17

public int dividir(int n1, int n2) throws Exception{


return n1 / n2;
}

Um método pode propagar mais de um tipo de exceção, para isso, basta


adicionar as exceções separadas por vírgula:

public void gravarArquivo(String valor) throws


SecurityException, FileNotFoundException, IOException{
//Código...
}

Portanto, a cláusula throws declara exceções que podem ser lançadas em


determinados métodos. Isso é uma vantagem para os desenvolvedores, pois
deixamos de modo explícito os eventuais erros que podem ocorrer na chamada do
método, permitindo que o tratamento adequado para o erro seja implementado.

Podemos também lançar uma nova exceção no nosso método. Para isso, basta
utilizar o comando throw:

public void depositar(double valor){


if (valor < 0){
throw new IllegalArgumentException();
}
saldo = saldo + valor;
}

No exemplo acima, estamos validando se o valor depositado é maior do que


zero. Se for, o valor é adicionado ao saldo, caso contrário, uma exceção do tipo
IllegalArgumentException será lançada. Isso indica que o valor passado como
parâmetro para o método é inválido. Repare que não foi preciso adicionar o throws
na assinatura do método, pois essa exceção é unchecked.

Caso a exceção seja checked, é necessário declará-la na assinatura do


método:

public void sacar(double valor) throws Exception{


if (valor > saldo){
throw new Exception("Saldo insuficiente");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 18

}
saldo = saldo - valor;
}

O método acima valida se o valor a ser retirado é maior do que o valor do saldo.
Caso o valor do saldo seja insuficiente, uma exception será lançada. Para isso, foi
necessário adicionar o throws na assinatura do método. Dessa forma, quem chamar
o método sacar deve tratar a exceção ou lançá-la novamente:

public static void main(String[] args) {

// Cria uma nova instância de Conta


Conta c = new Conta();
try {
// Saca
c.sacar(100);
} catch (Exception e) {
e.printStackTrace();
}
// Deposita
c.depositar(200);

Após criar um novo objeto conta, chamamos o método sacar, como ela lança
uma exceção checked, precisamos tratá-la ou lançá-la, neste caso, optamos por tratar
a exceção com o bloco try-catch. Já o método depositar lança uma exceção
unchecked, e dessa forma, não fomos obrigados a tratá-la. Porém, se uma exceção
ocorrer, ela será relançada automaticamente pelo método main que irá imprimir o erro
no console.

6.5 Criação de exceções

É possível também criar as nossas próprias classes de exceções. Observe o


exemplo acima, o método sacar lança a exceção mais genérica possível (Exception).
Para melhorar o uso das exceções e não utilizar uma exceção que serve para tudo,
podemos criar uma exceção específica para o erro que pode acontecer.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 19

Para criar uma exceção, basta criar uma classe que herde de Exception
(checked) ou RuntimeException (unchecked).

Vamos criar as nossas exceções, uma para identificar que o valor de saque é
inválido e outra para dizer que o saldo da conta é insuficiente.

A primeira exception será unchecked, ou seja, ela vai descender de


RuntimeException. Por padrão, as exceções no Java terminam com Exception:

public class ValorInvalidoException extends RuntimeException {

Para utilizá-la, vamos modificar o método de sacar, para que ela lance a nossa
exceção customizada:

public void depositar(double valor){


if (valor < 0){
throw new ValorInvalidoException();
}
saldo = saldo + valor;
}

Agora vamos criar uma exceção checked que identifica que o saldo é
insuficiente:

public class SaldoInsuficienteException extends Exception{

Para utilizá-la, podemos relançá-la, não se esquecendo de modificar o throws,


na assinatura do método:

public void sacar(double valor) throws


SaldoInsuficienteException{
if (valor > saldo){
throw new SaldoInsuficienteException();
}
saldo = saldo - valor;
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 20

Nos exemplos acima, criamos exceções checked e unchecked para ilustrar


nossos exemplos. Mas nada impediria de criar somente um tipo de exceção para a
nossa classe Conta. Procure sempre utilizar as exceções customizadas com
informações do motivo do erro.

6.6 Acesso a arquivos

O armazenamento de dados em variáveis, arrays, coleções ou qualquer outra


estrutura de dados em memória é temporário. Todas as informações armazenadas
em memória são perdidas quando o programa termina. Os arquivos são utilizados
para persistência de dados em longo prazo, mesmo após o término da execução do
programa.

Para armazenar grande quantidade de informações, como os clientes, produtos


ou vendas de uma empresa, os lugares mais adequados são os bancos de dados,
assunto que será abordado no próximo capítulo.

Os arquivos são muito úteis para armazenar as configurações do programa, ao


invés de colocar as configurações diretamente no código fonte. A grande vantagem
disso é a possibilidade de alterar o arquivo de configurações sem a necessidade de
recompilar e empacotar todo o programa novamente. Algo impossível, se a
configuração estivesse diretamente no código fonte.

Outra possibilidade de utilização de arquivos é a integração de sistemas


diferentes, algo muito utilizado. Um sistema pode realizar um processamento de
informações e gerar um arquivo final. Um outro sistema pode ler esse arquivo para
apresentar as informações, gerando assim a integração. Por exemplo, para calcular a
fatura de telefone, uma empresa pode utilizar um sistema de alto processamento que
gera um arquivo final com a fatura consolidada. Outro sistema lê esse arquivo e exibe
as informações na internet para o usuário final.

A plataforma Java possui uma facilidade na leitura e gravação de arquivos, pois


como ela é independente de plataforma, não precisamos nos preocupar com o tipo de
sistema operacional que o programa será executado. E claro, com uma linguagem
orientada a objetos, vamos utilizar objetos que realizam todo o trabalho para nós.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 21

Todas as entradas e saídas em Java são definidas em termos de fluxos, ou


streams, que são sequências ordenadas de dados que possui uma fonte, no caso de
streams de entrada, ou um destino, no caso de streams de saída.

Em outras palavras, uma stream é uma conexão para uma fonte de dados ou
para um destino de dados. A plataforma Java trata cada arquivo como uma stream.

A figura abaixo exibe os dois tipos de streams, dependendo do tipo de operação


que será realizada:

 Output stream: para gravar em um destino.


 Input stream: para ler de uma fonte.

Figura 6.2 – Streams


Fonte: Elaborado pelo autor (2017)

Arquivos baseados em um fluxo de caracteres são arquivos textos:

Figura 6.3 – Arquivos textos


Fonte: Elaborado pelo autor (2017)

Um arquivo texto pode ser lido e entendido facilmente pelas pessoas e também
de ser manipulado na plataforma Java. Podem ser utilizados facilmente por diversos
programas, pois é fácil saber a disposição dos registros e campos contidos nestes
arquivos. Geralmente, os registros nestes arquivos são representados pelas linhas,
enquanto os campos são representados por colunas ou valores separados por vírgula:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 22

Figura 6.4 – Exemplo de arquivo texto


Fonte: Elaborado pelo autor (2017)

Basicamente, para gravar dados em um arquivo texto, é preciso executar três


passos:

 Abrir o arquivo.
 Gravar os dados.
 Fechar o arquivo.

As classes para manipular os arquivos ficam dentro do pacote java.io. Duas


classes que podemos utilizar para a escrita em arquivo são: java.io.FileWriter e
java.io.PrintWriter.

A classe FileWriter é filha da classe OutputStreamWriter. Vamos utilizar essa


classe para abrir o arquivo para a escrita. Depois, vamos utilizar a classe PrintWriter
para escrever no arquivo. Para criar um objeto do tipo PrintWriter é preciso passar o
arquivo, ou seja o objeto FileWriter:

public static void main(String[] args) {

try {
//Abre o arquivo
FileWriter stream = new
FileWriter("arquivo.txt");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 23

PrintWriter print = new PrintWriter(stream);

//Escreve no arquivo
print.println("Teste");
print.println("Escrevendo no arquivo");

print.close();
//Fecha o arquivo
stream.close();
} catch (IOException e) {
e.printStackTrace();
}

O exemplo acima apresenta o método main que abre, escreve e fecha um


arquivo chamado “arquivo.txt”. Esse arquivo será aberto se existir, ou criado, caso não
exista. Observe que na instanciação do FileWriter é passado o caminho e nome do
arquivo. Como não especificamos nenhum caminho, o arquivo estará na pasta raiz do
programa:

Figura 6.5 – Exemplo de pasta raiz do programa


Fonte: Elaborado pelo autor (2017)

Podemos também especificar o caminho completo do arquivo, por exemplo:

FileWriter stream = new FileWriter("C://arquivo.txt");

Após criar o objeto FileWriter, foi instanciado o objeto PrintWriter, passando


com parâmetro o objeto que encapsula o nosso arquivo:

PrintWriter print = new PrintWriter(stream);

Com o objeto PrintWriter é possível utilizar os métodos print ou println para


escrever no arquivo:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 24

print.println("Teste");
print.println("Escrevendo no arquivo");

Para finalizar chamamos o método close do objeto PrintWriter e FileWriter,


para fechar o arquivo texto:

print.close();
stream.close();

Observe que foi preciso tratar a exceção IOException, pois podemos ter
problemas na hora de abrir ou manipular o arquivo.

O resultado da execução será o arquivo texto com as informações gravadas:

Figura 6.6 – O resultado da execução


Fonte: Elaborado pelo autor (2017)

Para ler o arquivo, devemos realizar três passos também:

 Abrir o arquivo.
 Utilizar o arquivo (ler os dados).
 Fechar o arquivo.
As classes que podemos utilizar para ler os dados de um arquivo são:
java.io.FileReader e java.io.BufferedReader. A classe FileReader descende da classe
InputStreamReader.

O exemplo abaixo abre o arquivo criado no exemplo anterior, o “arquivo.txt”, lê


cada linha do arquivo e exibe no console.

public static void main(String[] args) {

try {
//Abre o arquivo
FileReader stream = new
FileReader("arquivo.txt");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 25

BufferedReader reader = new


BufferedReader(stream);

//Lê uma linha do arquivo


String linha = reader.readLine();
while (linha != null){
System.out.println(linha);
//Lê a próxima linha do arquivo
linha = reader.readLine();
}

reader.close();
//Fecha o arquivo
stream.close();
} catch (IOException e) {
e.printStackTrace();
}

Assim como no exemplo de escrita de arquivo, precisamos abrir o arquivo, mas


dessa vez utilizarmos a classe FileReader ao invés do FileWriter. Também foi
necessário passar o nome do arquivo que queremos abrir como parâmetro. A mesma
regra do caminho se aplica, caso o arquivo esteja em outro diretório, devemos
especificá-lo:

FileReader stream = new FileReader("C://arquivo.txt");

Se o arquivo não for encontrado, será gerada a exceção


FileNotFoundException.

Após criar o objeto FileReader, foi instanciado o objeto BufferedReader para


realizar a leitura do arquivo. Para criar esse objeto, passamos como parâmetro o
objeto FileReader criado anteriormente:

BufferedReader reader = new BufferedReader(stream);

A classe BufferedReader possui o método readLine(), ele lê uma linha do


arquivo e retorna uma String com o valor lido ou null, caso o arquivo não possua mais
linhas para serem lidas.

Dessa forma, utilizamos esse método para ler uma linha e depois
criamos um laço de repetição, que vai ser executado até que a String recuperada for
nula, ou seja, até que todas as linhas do arquivo forem lidas.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 26

//Lê uma linha do arquivo


String linha = reader.readLine();
while (linha != null){
System.out.println(linha);
//Lê a próxima linha do arquivo
linha = reader.readLine();
}

Para finalizar, é preciso fechar o FileReader e o BufferedReader:

reader.close();
//Fecha o arquivo
stream.close();

A plataforma Java oferece várias Classes para a leitura/escrita de arquivos


texto. Caso implementação é destinada a uma aplicação específica, essas classes
ficam dentro do pacote java.io:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 27

Figura 6.7 – Classes


Fonte: Elaborado pelo autor (2017)

As principais classes desse pacote são:

 Classes para entrada ou saída baseada em bytes:


o FileInputStream: para entrada baseada em bytes de um arquivo.
o FileOutputStream: para saída baseada em bytes para um
arquivo.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 28

o RandomAccessFile: para entrada e saída baseada em bytes de


e para um arquivo.
 Classes para entrada e saída baseada em caracteres:
o FileReader: para entrada baseada em caracteres de um arquivo.
o FileWriter: para saída baseada em caracteres para um arquivo
Outra classe importante da API de IO do Java é o File. Essa classe representa
um arquivo ou um diretório no sistema de arquivo nativo. Ela permite obter
informações sobre o arquivo ou diretório, e não sobre o seu conteúdo.

Ao contrário das outras classes que estudamos, esta classe não abre o arquivo
ou permite o processamento de seu conteúdo. A sua função é gerenciar o arquivo ou
diretório, o seu caminho (path), verificar permissões, a existência, criar, renomear etc.

Um objeto da classe File apenas representa o arquivo ou diretório, isto não quer
dizer que o arquivo ou diretório exista de fato.

O quadro abaixo apresenta os principais métodos da classe File:

Quadro 6.2 – Os principais métodos da classe File


Fonte: Elaborado pelo autor (2017)

O exemplo abaixo cria um objeto do tipo File, passando o nome do arquivo, é


possível também passar o nome do arquivo e o seu caminho. O código verifica se o
arquivo existe. Se existir, ele recupera algumas informações a respeito do arquivo e
exibe no console. Caso não exista, o programa tenta criar o arquivo:

public static void main(String[] args) {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 29

File arquivo = new File("arquivo.txt");

// Verifica se o arquivo existe


if (arquivo.exists()) {
System.out.println("O arquivo existe!"+
"\nPode ser lido: " + arquivo.canRead() +
"\nPode ser gravado: " + arquivo.canWrite()
+
"\nTamanho: " + arquivo.length() +
"\nCaminho: " + arquivo.getPath());
} else {
// Cria o arquivo
try {
if (arquivo.createNewFile())
System.out.println("Arquivo criado!");
else
System.out.println("Arquivo não criado!");
} catch (IOException e) {
e.printStackTrace();
}
}
}

Se o arquivo for criado com sucesso, o método createNewFile() retorna o valor


true, caso contrário false.

Podemos também utilizar o objeto File para verificar se um diretório existe ou


para criá-lo. O código abaixo faz exatamente isso:

public static void main(String[] args) {


File diretorio = new File("fiap");

if (diretorio.exists()){
System.out.println("Diretório existe!");
}else{
if (diretorio.mkdir())
System.out.println("Diretório criado!");
else
System.out.println("Diretório não criado.");
}
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 30

O objeto File foi instanciado com o valor “fiap”, que é o nome do diretório.
Primeiro verificamos se o diretório existe, caso não exista, utilizamos o método mkdir()
para criar o diretório. Esse método retorna um valor booleano, verdadeiro se o diretório
foi criado ou false, caso contrário.

Após criar um diretório, podemos criar um arquivo dentro dele, conforme o


código abaixo:

public static void main(String[] args) {


File diretorio = new File("fiap");

if (diretorio.exists()){
System.out.println("Diretório existe!");
}else{
if (diretorio.mkdir())
System.out.println("Diretório criado!");
else
System.out.println("Diretório não
criado.");
}

File arquivo = new File(diretorio,"file.txt");


try {
if (arquivo.createNewFile())
System.out.println("Arquivo criado!");
else
System.out.println("Arquivo não criado!");
} catch (IOException e) {
e.printStackTrace();
}
}

Observe que primeiro verificamos se o diretório existe e se caso necessário,


criamos. Depois instanciamos uma classe File passando o nome do arquivo e o objeto
File que representa o diretório:

File arquivo = new File(diretorio,"file.txt");

Com esse novo objeto File, tentamos criar o arquivo dentro do diretório.

A classe File pode ser utilizada em conjunto com as outras classes de


manipulação do conteúdo do arquivo, vistos acima. Para isso, basta utilizar o objeto
File no momento de criar um FileWriter ou FileReader:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 31

try {
//Abre o arquivo para escrita
FileWriter writer = new FileWriter(arquivo);
//Abre o arquivo para leitura
FileReader reader = new FileReader(arquivo);
//Código...
} catch (IOException e) {
e.printStackTrace();
}

Depois, basta instanciar a classe PrintWriter para escrever no arquivo ou


BufferedReader para ler.

6.7 Polimorfismo

A palavra polimorfismo significa: “qualidade ou estado de ser capaz de assumir


diferentes formas” dicionário Houaiss. Na programação orientada a objetos,
polimorfismo significa ter múltiplos comportamentos.

Um método polimórfico resulta em diferentes ações dependendo do objeto que


está sendo referenciado. A capacidade polimórfica decorre diretamente da herança,
pois permite que uma variável de referência e o objeto sejam diferentes, ou seja,
podemos definir uma variável do tipo Conta e armazenar um objeto de
ContaCorrente, se este herdar da classe Conta. Portanto, o tipo da variável de
referência pode ser uma superclasse para o tipo do objeto real. Qualquer objeto de
uma classe que herde o tipo declarado da variável pode ser atribuído a ela.

Com o polimorfismo, é possível escrever um código que não tenha que ser
alterado quando novos tipos de subclasse forem introduzidos no sistema. Porém, a
utilização mais importante do polimorfismo se dá quando dois objetos, sendo um da
superclasse e outro da subclasse, executam ações diferentes quando o mesmo
método é invocado. Isso é possível através da sobrescrita de métodos, quando a
subclasse sobrescreve o método implementado na superclasse. Já vimos isso nos
primeiros capítulos de orientação a objetos.

Observe as classes abaixo:

public class Conta {

protected double saldo;

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 32

public void sacar(double valor) throws SaldoInsuficienteException{


if (valor > saldo){
throw new SaldoInsuficienteException();
}
saldo = saldo - valor;
}

public class ContaCorrente extends Conta{

private double limite;

@Override
public void sacar(double valor) throws SaldoInsuficienteException {
if (valor > saldo + limite){
throw new SaldoInsuficienteException();
}
saldo = saldo - valor;
}

Neste exemplo, a classe Conta possui um atributo que armazena o saldo e um


método que realiza saque. Observe que o método pode lançar uma exceção, caso o
valor a ser sacado é maior do que o saldo.

A classe ContaCorrente herda da classe conta, ou seja, a superclasse é a


Conta e a subclasse ContaCorrente. A subclasse adiciona um outro atributo que é o
limite da conta. O método sacar foi sobrescrito, agora a exceção é lançada caso o
valor a ser sacado seja maior que o saldo mais o limite disponível.

No exemplo abaixo, definimos uma variável de referência do tipo Conta e


atribuímos um objeto do tipo ContaCorrente:

public static void main(String[] args) {

Conta cc = new ContaCorrente();


try {
cc.sacar(20);
} catch (SaldoInsuficienteException e) {
e.printStackTrace();
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 33

Depois foi chamado o método sacar. Qual método será executado? O método
definido na classe Conta ou da classe ContaCorrente?

O método do objeto armazenado na variável será executado. Ou seja, o método


definido na ContaCorrente. Sempre a execução acontece com o objeto armazenado
e não com o tipo da variável.

6.8 Classe abstrata

No nosso exemplo, a classe Conta é uma conta genérica, que serve como base
para os outros tipos de conta como a conta corrente, conta poupança, conta
investimento etc. Por isso, não faz sentido instanciar uma classe Conta, pois não
existe uma “Conta Genérica” no nosso sistema. O que podemos instanciar são as
subclasses da classe conta. É ai que entra a classe Abstrata.

A palavra abstrata significa que possui alto grau de generalização (dicionário


Houaiss). Uma classe abstrata possui algumas características como:

 Não pode ser instanciada.


 Pode possuir métodos abstratos.
Logo, vamos discutir sobre métodos abstratos, porém, observe o destaque da
palavra “pode”, isso significa que a classe pode conter esse tipo de método e não que
deve.

A primeira característica é que uma classe abstrata não pode ser instanciada,
ou seja, não podemos utilizar o operador new. Dessa forma, nunca vamos ter uma
instancia de uma classe abstrata dentro da nossa aplicação.

O propósito de uma classe abstrata é atuar como uma superclasse. É uma


classe que existe para ser herdada. Dessa forma, ela será a base para as outras
classes que serão desenvolvidas.

Então a nossa classe Conta é perfeita para ser abstrata. Ela será a base para
todas as outras contas em nosso sistema.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 34

Como visto no exemplo acima, podemos definir uma variável com o tipo da
classe abstrata, porém, devemos atribuir um objeto de uma subclasse da mesma, a
fim de utilizar o polimorfismo.

Uma classe que não é abstrata é chamada de classe Concreta. Ao projetar uma
hierarquia de herança, devemos definir quais classes serão concretas e abstratas.

Uma classe abstrata pode conter métodos abstratos. O método abstrato não
possui implementação, ela define somente a assinatura do método. A sua subclasse,
obrigatoriamente, precisará implementar o método, caso esta seja concreta.

Em uma classe concreta não é permitido definir métodos abstratos. Se isso


acontecer, obrigatoriamente a classe deverá ser abstrata também. E isso faz sentido,
pois se fosse possível ter um método sem implementação em uma classe concreta, o
que aconteceria se você instanciar a classe e chamar este método? Difícil dizer. Por
essa razão que a classe também deve ser abstrata, para não ser possível instanciá-
la.

É possível ter uma herança com várias classes abstratas, porém a primeira
classe concreta da hierarquia será obrigada a implementar todos os métodos
abstratos definidos pelas suas superclasses.

Implementar o método abstrato é igual a sobrescrever um método, devemos


definir um método com o mesmo nome e parâmetros (assinatura) na subclasse e
implementá-la.

A figura abaixo representa uma classe abstrata no diagrama de classes:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 35

Figura 6.8 – Classe abstrata no diagrama de classes


Fonte: Elaborado pelo autor (2017)

Observe que o nome da classe abstrata e o método abstrato ficam em itálico.


As classes concretas e métodos implementados são exibidos sem nenhuma
formatação diferente.

Para definir uma classe ou método abstrato basta adicionar o modificador


abstract.

Observe o exemplo abaixo, vamos definir a classe Conta como abstrata e


adicionar o método depositar como abstrato:

public abstract class Conta {


protected double saldo;

public void sacar(double valor) throws SaldoInsuficienteException{


if (valor > saldo){
throw new SaldoInsuficienteException();
}
saldo = saldo - valor;
}

public abstract double verificarSaldo();

O método verificarSaldo é abstrato, portanto não possui implementação. Dessa


forma, a assinatura do método termina com ponto e vírgula (;).

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 36

Agora a subclasse ContaCorrente está com erro de compilação devido à adição


do método abstrato na classe Conta. Para arrumar o problema, devemos implementar
o método verificarSaldo na classe ContaCorrente:

public class ContaCorrente extends Conta{

private double limite;

@Override
public void sacar(double valor) throws SaldoInsuficienteException {
if (valor > saldo + limite){
throw new SaldoInsuficienteException();
}
saldo = saldo - valor;
}

@Override
public double verificarSaldo() {
return saldo + limite;
}

//Gets e Sets

Agora vamos implementar a classe ContaPoupanca:

public class ContaPoupanca extends Conta {

@Override
public double verificarSaldo() {
return saldo;
}
}

A classe ContaPoupanca é obrigada a implementar o método verificarSaldo,


pois ela é concreta. Porém, ela não foi obrigada a implementar o método sacar, pois
esse método não é abstrato e está implementado na superclasse Conta. Dessa forma,
a classe ContaPoupanca possui o mesmo método sacar da classe Conta e
implementa um comportamento específico no método verificarSaldo.

Abaixo está outro exemplo de representação de um diagrama de classes:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 37

Figura 6.9 – Representação de um diagrama de classes


Fonte: Elaborado pelo autor (2017)

A classe Forma é abstrata e possui um atributo com os métodos get e set. Ela
define também um método abstrato calcularArea. Esse método é abstrato porque a
classe Forma não consegue calcular a área, pois isso depende do tipo da forma.
Assim, todas as subclasses deverão implementar o método abstrato e calcular a sua
área.

6.9 Modificador final

O modificador final trabalha de forma contrária em relação ao modificador


abstract. Uma classe Java marcada como final não pode ser estendida. Exemplo:

public final class ContaPoupanca extends Conta {

@Override
public double verificarSaldo() {
return saldo;
}

A classe ContaPoupanca não pode possuir nenhuma subclasse. Dessa forma,


não podemos utilizá-la como base para criar nenhuma outra classe:

public class ContaPoupancaEspecial extends ContaPoupanca{//Não


Compila
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 38

O código acima não compila, pois a ContaPoupanca está marcada como final
e por isso não pode ser estendida.

Além das classes, também podemos utilizar a palavra-chave final em atributos.


Dessa forma, o valor do atributo será imutável, ou seja, não podemos alterar o valor
do atributo durante o ciclo de vida do objeto.

O atributo final é chamado de atributos constantes e sua inicialização é feita no


momento da declaração:

public class Circulo {

private final double NUMERO_PI = 3.1416;

Observe que o nome do atributo está um pouco diferente do utilizado até o


momento. Por convenção, os atributos constantes devem ser criados com todas as
letras em maiúsculas e caso o nome seja composto por mais de uma palavra, estes
devem ser separados pelo caractere underline.

O atributo NUMERO_PI está marcado como private, por isso só é visível dentro
da própria classe. Podemos criar um método dentro da classe Circulo para calcular o
valor da sua respectiva área. Para isso, precisamos de um atributo para armazenar o
valor do raio do círculo:

public class Circulo {

private final double NUMERO_PI = 3.1416;

private double raio;

public double calcularArea(){


return NUMERO_PI*raio*raio;
}

public double getRaio() {


return raio;
}

public void setRaio(double raio) {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 39

this.raio = raio;
}

Observe que utilizamos o atributo final da mesma forma que utilizamos os


outros atributos. A diferença é que não podemos alterar o seu valor:

public double calcularArea(){


raio = 10; //OK
NUMERO_PI = 10; //Não Compila
return NUMERO_PI*raio*raio;
}

Além de classes e atributos, podemos utilizar o modificador final também em


métodos, Dessa forma, método não poderá ser sobrescrito:

public final double calcularArea(){


return NUMERO_PI*raio*raio;
}

No código acima, o método calcularArea foi marcado como final, dessa forma,
se criarmos uma subclasse da classe Circulo e tentar implementar um método para
sobrescrever o método calcularArea, este não irá compilar:

public class Circulo2 extends Circulo {

public final double calcularArea(){//Não compila


}

Portanto, o modificador final é importante quando queremos que nenhum outro


desenvolvedor estenda a nossa classe ou modifique o comportamento de um método
em uma classe filha. É utilizado também para criar valores constantes.

O quadro abaixo resume as principais características da palavra-chave final,


dependendo de onde está sendo utilizada:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 40

Quadro 6.3 – Principais características da palavra-chave final


Fonte: Elaborado pelo autor (2017)

6.10 Modificador static

Outro modificador presente na plataforma java é o static. Esse modificador


pode ser aplicado aos membros de uma classe: métodos e atributos.

Um atributo ou método estático são compartilhados por todas as instancias de


uma determinada classe. Existem valores de atributos que devem ser compartilhados
entre todas os objetos de uma Classe, dessa forma, podemos marcá-la com o
modificador static.

Quando um atributo é declarado como estático, ele passa a se referir a Classe


e não mais à instância da Classe, ou seja, o atributo será igual para todos os objetos,
independentemente dos respectivos números de instâncias.

Por isso, se um objeto mudar o valor do atributo estático, todos os outros


objetos terão acesso ao novo valor:

public class AcessoCatraca {

private static int totalAcesso;


}

Um método marcado como estático não depende das características de cada


objeto. Podem ser invocados sem precisar de uma instancia da classe e são utilizados
para realizar uma tarefa comum para todos os objetos.

Já utilizamos um método estático. Lembra-se do método main?

public static void main(String[] args) {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 41

Um método estático utiliza apenas informações contidas em seus parâmetros


e nos atributos estáticos, ou seja, um método estático pode acessar somente atributos
estáticos, os atributos não estáticos não são acessíveis. O contrário é possível,
acessar um atributo estático dentro de um método não estático:

public class AcessoCatraca {

private static int totalAcesso;

private String nome;

public void entrar(String nome){


this.nome = nome;
totalAcesso = totalAcesso + 1;
}

public static int recuperarTotal(){


return totalAcesso;
}
}

O exemplo acima define um atributo estático (totalAcesso) e um atributo não


estático (nome). O método entrar depende do atributo nome. Dessa forma, o método
não pode ser estático, pois ele precisa utilizar um atributo não estático. Já o método
recuperarTotal é estático pois utiliza somente o atributo totalAcesso que também é
estático. Assim, ela não depende de nenhum atributo de instância da classe.

Um detalhe é que se retirarmos o modificador static do método recuperarTotal


não causaria nenhum problema de compilação. Porém a melhor opção seria deixar o
método estático, pois ele poderá ser acessado sem uma instância da classe por
realizar uma tarefa comum a todos os objetos.

Um exemplo de utilização de métodos estáticos é a classe java.lang.Math. Ela


possui vários métodos estáticos que auxiliam o desenvolvedor nas operações
matemáticas. Veja mais na documentação da Oracle.

Para utilizar um método estático não é preciso de uma instância da classe:

public static void main(String[] args) {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 42

int total = AcessoCatraca.recuperarTotal();


System.out.println("Total " + total);

long numero = Math.round(2.9);


System.out.println("Número arredondado: " + numero);
}

O código acima acessa o método estático recuperarTotal, da classe


AcessoCatraca e utiliza um método de arredondamento da classe Math. Em ambos
os casos, não foi preciso instanciar suas respectivas classes.

Para acessar o método entrar, da classe AcessoCatraca será preciso criar o


objeto:

public static void main(String[] args) {

AcessoCatraca a1 = new AcessoCatraca();


a1.entrar("Thiago");

AcessoCatraca a2 = new AcessoCatraca();


a2.entrar("Leandro");

int total = AcessoCatraca.recuperarTotal();


System.out.println("Total " + total);

Qual será o resultado da execução acima?

O método entrar incrementa o valor do atributo estático totalAcesso, um atributo


estático se refere à classe e não ao objeto, então eles irão compartilhar o mesmo
valor. Como o método foi chamado duas vezes, independentemente do objeto, no final
da execução o valor total será 2:

Total 2

É possível também chamar o método estático utilizando o objeto, porém o


resultado final será igual:

int total = a1.recuperarTotal();


System.out.println("Total " + total);

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 43

Resultado:

Total 2

Os métodos e atributos estáticos em um diagrama de classe são representados


com um sublinhado:

Figura 6.10 – Os métodos e atributos estáticos em um diagrama de classe representados com um


sublinhado
Fonte: Elaborado pelo autor (2017)

6.11 Constantes

É comum utilizar os modificadores public, static e final ao declarar uma


constante no Java. As constantes podem ser públicas, ou seja, todos podem ter
acesso. Estático, pois não existe a necessidade de cada objeto ter a sua própria
constante e final, para que o valor da constante nunca se altere.

Por convenção, o nome de uma constante é sempre escrito em maiúsculo com


as palavras separadas por underline:

public class Constantes {

public static final String JANEIRO = "Janeiro";


public static final double TAXA_RETIRADA = 10;
public static final int NUMERO_DIAS_SEMANA = 7;
public static final Estado SAO_PAULO = new Estado("São Paulo","SP");

Para acessar as constantes, basta utilizar o nome da classe:

public static void main(String[] args) {

System.out.println(Constantes.JANEIRO);

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 44

System.out.println(Constantes.TAXA_RETIRADA);

6.12 Interfaces:

A plataforma Java e algumas outras linguagens de programação orientada a


objetos possuem o conceito de Interface. Interface define um conjunto de requisitos
para as classes implementá-las. Uma interface não é uma classe.

Interface é um contrato entre a classe e o mundo externo. Quando uma classe


implementa uma interface, ela está comprometida a fornecer todos os
comportamentos definidos na interface.

Uma interface em Java não pode ser instanciada. Assim como as classes, uma
interface pode ser composta por atributos e métodos. Porém, como ela não é
instanciada, não apresenta construtores.

A plataforma Java não permite a herança múltipla, ou seja, não é possível


herdar duas classes diretamente. Porém, uma classe Java pode implementar uma ou
mais interfaces, devendo, assim, definir todos os métodos publicados por todas as
interfaces implementadas.

Uma classe abstrata não é obrigada a implementar todos os métodos definidos


na interface. Porém, em uma classe concreta é obrigatório.

Todos os atributos e métodos de uma interface são implicitamente públicos.


Todo atributo em uma interface é implicitamente público, final e estático (Constante).
Como esses qualificadores são fixos, não precisamos declará-los.

Exemplo de uma interface:

public interface Autenticavel {

String MSG_LOGOUT = "Saindo";

boolean login(String usuario, String senha);

void logou();

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 45

Note que após o modificador de acesso, a palavra-chave utilizada é interface


e não class. Dessa forma, sabemos que se trata de uma interface e não de uma
classe. Observe também que o arquivo gerado possui a extensão .java.

Para criar uma interface no eclipse, clique com o botão direito do mouse na
pasta src e escolha a opção New -> Interface:

Figura 6.11 – Exemplo de criação de uma interface no eclipse


Fonte: Elaborado pelo autor (2017)

Após isso, defina um pacote e nome da interface:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 46

Figura 6.12 – Definindo pacote e nome


Fonte: Elaborado pelo autor (2017)

A figura abaixo representa uma interface no diagrama de classes:

Figura 6.13 – Representação de uma interface no diagrama de classes


Fonte: Elaborado pelo autor (2017)

Para uma classe implementar uma interface, devemos utilizar a palavra-chave


implements:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 47

public class Usuario implements Autenticavel{

@Override
public boolean login(String usuario, String senha) {
// TODO Auto-generated method stub
return false;
}

@Override
public void logou() {
// TODO Auto-generated method stub

Como a classe Usuario implementa a interface Autenticavel, ela deve


implementar todos os métodos definidos pela interface. Caso isso não seja feito,
teremos um erro de compilação.

Se uma classe implementar mais de uma interface, devemos separá-las por


vírgula:

public class Usuario implements Autenticavel, Serializable {


// Código…
}

E se uma classe implementar uma ou mais interface e estender uma classe,


primeiro precisamos definir a herança:

public class Usuario extends Pessoa implements Autenticavel {


// Código…
}

No diagrama de classes, a representação de uma implementação é definida


por uma seta com a sua linha pontilhada:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 48

Figura 6.14 – A representação de uma implementação


Fonte: Elaborado pelo autor (2017)

Sempre utilize interfaces quando for preciso prover operações comuns a


classes de hierarquia diferentes:

Figura 6.15 – Utilização de interfaces


Fonte: Elaborado pelo autor (2017)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 49

O diagrama acima, define que as classes Morcego e Gaviao implementarão a


interface Voador, pois ambas as classes possuem essas características. Já a classe
Cavalo e Avestruz são Corredores. E por fim, todas as classes que definem um animal
Nadador deverão implementar essa interface.

Utilizar interfaces permite o uso do polimorfismo. Por exemplo, duas classes


que implementam uma mesma interface podem ser atribuídas a uma variável do tipo
da Interface. Porém, a execução dependerá do tipo do objeto que essa variável
armazena:

Figura 6.16 – Exemplo de duas classes que implementam uma mesma interface
Fonte: Elaborado pelo autor (2017)

No exemplo acima, as classes Avestruz e Cavalo implementam a interface


Corredor. Foi instanciada cada uma dessas classes e atribuídas a duas variáveis do
tipo da interface (Corredor). Quando o método correr é invocado, será executado o
método definido na classe correspondente ao tipo do objeto armazenado na variável.

Uma interface pode estender uma ou mais interfaces:

public interface Gerenciavel extends Autenticavel {


}

public interface Gerenciavel extends Autenticavel, Serializable


{
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 50

Podemos ter métodos concretos em uma interface. Para isso, devemos utilizar
o modificador default. Esses método chamado de default method, serão herdados
por todas as classes que implementarem a interface. Não sendo necessário
implementá-la na classe.

Exemplo:

public interface Corredor {

default void parar(){


System.out.println("Parando..");
}

Dessa forma, as classes que implementarem a interface Corredor já receberão


o método parar, sem precisar implementá-lo.

public class Avestruz implements Corredor{

Podemos utilizar o método com uma instancia da classe:

public static void main(String[] args) {

Corredor corredor = new Avestruz();


corredor.parar();

Um método static é outro método que possui implementação em uma interface.


A diferença entre o método default e o método estático é que o estático pertence à
interface e não pode ser sobrescrito. Um default method pode ser sobrescrito em
uma classe e precisa de uma de suas instâncias para ser executada.

public interface Corredor {

default void parar(){


System.out.println("Parando..");
}

static void acelerar(){

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 51

System.out.println("Acelerando");
}
}

Na classe avestruz, podemos sobrescrever o método default:

public class Avestruz implements Corredor{

@Override
public void parar() {
System.out.println("Avestruz parando...");
}
}

Porém, não é possível sobrescrever o método default. E para executar o


método estático, devemos referenciar a interface e não a classe ou o objeto dela:

public static void main(String[] args) {

Corredor corredor = new Avestruz();


corredor.parar();

Corredor.acelerar();

Em uma interface, podemos definir todos os tipos de métodos em conjunto, ou


seja, podemos ter métodos abstratos (sem implementação, que deverá ser
implementado na classe), métodos defaults e métodos estáticos:

public interface Corredor {

void correr(int velocidade);

default void parar(){


System.out.println("Parando..");
}

static void acelerar(){


System.out.println("Acelerando");
}
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 52

Para finalizar, podemos utilizar o operador instanceOf para verificar se uma


classe é do tipo de uma interface ou outra classe (herança). Esse operador retorna
true se o objeto à esquerda do operador é do tipo da classe ou interface especificada
à direita do operador:

public static void main(String[] args) {

Corredor avestruz = new Avestruz();

if (avestruz instanceof Corredor){


System.out.println("É um corredor");
}else{
System.out.println("Não é um corredor");
}

No exemplo acima, o resultado será “É um corredor”, pois o objeto referenciado


na variável avestruz é do tipo Avestruz, e este implementa a interface Corredor.

Podemos utilizar esse operador também para verificar se o objeto é do tipo de


uma classe:

public static void main(String[] args) {

Corredor avestruz = new Avestruz();

if (avestruz instanceof Animal){


System.out.println("É um animal");
}else{
System.out.println("Não é um animal");
}

Neste caso, a classe Avestruz herda da classe Animal. Dessa forma, o


resultado final será “É um animal”. Com esse operador, podemos testar um tipo de um
objeto.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 53

REFERÊNCIAS

BARNES, David J. Programação Orientada a Objetos com Java: Uma introdução


Prática Utilizando Blue J. São Paulo: Pearson, 2004.

CADENHEAD, Rogers; LEMAY, Laura. Aprenda em 21 dias Java 2 Professional


Reference. 5.ed. Rio de Janeiro: Elsevier, 2003.

DEITEL, Paul; DEITEL, Harvey. Java Como Programar. 8.ed. São Paulo: Pearson,
2010.

HORSTMANN, Cay; CORNELL, Gary. Core Java: Volume I Fundamentos. 8.ed. São
Paulo: Pearson 2009.

SIERRA, Kathy; BATES, Bert. Use a cabeça! Java. Rio de Janeiro: Alta Books, 2010.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Exceptions + vários outros, design patters Página 54

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com
julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 2

LISTA DE FIGURAS

Figura 5.1 – Vetor com 10 posições ................................................................... 9


Figura 5.2 – Estado atual do array de carros ................................................... 13
Figura 5.3 – Resultado da execução ................................................................ 18
Figura 5.4 – Variáveis nome e nome2 .............................................................. 22
Figura 5.5 – Resultado “As strings são iguais” ................................................. 22
Figura 5.6 – Estrutura de coleções e mapas .................................................... 34
Figura 5.7 – Detalhes da declaração de uma ArrayList utilizando Generics .... 43
Figura 5.8 – Exceção quando o tipo não é compatível com o cast .................. 44
Figura 5.9 – Com Generics, código não permite inserção de elemento que não
corresponde ao tipo de objeto da lista .............................................................. 44

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 3

LISTA DE QUADROS

Quadro 5.1 – Sequências de Escape ............................................................... 18


Quadro 5.2 – Principais métodos da interface Collection ................................. 35
Quadro 5.3 – Principais métodos de uma lista ................................................. 36
Quadro 5.4 – Métodos herdados da interface Collection ................................. 39
Quadro 5.5 – Definições da interface Map ....................................................... 41

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 4

SUMÁRIO

5 ESTRUTURAS DE REPETIÇÃO, ARRAYS, STRINGS E COLEÇÕES .......... 5


5.1 While ............................................................................................................ 5
5.2 Do-While....................................................................................................... 6
5.3 For ................................................................................................................ 7
5.4 Arrays ........................................................................................................... 8
5.5 Strings ........................................................................................................ 15
5.5.1 Comparação de strings ........................................................................... 21
5.6 Collections Framework (COLEÇÕES) ........................................................ 33
5.6.1 List ........................................................................................................... 36
5.6.2 Set ........................................................................................................... 39
5.6.3 Map ......................................................................................................... 40
5.6.4 Generics .................................................................................................. 42
REFERÊNCIAS ................................................................................................ 46

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 5

5 ESTRUTURAS DE REPETIÇÃO, ARRAYS, STRINGS E


COLEÇÕES

Estruturas de repetição ou loops permitem que um bloco de código seja


executado repetidamente, enquanto alguma condição permanecer verdadeira.

No Java existem três estruturas de repetição que veremos a seguir:


While, Do-While e For.

5.1 While

O loop while executa um bloco de código enquanto a condição for


verdadeira.

Estrutura básica do comando:

Perceba que o loop while nunca será executado se a condição for false
desde o início.

O exemplo abaixo exibe um trecho de código que imprime os números


do 1 ao 10:

No exemplo acima, o número é iniciado com o valor 0. Na primeira


iteração, ele é menor do que 10, então o while é executado. O número é
incrementado em uma unidade e seu valor é exibido no console. Na segunda
iteração, o número possui o valor 1, assim o loop será executado novamente.

Quando o número for 10, o loop será executado pela última vez, pois o
número será incrementado novamente e a condição do while será falsa, pois o
número será 11, ou seja, maior do que 10.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 6

O loop while é testado na parte inicial do loop, antes que seja executada
a primeira iteração. Outra forma, seria movendo esse teste para o final do
bloco, assim garantimos que o bloco de código será executado ao menos uma
vez. Desta forma, é utilizada outra estrutura de repetição chamada do-while,
que veremos a seguir.

5.2 Do-While

Esse loop primeiramente irá executar todo o bloco de código para depois
testar a condição, e assim verificar se repete novamente o bloco de código.

Sintaxe básica:

Vamos desenvolver um exemplo com o mesmo funcionamento do


exemplo anterior.

A única diferença entre os loops while e do-while é a posição do teste


para a repetição.

Os loops acima são mais utilizados quando não sabemos exatamente


quantas repetições serão efetuadas. Nesses exemplos, sabemos que cada
loop será executado 10 vezes. Para esse tipo de repetição, existe um outro
loop, mais indicado, que será abordado em breve.

Agora, vamos montar um exemplo mais interessante para o nosso loop:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 7

Neste exemplo, primeiro iremos ler os dois números inseridos pelo


usuário para efetuar a soma. Após, verificaremos se o usuário deseja realizar
outra soma. Caso o usuário digite “S”, o loop será executado novamente
(lembre-se de que para verificar a igualdade de strings, é necessário utilizar o
método equals ao invés do operador ==).

Para esse exemplo, iremos utilizar o do-while, pois é necessário que o


bloco de código seja executado ao menos uma vez. Outro ponto importante do
exemplo é que não podemos definir inicialmente quantas vezes o loop será
executado, pois isso dependerá dos valores inseridos pelo usuário.

A última estrutura de repetição que será abordada é o for, indicado


quando sabemos exatamente quantas vezes vamos repetir o loop, ou seja,
quando ela é controlada.

5.3 For

O loop for é uma estrutura de repetição controlada por uma variável de


contador que será atualizada depois de cada iteração.

Sintaxe básica:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 8

O primeiro valor (<inicialização>) da estrutura for normalmente é


utilizado para inicializar a variável de contador. A condição lógica verifica se o
loop deve repetir ou não, e o incremento (ou decremento) é a atualização da
variável de controle, a cada iteração. Por exemplo:

Este exemplo imprime os valores de 0 a 10. Observe que a atualização


da variável de controle foi realizada dentro do for, assim, não é necessária a
sua atualização dentro do bloco de código (apesar de ser possível modificá-la
dentro do bloco de código também).

Como imprimiremos os valores de 0 a 10, a condição lógica utilizada foi


para repetir enquanto a variável i for menor ou igual a 10. Assim, quando a
variável i for igual a 10, ela será exibida no console e atualizada para 11, e
depois o loop não será mais executado.

5.4 Arrays

Até o momento, nós trabalhamos com variáveis que armazenam uma


informação. Imagine agora se fosse necessário armazenar 40 itens do mesmo
tipo, como por exemplo, armazenar todas as notas dos alunos de uma
disciplina. Poderíamos criar 40 variáveis diferentes, porém essa é uma forma
muito trabalhosa e propensa a erros. Imagine agora se fossem 100 alunos?

Um array é uma estrutura de dados que armazena uma coleção de itens


do mesmo tipo, que pode ser um tipo primitivo ou um objeto. Cada item no
vetor possui o seu próprio local numerado, chamado índice. O índice é utilizado
para acessar um elemento no vetor e, assim, recuperar ou atribuir uma
informação naquele índice.

Em um array o índice se inicia a partir do 0, ou seja, para acessar o


elemento que está na segunda posição do array utilizaremos o índice 1 e assim
sucessivamente.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 9

Um array possui um comprimento fixo e que não pode ser alterado, ou


seja, será definido um valor para o array e esse deve permanecer. Existe a
possibilidade de recuperar o tamanho do array por meio do atributo length. A
figura 1 apresenta um array com um tamanho de 10 posições e seus índices
respectivos:

Figura 5.1 – Vetor com 10 posições


Fonte: Elaborado pelo autor (2014)

Um array em Java é um objeto. Dessa forma, podemos utilizar o


operador new para criar uma nova instância de um array.

Para declarar uma variável para armazenar um array, primeiro


precisamos especificar o tipo do array, acrescentar colchetes ([ ]) e definir o
nome da variável. Exemplo:

Neste exemplo, nós declaramos a variável notas, a qual armazena um


conjunto de números inteiros. Também é possível adicionar os colchetes
depois do nome da variável:

As duas formas produzem o mesmo resultado. Agora, podemos


inicializar um array utilizando o operador new:

No momento da declaração, precisamos definir entre os colchetes o


comprimento do array. Neste exemplo, criamos um array de 40 números
inteiros. Ao criar um array de número, todos os elementos são inicializados
com 0. Um array de boolean é inicializado com false e um array de objeto é
inicializado com null.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 10

Para atribuir um valor em uma posição do array, utilizamos o índice


dentro dos colchetes. No exemplo abaixo, estamos armazenando na primeira
posição do vetor o número 10:

E para recuperar o valor, basta dizer o índice do vetor:

No exemplo acima, recuperamos o valor armazenado no índice 0 do


vetor exibimos no console.

Existem duas formas de declarar um vetor com suas posições


preenchidas com valores pré-determinados:

A primeira, consiste em atribuir os valores entre chaves { } e separado


por vírgula:

No exemplo acima foi declarado um vetor com tipo de dado inteiro e com
4 posições.

A outra forma tem o mesmo princípio da primeira, diferenciando pela


adição do operador new na declaração:

O resultado das declarações acima é igual ao resultado do código


abaixo:

Podemos criar arrays de qualquer tipo de dado no Java: string, byte,


char, int, long, double, float, boolean ou qualquer classe Java.

Exemplos:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 11

Agora, como podemos acessar todas as posições de um vetor?

A resposta são os loops. Eles são perfeitos, pois podemos fazer um loop
para repetir uma quantidade de vezes igual ao tamanho do vetor.

Podemos pensar em outro exemplo, imagine um programa que precisa


armazenar as notas de uma turma de 10 alunos e calcular a sua média.
Primeiro, vamos ler as notas dos 10 alunos utilizando um loop. Depois vamos
calcular a média e exibir para o usuário.

No exemplo abaixo, foi instanciado o scanner para realizar a leitura do


teclado. Depois, criamos um vetor de float com 10 posições. Assim, vamos
utilizar a estrutura de repetição for para ler e armazenar em cada posição do
vetor as notas dos alunos.

Observe que a variável i é utilizada como um índice, para controlar a


posição do vetor que será utilizado para armazenar o valor. Dessa forma,
quando o programa for executado pela primeira vez, na primeira iteração do
loop o valor de i será 0 que é a primeira posição do vetor. Já na última vez que
o loop for executado, o valor de i será 9 que é a última posição do vetor.
Lembrando que em Java o vetor inicia sempre na posição 0, dessa forma,
como o vetor tem 10 posições, ele inicia no 0 e finaliza em 9.

Podemos otimizar nosso código, ao invés de deixar o valor 10 fixo no


comando for; primeiramente, vamos recuperar o tamanho do vetor e utilizar
esse valor recuperado para ser utilizado como critério de parada do loop.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 12

Dessa forma, não precisaremos modificar o loop se o vetor possuir mais


ou menos posições.

Agora vamos desenvolver a segunda parte do programa: calcular a


média de notas. Para isso, vamos utilizar outro loop para somar todas as notas
dos alunos, e depois dividir pela quantidade de notas, que neste caso é 10.

Na primeira linha, declaramos uma variável do tipo float para armazenar


a soma de todas as notas dos alunos. Depois implementamos um loop para
percorrer todo o vetor e ir somando as notas na variável totalNotas.

Por fim, realizamos a divisão do total de notas pela quantidade de


alunos, para calcular a média e imprimimos no console o resultado para o
usuário. Perceba que para o loop e para a divisão, utilizamos o valor da
quantidade de elementos do vetor.

No exemplo acima, utilizamos um array para armazenar números


primitivos. Já falamos que é possível criar um array para armazenar objetos,
que são os arrays de referências ou o “array de objetos”. Neste array é possível
armazenar várias referências a um tipo de objeto.

Neste exemplo, estamos definindo um array com 5 posições para


armazenar as referências de objetos do tipo Carro.

Até este momento, nenhum objeto Carro foi criado. O array foi criado
para armazenar as referências de 5 Carros, e por enquanto as posições do
vetor estão vazias (null).

Para popular um array de carros, primeiro é preciso instanciá-lo, e


depois armazenar a sua referência em uma posição do vetor:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 13

Assim, a posição 0 do vetor possui uma referência a um objeto Carro. As


outras posições ainda estão vazias. A figura a seuir representa o estado atual
do array de carros:

Figura 5.2 – Estado atual do array de carros


Fonte: Elaborado pelo autor (2014)

Para recuperar o valor do modelo do carro que está armazenado na


primeira posição do vetor, podemos escrever o seguinte código:

Este código recupera o valor do modelo do carro e imprime no console


do eclipse.

Podemos percorrer o vetor de referências da mesma forma que fizemos


com o array de primitivos, utilizando as estruturas já vistas neste capítulo.
Porém, além dessas estruturas, é possível percorrer um vetor de primitivos ou
referência com uma sintaxe mais simples.

Estamos falando do comando for-each, que não necessita manter uma


variável de controle para indicar a posição do elemento no vetor.

A sintaxe é:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 14

O primeiro parâmetro é o tipo do array. O segundo é um nome para a


variável que vai receber cada um dos itens do vetor. O último parâmetro, que
está após os dois pontos (:) é o array que queremos percorrer.

Imagine o vetor de carros acima. Podemos percorrê-lo com o seguinte


código:

O tipo do vetor é Carro, a variável que vai receber cada um dos itens do
vetor é o carro e o array que queremos percorrer é o vetor de carros.

Para um vetor de primitivos, como o array de notas que desenvolvemos


acima, também podemos utilizar o for-each:

Os arrays que acabamos de ver são os vetores unidimensionais.


Existem também as matrizes ou arrays multidimensionais. As matrizes nada
mais são do que arrays de arrays. Dessa forma, cada posição do array
armazena outro array. Esses arrays também podem conter arrays, e assim por
diante, ou seja, quantas dimensões que o desenvolvedor desejar.

Imagine agora que as notas dos alunos devem ser armazenadas por
disciplinas. O curso tem 9 disciplinas com 40 alunos cada. Dessa forma,
podemos criar um array com 9 posições e em cada posição armazenar um
outro array com 40 elementos:

O array de array denominado notas tem 360 posições, uma para cada
aluno em 9 disciplinas. Você pode armazenar a nota do primeiro aluno para a
primeira disciplina com a seguinte instrução:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 15

Para acessar a nota do segundo aluno da primeira disciplina, basta


alterar o índice:

Portanto, os arrays de arrays funcionam da mesma forma que os arrays


unidirecionais. O primeiro índice de cada array começa em 0.

É possível também criar um array de array de array ou em quantas


dimensões forem necessárias:

5.5 Strings

Strings nada mais são do que uma sequência de caracteres. Durante o


curso, já utilizamos strings para armazenar palavras e textos. Agora é o
momento de aprender a manipular as strings, pois é essencial para fazer
validações de dados de entrada, exibir informações para o usuário e outras
informações baseadas em texto.

O Java não tem um tipo de dado primitivo como int ou double para
armazenar uma string. Ao invés, podemos utilizar a biblioteca padrão Java que
contém uma classe predefinida chamada string.

Os objetos strings são imutáveis, isto é, seu conteúdo de caracteres não


pode ser alterado após a sua inicialização. Dessa forma, é impossível alterar o
valor da string. Porém, é possível armazenar outra string no lugar da string
original.

Uma string deve ser declarada, instanciada e inicializada.

Nós já declaramos uma string durante o curso. Declarar uma string é


igual a declarar uma variável ou atributo de qualquer outro tipo de dado, basta
declarar o tipo de dado e o nome da variável, conforme exemplo abaixo:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 16

Neste caso, o tipo de dado utilizado é string e o nome da variável é


nome. Depois de declarar uma string, podemos instanciá-la como uma classe
normal. A sintaxe para a instanciação é:

É possível inicializar uma string de diversas formas. Podemos instanciá-


la e depois atribuir um valor ou atribuir um valor no momento da instanciação:

ou

Neste último exemplo, utilizamos um construtor da classe string para


passar um valor. É possível também atribuir um valor a uma string sem
instanciá-la.

Dessa forma, a string será armazenada em um pool de strings, uma área


utilizada pelo Java como cache.

Caso a string seja uma variável de instância, ou seja, um atributo de


uma classe, ela precisa ser instanciada ou inicializada antes de ser utilizada.
Pois todos os atributos de referência são inicializados com null. Dessa forma,
se invocarmos um método de uma variável vazia, vamos receber uma
exception chamada NullPointerException. Não se preocupe, veremos exceções
no decorrer do curso. Neste momento, o importante é entender que um erro
pode acontecer.

No exemplo abaixo, estamos utilizando o método length() para recuperar


a quantidade de caracteres da string nome sem instanciá-la:

A variável nome acima não possui nenhum valor, ou seja, está com null,
quando o programa executar a linha que recupera o tamanho da string e tentar
imprimi-la no console, um erro irá ocorrer.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 17

Para corrigirmos e esse erro não acontecer, é preciso instanciar ou


inicializar uma string:

ou

Lembrando que quando declaramos uma variável dentro de um método


é preciso sempre inicializá-la antes de utilizá-la. Caso isso não aconteça, um
erro de compilação será exibido:

No exemplo acima, o código não compila, pois estamos utilizando a


variável nome antes de atribuir um valor a ela.

Agora que entendemos como uma string funciona, vamos pensar como
podemos imprimir ou armazenar aspas (“) ou adicionar um quebra de linha na
string?

Para isso, podemos utilizar os caracteres de escape que são alguns


caracteres precedidos da contra barra (\). Esses caracteres são considerados
sequência de escape e têm um significado especial para o compilador.

No Java as sequências de escape mais utilizadas são:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 18

Quadro 5.1 – Sequências de Escape


Fonte: Elaborado pelo autor (2014)

Para utilizar uma sequência de escape basta adicioná-la a uma string:

String nome = "FIAP \nA melhor faculdade de tecnologia";


System.out.println(nome);

O resultado da execução acima será:

Figura 5.3 – Resultado da execução


Fonte: Elaborado pelo autor (2014)

É possível também adicionar as sequências de escape diretamente no


método de impressão no console:

Teste as outras opções de sequência de escape. Por exemplo, adicione


as aspas duplas em uma frase:

A saída no console será: Faculdade: ”FIAP”

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 19

Todos sabem que é possível somar números. E com as strings, também


é possível?

Sim, também é possível “somá-las”, ou melhor, concatená-las.


Concatenação de strings nada mais é do que juntar duas ou mais strings para
criar uma nova string.

A forma mais fácil de concatenar uma string é utilizar o operador de


soma (+). Veja o exemplo abaixo:

Primeiro foram declaradas duas strings com valores “FIAP” e “A melhor


faculdade de tecnologia”, respectivamente. Depois, declaramos uma terceira
variável com o nome “faculdade” e atribuímos os valores das outras duas
strings, concatenando-as. O resultado impresso no console será:

As duas strings foram “somadas”, ou seja, foram ligadas. Porém, para


ter um resultado melhor, podemos adicionar um espaço entre as strings:

Dessa forma, concatenamos três strings: o valor da variável nome, a


string com o valor de espaço e o valor da variável slogan. O resultado dessa
vez será:

Podemos concatenar qualquer quantidade de strings e também


adicionar as sequências de escape, conforme vimos acima.

Lembram-se do operador de atribuição aditiva (+=)? Que soma um valor


e adiciona a própria variável da esquerda, exemplo:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 20

A variável numero é inicializada com 10 e depois é somada a ela mais


10, resultado assim o valor de 20.

Podemos utilizar esse operador para strings também. Dessa forma,


vamos concatenando strings e atribuindo o resultado para a mesma variável:

O valor final armazenado na variável faculdade do exemplo acima é:

Além do operador + e +=, podemos concatenar strings utilizando o


método concat:

No exemplo acima, concatenamos o valor da variável nome com a string


que apresenta um traço (-) e a string armazenada em slogan. O valor final da
nova string foi armazenado na variável faculdade. Assim, o resultado final é
igual ao exemplo anterior:

É possível misturar as técnicas apresentadas para realizar a


concatenação de strings:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 21

Além do método concat, a classe string fornece diversas opções de


métodos para a sua manipulação. Com eles, podemos comparar strings,
acessar seus caracteres, pesquisar por um caractere ou uma sequência e
transformar uma string. Veremos cada uma dessas opções a seguir:

5.5.1 Comparação de strings

A comparação de strings deve ser realizada através de métodos, cujos


principais métodos para comparação são:

− Equals(string): verifica a igualdade do valor das strings.

− EqualsIgnoreCase(string): verifica a igualdade do valor das strings


sem diferenciar as letras maiúsculas e minúsculas.

Não devemos utilizar o operador == para comparar strings, pois esse


operador compara o endereço de memória que a string está alocada, ao invés
do valor armazenado na string. Como no exemplo a seguir:

As duas variáveis têm o mesmo valor, porém estão alocadas em


endereços de memória diferentes. Dessa forma, o resultado será “As strings
são diferentes”, pois o operador == compara o endereço de memória e não o
valor.

A figura a seguir mostra que as variáveis nome e nome2 têm um


espaço de memória separado para armazenar o valor “FIAP”, pois as strings
foram instanciadas com o operador new.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 22

Figura 5.4 – Variáveis nome e nome2


Fonte: Elaborado pelo autor (2014)

Agora, se inicializar as strings sem instanciá-las, os valores serão


alocados em um pool de strings. Dessa forma, se os valores forem iguais, elas
vão compartilhar o mesmo espaço de memória no pool, fazendo com que o
operador == funcione!

O resultado é “As strings são iguais”, pois a variável nome e nome2


compartilham o mesmo endereço de memória:

Figura 5.5 – Resultado “As strings são iguais”


Fonte: Elaborado pelo autor (2014)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 23

Porém, se uma das duas variáveis for instanciada (new), o operador ==


não vai funcionar. O exemplo abaixo resulta em “As strings são diferentes”:

Por esse motivo é extremamente recomendado sempre utilizar os


métodos para realizar a comparação de strings, pois eles funcionam
independentemente da forma que a variável foi inicializada.

− Método equals: compara o conteúdo de duas strings, diferenciando


os caracteres maiúsculos e minúsculos. Dessa forma, a string “Fiap”
é diferente de “fiap”. O exemplo abaixo compara o conteúdo das
variáveis, assim o valor impresso no console será “As strings são
iguais”:

Como faremos se houver a necessidade em comparar se as strings são


diferentes? Para isso não precisamos de um método específico. Basta
adicionar na comparação o operador de negação (!) e, dessa forma, a
comparação será o contrário, ou seja, ao invés de ser igual, será diferente.

Exemplo:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 24

− Método equalsIgnoreCase: compara o conteúdo de duas strings,


mas não diferencia os caracteres maiúsculos e minúsculos. Assim
sendo, a string “Fiap” é igual à string “fiap”.

O resultado do exemplo acima é “As strings são iguais”. O operador de


negação também pode ser utilizado normalmente com este método, dessa
forma, você verifica se as strings são diferentes, independentemente das letras
maiúsculas e minúsculas.

Podemos verificar se uma string começa com uma sequência de


caracteres específica. O método startsWith recebe a palavra a ser procurada:

Neste exemplo, o resultado é “A string começa com FIAP”. Por padrão, o


Java sempre compara as strings, diferenciando as letras maiúsculas e
minúsculas, somente o método equalsIgnoreCase, com o próprio método diz,
ignora a diferença entre maiúsculas e minúsculas. Então o método startsWith
diferencia o case das letras.

Podemos verificar se uma string começa com uma determinada palavra,


também podemos verificar se uma string termina com uma sequência de
caracteres específica. O método que realiza essa função é o endsWith, que
também recebe a palavra a ser procurada.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 25

O resultado é que a string termina com a palavra procurada. Esse


método também diferencia as letras maiúsculas das minúsculas.

Assim como podemos recuperar o tamanho de um vetor, em uma string,


podemos recuperar a quantidade de caracteres através do método length.
Porém, na string, o length é um método, assim deve terminar com abre e fecha
parênteses:

O resultado da execução será:

Podemos também recuperar um caractere específico de uma string dada


a sua posição. Essa funcionalidade é muito parecida com um vetor, no qual
podemos recuperar um elemento por meio do seu índice. E assim como o
vetor, o primeiro caractere de uma string está na posição zero (0).

O método para obter um caractere da string é o charAt. Este método


recebe a posição do caractere que será recuperado:

O exemplo acima recupera e imprime no console o segundo caractere


da string (índice 1). Assim, o resultado será:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 26

Outro método muito interessante da classe string é o indexOf. Esse


método permite localizar a primeira ocorrência de um caractere ou palavra em
uma string. Dessa forma, se for localizado o caractere ou a palavra procurada,
o método retorna à posição (índice) da primeira ocorrência da palavra ou
caractere. Caso contrário, o valor -1 é retornado, indicando assim que a string
não possui o valor procurado.

No exemplo abaixo, estamos procurando a primeira ocorrência do


caractere ‘a’:

O resultado esperado é:

Lembre-se que o índice da string começa no zero e os espaços em


branco também são considerados.

Agora vamos realizar uma pequena alteração no exemplo, vamos buscar


por um caractere que não existe na string:

O resultado será:

O resultado -1 indica que o caractere ‘x’ não está presente na string. O


método indexOf também pode ser utilizado para procurar por uma sequência
de caracteres, para isso, basta passar uma palavra ao invés do caractere:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 27

A variável posição deve armazenar o valor do índice do início da palavra


“faculdade”:

Caso a palavra não seja encontrada, o valor -1 também será retornado.


Lembre-se de que esse método retorna à primeira ocorrência da palavra ou
caractere, dessa forma, no exemplo acima, se a variável facu possuir duas
palavras “faculdade”, o valor retornado será o índice da primeira palavra:

Resultado:

Outro método da classe string é o lastIndexOf, muito parecido com o


método indexOf, esse método retorna o índice da última ocorrência de um
caractere ou palavra em uma string.

No exemplo abaixo, estamos procurando pela última ocorrência do


caractere ‘a’:

A posição retornada será o index do último caractere a, neste caso a


última letra da string:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 28

Para procurar por uma palavra, basta passá-la como parâmetro:

Neste exemplo, o resultado será o mesmo da busca pela primeira


ocorrência de uma palavra:

Isso aconteceu porque existe somente uma palavra “Faculdade” na


string. Vamos testar agora com duas palavras iguais:

O resultado será o índice da segunda palavra “Faculdade” na string:

É possível criar uma string a partir de um trecho de outra string utilizando


o método subString. Este método recebe como parâmetro a posição inicial
(inclusive) e a posição final (exclusive) do conjunto de caracteres a serem
copiados da string original. O caractere da posição inicial será copiado para a
nova string, já o caractere da última posição não será copiado.

O resultado será uma nova string com a palavra “Faculdade”, que está
no índice 16 e se finaliza na posição 24:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 29

Podemos utilizar os métodos visto acima em conjunto ao método


subString. Por exemplo, podemos utilizar o método indexOf para retornar o
índice da primeira ocorrência e criar uma nova string:

O resultado da busca do índice do caractere ‘M’ será 9, dessa forma, a


nova string será iniciada na posição 9 e terminando na posição 25:

O método subString também aceita apenas a posição inicial do


conjunto de caracteres a serem copiados da string original. Assim, a nova
string será criada da posição inicial informada, até o final da string original.

O resultado será:

E também é possível utilizar os métodos em conjunto:

Dessa forma, o resultado da execução será:

Podemos converter os caracteres de uma string para maiúsculo ou


minúsculo, para isso a classe string possui os métodos toUpperCase e
toLowerCase. Para transformar os caracteres de uma string para maiúsculo,
podemos utilizar o método toUpperCase e para minúsculo o método

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 30

toLowerCase. Lembre-se que uma string é imutável, ou seja, ela não pode ser
alterada. Dessa forma, quando utilizamos esses métodos, uma nova string será
criada com a alteração solicitada.

Exemplo:

O resultado será:

Vamos realizar uma pequena alteração no exemplo anterior:

Dessa vez, qual será o resultado?

O resultado será a string original:

No código acima, o método toUpperCase é utilizado para transformar os


caracteres em maiúsculo, porém o resultado da transformação não é
armazenada em nenhuma variável. Com isso, o resultado será a impressão da
string original no console. O método toUpperCase (ou toLowerCase) cria uma
nova string com a modificação, sem alterar a string original.

Agora, vamos desenvolver um exemplo com o método toLowerCase:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 31

O resultado será a nova string armazenada na variável nova com todas


as letras em minúsculas:

Podemos substituir caracteres ou palavras de uma string original. O


método replace recebe como parâmetros o caractere ou palavra a ser
substituída e a letra ou palavra para substituir. Esse método também cria uma
nova string com a alteração:

No exemplo acima, estamos substituindo o caractere ‘a’ pelo caractere


‘x’ e estamos atribuindo o resultado dessa nova string criada na variável nova.
O resultado será:

Se imprimirmos o valor da variável facu, a string original será exibida:

O resultado será:

É possível também substituir uma palavra em uma string:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 32

O resultado da execução do exemplo acima será a nova string com as


palavras “São Paulo” no lugar da palavra “Tecnologia”:

O último método da classe string que será estudado será o método split.
Este é um método muito útil, que separa o valor de uma string em várias strings
separadas por um delimitador, que deve ser informado ao método:

Este exemplo separa a string armazenada na variável facu em várias


palavras separadas por um espaço. O resultado é armazenado em um vetor de
strings. Após, utilizamos um laço de repetição para percorrer o vetor e imprimir
o valor de seus elementos, o resultado será:

Além de utilizar o espaço como delimitador, podemos utilizar qualquer


outro caractere ou palavra:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 33

O exemplo acima utilizou o caractere ponto e vírgula (;) como


delimitador, dessa forma o resultado da execução será:

5.6 Collections Framework (COLEÇÕES)

Podemos utilizar um arrays para armazenar elementos do mesmo tipo,


porém, como vimos, é um processo um pouco trabalhoso, pois não podemos
redimensionar o tamanho de um vetor, portanto, caso seja preciso armazenar
mais elementos do que o tamanho do vetor, será necessário criar um novo
array e repassar todo o conteúdo do array antigo para o novo.

Outra dificuldade é encontrar um elemento do vetor pelo seu valor, é


possível somente encontrar o elemento pelo seu índice. Por exemplo, se
tivermos um vetor de strings que armazena os nomes dos alunos, se for
preciso procurar por um nome específico no vetor, será necessário percorrer
todo o array até encontrar o valor procurado ou então até o termino o vetor,
concluindo assim que o elemento não está no array.

Quando criamos um array, nós determinamos o seu tamanho. Porém,


não é possível determinar de uma forma simples a quantidade de posições que
foram preenchidas. Temos o conhecimento do tamanho total, contudo, para
identificar quantas posições estão vazias ou foram preenchidas, é necessário
percorrer todo o array. Portanto, pensando novamente no nosso vetor de
strings, o que é preciso fazer para armazenar um novo nome no array?
Precisamos procurar por um espaço vazio e para isso é necessário percorrer o
array. O que acontece se o array não possuir espaço vazio? Será necessário
criar um novo array e copiar os dados antigos para ele.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 34

Por esses e outros motivos é que a plataforma Java tem um conjunto de


classes e interfaces conhecido como Collections Framework, que
representam estruturas de dados avançadas.

Collections Framework ou Coleções são estruturas de dados utilizadas


para armazenar e organizar objetos de maneira eficiente e prática. Podem ser
utilizadas para representar estruturas como vetores, listas, pilhas, filas, mapas,
conjuntos e outras estruturas de dados.

Coleções são muito comuns nas aplicações Java, principalmente para o


acesso ao banco de dados, principalmente no resultado de buscas. Assim,
podemos armazenar os clientes, livros, endereços em nossa aplicação.

As coleções são definidas por meio de interfaces. As interfaces


determinam o que a estrutura deve fornecer de funcionalidades, ou seja,
fornecem um contrato para que a classe concreta as implemente. Na figura a
seguir é apresentada a estrutura de interfaces e classes das coleções e mapas
do Java:

Figura 5.6 – Estrutura de coleções e mapas


Fonte: Elaborado pelo autor (2014)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 35

No Java, as coleções podem ser classificadas em duas categorias: as


que implementam a interface Collection e as que implementam a interface
Map.

As principais subinterfaces de Collection são:

− List: representa uma lista de objetos, a implementação mais utilizada


é o ArrayList.

− Set: representa um conjunto de objetos únicos, e os objetos não se


repetem; a implementação mais utilizada é a HashSet.

A Interface Map representa uma tabela Hash, que armazena valores


compostos por [chave, valor]. Ou seja, para cada valor armazenado nesse
mapa podemos definir uma chave para facilitar a recuperação do valor. A
principal subinterface é:

− SortedMap: representa um mapa ordenado, a implementação mais


utilizada é o HashMap.

A interface Collection que é base para todas as coleções, exceto


Mapas, define um conjunto de métodos que são comuns a todas outras
estruturas que estão abaixo dela: list, set e queue.

Os principais métodos da interface Collection estão apresentados no


quadro a seguir:

Quadro 5.2 – Principais métodos da interface Collection


Fonte: FIAP (2015)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 36

5.6.1 List

A interface List representa uma sequência de elementos ordenados e


podem conter elementos repetidos. Dessa forma, os elementos de uma lista
estão dispostos pela ordem de inserção.

Para criar uma lista, não precisamos passar o tamanho dela, como
temos que fazer no array. Isso quer dizer que a lista se adequa quando
inserimos um elemento, possibilitando adicionar ou remover quantos elementos
forem necessários. Outra grande vantagem é que podemos manipular a lista,
ordenando-a ou buscando um elemento pelo seu valor.

A interface List especifica as funcionalidades que as classes devem


implementar para uma lista. Há diversas implementações disponíveis, sendo a
ArrayList a mais utilizada.

Principais métodos de uma lista:

Quadro 5.3 – Principais métodos de uma lista


Fonte: FIAP (2015)

A ArrayList armazena seus elementos em um array interno para gerar


uma lista. Essa lista cresce ou diminui dinamicamente no momento que um
elemento é inserido ou excluido da lista. Apesar do nome ArrayList, não é um

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 37

array, como visto anteriormente. ArrayList é uma implementação da interface


List da API de Collections do Java, essa classe somente utiliza um array
(também já visto neste capítulo) para armazenar os valores, porém, não
podemos acessar diretamente esse array, pois é um atributo encapsulado.

Para criar uma ArrayList, basta chamar o seu construtor:

No exemplo acima, declaramos uma ArrayList chamada lista e utilizamos


o método add, passando como parâmetro um objeto, para ser inserido na lista,
esse objeto será adicionado ao final da lista.

Outro método utilizado para inserir um elemento na lista é o set. Esse


método adiciona um elemento em determinada posição da lista, substituindo o
valor existente nele, ou seja, quando quisermos inserir algo na primeira posição
e essa já estiver ocupada, utilizamos o método set determinando a posição
desejada, que para o caso seria 0, já o objeto que estava nessa posição é
excluído da ArrayList:

No exemplo acima, no final da execução, a lista possuirá somente dois


elementos, na posição 0 o valor “LTP” e na posição 1 o valor “Algoritmos”.

Para remover um elemento, utilizamos o método remove, passando


como parâmetro a posição do elemento a ser removido:

Neste exemplo, foram adicionados dois elementos na lista e depois


removido o elemento da posição 1, ou seja, o segundo elemento. Dessa forma,
somente o valor “LTP” está armazenado na lista.

O método get recupera um elemento dado a sua posição:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 38

O valor que será impresso no console será “Web”.

Podemos percorrer uma lista como fizemos com arrays. No exemplo


abaixo, vamos percorrer a lista e imprimir o valor de cada posição dele:

O método size() retorna a quantidade de elementos na coleção. O


resultado da execução será:

Para procurar por um valor em uma ArrayList, podemos utilizar o método


indexOf ou lastIndexOf, que são muito parecidos com os métodos da classe
string, visto anteriormente. Como uma lista pode conter elementos duplicados,
o primeiro método indexOf retorna ao índice da primeira ocorrência encontrada
na lista:

O resultado da execução será:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 39

O método lastIndexOf() funciona de forma parecida com o método da


classe string, recuperando o índice da última ocorrência na lista. E os dois
métodos retornam o valor –1, caso o elemento procurado não esteja presente
na lista.

5.6.2 Set

A interface Set define uma coleção que não pode conter valores
duplicados. Corresponde à abstração de um conjunto que funciona de forma
análoga aos conjuntos da matemática. Outro ponto importante, é que nem
sempre a ordem de inserção dos elementos será a dos elementos dispostos na
coleção, isso pode variar de implementação para implementação. A interface
contém somente os métodos herdados da interface Collection:

Quadro 5.4 – Métodos herdados da interface Collection


Fonte: FIAP (2015)

Uma das principais implementações de Set é a classe HashSet, que


armazena seus elementos em uma tabela hash. É uma implementação
bastante simples e eficiente, como mostra o exemplo a seguir:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 40

Como se vê, o segundo valor “Java” não será adicionado ao HashSet. O


resultado será:

A grande vantagem do Set é a performance nas operações de busca


(método contais), em relação a List.

5.6.3 Map

Podemos armazenar informações em mapas, eles são muito úteis


quando precisamos recuperar de forma rápida as informações do objeto, para
isso é preciso passar uma chave. Por exemplo, podemos armazenar o objeto
Aluno em um mapa e utilizar o RM como chave. Dessa forma, é possível
informar o RM do aluno para recuperar o objeto que tem todas as informações
do aluno.

Podemos utilizar uma lista para isso? Claro que sim, o problema é que
seria necessário percorrer todos os elementos da lista para encontrar o aluno
correto, deste modo, a performance seria comprometida, mesmo para
pequenas listas.

Um mapa é composto por um par de chave e valor. As chaves não


podem conter valores iguais, porém o valor sim. A principal implementação de
Map é a classe HashMap.

Principais definições da interface Map são:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 41

Quadro 5.5 – Definições da interface Map


Fonte: FIAP (2015)

O método put é utilizado para adicionar um elemento ao Mapa. Esse


método recebe a chave e o valor a ser inserido:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 42

Para adicionar os elementos no mapa, foram utilizados os pares rm e


nome do aluno para a chave e valor, respectivamente.

O resultado da execução será:

Para recuperar um elemento do mapa, basta utilizar o método get


passando a chave:

O resultado será a impressão do valor “Thiago” no console.

As operações de inserir (put) e buscar (get) são as mais utilizadas em


mapas. Também existem métodos para remover um elemento do mapa. Já
para excluir, utilizamos o método remove, que recebe como parâmetro a chave
do elemento a ser removido:

O elemento com a chave “RM1234” foi removido do mapa, assim,


quando tentarmos recuperar o valor da chave removida, o valor retornado será
null (vazio).

5.6.4 Generics

Até o momento nós armazenamos qualquer tipo de objeto nas coleções.


Com isso, podemos misturar os objetos dentro de uma mesma coleção.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 43

E para recuperar o elemento da lista? O método get retorna um objeto e,


depois, é preciso realizar um cast. Mas com uma coleção com objetos
diferentes, será complicado realizá-lo.

A partir do Java 5, podemos utilizar o recurso de Generics para restringir


os tipos de dados aceitos por referência genérica. Dessa forma, somente o tipo
determinado no Generic será permitido inserir na lista, e não qualquer objeto.

O Generic permite a verificação do tipo em tempo de compilação e deixa


o código mais limpo, pois não é necessário realizar um cast.

Sintaxe:

Ao lado do ArrayList temos um < > e dentro dele, determinamos o tipo


que a lista poderá armazenar. A figura a seguir apresenta os detalhes da
declaração de uma ArrayList utilizando Generics:

Figura 5.7 – Detalhes da declaração de uma ArrayList utilizando Generics


Fonte: Elaborado pelo autor (2014)

Essa ArrayList poderá armazenar somente objetos do tipo produto.

Sem utilizar o Generic, seria necessário realizar o cast e, possivelmente,


ocorreria uma exceção se o tipo não fosse compatível com o cast, como
indicado a seguir:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 44

Figura 5.8 – Exceção quando o tipo não é compatível com o cast


Fonte: Elaborado pelo autor (2014)

Agora com o Generics, o código não permite a inserção de um elemento


que não corresponda ao tipo de objeto da lista:

Figura 5.9 – Com Generics, código não permite inserção de elemento que não corresponde ao
tipo de objeto da lista
Fonte: Elaborado pelo autor (2014)

Além disso, não será preciso realizar o cast para obter o objeto de volta
na lista, pois ela pode armazenar somente um tipo de objeto:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 45

Podemos utilizar o operador for-each para percorrer a lista:

Toda a API de Collections permite a utilização de generics por permitir


maior segurança na manipulação dos tipos e não há necessidade de cast.

Lembre-se que o generic permite definir um tipo de Objeto, os tipos


primitivos não são permitidos:

Assim, podemos determinar o tipo que será armazenado no Set e Map


também:

Portanto, sempre é recomendado utilizar as coleções com generics. No


exemplo acima, podemos somente armazenar no Set os objetos do tipo
Cliente. Já no Map, a chave será uma String e o valor um Cliente.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Estruturas de repetição, arrays, strings e coleções Página 46

REFERÊNCIAS

BARNES, David J. Programação Orientada a Objetos com Java: Uma


introdução Prática Utilizando Blue J. São Paulo: Pearson, 2004.

CADENHEAD, Rogers; LEMAY, Laura. Aprenda em 21 dias Java 2


Professional Reference. 5. ed. Rio de Janeiro: Elsevier, 2003.

DEITEL, Paul; DEITEL, Harvey. Java Como Programar. 8. ed. São Paulo:
Pearson, 2010.

HORSTMANN, Cay; CORNELL, Gary. Core Java. Fundamentos. v.1. 8. ed.


São Paulo: Pearson 2009.

SIERRA, Kathy; BATES, Bert. Use a cabeça! Java. Rio de Janeiro: Alta Books,
2010.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com
julianafigueiredo204@gmail.com
HerançaHerança Página 2

LISTA DE FIGURAS

Figura 4.1 – Hierarquia de classes ............................................................................4


Figura 4.2 – Classe com herança ..............................................................................5
Figura 4.3 – Atributo da classe conta corrente ..........................................................6
Figura 4.4 – Atributo que armazena o limite do cheque especial ..............................6
Figura 4.5 – Método que retorna o saldo disponível da conta corrente .....................7
Figura 4.6 – Operador instanceof ..............................................................................8
Figura 4.7 – Operador instanceof ..............................................................................8
Figura 4.8 – Operador instanceof ..............................................................................9
Figura 4.9 – Método Sobrescrito na classe Conta Corrente ......................................9
Figura 4.10 – Método sobrescrito: @Override e super..............................................10
Figura 4.11 – Classe Conta e Conta Corrente ..........................................................11
Figura 4.12 – Construtor da Classe Conta Corrente .................................................12
Figura 4.13 – Construtor da classe Conta Corrente com a chamada super de forma
explícita .....................................................................................................................12
Figura 4.14 – Construtor da classe Conta .................................................................12
Figura 4.15 – Construtor da classe Conta Corrente invocando o construtor da
superclasse ...............................................................................................................13
Figura 4.16 – Instrução super utilizada para chamar o construtor da superclasse ....13

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 3

SUMÁRIO

4 HERANÇA ..............................................................................................................4
4.1 Introdução ...........................................................................................................4
4.1 Sobrescrita de métodos.......................................................................................9

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 4

4 HERANÇA

4.1 Introdução

Uma classe que herda de outra classe é chamada de subclasse, já a classe


herdada é chamada de superclasse.

A herança é utilizada como forma de reutilizar os atributos e métodos de classes


já definidas, permitindo assim derivar uma nova classe mais especializada a partir de
outra classe mais genérica existente.

Uma classe só pode ter uma superclasse, ou seja, não é possível ter herança
múltipla. Porém, uma classe pode ter um número ilimitado de subclasses.

Dessa forma, uma subclasse recebe todas as características da superclasse e


de todas as outras classes acima dela. A hierarquia de classes se inicia com a classe
Object, isto é, todas as classes a herdam direta ou indiretamente. Veja a hierarquia
de classes:

Figura 4.1 – Hierarquia de classes


Fonte: Elaborado pelo autor (2017)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 5

A classe Object é a superclasse da classe A, e esta, por sua vez, é subclasse


de Object.

A classe A é a superclasse de B e C, desta forma, as classes B e C recebem


todos os atributos e métodos da classe A e da classe Object.

A palavra-chave extends é utilizada na declaração de uma classe para


determinar a sua superclasse. Caso a classe não tenha essa palavra-chave em sua
declaração, a herança que existe é diretamente da classe Object.

Sintaxe:

[public] class <subclasse> extends <superclasse> {

Agora é hora de praticar! Vamos ajustar a classe Conta para que ela possua as
subclasses ContaCorrente e ContaPoupanca. A classe Conta herda da classe Object.

A classe ContaCorrente possui o atributo tipo de conta, que define se a conta


é básica, especial ou premium. Já a ContaPoupanca não possui esse tipo de
definição.

Figura 4.2 – Classe com herança


Fonte: Elaborado pelo autor (2017)

Após definir que a classe ContaCorrente é uma subclasse de Conta, vamos


adicionar um atributo para definir o tipo de conta corrente.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 6

Figura 4.3 – Atributo da classe conta corrente


Fonte: Elaborado pelo autor (2017)

Observe que utilizamos o encapsulamento para proteger o atributo tipo, que


define o tipo da conta corrente.

Vamos adicionar outro atributo que será utilizado para armazenar o valor do
cheque especial, ou seja, o valor que o cliente pode utilizar junto do saldo da conta.

Figura 4.4 – Atributo que armazena o limite do cheque especial


Fonte: Elaborado pelo autor (2017)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 7

Agora que vimos como adicionar atributos na classe filha, vamos adicionar
métodos específicos à ContaCorrente. Uma conta corrente tem o comportamento de
retornar o Saldo Disponível, que é a soma do saldo da conta com o limite do cheque
especial:

Figura 4.5 – Método que retorna o saldo disponível da conta corrente


Fonte: Elaborado pelo autor (2017)

Note que o método retorna o valor da soma do cheque especial com o saldo da
conta. Para acessar o saldo da conta foi necessário utilizar o método getSaldo(), pois
o atributo saldo está definido na classe pai como private, por isso não é visível na
classe filha.

Uma forma de descobrir se a herança é adequada para as suas classes é seguir


a regra do “é um”, que afirma que cada objeto da subclasse é um objeto da
superclasse. Por exemplo, uma Conta Corrente é uma Conta, o que significa que a
herança deve ser utilizada nesta situação. Naturalmente, o contrário não é verdadeiro,
nem toda Conta é uma Conta Corrente.

Dessa forma, você pode utilizar um objeto de uma subclasse sempre que o
programa esperar por um objeto da superclasse. Assim, é possível atribuir um objeto
do tipo Conta Corrente em uma variável do tipo Conta.

Exemplo:

Conta conta = new Conta();

Conta cc = new ContaCorrente();

As variáveis que armazenam uma referência a um objeto são polimórficas. Isso


quer dizer que uma variável de uma superclasse pode receber qualquer objeto de
suas subclasses.

Podemos atribuir o objeto que está referenciado na variável cc a uma variável


do tipo ContaCorrente, para isso é necessário realizar um cast:

ContaCorrente c1 = (ContaCorrente) cc;

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 8

O cast é forçar um objeto ser de outro tipo em um momento. Neste caso,


forçamos o objeto a ser do tipo ContaCorrente para atribuirmos em uma variável do
tipo ContaCorrente. O cast é composto pelos parênteses () e a classe que queremos
forçar o objeto a se transformar naquele momento.

Observe que se tentarmos realizar o cast e o objeto não for do tipo ou subtipo
da classe que queremos forçar, o Java irá lançar a exceção ClassCastException:

ContaCorrente c2 = (ContaCorrente) conta;

A variável conta faz referência a um objeto do tipo Conta e não do tipo


ContaCorrente. Assim, a exceção será lançada.

Para verificar se o objeto é do tipo de uma classe, podemos utilizar a instrução


instanceof. Essa instrução retorna true caso o objeto a esquerda do operador é do
tipo (classe) especificado à direita do operador. Exemplo:

Figura 4.6 – Operador instanceof


Fonte: Elaborado pelo autor (2017)

No exemplo, estamos testando se a variável cc possui um objeto do tipo Conta.


Então, qual é o resultado da execução?

O resultado é “cc é do tipo Conta”. E se alteramos o programa para instanciar


um objeto do tipo ContaCorrente ao invés do tipo Conta, qual será o resultado da
execução?

Figura 4.7 – Operador instanceof


Fonte: Elaborado pelo autor (2017)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 9

A resposta é que cc é do tipo conta, pois uma ContaCorrente também é uma


Conta.

Mas se alterarmos novamente o programa anterior para ficar dessa forma:

Figura 4.8 – Operador instanceof


Fonte: Elaborado pelo autor (2017)

Agora estamos testando se o objeto da variável cc é do tipo ContaCorrente. A


resposta da execução é “cc não é do tipo Conta Corrente”. Pois uma Conta não é
necessariamente uma Conta Corrente.

4.1 Sobrescrita de métodos

Outra diferença, para o nosso sistema, é que para a conta poupança não há
taxa para efetuar um saque. Na conta corrente do tipo básica existe uma taxa para a
retirada de dinheiro.

Dessa forma, precisamos sobrescrever o comportamento do método retirar na


classe Conta Corrente. Sobrescrever um método é redefinir na subclasse um método
existente na superclasse. Assim, quando o método retirar for chamado de um objeto
do tipo Conta Corrente, o método chamado será o retirar definido na classe Conta
Corrente e não da classe Conta.

Para isso, precisamos implementar na classe Conta Corrente um método


retirar que tenha a mesma assinatura do método retirar da classe Conta.

Figura 4.9 – Método Sobrescrito na classe Conta Corrente


Fonte: Elaborado pelo autor (2017)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 10

A anotação @Override marca o método, identificando que o método está


sobrescrevendo um método de sua superclass.

O método retirar soma a taxa de retirada (10) ao valor a ser subtraído do saldo.
Como não temos acesso direto ao saldo e não podemos alterar o seu valor na
subclasse (não existe o método setSaldo() na classe Conta), precisamos utilizar o
método retirar que está na classe Conta. A palavra super é utilizada para referenciar
a superclasse, assim a instrução super.retirar(valor) está chamando o método retirar
que está na classe Conta.

Figura 4.10 – Método sobrescrito: @Override e super.


Fonte: Elaborado pelo autor (2017)

Isso faz parte de um dos pilares da Orientação a Objetos: o polimorfismo.

A palavra polimorfismo quer dizer várias formas, na orientação a objetos


representa que um objeto pode ser referenciado de várias formas. Quando
sobrescrevemos um método na subclasse, o que determina se o método que será
chamado é da subclasse ou da superclasse é o tipo de instância do objeto. Por
exemplo:

Conta conta = new Conta();

conta.retirar(100);

O método chamado será o definido na classe Conta.

ContaCorrente conta = new ContaCorrente();

conta.retirar(100);

O método chamado será o definido na classe ContaCorrente.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 11

Simples, certo? E no exemplo abaixo? Qual será o método chamado?

Conta conta = new ContaCorrente();

conta.retirar(100);

Neste caso, o método definido na ContaCorrente será invocado. Pois, o objeto


que está em conta é do tipo ContaCorrente.

Observe que podemos redefinir o comportamento de uma classe em sua


subclasse e assim um objeto pode se comportar de maneira diferente ao invocar um
método, dependendo do seu tipo de criação.

Construtores em Classes Estendidas

Os construtores das subclasses sempre precisam chamar um construtor da


superclasse. E para isso, a instrução super é utilizada.

Observe as classes Conta e ContaCorrente:

Figura 4.11 – Classe Conta e Conta Corrente


Fonte: Elaborado pelo autor (2017)

Os atributos e métodos foram omitidos para focarmos nos construtores. Essas


classes têm construtores?

A resposta é sim. Apesar de não estar definido, elas possuem o construtor


padrão (sem argumentos) que é fornecido pelo Java. O construtor padrão chama o
construtor da superclasse direta, ou seja, o construtor da classe ContaCorrente
chama o construtor da classe Conta e o construtor da classe Conta chama o
construtor da classe Object.

Vamos definir um construtor para a classe ContaCorrente. Esse construtor


recebe como parâmetro o valor do tipo da Conta.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 12

Figura 4.12 – Construtor da Classe Conta Corrente


Fonte: Elaborado pelo autor (2017)

Agora temos um construtor para a classe ContaCorrente. Esse construtor


chama o construtor de sua superclasse?

A resposta é sim. Isso é feito automaticamente pelo Java, pois a classe Conta
possui o construtor padrão. Então o código abaixo, com a instrução super( ) na
primeira linha do construtor é redundante, pois o Java irá fornecer a instrução caso
não seja definido.

Figura 4.13 – Construtor da classe Conta Corrente com a chamada super de forma explícita
Fonte: Elaborado pelo autor (2017)

Outras duas regras dos construtores são:

1) Não são herdados.

2) A chamada do construtor da superclasse deve ser sempre feita na primeira


linha do construtor da subclasse.

Dessa forma, se implementarmos um construtor que recebe um parâmetro na


classe Conta, a classe ContaCorrente não vai herdar esse construtor:

Figura 4.14 – Construtor da classe Conta


Fonte: Elaborado pelo autor (2017)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 13

A partir do momento em que implementamos esse construtor na classe Conta,


a classe ContaCorrente começa a exibir um erro de compilação. Isso acontece, pois
o construtor da classe ContaCorrente deve chamar o construtor da classe Conta,
porém agora, a classe Conta tem somente o construtor que recebe um parâmetro do
tipo int.

Para consertar o erro, devemos fazer com que o construtor da classe


ContaCorrente chame o construtor definido na classe Conta. Para isso, utilizamos a
instrução super, passando o parâmetro do tipo inteiro:

Figura 4.15 – Construtor da classe Conta Corrente invocando o construtor da superclasse


Fonte: Elaborado pelo autor (2017)

Dessa forma, o construtor da subclasse chama o construtor da superclasse:

Figura 4.16 – Instrução super utilizada para chamar o construtor da superclasse


Fonte: Elaborado pelo autor (2017)

Resumindo, se o super não for chamado, o compilador acrescenta uma


chamada ao construtor padrão: super( );

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 14

Se não existir um construtor padrão na superclasse, haverá um erro de


compilação e será necessário chamar explicitamente a instrução super, passando os
parâmetros do construtor da superclasse.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
HerançaHerança Página 15

REFERÊNCIAS

BARNES, David J. Programação Orientada a Objetos com Java: uma introdução


prática utilizando Blue J. São Paulo: Pearson, 2004.

CADENHEAD, Rogers; LEMAY, Laura. Aprenda em 21 dias Java 2 Professional


Reference. 5.ed. Rio de Janeiro: Elsevier, 2003.

DEITEL, Paul; DEITEL, Harvey. Java Como Programar. 8.ed. São Paulo. Pearson,
2010.

HORSTMANN, Cay; CORNELL, Gary. Core Java: Volume I. Fundamentos. 8.ed.


São Paulo: Pearson 2009.

SIERRA, Kathy; BATES, Bert. Use a cabeça! Java. Rio de Janeiro: Alta Books,
2010.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com
julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 2

LISTA DE FIGURAS

Figura 1 – Exemplo de atributos................................................................................ 8


Figura 2 – Método recuperarSaldo .......................................................................... 10
Figura 3 – Exemplo de parâmetros de métodos........................................................ 11
Figura 4 – Sobrecarga de métodos ........................................................................... 11
Figura 5 – Palavra this para referenciar ao atributo da classe.................................. 12
Figura 6 – Exemplo construtor .................................................................................. 13
Figura 7 – Classe Conta com três construtores ........................................................ 15
Figura 8 – Utilizando a palavra this para chamar um construtor da própria classe ... 15
Figura 9 – Classe Conta ............................................................................................ 16
Figura 10 – Classe de teste....................................................................................... 17
Figura 11 – Instanciando uma classe Conta ............................................................. 17
Figura 12 – Exemplo de utilização de objetos ........................................................... 18
Figura 13 – Resultado da execução da classe de teste ............................................ 18
Figura 14 – Visão de variáveis que armazenam referências aos objetos Java ......... 19
Figura 15 – Projeto exemplo ..................................................................................... 21
Figura 16 – Classe conta e modificadores de acesso ............................................... 21
Figura 17 – Criando um novo pacote ........................................................................ 22
Figura 18 – Novo pacote para a classe Teste ........................................................... 22
Figura 19 – Classe de Teste ..................................................................................... 23
Figura 20 – Visão geral da API Java ......................................................................... 24
Figura 21 – Exemplos de comentários no Java......................................................... 26
Figura 22 – Exemplo de comentário de documentação ............................................ 27
Figura 23 – Classe Conta com comentários de documentação ................................ 28
Figura 24 – Gerando documentação – Parte 1 ......................................................... 29
Figura 25 – Gerando documentação – Parte 2 ......................................................... 30
Figura 26 – Documentação da Classe Conta ............................................................ 30
Figura 27 – Atributo idade encapsulado .................................................................... 32
Figura 28 – Atributo do tipo boolean encapsulado .................................................... 33
Figura 29 – Método encapsulado .............................................................................. 33
Figura 30 – Classe JavaBean Conta ......................................................................... 35
Figura 31 – Classe de Teste ..................................................................................... 36

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 3

LISTA DE QUADROS

Quadro 1 –Visão geral sobre os modificadores......................................................... 20


Quadro 2 – Tags de documentação .......................................................................... 27

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 4

LISTA DE TABELAS

Tabela 1 – Valores padrões para variáveis de instância. .......................................... 9

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 5

SUMÁRIO

3 CLASSE, MÉTODOS, ATRIBUTOS ....................................................................... 6


3.1 Classe ................................................................................................................. 6
3.2 Atributos .............................................................................................................. 7
3.3 Métodos............................................................................................................... 9
3.3.1 Sobrecarga de métodos ................................................................................... 11
3.3.2 Construtor......................................................................................................... 12
3.4 Trabalhando com objetos .................................................................................... 16
3.5 Modificadores de acesso ..................................................................................... 20
3.6 Java API specification ......................................................................................... 24
3.7 Comentários ........................................................................................................ 25
3.8 Javadoc ............................................................................................................... 26
3.9 Java bean e encapsulamento.............................................................................. 31
REFERÊNCIAS ......................................................................................................... 37

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 6

3 CLASSE, MÉTODOS, ATRIBUTOS

3.1 Classe

Uma classe possui o modelo ou estrutura a partir do qual os objetos serão


criados. Pense em uma classe que precisa implementar uma conta bancária. Quais
são as informações que a conta precisa armazenar? E quais são as ações que ela
deve realizar?

As informações relevantes para uma conta bancária podem ser o saldo, número
da conta, agência, tipo de conta etc. E as ações ou comportamentos importantes de
uma classe Conta são: sacar, depositar, verificar o saldo etc.

Dessa forma, podemos desenvolver uma classe Conta que contenha essas
informações e comportamentos. Porém, essa classe é somente o modelo para o
conceito de Conta Bancária dentro do nosso sistema. Assim como em um Banco
Financeiro do “mundo real”, antes de guardar dinheiro na conta e depositar ou retirar,
é preciso ir ao Banco para abrir uma Conta. No mundo orientado a objetos, primeiro
precisamos criar um objeto utilizando a classe Conta para depois utilizá-la. Esse
processo de criação de um objeto a partir de uma classe é chamado de instanciação.

Em resumo, um objeto é uma instância de uma Classe. Para instanciar uma


classe utilizamos o operador new:

new Conta();

No exemplo acima foi criado um objeto do tipo Conta. Porém, precisamos


armazenar esse objeto em alguma variável para utilizá-lo posteriormente. Para isso,
podemos declarar uma variável do tipo da Classe (Conta) e atribuir o objeto a variável
com o operador =.

Conta cc = new Conta();

Conta poupanca = new Conta();

Dessa forma, a variável cc e poupança armazenam a referência de seus


respectivos objetos. E assim como um banco pode possuir várias contas, no
programa, podemos instanciar várias classes do mesmo tipo, neste caso o tipo Conta.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 7

As classes Java são definidas em arquivos separados com a extensão .java e


o nome do arquivo deve ser igual ao nome da Classe. Por convenção, o nome segue
o padrão UpperCamelCase, no qual as palavras sempre se iniciam com a letra em
maiúscula. Por exemplo: Conta, ContaCorrente, ContaPoupanca.

Para definir uma classe em Java, utilizamos a palavra reservada class:

[modificador] class [NomeDaClasse] {

Exemplo:

public class Conta{

Neste capítulo, vamos falar sobre os modificadores. Não se preocupe!

3.2 Atributos

Uma classe pode conter nenhum ou vários atributos. Depois de instanciar a


classe, os atributos serão utilizados para armazenar informações do objeto. Essas
informações diferenciam um objeto do outro.

Pense novamente na classe Conta, já identificamos alguns atributos


necessários, como: Saldo, Número da Conta, Agência, Tipo da Conta. Em um
programa para gerenciar as contas bancárias, serão necessários vários objetos do
tipo Conta, cada um deles com as informações de sua própria Conta.

Em uma classe, os atributos são definidos por variáveis, que podem ser do tipo
primitivo (como visto no capítulo anterior) ou do tipo de referência, no qual a variável
armazena uma referência ao objeto. No nosso exemplo, a classe conta pode conter
uma variável para armazenar a referência de um objeto Cliente. Assim, a classe Conta
possui um Cliente.

Por convenção, os nomes dos atributos seguem o lowerCamelCase, cuja


primeira letra é minúscula e as demais palavras começam com a letra maiúscula. Pela

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 8

boa prática, devemos utilizar substantivos e nomes bem definidos para os atributos,
como por exemplo: saldo, dataNascimento, email etc. Nomes poucos sugestivos
devem ser evitados: x, y, abc entre outros.

As variáveis que definem um atributo em uma classe são chamadas de


variáveis de instância, pois só é possível armazenar informação nessa variável após
a instanciação da Classe, ou seja, no objeto.

Declarar uma variável de instância segue a mesma sintaxe das variáveis locais,
visto no capítulo anterior.

A Figura 1 traz alguns exemplos de atributos:

Figura 1 – Exemplo de atributos


Fonte: FIAP (2015)

Diferentemente das variáveis locais, as variáveis de instância recebem valores-


padrão quando não atribuímos valores à sua declaração.

Por exemplo:

class Conta {

double saldo;

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 9

Neste caso, a variável saldo recebe o valor padrão 0. Podemos também, atribuir
um valor na hora de declarar um atributo, assim o valor padrão não será utilizado:

class Conta {

double saldo = 100;

Tabela 1 – Valores padrões para variáveis de instância.

Fonte: FIAP (2015)

3.3 Métodos

Os métodos definem os comportamentos que o objeto possui. O


comportamento pode ser entendido como uma ação ou serviço, por exemplo, um
objeto do tipo Conta possui comportamentos como recuperar o Saldo, depositar e
retirar dinheiro da conta.

Dessa forma, podemos definir um método como um comportamento específico,


residente no objeto, que define como ele deve agir quando exigido, definindo assim
as habilidades do objeto.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 10

Por convenção, o nome dos métodos, assim como os seus atributos, devem
sempre ser escritos em lowerCamelCase, e geralmente utilizamos verbos para os
nomes. Exemplos: exibirSaldo, depositar, calcularTaxa, pois os métodos executam
ações.

A sintaxe básica para declarar um método é:

<modificador> <tipo de retorno> <nomeDoMetodo>(<[lista de argumentos]>){

[instrucoes];

A Figura 2 exemplifica o método recuperarSaldo

Figura 2 – Método recuperarSaldo


Fonte: FIAP (2015)

Precisamos definir o tipo de retorno que o método deve devolver. No exemplo


acima (Figura 2), o método recuperarSaldo retorna um valor do tipo double. A
instrução return é utilizada para retornar o valor; o método retorna o valor do atributo
saldo.

Caso o método não precise retornar nenhum valor, podemos definir o retorno
como void. No exemplo acima, o método depositar não retorna nenhum valor.

Os métodos podem receber valores, como é o caso do método depositar. Os


parâmetros dos métodos são declarados pela [lista de argumentos] que são um
conjunto de declarações de variáveis que são separados por vírgulas e definidas
dentro de parênteses. Esses parâmetros se tornam variáveis locais no método,

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 11

recebendo seus valores quando o método for chamado. Como exemplificado na


Figura 3.

Figura 3 – Exemplo de parâmetros de métodos


Fonte: FIAP (2015)

3.3.1 Sobrecarga de métodos

Um recurso usual em Programação Orientada a Objetos é o uso de sobrecarga


de métodos. Sobrecarregar um método significa prover mais de uma versão de um
mesmo método. As versões devem, necessariamente, conter parâmetros diferentes,
seja no tipo ou número desses parâmetros. O tipo de retorno não é relevante.

Dessa forma, duas características diferenciam os métodos com o mesmo


nome: o número de parâmetros e o tipo deles. Essas características fazem parte da
assinatura de um método. O uso de vários métodos com o mesmo nome e assinaturas
diferentes é chamado de sobrecarga de métodos.

Figura 4 – Sobrecarga de métodos


Fonte: FIAP (2015)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 12

No exemplo acima (Figura 4), a classe Conta possui dois métodos com o nome
retirar, com assinaturas diferentes. Um que recebe um valor para retirada e outro que
recebe um valor de retirada e o valor da taxa de retirada.

A sobrecarga de métodos torna possível que os métodos se comportem de


modo diferente, dependendo dos argumentos que recebem. Quando nós chamamos
um método em um objeto, o Java verifica o nome do método e os parâmetros enviados
para escolher o melhor método a ser invocado.

A palavra reservada this faz referência ao próprio objeto. É por meio dela que
é possível acessar atributos, métodos e construtores do objeto em questão.

Quando houver duas variáveis com o mesmo nome, uma sendo uma variável
de instância (atributo da classe) e outra pertencente ao método, utilizaremos a palavra
this para referenciar o atributo da classe, como mostra a Figura 5.

Figura 5 – Palavra this para referenciar ao atributo da classe


Fonte: FIAP (2015)

No decorrer do curso, iremos utilizar a palavra this para as outras situações


citadas acima.

3.3.2 Construtor

Podemos construir métodos especiais, chamados de construtores, que são


executados automaticamente quando os objetos dessa classe são criados. Esses
métodos auxiliam na construção do objeto, podendo ser utilizado para inicializar os
atributos com valores-padrão ou valores informados e chamar métodos em outros
objetos.

Um método construtor é chamado quando o objeto é construído, ou seja, é


invocado quando utilizamos a instrução new para criar uma instância da classe.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 13

No momento em que criamos uma instância da classe, três passos são


executados pelo Java:

• Alocar memória para o Objeto.

• Inicializar os atributos com os valores iniciais ou padrões.

• Chamar o método Construtor da classe.

Os construtores se parecem muito com métodos comuns, mas têm três


diferenças básicas:

• Têm o mesmo nome da Classe.

• Não têm tipo de retorno (Nem mesmo void).

• Não podem retornar valor no método usando a instrução return.

Toda classe tem pelo menos um construtor. Quando o construtor não é


especificado, a linguagem Java fornece um construtor default (padrão) – vazio – que
não recebe parâmetros. Mas se for declarado algum construtor na classe, a linguagem
Java não fornecerá mais o construtor padrão.

A Figura 6 mostra o exemplo de um construtor.

Figura 6 – Exemplo construtor


Fonte: FIAP (2015)

Dessa forma, quando uma instância de Conta for criada (new Conta();), o
atributo saldo será inicializado com o valor 100 e será impresso no Console a frase
“Criando uma instância de Conta.”.

Podemos adicionar um construtor que recebe parâmetros (Figura 7):

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 14

Neste exemplo, o construtor padrão (sem parâmetros) não será fornecido pelo
Java. O único construtor que a classe Conta tem é o que recebe um valor double como
parâmetro. Esse valor é utilizado para inicializar o valor do atributo saldo.

Exemplo de utilização: new Conta(100);

Da mesma forma que os métodos, a instrução this foi utilizada para acessar as
variáveis de instância de um objeto atual:

No exemplo acima, o construtor recebe um parâmetro chamado saldo e atribui


o seu valor ao atributo saldo. Para diferenciar o atributo do parâmetro, utiliza-se a
instrução this.

Assim como os métodos, uma classe pode ter vários construtores com
diferentes tipos e quantidades de argumentos. Isso é chamado de sobrecarga de
métodos construtores. Dessa forma, uma classe pode ser instanciada com qualquer
construtor.

O exemplo a seguir (Figura 9) apresenta uma classe Conta com três


construtores:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 15

Figura 7 – Classe Conta com três construtores


Fonte: FIAP (2015)

Dessa forma, tempos três opções para instanciar a classe Conta:

• new Conta().

• new Conta(100).

• new Conta(10,100).

Outro uso para a palavra reservada this é na chamada de um construtor por


outro construtor da própria classe, como exemplifica a Figura 10.

Figura 8 – Utilizando a palavra this para chamar um construtor da própria classe


Fonte: FIAP (2015)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 16

3.4 Trabalhando com objetos

Para consolidar os conceitos, vamos criar uma classe Conta com os atributos
saldo, agência e número. Vamos desenvolver também os métodos de retirar,
depositar e verificarSaldo. Para facilitar a construção dos objetos dessa classe, vamos
implementar dois construtores: um construtor padrão e outro que recebe três
argumentos: o saldo, a agência e o número.

Para isso, crie uma nova Classe chamada Conta dentro do pacote
br.com.fiap.banco e depois implemente os atributos, métodos e construtores.

A figura 11 mostra o resultado final:

Figura 9 – Classe Conta


Fonte: FIAP (2015)

Agora, vamos criar uma classe de Teste (Figura 12) com o método main para
criar instâncias da classe Conta. Para isso, crie uma nova classe chamada Teste, no
pacote br.com.fiap.banco, e implemente o método main:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 17

Figura 10 – Classe de teste


Fonte: FIAP (2015)

Dentro do método main, vamos instanciar uma Classe conta (Figura 13) e
armazenar a referência desse objeto em uma variável.

Figura 11 – Instanciando uma classe Conta


Fonte: FIAP (2015)

A variável cc tem uma referência ao objeto Conta. É por meio dela que
podemos acessar os atributos e métodos do objeto.

Utilizando o operador ponto (.), podemos acessar as variáveis de instância e


métodos do objeto. Por exemplo, para acessar o atributo saldo do objeto conta que
está referenciada pela variável cc, podemos utilizar o seguinte código:

double valor = cc.saldo;

System.out.println(cc.saldo);

Na primeira linha, recuperamos o valor do atributo saldo do objeto conta e


atribuindo a variável valor. Na segunda linha, imprimimos o valor do saldo no console.

Para atribuir um valor ao atributo do objeto, utilizamos o operador de atribuição:

cc.saldo = 1000;

Chamar um método de um objeto é semelhante ao acesso de um atributo: é


utilizada a notação de ponto:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 18

cc.depositar(100);

cc.verificarSaldo();

A variável que referencia o objeto (cc) fica do lado esquerdo e o nome do


método e seus argumentos ficam do lado direito do ponto. Dentro dos parênteses são
informados os argumentos do método. Caso o método tenha mais de um argumento,
esses são separados por vírgulas. Métodos que não recebem parâmetros não
precisam receber nenhum valor, como é o exemplo do método verificarSaldo().

Vamos criar mais uma instância da classe conta, atribuir alguns valores aos
seus atributos e chamar os métodos.

Figura 12 – Exemplo de utilização de objetos


Fonte: FIAP (2015)

No exemplo acima, foram criados dois objetos do tipo Conta. No primeiro objeto
(cc), foram atribuídos valores aos seus atributos e invocados os métodos depositar e
verificarSaldo, imprimindo o resultado no console. O segundo objeto criado
(poupança) recebeu os valores iniciais de seus atributos pelo construtor. Após isso,
foram chamados os comportamentos de retirar e verificarSaldo.

Reflita: qual o resultado da execução do programa de teste?

Figura 13 – Resultado da execução da classe de teste


Fonte: FIAP (2015)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 19

O objeto referenciado na variável cc recebeu um valor inicial de 50. Depois, foi


adicionado ao saldo o valor 100 através do método depositar. Assim, quando o método
verificarSaldo é chamado, o valor retornado é 150.

O segundo objeto recebe um valor inicial de 1000. Após isso o método retirar é
acionado com o valor 50. Assim, o saldo final é 950.

Observe que cada objeto possui os seus próprios valores para as variáveis de
instância e seus métodos atuam dentro do próprio objeto, independentemente.

Figura 14 – Visão de variáveis que armazenam referências aos objetos Java


Fonte: FIAP (2015)

Uma variável que armazena a referência de um objeto pode ter o valor null.
Esse valor quer dizer que a variável está vazia e não faz referência a nenhum objeto.
Devemos tomar cuidado, pois no caso de tentar acessar um atributo ou método em
uma variável vazia, irá ocorrer um erro na execução do programa.

É possível utilizar o valor null na lógica do seu programa sempre que for
necessário verificar se a variável faz referência a um objeto ou não.

Exemplos:

Conta cc = null;

if (cc != null){

System.out.println(“Existe uma conta”);

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 20

3.5 Modificadores de acesso

Os modificadores são palavras-chave que alteram as definições de uma classe,


método, atributo ou construtor. Existem vários modificadores na linguagem Java, na
qual fazem parte: static, abstract e final.

No decorrer do curso abordaremos cada uma delas, mas neste momento,


vamos estudar os modificadores de acesso, que são as palavras-chave utilizadas para
controlar o acesso a uma classe, variável de instância, método ou construtor.

O Java disponibiliza três modificadores de acesso: public, protected e private.


Quando nenhum modificador é utilizado, o nível de acesso padrão (default) é utilizado.
Esse nível de acesso também é conhecido como package.

Os modificadores usados com mais frequência nos sistemas são aqueles que
controlam o acesso a métodos, atributos e construtores. Os modificadores irão
determinar quais variáveis, métodos e construtores serão visíveis a outras classes.

O Quadro 1, a seguir, apresenta uma visão geral sobre os modificadores:

Quadro 1 –Visão geral sobre os modificadores


Fonte: FIAP (2015)

Os membros da classe declarados sem nenhum modificador de acesso terão o


nível de acesso padrão. Dessa forma, os métodos, atributos e construtores serão
acessíveis a outras classes que estiverem dentro do mesmo pacote.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 21

Pacote, como visto no capítulo anterior, é uma forma de organizar as classes


em uma estrutura de diretórios.

Observe no package explorer do eclipse a estrutura de pacotes e classes do


projeto (Figura 17):

Figura 15 – Projeto exemplo


Fonte: FIAP (2015)

As classes Teste e Conta estão no mesmo pacote: br.com.fiap.banco

Observe agora, na Figura 18, a estrutura da classe Conta:

Figura 16 – Classe conta e modificadores de acesso


Fonte: FIAP (2015)

Todos os atributos não foram marcados com nenhum modificado de acesso,


assim o nível de acesso é o default. Os construtores e métodos têm o nível de acesso
public.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 22

Dessa forma, os atributos são visíveis somente a classes que estiverem dentro
do mesmo pacote da classe Conta. Os construtores e métodos são visíveis em
qualquer outra classe, independentemente do pacote em que esteja.

Vamos criar um novo pacote para a classe Teste, chamado


br.com.fiap.banco.teste (Figura 19):

Figura 17 – Criando um novo pacote


Fonte: FIAP (2015)

Arraste a classe para o novo pacote, como mostra a Figura 20:

Figura 18 – Novo pacote para a classe Teste


Fonte: FIAP (2015)

Observe acima, que a classe de Teste está marcada com um X vermelho,


indicando que existe algum erro na classe:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 23

Figura 19 – Classe de Teste


Fonte: FIAP (2015)

O problema é que a classe Teste não tem mais acesso aos atributos, pois estes
têm o nível de acesso default e as classes estão em pacotes diferentes. Por enquanto,
marque os atributos da classe Conta com public, para corrigir o problema.

O modificador de acesso private permite o acesso aos métodos, atributos e


construtores somente dentro da própria classe que as tem. Dessa forma, nenhuma
outra classe terá acesso aos membros privados.

Esse modificador é utilizado para o encapsulamento, que será abordado em


breve neste capítulo. Mas, previamente falando, o encapsulamento é um dos pilares
da orientação a objetos e tem o objetivo de proteger o acesso indevido de seus
atributos e métodos por outras classes.

E, finalmente, o modificador protected, que limita a visibilidade dos métodos,


construtores e atributos de duas formas:

• Subclasses de uma classe.

• Outras classes no mesmo pacote.

Ou seja, esse modificador é parecido com o nível default, pois permite a


visibilidade dentro do mesmo pacote. A diferença é a visibilidade dos membros da
classe em classes filhas. Em uma herança, os atributos, métodos e construtores
protegidos serão acessíveis nas subclasses dessa classe.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 24

3.6 Java API specification

Vimos como criar as nossas classes, porém a biblioteca de classes do Java


contém milhares de classes prontas e interfaces para o desenvolvimento de
aplicações. Essas classes e interfaces estão agrupadas em pacotes, de acordo com
suas funcionalidades. Por exemplo, as classes que são utilizadas para manipular
arquivos estão dentro do pacote java.io.

Existe uma documentação para descrever as classes e seus membros public e


protected. Essa documentação, conhecida como Java API Specification, apresenta
uma visão geral de todas as classes com detalhes de seus construtores, métodos e
campos públicos ou protegidos.

Essa documentação pode ser visualizada on-line em:


http://docs.oracle.com/javase/8/docs/api/

A documentação está dividida em três janelas: a janela superior esquerda, que


apresenta os pacotes da API Java em ordem alfabética; a janela logo abaixo, do lado
esquerdo, lista as classes e interfaces, pode ser filtrado pela escolha do pacote da
janela anterior; e a janela à direita, que exibe as informações da classe, pacote ou
interface, dependendo da escolha das janelas anteriores, como mostra a Figura 22:

Figura 20 – Visão geral da API Java


Fonte: FIAP (2015)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 25

3.7 Comentários

São informações incluídas no código fonte que não interferem no programa. É


uma forma de melhorar a legibilidade e ajudar os desenvolvedores na organização e
no entendimento do código.

Podemos utilizar os comentários para descrever o que for necessário, pois o


compilador Java ignora totalmente os comentários ao preparar uma versão executável
de um programa Java.

Existem três tipos de comentários:

• Para comentar uma linha, utilizam-se duas barras (//), tudo desde as barras até o
final da linha será considerado comentário, sendo desconsiderado pelo compilador
Java:

//comentário

• Caso seja necessário comentar mais de uma linha, pode-se iniciar o comentário
com /* e terminá-lo com */, tudo que estiver entre essas marcações será
considerado comentário:

/* Comentário

de várias

linhas */

• Comentário de documentação, ou seja, o comentário será legível tanto para


computadores quanto para os desenvolvedores. Esse tipo de comentário é
interpretado como sendo documentação oficial que descreve o funcionamento de
uma classe e seus métodos. Dessa forma, podemos gerar uma documentação
para outros desenvolvedores conhecerem o funcionamento de nossa classe. A
sintaxe desse tipo de comentário é semelhante ao comentário de várias linhas, se
inicia com /** e termina */, ou seja:

/** Comentário de Documentação */

Exemplos:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 26

Figura 21 – Exemplos de comentários no Java


Fonte: FIAP (2015)

3.8 Javadoc

Agora que vimos a documentação oficial da Oracle, vamos criar a


documentação das classes que desenvolvemos. Para isso, utilizaremos a ferramenta
de documentação javadoc., que permite que as classes criadas sejam documentadas
no formato HTML.

Podemos utilizar um comentário de documentação para detalhar melhor as


nossas classes, métodos, atributos etc.

Esse comentário tem a seguinte estrutura:

/** Descrição

* @tag descrição dessa tag

*/

Os comentários de documentação devem ser inseridos imediatamente acima


do elemento que está sendo documentado. Por exemplo, para documentar um método
da classe, precisamos colocar o comentário logo acima do dele.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 27

Além do texto que descreve o elemento, podemos utilizar algumas tags para
dar um significado próprio a trechos do comentário. Como por exemplo, determinar o
autor ou a versão do programa.

Essas tags são precedidas por um sinal de @, como @author ou @version.

As principais tags são apresentadas o Quadro 2, a seguir:

Quadro 2 – Tags de documentação


Fonte: FIAP (2015)

A Figura 24 apresenta um exemplo de utilização do comentário de


documentação com as tags:

Figura 22 – Exemplo de comentário de documentação

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 28

Fonte: FIAP (2015)

Agora vamos alterar a classe Conta adicionando os comentários para a


construção da documentação (Figura 25):

/**
* Classe que abstrai uma Conta Bancária
* @author thiagoyama
* @version 1.0
*/
public class Conta {

/**
* Número da Conta
*/
public int numero;
/**
* Número da Agencia
*/
public int agencia;
/**
* Saldo da Conta
*/
public double saldo;

public Conta(){}

public Conta(int numero, int agencia, double saldo){


this.numero = numero;
this.agencia = agencia;
this.saldo = saldo;
}

/**
* Deposita um valor ao saldo da conta
* @param valor Valor a ser depositado
*/
public void depositar(double valor){
saldo = saldo + valor;
}

/**
* Retira um valor do saldo da conta
* @param valor Valor a ser retirado
*/
public void retirar(double valor){
saldo = saldo - valor;
}

/**
* Verifica o saldo da conta
* @return Valor do saldo da conta
*/
public double verificarSaldo(){
return saldo;
}
}
Figura 23 – Classe Conta com comentários de documentação
Fonte: FIAP (2015)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 29

Agora vamos gerar a documentação da classe Conta. A ferramenta javadoc


fica dentro da pasta de instalação do Java (jdk) na pasta bin. Nesta pasta, existe o
programa executável javadoc.exe.

Vamos utilizar o eclipse para gerar a documentação. Para isso, acesse o menu
Project -> Generate javadoc, conforme a imagem abaixo (Figura 26):

Figura 24 – Gerando documentação – Parte 1


Fonte: FIAP (2015)

Após essa operação, uma janela será aberta. Nela, primeiro configure a
ferramenta javadoc, navegue até a pasta em que está a ferramenta e escolha o
programa javadoc.exe.

Agora, escolha os pacotes que terão as suas classes e interfaces


documentadas. Configure também uma pasta de destino para a criação dos arquivos
de documentação, como mostra a Figura 27:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 30

Figura 25 – Gerando documentação – Parte 2


Fonte: FIAP (2015)

O resultado pode ser visualizado na pasta que foi escolhida como destino dos
arquivos de documentação. Abra o arquivo index.html e navegue à vontade!

A figura 28 apresenta a documentação da classe Conta:

Figura 26 – Documentação da Classe Conta


Fonte: FIAP (2015)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 31

3.9 Java bean e encapsulamento

Uma das principais vantagens da programação orientada a objetos é a


capacidade de reutilizar o mesmo objeto em diferentes classes e programas. A
especificação JavaBeans define diretrizes que ditam os nomes de suas variáveis, os
nomes e tipos de retorno de seus métodos e alguns outros aspectos para que o objeto,
chamado de beans, sejam reutilizáveis.

A ideia é criar pequenos componentes que possam ser reaproveitados ao


máximo, simplificando o processo de desenvolvimento.

As regras para que uma classe seja um Java Bean são:

• Precisa ter um construtor padrão, sem argumentos.

• Encapsular os seus atributos, provendo métodos para o acesso a eles em outras


classes.

• É uma boa prática a implementação da interface java.io.Serializable

Uma classe bean pode conter construtores com argumentos, porém ela deve
ter também um construtor sem argumentos.

Vamos falar sobre interfaces ainda, agora só vamos deixar registrado que é
uma boa prática a implementação da interface Serializable, que permite a serialização
de objetos.

O encapsulamento é aplicado a métodos e atributos de uma classe e consiste


em proteger os dados, ou até mesmo escondê-los.

Para encapsular um método, devemos utilizar o acesso mais restritivo quando


desejamos que as outras classes não tenham acesso ao método. Permitindo assim o
uso somente de dentro da própria classe.

Para limitar ou controlar o conteúdo de um atributo, métodos devem ser


utilizados para atribuir ou alterar valores dos atributos de um objeto.

Dessa forma, sempre marcamos os atributos de uma classe com o nível de


visibilidade mais restritiva (private), a não ser que exista um bom motivo para deixá-la
com outro nível de acesso. Permitir o acesso total a um atributo não é uma boa prática,

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 32

pois qualquer mudança na estrutura interna da classe acarretaria em mudanças nas


outras classes que a utilizam, limitando a flexibilidade de mudança do código.

Outros benefícios do encapsulamento são:

• Esconder a implementação de uma classe: para utilizar uma classe que envia e-
mail, precisamos saber somente os valores que a classe precisa receber para
realizar o envio, não precisamos saber como ela o faz.

• Definir o modo de acesso aos dados: escrita, leitura, escrita e leitura.

• Proteger os dados que estão dentro dos objetos, evitando-se que eles sejam
alterados erroneamente.

O uso de métodos de leitura (get) e escrita (set) visam desacoplar os atributos


de uma classe dos clientes que a utilizam. No exemplo a seguir (Figura 29), o atributo
idade está encapsulado:

Figura 27 – Atributo idade encapsulado


Fonte: FIAP (2015)

A única forma de recuperar ou alterar o valor do atributo idade é utilizando os


métodos assessores, get e set. Como podemos perceber, a convenção de nome para
métodos que alteram o valor do atributo é adicionar a palavra set antes do nome do
atributo. Para os métodos que recuperam a informação, utiliza-se a palavra get
seguida do nome do atributo. Para atributos do tipo boolean, também é possível
utilizar a palavra is antes do atributo. Como mostra a Figura 30.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 33

Figura 28 – Atributo do tipo boolean encapsulado


Fonte: FIAP (2015)

Para os métodos, podemos encapsular da seguinte forma:

Figura 29 – Método encapsulado


Fonte: FIAP (2015)

A Figura 31 exibe o método formataTel encapsulado, pois está marcado como


private, que permite o acesso somente de dentro da própria classe Telefone.

Agora, vamos alterar a Classe conta para seguir a especificação JavaBean


(Figura 32). Altere a visibilidade dos atributos de public para private. Crie os métodos
assessores (gets e sets) dos atributos.

/**
* Classe que abstrai uma Conta Bancária
* @author thiagoyama
* @version 1.0
*/
public class Conta {

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 34

/**
* Número da Conta
*/
private int numero;
/**
* Número da Agencia
*/
private int agencia;
/**
* Saldo da Conta
*/
private double saldo;

public Conta(){}

public Conta(int numero, int agencia, double saldo) {


super();
this.numero = numero;
this.agencia = agencia;
this.saldo = saldo;
}

/**
* Deposita um valor ao saldo da conta
* @param valor Valor a ser depositado
*/
public void depositar(double valor){
saldo = saldo + valor;
}

/**
* Retira um valor do saldo da conta
* @param valor Valor a ser retirado
*/
public void retirar(double valor){
saldo = saldo - valor;
}

public int getNumero() {


return numero;
}

public void setNumero(int numero) {


this.numero = numero;
}

public int getAgencia() {


return agencia;
}

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 35

public void setAgencia(int agencia) {


this.agencia = agencia;
}

public double getSaldo() {


return saldo;

public void SetSaldo(double saldo) {


this.saldo = saldo;
}
}
Figura 30 – Classe JavaBean Conta
Fonte: FIAP (2015)

Observe que o método setSaldo não foi implementado, pois não podemos
deixar a alteração do valor do saldo seja feito de qualquer maneira. Para isso, existem
os métodos depositar e retirar.

Outro detalhe foi a remoção do método verificarSaldo, que foi substituído pelo
método getSaldo, já que os dois tinham o mesmo comportamento.

Função super()

A função super() é destinada a chamar o construtor de uma classe pai, sendo


essencial quando estamos utilizando herança para definir classes. Ela também
pode ser usada antes de colocarmos o this em uma função evitando erros de
referência. Devido a sua importância, ela termina sendo chamada sempre que
construímos uma classe mesmo que não esteja explicita.

Modifique também a classe de teste (Figura 33), para corrigir os erros que
surgiram.

public class Teste {

public static void main(String[] args) {

Conta cc = new Conta();


cc.depositar(50);
cc.setAgencia(123);
cc.setNumero(321);

cc.depositar(100);

System.out.println(cc.getSaldo());

Conta poupanca = new Conta(111,222,1000);

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 36

poupanca.retirar(50);

System.out.println(poupanca.getSaldo());
}
}
Figura 31 – Classe de Teste
Fonte: FIAP (2015)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 37

REFERÊNCIAS

BARNES, David J. Programação Orientada a Objetos com Java: Uma introdução


Prática Utilizando Blue J. São Paulo: Pearson, 2004.

CADENHEAD, Rogers; LEMAY, Laura. Aprenda em 21 dias Java 2 Professional


Reference. 5. ed. Rio de Janeiro: Elsevier, 2003.

DEITEL, Paul; DEITEL, Harvey. Java Como Programar. 8. ed. São Paulo. Pearson,
2010.

HORSTMANN, Cay; CORNELL, Gary. Core Java: Volume I. Fundamentos. 8. ed. São
Paulo: Pearson 2009.

SIERRA, Kathy; BATES, Bert. Use a cabeça! Java. Rio de Janeiro: Alta Books, 2010.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Classe, métodos, atributos Página 38

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com
julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 2 de 41

LISTA DE FIGURAS

Figura 2.1 – Eclipse IDE for Java EE Developers ..................................................... 5


Figura 2.2 – Arquivo principal de execução ............................................................ 6
Figura 2.3 – Escolha da Workspace (diretório de trabalho). ..................................... 6
Figura 2.4 – Escolha de Workspace (diretório de trabalho) ...................................... 7
Figura 2.5 – IDE Eclipse ............................................................................................ 8
Figura 2.6 – Criação de um Projeto Java (Parte I). ................................................... 8
Figura 2.7 – Criação de um Projeto Java (Parte II). .................................................. 9
Figura 2.8 – Criação de um Projeto Java (Parte III). ................................................. 10
Figura 2.9 – Resultado da criação do projeto. ........................................................... 10
Figura 2.10 – Criando pacotes (parte 1) .................................................................... 12
Figura 2.11 – Criando Pacotes (parte 2) ................................................................... 13
Figura 2.12 – Pacote no Package Explorer. .............................................................. 14
Figura 2.13 – Estrutura de pacotes no Windows Explorer. ....................................... 14
Figura 2.14 – Criação de Classe (parte 1)................................................................. 15
Figura 2.15 – Criação de classe (parte 2). ................................................................ 16
Figura 2.16 – Arquivo gerado e a o código da classe. .............................................. 17
Figura 2.17 – Visão lógica da IDE eclipse. ................................................................ 18
Figura 2.18 – Visão detalhada da IDE eclipse........................................................... 18
Figura 2.19 – Primeira classe Java ........................................................................... 19
Figura 2.20 – Projeto sem salvar............................................................................... 20
Figura 2.21 – Botão para Salvar e Executar o programa Java. ................................. 20
Figura 2.22 – Executando a classe Java. .................................................................. 21
Figura 2.23 – Resultado da execução do programa Java. ........................................ 21
Figura 2.24 – Palavras reservadas............................................................................ 23
Figura 2.25 – Tipos primitivos inteiros ....................................................................... 24
Figura 2.26 – Tipos primitivos de ponto flutuante ...................................................... 24
Figura 2.27 – Exemplo tipos primitivos. ..................................................................... 25
Figura 2.28 – Conversões de tipos de dados ............................................................ 26
Figura 2.29 – Conversões entre tipos primitivos ....................................................... 26
Figura 2.30 – Conversão utilizando cast ................................................................... 27
Figura 2.31 – Operadores aritméticos ....................................................................... 28
Figura 2.32 – Operadores de atribuição .................................................................... 29
Figura 2.33 – Exemplo de utilização dos operadores de incremento e decremento . 30
Figura 2.34 – Operadores aritméticos e de atribuição. .............................................. 31
Figura 2.35 – Resultado da execução ....................................................................... 31
Figura 2.36 – Tabela Operadores de igualdade e relacionais ................................... 32
Figura 2.37 – Fluxo para a instrução if ...................................................................... 35
Figura 2.38 – Fluxo para a instrução if – else............................................................ 36
Figura 2.39 – Fluxo para if – else aninhados ............................................................ 37
Figura 2.40 – Exemplo de leitura de dados ............................................................... 38
Figura 2.41 – Exemplo de leitura de dados. .............................................................. 39
Figura 2.42 – Exemplo de leitura de dados. .............................................................. 39

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 3 de 41

SUMÁRIO

2 IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD ........................................ 4


2.1 Introdução ........................................................................................................... 4
2.2 Tipos de dados e variáveis .................................................................................. 22
2.2.1 Atribuindo valores às variáveis ......................................................................... 25
2.3 Operadores ......................................................................................................... 27
2.3.1 Operadores de atribuição ................................................................................. 29
2.3.2 Operadores de incremento e decremento ........................................................ 30
2.3.3 Operadores de igualdade e relacionais ............................................................ 32
2.3.4 Operadores lógicos .......................................................................................... 33
2.4 Fluxo de controle e escopo de bloco ................................................................... 34
2.5 Entrada e saída de dados ................................................................................... 37

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 4 de 41

2 IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD

2.1 Introdução

Antes de começar, precisamos entender sobre as IDEs – programas de


computador que ajudam no desenvolvimento de sistemas. É possível implementar
sistemas em Java sem nenhuma ferramenta específica, porém é uma tarefa muito
trabalhosa e pouco produtiva.

Uma IDE (Integrated Development Environment ou Ambiente de Desenvolvimento


Integrado) é um programa que visa maximizar a produtividade do desenvolvedor, que
tem várias funcionalidades que auxiliam no desenvolvimento, entre elas, as mais
comuns são:

• Editor: editor de código-fonte específico para cada linguagem de programação


suportada pela IDE.

• Compilador: compila o código-fonte.

• Debugger (Depurador): executa o programa “passo-a-passo”, por meio do


qual é possível verificar o que ocorre em cada linha do programa, auxiliando no
entendimento do sistema e no processo de encontrar e corrigir problemas.

• Modelagem: criação de modelos de classes, objetos, interfaces, associações


e interações de forma visual.

• Geração de código: geração de código a partir de templates de código


comumente utilizados para solucionar problemas rotineiros.

• Deploy (Distribuição): auxilia no processo de gerar o arquivo final para a


instalação do programa desenvolvido.

• Testes automatizados: realiza testes no programa de forma automatizada,


baseados em scripts ou programas de testes previamente especificados,
gerando relatórios que auxiliam na análise do impacto das alterações no
código-fonte.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 5 de 41

• Refactoring (Refatoração): consiste na melhoria constante do código-fonte do


programa, seja na construção de código mais otimizado, mais limpo e/ou com
melhor entendimento pelos envolvidos no desenvolvimento do software.

Existem várias IDEs disponíveis no mercado, destinadas a linguagens de


programação ou plataforma de desenvolvimento específica. São exemplos de IDEs:
Visual Studio, da Microsoft, Netbeans, da Oracle etc.

Para a plataforma Java existem várias IDEs como:

• Eclipse

• NetBeans

• JDeveloper

Durante o curso vamos utilizar a IDE Eclipse, líder no mercado de


desenvolvimento Java, totalmente gratuito.

O Eclipse não é um software instalável, é necessário simplesmente realizar o


download e acessar o arquivo principal de execução.

Para a sua utilização é necessário instalar a JDK do Java. (Link para download:
http://www.oracle.com/technetwork/java/javase/downloads/index.html).

O eclipse possui várias versões. Vamos utilizar o “Eclipse IDE for Java EE
Developers”, pois ela dá suporte ao Java Enterprise Edition, ou seja, além de toda a
parte básica do Java, podemos utilizar a parte Enterprise, incluindo projetos Java
Web.

Figura 2.1 – Eclipse IDE for Java EE Developers

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 6 de 41

Fonte: elaborado pelo autor (2018)

Baixe o arquivo e descompacte. Dentro da pasta descompactada, encontre e


clique duas vezes no arquivo de inicialização da ferramenta:

Figura 2.2 – Arquivo principal de execução


Fonte: Elaborado pelo autor (2018)

O próximo passo é definir um diretório para gravar os arquivos gerados de dentro do


eclipse. Esse diretório é conhecido como workspace (diretório de trabalho).

Para isso, clique no botão “browser” e escolha uma pasta qualquer.

Figura 2.3 – Escolha da Workspace (diretório de trabalho).


Fonte: Elaborado pelo autor (2018)

Como a pasta estava vazia, o eclipse exibe uma página de boas-vindas, com opções
para visualizar tutoriais, exemplos e até um overview da ferramenta.

Vamos fechar essa página, clique no “X” na aba “Welcome”.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 7 de 41

Figura 2.4 – Escolha de Workspace (diretório de trabalho)


Fonte: Elaborado pelo autor (2018)

O Eclipse é formado por várias janelas. Toda a composição da tela pode ser alterada
pelo usuário, assim as janelas podem ser fechadas ou abertas, posicionadas
conforme as preferências do desenvolvedor.

Vamos utilizar duas janelas neste momento:

• Project explorer: está no lado esquerdo do eclipse, é onde a estrutura e


organização dos projetos e arquivos podem ser visualizados e acessados.

• Source editor: situado na área central (em cinza), é onde visualizamos e


editamos o código fonte.

Vamos explorar as outras abas na medida em que avançamos na disciplina.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 8 de 41

Figura 2.5 – IDE Eclipse


Fonte: Elaborado pelo autor (2018)

Agora, vamos criar o nosso primeiro projeto Java:

Para isso, vá ao menu – File – New – Project, conforme a figura abaixo:

Figura 2.6 – Criação de um Projeto Java (Parte I).


Fonte: Elaborado pelo autor (2018)

Escolha a primeira opção, Java Project e clique em Next.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 9 de 41

Figura 2.7 – Criação de um Projeto Java (Parte II).


Fonte: Elaborado pelo autor (2018)

Agora é a hora de definir o nome do projeto. Como sugestão, dê o nome de


01-OlaMundo e clique em Finish.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 10 de 41

Figura 2.8 – Criação de um Projeto Java (Parte III).


Fonte: Elaborado pelo autor (2018)

O resultado pode ser visualizado na aba de Package Explorer, localizado na


janela à esquerda no eclipse.

Figura 2.9 – Resultado da criação do projeto.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 11 de 41

Fonte: Elaborado pelo autor (2018)

A pasta src é onde devemos criar os arquivos Java. Abaixo dela, estão
localizadas as bibliotecas de classes básicas do Java. (JRE System Library).

Depois de definir a workspace e criar um projeto, está na hora de criar a


nossa primeira classe Java. Para isso, vamos primeiro definir o diretório em que ele
será criado. A hierarquia de diretórios para a organização dos arquivos de um
programa em Java é denominada Pacotes.

Imagine um sistema coorporativo, como um Sistema de um Banco ou de


Telefonia que precisa processar milhares de informações para seus clientes, como:
processar as transações financeiras de uma conta ou calcular a fatura de telefone.

Quantas classes são necessárias para desenvolver um sistema desses?


Centenas. Agora imagine se todas as classes estivessem no mesmo diretório. Seria
muito difícil de gerenciá-las. Por isso, devemos sempre criar uma estrutura de diretório
(pacotes) para organizar os arquivos do sistema. Dessa forma, podemos agrupar as
classes em coleções e separá-las das bibliotecas de classes fornecidas por outras
empresas.

Os pacotes em Java seguem uma hierarquia. Assim como podemos ter


diretórios e subdiretórios no disco rígido, podemos organizar os pacotes em níveis
hierárquicos.

Além de organizar, utilizar pacotes garante a singularidade dos nomes das


classes. Em um sistema não podemos ter classes com o mesmo nome dentro do
mesmo pacote. Porém, não há conflito se as classes estiverem em pacotes diferentes.
Assim, podemos ter duas classes com o nome Cliente no sistema, desde que estejam
em pacotes diferentes.

Para garantir um nome de pacote único, é recomendado utilizar o nome de


domínio da internet da empresa (que é único) escrito ao contrário. E depois especificar
mais ainda os pacotes com nome do projeto, tipos de classes etc.

Por exemplo, para a faculdade FIAP, que possui o domínio fiap.com.br e está
desenvolvendo um projeto para e-commerce, o pacote será definido como
br.com.fiap.ecommerce.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 12 de 41

Vamos criar um pacote para o nosso projeto. Será o br.com.fiap.tds, para


agrupar as classes do projeto do curso de TDS.

Para isso, clique com o botão direito do mouse no diretório src e escolha new
– package.

Figura 2.10 – Criando pacotes (parte 1)


Fonte: Elaborado pelo autor (2018)

Agora vamos definir o nome do pacote e finalizar o processo com o botão


Finish.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 13 de 41

Figura 2.11 – Criando Pacotes (parte 2)


Fonte: Elaborado pelo autor (2018)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 14 de 41

O resultado pode ser visualizado no Package Explorer:

Figura 2.12 – Pacote no Package Explorer.


Fonte: Elaborado pelo autor (2018)

Agora vamos ver a estrutura que foi criada no disco rígido. Para isso, navegue
até a pasta do workspace no Windows Explorer.

Figura 2.13 – Estrutura de pacotes no Windows Explorer.


Fonte: Elaborado pelo autor (2018)

Podemos visualizar uma pasta que representa o Projeto “01-OlaMundo”.


Dentro da pasta do projeto, temos a pasta src com uma estrutura de diretórios do
pacote criado. Assim, podemos perceber que cada pasta do pacote é separada pelo
“.” (ponto).

Agora, vamos criar a nossa primeira classe Java. Para isso, clique com o
botão direito do mouse no pacote e escolha New => Class.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 15 de 41

Figura 2.14 – Criação de Classe (parte 1)


Fonte: Elaborado pelo autor (2018)

É hora de definir o nome da classe. Vamos dar o nome de OlaMundo e


finalizar o processo com o botão Finish.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 16 de 41

Figura 2.15 – Criação de classe (parte 2).


Fonte: Elaborado pelo autor (2018)

O resultado pode ser visualizado na área central do eclipse, onde está


localizado o editor de código fonte. A classe possui uma primeira instrução, que define
o pacote da classe: package br.com.fiap.tds

A definição de pacote sempre é feita na primeira linha do arquivo Java.

Após, temos a definição da classe.

public class OlaMundo {

A princípio, não será necessário entender o significado da palavra plubic.


Veremos isso com detalhes no decorrer do curso.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 17 de 41

Após a palavra-chave class, vem o nome da classe. Atente-se que o nome


do arquivo gerado é o mesmo da classe com a extensão .java. Isso é importante, pois
é obrigatório que o nome do arquivo seja o mesmo da classe pública. Os nomes
devem iniciar com uma letra, depois, podem conter quaisquer combinações entre
letras e dígitos.

O padrão para atribuir nomes a classes é utilizar substantivos que iniciam com
uma letra maiúscula. Se o nome tiver mais de uma palavra, cada palavra deve iniciar
com letra maiúscula, por exemplo: PrimeiroExemplo, OlaMundo. Essa notação de
letras maiúsculas no meio de uma palavra é chamada de “notação camelo” ou
“CamelCase”.

Figura 2.16 – Arquivo gerado e a o código da classe.


Fonte: Elaborado pelo autor (2018)

Observe as chaves { } no código-fonte. No Java, as chaves delimitam os


blocos em um programa. Neste caso, as chaves delimitam o início e o fim da classe
OlaMundo.

Agora que sabemos o que são as workspaces, projetos, pacotes e classes,


podemos ter uma visão lógica da IDE eclipse:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 18 de 41

Figura 2.17 – Visão lógica da IDE eclipse.


Fonte: Elaborado pelo autor (2018)

Dentro de uma workspace, definimos os projetos. Projetos podem ter vários


pacotes, e estes, por sua vez, podem conter várias classes.

A visão detalhada pode ser visualizada na figura abaixo:

Figura 2.18 – Visão detalhada da IDE eclipse.


Fonte: Elaborado pelo autor (2018)

Já criamos a primeira classe Java, agora vamos adicionar um código para


executar o programa e exibir informações.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 19 de 41

Implemente a classe conforme a classe abaixo:

Figura 2.19 – Primeira classe Java


Fonte: Elaborado pelo autor (2018)

Na linha 5, o código public static void main(String[] args) define o método


main. As chaves de abertura e fechamento estão delimitando o início e o fim do
método.

Por enquanto, não se preocupe com o método main. Vamos explorar os


métodos em breve. O que você precisa saber no momento é que para executar uma
classe compilada, a máquina virtual do Java sempre inicia a execução pelo método
main. Portanto, é necessário ter um método main na classe que você deseja executar.
Mas podemos criar várias classes e chamá-las a partir do método main.

A instrução System.out.println(), que está dentro do método main, exibe na


console a informação que está entre os parênteses, neste caso “FIAP – Olá Mundo”.
Toda instrução deve terminar com ponto e vírgula (;).

Outro detalhe é o asterisco antes do nome da classe na aba do editor. Esse


asterisco indica que a classe não foi salva. Dessa forma, utilize o atalho c.

CTRL + S ou o botão Save, localizado na barra de ferramentas.

É sempre importante salvar os arquivos, pois nesse momento o Eclipse


manda compilar a classe Java.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 20 de 41

Figura 2.20 – Projeto sem salvar


Fonte: Elaborado pelo autor (2018)

Vamos executar o programa. Para isso, utilize o atalho F11 ou o botão “play”
localizado na barra de ferramentas:

Figura 2.21 – Botão para Salvar e Executar o programa Java.


Fonte: Elaborado pelo autor (2018)

Existe mais uma opção para executar a classe Java. Basta clicar com o botão
direito do mouse em cima da classe e escolher as opções: Run As => Java
Application.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 21 de 41

Figura 2.22 – Executando a classe Java.


Fonte: Elaborado pelo autor (2018)

O resultado é apresentado na figura abaixo:

Figura 2.23 – Resultado da execução do programa Java.


Fonte: Elaborado pelo autor (2018)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 22 de 41

A informação é exibida no Console do Eclipse.

Pronto! Desenvolvemos o primeiro programa em Java. Agora vamos estudar


os fundamentos básicos da programação Java.

2.2 Tipos de dados e variáveis

Para armazenar informações no programa, Java precisamos de variáveis. As


variáveis são compostas pelo seu nome e o tipo de informação que irá armazenar.
Para declará-la, primeiro é definido o tipo e depois o nome da variável, como por
exemplo:

int idade;

double preco;

É possível também declarar mais de uma variável do mesmo tipo de uma só


vez:

double preco, salario;

Dessa forma, sabemos que o Java é uma linguagem fortemente tipada, pois
cada variável precisa ter um tipo declarado. Existem oito tipos primitivos para
armazenamento de informações. Tipos primitivos não são objetos, eles são partes
internas da linguagem Java, o que os tornam mais eficientes. Uma variável também
pode armazenar um objeto, veremos isso mais adiante.

Os nomes das variáveis podem começar com uma letra, um caractere de


sublinhado ( _ ) ou $. Depois do primeiro caractere, os nomes das variáveis podem
conter qualquer combinação de letras ou números.

Por padrão, o nome da variável deve começar com um caractere em


minúsculo e se for composto por mais de uma palavra, a próxima palavra deve
começar com caractere em maiúscula.

Lembre-se de que a linguagem Java é case sensitiva, ou seja, as letras


maiúsculas e minúsculas são diferentes. Assim, uma variável preco é diferente de
Preco.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 23 de 41

Na linguagem Java existem palavras que não podemos utilizar para nomear
as variáveis, classes ou métodos. São as palavras reservadas, que possuem
significados dentro da programação. A lista completa é apresentada abaixo:

Figura 2.24 – Palavras reservadas


Fonte: Elaborado pelo autor (2018)

Voltando aos tipos de variáveis, como já adiantamos, existem oito tipos


primitivos. Quatro são para armazenar tipos números inteiros, positivo ou negativo,
sem a parte fracionária.

Abaixo apresentamos os nomes dos quatro tipos primitivos para números


inteiros, o tamanho que ocupa na memória e o intervalo de valores que cada tipo
consegue armazenar.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 24 de 41

Figura 2.25 – Tipos primitivos inteiros


Fonte: Elaborado pelo autor (2018)

A diferença entre os tipos é o tamanho do número que consegue armazenar,


e consequentemente, a quantidade de memória necessária para isso. Na maioria das
situações, o tipo int é o mais utilizado. Porém, quando for necessário armazenar um
número muito grande, precisamos recorrer ao tipo long.

Valores de ponto flutuante são os números que contêm parte fracionária, ou


seja, os números decimais. Para eles existem dois tipos, como apresentados na tabela
abaixo:

Figura 2.26 – Tipos primitivos de ponto flutuante


Fonte: Elaborado pelo autor (2018)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 25 de 41

O tipo double é duas vezes mais preciso que o tipo float. Na maioria dos
casos é utilizado o tipo double.

O tipo char é utilizado para armazenar caracteres individuais, como letras,


algarismos, sinais de pontuação, entre outros.

O último tipo é o boolean, que possui somente dois valores, verdadeiro (true)
ou falso (false). No Java não é possível converter números inteiros em valores
booleanos.

2.2.1 Atribuindo valores às variáveis

Depois de declarar uma variável, podemos atribuir um valor a ela com o


operador de atribuição, que é definido pelo sinal de igual (=).

Exemplos:

int idade = 10;

double preco = 10.0;

char sexo = ‘M’;

boolean maiorIdade = false;

Vamos praticar! Crie uma nova classe com o método main, adicione algumas
variáveis, atribua valores e imprima o seu conteúdo. Utilize como guia o exemplo
abaixo:

Figura 2.27 – Exemplo tipos primitivos.


Fonte: Elaborado pelo autor (2018)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 26 de 41

Teste todos os tipos de dados primitivos.

Muitas vezes, é necessário converter um tipo de dado em outro tipo. A figura


abaixo apresenta as conversões possíveis:

Figura 2.28 – Conversões de tipos de dados


Fonte: Elaborado pelo autor (2018)

As setas sólidas indicam as conversões de tipos onde não se perdem


informações, pois o tipo muda de um tamanho menor para um maior. As três setas
pontilhadas indicam conversões que podem perder informações. Por exemplo, um
número inteiro grande pode ter mais números que um tipo float pode armazenar.

Essas são as conversões que podem ser realizadas automaticamente.

Figura 2.29 – Conversões entre tipos primitivos


Fonte: Elaborado pelo autor (2018)

Por outro lado, existem momentos em que não é possível realizar as


conversões automáticas. Por exemplo, transformar um double em int. Essa conversão

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 27 de 41

é viável, porém há risco em perder informações. Esse tipo de conversão é possível


por meio de cast. A sintaxe é adicionar o tipo que queremos converter entre
parênteses:

double x = 10;

int y = (int) x;

Exemplo:

Figura 2.30 – Conversão utilizando cast


Fonte: Elaborado pelo autor (2018)

O exemplo acima converte um tipo double em tipo int, mas neste caso, a
variável x recebe somente a parte inteira do número, perdendo assim informações.

2.3 Operadores

Operadores são símbolos especiais utilizados para operações matemáticas,


instruções de atribuições e comparações lógicas.

Os operadores aritméticos comuns são utilizados para realizar somas,


subtrações, multiplicação e divisão. Existe ainda um operador que retorna o resto da
divisão de dois números, chamado módulo.

Abaixo apresentamos os cinco operadores aritméticos:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 28 de 41

Figura 2.31 – Operadores aritméticos


Fonte: Elaborado pelo autor (2018)

Observe que o símbolo asterisco (*) representa uma multiplicação, o sinal de


porcentagem (%) retorna o resto da divisão entre dois números.

A divisão entre inteiros produz números inteiros. A parte fracionária é


descartada, sem nenhum arredondamento. Por exemplo, o resultado de 7/2 é 3. O
operador módulo (%) fornece o resto da divisão, assim 7%2 produz o resultado 1.

Assim como na matemática, no Java podemos realizar várias operações


aritméticas de uma vez. As regras de precedência de operadores aplicados na
matemática também se aplicam no Java:

• As operações de multiplicação, divisão e módulo são realizadas primeiro. Eles


possuem o mesmo nível de precedência, dessa forma, se a expressão
matemática possuir dois operadores desses, elas serão aplicadas da esquerda
para a direita.

• As operações de adição e subtração são aplicadas em seguida. Elas possuem


o mesmo nível de precedência.

Podemos utilizar os parênteses para agrupar as operações matemáticas, da


mesma forma que são utilizados em expressões algébricas. Por exemplo, para x + y
e depois multiplicado por z escrevemos:

(x + y) * z;

Dessa forma, a expressão x + y é realizada primeiro.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 29 de 41

2.3.1 Operadores de atribuição

Como já vimos, atribuir valores a uma variável utilizamos o símbolo de igual


(=).

A atribuição ocorre sempre após o processamento das expressões do lado


direito da atribuição. Por exemplo:

int x = 10;

x = x + 15;

Qual valor final de x? Primeiro a variável x foi inicializada com o valor 10.
Depois a expressão x + 15 é processada primeiro, retornando o valor 25. Após isso,
é realizada a atribuição desse valor na própria variável x.

Para facilitar essa tarefa, que é extremamente comum na programação,


existem operadores específicos para esses casos. Assim, o código assim pode ser
escrito dessa forma:

int x = 10;

x +=15;

Os outros operadores aritméticos básicos: multiplicação, divisão e subtração


também possuem esses operadores de atribuição com a operação matemática.

Abaixo apresentamos os operadores de atribuição e as expressões às quais


são equivalentes.

Figura 2.32 – Operadores de atribuição


Fonte: Elaborado pelo autor (2018)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 30 de 41

2.3.2 Operadores de incremento e decremento

Para aumentar ou diminuir o valor de uma variável em uma unidade podemos


utilizar os operadores de incremento e decremento.

Por exemplo, para adicionar 1 à variável x, utilizamos x++; É o mesmo


resultado da expressão x = x + 1; Para subtrair 1 de x, podemos escrever x--; que
produz o mesmo resultado de x = x -1;

Assim, quais valores serão impressos na execução do código abaixo?

Figura 2.33 – Exemplo de utilização dos operadores de incremento e decremento


Fonte: Elaborado pelo autor (2018)

A resposta é 11 e 10. Pois primeiro acrescentamos 1 à variável a e


imprimimos. Depois decrementamos em 1 e imprimimos.

A classe abaixo apresenta um resumo de todos os operadores visto até o


momento:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 31 de 41

Figura 2.34 – Operadores aritméticos e de atribuição.


Fonte: Elaborado pelo autor (2018)

Figura 2.35 – Resultado da execução


Fonte: Elaborado pelo autor (2018)

Agora é a sua vez! Crie uma nova classe e realize testes com os operadores
aritméticos e de atribuição, conforme o exemplo anterior.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 32 de 41

2.3.3 Operadores de igualdade e relacionais

Para realizar comparações entre variáveis, variáveis e valores ou outros tipos


de informações, são utilizados operadores para formar expressões que retornam um
valor booleano verdadeiro (true) ou falso (false). Abaixo apresentamos os operadores
de comparação do Java:

Figura 2.36 – Tabela Operadores de igualdade e relacionais


Fonte: Elaborado pelo autor (2018)

Exemplo:

int idade = 10;

boolean maioridade = idade > 18;

No exemplo acima, a variável idade é inicializada com o valor 10. Depois é


criada uma variável booleana chamada maioridade, que recebe o resultado da
expressão idade > 18, ou seja, o resultado do teste da idade ser maior que 18. Neste
caso false.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 33 de 41

2.3.4 Operadores lógicos

Operadores lógicos são utilizados para formar expressões de comparação


mais complexas, que possuem mais de um termo para comparação. Essas
expressões resultam em valores booleanos.

Os operadores utilizados para combinar as comparações são AND, OR, XOR


e NOT.

O operador lógico AND (e) é representeado pelo símbolo &&. Quando duas
expressões booleanas utilizam o operador &&, o resultado final é verdadeiro (true)
somente quando as duas expressões forem verdadeiras. Exemplo:

boolean precisaVotar = idade > 18 && idade < 70;

A expressão combina duas comparações: a primeira verifica se a variável


idade é maior que 18 (idade > 18) e a segunda, testa se a idade é menor que 70 (idade
< 70). Se as duas expressões forem verdadeiras, a variável precisaVotar recebe
verdadeiro (true), em qualquer outra situação o valor será falso (false).

Para a combinação OR, o operador || é utilizado. Essas expressões


combinadas retornam como verdadeiro caso uma das expressões seja verdadeira.

Observe o exemplo abaixo:

boolean teste = x < 10 || x > 50;

A expressão acima também combina duas comparações. A diferença é que


ela foi combinada com o operador OR (ou), dessa forma, a variável teste receberá o
valor verdadeiro se qualquer uma das duas expressões forem verdadeiras. Ela
receberá o valor falso somente se as duas expressões forem falsas.

O operador XOR é representado pelo símbolo ^. A combinação resulta em um


valor verdadeiro (true) somente se as duas expressões tiverem valores opostos. Se
ambos forem verdadeiros, ou ambos serem falsos, o resultado da combinação será
false.

O operador NOT utiliza o operador lógico!

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 34 de 41

Ela reverte o valor da expressão booleana. Por exemplo, idade > 18 retorna
um valor verdadeiro se a idade for maior que 18. A expressão !(idade > 18) retornará
um valor false, caso a idade seja maior que 18:

!(idade > 18)

Se a idade for 20, a expressão retorna true: !(true) -> invertendo o valor (!) ->
o resultado é false.

2.4 Fluxo de controle e escopo de bloco

A maioria das linguagens possui um fluxo de controle como as instruções de


seleção e loops. Primeiramente vamos estudar as instruções condicionais (seleção).

Antes de entrar na estrutura de seleção, vale relembrar os blocos.

Vimos que as chaves { } delimitam o início e o fim de classes e métodos.


Neste caso, eles delimitam os blocos de código que pertencem à classe e ao método.
Os blocos podem ser aninhados dentro de outro bloco, como, por exemplo, a classe
que possui um método.

A instrução condicional no Java é realizada pela palavra reservada if e tem a


seguinte sintaxe:

if (condição) instrução.

A condição deve ser colocada entre os parênteses e podem conter várias


expressões combinadas com os operadores lógicos.

Quando a condição for verdadeira, o que estiver dentro do bloco if será


executado. Para determinar o bloco de código que pertence ao if as chaves são
utilizadas:

if (condição) {

instrução 1;

instrução 2;

Exemplo:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 35 de 41

if(x > 10){

System.out.println("X é maior que 10");

System.out.println(" ***** FIM ***** ");

Figura 2.37 – Fluxo para a instrução if


Fonte: Elaborado pelo autor (2018)

Podemos utilizar também o comando else (que é opcional) junto do if. Assim,
se a condição do if for false, o bloco de código do else será executado.

if (condição) {

Instrução;

}else{

Instrução;

Exemplo:

if (x > 10){

System.out.println("X é maior que 10");

} else {

System.out.println("X é menor ou igual a 10");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 36 de 41

Figura 2.38 – Fluxo para a instrução if – else


Fonte: Elaborado pelo autor (2018)

É possível utilizar uma instrução de seleção dentro de outra instrução de


seleção. Como por exemplo:

if(x > 10){

System.out.println("X é maior que 10");

} else if(x == 10) {

System.out.println("X é igual a 10");

} else {

System.out.println("X é menor que 10");

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 37 de 41

Dessa forma, um if fica dentro de outro if (neste caso do else). Sempre um


else pertence ao if que estiver mais próximo dele. No exemplo, primeiro é verificado
se o x é maior que 10, senão for, verifica-se o x é igual a 10, se não for imprime o valor
“X é menor que 10”.

Figura 2.39 – Fluxo para if – else aninhados


Fonte: Elaborado pelo autor (2018)

2.5 Entrada e saída de dados

Já vimos como podemos exibir informações para o usuário com a instrução


System.out.println(); existe também a instrução System.out.print(); sendo que a
diferença entre eles é a quebra de linha. O println pula uma linha no final, enquanto
que o print somente imprime a informação e continua na mesma linha.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 38 de 41

Agora, para ler uma informação inserida pelo usuário, precisamos da ajuda da
classe Scanner.

Scanner sc = new Scanner(System.in);

Assim, foi declarada uma variável do tipo Scanner com o nome sc (veremos
com detalhes o operador new e construtores nos próximos capítulos).

Um scanner permite a leitura de dados que podem ser provenientes de várias


origens, como um arquivo do disco ou informações digitadas pelo usuário. Dessa
forma, o valor System.in especifica que queremos ler os valores digitados pelo
usuário.

Após a declaração, podemos utilizar os métodos da classe Scanner para ler


as informações. Existem vários métodos, que são utilizados para ler cada um dos tipos
de dados possíveis:

Scanner sc = new Scanner(System.in);

int idade = sc.nextInt();

double preco = sc.nextDouble();

No exemplo acima, o método nextInt() lê um número inteiro. E o método


nextDouble() lê um número de ponto flutuante.

A classe Scanner está definida no pacote java.util.

Sempre que precisamos utilizar uma classe que estão em pacotes diferentes
e não são do pacote básico (java.lang) é necessário utilizar a instrução import.

Figura 2.40 – Exemplo de leitura de dados


Fonte: Elaborado pelo autor (2018)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 39 de 41

Observe a instrução import logo após a definição do pacote da classe. O


import tem o nome do pacote mais o nome da classe que queremos utilizar na classe
LeituraDeDados.

Na linha 9 é realizada a leitura de dados. Após, é feita a impressão do valor


digitado.

Na linha 11 estamos fechando o scanner, pois não vamos mais utilizá-lo.

No exemplo abaixo, o programa lê dois números e realiza a soma entre eles.


Depois verifica se o número é somado é par.

Figura 2.41 – Exemplo de leitura de dados.


Fonte: Elaborado pelo autor (2018)

Resultado da execução:

Figura 2.42 – Exemplo de leitura de dados.


Fonte: Elaborado pelo autor (2018)

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 40 de 41

Vamos praticar! Crie um programa Java que calcule o IMC e exiba se ele está
no peso ideal ou não.

O programa deve receber dois valores: altura e peso. O resultado do IMC é


calculado através da expressão: peso / (altura * altura);

Caso o imc esteja entre 18.5 e 25, informe que o peso é ideal, caso contrário,
informe que está fora do peso normal.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
IDES, VARIÁVEIS, CONVERSÕES E HELLO WORLD Página 41 de 41

REFERÊNCIAS

BARNES, David J. Programação Orientada a Objetos com Java: Uma introdução


Prática Utilizando Blue J. São Paulo: Pearson, 2004.

CADENHEAD, Rogers; LEMAY, Laura. Aprenda em 21 dias Java 2 Professional


Reference. 5.ed. Rio de Janeiro: Elsevier, 2003.

DEITEL, Paul; DEITEL, Harvey. Java Como Programar. 8.ed. São Paulo. Pearson,
2010.

HORSTMANN, Cay; CORNELL, Gary. Core Java. Volume I Fundamentos. 8.ed. São
Paulo: Pearson, 2009.

SIERRA, Kathy; BATES,Bert. Use a cabeça! Java. Rio de Janeiro: Alta Books, 2010.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com
julianafigueiredo204@gmail.com
Orientação a Objetos Página 2

SUMÁRIO
1 INTRODUÇÃO ................................................................................................ 4
1.1 Linguagem de Programação ........................................................................ 4
1.2 Introdução Java ............................................................................................ 5
1.3 Portabilidade ................................................................................................ 7
1.4 Orientação a objetos .................................................................................... 9
1.5 Princípios de Orientação a Objetos ............................................................ 12
REFERÊNCIAS ................................................................................................ 17

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 3

LISTA DE FIGURAS

Figura 1.1 – Compilação de código Java para um SO específico ...................... 7


Figura 1.2 – Funcionamento do processo de compilação, distribuição e execução de
código Java ........................................................................................................ 8
Figura 1.3 – Molde para construção de carros ................................................. 10
Figura 1.4 – Atributos da classe Professor ....................................................... 11
Figura 1.5 – Métodos da classe Professor ....................................................... 12
Figura 1.6 – Princípios da programação orientada a objetos ........................... 13
Figura 1.7 – Herança entre classes .................................................................. 15

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 4

1 INTRODUÇÃO

Nos últimos anos, o mundo presenciou uma ampla transformação tecnológica.


Sua utilização em diversas áreas é uma realidade e seus impactos são positivos,
trazendo progresso e agilidade por onde passa.

Pense em uma loja, um banco financeiro, um hospital, sua conta de telefone


ou na sua rede social favorita. Todos eles precisam de um sistema para serem
gerenciados. É aí que entra o Desenvolvedor de Sistemas.

Esse profissional de TI, tão requisitado, é fundamental na construção de


sistemas e deve dominar conceitos básicos, entre eles: a lógica e a linguagem de
programação.

O mercado atualmente dispõe de várias linguagens de programação para a


construção de softwares. Novas linguagens podem surgir e as “antigas” evoluem,
com novas versões.

A escolha de uma linguagem para o desenvolvimento de um sistema deve


levar em consideração diversas variáveis estratégicas, como: maturidade da
plataforma, custo, velocidade de desenvolvimento e curva de aprendizagem.

Java vem se tornando uma plataforma de desenvolvimento das mais


utilizadas e aceitas no mercado. Isso se deve a algumas características, como:
portabilidade, simplicidade e entre outros que iremos elencar no decorrer do curso.

Aprender a linguagem Java não limita o desenvolvedor a esta plataforma. Os


conceitos de Orientação a Objetos: Herança, Polimorfismo, Encapsulamento,
Modularização e Abstração são aplicados a qualquer tipo de linguagem Orientada a
Objetos (C#, VB.NET, PHP etc.) e, a lógica de programação, estruturas de controle,
variáveis, por exemplo, são comuns a todas elas.

1.1 Linguagem de Programação

Uma linguagem de programação pode ser definida como sendo um conjunto


limitado de instruções (vocabulário), associado a um conjunto de regras (sintaxe) que
define como as instruções podem ser associadas, ou seja, como se podem compor
os programas para a resolução de um determinado problema.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 5

A programação em computadores teve início com o objetivo de resolver


cálculos matemáticos, depois passou a ter uso nas empresas em meados dos anos
1970, com objetivo da automatização de processos manuais. O formato que dominava
a programação dos sistemas na época era chamado de programação linear e
estruturada, que tem como base o controle: sequência, condição e repetição, e a
subprogramação (ou modularização) utilizando sub-rotinas e funções.

Nesta categoria encaixam-se as chamadas linguagens de programação de


baixo nível, surgidas em meados dos anos 1960 como Fortran, Cobol, Pascal, C.

As linguagens concebidas nesse período resultam da necessidade da


produção de código de programa de forma clara, aparecendo o conceito de
estruturação do código. O período compreendido entre as décadas de 1960 e 1980
foi bastante produtivo no que diz respeito ao surgimento de linguagens de
programação, o que permitiu o aparecimento de uma grande quantidade de
linguagens.

Com o aumento na produção de sistemas e com a expressa necessidade de


reaproveitamento de códigos, este processo antes inicialmente tão positivo, passou a
se tornar repetitivo e trabalhoso, pois toda e qualquer atualização no sistema deveria
ser realizada em todas as partes que eram replicadas.

Mediante esta situação que, além do desgaste técnico, causava baixa


produtividade no desenvolvimento e peso financeiro às empresas, novas técnicas
surgiram para resolver estes problemas. Desponta o modelo de objetos, baseado nos
moldes já milenares da vida do ser humano.

Trazer para a programação os conceitos de objetos da vida real e a criação de


moldes para esses objetos, favoreceu toda uma nova linha de sistemas otimizados,
reaproveitáveis e de fácil atualização.

1.2 Introdução Java

A primeira versão da linguagem Java surgiu em 1995, criada por um time de


desenvolvedores da empresa Sun Microsystem, liderado por James Gosling. A ideia
inicial era desenvolver uma linguagem para controlar pequenos dispositivos, como
televisores, videocassetes e aparelhos de TV a cabo. A ideia não deu certo, mas com

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 6

o advento da internet, a plataforma foi adotada, se expandiu e evoluiu, e atualmente


é uma referência no mercado de desenvolvimento de sistemas.

Java se tornou popular pelo uso na internet e hoje roda em muitos


equipamentos e dispositivos: notebooks, celulares, videogames, cartões inteligentes
etc.

Podemos elencar várias características-chave para a plataforma ter alcançado


tanto sucesso:

 Simples: a sintaxe do Java é uma versão limpa da sintaxe das linguagens


da época, como C++. Não há a necessidade de arquivos de cabeçalho ou
trabalhar com ponteiros (alocar memória da máquina para armazenar
informações).

 Robusto: Java foi concebido para desenvolver programas confiáveis, em


vários aspectos. Existe uma verificação preliminar de possíveis
problemas, que em outras linguagens, só seriam descobertos em tempo
de execução.

 Seguro: Java é utilizado em ambientes de rede/distribuído. Desse modo,


muito se trabalhou para a segurança, deixando a plataforma livres de vírus
e adulterações.

 Alto desempenho: o código Java é convertido em bytecodes (veremos


com mais detalhes), esses bytecodes são interpretados em um ambiente
de execução do Java para executá-los. Se for necessário mais
desempenho, esse ambiente de execução transforma os bytecodes em
código de máquina nativo para a CPU específica, ganhando assim
desempenho.

Além desses, podemos citar duas outras características que foram


determinantes para o sucesso: portabilidade e orientação a objetos.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 7

1.3 Portabilidade

Entende-se por portabilidade a capacidade de ser utilizado em qualquer


plataforma, neste caso – sistema operacional (Windows, Linux, Mac OS.) e hardware.
Ou seja, Java é utilizado independente de plataforma.

Um programa Java gerado no ambiente Windows pode, facilmente, ser


executado em Linux, sem nenhuma alteração no código.

Quando escrevemos código utilizando uma linguagem de programação é


necessário a conversão desse código para um outro código, de modo que o
computador seja capaz de executá-lo. Esse processo possui o nome de compilação,
cujo significado é transformar o código fonte, que é mais fácil para os
desenvolvedores, em código de máquina, que é utilizado pelo computador.

Linguagens como C e Pascal são compiladas para um determinado sistema


operacional e arquitetura de hardware, ou seja, após a compilação, o código
executável (binário) roda somente para um tipo de sistema operacional. Se for
necessário executar em outro ambiente, será preciso compilar o programa
especificamente para esse ambiente.

Figura 1.1 – Compilação de código Java para um SO específico


Fonte: Elaborado pelo autor (2016), adaptado por FIAP (2017).

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 8

Em algumas situações haverá necessidade de realizar ajustes no código, para


o perfeito funcionamento em cada ambiente. Dessa forma, temos um código
executável para cada sistema operacional.

A linguagem Java é diferente. Existe uma máquina virtual, conhecida como


JVM (Java Virtual Machine), que é capaz de interpretar (executar) os arquivos Java
compilados.

A linguagem Java é Compilada e Interpretada. Primeiramente, os arquivos de


código fonte Java com extensão “.java” são compilados para bytecodes, também
conhecidos como arquivos de extensão “.class”.

Após esse processo, os bytecodes são interpretados pela JVM, iniciando a


execução do software. Para cada plataforma (sistema operacional + hardware) existe
uma Máquina Virtual Java, tornando as aplicações Java portáveis.

A imagem abaixo ilustra um código Java sendo compilado, que pode ser
executado em diferentes plataformas em suas respectivas JVMs.

Figura 1.2 – Funcionamento do processo de compilação, distribuição e execução de código Java


Fonte: Elaborado pelo autor (2016), adaptado por FIAP (2017).

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 9

Portanto, uma vez compilado, podemos executar o programa


independentemente da plataforma utilizada. Por exemplo, se estamos utilizando um
ambiente com o sistema operacional Linux e o hardware da família x86 para
desenvolver o nosso programa, uma vez compilado, o aplicativo pode ser executado
em um ambiente Windows ou Mac OS, sem a necessidade de recompilar.

1.4 Orientação a objetos

A programação orientada a objetos é uma técnica de programação que focaliza


os dados e interfaces com esses objetos. A essência da programação orientada a
objetos consiste em tratar os dados e os procedimentos que atuam sobre os dados
como um único objeto – uma entidade independente com uma identidade e certas
características próprias.

Para melhor representar a diferença, façamos a analogia com uma fábrica de


carros. Para fabricar carros, é necessário que seja desenhado um molde com as
propriedades que os carros fabricados terão, tais como: modelo, potência, cor, entre
outros. A partir de um único molde, é possível fabricar um, dois ou um milhão de
carros, cada qual com sua potência, cor e modelo. Portanto, um mesmo molde é
utilizado para a criação de vários objetos com caraterísticas diferentes.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 10

Figura 1.3 – Molde para construção de carros


Fonte: Banco de imagens Shutterstock (2017).

Esta analogia é aplicada na criação de sistemas através da Programação


Orientada a Objetos, cujos moldes são criados pensando no mundo real e são
chamados de Classes. Em tempo de execução (fabricação), os objetos são gerados
cada qual com suas informações. Caso uma atualização seja necessária, a Classe é
alterada e a mudança é refletida para todos os sistemas que utilizam este molde e,
consequentemente, a todos os objetos gerados também.

Um objeto, como já descrito, é gerado a partir de um molde ou classe, seguindo


os princípios do mundo real. Um objeto representa uma entidade que pode ser física,
conceitual ou de software:

 Física: quando representa um modelo físico (como um caminhão, óculos,


prédio, entre outros).

 Conceitual: quando representa formas abstratas, não palpáveis (como a


matemática, o pensamento, o sentimento, entre outros).

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 11

 De software: quando representam sistemas (como um usuário, e-mail,


acesso etc.).

Um objeto é uma entidade com fronteira e identidade bem definidas que


encapsulam o estado e comportamento.

O estado é representado pelos atributos e relacionamentos. É a condição ou


situação durante a vida de um objeto, que satisfaz alguma condição, realiza alguma
atividade ou aguarda algum evento. Um estado normalmente é alterado ao longo de
um tempo.

Portanto, o atributo representa as informações que o objeto pode ter, como


exemplificado na figura abaixo, os atributos são: nome, matrícula, admissão, cargo,
disciplina e carga horária.

Figura 1.4 – Atributos da classe Professor


Fonte: Elaborado pelo autor (2016), adaptado por FIAP (2017).

O comportamento é representado pelas operações, métodos e máquinas de


estado. Ele determina como o objeto age ou reage a uma requisição de outro objeto.
É representado pelas operações que ele pode realizar, ou seja, conforme mostra a
figura abaixo – todos os comportamentos que o Professor Roberto pode fazer
representam os métodos a ele designado.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 12

Figura 1.5 – Métodos da classe Professor


Fonte: Elaborado pelo autor (2016), adaptado por FIAP (2017).

Portanto, a programação orientada a objetos é uma sequência de instruções


enviadas ao computador que utiliza e manipula objetos em seu funcionamento.

Prática:

 Pense em dois objetos do mundo real.

 Para cada objeto:

 Identifique quatro atributos (propriedades).

 Descreva três comportamentos (métodos).

1.5 Princípios de Orientação a Objetos

O alicerce da Programação Orientada a Objetos é baseado em quatro


princípios, os quais devem ser pensados e refletidos nos processos do
desenvolvimento de um sistema:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 13

Figura 1.6 – Princípios da programação orientada a objetos


Fonte: Elaborado pelo autor (2016), adaptado por FIAP (2017).

 Abstração: entendimento e análise das necessidades do sistema, abstraindo


o do mundo real.

 Exemplos: para um sistema de gerenciamento acadêmico de uma faculdade,


mais especificamente para a funcionalidade de cadastro de alunos, os moldes
(classes) devem ser pensados com base nas características reais de um aluno
(registro, nome, endereço, curso, data de nascimento etc.) e que sejam
relevantes para o sistema. Por exemplo: informações como altura e peso
podem ser irrelevantes para o sistema.

 Encapsulamento: programar em partes, o mais isolado possível,


encapsulando-as. O objetivo é tornar o software mais flexível, fácil de modificar
e evoluir. As classes devem proteger as suas informações e comportamentos,
ou seja, devem possuir proteção no acesso a seus atributos e métodos.

 Pensando no mundo real, os objetos também possuem essa proteção.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 14

 Exemplo: quando um cliente compra um micro-ondas e deseja utilizá-lo, basta


acionar os botões para programar um tempo (inserindo informações aos seus
atributos) e pressionar o botão para iniciar o aquecimento (invocando um
comportamento). Esses botões irão acionar os circuitos elétricos e as placas
internas, sem que o cliente tenha a necessidade de conhecimento do que
ocorre dentro da “CÁPSULA” do micro-ondas.

 As classes devem ter a mesma proteção, permitindo que outras classes


somente acessem as suas funcionalidades, sem a necessidade de conhecer a
sua lógica interna. Dessa forma, a classe esconde a implementação de classes
clientes e faz com que estes interajam somente através das interfaces
disponíveis (Botões do micro-ondas).

 Hierarquia: na programação orientada a objetos existe herança, assim como


no mundo real. Por exemplo: um filho recebeu de seu pai a cor do olho azul e
seu pai herdou de seu avô essa característica.

No mundo da programação é o mecanismo pelo qual uma classe pode estender


(herdar) de outra classe para receber seus comportamentos (métodos) e variáveis
(atributos).

Exemplo: a classe mamífero é pai da classe humano, ou seja, um humano é


um mamífero e recebe os atributos e métodos da classe pai (mamífero).

A Herança é um dos mecanismos fundamentais para as linguagens que


suportam o paradigma OO (Orientação a Objetos). É um mecanismo que possibilita a
criação de novas classes a partir de uma já existente. É utilizada como forma de
reutilizar os atributos e métodos de classes já definidas, permitindo assim derivar uma
nova classe mais especializada a partir de outra classe genérica existente.

Aplicar herança sempre envolve basicamente dois elementos: uma superclasse


(classe pai) e uma subclasse (classe filha).

Superclasse é também conhecida como classe ancestral ou classe pai.


Apresenta as características genéricas de um conjunto de objetos.

Subclasse é também conhecida como classe descendente ou classe filha. Ela


estende a superclasse para incluir suas características. A imagem a seguir ilustra a
herança:

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 15

Figura 1.7 – Herança entre classes


Fonte: Elaborado pelo autor (2016), adaptado por FIAP (2017).

A organização das classes deve ser realizada hierarquicamente, e duas


perguntas são básicas para esta organização: IS-A (É-UMA) e HAS-A (TEM-UMA). É
necessário perguntar se uma classe É-UMA parte hierárquica de outra, ou se contém
outra classe.

Exemplo: supondo as classes Aluno, Pessoa e Disciplina.

 Aluno É-UMA Pessoa? Aluno TEM-UMA Pessoa?

o A resposta para a primeira pergunta é SIM, portanto o Aluno tem uma


ligação hierárquica com Pessoa (Herança).

 Aluno É-UMA Disciplina? Aluno TEM-UMA Disciplina?

 A reposta da segunda pergunta é SIM, portanto o Aluno tem uma ligação


direta com Disciplina, ou seja, a classe Aluno pode possuir um atributo para
armazenar as Disciplinas ligadas a ele.

Modularização: é o processo de dividir um todo em partes bem definidas, que


podem ser construídas e examinadas separadamente e que consigam interagir entre
si. Assim como no mundo real, a programação orientada a objetos permite a criação

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 16

de componentes modulares, que podem ser reutilizados para diversos sistemas


distintos.

Por exemplo: a classe Aluno, se for criada seguindo princípios citados


anteriormente, pode ser utilizada para o sistema de cadastro de alunos, para o sistema
financeiro da faculdade, lançamento de notas, consulta ao boletim, entre outros.

Veremos no decorrer do curso como implementar em código Java cada um dos


princípios de orientação a objetos apresentados aqui.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com
Orientação a Objetos Página 17

REFERÊNCIAS

BARNES, David J. Programação Orientada a Objetos com Java: Uma introdução


Prática Utilizando Blue J. São Paulo: Pearson, 2004.

COLHO, Alex. Java com Orientação a Objetos. Rio de Janeiro: Ciência Moderna,
2012.

HORSTMANN, Cay; CORNELL, Gary. Core Java. Volume I - Fundamentos. 8.ed.


São Paulo: Pearson 2009.

SIERRA, Kathy; BATES, Bert. Use a cabeça! Java. Rio de Janeiro: Alta Books,
2010.

PDF exclusivo para Juliana Moreira Figueiredo - julianafigueiredo204@gmail.com


julianafigueiredo204@gmail.com

Você também pode gostar