Fazer download em pdf ou txt
Fazer download em pdf ou txt
Você está na página 1de 173

PROGRAMAÇÃO

ORIENTADA A OBJETOS I
PROGRAMAÇÃO
ORIENTADA A OBJETOS I
Copyright © UVA 2019
Nenhuma parte desta publicação pode ser reproduzida por qualquer
meio sem a prévia autorização desta instituição.

Texto de acordo com as normas do Novo Acordo Ortográfico


da Língua Portuguesa.

AUTORIA DO CONTEÚDO PROJETO GRÁFICO


Adriana Aparicio Sicsú Ayres UVA
do Nascimento
DIAGRAMAÇÃO
REVISÃO UVA
Theo Cavalcanti
Lydianna Lima

R343

Rego, Angela

História da língua portuguesa no Brasil [livro eletrônico] /


Angela Rego. – Rio de Janeiro: UVA, 2019.

727 KB.

ISBN 978-85-5459-044-4

1. Língua portuguesa - Brasil - História. 2. Sociolinguística


- Brasil - História. I. Universidade Veiga de Almeida. II.
Título.

CDD – 469.800981

Bibliotecária Katia Cavalheiro CRB 7 - 4826.


Ficha Catalográfica elaborada pela Biblioteca Central da UVA.
SUMÁRIO

Apresentação 6
Autor 7

UNIDADE 1

A linguagem Java e o paradigma da orientação a objetos 8


• Histórico da linguagem Java

• Características

• Ambientes de desenvolvimento

UNIDADE 2

Os conceitos básicos da programação orientada a 49


objetos utilizando o Java
• Classes, objetos, atributos e métodos; métodos de acesso

• Polimorfismo de sobrecarga de operadores e de métodos

• Métodos construtores e sobrecarga de métodos construtores


SUMÁRIO

UNIDADE 3

Os conceitos avançados da programação orientada a 83


objetos utilizando o Java
• A herança de classes, o reaproveitamento de membros das classes e
o polimorfismo de sobrescrita

• Encapsulamento de métodos e atributos e a organização de classes


em pacotes

• Os conceitos de classes abstratas e interfaces

UNIDADE 4

Estruturas homogêneas com Java e o tratamento de 133


exceções
• Estruturas estáticas: vetores e matrizes de tipos básicos

• Criação de vetores de objetos e a organização em memória

• Aplicação do tratamento de exceções em vetores e matrizes


APRESENTAÇÃO

O desenvolvimento de sistemas tem se expandido muito ao longo dos anos. Inicialmen-


te, foram as aplicações científicas e militares, passando pelas comerciais de empresas,
e, posteriormente, cresceu muito com o advento da computação pessoal. A partir desta
e do uso de computadores para o entretenimento, novamente o mercado de desenvolvi-
mento se expandiu. Os computadores pessoais passaram a ser ferramentas importan-
tíssimas nas empresas para a execução de tarefas diárias, e as pessoas, a usar muito
as redes sociais e os aplicativos. Atualmente, estamos vivendo uma nova expansão
com a popularização dos smartphones e tablets, quando aplicações para dispositivos
móveis têm sido muito solicitadas e as empresas têm investido no desenvolvimento de
aplicativos capazes de facilitar a vida de seus usuários, aumentando assim suas opor-
tunidades de negócios. Nesse contexto, o desenvolvimento de sistemas e aplicações
tem sido sempre requisitado a contribuir com esse crescimento. O paradigma de pro-
gramação orientada a objetos permite o desenvolvimento tanto de aplicações simples
como complexas e com grande possibilidade de reaproveitamento de códigos, além de
facilitar a manutenção desses sistemas. A linguagem Java é uma linguagem orientada
a objetos muito versátil, pois permite o desenvolvimento de sistemas complexos com
emprego da arquitetura cliente × servidor, além da criação de aplicações para desktops
e dispositivos móveis.

6
AUTOR

ADRIANA APARICIO SICSÚ AYRES DO NAS-


CIMENTO
Doutora em Computação de Alto Desempenho pelo Instituto Alberto Luiz Coimbra de
Pós-Graduação e Pesquisa de Engenharia da Universidade Federal do Rio de Janeiro –
Coppe/UFRJ. Mestre em Engenharia da Computação pela Universidade do Estado do
Rio de Janeiro – Uerj. Bacharel e licenciada em Informática. Professora concursada do
Centro Universitário Estadual da Zona Oeste – Uezo. Professora da Universidade Veiga
de Almeida – UVA e da Universidade Estácio de Sá – Unesa. Possui experiência na área
de ciência da computação, com ênfase em engenharia de software, atuando principal-
mente nos seguintes temas: modelagem e desenvolvimento de sistemas, bancos de da-
dos e mineração de dados e textos.

7
UNIDADE 1

A linguagem Java e o paradigma


da orientação a objetos
INTRODUÇÃO

O conhecimento das técnicas de desenvolvimento de sistemas baseados no paradigma


de programação orientada a objetos é fundamental para o desenvolvimento de sistemas
complexos, facilitando a divisão de tarefas em partes mais simples e fáceis de serem
desenvolvidas, permitindo que posteriormente essas partes sejam agrupadas de forma
a resolver problemas que envolvam grandes e complexos sistemas. A prática exige o co-
nhecimento e o uso de uma linguagem de programação com suporte aos conceitos de
orientação a objetos. Dessa forma, é importante conhecer uma linguagem de programa-
ção orientada a objetos, tal como a linguagem Java, para poder desenvolver aplicações
segundo esse paradigma.

OBJETIVO

Nesta unidade, você será capaz de:

• Conhecer o paradigma da programação orientada objetos e o histórico e a es-


trutura da linguagem Java.

9
Histórico da linguagem Java

Desenvolvida na década de 1990 por James Gosling, da Sun Microsystems, foi inicial-
mente um pequeno trabalho anônimo, que, após a divulgação de suas ideias, foi apoiado
pela empresa Sun Microsystems, muito conhecida e forte no mercado de desenvolvi-
mento de estações de trabalho e de computação de alto desempenho. A Sun, então,
criou um grupo de trabalho para o projeto, que foi batizado de “The Green Project”, em
1991. Esse grupo foi separado das operações cotidianas da Sun, e uma equipe com 13
desenvolvedores trabalhou em um conjunto de escritórios próprios em Menlo Park, du-
rante 18 meses e sem comunicação com a matriz, para a criação de uma linguagem de
programação que fosse independente de plataforma, com a ideia de criar uma aplicação
em uma plataforma (write once) que pudesse ser executada em outras plataformas dife-
rentes, sem a necessidade de qualquer tipo de alteração (run anywhere).

Ainda naquela época, eles já previam a convergência entre dispositivos controlados di-
gitalmente e computadores. Podemos analisar um exemplo com os dispositivos eletro-
domésticos inteligentes ou ainda os smartphones, que se tornaram verdadeiros compu-
tadores pessoais, com sistema operacional próprio, diversos componentes e inúmeros
aplicativos.

Inicialmente, a linguagem criada foi bati-


zada de “Oak” (em referência ao carvalho
que existia em frente às janelas dos es-
critórios), para posteriormente ganhar o
nome de “Java”, que atualmente se tornou
uma referência no desenvolvimento de
aplicações e é uma homenagem ao tipo
de café muito apreciado pela equipe. Por
isso, a linguagem tem como marca o desenho de uma xícara de café com a fumaça ca-
racterística da bebida.

A equipe, ainda naquela época, criou um controlador portátil direcionado ao entreteni-


mento doméstico (setup box) voltado à televisão digital, mas estava muito além de seu
tempo, uma vez que nessa época a televisão digital não estava tão desenvolvida, mas
todo esse esforço foi recompensado ao se incluir a linguagem Java ao Netscape Navi-
gator (navegador de internet muito utilizado na época), que foi lançado em 1995. A partir
desse momento, a linguagem começou a ser conhecida e passou a ter milhares de adep-
tos e desenvolvedores, sendo usada em todo o mundo até hoje.

10
A tecnologia Java é encontrada em equipamentos de redes, dispositivos voltados à inter-
net, sistemas de controle, supercomputadores, notebooks, desktops, smartphones, tablets,
dispositivos de jogos, máquinas de cartões de crédito, controles de robôs, entre outros.

MIDIATECA

Acesse a midiateca da Unidade 1 e veja o conteúdo indicado como material


complementar pela professora sobre Java.

A plataforma Java

A tecnologia Java se divide entre:

• Uma linguagem de programação, com estrutura e sintaxe, além de empregar o


paradigma de programação orientada a objetos.
• Um ambiente de desenvolvimento, com compilador, interpretador, gerador de do-
cumentação, entre outros.
• Uma biblioteca de classes predefinidas, com suporte a interfaces gráficas (GUI),
coleções de dados, comunicação de dados, entre outras.
• Um ambiente de execução de aplicações capaz de executar aplicações Java nos
mais diferentes tipos de computadores e dispositivos.

Tipos de sistemas que podem ser desenvolvidos em Java

A tecnologia Java conta com três tipos de plataformas, cada uma voltada a um tipo de
aplicação, sendo elas:

• Java SE (Java Standart Edition): são aplicações mais simples, para uso em compu-
tadores pessoais e de empresas.
• Java EE (Java Enterprise Edition): são aplicações mais complexas, que se baseiam
na arquitetura cliente × servidor, que dependem da comunicação de dados e execu-
tam em servidores, normalmente disponíveis em redes locais ou na internet, para
atender a demandas de aplicações do cliente.

11
• JME (Java Micro Edition): permite o desenvolvimento de aplicações voltadas ao en-
tretenimento e ao uso doméstico, tais como aplicativos para celulares, equipamen-
tos de blu-ray, set-top boxes, módulos de equipamento, impressoras, entre outros
equipamentos com aplicações voltadas a dispositivos móveis e integrados.

A tecnologia Java ainda se divide em dois diferentes tipos de suporte às aplicações, o de


desenvolvimento (JDK), no qual criamos as aplicações, e o de execução (JRE), em que as
aplicações são utilizadas pelos usuários.

Para podermos contar com o suporte ao desenvolvimento Java, devemos primeiramente


instalar seu ambiente de desenvolvimento, conhecido como JDK (Java Distribution Kit),
disponibilizado pela Oracle por meio de download no site do Java. Essa plataforma é ne-
cessária para o desenvolvimento e a execução de aplicações Java, mas, se for apenas para
a execução de aplicações, devemos instalar apenas a JRE (Java Runtime Environment).

O ambiente do JDK permite o desenvolvimento e a execução de aplicações Java.

MIDIATECA

Acesse a midiateca da Unidade 1 e veja como realizar o download do ambien-


te JDK.

Esse ambiente instala o compilador e o interpretador Java, permitindo que você possa
criar aplicações nessa linguagem. Ele possui uma quantidade maior de arquivos e só
deve ser instalado pelos desenvolvedores, uma vez que pode atrapalhar o usuário final.
É possível criar aplicações apenas com o JDK, mas seu uso é mais complexo e depende
de conhecimentos avançados do sistema operacional para que o desenvolvedor possa
realizar essa tarefa. Dessa forma, é comum o uso de ferramentas apropriadas, tais como
o NetBeans e o Eclipse, que são específicas para o desenvolvimento de sistemas e muito
apropriadas ao desenvolvimento Java. Esse assunto voltará a ser discutido em breve
ainda neste conteúdo, mas é bom saber que essas ferramentas facilitarão o desenvolvi-
mento e os testes de seus aplicativos.

12
A seguir, podemos compreender o processo de desenvolvimento, no qual é necessário,
primeiramente, que o código do programa Java seja escrito em um editor de textos. Os
ambientes de desenvolvimento NetBeans e Eclipse já possuem um editor preparado para
facilitar a tarefa de edição do código. Após a edição, devemos então compilar o programa
Java para obtermos o arquivo com a extensão “class”, que é o segredo da portabilidade
Java. O arquivo com essa extensão é, então, executado a partir de um interpretador Java.

Editor Prog.java Compilador Prog.class Interpretador

O código é compilado uma vez, Atualmente, realiza uma


gerando o bytecode, que pode compilação just in time
ser interpretado quantas vezes (no momento da exe-
forem necessárias e em qualquer cução) com o intuito de
ambiente Java (JVM) existente. aumentar o desempenho.

O processo de compilação do Java é diferente dos das demais linguagens, pois, en-
quanto nelas a compilação gera um código de máquina para um determinado ambiente
(hardware + software), esse processo em Java gera um código intermediário chamado
“bytecode”, um código especial de máquina, que não leva em consideração um ambiente
específico, mas sim um ambiente genérico que independe do ambiente de desenvolvi-
mento. O bytecode, então, é uma linguagem de máquina genérica que o processo de
compilação da linguagem Java usa para padronizar as aplicações Java independente-
mente do ambiente em que ocorreu o processo de compilação. Os bytecodes indepen-
dem do hardware e do software (sistema operacional) do computador no qual ocorreu a
compilação, permitindo que a interpretação ocorra em qualquer ambiente, mesmo que
seja diferente daquele em que ocorreu a compilação. O interpretador Java também é
conhecido como JVM (Java Virtual Machine), que nada mais é do que um software ca-
paz de interpretar os bytecodes em um ambiente específico. Basta que seja criado um
interpretador Java (JVM) para cada ambiente em que o Java poderá ser executado, que
esse interpretador poderá, então, executar qualquer aplicação Java desenvolvida para
ele. Dessa forma, temos uma JVM específica para cada ambiente ou dispositivo espe-
cífico, mas não podemos esquecer que, uma vez compilado um programa ou aplicação,
essa técnica permite que o programa seja executado em qualquer ambiente. Existem
diferentes versões da máquina virtual Java, uma para cada computador ou dispositivo
que irá executar as aplicações Java.

13
• O ambiente do JRE permite apenas a execução de aplicações Java.

MIDIATECA

Acesse a midiateca da Unidade 1 e veja como realizar o download do ambien-


te do JRE.

O JRE instala apenas a máquina virtual Java (JVM), que é o interpretador Java apropriado
a cada máquina ou dispositivo, existindo então várias versões da JVM. Um computador
ou dispositivo com o JRE instalado poderá apenas executar aplicações Java, mas será
capaz de interpretar os bytecodes gerados em outros computadores com total compati-
bilidade, permitindo então a portabilidade da linguagem Java.

Prog.class Interpretador

Esse ambiente instala apenas o interpretador Java.

Existe, ainda, um plug-in Java para navegadores de internet que permite a execução de
aplicações Java incorporadas às páginas HTML, os chamados “applets Java”.

Como vimos, a linguagem Java é híbrida: enquanto as demais são compiladas ou inter-
pretadas, a linguagem Java é compilada e interpretada, sendo necessariamente obriga-
tória a compilação para o bytecode, e a execução é sempre interpretada pela máquina
virtual Java (JVM), que deve ser instalada no ambiente de execução do cliente. Essa ca-
racterística torna a linguagem Java muito diferente das demais linguagens, contribuindo
para a portabilidade das aplicações Java. Atualmente, o interpretador Java realiza uma
compilação ( just in time) com o intuito de aumentar o desempenho das aplicações. Isso
fez com que as execuções das aplicações se tornassem mais rápidas do que as lingua-
gens de script e mais próximas, mas ainda abaixo do desempenho das linguagens com-
piladas diretamente para um determinado ambiente.

14
MIDIATECA

Acesse a midiateca da Unidade 1 e veja o conteúdo sobre o funcionamento do


Java indicado como material complementar pela professora.

Curiosidade

Aplicações para smartphones com sistema operacional Android® são criadas,


testadas e emuladas em computadores usados para o desenvolvimento, mas
sua execução pelo cliente é toda realizada no smartphone. O Android® utiliza
como linguagem nativa de desenvolvimento a linguagem Java.

Principais características e vantagens da tecnologia Java:

• Suas aplicações independem de plataforma: escreva uma vez e execute em qual-


quer lugar (write once, run everywhere).
• Linguagem de programação orientada a objetos, com grande versatilidade para o
desenvolvimento de diferentes tipos de aplicações.
• Grande biblioteca de classes prontas para suporte a interfaces gráficas, comunica-
ções de dados, acesso a banco de dados, entre várias outras.
• Sua segurança possui mecanismos de suporte à proteção contra vírus e suporte
à criptografia.
• Sintaxe de comando se baseia no padrão da linguagem C.
• Sintaxe simples para a aplicação dos conceitos de orientação a objetos.
• Internacionalização de sistemas, permitindo que as aplicações possam ser de-
senvolvidas com suporte a várias línguas ao mesmo tempo, sendo escolhidas no
momento da instalação.
• Utilização do padrão Unicode, o que permite o uso de textos de qualquer sistema
de escrita.
• Robustez, dando suporte à criação de aplicações simples e com poucos requisitos
até a aplicações altamente complexas e com muitos requisitos.
• Tratamento de exceções em tempo de compilação e em tempo de execução, au-
mentando a segurança na execução de aplicações altamente complexas.
• Suporte a diversos protocolos de rede (TCP/IP, HTTP, FTP etc.).

15
• Execução simultânea, com o uso de múltiplas threads.
• Gerenciamento de memória, com sua limpeza (garbage collection).
• A JVM (máquina virtual Java) possui proteção contra a execução de aplicações
malcomportadas que possam vir a paralisar o sistema.
• Suporte à programação distribuída e à multitarefa.
• Gerenciamento de memória virtual por meio da JVM.
• Alto desempenho, sendo mais rápida do que linguagens de script, mas é mais lenta
do que linguagens de programação compiladas para um ambiente.
• Suas aplicações podem utilizar recursos da rede de forma tão simples quanto
acessar arquivos locais.
• Atualmente, diminuiu os problemas de desempenho com a inclusão da compilação
just in time em vez de uma simples interpretação executada pela máquina virtual.

16
Características

Comentários

Existem três tipos permitidos de comentários nos programas feitos em Java:

// comentário de linha: tudo na linha a partir dele é


// desconsiderado pelo compilador.

/* comentário de bloco: tudo entre o início e o fim é


desconsiderado pelo compilador.
*/

/** comentário de documentação: tudo entre o início e o fim é


desconsiderado pelo compilador, mas é considerado
pelo documentador. (Arquivos de documentação).
*/

Ponto e vírgula, blocos e o espaço em branco

• Na linguagem Java, os comandos são terminados com o sinal de ponto e vírgula ( ; ).


• Um bloco tem seu início e seu fim representados pelo uso das chaves ({ }).
• O uso dos espaços em branco (indentação) permite uma melhor visualização dos
comandos de controle de fluxo e de instruções, e, em consequência, facilita a visua-
lização para a realização da manutenção no programa.

Identificadores

Identificadores são usados para dar nomes aos elementos dos nossos programas, tais
como: classes, objetos, interfaces, variáveis, constantes, métodos, atributos etc.

• Os identificadores só podem começar por:

– Uma letra (maiúscula ou minúscula – ver as regras da boa prática de programação).


– O símbolo $.
– O símbolo _ (underscore).

17
• Após o primeiro caractere, passam a ser permitidas novas letras (maiúsculas ou
minúsculas), os símbolos $ e _, além dos dígitos de 0 a 9 (um identificador não pode
iniciar por um dígito).
• Não há limite para o número de letras, símbolos e dígitos em um identificador.
• Você deve evitar o uso de caracteres acentuados e de outros símbolos ao nomear
um identificador (ç, á, é, í, ó, ú, â, ê, ô, à, ã, õ, %, #, @ etc.).
• Identificadores na linguagem Java são case-sensitive, ou seja, fazem distinção
entre letras maiúsculas e minúsculas: pessoa, PESSOA e Pessoa são identificado-
res diferentes.
• Exemplos de identificadores permitidos:

– Identificador
– UserName
– Username
– _sys_var1
– $change

• Algumas palavras reservadas não são permitidas como identificadores, tais


como:

Abstract Do Implements Private Throw

Boolean Double Import Protected Throws

Break Else Instanceof Public Transient

Byte Extends Int Return True

Case False Interface Short Try

Catch Final Long Static Void

Char Finally Native Super Volatile

Class Float New Switch While

Continue For Null Synchronized

Default If Package This

18
Declaração de variáveis auxiliares

A linguagem Java possui grande semelhança com a sintaxe utilizada nas linguagens C/
C++, e todas as variáveis em Java devem ser tipadas (o tipo de dado deverá ser explicita-
mente informado).

• Linguagens de programação fracamente tipadas: são linguagens em que as va-


riáveis podem ser criadas sem a necessidade de identificação do tipo de dado que
será armazenado nelas. Essas variáveis são conhecidas como variantes e podem
armazenar tipos diferentes de dados durante a execução do programa. Lingua-
gens como PHP e Visual Basic são exemplos de linguagens fracamente tipadas,
sendo que o Visual Basic permite que as variáveis sejam obrigatoriamente tipadas
quando usamos “option explicit”.
• Linguagens de programação fortemente tipadas: são linguagens que obrigam
todas as variáveis criadas a terem seu tipo definido, não permitindo que tipos dife-
rentes do que foi declarado sejam armazenados nessas variáveis.

Importante

A linguagem Java é fortemente tipada, desse modo todas as variáveis, as cons-


tantes e os atributos devem ser tipados.

Tipos de dados básicos

A linguagem Java possui nove tipos de dados básicos, sendo oito deles primitivos e um
tipo especial. Esses dados formam a base para o armazenamento em memória de todos
os tipos suportados pela linguagem.

A boa prática em programação Java determina que variáveis e atributos devem ser
identificados pelo uso de letras minúsculas.

• Tipos primitivos – São responsáveis apenas pelo armazenamento de valores na


memória e são divididos em:

– Lógico (boolean): responsável pelo armazenamento de um valor lógico, pode


ser usado com os valores: on e off, true e false ou yes e no.

Exemplo: boolean flag = false;

19
– Caractere (char): responsável por armazenar um único caractere ou caracte-
re especial (indicado por iniciar com uma barra invertida).

Exemplos:

char letra = ‘a’;


char novaLinha = ‘\n’;

O tipo char define um caractere simples e o representa na forma da tabela


Unicode com 16-bits. O literal do tipo char pode ser representado com o uso
do (‘A’).

Caractere especial Descrição

‘\n’ Nova linha.

‘\r’ Enter.

Especifica um caractere Unicode, o qual


‘\u????’
é representado na forma hexadecimal.

‘\t’ Tabulação.

‘\\’ Representa um caractere \ (barra invertida).

‘\”’ Representa um caractere “ (aspa).

– Inteiros (byte, short, int e long): responsáveis por armazenar valores inteiros,
cada tipo possui uma limitação de valores, entre os limites inferior e superior,
a fim de permitir economia de espaço de memória no armazenamento de pe-
quenos valores.

Tipo Tamanho Escopo

byte 8 bits -27 . . . . 27 - 1

short 16 bits -215 . . . . 215 - 1

int 32 bits -231 . . . . 231 - 1

long 64 bits -263 . . . . 263 - 1

20
Exemplos:

byte vByte = 127b; // maior valor byte possível, o menor é -128


short vShort = 5000s;
int vInt = 20000;
long vLong = 2000000000;

Obs.: com exceção do int, os demais, ao receberem valores constantes, devem


indicar o tipo do valor, sendo: b ou B para byte, s ou S para short e l ou L para long.

– Reais (float e double): responsáveis por armazenar valores reais na memória.

Tipo Tamanho Descrição

Armazena valor real de simples precisão. Por


possuir uma quantidade menor de bits para ar-
float 32 bits mazenar o valor, não é capaz de guardar com
grande precisão números muito pequenos ou
muito grandes.

Armazena valor real de dupla precisão. Um


double possui maior precisão, ou seja, podemos
double 64 bits armazenar valores muito menores ou muito
maiores do que em um float, mas utilizam maior
espaço de memória para o armazenamento.

Exemplos:

float vFloat = 1.27f;


double vDouble = 5000.050556;

Obs.: o float também precisa de um indicador de tipo quando recebe um valor


constante, que deve indicar seu tipo: f ou F. Isso não é necessário para a atribui-
ção de um valor do tipo double.

A linguagem Java realiza uma conversão de qualquer tipo numérico para double
sempre que um tipo diferente de double é atribuído a uma variável double. Essa
característica é chamada de “coerção” e é empregada na linguagem Java.

21
• Tipo especial – Responsável por armazenar o valor em uma classe, com a possi-
bilidade de uso dos métodos disponibilizados por ela.

– String: o tipo String não é um tipo primitivo, mas especial. O valor é armazena-
do em uma classe, por isso esse tipo é iniciado com letra maiúscula, ao contrá-
rio dos tipos primitivos, que sempre se iniciam por letras minúsculas. Esse tipo
é usado para armazenar uma sequência de caracteres e possui várias ações
(métodos) que podem ser usadas sobre os valores armazenados. Variáveis e
atributos do tipo String também devem ter identificadores iniciados por letras
minúsculas.

Valores constantes

Valores constantes em Java são obtidos com o emprego do modificador final. Qualquer
tipo associado a ele fará com que, ao ser inicializado, o valor não possa mais ser alterado.
A boa prática em programação Java define que constantes devem ser identificadas por
meio do uso de letras maiúsculas.

Exemplos:

final int IDADEMINIMA = 18; // o valor será constante e não poderá


// ser alterado.
final String NOMEPROJETO = “Programação Java”;

Operadores

• Operadores aritméticos:

Operador Descrição

= Atribuição

+ Soma

- Subtração

* Multiplicação

/ Divisão

% Resto da divisão inteira

22
Exemplos:

int a = 7, b = 2, c;// declaração de variáveis


c = a + b;// atribuição de c com a soma inteira de a com b => 9
c = a - b;// atribuição de c com a subtração inteira de a com b => 2
c = a / b;// atribuição de c com a divisão inteira de a por b => 3
c = a * b;// atribuição de c com a multiplicação inteira de a por b => 14
c = a % b;// atribuição de c com o resto da divisão inteira de a por b => 1

Importante

Sempre que os operandos de uma expressão aritmética forem inteiros, a ope-


ração será realizada exclusivamente com os valores inteiros, resultando em um
valor inteiro para a atribuição. Já quando um número inteiro e um número em
ponto flutuante são usados como operandos sem uma única operação aritmé-
tica, o resultado é também um número em ponto flutuante. O número inteiro
é implicitamente convertido em um número em ponto flutuante antes de a ex-
pressão ser avaliada para a realização da operação.

int a = 7; // declaração de variáveis


double b = 2.0, c; // declaração de variáveis
c = a / b; // atribuição de c com a divisão real de a por b => 3,333...

Todo cálculo entre inteiros resulta em um inteiro, mesmo a divisão. Para uma divisão
entre inteiros que se queira a parte fracionária, é necessário converter o tipo, e isso
pode ser feito por meio de cast.

Exemplos:

int x=7, y = 3, z;
z = x / y; // z valerá 2: 7 / 3 => 2 e resto 1.

Podemos, então, usar o cast:

int x=7, y = 3;
float z;
z = (float) x / y;

23
• Operadores de incremento e decremento:

No Java, os operadores são muito similares ao estilo e à funcionalidade de outras


linguagens, por exemplo, as linguagens C/C++.

– Pré-incremento:

x = 10;
x = x + 1; O valor da variável x é 11
ou
x = 10;
++x; O valor da variável x é 11.

– Pós-incremento:

x = 10;
x = x + 1; O valor da variável x é 11
ou
x = 10;
x++; O valor da variável x é 11.

Diferença entre o pré-incremento e o pós-incremento em atribuições:

Exemplo 1:

int y, x = 10;
y = ++x ; => neste momento, a variável x foi primeiramente incremen-
tada e vale 11, já a variável y receberá o valor de x e também valerá 11.

Exemplo 2:

int y, x =10;
y = x++; => neste momento, a variável x será pós-incrementada,
e, sendo assim, a variável y receberá primeiramente o valor de
x e valerá 10; posteriormente, a variável x será incrementada e
passará a valer 11.

24
Pré-decremento e o pós-decremento:

--x; e x--; => Valem as mesmas regras apresentadas para o incremento, mas dimi-
nuem uma unidade respectivamente.

• Operadores relacionais:

Operador Descrição

== Igualdade/comparação

!= Negação

> Maior que

< Menor que

>= Maior ou igual a

<= Menor ou igual a

Exemplos:

if(a > b)
if(a+b >= c)

• Operadores em expressões lógicas

Operador Descrição

! NÃO lógico

&& E lógico

|| OU lógico

Esses operadores seguem as tabelas-verdade das operações lógicas de NÃO (nega-


ção lógica), E (AND) e OU (OR).

Exemplos:

if( a > b && c <= d)


if( ! a < b || c != d && e > f )

25
Precedência na avaliação: !, &&, ||

Assim, o segundo exemplo equivale a, de acordo com a precedência:

if( ( !(a < b) || (c != d && e > f) ) )

• Operadores de bits:

Operador Descrição
& E entre bits

^ OU EXCLUSIVO entre bits

| OU entre bits

Precedência: &, ^, |

Exemplos:

byte a = 45, b = 70, c=0;


c = a & b; // o valor de c será 4

128 64 32 16 8 4 2 1
a= 0 0 1 0 1 1 0 1 = 45
b= 0 1 0 0 0 1 1 0 = 70
c= 0 0 0 0 0 1 0 0 =4

byte a = 45, b = 70, c=0;


c = a ^ b; // o valor de c será 107

128 64 32 16 8 4 2 1
a= 0 0 1 0 1 1 0 1 = 45
b= 0 1 0 0 0 1 1 0 = 70
c= 0 1 1 0 1 0 1 1 = 107

No OU exclusivo, apenas um dos operandos pode ser 1 (um), não os dois.

26
byte a = 45, b = 70, c=0;
c = a | b; // o valor de c será 111

128 64 32 16 8 4 2 1
a= 0 0 1 0 1 1 0 1 = 45
b= 0 1 0 0 0 1 1 0 = 70
c= 0 1 1 0 1 1 1 1 = 111

As operações com bits são muito importantes não apenas para a definição de máscaras
e submáscaras de rede, mas principalmente para as operações relacionadas à criptogra-
fia para a segurança de dados. Nesse contexto, a operação de OU exclusivo é fundamen-
tal para a realização das operações de criptografia.

• Operador condicional (ternário):

O operador ? : é usado em expressões condicionais.

Pode ser usado em expressões aritméticas para tomar uma decisão no momento
do cálculo, para definir um valor de retorno, entre outras aplicações.

Exemplo:

int a=15, b=5, c;


c= b * ((a>=10) ? 20 : 10);// como a é maior do que 10, b será multi-
plicado por 20
System.out.println(“Valor de c= “ + c);// o resultado será 100

• Boa prática em programação Java (BP):

Convenções de codificação na linguagem Java:

• Classe – Nomes de classes podem ser maiúsculos, minúsculos ou misturados (le-


tras maiúsculas e minúsculas), mas, por convenção, o nome de classes deve come-
çar por uma letra maiúscula, e, a cada nova palavra, passa-se a iniciar por maiúscula.
Exemplo: class Aluno { }

27
• Interfaces – Nomes de interfaces seguem o mesmo formato de classes.

Exemplo: interface Atleta { }

• Métodos – Nomes de métodos podem ser verbos, podendo misturar letras


maiúsculas e minúsculas. Entretanto, a primeira letra deve ser minúscula, e, a
cada nova palavra, passa-se a iniciar por maiúscula.

Exemplo: cadastrar( ) { }

• Atributos – Nomes de atributos seguem a regra de identificação de métodos


(iniciar por letras minúsculas), podendo misturar entre maiúsculas e minúsculas,
sendo que a primeira letra deve ser minúscula, e, a cada nova palavra, passa-se
a iniciar por maiúscula.

Exemplo: String nome;

• Variáveis e objetos – Todas as instâncias de classes e variáveis globais su-


portam maiúsculas e minúsculas e devem ser nomeadas tal qual um atributo,
iniciando por letra minúscula.

Exemplo: Carro carro = new Carro();

• Identificadores com mais de uma palavra – Em todos os casos anteriores, as


demais palavras usadas para nomear um identificador devem começar por le-
tras maiúsculas.

Exemplos:
class AlunoGraduacao { }
interface AtletaProfissional { }
double alturaPredio;
setNome () { }

• Constantes – Nomes de constantes podem ser maiúsculos, minúsculos, mis-


turados ou separados com underscore (_). Na boa prática de programação, usa-
mos todas as letras maiúsculas.

28
• Controles de estruturas – Convencionou-se o uso obrigatório de { } (chaves).

• Espaços – Convencionou-se o uso de quatro espaços para indentação.

• Comentários – Use os comentários para explicar os segmentos de código que


não são óbvios.

Veja, a seguir, um exemplo de uso da boa prática de programação.

• Estruturas de controle de fluxo:

– Estruturas condicionais:

- Se (if):

if (condição) {
instruções;
}// A cláusula else é opcional.

- Se / senão (if ... else):

if (condição) {
instruções;
}
else {
instruções;
}

29
- Se / Senão Se / Senão (if ... else if ... else):
A cláusula if ocorre apenas uma vez.
A cláusula else if pode ocorrer nenhuma ou várias vezes.
A cláusula else pode ocorrer apenas uma vez.

if (condição1) {
instruções;
}
else if (condição2) {
instruções;
}
else if (condição3) {
instruções;
}
else {
instruções;
}

- Caso (switch … case):

Estruturas de decisão caracterizadas pela possibilidade de uma variável pos-


suir vários valores.

A cláusula switch ocorre uma vez, e a variável de controle em C/C++ e, Java


pode ser um tipo inteiro ou caractere.

A cláusula case pode ocorrer de uma a várias vezes, e default é opcional.

switch (variável) {
case 1 : instruções;
break;
case 2 : instruções;
break;
case 3 : instruções;
break;
default: instruções para condições não previstas anteriormente;
}

30
switch (variável) // Pode-se simular o uso do OU em um switch:
{
case 2 : numeroDias = 28;
break;
case 4 :
case 6 :
case 9 :
case 11: numeroDias = 30;
break;
case 1 : switch(letra){
case 3 : case ‘a’:
case 5 : case ‘A’: opcao = 1;
case 7 : break;
case 8 : ...
case 10 :
case 12 : numeroDias = 31;
break;
default: System.out.println(“Mês não identificado”);
}

• Estruturas de repetição:

– Para (for):
Estrutura de repetição controlada por uma ou mais variáveis contadoras e ca-
racterizadas pela existência de três parâmetros (opcionais):

1. Valor inicial.
2. Condição para parada das iterações.
3. Quantidade de incrementos/decrementos a cada iteração.

Exemplos:

for(inic (1); cond(2); passo(3))

// Repetição controlada por uma variável:


for (int i=0; i<valor; i++)

31
{
instruções;
}
// Repetição controlada por duas variáveis:
for (x=1, y=2; x*y<valor; x++, y+=2)
{
instruções;
}
// Repetição sem fim
for ( ; ; ) {
instruções; // você pode usar uma condicional if () e a instrução
// break, que encerrará a repetição
}

– Enquanto / Faça (while):


Estrutura de repetição que realiza as operações desejadas enquanto uma de-
terminada condição especificada for verdadeira.

// Teste de condição no início


while (condição) {
instruções;
}

– Faça / Enquanto (do ... while):


Estrutura de repetição semelhante à anterior, com o diferencial de que as con-
dições são verificadas ao final da estrutura, permitindo que as operações es-
pecificadas sejam sempre executadas pelo menos uma vez.

// Teste de condição no final


do
{
instruções;
} while (condição);

32
MIDIATECA

Acesse a midiateca da Unidade 1 e veja o conteúdo Java: introdução, caracte-


rísticas, estrutura e ambientes de programação indicado como material com-
plementar pela professora.

33
Ambientes de desenvolvimento

Existem várias ferramentas para o desenvolvimento de aplicações utilizando a tecnologia


Java, mas as duas principais são o Eclipse e o NetBeans. Você poderá escolher a que
mais lhe for agradável para desenvolver os projetos dos nossos exemplos e exercícios
práticos, mas não será necessário realizar as tarefas em ambos — basta escolher a que
você mais gostar. Outro ponto importante é que as empresas possuem sua preferência,
mas isso não será problema, porque quem está acostumado com uma delas não terá
dificuldades ao utilizar a outra, uma vez que as duas são muito parecidas e realizam as
mesmas tarefas.

JDK

Antes de mais nada, é importante que você instale o JDK.


No endereço disponibilizado na midiateca da Unidade 1, você poderá efetuar
o download da última versão do JDK até o momento e também baixar uma
versão antiga do NetBeans. Mais a seguir, você poderá efetuar o download da
versão mais atual.

Clique sobre o botão “Download” do Oracle JDK versão Java SE 12.0.1 e escolha:
Windows 158.49 MB jdk-12.0.1_windows-x64_bin.exe
Não se esqueça de aceitar o contrato de licença após analisá-lo e de se cadas-
trar na Oracle caso seja necessário.
Depois, basta instalá-lo seguindo as orientações do instalador. Após a instala-
ção, não se esqueça de reiniciar a máquina para que as configurações sejam
atualizadas. Essa versão irá atender tanto ao Eclipse como ao NetBeans.

MIDIATECA

Acesse a midiateca da Unidade 1 e veja como realizar o download do ambiente


JDK, disponibilizado pela Oracle.

34
NetBeans

Para realizar o download do NetBeans, acesse a midiateca da Unidade 1.

Faça a escolha pela versão mais recente e pelo pacote “bin” (neste momento,
é a versão 11.0), que contém os executáveis da ferramenta; o pacote “source”
contém todos os códigos do projeto do NetBeans, que foi feito em Java.

Essa versão não precisa ser instalada — basta descompactar o arquivo, e você
encontrará o executável na pasta “bin” do NetBeans.

Se quiser, você poderá clicar sobre o executável com o botão direito do mouse
e enviar para a área de trabalho para criar um atalho no desktop.

MIDIATECA

Acesse a midiateca da Unidade 1 e veja como realizar o download do NetBeans.

MIDIATECA

Acesse a midiateca da Unidade 1 e veja um tutorial de download do Java e da


IDE NetBeans.

35
Eclipse

Caso prefira, realize o download do Eclipse acessando também a midiateca


da Unidade 1 e siga os procedimentos de instalação. Nas versões anteriores,
bastava apenas descompactar o arquivo, assim como no NetBeans. Caso al-
gum problema de instalação ocorra, será aberta uma janela do navegador com
informações de suporte.

MIDIATECA

Acesse a midiateca da Unidade 1 e veja como realizar o download do Eclipse.

Usaremos o seguinte programa para testar as duas ferramentas, e você decidirá qual
prefere utilizar no desenvolvimento de seus projetos:

import java.util.Scanner;

public class Media {

public static void main(String[] args) {


// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
double media, nota1, nota2, nota3;
double menorNota;
System.out.println(“Digite a nota de A1:”);
nota1 = Double.parseDouble(sc.nextLine());
System.out.println(“Digite a nota de A2:”);
nota2 = Double.parseDouble(sc.nextLine());
System.out.println(“Digite a nota de A3:”);
nota3 = Double.parseDouble(sc.nextLine());
if((nota1 <= nota2) && (nota1 <= nota3)) {
menorNota = nota1;

36
}
else {
if((nota2 <= nota1) && (nota2 <= nota3)) {
menorNota = nota2;
}
else {
menorNota = nota3;
}
}
media = (((nota1 + nota2 + nota3) - menorNota)) /2.0;
System.out.println(“A média das 2 maiores notas é:” + media);
sc.close();
}
}

• Trabalhando com o NetBeans 11:

Tela de abertura do NetBeans 11.

Fonte: The Apache Software Foundation© (2019).

37
Para criar um novo projeto, clique em “File” e, em seguida, “New Project”.

Fonte: The Apache Software Foundation© (2019).

Para a disciplina, sempre use “Java with Ant” e “Java Application”. Clique em “Next”
para continuar.

Fonte: The Apache Software Foundation© (2019).

38
Defina o nome do projeto como “Media”. Clique em “Finish” para terminar e criar o
projeto.

Fonte: The Apache Software Foundation© (2019).

Tela do NetBeans com o projeto criado.

Fonte: The Apache Software Foundation© (2019).

39
Faça a codificação do programa na página de edição.

Fonte: The Apache Software Foundation© (2019).

Para executar esse código, selecione o arquivo da classe na área de projetos e clique
com o botão direito do mouse escolhendo “Run File” para executar o código.

Fonte: The Apache Software Foundation© (2019).

40
O código será executado na área de Output abaixo do código. Todas as áreas po-
dem ser redimensionadas, assim como foi feito no exemplo ao aumentar a área de
Output para analisar a execução.

Fonte: The Apache Software Foundation© (2019).

Sua primeira aplicação Java desenvolvida no NetBeans está pronta!

• Trabalhando com o Eclipse Oxygen 3 (atualizado para março de 2018):

Na tela principal do Eclipse, acesse o “Menu File”, em seguida, a opção “New”, e es-
colha “Java Project”.

Fonte: Eclipse Foundation, Inc.© (2019).

41
Defina o nome do projeto “Media” e clique em “Finish” para criar o projeto.

Fonte: Eclipse Foundation, Inc.© (2019).

Tela do Eclipse com o projeto Media criado.

Fonte: Eclipse Foundation, Inc.© (2019).

42
Crie uma classe Java para realizar a codificação da aplicação. Selecione o projeto e
clique com o botão direito do mouse, selecionando “New” e “Class”.

Fonte: Eclipse Foundation, Inc.© (2019).

Determine o nome da classe (Media), selecione a opção de criação do método “main”


para podermos codificar a aplicação e clique em “Finish” para criar a classe.

Fonte: Eclipse Foundation, Inc.© (2019).

43
Área de codificação da classe pronta para a edição do código.

Fonte: Eclipse Foundation, Inc.© (2019).

Codificação da classe realizada.

Fonte: Eclipse Foundation, Inc.© (2019).

44
Execute o código, selecione a classe e clique com o botão direito do mouse sobre
ela, escolhendo “Run As” e “Java Application”.

Fonte: Eclipse Foundation, Inc.© (2019).

Área de execução do código para a realização de testes do programa. Você pode


redimensionar as diversas áreas de forma a facilitar seu trabalho.

Fonte: Eclipse Foundation, Inc.© (2019).

Pronto! Seu primeiro programa Java desenvolvido no Eclipse está concluído.

45
NA PRÁTICA

Você conheceu as características da tecnologia e da linguagem Java e pode


aplicá-las na prática, para isso escolha uma das ferramentas de desenvolvi-
mento (NetBeans ou Eclipse) e desenvolva um programa para resolver o pro-
blema a seguir. Neste primeiro momento, não se preocupe com os conceitos
de orientação a objetos.

Problema: o cálculo do IMC (índice de massa corporal) é utilizado para detectar


casos de desnutrição ou obesidade. Sua fórmula é bem simples: divide o peso
pela altura elevada ao quadrado.

O programa deverá solicitar ao usuário seu peso e sua altura e retornar o valor
do IMC e em qual situação ele se encontra, de acordo com a tabela a seguir.

IMC Resultado
Menos do que 18,5 Abaixo do peso

Entre 18,5 e 24,9 Peso normal

Entre 25 e 29,9 Sobrepeso

Entre 30 e 34,9 Obesidade grau 1

Entre 35 e 39,9 Obesidade grau 2

Mais do que 40 Obesidade grau 3

46
Resumo da Unidade 1

Nesta unidade, você conheceu a história da linguagem Java e os tipos de aplicações


que pode desenvolver utilizando essa tecnologia. Conheceu, ainda, as características
da tecnologia Java e as estruturas de controle de fluxo condicionais e de repetição.
Você também pôde avaliar duas das ferramentas mais usadas no desenvolvimento de
aplicações baseadas na tecnologia Java, o Eclipse e o NetBeans, para poder escolher
aquela com a qual você se sinta mais à vontade para usar no desenvolvimento de seus
exercícios práticos.

CONCEITO

Histórico da linguagem Java; tipos de dados; operadores; variáveis; constan-


tes; estruturas de controle de fluxo; conversões de tipos; entrada e saída; pla-
taformas de desenvolvimento.

47
Referências

DEITEL, P. Java: como programar. 10. ed. São Paulo: Pearson Education do Brasil, 2017.
Biblioteca Virtual.

SCHILDT, H. Java para iniciantes: crie, compile e execute programas Java rapidamente.
6. ed. Porto Alegre: Bookman, 2015. Minha Biblioteca.

48
UNIDADE 2

Os conceitos básicos da
programação orientada a
objetos utilizando o Java
INTRODUÇÃO

A programação orientada a objetos possui diversos conceitos associados ao


desenvolvimento de sistemas. Alguns desses conceitos são básicos e estão
disponibilizados na maioria das linguagens de programação, mas nem todos os conceitos
de programação orientada a objetos são disponibilizados em todas essas linguagens;
alguns podem não estar presentes ou estar presentes parcialmente. Nesta unidade,
iremos conhecer os principais conceitos da programação orientada a objetos, que fazem
parte dos conceitos básicos para a implementação dessa técnica de desenvolvimento
utilizando o Java.

OBJETIVO

Nesta unidade, você será capaz de:

• Compreender e aplicar os conceitos básicos da programação orientada a ob-


jetos com Java.

50
Classes, objetos, atributos e métodos; mé-
todos de acesso

Classes

As classes na programação orientada a objetos são responsáveis por descrever as


características e as ações que o objeto poderá realizar. Dessa forma, a classe é desenvolvida
como uma biblioteca, uma vez que uma mesma classe pode ser responsável pela criação
de diversos objetos em uma aplicação, assim como pode ser utilizada em várias outras
aplicações diferentes. Essa característica é responsável pelo reaproveitamento de código,
um dos principais benefícios da programação orientada a objetos. É parte da codificação
e da criação de uma classe a ser utilizada em sua biblioteca.

Toda classe representa um tipo, ou seja, assim como temos os tipos básicos (byte, short,
int, long, float, double, char e boolean) e o tipo especial (String), toda classe representa
uma estrutura de dados que pode armazenar um conjunto de características.

Na programação orientada a objetos, temos dois tipos de membros em uma classe, que
são responsáveis por determinar as características e ações dos objetos nas aplicações.
É na aplicação que os objetos são criados e realizam suas ações.

Uma classe possui apenas dois tipos de membros:

oAtributos – Os atributos de uma classe são responsáveis por descrever o objeto quanto
a suas características. Cada objeto deve ser analisado, e apenas as características
importantes ao sistema devem ser levadas em consideração. As características de um
automóvel para um sistema de estacionamento podem se resumir em modelo, cor e placa,
sendo suficientes para representar o automóvel nesse contexto. Já para um sistema mais
abrangente, como o Detran, por exemplo, a codificação do chassi, o fabricante, o número
do Renavam e potência são igualmente importantes. Dessa forma, é necessário analisar
o contexto do projeto de sistema (minimundo) e determinar quais são as características
importantes de cada objeto ao contexto do sistema. Em um sistema acadêmico, por
exemplo, são importantes o nome, matrícula, CR, curso, entre outras características, mas
o time para o qual o aluno torce ou a sua religião não tem importância. Atributos devem,
então, definir um tipo de dado e um identificador para cada característica relevante do
objeto para o sistema.

51
Atributos não devem ser identificados de formas diferentes: uma vez que ocorra uma
definição de projeto sobre o seu identificador, não devemos alterá-lo. A boa prática em
desenvolvimento Java facilitará o desenvolvimento em equipes se todos usarem sempre
o identificador-padrão do projeto. Qualquer mudança atrasará o projeto, e provavelmente
parte dele precisará ser alterada. Se um atributo foi definido como NúmeroPessoas:
inteiro, ele deve ser declarado como o atributo:

int numeroPessoas;

Isso de acordo com a boa prática de desenvolvimento Java (BP).

Exemplo

public class Automovel {


// Atributos
String modelo, cor, placa;
int hora, minuto, dia, mes, ano;
}

Em uma aplicação, podemos então criar diferentes objetos Automovel,


baseados em apenas uma classe:

public class AppAutomovel {


public static void main(String[] args) {
// TODO Auto-generated method stub
Automovel auto1 = new Automovel();
auto1.modelo = “Corsa”;
auto1.cor = “Branca”;
auto1.placa = “RIO1A01”;
auto1.hora = 12;
auto1.minuto = 25;
auto1.dia = 03;
auto1.mes = 06;
auto1.ano = 2019;
Automovel auto2 = new Automovel();
Automovel auto3 = new Automovel();
Automovel auto4 = new Automovel();
Automovel auto5 = new Automovel();

52
auto2.placa = “SAL1A02”;
auto3.placa = “SAO1A03”;
auto4.placa = “VIT1A04”;
auto5.placa = “BEL1A05”;
System.out.println(“Placa do auto1: “ + auto1.placa);
System.out.println(“Placa do auto2: “ + auto2.placa);
System.out.println(“Placa do auto3: “ + auto3.placa);
System.out.println(“Placa do auto4: “ + auto4.placa);
System.out.println(“Placa do auto5: “ + auto5.placa);
}
}

Notas:

1. A classe Automovel foi definida uma única vez, e a aplicação criou cinco
diferentes objetos Automovel.
2. Para cada objeto Automovel criado, foi reservada uma região de memória
para armazenar as suas características (atributos).
3. As características dos diferentes objetos não se misturam, uma vez que a
atribuição de cada característica exige a identificação do objeto; dessa forma,
as atribuições das placas não se misturaram.
4. Exibir todas as características de cada Automovel exigiria uma grande
quantidade de programação na aplicação, com códigos quase repetidos,
alterando apenas o identificador de cada objeto.

o Métodos – Os métodos de uma classe são responsáveis pelas ações que o objeto
pode realizar. Enquanto os atributos se resumem apenas na declaração das suas
características, os métodos possuem um conjunto de instruções que serão executadas
para realizar ações ou funções referentes ao objeto. No caso acima, como temos oito
atributos (características), a impressão de cada atributo de cada objeto poderia demandar
um conjunto de 40 instruções (cinco objetos x oito atributos). Podemos, então, criar dois
métodos: um método capaz de realizar a exibição dos dados do objeto e outro para
realizar a entrada de dados dos atributos do objeto. Esses métodos serão responsáveis
pela entrada de dados para atribuição das características e por exibir todos os atributos
do objeto. Ambos os métodos serão desenvolvidos apenas uma vez e poderão ser
executados por todos os objetos criados em qualquer aplicação. As ações ocorrerão
sempre sobre o objeto que estiver identificado na chamada da ação.

53
Exemplo

import java.util.Scanner;
public class Automovel {
// Atributos
String modelo, cor, placa;
int hora, minuto, dia, mes, ano;
// Métodos
public void entradaDados ( ){
Scanner sc = new Scanner(System.in);
System.out.println(“Digite o Modelo :”);
modelo = sc.nextLine();
System.out.println(“Digite a Cor :”);
cor = sc.nextLine();
System.out.println(“Digite a Placa :”);
placa = sc.nextLine();
System.out.println(“Digite a Hora :”);
hora = Integer.parseInt(sc.nextLine());
System.out.println(“Digite o Minuto :”);
minuto = Integer.parseInt(sc.nextLine());
System.out.println(“Digite o Dia :”);
dia = Integer.parseInt(sc.nextLine());
System.out.println(“Digite o Mês :”);
mes = Integer.parseInt(sc.nextLine());
System.out.println(“Digite o Ano :”);
ano = Integer.parseInt(sc.nextLine());
}
public void imprimir ( ){
System.out.println(“Modelo : “ + modelo);
System.out.println(“Cor : “ + cor);
System.out.println(“Placa : “ + placa);
System.out.println(“Hora : “ + hora);
System.out.println(“Minuto : “ + minuto);
System.out.println(“Dia : “ + dia);
System.out.println(“Mês : “ + mes);
System.out.println(“Ano : “ + ano);
}
}

54
Em uma aplicação, podemos, então, criar diferentes objetos Automovel,
baseados em apenas uma classe:

public class AppAutomovel {


public static void main(String[] args) {
// TODO Auto-generated method stub
// criação dos 5 objetos
Automovel auto1 = new Automovel();
Automovel auto2 = new Automovel();
Automovel auto3 = new Automovel();
Automovel auto4 = new Automovel();
Automovel auto5 = new Automovel();
// entrada de dados dos 5 objetos
auto1.entradaDados();
auto2.entradaDados();
auto3.entradaDados();
auto4.entradaDados();
auto5.entradaDados();
// exibição dos dados dos 5 objetos
auto1.imprimir();
auto2.imprimir();
auto3.imprimir();
auto4.imprimir();
auto5.imprimir();
}
}

Notas:

1. A classe Automovel foi alterada (sofreu uma evolução), e foram criados dois
métodos.
2. Os métodos entradaDados e imprimir passaram a realizar as ações de
atribuições e de exibição dos dados armazenados, respectivamente.
3. Para cada objeto Automovel criado, os métodos são executados, mas a
entrada de dados e a exibição ocorrem separadamente para cada objeto, uma
vez que devemos sempre identificar o objeto que realizará a ação.
4. Os métodos foram reaproveitados por todos os objetos da aplicação, mas
eles também estão disponíveis para qualquer outro objeto em qualquer outra
aplicação que crie objetos da classe Automovel criada.

55
5. O objeto Scanner sc foi definido dentro do método de entrada de dados,
porque ele não representa uma característica do objeto Automovel; esse objeto
é apenas auxiliar para a realização da ação do método.

Um outro ponto importante é a evolução das classes: uma vez que elas são bibliotecas
disponíveis para as aplicações, essas classes podem ser utilizadas em várias aplicações
diferentes. É normal que determinadas aplicações tenham algumas exigências a mais
do que outras; dessa forma, as classes na programação orientada a objetos podem
sofrer evoluções, mas isso não quer dizer que elas passarão a atender a apenas uma
aplicação. Elas devem evoluir mantendo a compatibilidade com as aplicações anteriores.
Essa forma de evolução permite que cada classe criada possa ser utilizada em diversas
aplicações distintas, daí a ideia de biblioteca de classes.

Objetos

Objetos na programação orientada a objetos representam os objetos reais dentro do


sistema de computação. Como nos exemplos anteriores, criamos cinco diferentes
objetos, e cada um tem características diferentes, cada um deles pode representar um
automóvel diferente. Os modelos, cores, placas e demais características são próprios de
cada objeto, por isso eles se assemelham em suas características (atributos comuns),
mas se diferenciam em suas propriedades. Cada objeto possui para cada atributo um
valor diferente, ou seja, para o atributo placa, cada automóvel possui uma propriedade
placa próprio, o que o torna diferente dos demais. Enquanto as classes são criadas e
ficam à disposição das aplicações que irão usar objetos criados a partir delas, os objetos
só existem na memória do computador; eles só existirão quando a aplicação estiver em
execução e representarão objetos do contexto (minimundo) do sistema. Dizemos que os
objetos “só existem em tempo de execução”.

Os objetos realizam interações com o sistema realizando trocas de mensagens. Essas


trocas de mensagens são realizadas pelos métodos, quando são utilizados. A troca de
mensagens é a forma como a programação orientada a objetos realiza suas tarefas.

56
Exemplo

A classe Automovel então faz parte de uma biblioteca de classes criadas


para serem utilizadas em aplicações, que irão criar objetos baseados nessas
classes.

Exemplo:

// Aplicação 1:
public class AppAutomovel {
public static void main(String[] args) {
// TODO Auto-generated method stub
// criação dos 5 objetos
Automovel auto1 = new Automovel();
Automovel auto2 = new Automovel();
Automovel auto3 = new Automovel();
Automovel auto4 = new Automovel();
Automovel auto5 = new Automovel();
}
}
// Aplicação 2:
public class AppAuto {
public static void main(String[] args) {
// TODO Auto-generated method stub
// criação dos 5 objetos
Automovel a1 = new Automovel();
Automovel a2 = new Automovel();
Automovel a3 = new Automovel();
}
}

Notas:

1. Ambas as aplicações criam objetos Automovel da mesma classe.


2. A classe Automovel pode ser usada em diversas aplicações diferentes, sem
a necessidade de que ela seja duplicada.
3. Em ambas as aplicações, os objetos Automovel criados serão capazes de
representar objetos da vida real (contexto do sistema — minimundo).

57
Resumindo:

• Classe: é um conjunto de códigos de programação que definem um modelo para


a criação de um ou mais objetos. É uma estrutura capaz de representar diferentes
objetos, com propriedades distintas, mas com as mesmas características. A classe é
o modelo para a criação dos objetos.
• Objeto: é uma entidade única capaz de reunir propriedades (atributos próprios de
cada objeto) que difiram um objeto do outro. Pode efetuar ações para a realização
de tarefas ao utilizar seus métodos. Os métodos de cada objeto realizam operações
exclusivamente sobre as suas propriedades.
• Atributos: definem um conjunto de descritores do objeto de forma geral e de acordo
com as características necessárias do objeto para o contexto do sistema.
• Métodos: representam as ações que podem ser executadas por cada objeto.

MIDIATECA

Acesse a midiateca da Unidade 2 e veja o conteúdo sobre objetos indicado como


material complementar.

Métodos de acesso

São métodos especiais que são utilizados para evitar acesso direto aos seus atributos.
Uma atribuição direta a um atributo não permite que possamos analisar se o valor a ser
atribuído está de acordo com o realizado.

58
Exemplo

Imagine atribuir um valor –5 para uma idade, ou deixar de definir um nome.


Esses exemplos demonstram demonstram que não há como realizar uma
análise durante uma atribuição direta.

Exemplos:

auto1.hora = -3;
auto1.placa = “AAA”;
auto1.modelo = “”;

Notas:

1. Foi determinada uma hora inválida.


2. A placa não está completa.
3. O modelo não foi definido.

Nesses casos, as atribuições ocorreram sem que nenhum tipo de teste pudesse ser
realizado a fim de evitar essas atribuições incorretas. Outro ponto importante que será
visto mais adiante é o conceito de encapsulamento, em que os atributos deverão estar
protegidos para que não possam ser acessados indiscriminadamente pelas aplicações.
Esse conceito é responsável por proteger os atributos de um objeto, dando mais segurança
para que eles não sejam alterados diretamente pela aplicação.

o Métodos setters

São métodos especiais responsáveis por realizar a atribuição e o armazenamento na


memória de uma propriedade do objeto. Esses métodos recebem como parâmetro o
valor a ser atribuído e realizam uma análise para identificar se o valor é válido. De acordo
com a boa prática em programação Java, esses métodos se iniciam pela palavra set,
seguida pelo nome do atributo com letra inicial maiúscula, uma vez que será a segunda
palavra do identificador.

59
Devem realizar
Possuem sempre
Devem ser públicos a atribuição do
um parâmetro do
(public), para que São sempre do tipo conteúdo do
mesmo tipo do
possam ser usados void, porque nunca parâmetro da
atributo que
em qualquer retornam nada. propriedade
realizará a
aplicação. correspondente
atribuição.
do objeto.

Exemplo

Exemplos:

public void setModelo(String m) {


modelo = m;
}
public void setCor(String c) {
cor = c;
}
public void setPlaca(String p) {
placa = p;
}
public void setHora(int h) {
hora = h;
}
public void setMinuto(int m) {
minuto = m;
}
public void setDia(int d) {
dia = d;
}
public void setMes(int m) {
mes = m;
}
public void setAno(int a) {
ano = a;
}

60
Notas:

1. Para cada atributo, foi criado um método setter.


2. Todos os métodos são públicos (public).
3. Todos os métodos são do tipo void, uma vez que não realizam retorno de
dados.
4. Os parâmetros são do mesmo tipo do atributo.
5. Realizam a atribuição do valor do parâmetro da propriedade do objeto.
6. Os identificadores dos parâmetros puderam ser usados em diferentes
métodos, mesmo sendo de diferentes tipos, porque eles somente são válidos
dentro de seus respectivos métodos.

Você ainda pode incluir testes para analisar se os valores estão de acordo com o esperado:

Exemplo

public void setModelo(String m) {


if(!m.isEmpty()) {
modelo = m;
}
else {
System.out.println(“valor inválido, não foi atribuído”);
}
}
public void setPlaca(String p) {
if(p.length()!=7) {
placa = p;
}
else {
System.out.println(“valor inválido, não foi atribuído”);
}
}
public void setHora(int h) {
if (h >= 0 && h <= 24){
hora = h;
}

61
else {
System.out.println(“valor inválido, não foi atribuído”);
}
}

Notas:

1. O modelo só será atribuído se o texto passado como parâmetro não estiver


vazio.
2. A placa só será atribuída se o texto passado como parâmetro tiver exatamente
sete caracteres.
3. A hora só será atribuída se o valor da hora passado como parâmetro estiver
entre 0 e 24.

o Métodos getters

São métodos especiais responsáveis por recuperar valores atribuídos às propriedades


e que se encontram armazenados na memória de um objeto. Esses métodos nunca
recebem parâmetro, uma vez que apenas devem retornar o valor atribuído à propriedade.
De acordo com a boa prática em programação Java, esses métodos se iniciam pela
palavra get, seguida pelo nome do atributo com letra inicial maiúscula, uma vez que será
a segunda palavra do identificador.

Nunca são do
Devem ser Devem apenas
tipo void, porque
públicos (public) Não possuem realizar o
sempre retornam
para que possam parâmetros, retorno do valor
um valor, devendo
ser usados porque não armazenado na
ser do mesmo
em qualquer recebem valores. propriedade do
tipo do atributo
aplicação. objeto.
que irá retornar.

62
Exemplo

Exemplos:

public String getModelo() {


return modelo;
}
public String getCor() {
return cor;
}
public String getPlaca() {
return placa;
}
public int getHora() {
return hora;
}
public int getMinuto() {
return minuto;
}
public int getDia() {
return dia;
}
public int getMes() {
return mes;
}
public int getAno() {
return ano;
}

Notas:

1. Para cada atributo, foi criado um método getter.


2. Todos os métodos são públicos.
3. Nenhum método é do tipo void, devendo ser definidos com o mesmo tipo do
atributo que irá realizar o retorno.
4. Não recebem parâmetros.
5. Realizam o retorno do valor da propriedade do objeto armazenado na
memória.

63
o Atualização da classe (evolução)

A classe Automovel foi atualizada, mas a aplicação usada anteriormente não precisará
ser alterada, uma vez que a classe permanece compatível com as aplicações anteriores.

De forma a melhorar a classe e utilizar os métodos de acesso criados, a nova versão da


classe (evolução) irá utilizar os métodos setters e getters nos métodos de entrada de
dados e de exibição.

Exemplo

Classe Automovel atualizada:

import java.util.Scanner;
public class Automovel {
// Atributos
String modelo, cor, placa;
int hora, minuto, dia, mes, ano;
// Métodos de acesso
public String getModelo() {
return modelo;
}
public void setModelo(String m) {
if(!m.isEmpty() ) {
modelo = m;
}
else {
System.out.println(“valor inválido, não foi atribuído”);
}
}
public String getCor() {
return cor;
}
public void setCor(String c) {
cor = c;
}
public String getPlaca() {
return placa;
}

64
public void setPlaca(String p) {
if(p.length()==7) {
placa = p;
}
else {
System.out.println(“valor inválido, não foi atribuído”);
}
}
public int getHora() {
return hora;
}
public void setHora(int h) {
if (h >= 0 && h <=24){
hora = h;
}
else {
System.out.println(“valor inválido, não foi atribuído”);
}
}
public int getMinuto() {
return minuto;
}
public void setMinuto(int m) {
minuto = m;
}
public int getDia() {
return dia;
}
public void setDia(int d) {
dia = d;
}
public int getMes() {
return mes;
}
public void setMes(int m) {
mes = m;
}
public int getAno() {
return ano;
}

65
public void setAno(int a) {
ano = a;
}
// demais métodos
public void entradaDados ( ){
Scanner sc = new Scanner(System.in);
System.out.println(“Digite o Modelo :”);
setModelo(sc.nextLine());
System.out.println(“Digite a Cor :”);
setCor(sc.nextLine());
System.out.println(“Digite a Placa :”);
setPlaca(sc.nextLine());
System.out.println(“Digite a Hora :”);
setHora(Integer.parseInt(sc.nextLine()));
System.out.println(“Digite o Minuto :”);
setMinuto(Integer.parseInt(sc.nextLine()));
System.out.println(“Digite o Dia :”);
setDia(Integer.parseInt(sc.nextLine()));
System.out.println(“Digite o Mês :”);
setMes(Integer.parseInt(sc.nextLine()));
System.out.println(“Digite o Ano :”);
setAno(Integer.parseInt(sc.nextLine()));
}
public void imprimir ( ){
System.out.println(“Modelo : “ + getModelo());
System.out.println(“Cor : “ + getCor());
System.out.println(“Placa : “ + getPlaca());
System.out.println(“Hora : “ + getHora());
System.out.println(“Minuto : “ + getMinuto());
System.out.println(“Dia : “ + getDia());
System.out.println(“Mês : “ + getMes());
System.out.println(“Ano : “ + getAno());
}
}

Notas:

1. A classe Automovel ganhou novos métodos, mas as aplicações usadas como


exemplos em nosso estudo continuam compatíveis com a classe, apesar de
sua evolução.

66
2. Não existe ordem para os métodos e atributos de uma classe; apenas por
convenção, devemos definir os atributos no início, para facilitar a identificação.
3. Apenas por uma questão de organização, os métodos de acesso foram
colocados no início, mas alguns desenvolvedores ainda os separam em um
grupo para os setters e outro para os getters.
4. Os métodos entradaDados e imprimir foram alterados e passaram a utilizar
os métodos de acesso, e não mais o acesso direto aos atributos da classe.

Você ainda poderá melhorar os métodos setters que estão sem os testes de verificação
de dados para entender melhor como realizar
essa tarefa.

67
Polimorfismo de sobrecarga de operadores
e de métodos

Polimorfismo

O polimorfismo vem do grego e quer dizer “muitas formas”. Na programação orientada a


objetos, o polimorfismo permite que tenhamos diferentes formas de realizar uma tarefa.
Isso é importante quando precisamos que uma classe atenda a diferentes aplicações,
mas que em algum momento realizam a mesma operação de formas diferentes.

Conforme definido por Deitel:

[…] com o polimorfismo, podemos projetar e implementar sistemas que


são facilmente extensíveis — novas classes podem ser adicionadas com
pouca ou nenhuma modificação a partes gerais do programa, contanto
que as novas classes façam parte da hierarquia de herança que o
programa processa genericamente. (DEITEL, 2017, p. 312)

• Polimorfismo de sobrecarga de operadores

A sobrecarga de operadores é um conceito que ocorre quando utilizamos um mesmo


operador para realizar diferentes tarefas em uma mesma linguagem. A análise sintática
realizada pela linguagem é que irá definir qual ação deverá ser executada em cada
momento, para um mesmo operador.

68
Exemplo

Podemos analisar o operador + (soma), que será analisado sintaticamente de


acordo com o contexto em que o operador está empregado. Vamos analisar a
situação a seguir:

public static void main(String[] args) {


// TODO code application logic here
int x=12;
System.out.println(“Resultado: “ + (5.0 + (3 + 6) + ++ x));
}

“Resultado: “ + (5.0 + (3 + 6) + ++ x)

Ações:

• Uso do operador +: realizará uma operação de concatenação entre o texto a


ser exibido (“Resultado:”) e o valor resultante da expressão aritmética: (7.0
+ (2 + 5) + ++x).
• Uso do operador +: realizará uma operação de soma inteira, uma vez que
os operandos são valores inteiros: (3 + 6) 9 // “Resultado: “ + (5.0 + (9) +
++ x).
• Uso do operador +: realizará uma operação de soma real, uma vez que um
dos operandos tem valor real: 5.0 + (9) 14.0 // “Resultado: “ + (14.0 + ++ x).
• Uso do operador ++: realizará a operação de pré-incremento sobre a variável
x: ++x x = 13
// “Resultado: “ + (14.0 + 13).
• Uso do operador +: realizará uma operação de soma real, uma vez que um
dos operandos tem valor real: 14.0 + (13) 27.0 // “Resultado: “ + (27.0).

Após a execução, será exibido:

Resultado: 27.0

69
Importante

Podemos observar que o mesmo operador foi usado de muitas formas


diferentes, sendo a linguagem responsável por realizar a análise sintática e
identificar a ação correta a ser realizada entre as diferentes formas possíveis.

Polimorfismo de sobrecarga de métodos

A sobrecarga de métodos é obtida ao se criar mais de um método com o mesmo nome


em uma mesma classe; para isso, é importante que esses métodos possuam diferentes
assinaturas de métodos. As assinaturas dos métodos estão ligadas aos parâmetros re-
cebidos pelos métodos; assim, dois ou mais métodos podem ser sobrecarregados em
uma mesma classe, desde que não possuam a mesma assinatura.

A assinatura do método leva em conta apenas os tipos de dados e sua ordem, não levan-
do em consideração os identificadores dos parâmetros.

O método definido como int meuMetodo( int a, double b, String c ) possui como assi-
natura: int meuMetodo( int, double, String ).

Repare que apenas os tipos e a ordem dos tipos na área de parâmetros são levados em
consideração.

Dessa forma, os métodos a seguir não atendem ao critério de sobrecarga, porque pos-
suem a mesma assinatura:

public void setX(String a ) public void setX(String b )


{ {
x = a; x = b;
} }
Assinatura: setX( String ) Assinatura: setX( String )

70
Importante

Como os métodos possuem o mesmo nome e a mesma assinatura, eles não


podem ficar na mesma classe.

Exemplos de polimorfismo de sobrecarga de métodos

Você pode sobrecarregar o método setModelo, por exemplo:

O método setModelo recebe um parâmetro com o modelo do automóvel e o armazena


no atributo:

public void setModelo( String m )


{
modelo = m;
}

O método setNome não recebe parâmetros e serve para limpar (eliminar) o valor armaze-
nado no atributo modelo:

public void setModelo( )


{
modelo = “”;
}

As assinaturas dos dois métodos são diferentes e, por isso, podem existir na mesma
classe.

• void setNome( String )


• void setNome ( )

71
A linguagem Java resolve esse problema durante a execução da aplicação. O método
correto será executado em função de uma avaliação que será realizada na sintaxe da
chamada do método. Vamos analisar o seguinte exemplo:

No primeiro caso, a chamada ao


método será avaliada de acordo com
a sua assinatura, uma vez que existe
mais de um método com o mesmo
public class AppAutomovel { nome. Como temos um método que
public static void main(String[] args) { possui uma assinatura recebendo
// TODO Auto-generated method stub um String, essa chamada executará o
// criação dos 5 objetos método:
Automovel auto1 = new Automovel();
auto1.setModelo(“Uno”); auto1.setModelo(“Uno”);
auto1.setModelo();
} No segundo caso, a chamada ao mé-
} todo não possui parâmetros, e isso
fará com que o método sem parâme-
tros seja executado:

auto1.setModelo();

Nota:

Dessa forma, não importa quantos métodos com o mesmo nome existam em uma
mesma classe. Quando isso ocorre, a chamada ao método que está sendo realizada
irá avaliar e transferir a execução para o método sobrecarregado que possuir a mesma
assinatura da chamada.

72
Exemplo

Exemplos de polimorfismo de sobrecarga de métodos com a mesma


quantidade de parâmetros, mas com tipos diferentes:

public double calcQuadrado(double n) { public double calcQuadrado(int n) {


return n * n; return (double) n * n;
} }
Assinatura: calcQuadrado( double ) Assinatura: calcQuadrado( int )

Métodos de mesmo nome em uma mesma classe (sobrecarga) podem receber diferen-
tes mensagens (assinaturas) e responder à chamada de diferentes formas.

Exemplo

Os exemplos a seguir podem pertencer à mesma classe, uma vez que, apesar
de todos terem a mesma quantidade de parâmetros, as suas assinaturas são
diferentes:

Métodos sobrecarregados: Chamada na aplicação:


int meuMetodo(int a, double b, String c) obj.meuMetodo(10, 2.5, “texto”);
{}
obj.meuMetodo(2.5, “texto”, 10);
int meuMetodo(double b, String c, int a)
{} obj.meuMetodo(“texto”, 10, 2.5);

int meuMetodo(String c, int a, double b) obj.meuMetodo(“texto”, 2.5, 10);
{}

int meuMetodo(String c, double b, int a)


{}

73
O uso do polimorfismo de sobrecarga de métodos está associado à evolução das clas-
ses. Imagine que você tem uma classe de acesso aos sistemas, com identificação do
usuário, e esse método possui a seguinte assinatura:

public void nivelAcesso ( String nome, String senha ){ }

Vários sistemas já em funcionamento usam esse método para realizar o login dos usuá-
rios, mas um novo cliente precisa que, além do nome de login e da senha, seja verificado
um código gerado por um token. Você não precisa criar uma nova classe, basta evoluir
essa classe implementando uma nova forma de acesso:

public void nivelAcesso ( String nome, String senha, int token ){ }

Importante

A classe agora pode atender o seu novo cliente e ainda se mantém compatível
com as aplicações dos antigos clientes.

MIDIATECA

Acesse a midiateca da Unidade 2 e veja a aplicação do conceito de polimorfismo,


por meio de um estudo de caso, indicado como material complementar.

74
Métodos construtores e sobrecarga de mé-
todos construtores

Métodos construtores

São usados para controlar a criação (instanciação) do objeto e só executam nesse


momento. Após a criação do objeto, esses métodos não podem mais ser usados. São
responsáveis pelo controle durante a construção do objeto na memória. Podem ser
usados para definir valores para os atributos e/ou tarefas que devam ser realizados para
que o objeto seja criado com algumas características.

São sempre públicos (public).

Não podem retornar valores, por isso são sem tipo.

Devem obrigatoriamente possuir o mesmo nome da classe e


podem receber valores como parâmetros para a realização de
atribuição(ões) inicial(is) das propriedades do objeto.

Executam apenas durante o processo de criação do objeto (ins-


tanciação da classe), não podendo ser executados novamente
para o objeto já criado.

75
Exemplo

Exemplo:

public Automovel(String mo, String co, String pl, int ho,


int mi, int di, int me, int an) {
setModelo(mo);
setCor(co);
setPlaca(pl);
setHora(ho);
setMinuto(mi);
setDia(di);
setMes(me);
setAno(an);
}

Uso:

Automovel a1 = new Automovel( “Uno”, “Verde”, “RIO1A00”, 10, 23, 23, 06, 2019 );

O uso desse método permite que possamos criar um objeto automóvel já com todos os
valores atribuídos; isso é importante quando estamos trabalhando com bases de dados.
Como o objeto a1 já recebeu os valores para serem atribuídos às suas propriedades, o
objeto não precisará da entrada de dados ou outra forma de atribuição.

Por outro lado, as aplicações anteriores não irão mais funcionar com a classe Automovel.
Isso ocorre porque a forma antiga de instanciação deixou de ser válida.

Automovel a1 = new Automovel( );

Quando em Java criamos uma classe sem a definição de um método construtor, o


processo de compilação disponibiliza um método construtor vazio: Automovel a1 = new
Automovel( );

Porém, quando criamos algum método construtor, isso não acontece. Passa a ser uma
questão de segurança: como o método construtor controla a criação do objeto, só podem
ser criados objetos utilizando construtores existentes na classe.

76
Importante

Essa é uma medida de segurança, uma vez que não será permitido que sejam
criados objetos de qualquer forma, apenas obedecendo aos construtores
disponíveis.

Para assegurarmos que a classe Automovel se manterá compatível com as aplicações


anteriores, devemos recorrer ao polimorfismo de sobrecarga de métodos em nossos
métodos construtores.

Sobrecarga de métodos construtores

Métodos construtores podem ser sobrecarregados e seguem a mesma regra da


sobrecarga de métodos: os parâmetros são verificados não de acordo com o identificador,
mas sim pela sequência dos tipos (assinatura).

Para mantermos a compatibilidade de nosso Automovel com a inclusão do método


construtor que recebe todos os valores para atribuição nas propriedades do objeto,
devemos criar também um construtor vazio sobrecarregando os métodos construtores:

public Automovel() {
}

public Automovel(String mo, String co, String pl, int ho,


public int mi, int di, int me, int an) {
setModelo(mo);
setCor(co);
setPlaca(pl);
setHora(ho);
setMinuto(mi);
setDia(di);
setMes(me);
setAno(an);
}

77
A instanciação ou criação de um objeto segue a seguinte sintaxe:

Classe objeto = new Construtor(); Lembre-se de que o método construtor


Automovel auto2 = new Automovel(); possui o mesmo nome da classe.

Podemos, então, evoluir a classe Automovel incluindo alguns métodos construtores, mas
lembre-se de que não poderá haver métodos com o mesmo nome, construtores ou não,
e com a mesma assinatura.

Incluir na classe Automovel:

// métodos construtores
public Automovel() { } // construtor vazio para a classe
public Automovel( String pl) { // só a placa
setPlaca(pl);
}
public Automovel( String pl, int ho, int mi) { // poucos atributos
setPlaca(pl);
setHora(ho);
setMinuto(mi);
}
public Automovel(String pl, int ho, int mi, int di, int me, int an) {// alguns atributos
setPlaca(pl);
setHora(ho);
setMinuto(mi);
setDia(di);
setMes(me);
setAno(an);
}
public Automovel(String mo, String co, String pl, int ho,
int mi, int di, int me, int an) { // todos os atributos
setModelo(mo);
setCor(co);
setPlaca(pl);
setHora(ho);
setMinuto(mi);

78
setDia(di);
setMes(me);
setAno(an);
}

Importante

Lembre-se de alterar a aplicação AppAutomovel e criar alguns objetos utilizando


os novos construtores disponibilizados. Dizemos que os objetos estão sendo
criados com diferentes métodos construtores.

MIDIATECA

Acesse a midiateca da Unidade 2 e veja o conteúdo sobre construtores indicado


como material complementar.

79
NA PRÁTICA

A programação orientada a objetos procura trazer para o ambiente computa-


cional objetos existentes no mundo real. Ao analisar os conceitos aqui com-
preendidos, observamos que qualquer objeto do mundo real pode ter a sua
representação computacional, mas devemos ficar atentos às características
importantes para o contexto do sistema. Vamos analisar um objeto a nossa
volta e pensar em quais seriam as características importantes dele para um
sistema computacional. Vamos, então, analisar o mouse. Suas características
para um determinado sistema poderiam ser: marca (texto), modelo (texto), cor
(texto), peso (real), número de botões (inteiro) e tipo de conexão (texto), poden-
do ser bluetooth, wireless ou fio. Agora é sua vez de analisar outros objetos e
determinar as suas características para um sistema computacional.

80
Resumo da Unidade 2

Nesta unidade, você conheceu os conceitos de classe e objeto e aprendeu a diferenciá-


los. Você também aprendeu que uma classe é composta de membros e que os
membros de uma classe são os atributos e os métodos. Além disso, também aprendeu
as características de cada um dos membros de uma classe. Abordamos o conceito de
polimorfismo e como ele pode ser aplicado a operadores e métodos na programação
orientada a objetos. Por final, conhecemos os métodos construtores e suas características,
além de compreendermos que, por se tratar de métodos, eles também podem ser
sobrecarregados.

CONCEITO

Nesta unidade, conhecemos os conceitos de classes e objetos e suas carac-


terísticas. Vimos que uma classe é composta somente de atributos e méto-
dos, que são responsáveis, respectivamente, pela descrição do objeto e pelas
ações (tarefas) que o objeto pode executar. Conhecemos também o conceito
de polimorfismo aplicado à sobrecarga de operadores e à sobrecarga de mé-
todos. Entendemos como ocorre a sobrecarga de operadores e aprendemos
a utilizar na prática a sobrecarga de métodos. Ainda exploramos o conceito
de métodos construtores, suas características e como utilizá-los na prática.

81
Referências

DEITEL, P. Java: como programar. 10. ed. São Paulo: Pearson Education do Brasil, 2017.
p. 312. Biblioteca Virtual.

MANZANO, J. A. N. G.; COSTA JUNIOR, R. A. Java 7: programação de computadores:


guia prático de introdução, orientação e desenvolvimento. São Paulo: Érica, 2011. Minha
Biblioteca.

SCHILDT, H. Java para iniciantes: crie, compile e execute programas Java rapidamente.
6. ed. Porto Alegre: Bookman, 2015. Minha Biblioteca.

82
UNIDADE 3

Os conceitos avançados da
programação orientada a
objetos utilizando o Java
INTRODUÇÃO

Um dos principais conceitos da programação orientada a objetos é a herança. Por meio


dela, podemos diminuir a quantidade de código escrito, facilitando a manutenção do sis-
tema e proporcionando o reaproveitamento de boa parte da codificação desenvolvida.
Ainda em relação aos principais conceitos de orientação a objetos, temos o encapsula-
mento, que permite a proteção dos membros de uma classe de forma a limitar a visibili-
dade a esses membros, a fim de protegê-los ou ocultar a sua forma de implementação.
Já as classes abstratas e as interfaces propiciam que possamos incluir regras às clas-
ses, permitindo que as chamadas “regras de negócio” sejam obrigatoriamente imple-
mentadas pelas classes que herdarem de uma classe abstrata ou implementarem uma
interface.

OBJETIVO

Nesta unidade, você será capaz de:

• Compreender e aplicar os conceitos avançados da programação orientada a


objetos com Java.

84
A herança de classes, o reaproveitamento
de membros das classes e o polimorfismo
de sobrescrita

A herança está relacionada às hierarquias e às relações entre os objetos. Ela é o meca-


nismo em que uma subclasse (ou classe-filha) compartilha automaticamente todos os
membros (métodos e atributos) que são herdados de sua superclasse (ou classe-pai).

A herança permite implementar classes descendentes de outra classe, permitindo a im-


plementação de novos atributos e métodos que estendem uma superclasse e especiali-
zam a subclasse. As superclasses são capazes de conter membros comuns a diversas
classes e que seriam redundantes em todas essas classes. Dessa forma, como os mem-
bros da superclasse são compartilhados, todas as subclasses herdarão automaticamen-
te todo o conteúdo compartilhado entre essas classes, a fim de evitar a redundância de
códigos, facilitando o desenvolvimento e a manutenção do sistema.

Com a herança, também podemos substituir métodos da superclasse que não sejam
específicos da subclasse por um novo método mais pertinente ou substituir o método da
superclasse por um método que aproveite o método da superclasse, estendendo-o com
a inclusão de mais ações. Esse conceito é conhecido como polimorfismo de sobrescrita
e só ocorre em situação de herança de classes e com a substituição do método original
da superclasse por um método com a mesma assinatura na subclasse.

Deitel destaca que:

[…] com a herança você economiza tempo durante o desenvolvimento


de programas baseando novas classes existentes em software testado,
depurado e de alta qualidade. Isso também aumenta a probabilidade de
que um sistema seja implementado e mantido efetivamente. (DEITEL,
2017)

Na herança, trabalhamos ainda com os conceitos de generalização (superclasses) e de


especialização (subclasses).

85
Generalização Especialização

É o mecanismo por meio do qual o ser huma-


no constata que alguns conceitos obtidos a
partir de objetos dentro de uma parcela do É o inverso da generalização, em que as pro-
mundo real (minimundo ou domínio do pro- priedades e características se diferem dos
blema) possuem algumas propriedades ou demais objetos semelhantes, determinando
características comuns e cria um conceito características e/ou propriedades específicas
mais abrangente sintetizando essas carac- do objeto.
terísticas ou propriedades comuns a dois ou
mais objetos.

Na programação orientada a objetos, existem dois tipos de herança:

Herança simples Herança múltipla

Quando uma subclasse herda os membros de Quando uma subclasse herda os membros de
uma única superclasse por vez. mais de uma superclasse ao mesmo tempo.

Importante

O Java oferece apenas a herança simples entre classes. A herança múltipla em


Java só ocorre em interfaces, que são tipos especiais de classes e serão vistas
ainda nesta unidade.

Exemplos de herança simples:

Superclasse de B

Subclasse de A

B
A classe B herda da classe A.

86
Superclasse de B

A
Subclasse de A

B
Superclasse de C

Subclasse de B

C
A classe C herda da classe B, e a classe B herda da classe A.

Superclasse de B e C

Subclasse de A Subclasse de A

B C
As classes B e C herdam da classe A.

Superclasse de B e C

Subclasse de A
Subclasse de A
C
B Superclasse de D e E

Subclasse de C Subclasse de C

D E
A classe B herda da classe A, as classes D e E herdam da classe C, e a classe C herda da classe A.

87
Exemplos de herança múltipla:

Superclasse de C Superclasse de C

A B

Subclasse de A e B

C
A classe C herda ao mesmo tempo das classes A e B.

Superclasse de D Superclasse de D e E Superclasse de E

A B C

Subclasse de A e B Subclasse de B e C

D E
A classe D herda ao mesmo tempo das classes A e B, e a classe
E herda ao mesmo tempo das classes B e C.

Uma classe, para estender outra (se tornar uma subclasse), deve usar o modificador ex-
tends, que a tornará uma subclasse da classe estendida.

Exemplos:

1 -
public class A { // ... } // Classe A: Superclasse de B
public class B extends A { // ... } // Classe B: Subclasse de A

2 -
public class A { // ... } // Classe A: Superclasse de B
public class B extends A { // ... } // Classe B: Subclasse de A – Superclasse de C
public class C extends B { // ... } // Classe C: Subclasse de B

88
3 -
public class A { // ... } // Classe A: Superclasse
public class B extends A { // ... } // Classe B: Subclasse de A
public class C extends A { // ... } // Classe C: Subclasse de A

4 -
public class A { // ... } // Classe A: Superclasse de B e de C
public class B extends A { // ... } // Classe B: Subclasse de A
public class C extends A { // ... } // Classe C: Subclasse de A e Superclasse de D e E
public class D extends C { // ... } // Classe D: Subclasse de C

public class E extends C { // ... } // Classe E: Subclasse de C

Existem ainda várias outras estruturas de herança que podem ser implementa-
das, mas sempre respeitando a herança simples em Java.

Como na linguagem Java não temos a implementação da herança múltipla, não serão
apresentados exemplos práticos de herança múltipla.

A linguagem C++ é um exemplo de linguagem de programação que implementa a he-


rança múltipla, bastando para isso incluir, após o operador de herança, a sequência de
classes da herança múltipla separadas por vírgulas.

Polimorfismo de sobrescrita

Ocorre em uma relação de herança em que classes hierarquicamente relacionadas pos-


suem métodos com o mesmo nome e a mesma assinatura, sobrescrevendo na sub-
classe (filha) o método original da sua superclasse.

89
Pode ocorrer quando a funcionalidade apresentada na superclasse não atende ao requi-
sito da especialista da subclasse:

Exemplo

public class SuperClasse {


String nome;
public void imprimir(){ // Sobrescrita do método da superclasse
System.out.println(“Nome: “ + nome);
}
}

O método imprimir da superclasse será sobrescrito na subclasse:

public class SubClasse extends SuperClasse {


String sexo;
public void imprimir(){ // Sobrescrita do método da superclasse
System.out.println(“Nome: “ + nome + “ Sexo: “ + sexo);
}
}

A subclasse sobrescreveu o método da superclasse, apresentando uma funcio-


nalidade diferente da funcionalidade do método da superclasse.

Em algumas ocasiões, podemos realizar uma extensão do método da super-


classe. Essa técnica permite aproveitar o código já pronto da superclasse, incluin-
do apenas as ações que complementam a funcionalidade da subclasse. Nesse
caso, reaproveitamos o método pronto da superclasse e incluímos apenas a
complementação.

O exemplo anterior é um bom exemplo, dado que apenas desejamos incluir a exibição do
sexo, uma vez que o nome já é exibido pelo método na superclasse.

90
Exemplo

Exemplo de sobrescrita com reaproveitamento do método da superclasse:

public class SuperClasse {


String nome;
public void imprimir(){
System.out.println(“Nome: “ + nome);
}
}

A sobrescrita agora fará um reaproveitamento da funcionalidade do método da


superclasse, realizando uma extensão do método da superclasse ao chamá-lo
para execução dentro do método da subclasse:

public class SubClasse extends SuperClasse {


String sexo;
public void imprimir(){ // Sobrescrita do método da superclasse
super.imprimir(); // Reaproveitamento do método da superclasse
System.out.print(“ Sexo: “ + sexo);
}
}

Ao incluir dentro do método da subclasse a chamada ao método da superclasse


com o uso do super.imprimir(), o método da superclasse será executado antes
das novas ações incluídas no método imprimir da subclasse.

Exemplo

Exemplo prático:

Para aplicar corretamente o conceito de herança, primeiro é necessário identi-


ficar duas ou mais classes que possuam características semelhantes. Em um
sistema acadêmico, por exemplo, temos três atores igualmente importantes e
que possuem algumas similaridades. Alunos, professores e funcionários são

91
fundamentais no sistema e possuem algumas características semelhantes.
Vamos analisar as classes a seguir com alguns atributos determinados para o
sistema após um projeto de análise:

Tabela de classes e atributos do problema proposto

Classes Atributos

Matrícula : texto
Nome : texto
Celular : texto
Aluno
Idade : inteiro
CódigoCurso : inteiro
CR : real

Matrícula : texto
Nome : texto
Celular : texto
Professor Idade : inteiro
CódigoCarreira : inteiro
Salário : real
Titulação : texto

Matrícula : texto
Nome : texto
Celular : texto
Funcionario Idade : inteiro
CódigoCarreira : inteiro
Salário : real
Função : texto

Após a análise dos atributos, constatamos que os atributos a seguir são co-
muns às três classes:

• Matrícula : texto
• Nome : texto
• Celular : texto
• Idade : inteiro

92
Também podemos constatar que os atributos a seguir são comuns às classes
professor e funcionário:

• CódigoCarreira : inteiro
• Salário : real

Agora podemos estruturar a hierarquia das classes, organizando-as entre su-


perclasses e subclasses. A figura a seguir representa hierarquicamente as clas-
ses e faz a distribuição dos atributos de forma que os atributos compartilhados
(comuns às classes) possam ser relacionados às classes adequadas.

Lembre-se de não utilizar símbolos e acentuação nos nomes dos identifica-


dores. Utilize acentuação apenas em conteúdos de textos: “Função”.

• Matrícula : texto
• Nome : texto
Pessoa
• Celular : texto
• Idade : inteiro

• CódigoCarreira : inteiro
Colaborador
• Salário : real

Aluno Professor Funcionario

• CódigoCurso : inteiro • Titulação : texto • Função : texto


• CR : real

Ao aplicar o conceito de herança, teremos a superclasse Pessoa para atender


às necessidades comuns das classes Aluno, Professor e Funcionario. Como
Professor e Funcionario possuem ainda dois atributos em comum, vamos criar
a classe intermediária Colaborador, que será subclasse de Pessoa e superclas-
se das classes Professor e Funcionario.

93
Exemplo

Agora vamos criar o projeto herança no IDE escolhido (NetBeans ou Eclipse) com as
classes determinadas e uma classe de teste (aplicação). Para este exemplo prático,
vamos implementar pelo menos cinco métodos construtores, os métodos de aces-
so (setters e getters), além dos métodos de entrada de dados (entrada), de exibição
dos dados do objeto (imprimir) e do método de cadastro (cadastrar), que deve rece-
ber todos os dados do objeto e realizar as atribuições.

Solução do problema exposto (devemos começar pelas classes de maior hierar-


quia):

Classe: Pessoa (superclasse de Aluno e de Colaborador)

import java.util.Scanner;

public class Pessoa {


// Atributos
String matricula, nome, celular;
int idade;
public String getMatricula() {
return matricula;
}
public void setMatricula(String mat) {
if(!mat.isEmpty()) {
matricula = mat;
}
}
public String getNome() {
return nome;
}
public void setNome(String no) {
if(!no.isEmpty()) {
nome = no;
}
}
public String getCelular() {
return celular;
}
public void setCelular(String cel) {

94
if(!cel.isEmpty()) {
celular = cel;
}
}
public int getIdade() {
return idade;
}
public void setIdade(int ida) {
if(ida>=0) {
idade = ida;
}
}
public Pessoa() { }
public Pessoa(String nome, int idade) {
setNome(nome);
setIdade(idade);
}
public Pessoa(String matricula, String nome) {
setMatricula(matricula);
setNome(nome);
}
public Pessoa(String matricula, String nome, int idade) {
setMatricula(matricula);
setNome(nome);
setIdade(idade);
}
public Pessoa(String matricula, String nome, String celular) {
setMatricula(matricula);
setNome(nome);
setCelular(celular);
}
public Pessoa(String matricula, String nome, String celular, int idade) {
setMatricula(matricula);
setNome(nome);
setCelular(celular);
setIdade(idade);
}
public void cadastrar(String matricula, String nome, String celular,int idade){
setMatricula(matricula);
setNome(nome);
setCelular(celular);
setIdade(idade);
}

public void imprimir() {

95
System.out.println(“Matrícula :” + getMatricula());
System.out.println(“Nome :” + getNome());
System.out.println(“Celular :” + getCelular());
System.out.println(“Idade :” + getIdade());
}
public void entrada() {
// Como o Scanner não é um atributo da classe,
// ele deve ser declarado dentro do método em que será utilizado,
// como um objeto auxiliar
Scanner ent = new Scanner(System.in);
System.out.println(“Matrícula :”);
setMatricula(ent.nextLine());
System.out.println(“Nome :”);
setNome(ent.nextLine());
System.out.println(“Celular :”);
setCelular(ent.nextLine());
System.out.println(“Idade :”);
setIdade(Integer.parseInt(ent.nextLine()));
}
}

Classe: Colaborador (superclasse de Professor e de Funcionario)

import java.util.Scanner;

public class Colaborador extends Pessoa{


// Atributos
int codigoCarreira;
double salario;
public int getCodigoCarreira() {
return codigoCarreira;
}
public void setCodigoCarreira(int cc) {
if(cc>=0) {
codigoCarreira = cc;
}
}
public double getSalario() {
return salario;
}
public void setSalario(double sal) {
if(sal>=0) {

96
salario = sal;
}
}
public Colaborador() {
super();
}
public Colaborador(String matricula, String nome) {
super(matricula, nome);
}
public Colaborador(String nome,int idade) {
super(nome, idade);
}
public Colaborador(String nome, int idade, double salario) {
super(nome, idade);
setSalario(salario);
}
public Colaborador(String matricula, String nome, int codigoCarreira,
double salario) {
super(matricula, nome);
setCodigoCarreira(codigoCarreira);
setSalario(salario);
}
public Colaborador(String matricula, String nome, String celular, int idade) {
super(matricula, nome, celular, idade);
}
public Colaborador(String matricula, String nome, String celular,int idade, int
codigoCarreira, double salario) {
super(matricula, nome, celular, idade);
setCodigoCarreira(codigoCarreira);
setSalario(salario);
}
public void cadastrar(String matricula, String nome, String celular, int idade,
int codigoCarreira, double salario) {
// Reaproveitamento do método cadastrar da superclasse.
super.cadastrar(matricula, nome, celular, idade);
setCodigoCarreira(codigoCarreira);
setSalario(salario);
}
public void imprimir() {
// Reaproveitamento do método imprimir da superclasse.
super.imprimir();
System.out.println(“Código Carreira:” + getCodigoCarreira());
System.out.println(“Salário :” + getSalario());
}

97
public void entrada() {
// Como o Scanner não é um atributo da classe,
// ele deve ser declarado dentro do método em que será utilizado,
// como um objeto auxiliar
Scanner ent = new Scanner(System.in);
// Reaproveitamento do método entrada da superclasse.
super.entrada();
System.out.println(“Código Carreira:”);
setCodigoCarreira(Integer.parseInt(ent.nextLine()));
System.out.println(“Salário :”);
setSalario(Double.parseDouble(ent.nextLine()));
}
}

Classe: Aluno (subclasse de Pessoa)

import java.util.Scanner;

public class Aluno extends Pessoa{


int codigoCurso;
double cr;
public int getCodigoCurso() {
return codigoCurso;
}
public void setCodigoCurso(int cc) {
if(cc>=0) {
codigoCurso = cc;
}
}
public double getCr() {
return cr;
}
public void setCr(double cra) {
if(cra>=0) {
cr = cra;
}
}
public Aluno() { }
public Aluno(String matricula, String nome) {
super(matricula, nome);
}
public Aluno(String nome, int idade) {
super(nome, idade);
}

98
public Aluno(String matricula, String nome, int codigoCurso, double cr) {
super(matricula, nome);
setCodigoCurso(codigoCurso);
setCr(cr);
}
public Aluno(String matricula, String nome, int idade, int codigoCurso, double cr) {
super(matricula, nome, idade);
setCodigoCurso(codigoCurso);
setCr(cr);
}
public Aluno(String matricula, String nome, String celular, int idade,
int codigoCurso, double cr) {
super(matricula, nome, celular, idade);
setCodigoCurso(codigoCurso);
setCr(cr);
}
public void cadastrar(String matricula, String nome, String celular, int idade,
int codigoCurso, double cr) {
// Reaproveitamento do método cadastrar da superclasse.
super.cadastrar(matricula, nome, celular, idade);
setCodigoCurso(codigoCurso);
setCr(cr);
}
public void imprimir() {
// Reaproveitamento do método imprimir da superclasse.
super.imprimir();
System.out.println(“Código Curso :” + getCodigoCurso());
System.out.println(“CR :” + getCr());
}
public void entrada() {
// Como o Scanner não é um atributo da classe,
// ele deve ser declarado dentro do método em que será utilizado,
// como um objeto auxiliar
Scanner ent = new Scanner(System.in);
// Reaproveitamento do método entrada da superclasse.
super.entrada();
System.out.println(“Código Curso :”);
setCodigoCurso(Integer.parseInt(ent.nextLine()));
System.out.println(“CR :”);
setCr(Double.parseDouble(ent.nextLine()));
}
}

99
Classe: Professor (subclasse de Colaborador)

import java.util.Scanner;

public class Professor extends Colaborador {


String titulacao;

public String getTitulacao() {


return titulacao;
}
public void setTitulacao(String tit) {
if(!tit.isEmpty()) {
titulacao = tit;
}
}
public Professor() {
super();
}
public Professor(String nome, int idade, double salario) {
super(nome, idade, salario);
}
public Professor(String nome, int idade, String titulacao) {
super(nome, idade);
setTitulacao(titulacao);
}
public Professor(String matricula, String nome, int codigoCarreira, double salario,
String titulacao) {
super(matricula, nome, codigoCarreira, salario);
setTitulacao(titulacao);
}
public Professor(String matricula, String nome, String celular, int idade,
int codigoCarreira, double salario, String titulacao) {
super(matricula, nome, celular, idade, codigoCarreira, salario);
setTitulacao(titulacao);
}
public Professor(String matricula, String nome, String celular, int idade,
String titulacao) {
super(matricula, nome, celular, idade);
setTitulacao(titulacao);
}
public Professor(String matricula, String nome, String titulacao) {
super(matricula, nome);
setTitulacao(titulacao);

100
}
public void cadastrar(String matricula, String nome, String celular, int idade,
int codigoCarreira, double salario, String titulacao) {
super.cadastrar(matricula, nome, celular, idade, codigoCarreira,
salario);
setTitulacao(titulacao);
}
public void imprimir() {
// Reaproveitamento do método imprimir da superclasse.
super.imprimir();
System.out.println(“Titulação :” + getTitulacao());
}
public void entrada() {
// Como o Scanner não é um atributo da classe,
// ele deve ser declarado dentro do método em que será utilizado,
// como um objeto auxiliar
Scanner ent = new Scanner(System.in);
// Reaproveitamento do método entrada da superclasse.
super.entrada();
System.out.println(“Titulação :”);
setTitulacao(ent.nextLine());
}
}
Classe: Funcionario (subclasse de Colaborador)

import java.util.Scanner;

public class Funcionario extends Colaborador {


String funcao;
public String getFuncao() {
return funcao;
}
public void setFuncao(String fun) {
if(!fun.isEmpty()) {
funcao = fun;
}
}
public Funcionario() {
super();
}
public Funcionario(String nome, int idade, double salario, String funcao) {
super(nome, idade, salario);
setFuncao(funcao);
}

101
public Funcionario(String nome, int idade) {
super(nome, idade);
}
public Funcionario(String matricula, String nome, int codigoCarreira,
double salario, String funcao) {
super(matricula, nome, codigoCarreira, salario);
setFuncao(funcao);
}
public Funcionario(String matricula, String nome, String celular, int idade,
int codigoCarreira, double salario, String funcao) {
super(matricula, nome, celular, idade, codigoCarreira, salario);
setFuncao(funcao);
}
public Funcionario(String matricula, String nome, String celular, int idade) {
super(matricula, nome, celular, idade);
}
public Funcionario(String matricula, String nome, String funcao) {
super(matricula, nome);
setFuncao(funcao);
}
public void cadastrar(String matricula, String nome, String celular, int idade,
int codigoCarreira, double salario, String funcao) {
super.cadastrar(matricula, nome, celular, idade);
setFuncao(funcao);
}
public void imprimir() {
// Reaproveitamento do método imprimir da superclasse.
super.imprimir();
System.out.println(“Função :” + getFuncao());
}
public void entrada() {
// Como o Scanner não é um atributo da classe,
// ele deve ser declarado dentro do método em que será utilizado,
// como um objeto auxiliar
Scanner ent = new Scanner(System.in);
// Reaproveitamento do método entrada da superclasse.
super.entrada();
System.out.println(“Função :”);
setFuncao(ent.nextLine());
}
}

102
Classe: AppHeranca (aplicação para os testes)

public class AppHeranca {


public static void main(String[] args) {
System.out.println(“---------- Aluno -----------------------------------”);
Aluno al1 = new Aluno();
al1.entrada();
al1.imprimir();
System.out.println(“---------- Aluno -----------------------------------”);
Aluno al2 = new Aluno(“1001”, “João”, “99900-3232”, 23, 12, 6.76);
al2.imprimir();
System.out.println(“---------- Professor -------------------------------”);
Professor pf1 = new Professor();
pf1.entrada();
pf1.imprimir();
System.out.println(“---------- Professor -------------------------------”);
Professor pf2 = new Professor(“101001”, “Moacir”, “99900-2122”, 43, 5, 3000,
“Mestre”);
pf2.imprimir();
System.out.println(“----------Funcionário------------------------------”);
Funcionario fc1 = new Funcionario();
fc1.entrada();
fc1.imprimir();
System.out.println(“---------- funcionário -----------------------------”);
Funcionario fc2 = new Funcionario(“101033”, “Maria”, “99900-2222”, 33, 32, 6000,
“Chefe Administração”);
fc2.imprimir();
}
}

Notas:

1. Analisando a codificação da superclasse Pessoa, sem a herança todo o seu códi-


go deveria ser repetido nas classes Aluno, Professor e Funcionario.
2. O mesmo ocorre com a classe Colaborador, que teria todo o seu código repetido
nas classes Professor e Funcionario.
3. Com isso, temos uma economia de instruções na construção das classes apli-
cando o conceito de herança.
4. Outro ponto importante está relacionado à manutenção. Caso seja necessária a
inclusão de algum atributo, basta incluí-lo apenas uma vez. Se for comum às três
classes (Aluno, Professor e Funcionario), basta incluí-lo na superclasse Pessoa. A

103
atualização da classe Pessoa fará com que os métodos de entrada, imprimir, ca-
dastrar, setters, getters e construtores sejam atualizados no reaproveitamento e na
herança pelas subclasses. Caso seja um atributo comum somente a Professor e
Funcionario, basta atualizar a classe Colaborador. Se a inclusão for específica a al-
guma das três classes originais (Aluno, Professor e Funcionario), basta realizar a
atualização na classe específica.
5. Perceba que foi realizada um sobrescrita nos métodos imprimir e entrada. Isso
permite que não tenhamos códigos duplicados e façamos o reaproveitamento do
método da superclasse, que, se for alterado, fará com que a subclasse seja atuali-
zada automaticamente.
O recurso de reaproveitamento de código foi empregado no exemplo anterior nos
métodos construtores que chamaram para execução da superclasse [super()] e nos
métodos cadastrar( .. ), imprimir() e entrada(), respectivamente com super.cadas-
trar( .. ), super.imprimir() e super.entrada(). Já os métodos imprimir() e entrada() fo-
ram sobrescritos na subclasse, uma vez que possuem o mesmo nome e a mesma
assinatura dos respectivos métodos na superclasse.

O reaproveitamento de código faz com que tenhamos sistemas mais enxu-


tos e com maior facilidade de manutenção, mas lembre-se de que é necessá-
rio que tenhamos classes com alguma similaridade para aproveitarmos melhor
esse recurso.

MIDIATECA

Acesse a midiateca da Unidade 3 e veja o conteúdo complementar indicado


pela professora sobre como criar na prática um projeto simples com o uso do
conceito de herança em Java.

104
MIDIATECA

Acesse a midiateca da Unidade 3 e veja o conteúdo complementar indicado


pela professora sobre os conceitos de herança e polimorfismo de sobrescrita.

105
Encapsulamento de métodos e atributos e a
organização de classes em pacotes

Encapsulamento

Encapsulamento é o ato de esconder os membros (atributos e métodos) de uma clas-


se: seja por não serem de interesse por questões de implementação ou por segurança
dos dados atribuídos ao objeto.

O objeto deve se comportar como uma caixa-preta, que realiza determinadas funciona-
lidades, mas que um desenvolvedor que for utilizar a classe em alguma aplicação não
sabe e não precisa saber exatamente como ocorre.

O encapsulamento separa os chamados membros visíveis (com acesso) de um objeto


dos chamados membros invisíveis (sem acesso) da classe.

Em Java, a visibilidade padrão de classes, atributos e métodos está restrita a


todos os membros que fazem parte do mesmo pacote.

Um pacote é o conjunto de classes que se encontram em um mesmo diretório, e esse


conjunto de classes forma, assim, uma biblioteca.

Os modificadores de acesso (encapsulamento) são: public, omissão (vazio), private e


protected.

106
Tipos de visibilidade de membros de uma classe:

Omissão
public protected private
(package ou padrão)

Os métodos e
A classe é definida
atributos são
A classe, método como classe de
A classe, método acessíveis pelos
ou atributo é sem- suporte, já que
ou atributo é aces- membros da pró-
pre acessível a to- seus métodos
sível somente por pria classe e pelas
dos os métodos de e atributos são
métodos das clas- suas subclasses
quaisquer outras acessíveis somen-
ses que pertencem (herança), sendo
classes. É o nível te por membros da
ao mesmo pacote também acessíveis
menos rígido de própria classe. É o
(package). por outras classes
encapsulamento. nível mais rígido de
que estejam no
encapsulamento.
mesmo pacote.

public

• A palavra-chave public altera essa visibilidade de forma a ampliá-la, deixando-a sem restrições.

• Uma classe definida como pública pode ser utilizada por qualquer aplicação ou classe em
qualquer pacote. Em Java, uma unidade de compilação (um arquivo-fonte com extensão
.java) pode ter no máximo uma classe pública, cujo nome deve ser o mesmo do arquivo (sem
a extensão). As demais classes na unidade de compilação, não públicas, são consideradas
classes de suporte para a classe pública e têm a visibilidade padrão (pacote).

• Um atributo public de uma classe pode ser diretamente acessado e manipulado por apli-
cações e objetos de outras classes, sem nenhum tipo de restrição. O conjunto de atributos
públicos é visível e de acesso irrestrito.

• Um método public de uma classe pode ser usado por qualquer aplicação e objetos de qual-
quer classe. O conjunto de métodos públicos de uma classe determina o que pode ser feito
com objetos da classe, ou seja, determina o seu comportamento, suas ações.

107
Padrão / Omissão

• Package (“pacote”): no desenvolvimento de pequenas atividades ou aplicações, é viável man-


ter o código e suas classes no diretório corrente.

• Para grandes aplicações e desenvolvimento de diferentes projetos, é preciso organizar suas


classes em pacotes, de maneira a:

– 1. Evitar problemas com nomes duplicados de classes.

– 2. Localizar o código da classe de forma eficiente.

• Ao separarmos nossas classes em diferentes pacotes, podemos manter o mesmo nome em


mais de uma classe, desde que elas estejam em diferentes pacotes.

• Para maior segurança nos dados de um sistema, devemos separar a classe da aplicação das
demais classes.

• Para criar pacotes em seu projeto, clique sobre o projeto com o botão direito do mouse e
escolha New > Package:

Fonte: © Eclipse (2019).

108
• Nomes de pacotes podem começar por letras minúsculas:

Fonte: © Eclipse (2019).

• Para exemplificar, foram criados dois pacotes: aplicacao e biblioteca.


• Para criar suas classes no pacote correto, clique com o botão direito sobre o pacote
determinado e escolha New > Class.

Fonte: © Eclipse (2019).

109
protected

A palavra-chave protected restringe a visibilidade do membro modificado, método ou atributo ex-


clusivamente a membros da própria classe e de sua(s) subclasse(s), além de outras classes que
estejam no mesmo pacote.

private

A palavra-chave private restringe a visibilidade do membro modificado, método ou atributo exclusi-


vamente a membros da própria classe.

Utilizando a referência this

Quando um método de uma classe faz referência a outro membro dessa classe para um
objeto específico dessa classe, como o Java assegura que o objeto adequado recebe
referência?

A resposta é que cada objeto tem acesso a uma referência a ele próprio — chamado
de referência this.

Utiliza-se a referência this implicitamente para fazer referências aos membros de uma
classe:

– Atributos ou variáveis de instância.


– Métodos do próprio objeto.

Exemplo

String nome;
public void setNome(String nome) {
this.nome = nome;
}

String nome; – Indica um atributo da classe identificado por nome.


setNome(String nome) – Indica um parâmetro identificado por nome.

110
O uso do this permite que:

this.nome = nome;

this.nome – Faça referência ao atributo nome: nome.


nome – Faça referência ao parâmetro nome: nome.

Importante

Por questões de segurança dos dados dos objetos em uma aplicação, sempre
separe a sua aplicação em um pacote diferente das demais classes, que podem
ser separadas umas das outras em função de suas aplicabilidades.

Exemplo prático de uso do encapsulamento:

É comum assegurarmos que os atributos não tenham acesso direto pela apli-
cação, como uma questão de segurança. Também é comum que tenhamos
alguns métodos ocultos (sem visibilidade) por questões de implementação.

Exemplo

O exemplo a seguir apresenta uma forma comum de proteger os dados de um


objeto, além de usar alguns métodos de segurança não disponibilizados para
a aplicação:

Classe: SuperClasse (pacote: biblioteca)

package biblioteca;

public class SuperClasse {


protected String nome;
protected int idade;

111
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = verificarNome(nome);
}
public int getIdade() {
return idade;
}
public void setIdade(int idade) {
this.idade = verificarIdade(idade);
}
protected String verificarNome(String nome) {
if(!nome.isEmpty()) {
return nome;
}
else {
return “”;
}
}
protected int verificarIdade(int idade) {
if(idade >=0) {
return idade;
}
else {
return 0;
}
}
}

Classe: SubClasse (pacote: biblioteca)

package biblioteca;

public class SubClasse extends SuperClasse {


private double peso;
public double getPeso() {
return peso;
}
public void setPeso(double peso) {
this.peso = verificarPeso(peso);
}
private double verificarPeso(double peso) {
if(peso >=0) {

112
return peso;
}
else {
return 0.0;
}
}
}

Notas:

1. Os membros protegidos da superclasse foram definidos como protected


para que a subclasse tivesse visibilidade para acesso.
2. Os membros protegidos da subclasse foram definidos como private, uma
vez que não haverá uma nova subclasse com visibilidade de acesso.

Na aplicação, é necessário importar as classes que serão utilizadas, se elas se


encontrarem em pacotes diferentes.

Situação 1 – Tentativas de acessar um atributo protegido da classe SuperClas-


se ou da classe SubClasse serão impedidas pelo compilador. A aplicação não
compila.

package aplicacao;

import biblioteca.SuperClasse;
import biblioteca.SubClasse;

public class AppEncapsulamento {


public static void main (String[] args){
SuperClasse sp = new SuperClasse();

sp.nome = “Maria”;
}
}

Situação 2 – Tentativas de acessar um método protegido da classe SuperClas-


se ou da classe SubClasse serão impedidas pelo compilador. A aplicação não
compila.

package aplicacao;

import biblioteca.SuperClasse;

113
import biblioteca.SubClasse;

public class AppEncapsulamento {


public static void main (String[] args){
SuperClasse sp = new SuperClasse();

sp.verificarNome(“Maria”);
}
}

Situação 3 – Uso dos métodos de acesso (públicos) para realizar as atribuições


e para recuperar os valores do objeto.

package aplicacao;

import biblioteca.SuperClasse;
import biblioteca.SubClasse;

public class AppEncapsulamento {


public static void main (String[] args){
SubClasse sb = new SubClasse();
sb.setNome(“Maria”);
sb.setIdade(35);
sb.setPeso(65.5);
System.out.println(“Nome: “ + sb.getNome() + “ Idade
: “ + sb.getIdade() + “ Peso : “ + sb.getPeso() );
}
}

Execução:

Nome: Maria
Idade: 35
Peso: 65.5

Todos os membros protegidos (sem visibilidade) não são apresentados pelo


IDE ao identificarmos o objeto. Apenas membros visíveis são apresentados.

Para o objeto sb definido na aplicação, serão exibidos pelo IDE apenas os métodos:

• setNome()
• setIdade();

114
• setPeso();
• getNome();
• getIdade();
• getPeso();

Os atributos e demais métodos protegidos não estarão disponibilizados por


não serem visíveis pela aplicação.

MIDIATECA

Acesse a midiateca da Unidade 3 e veja o conteúdo complementar indicado


pela professora sobre como proteger os atributos de uma classe e como criar
os métodos de acesso (setters e getters) para realizar a atribuição e recuperar
o valor atribuído, respectivamente.

MIDIATECA

Acesse a midiateca da Unidade 3 e veja o conteúdo complementar indicado


pela professora sobre encapsulamento.

115
Os conceitos de classes abstratas e interfaces

Modificadores static e final

Modificador static

Atributo Método

Um método estático só pode acessar mem-


bros (atributos e métodos) estáticos de sua
classe. Já um método não estático pode
Um atributo é dito estático quando é compar-
acessar tanto membros estáticos quanto
tilhado por todas as instâncias da classe, ou
membros não estáticos.
seja, seu conteúdo é compartilhado por todos
os objetos criados.
Métodos definidos como estáticos podem ser
usados sem a necessidade de instanciação
Já em um atributo não estático, cada objeto
da classe.
possui seu próprio valor (propriedade) para o
atributo (não compartilhado).
Exemplo:

Exemplo:
public class MinhaClasse{
public static double meioPI( ) {
public static int idadeMinima = 15;
return Math.PI / 2;
}
Em todas as instâncias da classe, o atributo
}
idadeMinima terá o mesmo valor; caso ele
seja alterado, o novo valor será o mesmo para
Só é necessário importar a classe MinhaClas-
todos os objetos criados.
se e utilizar esse método sem criar o objeto
(instanciar): em qualquer aplicação que im-
porte esta classe: MinhaClasse.meioPI();.

Modificador final

Atributo Método Classe

A declaração de uma classe


Um atributo é dito final
final implicitamente declara
quando o seu valor, após ser É padrão que todos os mé-
todos os métodos da classe
inicializado, não pode mais todos que não sejam estáti-
como final. Isso impede que
ser alterado durante a exe- cos possam ser redefinidos
a classe seja estendida, de-
cução da aplicação; o seu (sobrescritos) em suas sub-
sativando, assim, a herança
valor será CONSTANTE. classes.
para a criação de subclas-
ses dessa classe.

116
Para que não seja permitido
que um método seja redefi-
nido por uma ou mais de
suas subclasses, o progra-
Um atributo final pode ser mador da superclasse pre-
declarado e não ter seu valor cisa impedir explicitamente
inicializado imediatamente, que as subclasses o rede-
mas, após a sua primeira atri- finam e, portanto, alterem
Isso pode restringir muito o
buição, esse valor não poderá o comportamento de um
projeto, então é comum de-
mais ser alterado. método.
clarar apenas um ou poucos
métodos como final. Isso
Exemplo: Exemplo:
permite que a classe ainda
possa ser redefinida, pos-
public final int IDADEMINIMA = 15; public class MinhaClasse{
sibilitando a sobrescrita de
public final double
qualquer método não final.
Para cada instância da classe, meioPI( ) {
o atributo IDADEMINIMA, ao return Math.PI /2;
ser inicializado, não poderá ter }
o seu valor alterado. }

O método meioPI() não po-


derá ser sobrescrito em
sua(s) subclasse(s).

Usar final é uma forma eficaz para restringir a redefinição de alguns métodos de suas
classes, aumentando a segurança da aplicação quando necessário.

Modificadores static e final combinados

Atributo Método

Um atributo é dito estático e final quando o


seu valor é compartilhado por todas as ins-
tâncias classe, e, após ser inicializado, o seu
Um método é dito estático e final quando não
valor não poderá mais ser alterado durante a
pode ser sobrescrito e pode ser usado sem a
execução da aplicação.
necessidade de criação de um objeto.

Exemplo:
Exemplo:

public static final IDADEMINIMA = 15;


public static final void método ( ... ){ }

Para todas as instâncias da classe, o valor


do atributo IDADEMINIMA será o mesmo e,
ao ser inicializado, não poderá ter o seu valor
alterado.

117
Classes abstratas

São classes usadas como superclasses e, por não serem completas para representar
um objeto, não devem ser instanciadas, isso em função da caracterização de pelo menos
um método abstrato na classe:

• Pode ocorrer que, ao escrever um método para uma classe, você não saiba como
ele vai ser implementado. Nesse caso, a implementação será feita pela classe que
herdar o método (a classe-filha).
• Pode ocorrer também que você saiba que um determinado método será sobrescri-
to com certeza na classe-filha; então, por que definir sua implementação se ele não
será usado a partir da superclasse?
• Esse método é apenas declarado (definição), mas não implementado (codificado).
Esse conceito determina que é obrigatório que esse método seja implementado na
classe-filha.
• Esse conceito fornece uma regra de obrigatoriedade (regras de negócios) para a
implementação de métodos concretos nas classes-filhas (descendentes).
• Em alguns casos, é comum que não sejam criados objetos a partir da superclasse,
mas ela será responsável por descrever membros (atributos e métodos) que serão
usados por diversas subclasses. A classe Humano, por exemplo, determina uma
série de características similares entre homens e mulheres, mas na prática a aplica-
ção irá criar objetos da classe Homem e da classe Mulher, mas não serão criados
objetos da classe Humano.

ATENÇÃO:
Atributos não podem ser declarados como abstratos, apenas métodos.

• Essas superclasses somente têm utilidade quando utilizadas em situações de he-


ranças, uma vez que não poderemos criar objetos “completos” diretamente a partir
delas, mas, em algumas situações especiais, estes ainda poderão ser instanciados.
• Nos métodos abstratos, você apenas define a assinatura dos métodos e deixa a
implementação (codificação) por conta da(s) subclasse(s) que irá(ão) herdar.
• Essas classes são, então, chamadas de classes abstratas, e o método que você
não implementou é chamado de método abstrato. Para que uma classe seja abstra-
ta, ela precisa ter pelo menos um método abstrato.
• Uma classe abstrata não pode ser instanciada por meio da palavra-chave new, a
não ser em situações especiais. As classes que permitem a instanciação de objetos

118
são chamadas de classes concretas.
• Apresentam o modificador abstract.
• Apresentam apenas a assinatura, seguida de “;”.
• Não possuem corpo.

Exemplo:

public abstract class Humano


{
public double idade;
public abstract void amamentar();
}

Uma classe abstrata serve para modelar objetos que possuam características seme-
lhantes, mas, ainda assim, tenham comportamento distinto para ações semelhantes.

Exemplo

Exemplo prático:

Classe: Humano (pacote: biblioteca)

package biblioteca;

public abstract class Humano {


protected String nome, sexo;
protected int idade;
protected double peso, altura;
public void setNome(String nome) {
this.nome = nome;
}
public void setSexo(String sexo) {
this.sexo = sexo;
}
public void setIdade(int idade) {
this.idade = idade;
}
public void setPeso(double peso) {
this.peso = peso;
}
public void setAltura(double altura) {
this.altura = altura;

119
}
public String getNome() {
return this.nome;
}
public String getSexo() {
return this.sexo;
}
public int getIdade() {
return this.idade;
}
public double getPeso() {
return this.peso;
}
public double getAltura() {
return this.altura;
}
public abstract String amamentar();
}

Classe: Homem (pacote: biblioteca)

package biblioteca;

public class Homem extends Humano {


private boolean barba, bigode;
private double peitoral;
public Homem() {
this.sexo = “Masculino”;
}
public void setBarba(boolean barba) {
this.barba = barba;
}
public void setBigode(boolean bigode) {
this.bigode = bigode;
}
public void setPeitoral(double peitoral) {
this.peitoral = peitoral;
}
public boolean getBarba() {
return this.barba;
}
public boolean getBigode() {
return this.bigode;
}

120
public double getPeitoral() {
return this.peitoral;
}
public String amamentar() {
return “Homens usam mamadeiras”;
}
}

Classe: Mulher (pacote: biblioteca)

package biblioteca;

public class Mulher extends Humano{


private boolean gravidez;
private double busto, cintura;
public Mulher() {
this.sexo = “Feminino”;
}
public void setGravidez(boolean gravidez) {
this.gravidez = gravidez;
}
public void setBusto(double busto) {
this.busto = busto;
}
public void setCintura(double cintura) {
this.cintura = cintura;
}
public boolean getGravidez() {
return gravidez;
}
public double getBusto() {
return busto;
}
public double getCintura() {
return cintura;
}
public String amamentar() {
return “Mulheres usam os seios”;
}
}

121
Classe: Manjar-principal (pacote: aplicacao)

package aplicacao;

import biblioteca.*; // Importa todas as classes do pacote

public class HumanoPrincipal {


public static void main(String[] args) {
// Humano h1 = new Humano(); --> Humano is abstract; cannot be instantiated
Homem h1 = new Homem();
h1.setSexo(“Masculino”);
h1.setNome(“Joao”);
h1.setIdade(23);
h1.setPeso(65.4);
h1.setAltura(1.76);
h1.setBigode(true);
h1.setBarba(false);
h1.setPeitoral(.96);
System.out.println(“Nome: “ + h1.getNome() + “ Sexo: “ + h1.getSexo()
+ “ Idade: “ + h1.getIdade() + “ Peso: “
+ h1.getPeso() + “ Altura: “ + h1.getAltura()
+ “ Bigode: “ + h1.getBigode() + “ Barba: “
+ h1.getBarba() + “ Peitoral: “ + h1.getPeitoral()
+ “ Amamentar: “ + h1.amamentar());

Mulher m1 = new Mulher();
m1.setSexo(“Feminino”);
m1.setNome(“Maria”);
m1.setIdade(21);
m1.setPeso(58.4);
m1.setAltura(1.67);
m1.setGravidez(false);
m1.setBusto(.80);
m1.setCintura(.70);
System.out.println(“Nome: “ + m1.getNome() + “ Sexo: “ + m1.getSexo()
+ “ Idade: “ + m1.getIdade() + “ Peso: “
+ m1.getPeso() + “ Altura: “ + m1.getAltura()
+ “ Gravidez: “ + m1.getGravidez() + “ Busto: “
+ m1.getBusto() + “ Cintura: “ + m1.getCintura()
+ “ Amamentar: “ + m1.amamentar());
}
}

122
Classes abstratas podem ser instanciadas em situações especiais:
se for usado um construtor de uma subclasse, desde que esta contenha a implementa-
ção dos métodos abstratos definidos nela.

Exemplo

public class ClassesAbstratas {


public static void main(String[] args) {
Homem h1 = new Homem();
Mulher m1 = new Mulher();
Humano hu1 = new Homem();
Humano hu2 = new Mulher();
System.out.println(“Homem:” + h1.amamentar());
System.out.println(“Mulher:” + m1.amamentar());
System.out.println(“Humano(H):” + hu1.amamentar());
System.out.println(“Humano(M):” + hu2.amamentar());
}
}

Execução:

Homem: Homens usam mamadeiras // objeto homem


Mulher: Mulheres usam os seios // objeto mulher
Humano(H): Homens usam mamadeiras // objeto humano com construtor Homem
Humano(M): Mulheres usam os seios // objeto humano com construtor Mulher

Interfaces

Uma interface Java é uma classe abstrata em que todos os seus métodos são abstract
e public e seus atributos são static e final implicitamente.

Uma interface é, então, uma classe completamente abstrata ou classe


abstrata pura.

123
Exemplo

public interface NomeInterface {


int IDADEMINIMA = 15; // static e final -> implicitamente
void metodo(int, String); // public e abstract -> implicitamente
}

Uma interface estabelece um molde a ser obedecido pelas classes que irão usá-la. Força
que uma classe, ao implementar uma interface, tenha que oferecer obrigatoriamente to-
das as funcionalidades especificadas por esta, assim como os seus atributos de classe.

Exemplo prático com o uso combinado de herança, classes abstratas e interfaces:

Exemplo

Interface Regras (pacote: biblioteca): define as regras de implementação das classes

package biblioteca;

public interface Regras {

void imprimir();
void entrada();

Interface Interface_De_Controle (pacote: biblioteca): estende a interface Regras

package biblioteca;

public interface Interface _ De _ Controle extends Regras {


// Todos os atributos definidos em uma interface
// são implicitamente static e final
int POTENCIAMAXIMA = 350; // static e final
int POTENCIAMINIMA = 120; // static e final

124
// Somente os métodos getters
// como os atributos em uma interface são final,
// não poderão ser alterados, ou seja, não teremos
// os métodos setters
public int getPotenciaMaxima( );
public int getPotenciaMinima( );

// Todos os métodos definidos em uma interface


// são implicitamente public e abstract

void assar(int potencia); // public e abstract

void aquecer(int potencia); // public e abstract

void desligar(); // public e abstract

Classe ClasseAbstrata (pacote: aplicacao): superclasse Abstrata

package biblioteca;

public abstract class ClasseAbstrata {


public abstract void metodoX(int x);
}

Classe Fogao (pacote: biblioteca)

package biblioteca;
import java.util.Scanner;

public class Fogao extends ClasseAbstrata implements Regras, Interface _


De _ Controle {

private String marca, modelo;


private int volume, potencia;
public String getMarca() {
return marca;
}
public void setMarca( String marca ) {
this.marca = marca;
}
public String getModelo() {
return modelo;

125
}
public void setModelo( String modelo ) {
this.modelo = modelo;
}
public int getVolume() {
return volume;
}
public void setVolume( int volume ) {
this.volume = volume;
}
public int getPotencia() {
return potencia;
}
public void setPotencia( int potencia ) {
this.potencia = potencia;
}
public Fogao( ) { }
public Fogao( String marca, String modelo ) {
this.marca = marca;
this.modelo = modelo;
}
public Fogao( int volume, int potencia ) {
this.volume = volume;
this.potencia = potencia;
}
public Fogao( String marca, String modelo, int volume, int potencia ) {
this.marca = marca;
this.modelo = modelo;
this.volume = volume;
this.potencia = potencia;
}
public void cadastrar( String marca, String modelo, int volume, int potencia ) {
this.marca = marca;
this.modelo = modelo;
this.volume = volume;
this.potencia = potencia;
}
public void imprimir() {
System.out.println(“Marca :” + getMarca());
System.out.println(“Modelo :” + getModelo());
System.out.println(“Volume :” + getVolume());
System.out.println(“Potência:” + getVolume());
}

126
public void entrada() {
Scanner ent = new Scanner(System.in);
System.out.println(“Marca :”);
setMarca(ent.nextLine());
System.out.println(“Modelo :”);
setModelo(ent.nextLine());
System.out.println(“Volume :”);
setVolume(Integer.parseInt(ent.nextLine()));
System.out.println(“Potência:”);
setVolume(Integer.parseInt(ent.nextLine()));
}
public int getPotenciaMaxima() {
return POTENCIAMAXIMA;
}
public int getPotenciaMinima() {
return POTENCIAMINIMA;
}
public void assar(int potencia) {
setPotencia(potencia);
System.out.println(“Forno assando com potencia=” + getPotencia());
}
public void aquecer(int potencia) {
setPotencia(potencia);
System.out.println(“Forno aquecendo com potencia=” + getPotencia());
}
public void desligar() {
System.out.println(“Desligar Forno.”);
}
public void metodoX(int x) {
System.out.println(“Valor de X: “ + x);
}
}

Classe AppForno (pacote: aplicacao)

package aplicacao;

import biblioteca.Forno;

public class AppForno {

public static void main(String[] args) {


// TODO Auto-generated method stub
// objetos Forno e Micro-ondas

127
Forno f = new Forno(“GE”, “f505”, 60, 120);
f.assar(200);
f.desligar();
System.out.println();
}
}

Execução:

Forno assando com potência = 200.


Desligar Forno.

Notas:

1. A interface Interface_De_Controle deve ser identificada tal como como uma clas-
se (ou seja, seu identificador deve começar por letras maiúsculas) e determina as
regras de negócio a serem implementadas pelas classes que implementarem a in-
terface.
2. A classe Fogao implementa as interfaces Regras e Interface_De_Controle — isso
faz com tenha acesso aos atributos das interfaces (static e final) — e deve imple-
mentar todos os métodos definidos nas interfaces, além do metodoX(), que é um
método abstrato da superclasse abstrata.
3. A aplicação utiliza normalmente a classe Forno, independentemente se esta utili-
za classes abstratas ou interfaces.

ATENÇÂO:

• Uma classe pode implementar mais de uma interface:

public class Fogao implements Interface _ De _ Controle, Regras,


Sistema { .. }

A classe Fogao deverá obrigatoriamente implementar todas as funcionalidades de-


terminadas pelas três interfaces.

• Uma interface pode estender outra (herança entre interfaces):

public interface Interface _ De _ Controle extends Regras {

Existe herança múltipla apenas entre interfaces na linguagem Java.

128
• Podemos utilizar em conjunto a herança, classes abstratas e interfaces:

public class Fogao extends ClasseAbstrata implements Regras, In-


terface _ De _ Controle

Podemos fazer o uso combinado de vários conceitos ao mesmo tempo.

MIDIATECA

Acesse a midiateca da Unidade 3 e veja o conteúdo complementar indicado


pela professora sobre um comparativo entre o uso de classes abstratas e inter-
faces, em que são descritas as vantagens e desvantagens do uso de cada uma
no desenvolvimento de um projeto.

MIDIATECA

Acesse a midiateca da Unidade 3 e veja o conteúdo complementar indicado


pela professora sobre a importância do polimorfismo de sobrescrita na aplica-
ção dos conceitos de classes abstratas e interfaces. Você verá também como
criar classes abstratas e interfaces na prática.

129
MIDIATECA

Acesse a midiateca da Unidade 3 e veja o conteúdo complementar indicado


pela professora sobre interfaces.

NA PRÁTICA

Ao desenvolvermos um sistema, não basta que ele funcione, mas também que
tenha sido desenvolvido de forma que possa ser reaproveitado e que seja de
fácil manutenção. Para isso, precisamos saber aplicar corretamente os concei-
tos de orientação a objetos. Para uma melhor compreensão e visão da impor-
tância de trabalhar com herança, classes abstratas e interfaces, implemente
os programas apresentados nos exemplos práticos e analise os códigos e os
resultados obtidos.

130
Resumo da Unidade 3

Nesta unidade, você conheceu e aplicou na prática alguns conceitos avançados da pro-
gramação orientada a objetos, entre eles a herança, que permite um melhor reaprovei-
tamento de código, implicando, ainda, uma maior facilidade na manutenção do sistema.
Conheceu e aplicou na prática também um conceito voltado à preparação do sistema
para atender às chamadas “regras de negócio”, tão importantes para satisfazer as expec-
tativas do cliente no desenvolvimento do sistema.

CONCEITO

Compreensão dos conceitos avançados de programação orientada a objetos de


herança, classes abstratas e interfaces, com exemplos de aplicações práticas.

131
Referências

DEITEL, P. Java: como programar. 10. ed. São Paulo: Pearson Education do Brasil, 2017.
Biblioteca Virtual.

MANZANO, J. A. N. G.; COSTA JUNIOR, R. A. Java 7: programação de computadores:


guia prático de introdução, orientação e desenvolvimento. São Paulo: Érica, 2011. Minha
Biblioteca.

SCHILDT, H. Java para iniciantes: crie, compile e execute programas Java rapidamente.
6. ed. Porto Alegre: Bookman, 2015. Minha Biblioteca.

132
UNIDADE 4

Estruturas homogêneas com


Java e o tratamento de exceções
INTRODUÇÃO

No desenvolvimento de sistemas, muitas vezes precisamos armazenar um conjunto de


dados em memória para que possam ser usados posteriormente em outra parte do pro-
cessamento. Armazenar um conjunto grande de dados em variáveis convencionais pode
ser muito trabalhoso, tornando o projeto altamente complexo. O uso de estruturas de
dados simples como vetores e matrizes pode simplificar muito esse processo, facilitando
o armazenamento e a recuperação desses dados. Se você precisa determinar a média
de notas de um grupo de alunos, você pode utilizar apenas uma variável a cada leitura
de nota: você soma a nota lida a uma variável totalizadora de notas, e após a leitura de
todas as notas basta dividir o total de notas pela quantidade de notas lidas. Já se você
precisar saber quantos alunos estão abaixo ou acima da média, você precisará ter arma-
zenado todas as notas na memória; se forem muitas, você precisará de muitas variáveis
e de muitas leituras de notas. Imagine se forem 100 notas ou mais? Você precisará de
100 variáveis, 100 leituras e 100 somas para realizar a tarefa. Se forem mais de 100 no-
tas, o trabalho será ainda maior. Para esses casos, podemos trabalhar com os vetores e
até mesmo matrizes para resolver de forma simples e prática essa tarefa. Na linguagem
Java, podemos ainda trabalhar com vetores e matrizes de objetos, o que nos permitirá
trabalhar de forma simples com grandes quantidades de objetos.

OBJETIVO

Nesta unidade, você será capaz de:

• Compreender como definir vetores e matrizes e utilizá-los na criação de estru-


turas de tipos básicos e de objetos.

134
Estruturas estáticas: vetores e matrizes de
tipos básicos

Vetores e matrizes são estruturas de dados homogêneas e de tamanho fixo utilizadas


para armazenar de forma eficiente um conjunto de dados. Essas estruturas devem ter
um tipo e o tamanho determinados, não podendo armazenar tipos diferentes, além de
não poder aumentar ou diminuir a quantidade de elementos. São organizados na me-
mória de forma consecutiva (sequencial) em função dos índices, que são usados para
identificar cada elemento do vetor.

Vetores também são conhecidos como variáveis indexadas, uma vez que são variáveis
com o mesmo nome, mas com índices diferentes.

Vetores também são conhecidos como array unidimensional.

Matrizes e estruturas com duas ou mais dimensões são chamadas de


array multidimensional.

Vetores

Características dos vetores:

• São estruturas homogêneas de dados, e seus elementos devem ser todos de


um mesmo tipo.
• Vetores de tipos básicos podem ser dos tipos primitivos: byte, short, int, long,
float, double, char e boolean, ou do tipo especial String.
• Possuem tamanho fixo, não podendo ter a quantidade de elementos alterada
durante o processamento.
• Cada elemento é acessível por meio de um índice que representa a posição do
elemento dentro da estrutura.
• Assim como na linguagem C/C++, o primeiro elemento é sempre o de índice 0
(zero).
• O último elemento é sempre definido pelo seu tamanho – 1. Assim, um vetor de

135
100 elementos possui índice 99 para o último elemento, uma vez que o índice
sempre começa por 0 (zero).

Vetores de tipos básicos não requerem muitos cuidados, mas você verá que vetores de
objetos requerem alguns cuidados.

Sintaxe para criação de vetores:

Para declararmos um vetor em Java, podemos utilizar a sintaxe a seguir:

<tipo> <nome>[] = new <tipo>[<num_elementos>];

Para criar um vetor contendo 10 elementos inteiros, deve-se escrever:

int vetor[] = new int[10];

Primeiro 0 1 2 3 4 5 6 7 8 9 Índices
índice

O comprimento do array é 10 (o comprimento é obtido na


propriedade length).
Elemento no índice 8
(note que é a 9ª posição).

Definição em memória de um vetor de 10 elementos do tipo inteiro.

Dessa forma, para o vetor de 10 elementos:

• O primeiro elemento é o de índice 0 (zero): vetor[0].


• O segundo elemento é o de índice 1 (um): vetor[1].
• E assim por diante até o último elemento, de índice 9 (nove): vetor[9].

Se tentarmos acessar um elemento fora do escopo do vetor, é gerada uma exceção indi-
cando que o uso de uma posição inválida foi referenciada. A exceção gerada é:

java.lang.OutOfBoundException

Podemos definir os valores dos elementos de um vetor junto com a sua declaração.

136
Para a criação de um vetor com as notas de 10 alunos de uma sala de aula, vamos usar:

float nota[] = {10.0f, 5.0f, 6.6f, 8.0f, 7.0f, 7.8f, 8.4f, 4.2f, 1.8f, 6.4f };

A quantidade de elementos não precisa ser definida quando você determina os valores
dos elementos.

Assim, temos as seguintes variáveis indexadas:

nota[0] 10.0 nota[1] 5.0 nota[2] 6.6 nota[3] 8.0 nota[4] 7.0

nota[5] 7.8 nota[6] 8.4 nota[7] 4.2 nota[8] 1.8 nota[9] 6.4

Declaração de vetores de tipos básicos:

// Binários
byte vbin[] = new byte[10];
vbin[0] = 0;
vbin[9] = 0;
// Inteiro curto
short vshort[] = new short[20];
vshort[0] = 0;
vshort[19] = 0;
// Inteiro
int vint[] = new int[30];
vint[0] = 0;
vint[29] = 0;
// Inteiro longo
long vlong[] = new long[40];
vlong[0] = 0;
vlong[39] = 0;
// Real de simples precisão
float vfloat[] = new float[20];
vfloat[0] = 0;
vfloat[19] = 0;
// Real de dupla precisão
double vdouble[] = new double[20];
vdouble[0] = 0;
vdouble[19] = 0;
// Caracteres
char vchar[] = new char[26];

137
vchar[0] = ‘A’;
vchar[25] = ‘Z’;
// Lógicos
boolean vbool[] = new boolean[10];
vbool[0] = false;
vbool[9] = true;
// String (texto)
String vstring[] = new String[100];
vstring[0] = “André”;
vstring[99] = “Zandini”;

Vetores podem ter os seus elementos definidos por meio de uma expressão aritmética.
A seguir o exemplo cria um vetor de double com 12 elementos:

// Declaração do vetor:
double fracoes[] = new double[12];
// Preenchimento do vetor
for (int i=0; i<12; i++) {
// Se for apenas i, será gerada uma exceção por tentativa de divisão por zero
fracoes[i] = 1 / (i + 1);
}
// Exibição do conteúdo do vetor
for (int i=0; i<12; i++) {
System.out.println(“fracoes[“+ i + “] = “ + fracoes[i]);
}

Importante

Conforme colocado por Deitel (2017), “declarar múltiplas variáveis em uma úni-
ca declaração pode levar a erros sutis”.

Considere a declaração int[] a, b e c;. Se a, b e c devem ser declarados como


variáveis de array, então essa declaração é correta — colocar os colchetes
logo depois do tipo indicando que todos os identificadores na declaração
são variáveis de array.

138
Entretanto, se apenas a destina-se a ser uma variável de array, e b e c, variá-
veis int individuais, então essa declaração é incorreta — a declaração int a[],
b, c; alcançaria o resultado desejado (DEITEL, 2017, p. 194).

O exemplo a seguir cria um vetor de tipos básicos do tipo String, que realiza a entrada de

Exemplo

Exemplo prático:

Classe: Vetores

import java.util.Scanner;

public class Vetores {


public static void main(String[] args) {
Scanner ent = new Scanner(System.in);

// Declaração do vetor
String nomes[] = new String[5];

// Preenchimento do vetor
for (int i = 0; i < 5; i++) {
System.out.println(“Digite um nome: “);
nomes[i] = ent.nextLine();
}
System.out.println();// Pula uma linha
// Exibição do conteúdo do vetor
for (int i = 0; i < 5; i++) {
System.out.println(nomes[i]);
}
}
}

dados no vetor e, posteriormente, exibe todos os elementos do vetor.

139
Resultados:

Digite um nome:
João
Digite um nome:
Marcela
Digite um nome:
Maria
Digite um nome:
Pedro

André
João
Marcela
Maria
Pedro

Notas:

1. Foi criado um vetor para armazenar cinco nomes.


2. Os nomes foram inseridos no vetor por meio da entrada de dados pelo teclado.
3. Após o preenchimento do vetor, cada elemento foi exibido.

Não podemos exibir os elementos de um vetor simplesmente exibindo o vetor:

System.out.println(nomes);

O resultado será a exibição da posição de memória do primeiro elemento do vetor, e não


serão exibidos os elementos:

[Ljava.lang.String;@28d93b30

Para exibir os elementos de um vetor, é necessário exibir cada elemento separadamente:

for (int i = 0; i < 5; i++) {


System.out.println(nomes[i]);
}

140
Seguem alguns exemplos de vetores com valores predeterminados:

// Doze primeiros termos da sequência de Fibonacci:


long Fibonacci[] = { 1, 1, 2, 3, 5, 8, 13, 34, 55, 89, 144 };

// Tabela de sen(n*pi/6), n=0,1,2,...5


// Constantes float devem ter o f informado ao final
float seno[] = { 0.0000f, 0.5000f, 0.8660f, 1.0000f, 0.8660f,
0.5000f };

// Tabela de log(1+n), n=0,2...99:


double tlog[] = new double[100];
for (int i = 0; i < 100; i++) {
tlog[i] = Math.log(1 + i);
}

A forma mais comum de uso de vetores é por meio da entrada de dados para armazena-
mento e posterior acesso aos valores armazenados. Vamos analisar o exemplo a seguir, para
resolver o problema inicial, apresentando a quantidade de alunos de uma turma com 100
estudantes, e saber quantos alunos estão com média igual ou superior à média da turma.

Exemplo

Exemplo prático:

Classe: Vetores

import java.util.Scanner;

public class Vetores {


public static void main(String[] args) {
Scanner ent = new Scanner(System.in);

// Declaração do vetor
int totalAlunos = 100;// Você pode alterar a quantidade
int contaAlunosMedia=0;
double medias[] = new double[totalAlunos];
double somaMedias=0, mediaTurma=0;

141
// Preenchimento do vetor com as médias dos alunos
for (int i = 0; i < medias.length; i++) {
System.out.println(“Digite a média do aluno[“ + (i+1) +”]:” );
medias[i] = Double.parseDouble(ent.nextLine());
somaMedias += medias[i];
}
mediaTurma = somaMedias / totalAlunos;
// Conta quantos alunos estão com média igual ou superior
// à média da turma
for (int i = 0; i < medias.length; i++) {
if(medias[i]>=mediaTurma) {
contaAlunosMedia ++;
}
}
System.out.println();// Pula uma linha
// Exibe a média da turma e a quantidade de alunos
// Com média igual ou superior à média da turma
System.out.printf(“Média da turma %.2f :”, mediaTurma);
System.out.println();// Pula uma linha
System.out.print(“Alunos com média igual ou superior a média da turma:”);
System.out.printf(“ %d “, contaAlunosMedia);
}
}

Resultados:

Digite a média do aluno[1]:


8
Digite a média do aluno[2]:
7
Digite a média do aluno[3]:
6
Digite a média do aluno[4]:
5
Digite a média do aluno[5]:
4

Média da turma: 6,00


Alunos com média igual ou superior à média da turma: 3

142
Notas:

1. Para os testes, o total de alunos foi alterado para cinco.


2. Foram lidas por meio do teclado todas as médias, que foram totalizadas na soma
das médias.
3. Foi usada de formas alternadas a identificação do total de alunos pela variável ou
por meio da propriedade length do vetor: medias.length.
4. A média da turma só pôde ser computada após a entrada de todas as médias.
5. Após ter sido computada a média da turma, foram comparadas todas as médias
armazenadas com a média da turma para contar a quantidade de alunos com mé-
dia igual ou superior à média da turma.
6. Ao final, foram exibidos a média da turma e o total de alunos com média igual ou
superior à média da turma.

O uso de vetores é relativamente fácil, e ao analisarmos o exemplo anterior podemos ve-


rificar que o tamanho do vetor não importa: a complexidade e o tamanho do código não
se alteram. Se você alterar a quantidade de alunos na variável totalAlunos, o mesmo pro-
grama poderá atender a uma quantidade menor ou maior de alunos, sem necessidade
de outras alterações. Se você quiser, você ainda pode incluir a entrada da quantidade de
alunos pelo teclado, inserindo o código a seguir antes da declaração do vetor de médias:

int totalAlunos = 0;
int contaAlunosMedia=0;

System.out.println(“Quantos alunos a turma possui?”);
totalAlunos = Integer.parseInt(ent.nextLine());

double medias[] = new double[totalAlunos];

Matrizes

Matrizes são como os vetores, mas, enquanto um vetor possui apenas uma dimensão
(um índice), as matrizes possuem duas dimensões e, por consequência, dois índices.
Matrizes são importantes para o armazenamento de conjuntos de dados para realização
de operações matemáticas, assim como para o armazenamento de conjuntos de dados.

143
Podemos usar uma matriz para armazenar um conjunto de notas de um grupo de alunos.
O grupo de alunos pode determinar a quantidade de linhas da matriz, e a quantidade de
notas, o número de colunas.

Matrizes então são estruturas de dados que podem armazenar conjuntos


de dados que normalmente são organizados em tabelas.

Características:

• São homogêneas (todos os elementos da matriz são do mesmo tipo).


• Possuem tamanho fixo, não podendo aumentar ou reduzir a quantidade de ele-
mentos após a sua declaração, permanecendo a quantidade de linhas e de colunas
inalterada.
• O primeiro índice de uma matriz sempre representa a quantidade de linhas, e o
segundo, a quantidade de colunas.

Sintaxe para criação de matrizes:

Para declararmos uma matriz em Java, podemos utilizar a sintaxe a seguir:

<tipo> <nome>[ ] [ ] = new <tipo>[<num_linhas>][<num_colunas>];

Para criar uma matriz contendo 10 linhas e 10 colunas de inteiros, deve-se escrever:

int matriz[][] = new int[10][10];

Exemplo: matriz 3 x 3 de inteiros (nove elementos).

1 2 3
Declaração da matriz em Java:
4 5 6
int matriz[][] = new int[3][3];
7 8 9

Podemos definir os valores dos elementos de uma matriz junto com a sua declaração,
criando a matriz com valores inteiros, com a seguinte sintaxe:

int matriz[][] = { {0, 1, 2}, {1, 11, 12}, {2, 21, 22} };

144
0 1 2 O resultado é determinado pelas linhas, cada conjunto
1 11 12 entre chaves e as colunas, com os elementos dentro de
2 21 22 cada linha.

Declaração de matrizes de tipos básicos:

// Binários
byte mbin[][] = new byte[10][30];
mbin[0][0] = 0;
mbin[9][29] = 0;
// Inteiro curto
short mshort[][] = new short[20][30];
mshort[0][0] = 0;
mshort[19][29] = 0;
// Inteiro
int mint[][] = new int[30][30];
mint[0][0] = 0;
mint[29][29] = 0;
// Inteiro longo
long mlong[][] = new long[40][30];
mlong[0][0] = 0;
mlong[39][29] = 0;
// Real de simples precisão
float mfloat[][] = new float[20][20];
mfloat[0][0] = 0;
mfloat[19][19] = 0;
// Real de dupla precisão
double mdouble[][] = new double[20][1000];
mdouble[0][0] = 0;
mdouble[19][999] = 0;
// Caracteres
char mchar[][] = new char[30][26];
mchar[0][0] = ‘a’;
mchar[29][25] = ‘Z’;
// Lógicos
boolean mbool[][] = new boolean[10][40];
mbool[0][0] = false;
mbool[9][39] = true;
// String (texto)
String mstring[][] = new String[100][5];
mstring[0][0] = “André”;
mstring[99][4] = “Zandini”;

145
Declaração de estruturas multidimensionais:

O Java permite, ainda, a criação de estruturas com mais dimensões, tal como um cubo
de dados ou com mais dimensões.

int multicubo[][][] = new int[3][3][3];

Imagem de cubo de dados segundo a Microsoft.

Região 1
Região 2
Região 3
Região 4
Produto 3
Região 5 Produto 2
Produto 1
Dia 1 Dia 2 Dia 3 Dia 4

Fonte: docs.microsoft.com/pt-br.

Um cubo de dados pode armazenar pares de dados, tal como código do produto e sua
quantidade, mas com um dado a mais, fazendo referência à data em que determinada
quantidade do produto foi vendida. Com um cubo de dados, é possível criar gráficos ilus-
trativos com a evolução das vendas ao longo do tempo.

int multiquad[][][][] = new int[3][3][3][3];

MIDIATECA

Acesse a midiateca da Unidade 4 e veja o conteúdo complementar indicado


pela professora sobre a criação e o uso de vetores (array) em comparação ao
uso de variáveis comuns.

146
MIDIATECA

Acesse a midiateca da Unidade 4 e veja o conteúdo complementar indicado


pela professora para saber mais sobre os vetores (arranjos unidimensionais) e
ordenação de vetores.

147
Criação de vetores de objetos e a organiza-
ção em memória

Vetores e matrizes de objetos são, na verdade, vetores de referências para os objetos


(ponteiros implícitos); sendo assim, após a sua declaração, todas as posições do vetor
estão preenchidas com o valor null.

Isso indica que não temos uma referência válida ainda nessa posição, sendo necessária
a instanciação do objeto. Se for feita uma referência a um elemento que ainda esteja
com o valor null, ocorrerá a exceção: java.lang.NullPointerException, e isso indica que
foi feita uma tentativa de acesso a um objeto inválido. Dessa forma, vetores e matrizes
de objetos requerem um cuidado maior para a sua criação e uso, mas são muito interes-
santes para tratar conjuntos de objetos em sistemas computacionais.

Você pode criar vetores e matrizes de qualquer tipo de objeto, mas sempre será necessá-
rio instanciar (criar) o objeto antes de usá-lo.

Sintaxe para criação de vetores de objetos:

Para declararmos um vetor em Java, podemos utilizar a sintaxe a seguir:

<tipo> <nome>[ ] = new <tipo_objeto>[<numero_elementos>];

Um tipo String é também um objeto; dessa forma, podemos trabalhar esse tipo também
como um objeto:

// Declaração do vetor
String valores[] = new String[5];

// Preenchimento do vetor
valores[0] = new String(“Zero”);
valores[1] = new String(“Um”);
valores[2] = new String(“Dois”);
valores[3] = new String(“Três”);
valores[4] = new String(“Quatro”);

// Exibição do conteúdo do vetor


for (int i=0; i<5; i++) {
System.out.println(valores[i]);
}

148
Declaração de vetores e matrizes de objetos:

Vetores de objetos

Carro vetorCarro[] = new Carro[10];



Geladeira vetorGeladeira[] = new Geladeira[20];

Servidor vetServidor[] = new Servidor[100];

Observação: a declaração do vetor não instancia os objetos que são elementos do vetor.

Exemplo

Exemplo prático:

// Declaração do vetor
Double valores[] = new Double[15];
// Preenchimento do vetor
for (int i=0; i<15; i++) {
// Cada elemento do vetor é instanciado (criado):
valores[i] = new Double(i);
}

// Exibição do conteúdo do vetor


for (int i=0; i<15; i++) {
System.out.println(“Posicao “+ (i+1) +”:
“+valores[i].doubleValue());
}

Observe que foi necessário instanciar o objeto, uma vez que double é um tipo bási-
co, e Double é um objeto.

149
Matrizes de objetos

Matrizes de objetos seguem as mesmas recomendações dos vetores e os mesmos cui-


dados ao se trabalhar com objetos, sendo necessário instanciar (criar) cada objeto indivi-
dualmente antes de utilizá-lo.

Carro matrizCarro[][] = new Carro[10][20];



Geladeira matrizGeladeira[][] = new Geladeira[20][20];

Servidor matServidor[][] = new Servidor[20][100];

Trabalhando com vetores de objetos

No desenvolvimento de projetos na linguagem Java, é comum o uso de vetores de obje-


tos; dessa forma, é importante conhecer com mais atenção o seu uso e como utilizar os
métodos dos objetos por meio de um vetor ou matriz. O ponto mais importante que de-
vemos observar é que o uso é praticamente igual, sendo a única diferença a identificação
do elemento a partir do seu índice.

O exemplo a seguir criará alguns vetores e matrizes de objetos de forma a visualizarmos o


uso e os cuidados que devem ser tomados quando trabalhamos com estruturas de objetos.

Exemplo

Exemplo prático:

Classe: Geladeira (pacote: classes)

package classes;
import java.util.Scanner;

public class Geladeira {


private String modelo;
private int capacidade;
private double preco;

150
public String getModelo() {
return modelo;
}

public void setModelo(String modelo) {


if (!modelo.isEmpty()) {
this.modelo = modelo;
}
}

public int getCapacidade() {


return capacidade;
}

public void setCapacidade(int capacidade) {


if (capacidade > 0) {
this.capacidade = capacidade;
}
}

public double getPreco() {


return preco;
}

public void setPreco(double preco) {


if (preco > 0) {
this.preco = preco;
}
}

public Geladeira() { }

public Geladeira(String modelo) {


setModelo(modelo);
}

public Geladeira(int capacidade) {


setCapacidade(capacidade);
}

public Geladeira(String modelo, int capacidade) {


setModelo(modelo);
setCapacidade(capacidade);
}

151
public Geladeira(String modelo, int capacidade, double preco) {
setModelo(modelo);
setCapacidade(capacidade);
setPreco(preco);
}

public void cadastrar(String modelo, int capacidade, double preco) {


setModelo(modelo);
setCapacidade(capacidade);
setPreco(preco);
}

public void imprimir() {


System.out.println(“Modelo : “ + getModelo());
System.out.println(“Capacidade: “ + getCapacidade());
System.out.println(“Preço : “ + getPreco());
}

public void entradaDados() {


Scanner sc = new Scanner(System.in);
System.out.println(“Modelo : “);
setModelo(sc.nextLine());
System.out.println(“Tamanho : “);
setCapacidade(Integer.parseInt(sc.nextLine()));
System.out.println(“Preço : “);
setPreco(Double.parseDouble(sc.nextLine()));
}
}

Classe: Servidor (pacote: classes)

package classes;
import java.util.Scanner;

public class Servidor {


private String processador;
private int quantidadeMemoria;
private double valor;

public String getProcessador() {


return processador;
}

152
public void setProcessador(String processador) {
if(!processador.isEmpty()){
this.processador = processador;
}
}
public int getQuantidadeMemoria() {
return quantidadeMemoria;
}
public void setQuantidadeMemoria(int quantidadeMemoria) {
if(quantidadeMemoria>0) {
this.quantidadeMemoria = quantidadeMemoria;
}
}
public double getValor() {
return valor;
}
public void setValor(double valor) {
if(valor>0) {
this.valor = valor;
}
}

public Servidor() { }

public Servidor(String processador) {


setProcessador( processador );
}

public Servidor(int quantidadeMemoria) {


setQuantidadeMemoria( quantidadeMemoria );
}

public Servidor(String processador, int quantidadeMemoria) {


setProcessador( processador );
setQuantidadeMemoria( quantidadeMemoria );
}

public Servidor(String processador, int quantidadeMemoria, double valor) {


setProcessador( processador );
setQuantidadeMemoria( quantidadeMemoria );
setValor( valor );
}

153
public void cadastrar(String processador,int quantidadeMemoria, double valor) {
setProcessador( processador );
setQuantidadeMemoria( quantidadeMemoria );
setValor( valor );
}

public void imprimir() {


System.out.println(“Processador : “ + getProcessador());
System.out.println(“Quantidade Memória: “ + getQuantidadeMemoria());
System.out.println(“Valor : “ + getValor());
}

public void entradaDados() {


Scanner sc = new Scanner(System.in);
System.out.println(“Processador : “);
setProcessador(sc.nextLine());
System.out.println(“Quantidade Memória: “);
setQuantidadeMemoria(Integer.parseInt(sc.nextLine()));
System.out.println(“Valor : “);
setValor(Double.parseDouble(sc.nextLine()));
}
}

Classe: AppVetorMatriz (pacote: aplicacoes)

import java.util.Scanner;

// Importa todas as classes do pacote classes


import classes.*;

public class AppVetorMatriz {


public static void main(String[] args) {

// Declaração do vetor de Geladerias com 10 elementos


Geladeira vetGeladeiras[] = new Geladeira[10];
// O atributo length de um vetor indica o número de elementos
for (int i = 0; i < vetGeladeiras.length; i++) {
// O mais importante:
// você não pode se esquecer que deve ser criado
// cada objeto Geladeira do vetor, antes de usá-lo
vetGeladeiras[i] = new Geladeira();
// Você pode usar qualquer método visível do objeto
// Você deve apenas indicar o índice do elemento
vetGeladeiras[i].entradaDados();

154
}
// Geladeiras criadas:
for (int i = 0; i < vetGeladeiras.length; i++) {
// Exibe os dados de cada Geladeira do vetor
vetGeladeiras[i].imprimir();
}
// Declaração da matriz de Servidores com 16 elementos
Servidor matServidores[][] = new Servidor[4][4];
// O atributo length de uma matriz, sem o índice da coluna,
// indica o número de linhas da matriz
for (int i = 0; i < matServidores.length; i++) {
// O atributo length de uma matriz, com a indicação de uma linha,
// indica o número de colunas da matriz
for (int j = 0; j < matServidores[0].length; j++) {
// O mais importante:
// você não pode se esquecer que deve ser criado
// cada objeto Servidor da matriz, antes de usá-lo
matServidores[i][j] = new Servidor();
// Você pode usar qualquer método visível do objeto
// Você deve apenas indicar o índice do elemento
matServidores[i][j].entradaDados();
}
}
// Servidores criados:
for (int i = 0; i < matServidores.length; i++) {
for (int j = 0; j < matServidores[0].length; j++) {
matServidores[i][j].imprimir(); // Exibe os dados de cada Servidor
}
}
}
}

155
Notas:

1. Realize os testes da aplicação.


2. É importantíssimo não se esquecer de instanciar o objeto antes de usá-lo, uma
vez que a declaração do vetor ou da matriz apenas define o tipo e o tamanho do
vetor, não instanciando os objetos que são elementos do vetor ou da matriz.
3. Foram usados métodos dos objetos dos tipos Geladeira e Servidor sem proble-
mas, apenas não esquecendo de indicar o índice.
4. Você pode criar ainda estruturas multidimensionais com três ou quatro dimensões.

Observe que o uso de vetores e matrizes de objetos é simples, apenas


não esquecendo que, por serem objetos, os elementos devem ser ins-
tanciados e identificados pelos seus índices.

MIDIATECA

Acesse a midiateca da Unidade 4 e veja o conteúdo complementar indicado


pela professora sobre como criar e usar vetores de objetos em seus sistemas,
para diminuir a complexidade no desenvolvimento de sistemas e facilitar a ma-
nutenção.

MIDIATECA

Acesse a midiateca da Unidade 4 e veja o conteúdo complementar indicado


pela professora para saber mais sobre arranjos unidimensionais (vetores), ar-
rays multidimensionais e arrays irregulares.

156
Aplicação do tratamento de exceções em
vetores e matrizes

O tratamento de exceções é um recurso importante para evitar que uma aplicação se


encerre abruptamente quando ocorrer alguma inconsistência ou situação não prevista. O
tratamento de exceções permite que, caso alguma situação anormal de processamento
ocorra, essa situação possa ser tratada, evitando que a aplicação se encerre.

Podemos ter problemas com um tipo incompatível na entrada de dados em expressões


aritméticas em que um denominador igual a zero pode gerar uma exceção na divisão, ou
ainda exceções ao acessar arquivos ou gerenciadores de banco de dados. No proces-
samento de vetores e matrizes, um cuidado importante é evitar o acesso a um elemento
inexistente na estrutura, tal como declarar um vetor de inteiros de 10 elementos e tentar
acessar o elemento na posição vetor[10]. Sabemos que um vetor de elementos inicia-se
do elemento vetor[0] e tem como último elemento o vetor[9].

Dessa forma, tentar acessar um elemento inexistente gerará uma exceção do tipo java.
lang.OutOfBoundException, e isso fará com que a aplicação se encerre.

Outra causa de exceções em nossas aplicações é a não instanciação dos objetos perten-
centes ao vetor ou matriz. Como a declaração dessas estruturas apenas determina o tipo
e o tamanho, quando trabalhamos com objetos, devemos ter em mente que eles preci-
sam ser instanciados para poderem ser usados. Caso contrário, teremos o lançamento
de uma exceção do tipo java.lang.NullPointerException, que também é uma causa de
encerramento abrupto da aplicação.

O tratamento de exceções em Java é feito por meio de uma estrutura determinada pelo
conjunto try / catch / finally, e devemos trabalhar com essa estrutura para evitar que
nossas aplicações gerem exceções ao usarmos vetores e matrizes.

157
Características do tratamento de exceções:

Quando uma condição anormal de processamento ou compilação, que normalmente


abortaria a execução ou geraria erro de compilação, ocorre, ela pode ser tratada.

A esse tratamento feito por meio da linguagem, chamamos de tratamento


de exceção.

Uma exceção é um erro que pode ser tratado em tempo de execução e permite que a
aplicação continue apesar do erro. Esse erro pode ser tratado por meio de avisos ao
usuário ou pela execução do código relativo ao tratamento.

Em um mesmo conjunto de instruções, mais de uma exceção pode ocorrer; dessa


forma, mais de um tratamento pode ocorrer.

Utilizamos algumas palavras reservadas para esse tratamento, são elas: try, catch,
finally, throw e throws.

Neste estudo, não trataremos do uso de throw e throws.

Conceitos:

• Exceções representam erros ocorridos no programa que interrompem o fluxo de


execução normal.
• O processo de geração de exceções é chamado de disparo ou lançamento.
• O tratamento de uma exceção disparada é chamado de captura.
• Exceções não capturadas devem ser repassadas.
• Exceções em Java são objetos.
• A API Java possui diversas classes representando exceções.
• Paradigma tentar-e-capturar (try-and-catch): quando um comando puder gerar ex-
ceções, este será tentado (executado); caso a exceção ocorra, esta será capturada.

158
Uma exceção em Java é um sinal que alguma condição excepcional aconteceu.

Algo de errado aconteceu!

Exemplos:

• Solicitação de abertura de um arquivo não encontrado.


• Índice de um vetor (array) fora de faixa.
• Uma conexão de rede perdida.
• Uma inserção no banco com chave primária repetida

Conjunto de instruções para o tratamento de exceções em Java:

try catch finally

Pode-se ter várias cláusulas


É sempre executado
catch por cada try. Cada
quando do término de um
cláusula pode ser usada
tratamento de exceção. É
Inicia a tentativa de execu- para o tratamento de um
utilizado para a liberação de
ção de um bloco de coman- tipo de exceção diferente
recursos (fechamento de
dos e necessita de pelo (aritmética, io, arquivos,
arquivo, de conexão com
menos um bloco catch ou threads etc.). Após execu-
banco de dados, conexões
finally a seguir. tar um bloco catch, o fluxo
de rede etc.). É opcional e
do programa passa para a
é colocado após o último
primeira instrução depois
bloco catch de cada try.
do último bloco catch.

Tratamento de exceções aplicado a vetores e matrizes

Primeiramente, vamos tratar do acesso indevido a um elemento inexistente. Nesse


caso, vamos aproveitar a classe Servidor do exemplo anterior e vamos criar uma nova
aplicação. Nos testes, vamos forçar a exibição dos dados de um elemento inexistente
para compreendermos o que é e como ocorre a exceção.

159
Exemplo

Exemplo prático:

Classe: AppExcecoes1 (pacote: aplicacoes)

package aplicacoes;
//Importa todas as classes do pacote classes
import classes.*;

import java.util.Scanner;

public class AppExcecoes1 {


public static void main(String[] args) {
Scanner ent = new Scanner(System.in);
int qtdElementos=0;
int elemento;
// Definição da quantidade de elementos do vetor
System.out.println(“Quantos elementos do tipo Servidor no vetor?”);
qtdElementos = Integer.parseInt(ent.nextLine());
// Declaração do vetor
Servidor vetServ[]= new Servidor[qtdElementos];
// Criação dos objetos e preenchimento do vetor
for (int i = 0; i < vetServ.length; i++) {
vetServ[i] = new Servidor();
vetServ[i].entradaDados();
}
// Determinação do elemento a ser exibido
System.out.println(“Qual é o índice do elemento que você quer exibir?”);
elemento = Integer.parseInt(ent.nextLine());
// Exibe o elemento
vetServ[elemento].imprimir();
}
}

Resolução 1:

Quantos elementos do tipo Servidor no vetor?


3
Processador :
1
Quantidade Memória:
1

160
Valor :
1
Processador :
2
Quantidade Memória:
2
Valor :
2
Processador :
3
Quantidade Memória:
3
Valor :
3
Qual é o índice do elemento que você quer exibir?
2
Processador : 3
Quantidade Memória: 3
Valor : 3.0

Resolução 2:

Quantos elementos do tipo Servidor no vetor?


3
Processador :
1
Quantidade Memória:
1
Valor :
1
Processador :
2
Quantidade Memória:
2
Valor :
2
Processador :
3
Quantidade Memória:
3
Valor :
3

161
Qual é o índice do elemento que você quer exibir?
3
Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 3
at aplicacoes.AppExcecoes1.main(AppExcecoes1.java:26)

Notas:

1. No primeiro teste, foi criado um vetor de três elementos, e este foi preenchido
normalmente.
2. No momento da escolha do elemento, foi escolhido o elemento de índice 2, que é
existente e não gerou uma exceção.
3. Já no segundo exemplo, também foram criados três elementos, mas, ao ser so-
licitado o índice do elemento, foi informado o total de elementos, 3 (três), que não é
um índice válido, lançando a exceção.

Para evitar tal problema, podemos então proteger nosso vetor com um tratamento de
exceções para a situação:

Exemplo

Exemplo prático:

Classe: AppExcecoes2 (pacote: aplicacoes)

package aplicacoes;

// Importa todas as classes do pacote classes


import classes.*;

import java.util.Scanner;

public class AppExcecoes2 {


public static void main(String[] args) {
Scanner ent = new Scanner(System.in);

162
int qtdElementos = 0;
int elemento;
// Variável para determinar o encerramento da aplicação
boolean continuar = true;
// Definição da quantidade de elementos do vetor
System.out.println(“Quantos elementos do tipo Servidor no vetor?”);
qtdElementos = Integer.parseInt(ent.nextLine());
// Declaração do vetor
Servidor vetServ[] = new Servidor[qtdElementos];

// Criação dos objetos e preenchimento do vetor


for (int i = 0; i < vetServ.length; i++) {
vetServ[i] = new Servidor();
vetServ[i].entradaDados();
}
// Repetição até apresentar um elemento válido
do {
// Determinação do elemento a ser exibido, com proteção
try {
System.out.println(“Qual é o índice do elemento que você quer exibir?”);
elemento = Integer.parseInt(ent.nextLine());
// Exibe o elemento
vetServ[elemento].imprimir();
continuar = false;
} catch (ArrayIndexOutOfBoundsException ex1) {
System.out.println(“Você escolheu um elemento inexistente do vetor.”);
System.out.println(“Tente novamente!”);
} catch (Exception ex2) {
System.out.println(“Alguma outra exceção ocorreu!”);
}
} while (continuar);
}
}

Resolução:

Quantos elementos do tipo Servidor no vetor?


3
Processador :
1
Quantidade Memória:
1

163
Valor :
1
Processador :
2
Quantidade Memória:
2
Valor :
2
Processador :
3
Quantidade Memória:
3
Valor :
3
Qual é o índice do elemento que você quer exibir?
3
Você escolheu um elemento inexistente do vetor.
Tente novamente!
Qual é o índice do elemento que você quer exibir?
2
Processador : 3
Quantidade Memória: 3
Valor : 3.0

Notas:

1. No teste, foi criado um vetor de três elementos, e este foi preenchido normalmente.
2. No momento da escolha do elemento, foi escolhido o elemento de índice 3, que é
inexistente e lançou uma exceção.
3. Como a aplicação está protegida, foi exibida uma mensagem ao usuário, mas a
aplicação não encerrou.
4. Para efeito didático, foi incluída uma repetição que fez com que fosse solicitado
novamente o índice do elemento; uma vez sendo inserido um índice válido, a aplica-
ção exibiu corretamente os dados do elemento e encerrou normalmente.

Outro problema é a tentativa de uso de elemento não instanciado em vetor de objetos.


Nesse caso, a exceção é diferente. Vamos analisar o código a seguir, no qual será criado
um vetor com n elementos determinados pelo usuário, mas o usuário deve fornecer o

164
índice do elemento que será usado no preenchimento de dados — porém, elementos não
instanciados lançarão uma exceção.

Exemplo

Exemplo prático:

Classe: AppExcecoes3 (pacote: aplicacoes)

package aplicacoes;

// Importa todas as classes do pacote classes


import classes.*;

import java.util.Scanner;

public class AppExcecoes3 {


public static void main(String[] args) {
Scanner ent = new Scanner(System.in);
int qtdElementos = 0;
int elemento;
// Variável para determinar o encerramento da aplicação
boolean continuar = true;
// Definição da quantidade de elementos do vetor
System.out.println(“Quantos elementos do tipo Servidor no vetor?”);
qtdElementos = Integer.parseInt(ent.nextLine());
// Declaração do vetor
Servidor vetServ[] = new Servidor[qtdElementos];
// Determinação do elemento a ser preenchido
do {
// Criação dos objetos e preenchimento do vetor
System.out.println(“Qual é o índice do elemento que você quer preencher?”);
System.out.println(“Use -1 para encerrar!”);
int i = Integer.parseInt(ent.nextLine());
if (i != -1) {
vetServ[i] = new Servidor();
vetServ[i].entradaDados();
} else {
continuar = false;
}
} while (continuar);

165
continuar = true;
// Repetição até apresentar um elemento válido
do {
System.out.println(“Qual é o índice do elemento que você quer exibir?”);
elemento = Integer.parseInt(ent.nextLine());
// Exibe o elemento
vetServ[elemento].imprimir();
continuar = false;
} while (continuar);
}
}

Resolução:

Quantos elementos do tipo Servidor no vetor?


3
Qual é o índice do elemento que você quer preencher?
Use -1 para encerrar!
0
Processador :
1
Quantidade Memória:
1
Valor :
1
Qual é o índice do elemento que você quer preencher?
Use -1 para encerrar!
2
Processador :
3
Quantidade Memória:
3
Valor :
3
Qual é o índice do elemento que você quer preencher?
Use -1 para encerrar!
-1
Qual é o índice do elemento que você quer exibir?
1
Exception in thread “main” java.lang.NullPointerException
at aplicacoes.AppExcecoes2.main(AppExcecoes2.java:41)

166
Notas:

1. No teste, foi criado um vetor de três elementos.


2. Os elementos foram preenchidos de acordo com a escolha do usuário; no caso,
apenas os elementos de índice 0 e 2 foram criados e preenchidos.
3. O elemento de índice 1 não foi criado nem preenchido.
4. No momento da escolha do elemento a ser exibido, foi escolhido o elemento de
índice 1, que não foi instanciado, por isso sua posição no vetor aponta para endere-
ço null.
5. Como a aplicação não está protegida, foi exibida uma mensagem ao usuário e a
aplicação encerrou.

Como temos uma nova exceção, o trecho de proteção terá mais uma cláusula catch, para
atender a essa nova demanda. Lembre-se de que podemos ter várias cláusulas catch
para cada conjunto try.

Exemplo

Exemplo prático:

Classe: AppExcecoes4 (pacote: aplicacoes)

package aplicacoes;

// Importa todas as classes do pacote classes


import classes.*;

import java.util.Scanner;

public class AppExcecoes4 {


public static void main(String[] args) {
Scanner ent = new Scanner(System.in);
int qtdElementos = 0;
int elemento;
// Variável para determinar o encerramento da aplicação
boolean continuar = true;
// Definição da quantidade de elementos do vetor
System.out.println(“Quantos elementos do tipo Servidor no vetor?”);
qtdElementos = Integer.parseInt(ent.nextLine());

167
// Declaração do vetor
Servidor vetServ[] = new Servidor[qtdElementos];
// Determinação do elemento a ser preenchido
do {
// Criação dos objetos e preenchimento do vetor
System.out.println(“Qual é o índice do elemento que você quer preencher?”);
System.out.println(“Use -1 para encerrar!”);
int i = Integer.parseInt(ent.nextLine());
if (i != -1) {
vetServ[i] = new Servidor();
vetServ[i].entradaDados();
} else {
continuar = false;
}
} while (continuar);
continuar = true;
// Repetição até apresentar um elemento válido
do {
// Determinação do elemento a ser exibido, com proteção
try {
System.out.println(“Qual é o índice do elemento que você quer exibir?”);
elemento = Integer.parseInt(ent.nextLine());
// Exibe o elemento
vetServ[elemento].imprimir();
continuar = false;
} catch (ArrayIndexOutOfBoundsException ex1) {
System.out.println(“Você escolheu um elemento inexistente do vetor.”);
System.out.println(“Tente novamente!”);
} catch (NullPointerException ex2) {
System.out.println(“Você escolheu um elemento não instanciado do vetor.”);
System.out.println(“Tente novamente!”);
} catch (Exception ex3) {
System.out.println(“Alguma outra exceção ocorreu!”);
}
} while (continuar);
}
}

Resolução:

Quantos elementos do tipo Servidor no vetor?


3
Qual é o índice do elemento que você quer preencher?
Use -1 para encerrar!
0

168
Processador :
1
Quantidade Memória:
1
Valor :
1
Qual é o índice do elemento que você quer preencher?
Use -1 para encerrar!
2
Processador :
3
Quantidade Memória:
3
Valor :
3
Qual é o índice do elemento que você quer preencher?
Use -1 para encerrar!
-1
Qual é o índice do elemento que você quer exibir?
1
Você escolheu um elemento não instanciado do vetor.
Tente novamente!
Qual é o índice do elemento que você quer exibir?

Notas:

1. No teste, também foi criado um vetor de três elementos.


2. Os elementos foram preenchidos de acordo com a escolha do usuário; no caso,
apenas os elementos de índice 0 e 2 foram criados e preenchidos.
3. O elemento de índice 1 não foi criado nem preenchido.
4. No momento da escolha do elemento a ser exibido, foi escolhido o elemento de
índice 1, que não foi instanciado, por isso sua posição no vetor aponta para endere-
ço null.
5. Como a aplicação está protegida, foi exibida uma mensagem ao usuário e a apli-
cação encerrou.

Podemos observar que, com a aplicação protegida, o usuário tanto pode escolher um
índice de elemento inexistente como tentar usar um elemento não instanciado que a

169
aplicação não irá encerrar. O uso do tratamento de exceções é mais extenso, mas aqui
fizemos o seu uso para a proteção de vetores — o uso com matrizes é análogo a este,
conforme visto anteriormente.

MIDIATECA

Acesse a midiateca da Unidade 4 e veja o conteúdo complementar indicado


pela professora sobre o tratamento de exceções, os tipos de exceções e a hie-
rarquia de exceções.

MIDIATECA

Acesse a midiateca da Unidade 4 e veja o conteúdo complementar indicado


pela professora para saber mais sobre o tratamento de exceções, a hierarquia
das exceções e exceções de arrays.

NA PRÁTICA

Quando estamos executando uma aplicação, uma exceção pode ser lançada,
ou seja, um evento inesperado pode ocorrer. Uma exceção pode ser lançada
a partir de erros de lógica ou mesmo por ocasião de problemas de hardware
ou de recursos da máquina virtual Java. Como exemplo, ao desenvolvermos
uma calculadora, por mais simples que pareça, não podemos esquecer de que
não existe divisão por zero. Imagine que o usuário tente realizar uma divisão
por zero: uma exceção será disparada, e como consequência teremos a inter-
rupção do programa. Sendo assim, durante o desenvolvimento da aplicação,
precisamos aplicar o conceito de tratamento de exceções, visando identificar e
tratar uma exceção, de forma que o programa continue executando.

170
Resumo da Unidade 4

Nesta unidade, você pôde compreender como trabalhar com vetores e matrizes, além
de aplicar na prática esse conhecimento. Foram abordados os conceitos de vetores e
matrizes para os tipos básicos e para objetos, aumentando consideravelmente as apli-
cações desses recursos no desenvolvimento de nossos projetos na linguagem Java. O
tratamento de exceções no uso de vetores e matrizes também foi abordado de forma
prática em nossos exemplos.

CONCEITO

Definição e uso de vetores e matrizes de dados de tipos primitivos e de objetos.

171
Referências

DEITEL, P. Java: como programar. 10. ed. São Paulo: Pearson Education do Brasil, 2017.
p. 194. Biblioteca Virtual.

MANZANO, J. A. N. G.; COSTA JUNIOR, R. A. Java 7: programação de computadores:


guia prático de introdução, orientação e desenvolvimento. São Paulo: Érica, 2011. Minha
Biblioteca.

SCHILDT, H. Java para iniciantes: crie, compile e execute programas Java rapidamente.
6. ed. Porto Alegre: Bookman, 2015. Minha Biblioteca.

172

Você também pode gostar