Java Poo
Java Poo
29 de maio de 2000
i
Sumário
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
ii
5 Herança 43
5.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.2 O mecanismo de sobrecarga . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
5.3 Herança de variáveis e métodos privados . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
5.4 Outros exemplos e mecanismos de herança . . . . . . . . . . . . . . . . . . . . . . . . . 50
5.5 Exercícios do capítulo 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
6 Polimorfismo 57
6.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6.2 Regras de polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
6.3 Mais exemplos de polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
6.4 Exercícios do capítulo 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
7 Construtores 67
7.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.1.1 O construtor default . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
7.2 Construtores, herança e polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
7.3 O método toString() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
7.4 Exercícios do capítulo 7 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
9 A Classe String 99
9.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
9.2 Métodos básicos da classe String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
9.3 Métodos para comparação de Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
9.4 Métodos para modificação de Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
9.5 Métodos para seleção em Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
9.6 Métodos para procura em Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
9.7 Exercícios do capítulo 9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
iii
12 Exceções 149
12.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
12.2 O que são exceções ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
12.2.1 Tipos de exceções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
12.3 Usando exceções em classes desenvolvidas pelo programador . . . . . . . . . . . . . . . . 154
12.4 Exercícios do capítulo 12 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
iv
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
v
Lista de Figuras
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
vi
Lista de Listagens
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
vii
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
viii
11.1 Um programa que demonstra usos das constantes da classe Math . . . . . . . . . . . . . . 142
11.2 Um programa que demonstra usos de métodos de comparação e arredondamento da classe
Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
11.3 Um programa que demonstra usos de métodos trigonométricos da classe Math . . . . . . 144
11.4 Um programa que demonstra usos de métodos exponenciais da classe Math . . . . . . . . 145
11.5 Um programa que demonstra usos do método random da classe Math . . . . . . . . . . . 145
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
ix
B.1 Exemplo de uso da classe Keyboard para leitura de valores tipo boolean . . . . . . . . . 202
B.2 Exemplo de uso da classe Keyboard para leitura de valores tipo byte . . . . . . . . . . . 203
B.3 Exemplo de uso da classe Keyboard para leitura de valores tipo char . . . . . . . . . . . 203
B.4 Exemplo de uso da classe Keyboard para leitura de valores tipo short . . . . . . . . . . 204
B.5 Exemplo de uso da classe Keyboard para leitura de valores tipo int . . . . . . . . . . . . 204
B.6 Exemplo de uso da classe Keyboard para leitura de valores tipo long . . . . . . . . . . . 205
B.7 Exemplo de uso da classe Keyboard para leitura de valores tipo float . . . . . . . . . . 206
B.8 Exemplo de uso da classe Keyboard para leitura de valores tipo double . . . . . . . . . . 206
B.9 Exemplo de uso da classe Keyboard para leitura de instâncias da classe String . . . . . 207
B.10 Mais exemplos de usos da classe Keyboard . . . . . . . . . . . . . . . . . . . . . . . . . 207
B.11 Exemplo de uso da classe Keyboard na classe Aluno . . . . . . . . . . . . . . . . . . . . 208
B.12 Exemplo de uso da classe Aluno com instâncias da classe Keyboard . . . . . . . . . . . 209
B.13 A classe Keyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
x
Lista de Tabelas
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
1
Capítulo 1
Ao desenvolver este livro, as motivações principais foram apresentar os conceitos de programação orienta-
da a objetos com clareza e simplicidade, mostrando exemplos e sugerindo problemas práticos e ilustrativos
dos conceitos. Muitos livros de programação orientada a objetos, especialmente usando a linguagem Java,
concentram-se em aspectos visuais, deixando a teoria necessária para melhor compreensão das técnicas de
lado. Na maioria dos casos, demonstrações das capacidades da linguagem são apresentadas desde cedo,
sem as explicações necessárias para compreensão do que acontece nos programas-exemplo. Em contraste,
este livro concentra-se nas técnicas de programação orientada a objetos, deixando a parte visual para os
últimos capítulos. Espera-se que com isto os alunos estejam mais confortáveis com os conceitos de classes
e objetos quando forem utilizá-los em aplicações gráficas.
Este livro também pode ser usado por outros estudantes interessados em técnicas de programação orientada
a objetos e na linguagem Java, e possivelmente por turmas inteiras, se o professor da disciplina correspon-
dente estiver interessado. Em qualquer caso, por favor informe o autor por e-mail ([email protected]),
para comentários, correções, sugestões e/ou incentivo à melhorias.
Este livro definitivamente não é um guia completo à linguagem Java ou à orientação a objetos - vários
conceitos teóricos e detalhes práticos da linguagem serão deixados de lado. O enfoque é dado aos aspectos
básicos e mais práticos.
Esta versão do livro está sendo colocada à disposição dos interessados como uma cortesia da Faculdade
de Ciência da Computação da Universidade do Vale do Paraíba. Ninguém tem o direito de cobrar pelo
acesso ou cópias deste livro sem a permissão expressa da Faculdade de Ciência da Computação e do
autor do livro - em caso de dúvida, consulte o autor por e-mail ([email protected]).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
2
As versões do livro são identificadas por sua data - esta versão foi compilada em 29 de maio de 2000, e
contém 164 programas e 326 exercícios, sendo que 132 são de uma estrela, 106 são de duas estrelas, 62
são de três estrelas, 19 são de quatro estrelas e 7 são de cinco estrelas.
O livro também pode ser impresso através do Adobe Acrobat Reader, mas várias das características inte-
ressantes disponíveis na versão digital (links diretos para seções, listagens e figuras, índices que funcionam
como links, etc.) serão, evidentemente, perdidas. Adicionalmente, novas versões com correções e modifi-
cações podem estar sendo liberadas brevemente, invalidando impressões anteriores.
FCC/UNIVAP Usuários de computadores que rodam Linux nos laboratórios da FCC podem aces-
sar a última versão deste livro diretamente dos seus terminais com o comando acroread -geometry
800x555 ˜POO/POO.pdf. O parâmetro -geometry 800x555 faz com que a tela não apareça maximi-
zada, garantindo a visibilidade dos menus e barra da janela do acroread.
• Capítulo 3: Criando Classes em Java mostra como criamos classes em Java usando os tipos de
dados e mecanismos de criação de métodos.
• Apêndice A: Tipos de Dados em Java apresenta os diferentes tipos de dados e classes básicas da
linguagem Java, incluindo características e problemas relacionados à representação de tipos e classes
nativas em Java e vários programas-exemplo.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
3
Adicionalmente, programas incluídos no texto serão mostrados com diferentes cores para facilitar a leitura:
comentários em vermelho, conjuntos de caracteres em cinza, palavras reservadas em diferentes cores de
acordo com sua categoria. As linhas dos programas também serão numeradas para fácil referência.
Alguns tópicos, exercícios, arquivos, ferramentas, etc. mencionados neste livro estão disponíveis somente
para alunos da Faculdade de Ciência da Computação da Universidade do Vale do Paraíba. Estes tópicos
estarão marcados com FCC/UNIVAP.
• Uma estrela (?): Exercícios teóricos ou práticos que podem ser resolvidos rapidamente, geralmente
através de consultas a programas mostrados ou respostas de outros exercícios, e modificação de
exemplos ou outras respostas. Em muitos casos podem ser resolvidos mentalmente, isto é, sem a
necessidade de escrever, compilar e executar programas.
• Duas estrelas (? ?): Exercícios teóricos ou práticos que exigem um pouco mais de raciocínio e
modificações ligeiras de exemplos apresentados. Exercícios desta categoria geralmente precisarão
ser compilados e executados para verificação dos resultados.
• Três estrelas (? ? ?): Exercícios que requerem compreensão mais completa dos conceitos envolvi-
dos, mas mesmo assim podem ser resolvidos com base em exemplos ou respostas a outros exercícios.
• Quatro estrelas (? ? ? ?): Exercícios que requerem compreensão mais profunda dos conceitos
e que geralmente não podem ser resolvidos tomando como base exemplos ou respostas a outros
exercícios.
• Cinco estrelas (? ? ? ? ?): Exercícios que requerem a solução de um problema mais completo e
complexo, envolvendo vários conceitos diferentes da disciplina. Estes exercícios podem servir como
base para projetos mais interessantes.
FCC/UNIVAP Alguns exercícios estão marcados com Novo ! : estes exercícios foram incluídos
nos capítulos algum tempo depois da disponibilização “oficial” dos mesmos. Estes novos exercícios não
serão usados para criação das provas, mas devem ser feitos para aumentar a compreensão dos tópicos
relacionados.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
4
Java é obrigatoriamente orientada a objetos. Algumas linguagens permitem que objetos e variáveis exis-
tam em diversos pontos de um programa, como se estivessem desatreladas de qualquer estrutura
exceto funções. Em Java, todas as variáveis e métodos devem estar localizados dentro de classes,
forçando o uso de orientação a objetos até mesmo em tarefas simples. Dessa forma, o estudante de
programação orientada a objetos que esteja usando Java estará usando mais as técnicas de POO.
Java é simples. A estrutura de programas e classes em Java segue a organização de linguagens tradicionais
como C e C++, mas sem elementos que tornam programas e programação mais complexos. Após
o aprendizado dos conceitos básicos de programação orientada a objetos, o estudante da linguagem
pode começar a criar aplicativos úteis e complexos.
A simplicidade se reflete também na maneira com que arquivos contendo programas em Java são
compilados e executados: se as recomendações básicas forem seguidas, o compilador se encarregará
de compilar todas as classes necessárias em uma aplicação automaticamente, sem necessidade de
arquivos adicionais de configuração e inclusão de bibliotecas.
Java é portátil. O código-fonte de um programa ou classe em Java pode ser compilado em qualquer com-
putador, executando qualquer sistema operacional, que tenha uma máquina virtual Java adequada
(veja o apêndice C). Adicionalmente, as classes criadas podem ser copiadas e executadas em qual-
quer computador nas mesmas condições, aumentando a utilidade da linguagem através da indepen-
dência de plataformas.
Java é gratuita. A máquina virtual Java, mencionada acima, está à disposição para cópia no site da Sun
e em vários outros. Compiladores simples, de linha de comando (sem interfaces visuais elaboradas)
fazem parte do JDK, o ambiente de desenvolvimento gratuito de Java. Aplicações em Java precisam
de uma máquina virtual para sua execução, mas não existem sequer royalties de distribuição, fazendo
de Java uma plataforma extremamente econômica para desenvolvedores e usuários finais.
Java é robusta. Administração de memória (alocação e liberação) e o uso de ponteiros, duas das fontes
de erros e bugs mais frequentes em programas em C e C++, são administrados internamente na
linguagem, de forma transparente para o programador. De maneira geral, programas em Java tem
restrições no acesso à memória que resultam em maior segurança para os programas sem diminuir a
utilidade dos mesmos.
Java também tem um poderoso mecanismo de exceções que permitem melhor tratamento de erros
em tempo de execução dos programas.
Java tem bibliotecas prontas para diversas aplicações. As bibliotecas de classes de Java contém várias
classes que implementam diversos mecanismos de entrada e saída, acesso à Internet, manipulação de
Strings de alto nível, poderosas estruturas de dados, utilitários diversos e um conjunto completo de
classes para implementação de interfaces gráficas.
Vale a pena relembrar que estas bibliotecas são padrão de Java - qualquer máquina virtual Java
permite o uso destas bibliotecas, sem a necessidade de instalar pacotes adicionais, e quemesmo que
o compilador usado não tenha interface gráfica similar à de linguagens visuais, os programas criados
com este compilador podem ter interfaces gráficas complexas.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
5
1. Introdução aos conceitos de Programação Orientada a Objetos e comparação com Programação Pro-
cedural.
2. Fundamentos do Paradigma “Programação Orientada a Objetos”: Tipos Abstratos de Dados, Classes
e Objetos (Capítulo 2), Encapsulamento (Capítulo 2), Herança, Polimorfismo e Sobrecarga. Imple-
mentação dos conceitos em Java.
3. Programação em Java: Conceitos Básicos, Comandos de Iteração, Comandos de Decisão, Vetores de
Dados.
4. Classes e Métodos para Entrada e Saída.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
6
• Introdução à classes de estruturas de dados genéricas de Java: String, Vector, Hashtable, Classes
que representam tipos nativos.
• Programação usando sockets e usando URLs para obter dados via Internet.
• Programação de aplicações com interfaces gráficas: o Abstract Windowing Toolkit.
• Programação com fluxo linear e programação com eventos: registrando e processando eventos.
1.6 Agradecimentos
Este livro não teria sido possível sem o incentivo e paciência da minha esposa, Yukari, à qual sou grato por
muitas outras coisas.
Agradeço também à colegas da Univap pelo incentivo à criação deste livro, e aos alunos que colaboraram
de uma forma ou de outra.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
7
Capítulo 2
A simplificação inerente aos modelos nos permite armazenar, representar, processar e trocar informações
de maneira eficiente. Muitas vezes a simplificação é necessária para que não tenhamos que representar
informações inúteis em determinado contexto.
Por exemplo, consideremos a tarefa de representar os dados relativos à uma pessoa: se estamos pensan-
do em uma pessoa que faz parte de uma folha de pagamento de empregados, representaremos o nome, o
cargo e o salário desta pessoa. Se estamos considerando que esta pessoa faz parte do banco de dados de
pacientes de um médico, representaremos o nome, o sexo, a idade, a altura, o peso e o histórico de
consultas desta pessoa. Ainda, se queremos representar os dados de um amigo ou conhecido na nossa
lista telefônica particular, usaremos o seu nome, seu endereço e seu telefone.
Podemos notar que os três modelos citados representam, cada um a seu modo, uma pessoa, e não existe
necessidade nem sentido em criar um “super modelo” capaz de representar cada dado relativo à uma pessoa
e usar este modelo em cada ocasião em que se faz necessário: seria absurdo ou ao menos sem propósito
representarmos o histórico de consultas de uma pessoa em uma lista telefônica pessoal ou represen-
tarmos o salário na nossa lista telefônica.
Modelos, além de conterem dados necessários para representar um objeto ou conceito qualquer, podem
conter operações relativas aos dados contidos neles. Por exemplo, no modelo pessoa-paciente descrito
acima, poderíamos ter as operações adiciona-informação-ao-histórico, que adicionaria informações
recentes ao histórico do paciente, ou verifica-obesidade, que usaria os dados sexo, idade, altura
e peso para verificar se aquela pessoa está com o peso ideal para sua categoria. Similarmente, podemos
imaginar uma operação calcula-horas-extras no modelo pessoa-empregado. Estas operações tem
sentido somente para os modelos que representam dados que podem ser processados por eles: não há sen-
tido em termos a operação verifica-obesidade disponível para uso na nossa lista telefônica.
Modelos podem ser reutilizados infinitamente para representar diferentes objetos, pessoas ou itens: nos
exemplos mostrados acima, o modelo adequado seria usado para cada pessoa distinta na lista telefônica ou
na folha de pagamento. Considere a representação dos dados dos livros em uma biblioteca: um modelo
que contenha os dados título, autor, número-de-registro, editora e outros poderia ser usado para
representar os livros, mas cada um dos livros terá um título, autor, etc. diferente dos outros.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
8
Modelos podem também conter outros modelos: se resolvermos representar os dados de uma data usando
um modelo chamado, por exemplo, data-de-calendário que contenha valores para representar dia, mês
e ano, podemos, sempre que a representação de uma data for necessária, usar o modelo criado ao invés de
representarmos separadamente o dia, mês e ano desta data. Em outras palavras, ao invés de separadamente
usarmos valores para dia, mês e ano em outros modelos, podemos usar o data-de-calendário que foi
criado anteriormente. Por exemplo, em um modelo mais completo para os livros da biblioteca, poderíamos
incluir a data-de-aquisição que seria baseada no modelo data-de-calendário (contendo os dados
deste).
Em resumo, a criação e uso de modelos é uma tarefa natural e a extensão desta abordagem à programação
deu origem ao paradigma Programação Orientada a Objetos.
Em Programação Orientada a Objetos, os dados pertencentes aos modelos são representados por tipos de
dados nativos, característicos da linguagem de programação, ou de outros modelos criados pelo programa-
dor. As principais diferenças entre os modelos “naturais” descritos na seção 2.1 e os “artificiais” 1 criados
em programas orientados a objetos são a limitação nas tarefas que um computador pode executar e a limi-
tação da própria linguagem de programação.
Como exemplo das diferenças entre modelos do mundo real e os implementados em linguagens de progra-
mação, consideremos a operação adiciona-informação-ao-histórico, do modelo pessoa-paciente,
descrito anteriormente. Podemos imaginar que no mundo real esta operação se resume a escrever em
uma ficha própria as informações adicionais, que provavelmente estarão juntas às informações prévias (em
uma ficha, por exemplo). A implementação deste modelo e operação em programas de computador pro-
vavelmente terá que ser feita usando arquivos para armazenar as informações, e provavelmente existirão
restrições quanto ao tipo e tamanho das informações a serem adicionadas - possivelmente somente infor-
mações textuais poderão ser armazenadas, mas não gráficos.
Modelagem dos dados e operações nestes dados em um programa de computador, apesar das limitações,
permite processamento de dados de forma mais coesa, natural e menos suscetível à erros de programação.
Por outro lado, mais atenção tem que ser dada ao design dos modelos que serão implementados. Os
detalhes de implementação de modelos em Java serão dados no capítulo 3, mas antes alguns detalhes
teóricos precisam ser elucidados.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
9
Classes são escritas com os recursos da linguagem de programação orientada a objetos para implemen-
tação dos modelos, mas elas não podem ser utilizadas diretamente nos programas - classes são somente
moldes ou formas que representam os modelos abstratamente. Nos modelos e classes, sabemos que o dado
endereço do modelo lista-telefônica representa o endereço, mas não há como determinar de quem é
o endereço, ou seja, o dado representa uma informação genérica e não uma informação sobre uma pessoa
cujos dados são usados no modelo.
Para que possamos representar dados específicos usando classes é necessário que criemos objetos, instân-
cias, exemplos ou amostras desta classe. Um objeto ou instância (termos mais comumente usados) é uma
materialização da classe, e pode ser usado para representar dados. Para cada item que queiramos represen-
tar no nosso programa, devemos criar um objeto da classe adequada. Um exemplo mais detalhado é dado
na figura 2.1.
Objeto Automóvel
− Número de passageiros: 5
− Velocidade Máxima: 200 km/h
− É aéreo ?: não
− É terrestre ?: sim
Objeto Navio
− Número de passageiros: 450
− Velocidade Máxima: 90 km/h
− É aéreo ?: não
− É terrestre ?: não
Na figura 2.1 temos uma classe Veículo e quatro objetos desta classe. Cada objeto é um veículo, então
cada objeto terá as mesmas informações (Número de passageiros, É aéreo, etc.), mas os valores destas
informações (suas características) serão diferentes para cada objeto. Podemos dizer que a classe representa
todos os objetos de maneira abstrata, sem entrar em detalhes de cada um. Nota-se que neste exemplo a
classe Veículo contém somente valores ou atributos, mas não operações.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
10
2.4 Encapsulamento
Nos exemplos descritos até agora, os dados relativos à um modelo qualquer foram agrupados ou encapsula-
dos em uma classe. O encapsulamento de dados em uma classe é uma das características mais importantes
e úteis de Programação Orientada a Objetos.
O encapsulamento dos dados e operações para processamento destes dados nos garante que, ao criar-
mos instâncias ou objetos desta classe, todos os dados e operações necessários para representar o objeto
e processar seus dados estarão presentes. Outra função importante do encapsulamento é a ocultação de
informação: se uma classe é bem preparada, ela pode ter operações que permitam a um programador mo-
dificar e ler os dados representados, mas não diretamente, para garantir a integridade destes dados. Toda a
manipulação dos dados seria feita através de interfaces que seriam operações específicas para manipulação
dos dados das classes.
Como exemplo, consideremos a classe Data, que implementa o modelo de mesmo nome, descrito anteri-
ormente. Esta classe conteria valores para representar o dia, mês e ano da data. Se um programador fosse
usar um objeto desta classe em um programa e tivesse livre acesso aos dados encapsulados, ele ou ela
poderia tentar colocar valores inválidos nos dados, como por exemplo, 45 no valor que representa o dia.
Seria desejável que o valor que representa o dia ficasse escondido dentro da classe, e que a única maneira
de modificar este valor fosse através de uma operação que verificaria se o valor passado é válido.
Consideremos um modelo para uma lâmpada incandescente comum - este modelo tem alguns atributos e
operações que são ilustrados pela figura 2.2.
Atributos Operações
− Estado (ligada ou − Ligar
desligada) − Desligar
Uma lâmpada incandescente comum tem um estado, que pode ser ligada ou desligada. Este estado
pode ser modificado através das operações ligar e desligar. Desta forma, todo o mecanismo de funcio-
namento de lâmpadas estaria encapsulado na classe mostrado na figura 2.2. Instâncias da classe lâmpada
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
11
poderiam ser usadas para representar lâmpadas específicas, que a qualquer momento podem ter estados
diferentes (uma lâmpada pode estar ligada e outra, desligada).
Uma classe que representasse este modelo poderia, através do encapsulamento, garantir que um progra-
mador que usasse instâncias da classe lâmpada poderia modificar seu estado acesa/apagada somen-
te através das operações ligar/desligar. Desta forma, quando várias instâncias ou objetos da classe
lâmpada forem criados (por exemplo, lâmpada_sala, lâmpada_quarto, etc.) cada uma terá seu atributo
acesa/apagada e poderá ser ligada/desligada através da suas operações ligar/desligar.
Nota-se que alguns atributos óbvios que definem uma lâmpada incandescente foram deixados de lado, co-
mo consumo em watts, tamanho e cor do bulbo. A decisão sobre o que deve ou não pertencer à um objeto
é um pouco arbitrária, e dependente da aplicação - para um exemplo simples, os dados mostrados na figura
2.2 bastam, enquanto que para uma aplicação real de controle de qualidade, por exemplo, dados como
número do lote, data de fabricação e unidade produtora seriam necessários.
Consideremos o exemplo de uma data simples (como a de um evento como aniversário, etc.) - esta data
tem alguns atributos e operações que são mostrados na figura 2.3.
March 2000
Atributos Operações
− Dia − Ajusta dia
− Mês − Ajusta mês
− Ano − Ajusta ano
− Ajusta simultaneamente
dia, mês e ano
− Imprime data
Figura 2.3: Uma data, seus atributos e operações
Uma data conforme o modelo acima tem os atributos dia, mês e ano, que representam valores distintos
com faixas de valores aceitáveis distintas. O mês pode ser representado por um valor numérico de 1 a 12
ou pelos nomes dos meses (“Janeiro”, “Fevereiro”, etc.).
Pode-se imaginar que algumas das operações da classe que implementa o modelo data são redundantes -
para que ajustar ou inicializar os valores dia, mês e ano através de operações quando podemos fazer isto
diretamente ?
A resposta é simples: quando a classe for implementada em uma linguagem de programação, os atributos
serão representados por tipos de dados dependentes da linguagem de programação. Por exemplo, o valor
dia será representado por um valor numérico, que pode representar valores numa faixa muito mais ampla
do que o necessário para representar um dia. Isso significa que um usuário da classe data poderia, por
desatenção, atribuir o valor 45 ao dia.
Para impedir que valores indevidos sejam colocados nos atributos, podemos fazer com que eles passem
por um “filtro”, que são operações que, antes de atribuir valores à atributos, verificam se estes valores são
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
12
realmente válidos. Uma versão simplificada da operação ajusta_dia2 na classe data poderia verificar se
um valor passado pelo usuário é adequado, e caso não seja, mostre uma mensagem de erro.
As operações consideradas neste exemplo permitem que valores sejam atribuídos separadamente para os
atributos dia, mês e ano, ou todos de uma vez através da operação ajusta_dia_mês_ano. É posível tam-
bém solicitar às instâncias da classe data que imprimam os valores através da operação imprime_data.
O modelo do próximo exemplo representa uma registro acadêmico simplificado de um aluno em uma fa-
culdade. Esta ficha contém os atributos nome, número_de_matrícula, data_de_nascimento, ano (em
que se encontra no curso), turma e é_bolsista. Podemos pensar neste registro como um formulário a
ser preenchido com os valores acima. A figura 2.4 mostra os atributos e operações de uma classe que
implementa este registro.
Atributos Operações
− Nome − Entra os dados
− Número de Matrícula − Imprime os dados
− Data de Nascimento − Calcula a mensalidade
− Ano
− Turma
− Tem bolsa de estudos ?
Figura 2.4: Um registro de aluno, seus atributos e operações
Na figura 2.4, além dos atributos descritos anteriormente, temos as operações entra_dados, que seria en-
carregada de verificar se dados passados por um usuário são condizentes com os esperados dentro da classe,
e a operação imprime_dados que poderia imprimir os dados da classe formatados como um relatório.
Uma operação interessante que pode ser definida nesta classe é a calcula_mensalidade que, a partir dos
valores dos atributos ano (em que se encontra no curso) e é_bolsista de uma instância da classe, calcule
o valor da mensalidade a ser paga. Este é mais um exemplo de uso das operações embutidas em um objeto
- ao invés de entrarmos o valor da mensalidade manualmente em um registro acadêmico de aluno (no mo-
delo do mundo real), possibilitamos que valores da mensalidade sejam calculados pela classe (usando uma
linguagem de programação e o conceito de operações).
Consideremos o seguinte exemplo: uma empresa de computadores pessoais oferece, via uma loja virtual
na Internet ou um catálogo de vendas por encomenda, a possibilidade do usuário escolher a configuração
exata do computador que quer comprar. Para isto, criou uma classe para representar os computadores,
mostrada na figura 2.5.
2 Osnomes dados às operações são diferentes dos mostrados nas figuras dos exemplos: os nomes mostrados nos textos
seguem regras das linguagens de programação enquanto os das figuras são mais descritivos.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
13
Atributos Operações
− Processador − Entra os dados
− MB de memória RAM − Imprime os dados
− GB de disco − Calcula o preço
− Tamanho do monitor
Na figura 2.5 temos todos os atributos necessários para configurar o computador, além das operações
entra_dados, usada para que um cliente entre os dados do computador que quer, imprime_dados, para
impressão de um relatório de compras ou nota fiscal e calcula_preço para que o preço seja calculado de
acordo com a configuração escolhida.
Da mesma maneira que com a classe data mostrada no exemplo 2, poderíamos dispensar as operações
entra_dados e imprime_dados, mas poderíamos ter um problema similar: considerando que cada mo-
delo de computador tem uma limitação na quantidade de memória RAM que pode ter, seria imprudente
deixar que um usuário entrasse um valor arbitrário no campo quantidade_memória_RAM. Da mesma ma-
neira, existem apenas poucos tipos de monitores de vídeo, e o usuário não deveria escolher à vontade, mas
somente um dos tipos disponíveis. A garantia de que somente valores válidos serão entrados nos atributos
pode ser feita através de operações que verificam os valores entrados, filtrando os não-válidos.
Como último exemplo nesta seção, consideremos um modelo de uma conta bancária simples, que tem so-
mente um correntista e não tem outras contas vinculadas. A figura 2.6 mostra um modelo gráfico deste
modelo, com os atributos e operações considerados importantes para ele.
Atributos Operações
− Nome do correntista − Abre a conta
− Número da conta (entra os dados)
− Data de abertura − Retira valor
− Saldo − Deposita valor
− É conta especial ? − Imprime o saldo
Na figura 2.6 temos os atributos que definem uma conta bancária e algumas operações que são variações
de outras já vistas em outros exemplos nesta seção. Duas operações interessantes são deposita_valor
e retira_valor: a primeira adiciona um valor ao atributo saldo enquanto que a segunda subtrai, mas
ambas devem implementar mecanismos que garantam o funcionamento correto da classe: devem proibir
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
14
o depósito de valores negativos e retirada de valores acima do saldo, exceto quando a conta for especial
(atributo é_conta_especial).
Exercício 2.2: ?
Escreva uma classe que represente uma hora (incluindo minutos e segundos). Dica: use o exemplo 2 da
seção 2.5 (figura 2.3) como referência.
Exercício 2.3: ?
Usando a classes criada no exercício 2.2 e a classe data mostrada no exemplo 2 da seção 2.5, crie uma
classe datahora que represente simultaneamente uma data e uma hora. Dica: não é necessário reescrever
classes, basta aproveitar classes já existentes nas que serão criadas (veja o exemplo 3 da seção 2.5 e a
figura 2.4).
Exercício 2.4: ?
Escreva uma classe que represente um livro, do ponto de vista de uma biblioteca. Que atributos e opera-
ções devem ser representados pela classe ? (veja também o exercício 2.5).
Exercício 2.5: ?
Escreva uma classe que represente um livro, do ponto de vista de uma livraria. Que atributos e operações
devem ser representados pela classe ? (veja também o exercício 2.4).
Exercício 2.6: ?
Usando como base os exercícios 2.4 ou 2.5, escreva uma classe dicionário para representar dicionários
de línguas (ex. português-inglês, latim-aramaico, etc.) Que atributos e operações devem ser representados
pela classe ? Quais as diferenças entre a classe usada como referência e a classe dicionário ?
Exercício 2.7: ?
Escreva uma classe professor, nos moldes da classe registro_acadêmico (veja o exemplo 3 da se-
ção 2.5 e figura 2.4) que contenha dados relativos à um professor de uma disciplina qualquer.
Exercício 2.8: ?
Neste capítulo vimos algumas classes que contém atributos e operações ou somente atributos, mas tam-
bém é possível o desenvolvimento e uso de classes que contenham somente operações. Escreva uma
classe arremesso_de_dado, que modele o resultado de um dado arremessado (ou seja, um valor aleató-
rio), usando somente operações (não é necessário armazenar os resultados, somente imprimí-los).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
15
Exercício 2.9: ?
Considerando o exercício 2.8, imagine uma classe variante da classe arremesso_de_dado, que armazene
quantas vezes um número saiu a cada vez que o dado foi arremessado. Para isto, alguns atributos e
operações deverão ser criados. Crie esta classe variante da classe arremesso_de_dado.
Exercício 2.10: ?
Crie uma classe carta_de_baralho. Dica: como supomos que instâncias desta classe não deverão
mudar seus atributos depois de criadas, esta classe deverá ter atributos (em contraste com a classe
arremesso_de_dado do exercício 2.8).
Exercício 2.11: ?
Escreva uma classe que represente um time_de_futebol. Que atributos e operações devem ser repre-
sentados pela classe ?
Exercício 2.12: ?
Escreva uma classe que represente uma música (para uso em um banco de dados sobre músicas, por
exemplo). Que atributos e operações devem ser representados pela classe ?
Exercício 2.13: ?
Escreva uma classe que represente um ponto no espaço cartesiano de duas dimensões. Dica: imagine um
gráfico no qual você tenha que marcar ou desenhar pontos, que serão instâncias desta classe ponto. Que
atributos e operações devem ser representados por esta classe ?
Exercício 2.14: ? ?
Escreva uma classe relógio_despertador que use duas instâncias da classe hora (exercício 2.2) para
representar a hora atual e a hora em que o despertador deverá tocar. Que atributos e operações devem ser
representados por esta classe ?
Exercício 2.15: ? ?
Considerando o exercício 2.13, escreva uma classe linha que una duas instâncias da classe ponto. Que
atributos e operações devem ser representados por esta classe ?
Exercício 2.16: ? ?
Escreva uma classe que represente um polígono. Que atributos e operações devem ser representados
pela classe ? Inclua operações para calcular alguns associados ao polígono (área, perímetro, etc.). Quais
seriam as diferenças entre as instâncias quadrado e triângulo da classe polígono ?
Exercício 2.17: ? ?
Considere a figura 2.1. Nela, vários tipos de veículos estão representados, mas podemos ver que os
exemplos fazem parte de duas categorias principais: veículo_aéreo e veículo_terrestre. Escreva
as classes veículo_aéreo e veículo_terrestre, comentando as diferenças e pontos comuns entre as
classes.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
16
Exercício 2.18: ? ?
Considere a classe criada no exercício 2.11. Escreva uma classe partida_de_futebol usando
dois time_de_futebol. Que atributos e operações adicionais seriam necessários para a classe
partida_de_futebol ? Dica: evite reescrever a classe time_de_futebol.
Exercício 2.19: ? ?
Escreva uma classe que represente um CD_de_música, usando várias instâncias da classe música (desen-
volvida no exercício 2.12). Considere que diversas instâncias desta classe podem ser criadas, e algumas
instâncias da classe CD_de_música podem conter somente uma ou duas instâncias de música, outras
podem conter mais de vinte instâncias de música. Como resolver este problema ?
Exercício 2.20: ? ? ?
Escreva uma classe que represente uma equação do segundo grau. Que atributos e operações devem ser
definidos nesta classe ? Como fazer com que a classe represente as três possibilidades de solução destas
equações (∆ < 0, ∆ = 0 e ∆ > 0) ?
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
17
Capítulo 3
3.1 Introdução
No capítulo 2 vimos como programação orientada a objetos pode ser usada para modelagem de objetos
reais ou não para representação em programas de computador. Este capítulo apresenta a complementação
prática à teórica, através da explicação dos conceitos relativos à implementação de classes e objetos em
Java.
Para melhor aproveitamento destas aulas você deve ter acesso a um computador com o compilador e inter-
pretador Java instalados e um editor de textos apropriado. Veja no apêndice C informações sobre onde o
ambiente gratuito de desenvolvimento pode ser encontrado para download ou cópia.
FCC/UNIVAP Alunos da FCC/Univap já tem o JDK instalado e pronto para o uso: uma versão
atual do JDK e do editor de textos sugerido já está instalada nos computadores rodando Linux ou
terminais que possibilitem o acesso à contas no Linux nos laboratórios de informática da Faculdade de
Ciência da Computação.
Ao digitar uma classe ou programa em Java, alguns cuidados devem ser tomados:
• Ao gravar o arquivo que contém a classe, a extensão dada deve ser .java - em sistemas operacio-
nais que fazem distinção entre nomes e extensões maiúsculas e minúsculas, a extensão deve ser em
minúsculas. Cuidado especial deve ser tomado com editores de texto que tentam colocar extensões
próprias nos arquivos gravados por eles.
• Java considera que caracteres maiúsculos e minúsculos são diferentes em programas: nomes dos
identificadores nos programas são considerados diferentes se qualquer dos seus caracteres for dife-
rente. Por exemplo, os identificadores nome, Nome, NOME e NoMe são considerados diferentes, e uso
indiscriminado das diversas formas pode gerar erros de compilação.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
18
• Em muitas estruturas de classes e programas, chaves ({ e }) são usadas para marcar blocos dos
programas. Para cada símbolo { deve haver um símbolo } correspondente, caso contrário erros de
compilação podem ocorrer.
• Todos os comandos em Java (declarações, chamadas de métodos, etc.) são terminados por pontos-e-
virgulas (;), mas algumas definições (nomes das classes, nomes e argumentos dos métodos, decla-
rações de laços, etc.) não devem ser terminados por pontos-e-virgulas - descuido na colocação dos
pontos-e-virgulas pode levar a erros de compilação e execução.
• É extremamente aconselhável que se coloque cada classe em Java em um arquivo separado, ou seja,
que se evite colocar todos os programas e classes em um único arquivo. Adicionalmente, colocar
cada classe em um arquivo com o nome da classe é também aconselhável - por exemplo, uma classe
chamada aluno deve ser escrita no arquivo aluno.java.
A estrutura básica de uma classe é mostrada na listagem 3.1. Esta classe está completamente vazia, mas
sua sintaxe está correta, e ela pode ser compilada pelo compilador sem problemas.
• Toda classe em Java começa com a palavra mágica class, que deve ser digitada totalmente em letras
minúsculas (linha 5 da listagem 3.1).
• Após a palavra class, o nome da classe deve ser digitado. Este nome não pode conter espaços,
deve começar com uma letra, podendo ter números e o caracter sublinhado (_) em seu nome (li-
nha 5 da listagem 3.1). Tradicionalmente os primeiros caracteres de cada palavra do nome da clas-
se são em caracteres maiúsculos, como, por exemplo, NomeDaClasse, IdentificaçãoDoAluno,
UmNomeDeClasseExcessivamenteLongo ou Data, mas basta que as regras sejam seguidas para que
seja um nome de classe válido.
• O corpo de uma classe começa com o caracter { (linha 6 da listagem 3.1) e termina com o caracter }
(linha 8 da listagem 3.1) - o que estiver entre estes dois caracteres será parte da classe.
• Comentários podem aparecer livremente em qualquer parte do arquivo que contém as classes. Co-
mentários serão ignorados pelo compilador, mas, quando bem escritos, servem para dar valiosas
informações sobre o código.
Existem dois tipos de comentários mais usados em Java: comentários em uma linha são comentá-
rios que começam com os caracteres //, e são ignorados pelo compilador até o final da linha onde
aparecem (linha 3 da listagem 3.1), e comentários em múltiplas linhas, que são comentários que são
iniciados com os caracteres /* e se extendem até a próxima ocorrência dos caracteres */ (linhas 1
a 4 da listagem 3.1).
• Não existe uma obrigatoriedade nos espaçamentos e tabulações das linhas e comandos dos progra-
mas, embora estas sejam importantes para a clareza do programa.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
19
De posse destas informações básicas a respeito da criação de classes, e conhecendo a estrutura básica
de uma classe, vamos implementar a teoria do capítulo 2 em Java. Para isto precisamos entender como
podemos implementar os atributos e operações dos modelos em Java.
Uma diferença fundamental entre a teoria mostrada no capítulo 2 e a prática (implementação das classes
em Java) é que precisamos escolher entre um número limitado de tipos de dados, que tem características
bem definidas, e que são dependentes da linguagem. Para referência rápida, a tabela 3.1 sumariza os tipos
básicos de dados de Java com alguns exemplos. O apêndice A apresenta mais detalhes sobre os tipos bási-
cos e algumas classes padrão de Java.
Vale a pena lembrar que um dos conceitos básicos de programação orientada a objetos é a criação de novas
classes que modelam entidades diferentes, e instâncias destas novas classes podem ser usadas em outras
classes e programas.
– Variáveis criadas dentro de uma classe mas fora dos métodos (como nos exemplos que serão
mostrados abaixo) podem ser vistas e modificadas de dentro de todos os métodos da classe.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
20
– Variáveis passadas como argumentos para os métodos só são válidas dentro dos métodos.
• É aconselhável que o nome das variáveis represente de forma sumarizada o seu significado no pro-
grama, para maior clareza.
Alguns exemplos de criação de variáveis podem ser vistos no trecho de código na listagem 3.2.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
21
É importante lembrar que o trecho de código na listagem 3.2 não pode ser compilado, porque deveria estar
dentro de uma classe como a mostrada na listagem 3.1). Muitos outros exemplos de declaração, atribuição
e uso de variáveis em Java podem ser vistos no apêndice A.
Métodos são blocos de código, presentes dentro das classes, que podem processar dados desta classe e
dados que são passados como argumentos para os métodos. Algumas informações sobre métodos em Java
são mostradas abaixo:
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
22
Alguns exemplos de métodos podem ser vistos no trecho de código na listagem 3.3.
É importante lembrar que o trecho de código na listagem 3.3 não pode ser compilado, porque deveria estar
dentro de uma classe como a mostrada na listagem 3.1).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
23
Considerando a figura 2.2 da seção 2.5, vemos que temos que representar um estado de uma lâmpada, que
pode ser ou apagada ou acesa. Java (e outras linguagens de programação) não tem como representar os
conceitos “aceso” e “apagado”, mas podemos usar um valor tipo booleano para indicar se a lâmpada está
acesa ou apagada.
Para modelar as operações que acendem e apagam a lâmpada, criamos métodos correspondentes que mu-
dam o estado (variável booleana). A primeira versão da classe Lampada é mostrada na listagem 3.4.
Considerando a figura 2.3 da seção 2.5, vemos que temos que representar os valores dia, mês e ano como
componentes de uma data. Dia e mês podem ser representados por um byte cada (uma vez que os valores
válidos para o dia e o mês podem ser confortavelmente representados na faixa dos valores do byte, -128 a
127), e ano pode ser representado por um valor do tipo short (permitindo assim a representação de anos de
-32768 a 32767).
Para modelar as operações que ajustam e imprimem a data, criamos métodos correspondentes. A primeira
versão da classe Data é mostrada na listagem 3.5.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
24
5 deve ser representado por um short para permitir representação de anos completos (1999,
6 2000, etc). Note que as variáveis são private e só poderão ser manipuladas pelos métodos
7 desta classe. */
8 private byte dia,mês;
9 private short ano;
10 /* Este método permite que ajustemos o dia da data. Basicamente ele passa à variável dia
11 da classe o argumento passado ao método. */
12 void ajustaDia(byte d)
13 {
14 dia = d;
15 }
16 /* Este método permite que ajustemos o mês da data. Basicamente ele passa à variável mês
17 da classe o argumento passado ao método. */
18 void ajustaMês(byte m)
19 {
20 mês = m;
21 }
22 /* Este método permite que ajustemos o ano da data. Basicamente ele passa à variável ano
23 da classe o argumento passado ao método. */
24 void ajustaAno(short a)
25 {
26 ano = a;
27 }
28 /* Este método permite que ajustemos simultaneamente o dia, mês e ano da data. Este método
29 chama os outros métodos declarados anteriormente, para simplificar. */
30 void ajustaData(byte d,byte m,short a)
31 {
32 ajustaDia(d); // chama o método ajustaDia com o argumento d
33 ajustaMês(m); // chama o método ajustaMês com o argumento m
34 ajustaAno(a); // chama o método ajustaAno com o argumento a
35 }
36 /* Este método imprime a data. */
37 void imprime()
38 {
39 System.out.print("Dia:"+dia+" ");
40 System.out.print("Mês:"+mês+" ");
41 System.out.println("Ano:"+ano);
42 }
43 /* Este método retorna a data formatada como uma String. */
44 String formata()
45 {
46 String temporária = "Dia:"+dia+" Mês:"+mês+" Ano:"+ano;
47 return temporária;
48 }
49 } // fim da classe Data
Na classe na listagem 3.5 (linhas 39 a 41) dois métodos chamados System.out.print e System.out.println
são usados. Estes métodos imprimem no terminal os valores dos argumentos passados, como instâncias
da classe String. A diferença entre os dois métodos é que o segundo imprime, além dos argumentos, uma
quebra de linha (caracter de controle \n). Caso existam mais do que um argumento para estes métodos,
eles devem ser concatenados com o sinal +, de acordo com as regras explicadas na seção A.2.1 (veja o
programa na listagem A.19 para mais informações e exemplos).
Considerando a figura 2.4 da seção 2.5, vemos que temos que representar vários dados relativos à um re-
gistro acadêmico de aluno, de diferentes tipos, em uma classe. Um destes dados (a data de nascimento)
pode ser representado pela classe Data, descrita anteriomente, e os outros podem ser representados por
tipos nativos de Java.
Para modelar as operações que preenchem os dados e os imprimem, criamos métodos correspondentes.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
25
Também criamos um método que calcula e retorna a mensalidade devida por este aluno. A primeira versão
da classe RegistroDeAluno é mostrada na listagem 3.6.
Na listagem 3.6, linhas 40 e 41 e linhas 48 e 49 vamos a estrutura de tomada de decisões if/else, que
será esclarecida no capítulo 8, seção 8.3.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
26
Considerando a figura 2.5 da seção 2.5, vemos que os atributos que definem um modelo de computador são
seu processador, sua memória, o tamanho de seu disco e monitor. Além de criar estas variáveis na classe
que representará o modelo de computador, devemos criar métodos para inicializar os dados (ou configurar
o computador), imprimir a configuração e calcular o preço daquela configuração.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
27
Nas linhas 36 e 37 da listagem 3.7 vemos o uso do método equals da classe String. Este método compara
duas Strings, retornando true se elas forem iguais. Este e outros métodos da classe String são apresentados
no capítulo 9.
Nas linhas 39 a 41, 43 a 45 e 47 a 49 da listagem 3.7 vemos como valores e variáveis de tipos nativos em
Java podem ser comparados usando o sinal ==. Mais informações sobre comparações podem ser vistas no
capítulo 8.
Considerando a figura 2.6 da seção 2.5, vemos que temos que representar os atributos nome, número da
conta, saldo, é especial e data de abertura, juntamente com métodos que nos permitam a inicialização dos
dados da conta, impressão dos mesmos e retiradas e depósitos da conta.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
28
43 {
44 saldo = saldo - valor;
45 }
46 /* Este método retorna o saldo da conta bancária, permitindo a "leitura" do valor
47 mas garantindo através dos métodos deposita e retira que modificações só poderão ser
48 feitas controladamente (pela própria classe). */
49 float retornaSaldo()
50 {
51 return saldo;
52 }
53 } // fim da classe ContaBancaria
Exercício 3.2: ?
Considerando a tabela 3.1, escolha o tipo de dado ou classe mais adequada para representar:
Exercício 3.3: ?
Modifique a classe Lampada, descrita no exemplo 1 da seção 2.5 e implementada na listagem 3.4 para que
este também represente o número de watts da lâmpada.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
29
Exercício 3.4: ?
Modifique a classe Lampada, descrita no exemplo 1 da seção 2.5 e implementada na listagem 3.4 para
que esta tenha métodos de saída e impressão do estado da lâmpada (veja também a listagem 3.5, métodos
imprime e formata.)
Exercício 3.5: ?
Escreva uma classe LampadaFluorescente que além dos atributos da classe Lampada (seção 2.5), repre-
sente o tamanho (comprimento) da lâmpada.
Exercício 3.6: ?
O que aconteceria se todos os métodos da classe Data (listagem 3.5) fossem private ?
Exercício 3.7: ?
Modifique a classe Data (listagem 3.5) para que esta contenha métodos que permitam o acesso às variá-
veis dia, mês e ano. Estes métodos devem retornar o valor das variáveis.
Exercício 3.8: ?
Modifique a classe Data (listagem 3.5) para que esta represente o mês com Strings ao invés de valores
numéricos.
Exercício 3.9: ?
Escreva um método para a classe Data (listagem 3.5) que formate os valores da classe como DD/MM/AAAA
onde DD é o dia, MM é o mês e AAAA é o ano. Não se preocupe com o número de posições que cada variável
pode ocupar, o importante é que estejam separados por barras. Este método deve ter um nome diferente
de formata.
Exercício 3.10: ?
O método calculaPreço da classe ModeloDeComputador (listagem 3.7) reconhece somente alguns mo-
delos de processador, quantidade de memória e disco e tamanhos de monitor. Modifique este método para
que mais alguns modelos de processador e opções de memória, disco e monitor sejam reconhecidos.
Exercício 3.11: ?
Escreva uma classe Contador que encapsule um valor usado para contagem de itens. Esta classe deve ter
os métodos incrementa (que incrementa o valor do contador em um) e reseta (que zera o contador).
Exercício 3.12: ?
Escreva uma classe Hora que represente, em Java, o modelo do exercício 2.2. Crie ao menos dois métodos
na classe, um para inicializar os dados e outro para imprimi-los.
Exercício 3.13: ?
Escreva uma classe LivroBiblioteca que represente, em Java, o modelo do exercício 2.4.
Exercício 3.14: ?
Escreva uma classe LivroLivraria que represente, em Java, o modelo do exercício 2.5.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
30
Exercício 3.15: ?
Escreva uma classe PontoCartesiano que represente, em Java, o modelo do exercício 2.13. Que variá-
veis e métodos esta classe deve ter ? Inclua também métodos que permitam a um programa ou classe
recuperar as coordenadas dos pontos (veja a listagem 3.8, método retornaSaldo, como exemplo).
Exercício 3.16: ?
Escreva uma classe AutomovelUsado que encapsule os dados de um automóvel usado à venda (modelo,
marca, cor, ano, quilômetros rodados, preço, se é a álcool ou gasolina, etc) - que tipos de dados ou
instâncias de classes devem ser usados para representar estes dados ? Crie ao menos dois métodos na
classe, um para inicializar os dados e outro para imprimi-los.
Exercício 3.17: ?
Escreva uma classe Pais que represente, em Java, os dados de um país (nome, área, população, nome da
moeda corrente e outros dados relativos à um país). Que variáveis e métodos esta classe deve ter ?
Exercício 3.18: ?
Escreva uma classe AgendaTelefonica que represente, em Java, as entradas em uma agenda telefônica,
com o nome, endereço, telefone, e-mail, etc. de uma pessoa. Que variáveis e métodos esta classe deve
ter ?
Exercício 3.19: ?
Identifique, explique e corrija três erros na classe abaixo.
1 class Lampada Errada
2 {
3 private boolean acesa;
4 private void acende()
5 {
6 acesa = 1;
7 }
8 private void apaga()
9 {
10 acesa = 0;
11 }
12 }
Exercício 3.20: ?
Identifique, explique e corrija três erros na classe abaixo.
1 class Livro
2 {
3 private string título,autor;
4 void inicializa(string t)
5 {
6 título = t1;
7 void inicializa(String a)
8 {
9 autor = a;
10 }
11 }
12 }
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
31
Exercício 3.21: ? ?
Modifique a classe Lampada (listagem 3.4) para que esta também seja capaz de armazenar em um valor
inteiro o número de vezes que foi acesa. Onde você modificaria este valor ?
Exercício 3.22: ? ?
Modifique a classe Data (listagem 3.5) para que os métodos ajustaDia, ajustaMês e ajustaAno veri-
fiquem se os dados passados são ao menos coerentes: os métodos só devem alterar os valores da classe
caso o dia esteja entre 1 e 31, o mês esteja entre 1 e 12 e o ano, positivo. Caso um valor errado seja
passado para os métodos, estes devem imprimir uma mensagem de erro.
Exercício 3.23: ? ?
Modifique a classe RegistroDeAluno (listagem 3.6) para que esta contenha um atributo adicional que
represente o curso do aluno. Que tipo de dado ou classe será apropriado para representar o curso ?
Modifique todos os métodos que recebem e imprimem dados para que este novo atributo seja levado em
consideração.
Exercício 3.24: ? ?
Considerando o exercício 3.23, modifique novamente a classe RegistroDeAluno (listagem 3.6) para que
o cálculo da mensalidade leve em conta o curso no qual o aluno está matriculado. Use como referência o
método calculaPreço da classe ModeloDeComputador (listagem 3.7). Invente uns três ou quatro cursos,
cada um com um valor de mensalidade diferente, para que o exercício fique mais interessante.
Exercício 3.25: ? ?
Usando a classe RegistroDeAluno (listagem 3.6) como referência, crie a classe Professor que deve
representar um professor usando os atributos: nome, número de registro, idade, data de admissão, nome
da faculdade, salário.
Exercício 3.26: ? ?
O método calculaPreço da classe ModeloDeComputador (listagem 3.7) reconhece algumas variações
nos componentes do computador, mas o método configura da mesma classe permite que qualquer valor
seja aceito. Modifique o método configura para que este somente aceite as variações reconhecidas. Veja
também o exercício 3.10.
Exercício 3.27: ? ?
Valores de ponto flutuante podem, dependendo de algumas operações efetuadas com eles, perder par-
te de sua precisão (veja a seção A.1.6 e a listagem A.13). Considerando isto, modifique a classe
ContaBancaria (listagem 3.8) para que esta represente o saldo da conta em centavos ao invés de re-
ais, usando um tipo inteiro apropriado. Modifique o método imprime para que este imprima o valor em
reais e não centavos.
Exercício 3.28: ? ?
Escreva uma classe DataHora que represente, em Java, o modelo do exercício 2.3. Crie ao menos dois
métodos na classe, um para inicializar os dados e outro para imprimi-los. Para ambos, reutilize os métodos
já existentes nas classes Data e Hora.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
32
Exercício 3.29: ? ?
Escreva uma classe Musica que represente, em Java, o modelo do exercício 2.12. Entre outros atributos,
represente a duração da música usando uma instância da classe Hora, feita no exercício 3.12.
Exercício 3.30: ? ?
Escreva uma classe LinhaCartesiana que represente, em Java, o modelo do exercício 2.15. Que va-
riáveis e métodos esta classe deve ter ? Use a classe PontoCartesiano, desenvolvida no exercício 3.15
como base.
Exercício 3.31: ? ?
Usando os exercícios 3.15 e 3.30 como base, crie a classe Retangulo que usa dois pontos para representar
um retângulo.
Exercício 3.32: ? ? ?
Como você poderia modificar a classe Lampada (listagem 3.4) para que esta também representasse o
estado queimada ? Reescreva a classe de maneira que os métodos acende e apaga sejam executados de
maneira diferente caso a lâmpada esteja queimada.
Exercício 3.33: ? ? ?
Considerando o exercício 3.24, modifique novamente a classe RegistroDeAluno (listagem 3.6) de for-
ma que o método entraDados imprima uma mensagem de erro caso seja chamado com um curso não
reconhecido passado como argumento.
Exercício 3.34: ? ? ?
Os métodos deposita e retira da classe ContaBancaria (listagem 3.8) podem ser usados incorreta-
mente - alguém pode tentar depositar um valor negativo, ou retirar mais dinheiro do que existente na conta
bancária. Se a conta for especial (de acordo com a variável éEspecial) mais dinheiro do que existe na
conta pode ser retirado, até um limite de 100 reais. Modifique os métodos deposita e retira da classe
ContaBancaria para que corrijam este problema.
Exercício 3.35: ? ? ?
Usando os exercício 3.31 como base, adicione métodos que calculem e retornem a área e perímetro do
retângulo representado na classe.
Escreva uma classe em Java que represente um número complexo, e contenha quatro métodos que rece-
bam instâncias de números complexos para as quatro operações simples. Estes métodos devem retornar
instâncias da classe que representa os números complexos. O método soma deve ser declarado como
NumeroComplexo soma(NumeroComplexo y) e deve somar os dados da classe com os da instância y.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
33
Capítulo 4
4.1 Introdução
No capítulo anterior, vimos como podemos criar classes em Java que representam modelos. Embora as
classes criadas nos exemplos e exercícios anteriores possam ser compiladas, estas não podem ser exe-
cutadas. Neste capítulo veremos como criar métodos especiais nas classes que permitam a execução de
programas em Java.
O modificador public já foi visto na seção 3.2.2: o uso deste modificador garantirá que o método poderá
ser usado de fora da classe que o contém, o que é uma exigência da máquina virtual Java para a execução
do método.
O modificador static permite que usemos métodos de classes sem que seja preciso criar instâncias destas
classes. A maioria dos programas que criaremos serão classes que conterão somente o método main, e não
será necessária a criação de instâncias destas classes. A seção 4.5 mostrará outros usos do modificador
static.
O método main tem void como tipo de retorno, ou seja, nenhum valor é retornado.
Os argumentos String args[] representam um array de Strings que serão passados para o método main.
Um array é uma forma conveniente de armazenarmos vários valores do mesmo tipo em uma única variável,
que usará um índice para que os diferentes valores sejam acessados. Arrays são descritos no capítulo 10. O
array passado para o método main será composto dos valores passados pela linha de comando, conforme
será demonstrado na seção 4.4.
É possível criarmos o método main nas próprias classes que representam modelos (como por exemplo, as
classes Data e ContaBancaria), mas além de confuso, esta abordagem não demonstra as possibilidades
de uso de instâncias de diversas classes em programas. Para mais clareza e melhor entendimento dos con-
ceitos de programação orientada a objetos, é sugerido que o método main não seja colocado nas classes
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
34
usadas para representar modelos, e sim em classes separadas, que provavelmente conterão somente este
método, como mostrado nos exemplos na próxima seção.
Esta seção mostra um programa mínimo em Java, o tradicional hello world. O programa na listagem 4.1
imprime no console a mensagem Alô, Mundo !.
Alguns pontos de interesse do programa na listagem 4.1 são mostrados na lista abaixo:
Um outro exemplo de classe que pode ser executada por conter um método main com os modificadores,
valor de retorno e argumentos apropriados é mostrado no programa na listagem 4.2). O programa cria
alguma instâncias da classe Lampada (listagem 3.4) e modifica estado das instâncias. Os comentários do
programa explicam o que está sendo feito, linha a linha.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
35
Um outro exemplo de classe que pode ser executada é mostrado na listagem 4.3). O programa desta lis-
tagem cria alguma instâncias da classe Data (listagem 3.5) e as usa para inicialização e impressão. Os
comentários do programa explicam o que está sendo feito, linha a linha.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
36
Além de criar referências para instâncias das classes e alocar memória para estas, a palavra-chave new cha-
ma um de alguns métodos especiais da classe que está sendo referenciada. Estes métodos são conhecidos
como construtores e são explicados com detalhes no capítulo 7.
Valores da linha de comando são passados para o programa como Strings, mesmo que aparentemen-
te representem valores inteiros, booleanos ou de ponto flutuante. Um programa chamado como java
NomeDaClasse 1 3.1416 true passará para o array de Strings que é argumento do método main três
Strings: “1”, “3.1416” e “true”.
Podemos contar quantos elementos existem em um array (e consequentemente quantos argumentos foram
passados pela linha de comando para um programa em Java) usando o atributo length dos arrays. O
programa na listagem 4.4 mostra como podemos contar o número de argumentos passados. Mais detalhes
sobre processamento de arrays serão mostrados no capítulo 10.
Listagem 4.4: Um programa que conta quantos argumentos foram passados pela linha de comando
1 /* Classe executável que mostra quantos argumentos foram passados pela linha de comando */
2 class LinhaDeComando
3 {
4 /* Método main que possibilita a execução da classe */
5 public static void main(String parâmetros[])
6 {
7 // Imprime mensagem com o número de argumentos passados.
8 System.out.println("Foram passados "+parâmetros.length+" argumentos.");
9 if (parâmetros.length > 1)
10 System.out.println("O primeiro argumento é "+parâmetros[0]+".");
11 }
12 } // fim da classe LinhaDeComando
O programa na listagem 4.4, quando executado, mostra o número de argumentos passados pela linha de
comando, e caso ao menos um argumento tenha sido passado, imprime o primeiro argumento.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
37
A primeira aplicação pode ser demonstrada com um programa que necessita, de seu método main, chamar
várias vezes um trecho de código que pode ser transformado em uma subrotina. Esta subrotina (e qualquer
outra que deva ser chamada do método main sem ser via uma instância de uma classe) deve ser declarada
com o modificador static. Um exemplo de classe com subrotina é mostrada na listagem 4.5.
• Subrotinas podem ser declaradas antes ou depois do método main, e não precisam de protótipos
como em C ou C++.
• Subrotinas que serão chamadas de dentro do método main devem ser declaradas como static.
• Subrotinas são métodos, então seguem as mesmas regras de nomes e declarações mostradas na se-
ção 3.2.2.
• Métodos estáticos (subrotinas) podem ser chamados de outros métodos estáticos, mas cuidado es-
pecial deve ser tomado para que as chamadas não se tornem recursivamente infinitas, como no pro-
grama na listagem 4.6. Neste caso, um método chama o outro que chama o primeiro infinitamente
(embora a máquina virtual Java indique um erro de estouro de pilha).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
38
• É possível a declaração de variáveis estáticas: se declaradas dentro da classe mas fora de todos os
métodos, estas variáveis serão visíveis de todos os métodos ou subrotinas de uma classe. Podemos
declarar variáveis estáticas para servirem de variáveis globais dentro da classe, mas esta prática não
é recomendada (veja o exercício 4.10). O programa na listagem 4.7 mostra a declaração e uso de
variáveis estáticas.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
39
É possível criar classes compostas inteiramente de variáveis e métodos estáticos. Esta classe não precisaria
ser instanciada para que suas variáveis e métodos fossem utilizados em outras classes e programas. Estas
classes puramente estáticas podem ser usadas como bibliotecas de constantes e funções, como mostrado
na classe na listagem 4.8.
O programa na listagem 4.9 usa variáveis e métodos da classe BibliotecaDeConstantes (listagem 4.8).
Nota-se que em nenhum momento instâncias da classe BibliotecaDeConstantes são criadas - suas va-
riáveis e métodos são usados diretamente.
Listagem 4.9: Um programa que usa a classe com algumas variáveis e métodos estáticos
1 /* Esta classe usa as constantes e métodos estáticos na classe BibliotecaDeConstantes.
2 */
3 class TesteBibliotecaDeConstantes
4 {
5 /* Este é o método main, que será o ponto de entrada na execução do programa. */
6 public static void main(String args[])
7 {
8 // crio uma variável que valerá (pi * e) e a imprimo
9 double meuvalor = BibliotecaDeConstantes.pi * BibliotecaDeConstantes.e;
10 System.out.println("Pi * e = "+meuvalor);
11 // imprimo algumas operações com pi
12 System.out.println("Pi/2="+BibliotecaDeConstantes.piDivididoPor(2));
13 System.out.println("Pi/3="+BibliotecaDeConstantes.piDivididoPor(3));
14 System.out.println("Pi/Pi="+BibliotecaDeConstantes.piDivididoPor(BibliotecaDeConstantes.pi));
15 }
16 } // fim da classe TesteBibliotecaDeConstantes
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
40
Exercício 4.2: ?
O programa abaixo apresentará erros de compilação. Explique porquê.
1 class Programa
2 public static void main(String argumentos[])
3 {
4 String nome = "Pablo Picasso";
5 System.out.println("Meu nome é "+nome);
6 }
7
Exercício 4.3: ?
O programa abaixo apresentará erros de compilação. Explique porquê.
1 class Nome da Classe
2 {
3 public static void main(String parâmetros[])
4 {
5 int i = 1000;
6 int j = 33;
7 System.out.print("O resultado da divisão inteira de "+i);
8 System.out.print(" por "+j+" é ");
9 System.out.println(i/j);
10 }
11 }
Exercício 4.4: ?
O programa abaixo poderá ser compilado mas não executado. Explique porquê.
1 class TestePrograma
2 {
3 public static void main()
4 {
5 boolean d;
6 d = (2 > 3);
7 System.out.println("A expressão (2 > 3) é "+d);
8 }
9 }
10
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
41
Exercício 4.5: ?
O programa abaixo poderá ser compilado mas não executado. Explique porquê.
1 class Programa
2 {
3 void main(String parâmetros[])
4 {
5 char a,b,c;
6 a = ’A’; b = ’B’; c = ’C’;
7 System.out.println(""+a+b+c);
8 }
9 }
10
Exercício 4.6: ?
Escreva um programa que contenha o método main e crie algumas instâncias da classe
ModeloDeComputador (listagem 3.7).
Exercício 4.7: ?
Ache e explique o erro no programa abaixo.
1 class Demo
2 {
3 public static void main(String params[])
4 {
5 Data hoje,amanhã;
6 hoje = new Data();
7 hoje.ajustaData((byte)5,(byte)10,(short)1999);
8 amanhã.ajustaData((byte)6,(byte)10,(short)1999);
9 }
10 }
Exercício 4.8: ?
Ache e explique o erro no programa abaixo.
1 class Demo
2 {
3 public static void main(String params[])
4 {
5 Data hoje;
6 hoje = new RegistroDeAluno();
7 hoje.ajustaData((byte)17,(byte)3,(short)1954);
8 }
9 }
Exercício 4.9: ?
O programa da listagem 4.2, ao ser executado, não imprimirá nada no terminal, porque não existem
métodos de saída ou impressão na classe Lampada (listagem 3.4). Modifique a classe Lampada conforme
pedido no exercício 3.4 e o programa na listagem 4.2 para que este mostre o estado das lâmpadas ao final
do programa.
Exercício 4.10: ?
O que aconteceria no programa na listagem 4.7 se declarássemos, dentro do método main, duas variáveis
do tipo double chamadas x e y ?
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
42
Exercício 4.11: ?
O que aconteceria no programa na listagem 4.7 se não declarássemos as duas variáveis x e y como sendo
static na linha 5 ?
Exercício 4.12: ?
O que acontecerá se colocarmos uma linha lâmpadaDoQuarto.ligada = true; no método main do
programa na listagem 4.2 ?
Exercício 4.13: ? ?
Escreva um programa que contenha o método main e crie algumas instâncias da classe RegistroDeAluno
(listagem 3.6).
Exercício 4.14: ? ?
Escreva um programa que contenha o método main e crie algumas instâncias da classe ContaBancaria
(listagem 3.8).
Exercício 4.15: ? ?
Reescreva a classe BibliotecaDeConstantes (listagem 4.8) para que nada nela seja estático. Modifique
também o programa na listagem 4.9 para que este use a classe não-estática.
• 1 polegada = 2,54 cm
• 1 pé = 30,48 cm
• 1 milha = 1,609 km
• 1 metro quadrado = 10,76 pés quadrados
• 1 milha quadrada = 640 acres
• 1 acre = 43.560 pés quadrados
• 1 metro cúbico = 1000 litros = 35,32 pés cúbicos
• 1 galão americano = 3,785 litros
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
43
Capítulo 5
Herança
5.1 Introdução
Em alguns exemplos e exercícios dados até agora vimos que às vezes é necessária a criação de duas classes
distintas mas com muitas características em comum. Ao invés de criarmos estas classes e praticamente
duplicarmos suas variáveis e métodos, podemos usar um conceito de Programação Orientada a Objetos
chamado herança que permite que uma classe herde de outra algumas variáveis e métodos, reduzindo a
necessidade de duplicação.
Herança entre classes em Java é declarada usando a palavra-chave extends. Para que uma classe D herde
as variáveis e métodos da classe C, declaramos a classe D como class D extends C.
Só é permitida a herança de uma classe para outra (ou seja, não existem mecanismos diretos para herança
múltipla em Java), mas é possível termos classes que herdam indiretamente de outras através da herança
em cascata: a classe E pode herdar das classes C e D se a classe E herdar da D e esta, por sua vez, herdar da
classe C.
Herança de classes funciona em um sentido somente: A classe Filho pode herdar da classe Pai e acrescen-
tar métodos e variáveis próprias, mas estas somente valerão para a classe Filho - a classe Pai não sofrerá
modificações nem poderá usar o que foi declarado dentro da classe Filho.
Para demonstrar o conceito de herança através de alguns exemplos, vamos criar uma classe Veiculo (lis-
tagem 5.1).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
44
Uma classe executável que cria várias instâncias da classe Veiculo é mostrada na listagem 5.2.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
45
38 fusca66.imprime();
39 }
40 } // fim da classe TesteVeiculo
No programa na listagem 5.2 podemos notar que algumas instâncias tem muitos dados em comum, parti-
cularmente as instâncias lambreta e fusca66. Estas instâncias, por sua vez, tem muitos dados diferentes
das outras na listagem.
Considerando as similaridades e diferenças entre as instâncias no programa na listagem 5.2, podemos con-
siderar a criação de uma classe específica para representar veículos terrestres. Esta classe teria os mesmos
dados da classe Veículo mas algumas de suas variáveis já estariam com valores definidos que refletiriam
detalhes particulares da classe herdeira.
Uma primeira abordagem para a criação de uma classe específica para veículos terrestres mas que herde da
classe Veiculo é mostrada na listagem 5.3.
Embora a classe VeiculoTerrestre na listagem 5.3 esteja aparentemente vazia, ela tem a mesma funci-
onalidade da classe Veiculo uma vez que todos os dados da classe Veiculo foram herdados pela classe
VeiculoTerrestre. Para confirmar, podemos criar instâncias das duas classes e comparar os resultados,
como mostrado no programa na listagem 5.4.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
46
O resultado do programa na listagem 5.4 mostra que para todos os efeitos as duas classes são idênticas,
mas não demonstra nenhuma vantagem em criar classes herdeiras - não existe diferença no tratamento das
instâncias das classes pai ou ancestral (Veiculo) e herdeira (VeiculoTerrestre).
Uma vantagem por enquanto não aproveitada de termos as classes separadas seria inicializar alguns dados
de instâncias da classe VeiculoTerrestre com valores que raramente mudariam. Nos exemplos acima,
as variáveis éAéreo, éTerrestre e éAquático tem valores diferentes para instâncias da classe Veiculo,
mas podemos considerar que seus valores para instâncias da classe VeiculoTerrestre seriam sempre
false, true e false, respectivamente. Estes valores poderiam ser inicializados automaticamente pelo
método inicializa, herdado da classe Veiculo. A próxima seção mostrará como podemos modificar um
método herdado.
Poderíamos adicionar à classe VeiculoTerrestre um método novo que inicializasse as variáveis éAéreo,
éTerrestre e éAquático de forma padrão, mas teríamos que chamar este método e o método inicializa
sempre que formos criar instâncias da classe VeiculoTerrestre. Uma solução melhor seria usar o meca-
nismo de sobrecarga de programação orientada a objetos, que permite que um método com o mesmo nome,
tipo de retorno e argumentos substitua ou sobreescreva o método herdado da classe pai ou ancestral. A clas-
se VeiculoTerrestre, modificada para ter o método inicializa modificado, é mostrada na listagem 5.5.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
47
14 velocidadeMédia = vm;
15 // Esta parte torna o método inicializa específico para a classe VeiculoTerrestre
16 éAéreo = false;
17 éTerrestre = true;
18 éAquático = false;
19 }
20 } // fim da classe VeículoTerrestre
• A sobrecarga dos métodos somente é feita caso o método tenha o mesmo nome e os valores passados
como argumentos para este método tenham o mesmo tipo. Caso haja alguma diferença entre o
número e tipo de argumentos do método, o método da classe ancestral não será sobreescrito ou
sobrecarregado - continuará sendo um método válido, e dois métodos com o mesmo nome mas tipo
ou número de argumentos diferentes estarão presentes na classe herdeira. O capítulo 6 tratará deste
fato com mais detalhes, e a seção 5.3 mostra alguns exemplos onde a não-sobreescrita de métodos é
útil e desejável..
• Variáveis de uma classe podem ser sobreescritas, bastando para isto redeclarar a variável com um ti-
po novo na classe herdeira. Desta forma, uma classe Ancestral pode ter uma variável boolean
valor; e a classe Descendente, que herda da Ancestral pode redeclarar esta variável como
String valor;.
Um problema sério pode ocorrer no caso de sobrecarga de variáveis: os métodos herdados que não
forem sobreescritos continuarão a considerar a variável da classe ancestral como sendo a válida. Este
problema é exemplificado nas classes da listagem 5.6 onde a classe IdentificacaoNumerica sobre-
escreve uma variável da classe Identificacao. Se instâncias da classe IdentificacaoNumerica
forem criadas, os métodos qualIdent destas instâncias sempre retornarão o valor nulo (null) por
não estarem preparadas para retornar o valor do tipo long que sobreescreveu a String. A solução
neste caso é sobreescrever todos os métodos que processam a variável sobreescrita, o que é pouco
prático.
• Não é possível a criação de um método em uma classe herdeira que tenha o mesmo nome, tipos de
argumentos e tipo de retorno diferente (um erro de compilação é gerado).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
48
17 String qualIdent()
18 {
19 return ident;
20 }
21 } // fim da classe Identificacao
22
23 /* Classe que representa uma identificação numérica */
24 class IdentificacaoNumerica extends Identificacao
25 {
26 long ident; // Note que este sobreescreve a String ident da classe Identificacao !
27 } // fim da classe IdentificacaoNumerica
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
49
40 }
41 /* Método para imprimir */
42 void imprime()
43 {
44 System.out.println("("+x+","+y+","+z+")");
45 }
46 /* Método que permite a leitura da variável z */
47 short qualZ()
48 {
49 return z;
50 }
51 } // fim da classe Ponto3D
O compilador Java reclamará que as variáveis x e y não são acessíveis na classe Ponto3D na listagem 5.7,
impossibilitando o seu uso.
Existem duas maneiras de evitar este problema: a primeira seria evitar o uso de variáveis e métodos priva-
dos em classes que poderão eventualmente ter herdeiras. Este método não é recomendável porque além de
ser recomendável o uso de variáveis privadas em classes, não é tão simples determinar se a classe que está
sendo criada terá ou não herdeiras.
A segunda solução usa um conceito já apresentado anteriormente: Como não podemos acessar variáveis
privadas de classes, pedimos à métodos da própria classe que as acessem. Para o exemplo em questão,
quando formos inicializar as variáveis x e y, ao invés de tentarmos acessar as variáveis diretamente, pe-
diremos ao método void inicializa(short _x,short _y), que foi herdado da classe Ponto2D, que
inicialize as variáveis, conforme mostrado nas classes na listagem 5.8
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
50
32 // Variáveis privadas
33 private short z;
34 /* Método para inicializar */
35 void inicializa(short _x,short _y,short _z)
36 {
37 // Chama o método herdado da classe Ponto2D
38 inicializa(_x,_y);
39 z = _z;
40 }
41 /* Método para imprimir */
42 void imprime()
43 {
44 System.out.println("("+qualX()+","+qualY()+","+z+")");
45 }
46 /* Método que permite a leitura da variável z */
47 short qualZ()
48 {
49 return z;
50 }
51 } // fim da classe Ponto3D
• Ambas as classes Ponto2D e Ponto3D na listagem 5.8 implementam métodos que permitem o aces-
so à variáveis privadas para leitura ou recuperação, no caso, os métodos qualX, qualY e qualZ.
A implementação deste tipo de método é bastante útil, pois não só permite a criação de variáveis
que podem ser lidas livremente mas modificadas somente por métodos específicos quanto também
permite que estes métodos sejam herdados e possam ser utilizados por classes herdeiras.
• A classe Ponto3D herdou todos os métodos da classe Ponto2D, inclusive o método inicializa
com dois argumentos (linhas 7 a 11 da listagem 5.8). Como este método tem número de argumentos
diferentes do método inicializa com três argumentos (linhas 35 a 40), ele não é sobreescrito - os
dois métodos existem na classe Ponto3D, e podemos inclusive chamar um deles de dentro do outro,
como na linha 38 da listagem 5.8, o que possibilita o acesso às variáveis x e y. É possível também
chamarmos o método inicializa com dois argumentos a partir de instâncias da classe Ponto3D.
Detalhes sobre a possibilidade de termos vários métodos com o mesmo nome numa mesma classe
serão mostrados no capítulo 6.
• Uma vez que o método imprime da classe Ponto3D deve imprimir os valores das três variáveis, ele
teve que ser reescrito. Como este método não pode acessar as variáveis x e y herdadas da classe
Ponto2D, os métodos qualX e qualY foram chamados.
• O exemplo mostrado na listagem 5.8 demonstra que uma classe pode herdar todas as variáveis e
métodos de outra e acrescentar suas próprios variáveis e métodos - esta forma de herança, onde uma
classe efetivamente aumenta as capacidades de outra, é a mais comum.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
51
A classe Aluno, mostrada na listagem 5.9, tem vários métodos que permitem o acesso e modificação de
suas variáveis, que são todas privadas.
A classe AlunoMestrado, mostrada na listagem 5.10, usa a classe Aluno como base e adiciona algumas
variáveis e métodos através do mecanismo de herança.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
52
Apesar de boa parte da classe AlunoMestrado ter sido herdada da classe Aluno, vemos que em alguns
casos ainda temos que repetir partes dos métodos. Nos exemplos mostrados, especificamente, temos que
reescrever e repetir boa parte do método imprime na classe AlunoMestrado.
Uma maneira de economizar ainda mais a tarefa de reescrever classes é usar a referência super. Esta
referência funciona como uma instância da classe ancestral que pode ser usada de dentro da classe herdeira
e que permite o acesso às variáveis e métodos não-privados da classe ancestral.
Uma aplicação da referência super na classe mostrada na listagem 5.10 seria no método imprime - as
três primeiras linhas deste método são idênticas ao conteúdo do método imprime na classe Aluno (lista-
gem 5.9), e podem ser reaproveitadas, bastando chamar o método imprime da classe Aluno de dentro do
método imprime da classe AlunoMestrado. A classe AlunoMestrado modificada é mostrada na lista-
gem 5.11.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
53
13 tese = t;
14 inicializaMensalidade(200); // mensalidade fixa para os alunos de mestrado
15 }
16 /* O método que imprime - note que como não podemos acessar as variáveis
17 diretamente, usamos métodos que as acessam. */
18 void imprime()
19 {
20 super.imprime();
21 System.out.println("Área de especialização: "+área);
22 System.out.println("Título da tese: "+tese);
23 }
24 /* Método para retornar a área de especialização */
25 String qualÁrea()
26 {
27 return área;
28 }
29 /* Método para retornar o título da tese */
30 String qualTese()
31 {
32 return tese;
33 }
34 } // fim da classe AlunoMestrado
Note que seria impossível chamar o método imprime da classe Aluno, uma vez que este foi sobreescrito
pelo método de mesmo nome e tipos de parâmetros na classe AlunoMestrado.
Além da referência super temos também a referência this, que aponta para a própria classe.
Exercício 5.2: ?
Modifique as variáveis da classe Veiculo (listagem 5.1) para que todos sejam private. Modifique
também o método inicializa para tratar dos dados que não são mais acessíveis de fora da classe.
Exercício 5.3: ?
Escreva uma classe Automovel que herde as variávels e métodos da classe VeiculoTerrestre
(listagem 5.3), mas que considere constante os valores númeroDePassageiros, númeroDeRodas e
velocidadeMédia. Escreva também um programa que use instâncias da classe Automovel.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
54
Exercício 5.4: ?
As classes abaixo contém 3 erros. Indique e explique os erros.
1 class Pai
2 {
3 private char x,y;
4 }
5
6 class Filho extends Pai
7 {
8 char z;
9 void imprime()
10 {
11 System.out.println("X é "+x);
12 System.out.println("Y é "+y);
13 System.out.println("Z é "+z);
14 }
15 }
16
17 class Teste
18 {
19 Pai p = new Pai();
20 p.x = ’N’;
21 Filho f = new Filho();
22 f.z = ’C’;
23 p.imprime();
24 f.imprime();
25 }
Exercício 5.5: ?
O que acontecerá quando a classe Executavel da listagem abaixo for executada ? Que valores serão
impressos, e porquê ? Como corrigir o problema existente nestas classes ?
1 class Pai
2 {
3 int x;
4 void imprime()
5 {
6 System.out.println("Valor é "+x);
7 }
8 }
9
10 class Filho extends Pai
11 {
12 boolean x;
13 }
14
15 class Executavel
16 {
17 public static void main(String params[])
18 {
19 Pai p = new Pai();
20 p.x = 12345;
21 p.imprime();
22 Filho f = new Filho();
23 f.x = false;
24 f.imprime();
25 }
26 }
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
55
Exercício 5.6: ?
Crie uma classe Ponto4D que extenda a classe Ponto3D (listagem 5.8). Como ficaria o método
inicializa da nova classe ?
Exercício 5.7: ?
A classe abaixo contém 3 erros. Indique e explique os erros.
1 class Pontos
2 {
3 public static void main(String params[])
4 {
5 Ponto2D p1,p2;
6 p2 = new Ponto2D();
7 Ponto3D p3,p4;
8 p3 = new Ponto3D();
9 p4 = new Ponto3D();
10 p1.inicializa((short)10,(short)12);
11 p2.inicializa((short)27,(short)-5);
12 System.out.println("Coordenada Z de p2 é "+p2.qualZ());
13 p3.inicializa((short)80,(short)-45);
14 p4.x = 16;
15 }
16 }
Exercício 5.8: ?
Indique e explique o erro existente nas classes abaixo.
1 class Pai
2 {
3 private int x;
4 }
5
6 class Filho extends Pai
7 {
8 void inicializa(int _x)
9 {
10 super.x = _x;
11 }
12 }
Exercício 5.9: ?
O que aconteceria se removêssemos a palavra-chave super da linha 20 da listagem 5.11 ? Explique.
Exercício 5.10: ? ?
Seguindo o exemplo mostrado na listagem 5.5, crie as classes VeiculoAereo e VeiculoAquatico, todas
descendentes da classe Veiculo.
Exercício 5.11: ? ?
Considerando o exercício 3.5, crie uma classe LampadaFluorescente que herde variáveis e métodos da
classe Lampada (listagem 3.4) e acrescente uma variável para representar o comprimento da lâmpada e
métodos para inicializar e imprimir os valores.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
56
Exercício 5.12: ? ?
Usando as classes criadas no exercício 5.10, escreva um programa em Java que crie as instâncias
aviãoAJato, jetski, táxi, lancha, miniVan, bicicleta e tecoTeco. Estas instâncias devem ser
criadas a partir das classes mais adequadas.
Exercício 5.13: ? ? ?
Considere os exercícios 2.4 e 2.5 e escreva uma classe Livro que represente um livro genérico, e duas
classes LivroBiblioteca e LivroLivraria que herdem da classe Livro.
Exercício 5.14: ? ? ?
Usando a classe RegistroDeAluno (listagem 3.6) como base, crie a classe herdeira
RegistroDeAlunoDeMestrado que conterá duas Strings adicionais: uma para representar o seu
tema de pesquisa e outra para representar seu orientador.
Exercício 5.15: ? ? ?
Usando a classe ContaBancaria (listagem 3.8) como base, crie a classe herdeira ContaPoupança
que contém uma variável do tipo byte dia, que deve ser inicializada com os outros dados da classe
ContaPoupança. O método retira da classe deve ser sobreescrito de forma que a retirada só possa ser
feita se um valor do tipo byte hoje, passado como argumento para o método retira, for igual ao valor
da variável dia.
Exercício 5.16: ? ? ?
Crie uma classe Presidente que contenha o nome do presidente, partido político de filiação e nome do
país que este governa. Crie nesta classe métodos básicos para inicialização, impressão e recuperação dos
valores. Crie a classe Governador que herde tudo da classe Presidente e adicione uma variável para
representar qual estado é governado. Crie também uma classe Prefeito que herde da classe Governador
e contenha o nome do município que é governado pelo prefeito. Use os mecanismos de herança mostrados
neste capítulo.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
57
Capítulo 6
Polimorfismo
6.1 Introdução
Linguagens de programação orientadas a objeto permitem a criação de métodos com o mesmo nome em
uma mesma classe, graças a um mecanismo chamado polimorfismo. Os métodos podem ter o mesmo no-
me, mas devem ser diferenciados pelo número e tipo de argumentos que recebem.
Métodos polimórficos podem ser usados quando queremos criar várias opções para que a mesma tarefa
seja feita por um método. Para exemplificar, consideremos a classe Hora mostrada na listagem 6.1, que
define um único método ajusta, que recebe três argumentos para inicialização dos dados das instâncias
da classe Hora.
A classe TesteHora, que contém um método main e é mostrada na listagem 6.2, demonstra o uso de
instâncias da classe Hora. Várias instâncias com valores diferentes para cada hora, minuto e segundo re-
presentados na classe são criadas.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
58
Podemos ver na listagem 6.2 que quando chamamos o método ajusta das instâncias da classe Hora, o
valor dos segundos (terceiro argumento passado) é, em muitos casos, zero, mas devido às regras da lingua-
gem, deve sempre ser passado.
Usando polimorfismo, podemos criar métodos em uma classe que aceitem números de argumentos dife-
rentes, que reflitam o nível de detalhe que o usuário da classe quer utilizar. Para possibilitar ao usuário da
classe a escolha sobre passar ou não o número de segundos para uma instância da classe Hora pelo método
ajusta basta a criação de um ou mais métodos com o mesmo nome que aceitem números de argumentos
diferentes e os processem corretamente, conforme mostrado na classe Hora na listagem 6.3.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
59
23 /* Este método ajusta a hora, usando somente horas e considerando minutos e segundos como zero */
24 void ajusta(byte phoras)
25 {
26 horas = phoras;
27 minutos = 0; // consideramos minutos como zero
28 segundos = 0; // consideramos segundos como zero
29 }
30 /* Este método ajusta as variáveis horas, minutos e segundos como sendo zero */
31 void ajusta()
32 {
33 horas = 0; // consideramos horas como zero
34 minutos = 0; // consideramos minutos como zero
35 segundos = 0; // consideramos segundos como zero
36 }
37 /* Este método imprime a hora formatada */
38 void imprime()
39 {
40 System.out.println(horas+":"+minutos+":"+segundos);
41 }
42 } // fim da classe Hora
A classe Hora na listagem 6.3 contém quatro métodos ajusta, cada um com o número de argumentos
diferentes, que podem ser chamados de acordo com a necessidade ou desejo do usuário da classe. A classe
TesteHora pode ser reescrita de forma a passar o número de minutos e segundos somente quando isto for
desejado pelo usuário da classe, conforme mostrado na listagem 6.4.
Listagem 6.4: Um programa que demonstra usos da classe Hora que contém métodos polimórficos
1 /* Esta classe demonstra usos da classe Hora com os métodos polimórficos */
2 class TesteHora
3 {
4 /* Método que possibilita a execução da classe */
5 public static void main(String args[])
6 {
7 // crio algumas instâncias e inicializo-as
8 Hora agora = new Hora();
9 agora.ajusta((byte)22,(byte)53,(byte)41); // primeiro método usado
10 Hora meianoite = new Hora();
11 meianoite.ajusta(); // quarto método usado
12 Hora meiodia = new Hora();
13 meiodia.ajusta((byte)12); // terceiro método usado
14 Hora onzeemeia = new Hora();
15 onzeemeia.ajusta((byte)11,(byte)30); // segundo método usado
16 // peço às instâncias que se imprimam
17 agora.imprime();
18 meianoite.imprime();
19 meiodia.imprime();
20 onzeemeia.imprime();
21 }
22 } // fim da classe TesteHora
Na listagem 6.4 vemos que podemos inicializar os valores de uma instância da classe Hora passando os
valores das horas, minutos e segundos (linha 9), somente das horas e minutos (linha 15), somente das horas
(linha 13) e sem nenhum argumento (linha 11).
Poderiámos ter criado quatro métodos com nomes ligeiramente diferentes para ajustar os valores da classe,
sem usar o polimorfismo, mas a vantagem do uso deste é que o mesmo nome de método é usado para
tarefas bem parecidas - o programador que usar a classe não precisará se preocupar com nomes diferentes
para métodos cuja finalidade é praticamente igual.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
60
Para exemplificar as regras de polimorfismo, consideremos a classe Terminal na listagem 6.5. Esta classe
implementa vários métodos polimórficos, todos estáticos, permitindo assim o uso dos métodos da classe
sem a necessidade de criação de uma instância desta.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
61
A classe Terminal (listagem 6.5) contém oito métodos chamados print, sendo que todos tem número
e tipos diferentes de argumentos. Podemos inclusive ter métodos que retornam tipos diferentes, contanto
que o número e tipos de argumentos seja diferente, conforme mostrado no último método print da classe
Terminal - este retorna uma String, enquanto os outros métodos com o mesmo nome retornam void.
Modificadores e nomes de variáveis são completamente ignorados pela linguagem quando esta conside-
ra os nomes dos métodos em uma mesma classe: desta maneira static void print(int a) e void
print(int z) são consideradas iguais.
Uma regra simples para verificar se os métodos serão considerados como iguais (portanto quebrando as
regras do polimorfismo) é considerar os nomes dos métodos sem modificadores como public, private,
etc. e sem os nomes das variáveis, ou seja, considerar somente o nome simplificado do método. Desta
forma, os dois métodos apresentados como exemplo teriam os nomes simplificados void print(int) e
void print(int), sendo considerados iguais e não podendo estar presentes na mesma classe.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
62
O método inicializa da classe LivroComSoftware chama, através da referência super (que aponta para
a classe ancestral), o método inicializa da classe Livro (linha 13 da listagem 6.7). Na verdade, neste
caso o uso da referência super é opcional, uma vez que a classe LivroComSoftware contém o método
void inicializa(String, String, String, short np) - herdado da classe Livro. Como um mé-
todo pode chamar outro da mesma classe diretamente, podemos tranquilamente reescrever a linha 13 da
listagem 6.7 como inicializa(t,a,e,np);.
É importante notar que se o método inicializa da classe Livro fosse declarado como private, ele não
poderia ser chamado de dentro da classe LivroComSoftware, mesmo se a referência super fosse utilizada
- ele estaria “invisível” para a classe LivroComSoftware.
É também importante notar que em alguns casos o uso do super se faz necessário, apesar do exemplo
dado acima. Na classe LivroComSoftware temos um método void imprime() que chama o método
imprime da classe Livro através da referência super (linha 22 da listagem 6.7). Caso retirássemos a
referência super desta linha, o método que seria chamado seria o método imprime da própria classe
LivroComSoftware, uma vez que ele sobreescreveu o método imprime herdado da classe Livro. Neste
caso, o método estaria se chamando recursivamente, criando uma volta ou laço recursivamente infinito, que
causaria um erro de execução no programa. A única maneira de evitar este laço infinito seria garantir que
o método imprime da classe LivroComSoftware estaria chamando o método imprime da classe Livro,
através da referência super.
Um exemplo diferente de uso de polimorfismo é mostrado na classe MatBasica (listagem 6.8). Esta classe
contém vários métodos estáticos (que podem ser usados sem necessidade de instanciação da classe) que cal-
culam duas funções matemáticas, média e maior. Estes métodos são polimórficos de forma que podemos
chamar ambos com dois ou três argumentos do tipo double, como mostrado na classe TesteMatBasica
(listagem 6.9).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
63
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
64
• O resultado da linha 14 da listagem 6.9 é zero, uma vez que os valores passados como argumentos
para o método maior são resultados das divisões de valores inteiros (ambos iguais a zero).
Um ponto importante a ser considerado com métodos polimórficos que aceitam valores numéricos é que
tipos de dados “menores” podem ser aceitos por métodos que esperam tipos de dados “maiores” - no
exemplo mostrado nas listagens 6.8 e 6.9, os métodos esperavam valores do tipo double mas aceitaram
valores do tipo int, pois a conversão é feita automaticamente. O inverso não ocorre - se o método espera
um tipo int e um valor double é passado, o compilador gerará uma mensagem de erro. Detalhes sobre tipos
de dados e conversões são mostrados no apêndice A.
Exercício 6.2: ?
Crie mais métodos polimórficos na classe MatBasica para cálculo da média de quatro valores, e para
cálculo dos menores valores de dois e três valores passados como argumentos.
Exercício 6.3: ?
Ache e explique os dois erros no programa abaixo.
1 class Teste
2 {
3 int soma(int a,int b)
4 {
5 return a+b;
6 }
7 int soma(int c,int d)
8 {
9 return c+d;
10 }
11 float soma(float e,float f)
12 {
13 return e+f;
14 }
15 float soma(int g,int h)
16 {
17 return g+h;
18 }
19 }
Exercício 6.4: ?
Os métodos ajusta da classe Hora (listagem 6.3) recebem somente variáveis tipo byte, obrigando o
programador que usa as classes a usar o cast (conversão) quando chama os métodos, como mostrado nas
linhas 9, 13 e 15 da listagem 6.4. Crie métodos polimórficos adicionais na classe Hora que permitam
ao usuário passar valores do tipo int, dispensando o cast. Que problema pode ocorrer por causa desta
mudança ?
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
65
Exercício 6.5: ?
Considere a classe Terminal na listagem 6.5 e os nomes de métodos abaixo. Quais destes métodos
podem pertencer à classe Terminal (seguindo as regras de polimorfismo) e quais não podem ? Explique,
caso a caso. Os métodos somente contém o cabeçalho, para simplificação.
Exercício 6.6: ?
Crie mais métodos média e maior, usando polimorfismo, na classe MatBasica (listagem 6.8). Estes
métodos devem tratar somente com valores do tipo inteiro.
Exercício 6.7: ? ?
Considerando as classes Livro (listagem 6.6) e LivroComSoftware (listagem 6.7), o que acontecerá com
as instâncias do programa abaixo ? Explique.
1 class TesteLivros
2 {
3 public static void main(String z[])
4 {
5 LivroComSoftware l1 = new LivroComSoftware();
6 l1.inicializa("O Grande Livro das Mentiras","Kung Pao","Marmora Editora",(short)459);
7 LivroComSoftware l2 = new LivroComSoftware();
8 l2.inicializa("O Grande Livro das Mentiras","Kung Pao","Marmora Editora",(short)459,
9 "Lie Detector 1.0",true);
10 l1.imprime();
11 l2.imprime();
12 }
13 }
Exercício 6.8: ? ?
Usando métodos polimórficos já existentes, pode-se criar novos métodos que retornem os maiores ou
menores valores de quatro, cinco, seis, etc. valores passados como argumentos. Crie estes métodos na
classe MatBasica (listagem 6.8).
Exercício 6.9: ? ?
Modifique o método ajusta da classe Hora (listagem 6.3) que não recebe argumentos. Considere que
se nenhum argumento é passado, o método deve ler os valores do teclado. Use o método readByte da
classe Keyboard (apêndice B) para ler os valores do teclado.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
66
Exercício 6.10: ? ?
Considere a classe Qual e a classe Teste na listagem abaixo. Quando as chamadas aos métodos forem
feitas (linhas 29 a 36), quais métodos serão executados para cada linha ? Explique.
1 class Qual
2 {
3 static void método(int a,int b)
4 {
5 System.out.println("Primeiro método !");
6 }
7 static void método(double a,double b)
8 {
9 System.out.println("Segundo método !");
10 }
11 static void método(int a,double b)
12 {
13 System.out.println("Terceiro método !");
14 }
15 static void método(double a,int b)
16 {
17 System.out.println("Quarto método !");
18 }
19 }
20
21 class Teste
22 {
23 public static void main(String args[])
24 {
25 byte umByte = 1;
26 int umInt = 17;
27 long umLong = 100L;
28 double umDouble = 1.3;
29 Qual.método(umByte,umLong);
30 Qual.método(umLong,umInt);
31 Qual.método(umDouble,umLong);
32 Qual.método(umDouble,umByte);
33 Qual.método(umInt,umLong);
34 Qual.método(umByte,umInt);
35 Qual.método(umLong,umLong);
36 Qual.método(umByte,umByte);
37 }
38 }
Exercício 6.11: ? ? ?
Modifique a classe Data (listagem 3.5) para que esta tenha dois outros métodos chamados ajustaData
usando polimorfismo. Um destes métodos receberá uma instância da classe Data como argumento, e
usará os valores contidos nesta instância para inicializar a data. Outro método não receberá argumentos e
lerá os dados do teclado usando a classe Keyboard (apêndice B).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
67
Capítulo 7
Construtores
7.1 Introdução
As classes para representação de dados criadas até agora seguem um padrão: as variáveis das classes são
declaradas como private, e devem ser manipuladas por métodos que inicializam e imprimem estes valo-
res. Adicionalmente podemos ter métodos que podem calcular ou modificar os valores da classe.
Só podemos chamar os métodos de uma instância de uma classe depois que esta for inicializada através
da palavra-chave new. Mesmo assim, ainda não existem garantias de que os valores contidos na instância
estarão inicializados, e em alguns casos estaremos chamando métodos que tratarão ou mostrarão dados
sem sentido. Um exemplo deste problema é mostrado no programa na listagem 7.1.
No programa na listagem 7.1 uma instância da classe RegistroDeAluno (mostrada na listagem 3.6) é
criada através da palavra-chave new (linha 9). Na linha 11 usamos o método calculaMensalidade que
calculará a mensalidade sem que um valor para a variável de classe éBolsista tenha sido explicitamente
inicializada, e na linha 13 usamos o método imprime que imprimirá valores não inicializados (Strings se-
rão consideradas como null, valores numéricos como zero, etc.).
No programa na listagem 7.1 esperava-se que após a criação da instância com a palavra-chave new e antes
do uso dos métodos desta instância, o método entraDados (que permite que passemos valores às variáveis
internas da classe RegistroDeAluno) fosse chamado, mas não existe um mecanismo implícito da lingua-
gem Java que garanta a chamada de métodos em uma ordem particular - isto é obrigação do programador
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
68
É possível, no entanto, garantir que um método será chamado antes de qualquer outro método em uma
classe. Este método é conhecido como construtor daquela classe. Este método pode executar qualquer
tarefas relativa à classe que o implementa, mas frequentemente é usado para inicializar os dados das ins-
tâncias das classes.
Métodos serão considerados como construtores se todas as seguintes regras forem cumpridas:
• Construtores devem ter o mesmo nome da classe, inclusive em relação à caracteres maiúsculos e
minúsculos.
• Construtores não podem retornar nenhum valor, nem mesmo void - são declarados somente com o
nome da classe e os valores passados como argumentos.
• Construtores não devem ter modificadores como static, private, public, etc.
Construtores, apesar de serem métodos, não podem ser chamados diretamente de programas ou de dentro
de outros métodos da mesma classe - a única maneira de executar o código contido em um construtor é
através da palavra-chave new, que automaticamente chamará o construtor. Isto garante que o construtor
será o primeiro método executado de cada classe.
Um exemplo de classe com construtor é mostrada na listagem 7.2. Instâncias desta classe são mostradas
no programa na listagem 7.3.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
69
Listagem 7.3: Classe que usa instâncias da classe Lampada com construtor
1 /* Esta classe demonstra instâncias da classe Lampada (usando construtores) */
2 class TesteLampada
3 {
4 /* Este método permite a execução da classe */
5 public static void main(String args[])
6 {
7 // Criamos três instâncias da classe Lampada e passamos para o construtor
8 // um estado inicial para cada.
9 Lampada lâmpadaDaSala = new Lampada(true); // ligada
10 Lampada lâmpadaDoQuarto = new Lampada(false); // desligada
11 Lampada lâmpadaDaCozinha = new Lampada(true); // ligada
12 // Apago a luz da sala
13 lâmpadaDaSala.apaga();
14 // Imprimo o estado de cada uma delas
15 System.out.print("A lâmpada da sala está ");
16 lâmpadaDaSala.imprime();
17 System.out.print("A lâmpada da quarto está ");
18 lâmpadaDoQuarto.imprime();
19 System.out.print("A lâmpada da cozinha está ");
20 lâmpadaDaCozinha.imprime();
21 }
22 } // fim da classe TesteLampada
Na linha 10 da listagem 7.2 vemos o construtor para a classe Lampada é o método que será automatica-
mente chamado pela palavra-chave new nas linhas 10, 11 e 12 da listagem 7.3.
Este construtor vazio é dado automaticamente pela linguagem para as classes que não tem nenhum cons-
trutor. Se qualquer construtor for criado explicitamente para a classe, o construtor default vazio não será
criado automaticamente, e não poderá ser usado por outras classes, a não ser que um dos construtores
criados para a classe tenha a mesma forma do construtor default (vazio, ou sem argumentos).
Construtores podem chamar outros métodos da classe, mas os outros métodos não podem chamar constru-
tores. Exemplos destas duas características são mostrados nas classes das listagens 7.4 e 7.5.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
70
13 {
14 mês = m;
15 }
16 /* Este método ajusta o ano da data */
17 void ajustaAno(short a)
18 {
19 ano = a;
20 }
21 /* Este método ajusta simultaneamente o dia, mês e ano da data, chamando
22 os outros métodos declarados anteriormente */
23 void ajustaData(byte d,byte m,short a)
24 {
25 ajustaDia(d); // chama o método ajustaDia com o argumento d
26 ajustaMês(m); // chama o método ajustaMês com o argumento m
27 ajustaAno(a); // chama o método ajustaAno com o argumento a
28 }
29 /* Este é o construtor da classe Data, que inicializará os valores
30 através de uma chamada ao método ajustaData */
31 Data(byte d,byte m,short a)
32 {
33 ajustaData(d,m,a);
34 }
35 /* Este método imprime a data. */
36 void imprime()
37 {
38 System.out.print("Dia:"+dia+" ");
39 System.out.print("Mês:"+mês+" ");
40 System.out.println("Ano:"+ano);
41 }
42 /* Este método retorna a data formatada como uma String. */
43 String formata()
44 {
45 String temporária = "Dia:"+dia+" Mês:"+mês+" Ano:"+ano;
46 return temporária;
47 }
48 } // fim da classe Data
Listagem 7.5: Classe que usa instâncias da classe Data com construtor
1 /* Esta é a classe TesteData, que criará instâncias da classe Data usando seu construtor. */
2 class TesteData
3 {
4 /* Este é o método main, que permite a execução da classe */
5 public static void main(String args[])
6 {
7 // Crio uma instância da classe Data
8 Data hoje = new Data((byte)2,(byte)4,(short)2000);
9 // Crio outra instância da classe Data, que será inicializada com uma data
10 Data nascimento = new Data((byte)3,(byte)2,(short)1939);
11 // Modifico a data da instância nascimento
12 nascimento.ajustaData((byte)3,(byte)10,(short)1962);
13 // Imprimo as instâncias da classe Data
14 hoje.imprime();
15 nascimento.imprime();
16 }
17 } // fim da classe TesteData
Na classe Data, mostrada na listagem 7.4, temos o construtor na linha 31 que chama o método ajustaData
(linha 23), passando para este os valores passados como argumento. Desta forma as funções do método
ajustaData e do construtor são as mesmas, mas possibilitamos que uma data seja inicializada com valores
quando instanciada com a palavra-chave new e também que uma data seja instanciada e depois seus valores
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
71
É importante notar que uma vez que criamos um construtor para a classe Data (listagem 7.4), não podemos
mais criar instâncias da classe através da palavra-chave new como Data instância = new Data() pois
o construtor default não será criado automaticamente, e não existe um construtor sem argumentos para a
classe Data que possa ser chamado no lugar do construtor default.
Alguns detalhes sobre as regras de polimorfismo e herança aplicadas aos construtores são mostradas nos
comentários sobre as classes nas listagens 7.6, 7.7 e 7.8.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
72
Listagem 7.8: Uma classe que usa instâncias da classe VeiculoTerrestre com construtores polimórficos
1 /* Classe executável que cria instâncias das classes Veiculo e VeiculoTerrestre */
2 class TesteVeiculo
3 {
4 /* Método que faz com que a classe seja executável */
5 public static void main(String args[])
6 {
7 // Crio e inicializo uma instância da classe Veiculo para representar um ônibus
8 VeiculoTerrestre onibus = new VeiculoTerrestre("Ônibus de Passageiros",
9 (short)50,(byte)6,(short)90);
10 // Crio e inicializo uma instância da classe Veiculo para representar um fusca
11 VeiculoTerrestre fusca = new VeiculoTerrestre("Fusca",(short)65);
12 // imprimo os dados das instâncias
13 onibus.imprime();
14 fusca.imprime();
15 }
16 } // fim da classe TesteVeiculo
Algumas regras que se aplicam à construtores, herança e polimorfismo estão listadas abaixo:
• O construtor da classe ancestral pode ser chamado através da referência super sem o nome do
método, como mostrado na linha 9 da listagem 7.7.
• Quando uma classe que não possui o construtor default (como a classe Veículo, na listagem 7.6) é
usada como classe ancestral de outra, o construtor da classe descendente deve chamar o construtor
da classe ancestral explicitamente através da referência super, que neste caso deve corresponder à
uma das formas polimórficas explícitas dos construtores da classe ancestral.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
73
Se a classe ancestral possuir o construtor default, este será chamado automaticamente de todos os
construtores da classe descendente que não chamarem o construtor explicitamente através da refe-
rência super.
• Construtores são herdados, mas não podem ser chamados como métodos comuns. Para chamar
um construtor da classe ancestral, devemos sempre usar o super(). Somente construtores podem
chamar construtores.
• Se o construtor da classe ancestral for chamado de dentro do construtor da classe descendente, o
super deve ser o primeiro comando a ser executado no construtor da classe descendente.
• Quando a classe possui vários construtores, as regras de polimorfismo (exemplificadas pelas lista-
gens 6.8 e 6.9) decidirão qual deles será chamado: nos exemplos nesta seção, a palavra-chave new
na linha 8 da listagem 7.8 chamará o construtor na linha 6 da listagem 7.7 enquanto a palavra-chave
new na linha 11 da listagem 7.8 chamará o construtor na linha 12 da listagem 7.7.
• A referência this pode ser usada para chamar um construtor dentro de outro da mesma classe. A
linha 17 da listagem 7.7 poderia ser escrita como this(n,(short)5,(byte)4,vm); - neste caso o
construtor sendo chamado seria o da mesma classe (linha 6) ao invés do da classe ancestral, mas o
resultado seria o mesmo.
Nas classes desenvolvidas até agora o método toString() (que deve ser declarado obrigatoriamente como
public, e não recebe nenhum argumento) não foi sobreescrito, sendo herdado diretamente da classe an-
cestral (na maior parte dos casos, Object). Este método, quando não-sobreescrito, simplesmente imprime
o nome da classe e alguns valores, como mostrado no resultado do programa na listagem 7.9.
Listagem 7.9: Uma classe que demonstra o uso implícito dos métodos toString
1 /* Esta é a classe TesteToString, que demonstrará os resultados das chamadas aos métodos
2 toString de algumas classes. */
3 class TesteToString
4 {
5 /* Este é o método main, que permite a execução da classe */
6 public static void main(String args[])
7 {
8 // Uma instância da classe Data...
9 Data hoje = new Data((byte)27,(byte)3,(short)2000);
10 System.out.println(hoje); // Deve imprimir "Data@..."
11 // Uma instância da classe Veiculo...
12 Veiculo carro = new Veiculo("Automóvel",(short)5,(byte)4,(short)110);
13 System.out.println(carro); // Deve imprimir "Veiculo@..."
14 }
15 } // fim da classe TesteToString
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
74
Para que possamos usar o método toString() em uma classe, basta a sua criação. Este método deve
retornar uma String contendo os valores da classe, da forma que o programador quiser colocá-los. Para
exemplificar, uma versão simplificada da classe Data é mostrada na listagem 7.10.
Devemos observar que o método toString() mostrado na linha 14 da listagem 7.10 é declarado como
public, não recebe nenhum tipo de argumento e retorna uma String. Chamadas diretas à este método ou
indiretas através de System.out.println ou concatenação de Strings com o sinal + retornarão os valores
da classe Data formatados como desejado.
Exercício 7.1: ?
Complete a classe Lampada (listagem 3.4) com construtores e o método toString.
Exercício 7.2: ?
Complete a classe RegistroDeAluno (listagem 3.6) com construtores e o método toString.
Exercício 7.3: ?
Complete a classe ModeloDeComputador (listagem 3.7) com construtores e o método toString.
Exercício 7.4: ?
Complete a classe ContaBancaria (listagem 3.8) com construtores e o método toString.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
75
Exercício 7.5: ?
Crie uma classe NomeETelefone que conterá o nome e o telefone de uma pessoa. Crie ao menos um
construtor para esta classe e escreva seu método toString.
Exercício 7.6: ?
Dos métodos na classe Contador mostrada abaixo, quais são construtores e quais não são ? Explique.
1 class Contador
2 {
3 private int valor;
4 void Contador(int v)
5 {
6 valor = v;
7 }
8 private void Contador(int v)
9 {
10 valor = v;
11 }
12 private Contador(int v)
13 {
14 valor = v;
15 }
16 Contador()
17 {
18 valor = 0;
19 }
20 contador()
21 {
22 valor = 0;
23 }
24 }
Exercício 7.7: ?
Considerando a classe Lampada da listagem 7.2, qual é o erro do programa na listagem abaixo ? Explique.
1 class TesteLampada
2 {
3 public static void main(String args[])
4 {
5 Lampada lâmpada1 = new Lampada();
6 lâmpada1.acende();
7 lâmpada1.imprime();
8 }
9 }
Exercício 7.8: ?
Crie um construtor que não recebe argumentos para a classe RegistroDeAluno. Escreva este construtor
de forma que se ele for chamado, os dados do aluno serão lidos do teclado. Use métodos da classe
Keyboard (apêndice B) para ler os dados.
Exercício 7.9: ?
Crie uma classe SiteNaInternet que represente um site na internet através da sua URL, seu título, uma
categoria e subcategoria (como usado nos principais sites de busca). Crie ao menos um construtor e o
método toString().
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
76
Exercício 7.10: ?
Considerando as regras de herança e construtores, quais são os três erros do programa na listagem abaixo ?
Explique.
1 class Ponto2D
2 {
3 private int x,y;
4 Ponto2D(int _x,int _y)
5 {
6 x = _x;
7 y = _y;
8 }
9 }
10
11 class Ponto3D extends Ponto2D
12 {
13 int z;
14 Ponto3D(int _x,int _y,int _z)
15 {
16 Ponto3D(_x,_y);
17 z = _z;
18 }
19 void inicializa(int _x,int _y,int _z)
20 {
21 super(_x,_y);
22 z = _z;
23 }
24 }
25
26 class Pontos
27 {
28 public static void main(String p[])
29 {
30 Ponto3D a = new Ponto3D(1,2,-5);
31 Ponto3D b = new Ponto3D(-8,8);
32 }
33 }
Exercício 7.11: ? ?
Considerando o exercício 5.10, recrie as classes VeiculoAereo e VeiculoAquatico, descendentes da
classe Veiculo, com construtores e métodos toString().
Exercício 7.12: ? ?
Modifique as classes Ponto2D e Ponto3D (listagem 5.8) para que estas tenham construtores apropriados
e métodos toString(). Dica: crie um construtor que recebe valores e um construtor que não recebe
valores, neste caso as variáveis da classe serão inicializadas com zeros.
Exercício 7.13: ? ?
Crie uma classe NumeroComplexo que represente as partes real e imaginária de um número complexo.
Crie três construtores para esta classe: um que recebe os dois valores como argumento, um que recebe
somente a parte real e considera a imaginária como zero e um que não recebe nenhum argumento e
considera as duas partes como zero. Crie também um método toString() apropriado.
Exercício 7.14: ? ? ?
Considerando o exercício 5.13, crie as classes LivroBiblioteca e LivroLivraria que herdem da classe
Livro, com construtores apropriados e métodos toString().
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
77
Exercício 7.15: ? ? ?
Usando o exercício 5.16 como base, crie as classes Presidente, Governador e Prefeito com os cons-
trutores adequados e métodos toString().
Exercício 7.16: ? ? ?
Crie um construtor para a classe Data que receba uma instância da própria classe Data para sua iniciali-
zação.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
78
Capítulo 8
8.1 Introdução
Neste capítulo veremos as estruturas de decisão e controle que permitem que programas e classes executem
trechos ou métodos inteiros condicionalmente, isto é, que serão ou não executados dependendo de condi-
ções. Veremos também estruturas que permitem que partes de programas sejam executadas repetidamente.
Os operadores de comparação para dados dos tipos numéricos e booleanos são definidos como valor
sinal valor, onde os valores podem ser variáveis, constantes ou resultados de operações e o sinal pode
ser um dos abaixo:
• == retorna o valor booleano true se os dois valores forem exatamente iguais e false se forem
diferentes.
• != retorna o valor booleano true se os dois valores forem diferentes e false se forem exatamente
iguais (inverso do caso anterior).
• > retorna o valor booleano true se o valor à esquerda do sinal for maior do que o valor à direita
do sinal, e false caso for menor ou igual.
• < retorna o valor booleano true se o valor à esquerda do sinal for menor do que o valor à direita
do sinal, e false caso for maior ou igual.
• <= retorna o valor booleano true se o valor à esquerda do sinal for menor ou igual do que o valor
à direita do sinal, e false se for maior.
• >= retorna o valor booleano true se o valor à esquerda do sinal for maior ou igual do que o valor
à direita do sinal, e false se for menor.
O programa mostrado na listagem 8.1 demonstra alguns usos dos operadores mostrados acima, com valores
numéricos do tipo inteiro. Os operadores podem ser usados também com outros tipos de dados nativos.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
79
Operadores lógicos e valores booleanos podem ser combinados entre si para a criação de operadores mais
complexos. As combinações são feitas com três operadores na forma valor sinal valor (vários valores
podem ser combinados de uma vez, contanto que existem sinais entre uns e outros), onde os valores são
constantes ou expressões que retornam valores booleanos e o sinal pode ser um dos abaixo:
• && retorna o valor booleano true se e somente se os dois valores (à esquerda e à direita do sinal)
valerem true. Este é o operador booleano AND (E).
• || retorna o valor booleano true se ao menos um dos dois valores (à esquerda e à direita do sinal)
valerem true. Este é o operador booleano OR (OU). Note que o sinal usado é a barra vertical e não o
sinal de exclamação (!).
Existe também o sinal da negação (NOT, NÃO), que transforma um valor booleano true em false e vice-
versa: este sinal é a exclamação (!) e deve preceder um valor ou operador booleano. Alguns exemplos de
operadores e combinações são mostrados no programa da listagem 8.2.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
80
A estrutura de decisão if pode ser seguida opcionalmente da palavra-chave else. A palavra-chave else
deve ser seguida por um comando ou bloco de comandos da mesma forma que a palavra-chave if. O
comando ou bloco de comandos associados ao else será executado caso o operador lógico avaliado pelo
comando if tenha resultado false. Em outras palavras, a execução dos comandos e/ou blocos em uma
estrutura if-else é mutuamente exclusiva.
A listagem 8.3 mostra uma classe executável que demonstra o uso das estruturas if e else.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
81
É possível e comum termos blocos de if e else aninhados, ou seja, uns dentro de outros, como mostrado
na listagem 8.3. Neste caso, o if da linha 26 só será executado caso o if da linha 22 não for executado
(fazendo com que o bloco de comandos associados ao else da linha 24 seja executado).
Quando blocos de if e else aninhados são usados, é necessário tomar cuidado com que bloco else será
associado aos blocos if - a regra básica é que blocos else são associados aos blocos if mais próximos
que não estejam delimitados pelas chaves ({ e }). O programa na listagem 8.4 demonstra esta regra.
Também é possível o encadeamento de if e else em cascata, aonde a cada else se segue um outro if.
Neste tipo de construção de comandos, a primeira condição é avaliada, e somente caso o resultado da avali-
ação seja false a segunda condição será avaliada, e assim sucessivamente. O uso de if e else em cascata
é mostrado no método calculaPreço() da classe AparelhoDeTV na listagem 8.5.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
82
A estrutura de decisão switch permite que uma expressão do tipo inteiro seja avaliada e a partir do valor
desta expressão, um de vários blocos de comandos seja executado, emulando de forma diferente a estrutura
de if e else encadeados, mas com algumas diferenças básicas:
• A estrutura switch deve ser acompanhada de uma ou mais cláusulas case, que identificarão o bloco
de comandos a ser executado caso o número que acompanha o case seja o resultado da avaliação do
switch. A forma geral da estrutura switch é mostrada no programa na listagem 8.6.
• Não podemos ter duas cláusulas case com valores iguais, mas não é necessário que os valores das
cláusulas sejam contíguos ou mesmo que estejam na ordem numérica.
• Ao final de cada bloco de comando em cada cláusula case devemos usar o comando break para que
este transfira a execução do programa para o fim do switch. Isto deve ser feito porque o comando
switch simplesmente transfere a execução do programa para a linha que contém o case corres-
pondente, e continua o processamento a partir de lá. Sem os comandos break, todos os blocos de
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
83
comandos subsequentes seriam executados, mesmo se o valor do case for diferente do resultado do
switch.
• A estrutura switch avalia dados do tipo int, significando que dados dos tipos byte, char e short
serão convertidos automaticamente para int. O tipo long pode ser usado com conversão explícita
(cast), mas por causa dos possíveis erros de arredondamento seu uso não é aconselhável.
• A estrutura switch não pode avaliar dados de outros tipos de dados, como boolean, nem instâncias
de outras classes, como String.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
84
14 {
15 case 1:
16 {
17 System.out.println("Você escolheu Matemática.");
18 break;
19 } // fim do case 1
20 case 2:
21 {
22 System.out.println("Você escolheu Física.");
23 break;
24 } // fim do case 2
25 case 3:
26 {
27 System.out.println("Você escolheu Biologia.");
28 break;
29 } // fim do case 3
30 default:
31 {
32 System.out.println("Você não escolheu nenhuma das disciplinas.");
33 } // fim do default
34 } // fim do switch
35 } // fim do método main
36 } // fim da classe DemoSwitch
Assim como a estrutura de comandos if, a estrutura switch pode ser usada dentro de métodos de classes
que implementam modelos, como mostrado no método toString() da classe na listagem 8.8.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
85
36 }
37 case 39: // código para Engenharia da Computação
38 {
39 dados = dados + "curso: Engenharia da Computação\n";
40 break;
41 }
42 case 42: // código para Biologia
43 {
44 dados = dados + "curso: Biologia\n";
45 break;
46 }
47 case 51: // código para Ciências Contábeis
48 {
49 dados = dados + "curso: Ciências Contábeis\n";
50 break;
51 }
52 default: // se não foi nenhum dos acima...
53 {
54 dados = dados + "curso não reconhecido !\n";
55 }
56 } // fim do switch
57 return dados; // retorna os valores da classe, formatados
58 } // fim do método toString
59 } // fim da classe Aluno
As estruturas de repetição em Java são chamadas coletivamente de laços. Em suas formas básicas elas
consideram uma condição que determine se o laço deve ser executado ou não, e executam um ou mais
comandos enquanto a condição especificada for válida ou verdadeira.
Uma tarefa inerente à execução de laços em Java é a modificação de variáveis que controlam a execução
dos laços (chamadas variáveis de controle). Frequentemente teremos que alterar o valor de uma variável
através da soma, subtração, multiplicação ou divisão desta mesma variável com outro valor. Java tem al-
guns operadores que podem ser usados em variáveis dos tipos inteiros e de ponto flutuante que são descritas
na lista abaixo.
• ++ Este operador, quando aplicado à uma variável dos tipos inteiros ou ponto flutuante, incremen-
tará o valor da variável em um. Exemplo: ao final do código double a = 12.5; a++; a variável
a valerá 13.5. O comando a++ poderia ser escrito como a = a + 1.
• -- Este operador, quando aplicado à uma variável, decrementará o valor da variável em um. Exem-
plo: ao final do código int z = 1982; z--; a variável z valerá 1981. O comando z-- poderia
ser escrito como z = z - 1.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
86
• += Este operador, quando aplicado à uma variável, incrementará o valor da variável usando o
argumento para o incremento. Exemplo: ao final do código short val = 800; val += 200; a
variável val valerá 1000. O comando val += 200 poderia ser escrito como val = val + 200.
• -= Este operador, quando aplicado à uma variável, decrementará o valor da variável usando o
argumento para o incremento. Exemplo: ao final do código float med = 49.5f; med -= 11.04;
a variável med valerá 38.46. O comando med -= 11.04 poderia ser escrito como med = med -
11.04.
• *= Este operador, quando aplicado à uma variável, multiplicará o valor presente da variável pelo
argumento passado, colocando o resultado na variável. Exemplo: ao final do código double j =
732.5; j *= 4; a variável j valerá 2930. O comando j *= 4 poderia ser escrito como j = j *
4.
• /= Este operador, quando aplicado à uma variável, dividirá o valor presente da variável pelo argu-
mento passado, colocando o resultado na variável. Exemplo: ao final do código int o = 2000; o
/= 12; a variável o valerá 166 (note que a divisão foi feita com números inteiros). O comando o
/= 12 poderia ser escrito como o = o / 12.
Um exemplo de laço while é mostrado na classe DemoWhile, na listagem 8.9. Neste programa, um laço
while será repetido até que um valor maior do que 1000 seja entrado via teclado.
Listagem 8.9: Uma classe com método main que usa o laço while
1 /* Uma classe com método main que demonstra a estrutura de controle while */
2 class DemoWhile
3 {
4 public static void main(String par[])
5 {
6 int valor = 0; // um valor para entrada e comparação - deve ser inicializado !
7 while(valor < 1000) // enquanto o valor for menor que mil
8 {
9 System.out.print("Entre um valor maior ou igual a 1000:");
10 valor = Keyboard.readInt(); // lemos o valor do teclado
11 } // fim do while
12 } // fim do método main
13 } // fim da classe DemoWhile
Um exemplo mais complexo do uso do laço while é mostrado na classe Escolha, na listagem 8.10. Esta
classe permite que uma faixa de valores do tipo short seja especificada e um valor que deve ser maior
ou igual ao limite inferior e menor ou igual ao limite superior seja entrado. Enquanto o valor entrado no
método escolhe() estiver fora da faixa o programa perguntará novamente. O controle do laço é feito por
uma variável booleana, que somente valerá true quando as condições forem satisfeitas.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
87
O laço while pode ser usado para tarefas que envolvem contagem, como mostrado no programa da lista-
gem 8.11. Neste caso, é importante que verifiquemos os valores iniciais das variáveis de controle, a sua
modificação e a condição de continuação dos laços, para evitar laços que não são executados ou que são
executados infinitamente. Em especial, devemos ter cuidado com o uso de laços contadores que comparem
valores para ver se são exatamente iguais ou diferentes de um valor: é possível que esta comparação não
retorne true.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
88
Podemos notar, na listagem 8.11, que o quarto laço (linhas 32 a 38) terminará quando a variável valor
valer 131072, mas somente os valores menores do que 100000 serão impressos.
O bloco ou comando associado ao laço será repetido enquanto o valor booleano for verdadeiro. A dife-
rença básica entre o laço while e o do-while é que o bloco de comandos associado ao laço do-while
será executado ao menos uma vez antes que a condição seja verificada, enquanto que o bloco de comandos
associado ao laço while poderá nem ser executado dependendo da primeira avaliação da condição.
Um exemplo de laço do-while é mostrado na classe DemoDoWhile, na listagem 8.12. A função deste
programa é a mesma da classe DemoWhile, na listagem 8.9.
Listagem 8.12: Uma classe com método main que usa o laço do-while
1 /* Uma classe com método main que demonstra a estrutura de controle do-while */
2 class DemoDoWhile
3 {
4 public static void main(String args[])
5 {
6 int valor; // desta vez não é necessária a inicialização
7 do
8 {
9 System.out.print("Entre um valor maior ou igual a 1000:");
10 valor = Keyboard.readInt(); // lemos o valor do teclado
11 } while(valor < 1000);
12 } // fim do método main
13 } // fim da classe DemoDoWhile
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
89
Como outro exemplo, a listagem 8.13 mostra a classe Agenda que usa o laço do-while em seu construtor
para garantir que um valor não vazio será passado para algumas variáveis.
Vemos nas linhas 14 e 19 da listagem 8.13 o método equals, que compara Strings - o operador == não
pode ser usado com Strings. Mais detalhes sobre os métodos de comparação de Strings são mostrados na
seção 9.3.
A estrutura de repetição for facilita a criação de laços com finalidade de contagem. Sua forma básica
é for(inicialização; verificação_de_condições; atualização) comando_ou_bloco;. A ini-
cialização será executada uma vez antes do início do laço, a verificação de condições a cada vez que o
comando ou bloco for executado e a atualização depois de cada execução do comando ou bloco.
O comando_ou_bloco associado ao laço pode ser um único comando, que deve ser terminado com um
ponto-e-vírgula, ou um bloco de comandos, que deve ser cercado por chaves ({ e }) O bloco ou comando
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
90
associado ao laço for será repetido enquanto a condição for verdadeira. É possível termos mais de um
comando na inicialização ou na atualização, se estes forem separados por vírgulas. O uso do laço for co-
mo um contador simples tem a forma for(variável = valor_inicial; variável < valor_final;
variável++) comando_ou_bloco;.
Um exemplo de laço for é mostrado na classe DemoFor, na listagem 8.14. O programa mostrado desenhará
um retângulo composto de asteriscos no terminal, com 32 asteriscos de lado e 8 de altura.
Listagem 8.14: Uma classe com método main que usa o laço for
1 /* Uma classe com método main que demonstra a estrutura de controle for */
2 class DemoFor
3 {
4 public static void main(String args[])
5 {
6 byte largura = 32;
7 byte altura = 8;
8 for(int a=0;a<altura;a++)
9 {
10 for(int l=0;l<largura;l++)
11 {
12 System.out.print("*");
13 } // fim do laço for com variável de controle l
14 System.out.println();
15 } // fim do laço for com variável de controle a
16 } // fim do método main
17 } // fim da classe DemoFor
Para exemplificar outro uso do laço for criaremos uma classe com métodos estáticos. A listagem 8.15
mostra a classe ProbabilidadeBasica, que usa as fórmulas comb = x!/(y!(x y)!) para calcular o
número comb de combinações que se pode ter tendo x valores e tomando-se y valores de cada vez e
perm = x!/(x y)! para calcular o número de permutações perm que se pode ter tendo x valores e tomando-
se y valores de cada vez. A classe também implementa o cálculo do fatorial, necessário às equações, usando
um laço for.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
91
20 return fatorial(quantos)/fatorial(quantos-tomados);
21 }
22 } // fim da classe ProbabilidadeBasica
A classe Agenda, mostrada na listagem 8.16, modifica o comportamento do construtor mostrado na lis-
tagem 8.13: este repetirá “para sempre” a leitura de dados através do comando while(true), e só sairá
deste laço infinito se algo diferente de uma String em branco for digitada.
Listagem 8.16: Uma classe cujo construtor usa o laço while e o comando break
1 /* Uma classe para guardar o nome e e-mail de uma pessoa. */
2 class Agenda
3 {
4 private String nome; // variável para guardar o nome
5 private String email; // variável para guardar o e-mail
6 /* Este é o construtor vazio. Caso seja chamado, este construtor irá perguntar o nome e
7 e-mail da classe via teclado, e não aceitará respostas em branco. */
8 Agenda()
9 {
10 while(true) // pergunta "para sempre" o nome até que seja dado um que não seja vazio
11 {
12 System.out.print("Entre o nome:");
13 nome = Keyboard.readString();
14 if (!nome.equals("")) break; // se o nome não for igual a "" sai do laço
15 }
16 while(true) // pergunta "para sempre" o e-mail até que seja dado um que não seja vazio
17 {
18 System.out.print("Entre o e-mail:");
19 email = Keyboard.readString();
20 if (!email.equals("")) break; // se o e-mail não for igual a "" sai do laço
21 }
22 }
23 /* Método que formata o conteúdo da classe e retorna como uma String */
24 public String toString()
25 {
26 return "Nome "+nome+" e-mail "+email+"\n";
27 }
28 } // fim da classe Agenda
O comando continue pode servir para que somente partes de um laço sejam executadas, como mostrado
no exemplo da listagem 8.17. Este programa lerá cinco valores do teclado, mas somente calculará o fatorial
dos valores positivos.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
92
3 {
4 public static void main(String args[])
5 {
6 int valor;
7 for(int contador=0;contador<5;contador++) // o valor será perguntado cinco vezes...
8 {
9 valor = Keyboard.readInt();
10 if (valor < 0) continue; // mas se for menor que zero o seu fatorial não será calculado
11 System.out.println("O fatorial de "+valor+" é "+ProbabilidadeBasica.fatorial(valor));
12 }
13 } // fim do método main
14 } // fim da classe DemoContinue
Exercício 8.2: ?
O programa mostrado na listagem 8.3 não é muito “inteligente” - se a idade for maior do que 65 ou menor
que 14, não existe necessidade de se perguntar o dia da semana, e se o dia da semana for terça, quarta ou
quinta, não existe necessidade de se perguntar a idade.
Para tornar o programa mais “inteligente” será necessário modificar a ordem das decisões e colocar blocos
if dentro dos blocos de comandos de outros if. Dica: tente resolver este exercício usando o exercício 8.1
como base. Note que existe mais de uma solução para este problema !
Exercício 8.3: ?
O que acontecerá se retirarmos todos os comandos else do método calculaPreço() da classe
AparelhoDeTV mostrada na listagem 8.5 ? Existe alguma vantagem em fazê-lo ?
Exercício 8.4: ?
Reescreva o construtor da classe Aluno para que este receba o curso como uma String e calcule, através de
comparações, o valor da variável curso (por exemplo, se o valor passado for “Engenharia da Computa-
ção”, o valor do curso será 39). Quais as vantagens e desvantagens desta abordagem ? Use a listagem 8.8
como referência.
Exercício 8.5: ?
Reescreva o método calculaPreço da classe AparelhoDeTV (listagem 8.5) para que um switch seja
usado ao invés de um bloco de ifs encadeados.
Exercício 8.6: ?
Reescreva o método main da classe DemoSwitch (listagem 8.7) para que um bloco de ifs encadeados
seja usado ao invés de um switch.
Exercício 8.7: ?
Reescreva o método toString da classe Aluno (listagem 8.8) para que um bloco de ifs encadeados seja
usado ao invés de um switch.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
93
Exercício 8.8: ?
Modifique o método retira da classe ContaBancaria (veja listagem 3.8) para que este somente efetue
a retirada se o valor da retirada for menor ou igual ao saldo corrente.
Exercício 8.9: ?
Escreva um programa em Java que conte de um até cem usando um bloco while.
Exercício 8.10: ?
Escreva um programa em Java que conte de um até cem usando um bloco do-while.
Exercício 8.11: ?
O que aconteceria se a variável valor valesse inicialmente 2000, na classe DemoWhile (listagem 8.9) ?
Exercício 8.12: ?
O programa abaixo poderá ser compilado mas seus laços contém erros de lógica. Localize e explique os
erros.
1 class ContadorComErros
2 {
3 public static void main(String argumentos[])
4 {
5 int valor;
6 valor = 100;
7 while(valor <= 0)
8 {
9 System.out.print(valor+" ");
10 valor++;
11 }
12 System.out.println();
13 valor = 100;
14 while(valor >= 100)
15 {
16 System.out.print(valor+" ");
17 valor += 5;
18 }
19 valor = 997;
20 while(valor != 1000)
21 {
22 System.out.print(valor+" ");
23 valor += 2;
24 }
25 System.out.println(valor);
26 }
27 }
Exercício 8.13: ?
Crie uma classe Histograma5 que contenha 5 valores inteiros, passados via um método ou construtor.
Esta classe deve ter um método imprime que recebe um caracter como argumento, e imprime histogramas
baseados nos cinco valores e caracter passado. Se para uma instância desta classe os valores 7, 2, 10, 3
e 12 fossem passados, e o caracter ’*’ fosse passado para o método imprime, este deveria imprimir o
histograma como mostrado abaixo:
*******
**
**********
***
************
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
94
Exercício 8.14: ?
Escreva um programa em Java (com o método main) que crie e use instâncias da classe Escolha (lista-
gem 8.10).
Exercício 8.15: ?
Modifique a classe Escolha (listagem 8.10) para que um laço do-while seja usado ao invés de um laço
while no método escolhe.
Exercício 8.16: ?
Escreva uma classe Tabuada com um método estático que imprima a tabuada de um valor passado para
este método como argumento. Use a estrutura de repetição mais apropriada.
Exercício 8.17: ?
Escreva uma classe TesteTabuada que imprima as tabuadas de um a dez, usando o método Tabuada
(exercício 8.16).
Exercício 8.18: ?
O valor de xy pode ser calculado como sendo x multiplicado por si mesmo y vezes (se y for inteiro).
Escreva um programa em Java que leia os valores de x e y do teclado e calcule xy .
Exercício 8.19: ?
Escreva um programa em Java com um laço que leia uma String do teclado e somente saia do laço se a
String for igual à uma palavra-chave qualquer (que deve ser declarada dentro do programa). Use o método
equals da classe String para fazer a comparação (veja linhas 14 e 19 da listagem 8.13).
Exercício 8.20: ?
Escreva um programa completo em Java que imprima todos os resultados da soma X + Y onde X e Y
variam de um a vinte e a soma seja igual à 21. Dica: dois laços podem ser usados, e o comando continue
pode “filtrar” os resultados indesejados.
Exercício 8.21: ?
Escreva um programa em Java que aceite dois valores inteiros via teclado: um multiplicador e um valor
máximo, e mostre todos os múltiplos do multiplicador que sejam menores do que o valor máximo.
Exercício 8.23: ? ?
Instâncias da classe Aluno (mostrada na listagem 8.8), quando inicializadas, pedem uma String para o
nome e um short para o curso. É possível criar uma instância desta classe que receba um valor errado
para o curso - qualquer valor diferente de 23, 27, 34, 39, 42 ou 51 não será reconhecido pelo método
toString() como válido.
Reescreva o construtor da classe para que se o valor passado for inválido, o construtor imprima uma
mensagem de erro e considere o curso como sendo zero.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
95
Exercício 8.24: ? ?
Crie a classe ContaBancariaEspecial que herda da classe ContaBancaria (listagem 3.8). A classe
ContaBancariaEspecial deve conter um valor booleano éEspecial, que indicará se a conta é especial
ou não. Se a conta for especial, o cliente pode retirar dinheiro da conta até ficar com 1000 reais de saldo
negativo. Altere o método retira para permitir isto.
Exercício 8.25: ? ?
Um problema potencial da classe Escolha (listagem 8.10) é que seu construtor não verifica se o valor
inicial é menor do que o final - se uma instância for construída com os valores(1000,-1000), o método
escolhe nunca terminará !
Reescreva o construtor de forma que se o valor inicial da faixa for maior do que o final, o construtor
trocará os valores, fazendo com que o final vire o inicial e vice-versa.
Exercício 8.26: ? ?
Escreva um programa em Java que simule uma calculadora bem simples. Este programa deve ler dois
valores de ponto flutuante do teclado, escolher uma operação (+, -, * ou /), calcular a operação e imprimir
o resultado. O programa deve considerar divisões por zero como sendo erros, e imprimir uma mensagem
adequada.
Exercício 8.27: ? ?
Reescreva o programa do exercício 8.19 de forma que o usuário do programa somente tenha três tentativas
para entrar a senha. Se em nenhuma das três tentativas o usuário acertar a senha, o programa mostra uma
mensagem de erro correspondente. Use um laço para isto.
Exercício 8.28: ? ?
Crie um método éIgual() na classe Ponto2D (listagem 5.8) que receba, como argumento, uma instância
da própria classe Ponto2D e retorne um valor booleano que será true se os valores x e y da instância
presente e da passada forem iguais, e false se forem diferentes.
Exercício 8.29: ? ?
Usando a classe Retangulo criada no exercício 3.31, crie nela um método contémPonto() que recebe
uma instância da classe Ponto2D (listagem 5.8) e retorna um valor booleano que será true se a instância
da classe Ponto2D estiver dentro do retângulo.
Exercício 8.30: ? ?
π2
Usando um programa em Java, mostre que a sequência infinita 1
12
+ 212 + 312 + 412 + 512 + · · · equivale a 6.
Exercício 8.31: ? ?
π4
Usando um programa em Java, mostre que a sequência infinita 1
14
+ 214 + 314 + 414 + 514 + · · · equivale a 90 .
Exercício 8.32: ? ?
π2
Usando um programa em Java, mostre que a sequência infinita 1
12
+ 312 + 512 + 712 + 912 + · · · equivale a 8.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
96
Exercício 8.33: ? ?
Usando um programa em Java, mostre que a sequência infinita 1
1⇥3 + 3⇥5
1
+ 5⇥7
1
+ 7⇥9
1
+ · · · equivale a
1/2.
Exercício 8.34: ? ?
Usando um programa em Java, mostre que a sequência infinita 1
1⇥3 + 2⇥4
1
+ 3⇥5
1
+ 4⇥6
1
+ · · · equivale a
3/4.
Exercício 8.35: ? ?
2+3 4+5 6 + · · · equivale a ln(2)
1 1 1 1 1 1
Usando um programa em Java, mostre que a sequência infinita 1
(0.6931471805599453).
Exercício 8.37: ? ? ?
Escreva uma classe Lanchonete em Java que represente o menu de uma lanchonete. Crie o método
imprime() que imprima o menu desta lanchonete (com um número associado a cada pedido), e o método
seleciona() que pergunta ao usuário qual opção do menu ele/a deseja comprar (perguntando o número
do pedido). Escreva também um programa que use uma instância desta classe.
Exercício 8.38: ? ? ?
Escreva uma classe RetanguloNaTela que represente retângulos que podem ser desenhados na tela (atra-
vés de chamadas à System.out.print e System.out.println, como na listagem 8.14). Os retângulos
devem ter variáveis para representar a largura e altura, o caracter que vai ser usado para desenhar a borda,
o caracter de preenchimento e um valor booleano que diz se o retângulo vai ser preenchido ou não. A
classe deve ter construtores e um método desenha que desenhará o retângulo. Como exemplo, se uma
instância da classe com o tamanho 12x5 fosse criada com o caracter x para borda, o caracter . para
preenchimento e o retângulo fosse preenchido, o resultado seria o mostrado abaixo:
xxxxxxxxxxxx
x..........x
x..........x
x..........x
xxxxxxxxxxxx
Exercício 8.39: ? ? ?
Crie um programa em Java que implemente um jogo simplificado de senha. Neste jogo, o usuário terá
10 chances para acertar o valor de um número inteiro entre 0 e 2000 através de tentativa e erro. A cada
chance, o usuário deve entrar um valor pelo teclado, e o programa deve dizer se o valor entrado é maior ou
menor do que o valor secreto. O jogo termina quando as chances acabam (derrota) ou quando o usuário
entra um valor igual ao valor secreto (vitória). Para simplificar, considere o valor secreto como sendo
constante no programa.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
97
Exercício 8.40: ? ? ?
O valor de π pode ser calculado pela série infinita 4 ⇥ 11 13 + 15 71 + 19 · · · , e pode ser calculado usando
um laço e um if dentro do laço. Este laço não pode ser infinito, devendo terminar depois de N iterações.
Escreva uma classe Matematica em Java que contenha o método estático calculaPi() que recebe um
valor N como argumento e retorna o valor calculado de π.
Exercício 8.41: ? ? ?
O valor de π também pode ser calculado pela série infinita 2 ⇥ 21 ⇥ 32 ⇥ 43 ⇥ 45 ⇥ 65 ⇥ 76 · · ·, e pode ser
calculado usando um laço e um if dentro do laço. Este laço não pode ser infinito, devendo terminar
depois de N iterações. Escreva um método estático na classe Matematica (veja exercício 8.40) chamado
calculaPiDeOutraForma() que recebe um valor N como argumento e retorna o valor calculado de π.
Exercício 8.42: ? ? ?
2
O valor ex (onde e é a base dos logaritmos naturais) pode ser calculado pela série infinita 1 + x + x2! +
x3 x4 x5
3! + 4! + 5! + · · ·. Escreva um método estático na classe Matematica (veja exercício 8.40) que receba um
valor inteiro N e um de ponto flutuante x e calcule a série considerando somente os N primeiros termos. O
fatorial de um número pode ser calculado usando o método fatorial na classe ProbabilidadeBasica
(listagem 8.15). Veja também o exercício 8.18.
Exercício 8.43: ? ? ?
x2 x2 x2
O seno de um ângulo x pode ser calculado pela série infinita x ⇥ (1 π2
) ⇥ (1 4π2
) ⇥ (1 9π2
) ⇥ (1
x2
16π2
) · · ·.
Escreva um método estático na classe Matematica (veja exercício 8.40) que receba um valor
inteiro N e um de ponto flutuante x e calcule a série considerando somente os N primeiros termos. O valor
de π pode ser obtido pelo método calculaPi() criado no exercício 8.40.
Exercício 8.44: ? ? ?
3 5 7 9
O seno de um ângulo x também pode ser calculado pela série infinita x x3! + x5! x7! + x9! · · ·. Escreva
um método estático na classe Matematica (veja exercício 8.40) que receba um valor inteiro N e um de
ponto flutuante x e calcule a série considerando somente os N primeiros termos. O fatorial de um número
pode ser calculado usando o método fatorial na classe ProbabilidadeBasica (listagem 8.15). Veja
também o exercício 8.18.
Exercício 8.45: ? ? ?
4x2 4x2 4x2
O coseno de um ângulo x pode ser calculado pela série infinita x ⇥ (1 π2
) ⇥ (1 9π2
) ⇥ (1 25π2
)⇥
2
(1 49π4x
2 ) · · ·. Escreva um método estático na classe Matematica (veja exercício 8.40) que receba um
valor inteiro N e um de ponto flutuante x e calcule a série considerando somente os N primeiros termos.
O valor de π pode ser obtido pelo método calculaPi() criado no exercício 8.40.
Exercício 8.46: ? ? ?
2 4 6 8
O coseno de um ângulo x também pode ser calculado pela série infinita 1 x2! + x4! x6! + x8! · · ·. Escreva
um método estático na classe Matematica (veja exercício 8.40) que receba um valor inteiro N e um de
ponto flutuante x e calcule a série considerando somente os N primeiros termos. O fatorial de um número
pode ser calculado usando o método fatorial na classe ProbabilidadeBasica (listagem 8.15). Veja
também o exercício 8.18.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
98
Exercício 8.47: ? ? ?
O valor sin(x)
x pode ser calculado pela série infinita cos( 2x ) ⇥ cos( 4x ) ⇥ cos( 8x ) ⇥ cos( 16
x
) ⇥ cos( 32
x
) ⇥ · · ·.
Escreva um programa em Java que utilize os métodos que calculam o seno e coseno na classe Matematica
e verifique esta igualdade.
Exercício 8.48: ? ? ?
A
⇣ tangente de um ângulo x ⌘ pode ser calculado pela série infinita 8x ⇥
1
π2 4x2
+ 9π2 1 4x2 + 25π21 4x2 + 49π21 4x2 · · · . Escreva um método estático na classe Matematica
(veja exercício 8.40) que receba um valor inteiro N e um de ponto flutuante x e calcule a série conside-
rando somente os N primeiros termos. O valor de π pode ser obtido pelo método calculaPi() criado no
exercício 8.40.
Exercício 8.49: ? ? ?
A ⇣ cotangente de um ângulo x⌘ pode ser calculado pela série infinita 1
x +
2x x2 π2 +
1
+1
x2 4π2
+ x2
1
x2 9π2
+ · · · Escreva um método estático na classe Matematica
1
16π2
(veja exercício 8.40) que receba um valor inteiro N e um de ponto flutuante x e calcule a série conside-
rando somente os N primeiros termos. O valor de π pode ser obtido pelo método calculaPi() criado no
exercício 8.40.
Exercício 8.50: ? ? ?
A
⇣ secante de um ângulo x ⌘pode ser calculado pela série infinita 4π ⇥
1
π2 4x2
3
9π2 4x2
+ 25π25 4x2 49π27 4x2 · · · . Escreva um método estático na classe Matematica
(veja exercício 8.40) que receba um valor inteiro N e um de ponto flutuante x e calcule a série conside-
rando somente os N primeiros termos. O valor de π pode ser obtido pelo método calculaPi() criado no
exercício 8.40.
Exercício 8.51: ? ? ?
A ⇣ cosecante de um ângulo x ⌘ pode ser calculado pela série infinita 1x
2x x2 1 π2 x2 14π2 x2 19π2 x2 116π2 · · · . Escreva um método estático na classe Matematica
(veja exercício 8.40) que receba um valor inteiro N e um de ponto flutuante x e calcule a série conside-
rando somente os N primeiros termos. O valor de π pode ser obtido pelo método calculaPi() criado no
exercício 8.40.
Exercício 8.52: ? ? ? ?
1 x3 1⇥3 x5 1⇥3⇥5 x7
O arcoseno de um ângulo x pode ser calculado pela série infinita x + 2 3 + 2⇥4 5 + 2⇥4⇥6 7 +
1⇥3⇥5⇥7 x9
2⇥4⇥6⇥8 9 + · · ·. Escreva um método estático na classe Matematica (veja exercício 8.40) que receba
um valor inteiro N e um de ponto flutuante x e calcule a série considerando somente os N primeiros
termos.
Exercício 8.53: ? ? ? ?
x 1 3
O logaritmo natural de um número x pode ser calculado pela série infinita 2 ⇥ { 11 x 1
x+1 + 31 x+1 +
x 1 5 x 1 7
1
5 x+1 + 17 x+1 + ···}
se x > 0. Escreva um método estático na classe Matematica (veja exercí-
cio 8.40) que receba um valor inteiro N e um de ponto flutuante x e calcule a série considerando somente
os N primeiros termos.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
99
Capítulo 9
A Classe String
9.1 Introdução
Em diversos programas e classes até agora, usamos instâncias da classe String para criar variáveis capazes
de representar cadeias de caracteres. Embora a classe String possa ser usada para criar instâncias simples,
por ser uma classe ela contém muitos métodos úteis. Nesta capítulo veremos os métodos mais úteis da
classe e exemplos de seu uso.
Um conceito importante sobre Strings é que instâncias desta classe são compostas de zero ou mais caracte-
res (valores do tipo char) enfileirados em ordem. Por exemplo, a String ”Java” é composta dos caracteres
’J’, ’a’, ’v’ e ’a’. O comprimento da String é dado pelo número de caracteres que esta contém: no
exemplo anterior, a String contém quatro caracteres. O índice de cada um dos caracteres indica a posição
deste na String: este índice pode valer entre zero e o valor do comprimento da String menos um. Por
exemplo, a posição do caracter ’J’ na String ”Java” é zero, e do caracter ’v’ na mesma String é dois. Os
índices na String podem estar entre zero e três.
Tentativas de acessar caracteres ou trechos de uma String usando índices fora da faixa de valores válidos
(0 · · · length() 1) causarão uma exceção chamada java.lang.StringIndexOutOfBoundsException
(exceções são categorias especiais de erros em Java, e serão vistas com detalhes no capítulo 12). Nestes
casos o programa em Java será terminado imediatamente.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
100
O método length() conta o número total de caracteres na String, mesmo espaços, caracteres que não
sejam letras e dígitos e caracteres de controle (caracteres usados para efeitos como quebra de linha, tabu-
lação, etc.): a String ”1\n2” contém três caracteres. Os caracteres de controle mais usados são mostrados
na tabela A.1 na seção A.2.1.
Outro método básico da classe String é o método charAt(), que recebe um único valor inteiro e retorna o
caracter cujo índice é o argumento passado. Este método retorna variáveis do tipo char, e não instâncias da
classe String. Exemplos de uso do método charAt() são mostrados no programa na listagem 9.2.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
101
Outra maneira de compararmos Strings é usando o método compareTo() que deve ser chamado a partir de
uma instância de uma String, recebe uma String como argumento e retorna um valor inteiro correspondente
à ordenação das duas Strings. As regras que determinam o resultado do método são:
• Quando a instância da classe String começa com a String passada como argumento, o valor será a
diferença (positiva) entre os comprimentos das Strings.
• Quando a String passada como argumento começa com a instância da classe String, o valor será a
diferença (negativa) entre os comprimentos das Strings.
• Quando as Strings forem exatamente iguais, o valor será zero.
• Quando as Strings não começarem uma com a outra, o valor será a diferença dos valores Unicode
dos primeiros caracteres diferentes das Strings.
• Quando uma das Strings for vazia, o valor será a diferença entre os comprimentos das Strings.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
102
Dois métodos podem ser usados para verificar se Strings são iniciadas ou terminadas com outra String: o
método startsWith() recebe uma String como argumento e retorna o valor booleano true se a String
que chama o método começa com a String que foi passada como argumento, e false se não. O método
endsWith() recebe uma String como argumento e retorna o valor booleano true se a String que chama
o método termina com a String que foi passada como argumento, e false se não. Os dois métodos são
demonstados no programa da listagem 9.5.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
103
18 System.out.println(s3.endsWith("eiro")); // true
19 // Outro exemplo: algoritmo simples e altamente falível para determinar
20 // através do nome de uma pessoa se esta pessoa é do sexo feminino.
21 System.out.print("Entre uma String:"); // Pergunto ao usuário
22 String nome = Keyboard.readString(); // Leio a String que ele/a digitar
23 if (nome.endsWith("a")) // Se esta String termina com "a" então...
24 System.out.println("É possivelmente feminino !");
25 }
26 } // fim da classe DemoStrings
É importante levar em consideração que quando uma String é modificada, seja através dos métodos mos-
trados nesta seção ou através da concatenação com o sinal +, uma nova instância da classe String é criada,
o que representa um certo esforço computacional adicional. Não existem métodos que modifiquem a ins-
tância da classe String que os chama: todos estes métodos mantém a String original inalterada e retornam
uma nova instância modificada.
Existem três métodos na classe String que permitem a modificação direta de seus caracteres: o método
replace() que substituirá todas as ocorrências de um caracter em uma String por outro caracter, o méto-
do toLowerCase() que transformará todos os caracteres maiúsculos em uma String em minúsculos, e o
método toUpperCase() que transformará todos os caracteres minúsculos em uma String em maiúsculos.
Estes três métodos são demonstrados no programa na listagem 9.6.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
104
27 s3 = s3.toUpperCase();
28 System.out.println(s3);
29 // modificação pode ser feita com "constantes" de Strings !
30 System.out.println("palavras".replace(’a’,’o’).replace(’a’,’x’));
31 }
32 } // fim da classe DemoStrings
Todos os métodos da classe String que retornam Strings podem ser usados de forma encadeada, como
mostrado nas linhas 18 e 19 do programa na listagem 9.6: desta forma, o resultado de uma chamada ao
método será uma String, que pode ter outro método chamado. No caso de métodos encadeados, as opera-
ções são executadas da esquerda para a direita: na linha 30 da listagem 9.6 os caracteres ’a’ serão trocados
primeiramente pelos caracteres ’o’ e o resultado da troca terá seus caracteres ’a’ trocados por ’x’ - uma
troca sem efeito uma vez que já não existem caracteres ’a’ na String.
Outros métodos para modificação de Strings são o método concat(), que recebe uma String como argu-
mento e concatena esta String à String que chamou o método, e trim(), sem argumentos, que elimina
espaços em branco no início e fim de uma String e retorna a String sem estes espaços. Exemplos de uso
destes métodos são mostrados na listagem 9.7.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
105
23 System.out.println(s6.length()); // comprimento é 48
24 System.out.println(s7.length()); // comprimento é 38
25 }
26 } // fim da classe DemoStrings
Podemos notar o encadeamento dos métodos na linha 14 do programa na listagem 9.7 - a ordem de con-
catenação é da esquerda para a direita. O resultado da execução deste método é igual ao da concatenação
com o sinal +, como mostrado pela linha 18 da listagem.
Exemplos de uso do método substring() (inclusive as versões polimórficas) são mostrados no programa
na listagem 9.8.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
106
Existem dois métodos polimórficos para procura de Strings: indexOf(), que recebe uma String como
argumento em uma das suas formas e retorna a posição da String passada dentro da String que chamou o
método ou o valor 1 se nada for encontrado. A segunda forma do método recebe uma String e um valor
inteiro, e procura a String a partir da posição passada.
O segundo método de procura é chamado lastIndexOf(), e em sua primeira forma recebe uma String
e retorna a posição daquela String ou 1 se nada for encontrado. A diferença entre este método e o
indexOf() é que o indexOf() procura a partir da primeira posição na String sendo procurada, enquanto
o lastIndexOf() procura a partir da última posição. A segunda forma do método lastIndexOf() tam-
bém recebe uma String e um valor numérico, e efetua a procura a partir da posição especificada pelo valor
numérico. Exemplos de usos dos dois métodos são mostrados no programa na listagem 9.9.
Exercício 9.2: ?
O que acontecerá à qualquer String quando chamarmos de modo encadeado o método trim() duas vezes
como no exemplo String a; a = a.trim().trim(); ?
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
107
Exercício 9.3: ?
Escreva um programa em Java que leia uma String do teclado e imprima seus caracteres, um por um.
Exercício 9.4: ?
Escreva um programa em Java que receba uma String e um valor numérico N do teclado, e imprima
somente os primeiros N caracteres da String. O programa deve verificar se N é um valor válido (menor
que o comprimento da String).
Exercício 9.5: ?
Escreva um programa em Java que leia uma String do teclado e imprima seus caracteres, um por um, na
ordem reversa (do último caracter para o primeiro).
Exercício 9.6: ?
Escreva um programa em Java que leia uma String do teclado e troque todas as vogais não acentuadas da
String pelo caracter ’?’.
Exercício 9.7: ?
Escreva um programa em Java que filtre uma String, de forma que a partir de uma String lida do teclado,
o programa crie uma nova String contendo somente os valores numéricos da String entrada. Por exemplo,
se a String entrada for ”1a2b09cd”, a String resultante deve ser ”1209”. Dica: você pode usar o método
estático isDigit() da classe Character (seção A.2.2.2)
Exercício 9.8: ?
Escreva um programa em Java que tenha um método chamado éURL que recebe uma String como argu-
mento e retorna o valor booleano true se esta String começa com ”http:” ou ”ftp:”.
Exercício 9.9: ?
Escreva um programa em Java que tenha um método chamado éGráfico que recebe uma String como
argumento e retorna o valor booleano true se esta String termina com ”.gif”, ”.jpg” ou ”.jpeg”.
Exercício 9.10: ?
Escreva um programa em Java que tenha um método chamado qualLing que recebe uma String como
argumento e retorna uma String correspondente à linguagem de programação correspondente aos últimos
caracteres da String passada como argumento. Por exemplo, se a String passada como argumento terminar
com ”.c” ou ”.h” o método deverá retornar a String ”C”. Se a String passada como argumento terminar
com ”.pas”, o método deverá retornar a String ”Pascal”. Se a String passada como argumento terminar
com ”.java”, o método deverá retornar a String ”Java”.
Exercício 9.11: ? ?
Escreva uma classe em Java que represente o nome completo de uma pessoa, composto de três Strings
(nome próprio, nome do meio e nome da família). Escreva nessa classe o método rubrica() que retorna
somente as iniciais do nome completo em caracteres minúsculos, e o método assinatura() que retorna
as iniciais dos nomes próprio e do meio (com pontos) e o nome de família completo. Por exemplo, se o
nome da pessoa representado por esta classe for ”Richard Langton Gregory”, o método rubrica()
deve retornar ”rlg” e o método assinatura() deve retornar ”R.L.Gregory”. Para facilitar, considere
armazenar os três nomes em Strings separadas.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
108
Exercício 9.12: ? ?
Escreva uma classe StringUtils com métodos estáticos. Escreva, nesta classe, vários métodos poli-
mórficos para comparação entre Strings (baseados nos métodos equals() e equalsIgnoreCase()), que
recebam duas ou mais Strings e retornem true se todas forem iguais e false se ao menos uma for
diferente das outras.
Exercício 9.13: ? ?
Escreva na classe StringUtils (veja exercício 9.12) um método que receba uma String como argumento,
conte e retorne o número de caracteres de uma String que são iguais a espaços.
Exercício 9.14: ? ?
Escreva na classe StringUtils (veja exercício 9.12) um método que receba uma String como argumento,
substitua todos os espaços desta String pelo caracter + e retorne a String nova.
Exercício 9.15: ? ?
Escreva na classe StringUtils (veja exercício 9.12) um método que receba uma como argumento e
desacentue esta String, isto é, troque todos os caracteres acentuados por caracteres correspondentes sem
acentos (’Ã’ por ’A’, ’ç’ por ’c’, etc), considerando todos os caracteres acentuados, maiúsculos e
minúsculos.
Exercício 9.16: ? ?
Escreva na classe StringUtils (veja exercício 9.12) um método que reverta a ordem dos caracteres de
uma String passada como argumento e retorne a String revertida. Um exemplo: se a String ”Java” for
passada para este método, ele deve retornar a String ”avaJ”. Dica: Use um laço for ou while e o método
charAt().
Exercício 9.17: ? ?
Uma String é dita palíndroma se ela pode ser lida da esquerda para a direita ou da direita para a esquerda
da mesma forma. As Strings ”radar”, ”asa” e ”O breve verbo” são palíndromas. Escreva um método
estático na classe StringUtils (veja exercício 9.12) que retorne true se uma String passada como
argumento for palíndromas e false se não for. Dica: use o exercício 9.16 como base.
Exercício 9.18: ? ?
Escreva na classe StringUtils (veja exercício 9.12) um método que conte quantas ocorrências de um
caracter existem em uma String. Dica: este método receberá uma String e um caracter como argumentos
e retornará um inteiro.
Exercício 9.19: ? ?
Escreva um programa em Java que receba uma String pelo teclado e conte quantas consoantes existem
nesta String. Dica: existem várias maneiras de resolver este problema - pense em ao menos duas e
considere qual é a mais simples.
Exercício 9.20: ? ?
Escreva um programa em Java que receba uma String pelo teclado e imprima todas as ocorrências de
duas letras iguais uma após a outra. Por exemplo, se este programa receber a String ”irrepreensível”,
deverá imprimir como resultado ”rr” e ”ee”. Dica: use um laço e o método charAt().
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
109
Exercício 9.21: ? ?
Escreva um método estático na classe StringUtils (veja exercício 9.12) que receba duas Strings e re-
torne o valor booleano true se a primeira String contiver todos os caracteres da segunda String, em
qualquer ordem. Por exemplo, se as Strings ”Abracadabra” e ”cabra” forem passadas como argumen-
tos, o método deverá retornar true, mas se as Strings ”Abracadabra” e ”cobra” forem passadas como
argumentos, o método deverá retornar false. Note que este método é diferente do indexOf() porque
”Abracadabra”.indexOf(”cabra”) equivale a false.
Exercício 9.22: ? ?
Escreva um programa em Java que receba uma String do teclado, e separe esta String em duas: uma
contendo as letras da String entrada e outra contendo os dígitos da String. Por exemplo, se a String
”abc12d3e4f56” for entrada, o programa deve criar as Strings ”abcdef” e ”123456” como saída. Use
o exercício 9.7 como base.
Exercício 9.23: ? ?
Em um jogo de tabuleiro chamado Palavras Cruzadas, cada palavra formada vale um certo número de
pontos, que depende das letras usadas. O score para as letras do alfabeto é dado por:
Por exemplo, o score para a palavra ”Java” no jogo será 8 + 1 + 4 + 1 = 14 pontos. Escreva um programa
ou rotina em Java que, a partir de uma String, calcule o score que esta String teria no jogo.
Exercício 9.24: ? ?
Escreva um método estático na classe StringUtils (veja exercício 9.12) que receba que receba uma
String e um inteiro como argumentos e “centralize” a String adicionando espaços no seu início e fim de
forma que o comprimento final da String seja igual ao valor passado como argumento. Por exemplo,
se a String ”Java1” e o valor 20 forem passados como argumento, o método deverá adicionar espaços
no início e no fim da String até que seu comprimento seja exatamente 20 caracteres. Se o comprimento
da String passada já for maior que o valor passado como argumento, o método deve retornar a String
inalterada.
Exercício 9.25: ? ?
O método replace() da classe String somente substitui um único caracter por vez. Escreva um método
estático replaceMultiple() na classe StringUtils (veja exercício 9.12) que receba três Strings como
argumentos: a primeira é a String que sofrerá as modificações, a segunda String conterá os caracteres
que serão substituídos pelos caracteres correspondentes na terceira String. A segunda e terceira Strings
devem ter exatamente o mesmo número de caracteres. Este método retornará uma String. Por exemplo,
se o método for chamado como StringUtils.replaceMultiple(”Paralelepípedo”,”alp”,”xyz”)
o resultado deverá ser ”Pxrxyeyezízedo” (’a’ foram trocados por ’x’, ’l’ foram trocados por ’y’ e
’p’ foram trocados por ’z’).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
110
Exercício 9.26: ? ?
Escreva um programa em Java que leia uma String do teclado e remova todas as vogais desta String. Não
basta simplesmente imprimir somente as consoantes da String - é necessário criar uma nova String que
só contenha as consoantes.
Exercício 9.27: ? ? ?
Escreva um programa com o método main() em Java que funcione como uma calculadora bem básica:
três argumentos devem ser passados para o programa, sendo que o primeiro deve ser uma String contendo
um valor, o segundo um dos caracteres +, -, * ou /, e o terceiro outra String contendo um valor. O
programa deve receber estes três argumentos e efetuar uma operação neles, de forma que se os argumentos
passados forem ”12.5 * 4” o programa deve calcular a operação 12.5 ⇥ 4 e imprimir o resultado. O
programa deve ser capaz de reconhecer e tratar os erros básicos (Strings que não contém valores, sinais
diferentes dos esperados, divisões por zero).
Dica: a conversão de Strings para valores do tipo double pode ser feita com o método valueOf() da
classe Double, descrita na seção A.2.2.7 do capítulo A.
Exercício 9.28: ? ? ?
Considerando o exercício 9.27, escreva um programa em Java com o método main() que funcione como
uma calculadora para soma e multiplicação somente, mas que aceite vários valores da linha de comando,
onde o primeiro é o sinal da operação + ou * e os outros são os valores a serem somados ou multiplicados.
Por exemplo, se os argumentos passados na linha de comando forem + 3 8 7 1.6 2.1 o programa deve
calcular a soma destes valores e imprimir o resultado (neste caso, 21.7).
Dica: a conversão de Strings para valores do tipo double pode ser feita com o método valueOf() da
classe Double, descrita na seção A.2.2.7 do capítulo A.
Exercício 9.29: ? ? ?
O algoritmo rot13 de ofuscação de Strings é um dos métodos mais simples (e menos eficientes) de crip-
tografia de Strings que existe: para cada caracter na String que seja uma letra de A a Z, o algoritmo
substitui este caracter por uma treze posições depois: ’A’ é trocada por ’N’, ’m’ é trocada por ’z’, ’R’
é trocada por ’E’, etc. (as letras são consideradas cíclicas, isto é, depois do ’Z’ vem o ’A’, etc.). Um
ponto interessante deste algoritmo é que o mesmo pode ser usado para codificar e decodificar Strings:
quando o algoritmo é usado em uma String, por exemplo, ”Java”, o resultado será ”Wnin”, e quando a
String ”Wnin” for codificada pelo algoritmo, o resultado será ”Java”.
Escreva um método estático na classe StringUtils (veja exercício 9.12) que implemente o algoritmo
rot13, recebendo uma String como argumento e retornando outra String criptografada. Este método deve
considerar que somente as letras não-acentuadas devem ser criptografadas, as letras acentuadas, números,
espaços e outros símbolos devem continuar como estão.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
111
Exercício 9.30: ? ? ?
O Algoritmo de César de criptografia de Strings é uma versão melhorada do algoritmo rot13 (veja exer-
cício 9.29): o seu funcionamento é o mesmo, só que em vez de substituir cada caracter por um caracter
treze posições depois, o algoritmo de César recebe um valor chamado chave, e usa este valor como o
número de posições que devem ser puladas para a criptografia. Por exemplo, se a chave for 1 o algoritmo
pulará uma posição ao codificar as letras, então se a String passada for ”Java”, o resultado será ”Kbwb”.
O algoritmo de decodificação deve receber a mesma chave só que deve substituir os caracteres da String
por valores em posições anteriores.
Escreva um método estático na classe StringUtils (veja exercício 9.12) que implemente o Algoritmo
de César, recebendo uma String e uma chave (valor numérico) como argumento e retornando outra String
criptografada. Este método deve considerar que somente as letras não-acentuadas devem ser criptografa-
das, as letras acentuadas, números, espaços e outros símbolos devem continuar como estão. Dica: Para
simplificar o algoritmo, considere que o valor da chave só pode estar entre 1 e 25.
Exercício 9.31: ? ? ?
Escreva uma classe StringDNA que seja capaz de processar uma String de DNA. Strings de DNA são
Strings que são formadas exclusivamente pelos caracteres ’A’, ’C’, ’G’ e ’T’ - nenhum outro caracter é
permitido. Esta classe deve encapsular uma String e conter ao menos os seguintes métodos:
• Construtor, que recebe uma String normal como argumento e copia-a para a String encapsulada
pela classe se a passada por argumento estiver dentro dos parâmetros exigidos (isto é, se a String
passada for ”CATGATTAG”, a String encapsulada será ”CATGATTAG”, mas se a String passada for
”JAVA”, a String encapsulada será vazia).
• toString(), que retorna a String encapsulada,
• charAt(), que retorna o caracter na posição que for passada como argumento,
• quantosA(), quantosC(), quantosG() e quantosT(), que retornam, respectivamente, quantos
caracteres ’A’, ’C’, ’G’ e ’T’ existem na String encapsulada,
• length(), que retorna o comprimento da String encapsulada.
Exercício 9.32: ? ? ?
Crie, na classe StringDNA (veja exercício 9.31), o método compara() que recebe uma instância da pró-
pria classe StringDNA para comparação e retorna um valor inteiro, calculado com o seguinte algoritmo:
Exemplo: Se a instância da classe StringDNA conter a String ”ACATTG” e para o método compara() for
passada a String ”ATTCCG”, o valor a ser retornado será 3 + 0 + 1 + 0 + 0 + 3 = 7.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
112
Exercício 9.33: ? ? ?
O método replace() da classe String considera caracteres maiúsculos e minúsculos como sendo diferen-
tes: o resultado de ”AbracadabrA”.replace(’a’,’o’) será ”AbrocodobrA” e não ”ObrocodobrO”.
Escreva um método estático replaceIgnoreCase() na classe StringUtils (veja exercício 9.12) que
faça a troca de caracteres maiúsculos e minúsculos simultaneamente, de forma que quando chamarmos
o método através de StringUtils.replaceIgnoreCase(”AbracadabrA”,’a’,’o’) o resultado seja
”ObrocodobrO”. Dica: Basta fazer um replace() duas vezes dentro do método, uma para o carac-
ter maiúsculo e uma para o minúsculo. Você pode passar um caracter de maiúsculo para minúsculo
convertendo-o para uma String, usado o método toUpperCase() ou toLowerCase() e extraindo o ca-
racter da String com o método charAt().
Exercício 9.34: ? ? ?
Escreva um método estático removeMultipleSpaces() na classe StringUtils (veja exercício 9.12)
que, recebendo uma String como argumento, remova espaços múltiplos na String e retorne a String re-
sultante. Por exemplo, se a String ”Uma String com muitos espaços redundantes” for
passada, o método deve retornar a String ”Uma String com muitos espaços redundantes”.
Exercício 9.35: ? ? ?
Escreva um método estático subtractChars() na classe StringUtils (veja exercício 9.12) que, rece-
bendo duas Strings como argumentos, retorne uma String que é a subtração dos caracteres da segunda
String passada como argumento dos caracteres da primeira String. O método deve considerar caracteres
maiúsculos e minúsculos como sendo iguais. Por exemplo, se as Strings ”Abracadabra” e ”cabra”
forem passadas como argumentos, o algoritmo deve remover uma de cada uma das letras de ”cabra”
da palavra ”Abracadabra”, resultando em ”adabra”. Se algum caracter da segunda String não existir
na primeira, o método deve retornar uma String vazia (exemplo: se a segunda String for ”praxe” e a
primeira for ”paralelepípedo”, a subtração não poderá ser efetuada.)
Exercício 9.36: ? ? ? ?
Escreva uma classe Formata que contenha vários métodos estáticos para formatação de valores dos tipos
int, long, float e double para impressão. Estes métodos devem receber os valores como argumentos
e retornam Strings contendo os valores formatados. Os métodos para impressão de valores dos tipos
int e long devem receber um valor inteiro adicional que representa o número de casas que se deseja
na impressão - neste caso, o número de dígitos que se deseja representar. Os métodos para impressão
de valores dos tipos float e double devem receber dois valores inteiros adicionais, um para representar o
número total de dígitos para impressão e outro para representar o número de valores após o ponto decimal.
Estes métodos devem prever e tratar o caso de valores de ponto flutuante que usem a notação científica,
como por exemplo 1.34e12.
Dicas: você pode usar polimorfismo para ter métodos com o mesmo nome mas que serão chamados de
acordo com os tipos de dados passados. Um valor de qualquer dos tipos previstos pode ser transformado
em uma String através da adição de um espaço vazio ao valor. Exemplo: se a variável a conter o valor
inteiro 12345, ela pode ser convertida para uma String através da operação ””+a.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
113
Exercício 9.37: ? ? ? ?
Escreva um programa em Java com uma rotina que converta Strings de caracteres para Strings em código
morse e vice-versa. No código morse, caracteres são representados por pontos (correspondentes a um
impulso elétrico curto) e traços (correspondentes a um impulso elétrico longo). Os caracteres básicos e
seus correspondentes em código morse são mostrados abaixo:
a .- b -... c -.-. d -.. e . f ..-. g -.
h .... i .. j .-- k -.- l .-.. m - n -.
o -- p .-. q -.- r .-. s ... t - u ..-
v ...- w .- x -..- y -.- z -.. ponto .-.-.- vírgula -..-
A cada caracter que for codificado, um espaço deve ser adicionado à String de saída. A rotina deve
considerar caracteres maiúsculos e minúsculos como sendo equivalentes, e ignorar outros símbolos.
Exemplo: se uma String ”Farfalhar” for passada para a rotina, esta deve retornar ”..-. .- .-. ..-.
.- .-.. .... .- .-.”.
Dica: para decodificação de código morse para caracteres, use os espaços que devem existir na String
codificada como delimitadores dos caracteres do código morse. Se algum código morse não tiver caracter
correspondente (exemplo, ---), use o caracter ? para saída.
Exercício 9.38: ? ? ? ?
Escreva, na classe StringUtils (veja exercício 9.12), vários métodos polimórficos chamados ordena()
que recebem diferentes números de argumentos, todos Strings, e imprimam estas Strings ordenadas.
Por exemplo, uma chamada ao método StringUtils.ordena(”alface”,”alfabeto”,”alforria”)
deve imprimir ”alfabeto alface alforria” como resultado. Dica: use os métodos length() e
compareTo() da classe String para efetuar as comparações.
Exercício 9.39: ? ? ? ?
Uma String contendo RNA é composta somente dos caracteres ’A’, ’C’, ’G’ e ’U’ - nenhum outro
caracter é permitido. Escreva uma classe StringRNA que herde da classe StringDNA (exercício 9.31) e
implemente os mesmos métodos da classe StringDNA. Quais métodos devem ser sobreescritos ?
Exercício 9.40: ? ? ? ?
O Algoritmo de César (veja o exercício 9.30) pode ser implementado de maneira mais eficiente, se ao
invés de uma única chave, várias forem usadas. O primeiro caracter da String será codificado com a
primeira chave, o segundo caracter com a segunda chave, etc. Quando as chaves acabarem, a primeira
será reutilizada, até o final da String a ser codificada. A chave pode ser especificada por outra String,
onde cada caracter tem um valor numérico correspondente, de forma que a String ”AEIY” corresponde
a quatro chaves 1, 5, 9, 25. Desta forma, se a String ”Programa” fosse codificada com a chave ”aeb”
(correspondente aos valores 1, 5 e 2, o resultado seria ”Qwqhwcnf” (’P’ foi adicionada a 1 e o resultado
é ’Q’, ’r’ foi adicionada a 5 e o resultado é ’w’, ’o’ foi adicionada a 2 e o resultado é ’q’, ’g’ foi
adicionada a 1 e o resultado é ’h’, ’r’ foi adicionada a 5 e o resultado é ’w’, etc.) - notem o uso cíclico
dos valores da chave.
Escreva um método estático na classe StringUtils (veja exercício 9.12) que implemente o Algoritmo
de César modificado, recebendo uma String e uma chave (outra String) como argumento e retornando
outra String criptografada. Este método deve considerar que somente as letras não-acentuadas devem ser
criptografadas, as letras acentuadas, números, espaços e outros símbolos devem continuar como estão.
Dica: Para simplificar o algoritmo, considere que o valor da chave só pode estar entre 1 e 26, ou seja, as
letras ’A’ a ’Z’. O algoritmo de codificação deve verificar se a String passada como chave é válida, ou
seja, se ela contém somente caracteres maiúsculos na faixa prevista.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
114
Exercício 9.41: ? ? ? ?
O Algoritmo fatiado de codificação recebe uma String como argumento e produz uma outra String como
resultado, e pode ser descrito da seguinte forma: enquanto a String de entrada tiver caracteres, remo-
va o primeiro e o último caracteres da String de entrada e os coloque na String de saída. Desta for-
ma, se a String ”Programação em Java” for entrada no algoritmo, este mostrará como saída a String
”ParvoagJr ammea çoã”. A decodificação de uma String pode ser feita da seguinte forma: crie duas
Strings temporárias, e para cada par de caracteres extraídos da String codificada de entrada adicione o
primeiro no fim da primeira String e o segundo no início da segunda String. A concatenação das duas
Strings é o resultado da decodificação.
Escreva uma classe em Java com métodos estáticos para codificar e decodificar uma String usando este
argumento. Escreva também um programa que demonstre usos desta classe.
Exercício 9.42: ? ? ? ? ?
Escreva um programa que leia uma String do teclado e converta esta String para o alfabeto braille A figura
abaixo mostra o alfabeto braille simplificado, onde um círculo preenchido significa uma marca em relevo
no papel. Cada letra maiúscula que aparecer no texto deve ser precedida pelo caracter maiúsculo do
alfabeto braille. Cada dígito que aparecer no texto deve ser precedido pelo caracter dígito do alfabeto
braille. No caso dos dígitos, os caracteres braille correspondentes a ’a’, ’b’, ’c’ ... ’i’, ’j’ são usados
para representar os dígitos ’1’, ’2’, ’3’ ... ’9’, ’0’. Para simplificar, considere que as Strings a serem
convertidas não contém acentos nem símbolos, e que um espaço em braille pode ser representado por um
caracter braille sem nenhuma marca em relevo.
a b c d e f g h i j k l m n
o p q r s t u v w x y z maiúsculo dígito
A saída do programa pode ser feita usando os caracteres de texto ’X’ para representar uma marca em
relevo, ’.’ para representar uma posição onde não há marca em relevo, e o espaço para separar uma letra
do alfabeto braille de outra. Assim, se a String ”Java 123” for entrada, a saída deverá ser:
.. .X X. X. X. .. .X X. .X X. .X XX
.. XX .. X. .. .. .X .. .X X. .X ..
.X .. .. XX .. .. XX .. XX .. XX ..
Dica: Para cada String entrada, três Strings deverão ser criadas na saída, cada uma com uma “linha”
de pontos dos caracteres braille. O comprimento destas três Strings é igual, mas deve ser calculado
verificando-se se a String de entrada tem caracteres maiúsculos e dígitos.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
115
Exercício 9.43: ? ? ? ? ?
Aminoácidos são definidos por conjuntos de três caracteres em Strings de RNA, sendo que cada aminoá-
cido pode ter mais do que um conjunto de três caracteres correspondentes. Existem vinte aminoácidos,
mas algumas combinações de três caracteres formam um sinal de término. Os vinte aminoácidos e o sinal
de término, seus símbolos (entre parênteses) e as combinações correspondentes são:
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
116
Capítulo 10
Arrays em Java
10.1 Introdução
Arrays 1 são estruturas de dados em Java que permitem o armazenamento de várias variáveis de um mesmo
tipo ou instâncias de uma mesma classe sob o mesmo nome. Cada um dos valores individuais (ou elementos
do array) será acessado através de um índice, mas sob certas condições o array pode ser processado como
uma única entidade, simplificando bastante programas e classes que tem necessidade de várias variáveis
ou instâncias. A maior vantagem do uso de arrays é que estes dispensam a necessidade de declaração de
várias variáveis individuais quando necessário.
Por exemplo, em um programa ou classe onde fosse necessário o armazenamento de cem variáveis do
mesmo tipo que representam de alguma forma o mesmo tipo de dado, seria complicado e sujeito a erros
a representação destes dados um em cada variável do tipo necessário. Similarmente, ao representar uma
turma de 45 alunos seria muito complicado e trabalhoso criar 45 instâncias diferentes da classe Aluno e
manipulá-las uma a uma. Alguns exemplos ilustrativos de arrays são mostrados na figura 10.1.
0 1 2 3 4 5 6 7 0 "Programação"
1 4 2 5 0 −9 7 −2 1 "Encapsulamento"
2 "Polimorfismo"
Na figura 10.1, à esquerda, vemos um array de oito valores numéricos, que pode ser representado por uma
única variável. Acima dos valores nas caixas vemos valores inteiros que representam os índices, que sem-
pre são começados por zero. À direita vemos um array de Strings com três Strings, com os índices 0, 1 e 2
apontando para diferentes Strings.
Java permite a criação de arrays de tipos nativos (como int, short, double, etc.) e de instâncias de classes
já existentes ou criadas pelo programador. Arrays podem ter uma ou mais dimensões: um array de uma
dimensão pode ser comparado com um vetor matemático, um array de duas dimensões com uma matriz.
1 Arrays também são conhecidos como vetores, mas como existe uma classe chamada Vector em Java (que será vista na
seção 14.1), usaremos a palavra array para denotar o tipo de estrutura vista neste capítulo.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
117
Variáveis do tipo array somente podem conter um tipo de dados: se o array é declarado como array de boo-
leanos, todos os elementos deste array serão booleanos: não podemos misturar valores booleanos, inteiros
e outros no mesmo array. Similarmente, não podemos declarar o array como sendo de um tipo de dados
e alocá-lo como sendo de outro tipo: o tipo de declaração e de alocação deve ser obrigatoriamente o mesmo.
O valor colocado entre os colchetes quando o array é alocado irá especificar o número de posições no ar-
ray, ou seja, quantos valores diferentes poderão ser armazenados na mesma variável. Os índices que serão
usados para acessar os valores individuais dos arrays deverão estar na faixa 0 · · · N 1 onde N é o número
de posições. Somente valores inteiros podem ser usados como índices para os arrays. Desta forma, o valor
números[8] corresponde à nona posição do array números. Depois que o array é alocado, não é possível
modificar o número de posições que ele contém.
É importante reconhecer que o valor que indica qual elemento do array está sendo processado, e que é
passado entre os colchetes, não precisa ser necessariamente uma constante, podendo ser uma variável ou
mesmo o resultado de uma expressão. Como um array é geralmente usado para representar vários va-
lores em uma única variável, é muito comum usarmos um laço para iterar entre todos os elementos do
array. Similarmente, o número de elementos de um array (especificado quando alocamos memória para
ele) não precisa ser uma constante, podendo ser uma variável de tipo inteiro ou mesmo o resultado de
uma expressão, mas deve ser obrigatoriamente um número inteiro positivo, caso contrário um tipo de erro
especial de Java, chamado exceção, irá ocorrer. Exceções são explicadas com detalhes no capítulo 12.
No caso específico de valores negativos passados usados para especificar o número de elementos do array,
a exceção java.lang.NegativeArraySizeException irá ocorrer e o programa irá parar na linha do erro.
A listagem 10.1 mostra um programa em Java que declara, aloca e popula um array. Os valores são entra-
dos em um array através de um laço for que fará com que cada valor do array seja lido do teclado. Após a
leitura os valores serão impressos.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
118
Existe outra forma alternativa de alocação e inicialização de arrays, que pode ser usada quando o array tiver
valores iniciais default e poucos elementos. Esta forma recebe como argumento adicional os valores que
serão colocados no array, separados por vírgulas e colocados entre chaves. Desta forma não é necessário
informar diretamente ao compilador Java quantos elementos o array deve conter, nem usar a palavra-chave
new para alocar memória para o array. Esta forma é demonstrada no programa na listagem 10.2.
A forma de inicialização de arrays mostrada nas linhas 8, 10 e 12 da listagem 10.2 só pode ser usada se
declararmos e inicializarmos os arrays com o mesmo comando: não podemos declarar os arrays e depois,
em outro comando, inicializá-los diretamente.
Arrays em Java contém uma variável interna chamada length que indica quantas posições o array tem.
Esta variável interna é bastante usada quando queremos passar um array como argumento para uma função
ou método, como visto no exemplo na listagem 10.3 (linha 7).
Listagem 10.3: Um programa que demonstra a passagem de arrays como argumentos para métodos
1 /* Esta classe demonstra a passagem de arrays como argumentos para métodos */
2 class DemoArray
3 {
4 /* Método que imprime um array de longs */
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
119
Na listagem 10.3 vemos que o tamanho do array que é passado para um método é indiferente, o que importa
é o tipo do array que é passado.
Arrays se comportam internamente como referências à objetos, significando que se fizermos cópias dos
arrays através da atribuição de variáveis, qualquer modificação feita à cópia será refletida no array original,
e vice-versa. Esta característica é demonstrada no programa na listagem 10.4.
Listagem 10.4: Um programa que mostra que arrays se comportam como referências
1 /* Esta classe demonstra que arrays são referências a objetos */
2 class DemoArray
3 {
4 /* Este método inicializa os valores de um array com zeros */
5 static void zeraArrayDeDoubles(double umArray[])
6 {
7 for(int contador=0;contador<umArray.length;contador++) // para todos elementos do array
8 umArray[contador] = 0; // zeramos o elemento
9 }
10 /* Método que permite a execução da classe */
11 public static void main(String parâmetros[])
12 {
13 // declaramos e alocamos espaço para um array de 5 posições de doubles
14 double meuArray[] = new double[5];
15 // preenchemos ele com alguns valores
16 meuArray[0] = 9; meuArray[1] = 8; meuArray[2] = 3; meuArray[3] = 1; meuArray[4] = 5;
17 // declaramos (sem alocar !) um outro array de doubles
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
120
18 double outroArray[];
19 // criamos uma cópia do array através de atribuição simples de variáveis
20 outroArray = meuArray;
21 // chamamos o método zeraArrayDeDoubles com meuArray como argumento
22 zeraArrayDeDoubles(meuArray);
23 // imprimimos o conteúdo do meuArray
24 for(int i=0;i<meuArray.length;i++)
25 System.out.print(meuArray[i]+" ");
26 System.out.println();
27 // imprimimos o conteúdo do outroArray
28 for(int i=0;i<outroArray.length;i++)
29 System.out.print(outroArray[i]+" ");
30 System.out.println();
31 }
32 } // fim da classe DemoArray
Ao executarmos o programa na listagem 10.4, verificaremos que ao final do programa o array meuArray
estará com os elementos zerados, pois uma cópia deste foi criada e manipulada quando passamos o array
como argumento para o método zeraArrayDeDoubles. O array outroArray também estará zerado pois
ele é somente uma referência ao array meuArray.
Os índices para os arrays devem estar entre os valores 0 e N 1, onde N é o tamanho do array (número de
elementos que ele contém), caso contrário uma exceção irá ocorrer e o programa irá parar na linha do erro.
A listagem 10.5 mostra um programa onde este tipo de erro pode ocorrer.
Listagem 10.5: Um programa que demonstra erros potenciais relacionados à índices de arrays
1 /* Esta classe demonstra erros possíveis relativos aos índices dos arrays */
2 class ErroArray
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Declaro e ao mesmo tempo aloco um array chamado quadrados que conterá 100 doubles
8 double quadrados[] = new double[100];
9 // Um laço de 0 a 99 calculará os quadrados e populará o array
10 for(int contador=0;contador<=99;contador++) // a variável contador só valerá dentro do for !
11 quadrados[contador] = contador*contador; // cada elemento conterá o quadrado do seu índice
12 // os valores já foram lidos, vamos entrar em um laço
13 boolean continua = true;
14 while(continua) // enquanto a variável continua for verdadeira
15 {
16 System.out.print("Entre um número de 0 a 99:"); // imprime a pergunta
17 int valor = Keyboard.readInt(); // declaro a variável, que receberá a resposta
18 // imprimo o valor entrado e seu quadrado
19 System.out.println("O quadrado de "+valor+" é "+quadrados[valor]);
20 System.out.print("Quer continuar ? (S/N):"); // imprime a pergunta
21 continua = Keyboard.readBoolean(); // recebe a resposta na variável continua
22 } // fim do while
23 } // fim do método main
24 } // fim da classe ErroArray
O problema do programa na listagem 10.5 é que nada impede o usuário de digitar valores fora da faixa
0 · · · 99, e caso um valor fora da faixa seja entrado, o programa será interrompido com uma mensagem
dizendo que houve uma exceção do tipo java.lang.ArrayIndexOutOfBoundsException (tentativa de
acesso à elemento do array fora da faixa de valores válidos).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
121
Uma maneira de evitar este problema usando orientação a objetos é encapsular o array em uma classe, e só
permitir o acesso aos dados do array através de métodos desta classe, como mostrado na listagem 10.6.
Esta classe pode ser usada em um programa, como mostrado na listagem 10.7.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
122
O encapsulamento do array em uma classe (listagens 10.6 e 10.7) oferece as seguintes vantagens, quando
comparado com o uso direto (listagem 10.5):
• O array é alocado e seus valores inicializados em uma única operação, no construtor da classe.
• Usuários do array não podem modificar seus valores, já que o array é declarado como privado da
classe. Seu acesso somente pode ser feito para leitura, através do método quadrado(). Se fosse
necessário, outros métodos poderiam possibilitar o acesso para modificação dos elementos do array.
• O método de acesso quadrado() implementa um mecanismo simples de tratamento de erros (evi-
tando a ocorrência da exceção java.lang.ArrayIndexOutOfBoundsException).
O encapsulamento de arrays dentro de classes traz ainda outras vantagens em potencial: podemos criar
nas classes métodos que façam operações úteis ou necessárias no array, como demonstrado pelos métodos
maiorValor() e menorValor() da classe ArrayDeFloats, mostrada na listagem 10.8.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
123
O programa mostrado na listagem 10.9 exemplifica o uso da classe ArrayDeFloats criando duas instâncias
da classe e usando seus diversos métodos.
Como exemplo, considere uma classe Teste (que contenha o método main()). Quando esta classe for
executada com o comando java Teste, o array de Strings declarado dentro do método main() terá com-
primento zero, ou seja, será vazio. Se a mesma classe for executada com o comando java Teste a1 b2
3 4 5, o array de Strings declarado dentro do método main() terá comprimento 5, e seus elementos serão
a1, b2, 3, 4 e 5 (todos são instâncias da classe String).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
124
A linha de comando é um mecanismo muito prático e eficiente para que usuários passem valores dire-
tamente para o programa sem precisar que este interrompa a execução para pedir valores pelo teclado,
especialmente útil para trabalhos em lote. A listagem 10.10 demonstra o processamento do array que é o
argumento do método main().
Alguns exemplos simples de arrays multidimensionais são matrizes matemáticas, tabuleiros de xadrez e jo-
gos de palavras cruzadas. Estes exemplos podem ser representados por arrays bidimensionais. Um exemplo
de array tridimensional seria um endereço de apartamento dentro de um bloco de prédios: o primeiro índice
indicaria em qual prédio o apartamento está localizado, o segundo indicaria o andar e o terceiro o apar-
tamento dentro do andar. Arrays de dimensões superiores são frequentemente necessários para cálculos
matemáticos e simulações. A figura 10.2 mostra alguns exemplos ilustrativos de arrays multidimensionais.
A criação de arrays multidimensionais em Java é simples: basta que para cada dimensão tenhamos um
par de colchetes, tanto para declarar o array, quanto para alocar memória para o mesmo e acessar seus
elementos. O processo de declaração, alocação e uso é demonstrado pelo programa na listagem 10.11.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
125
Arrays multidimensionais estão sujeitos às mesmas regras que arrays unidimensionais: suas dimensões
devem ser valores inteiros positivos maiores do que zero, tentativas de acesso usando índices fora dos va-
lores permitidos resultarão em exceções, etc. Assim como pode ser feito com os arrays unidimensionais,
os arrays multidimensionais podem ser encapsulados em classes, facilitando o seu uso determinando exa-
tamente que dados podem ser acessados nos arrays e de que forma podem ser acessados. Um exemplo é
mostrado na classe JogoDeDamas, que provê alguns métodos para que um jogo de damas seja feito, mos-
trada na listagem 10.12.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
126
Esta característica deve-se ao fato que Java trata arrays multidimensionais como arrays de arrays: desta
forma um array bidimensional pode ser considerado um array unidimensional onde cada elemento é outro
array unidimensional que contém valores de determinado tipo. Um exemplo ilustrativo de array irregular é
mostrado na figura 10.3.
A coluna à esquerda da figura 10.3 representa o índice da primeira dimensão do array - cada posição na
primeira dimensão aponta para um array de valores inteiros.
Um array irregular pode ser declarado da mesma forma que um array multidimensional regular, mas a sua
alocação deve ser feita em vários passos separados, um para cada dimensão do array. Um exemplo de uso
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
127
0 7 1 5 8 3 6
1 5 11 2
2 7
3 12 7 6 9
4 6 9 4 5 5 10 4 1
Figura 10.3: Exemplo de arrays irregulares
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
128
array de instâncias de classes (considerando uma classe que contenha os dados nome, idade e telefone é
mostrado na figura 10.4.
Arrays de instâncias de classes devem ser inicializados da mesma maneira que arrays de tipos nativos. A
diferença principal entre seu uso é que um array de tipos nativos pode ser usado imediatamente após aloca-
do, enquanto que no caso de um array de instâncias de classes, todas as instâncias devem ser inicializadas
através da palavra-chave new - a inicialização do array corresponde à declaração de várias variáveis que são
instâncias da classe, mas estas ainda devem ser inicializadas. O processo é mostrado nas listagens 10.14
e 10.15.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
129
Listagem 10.15: Uma classe que usa arrays de instâncias da classe Pessoa
1 /* Esta classe demonstra o uso de um array de instâncias da classe Pessoa */
2 class DemoArrayPessoas
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Declaramos e ao mesmo tempo aloco um array que conterá 8 instâncias da classe Pessoa
8 Pessoa lista[] = new Pessoa[8];
9 // Neste ponto do programa, nenhuma das instâncias da classe foi inicializada ! Devemos
10 // inicializar todas.
11 for(int p=0;p<8;p++)
12 lista[p] = new Pessoa(); // o construtor vazio é usado
13 // E agora podemos usar as instâncias normalmente
14 lista[3].inicializa("José da Silva",(byte)38,3092908);
15 lista[7].inicializa("Maria da Silva",(byte)34,3092912);
16 // Imprimimos alguns dos elementos
17 String res = lista[3].toString(); // converto a instância lista[3] para String
18 System.out.println(res); // e imprimo
19 System.out.println(lista[7]); // converto a instância lista[7] para String e imprimo
20 }
21 } // fim da classe DemoArrayPessoas
Alguns pontos interessantes das classes nas listagens 10.14 e 10.15 são:
• A classe Pessoa (listagem 10.14) implementa um construtor vazio para que a inicialização de suas
instâncias possa ser feita em blocos, por um laço, como feito nas linhas 11 e 12 da listagem 10.15.
Se somente existisse um construtor que aceitasse valores, este deveria ser chamado na linha 12 da
listagem 10.15, dificultando ou impossibilitando a criação das instâncias contidas no array por um
laço.
• Mesmo com a declaração do array (linha 8 da listagem 10.15), as instâncias devem ser individu-
almente inicializadas: qualquer tentativa de acesso à uma instância não inicializada causará uma
exceção java.lang.NullPointerException.
• Após a declaração e inicialização do array os elementos do mesmo podem ser usados como se fossem
instâncias comuns da classe.
Da mesma maneira com que arrays unidimensionais e multidimensionais, arrays de instâncias de classes
também podem ser encapsulados em outra classe que facilita a construção e manipulação do array. Esta
abordagem permite, em muitos casos, que a complexidade dos arrays seja encapsulada ou escondida den-
tro das classes, e que um programador que use estas classes somente se preocupe com os métodos que
permitem acesso aos dados encapsulados. Esta abordagem é demonstrada pela classe ListaDePessoas,
mostrada na listagem 10.16.
Listagem 10.16: Uma classe que encapsula arrays de instâncias da classe Pessoa
1 /* Esta classe encapsula um array de instâncias da classe Pessoa dentro
2 de outra classe, facilitando o seu uso posterior. */
3 class ListaDePessoas
4 {
5 // A Lista de Pessoas é declarada como um array de instâncas
6 private Pessoa lista[];
7 /* Construtor, que aloca memória para um número específicos de instâncias */
8 ListaDePessoas(int quantas)
9 {
10 lista = new Pessoa[quantas]; // aloca memória para o array
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
130
11 for(int q=0;q<quantas;q++)
12 {
13 lista[q] = new Pessoa(); // aloca usando o construtor vazio
14 }
15 } // fim do construtor
16 /* Método que inicializa certa pessoa na lista. Note que uma instância da classe
17 Pessoa é passada como argumento. O método não permite acessos fora da faixa. */
18 void setaDados(int qual,Pessoa quem)
19 {
20 if ((qual < 0) || (qual >= lista.length)) // fora da faixa !
21 {
22 System.out.println("Erro ! Somente existem "+lista.length+
23 "pessoas na lista"); // imprime mensagem de erro
24 }
25 else // valor do índice está dentro da faixa
26 lista[qual] = quem;
27 }
28 /* Método que retorna a lista inteira formatada como uma String */
29 public String toString()
30 {
31 String resultado = ""; // deve ser inicializada !
32 for(int quem=0;quem<lista.length;quem++)
33 {
34 // Pedimos à cada elemento do array, que é uma instância da classe Pessoa, que se
35 // concatene com uma String, chamando implicitamente o método toString da classe Pessoa
36 resultado += "- "+lista[quem]+"\n";
37 }
38 return resultado;
39 }
40 } // fim da classe ListaDePessoas
É importante notar que, no exemplo mostrado na listagem 10.17, instâncias diferentes da classe Pessoa
devem ser passadas como argumento para o método setaDados() da classe ListaDePessoas já que estas
serão simplesmente copiadas para os elementos do array encapsulado (linha 26 da listagem 10.16).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
131
Exercício 10.2: ?
O que aconteceria se tentássemos passar um array de inteiros para o método imprimeArrayDeLongs()
no programa na listagem 10.3 ?
Exercício 10.3: ?
Corrija o programa mostrado na listagem 10.5 para que o programa mostre o valor quadrado somente se o
usuário digitar valores dentro da faixa. Dica: use um while para garantir que o usuário digitou um valor
válido.
Exercício 10.4: ?
Os métodos setaValor() e pegaValor() na classe ListaDeNomes (listagem 10.6) apresentam erros em
potencial: caso um valor maior do que o comprimento do array ou menor do que zero sejam passados
para estes métodos, uma exceção irá ocorrer. Corrija os métodos de forma que se valores inválidos para
as posições dos arrays sejam passados, uma mensagem de erro seja mostrada.
Exercício 10.5: ?
Modifique o construtor da classe ArrayDeQuadrados (listagem 10.6) para que o usuário não possa espe-
cificar um número menor do que um para o construtor.
Exercício 10.6: ?
Modifique o programa na listagem 10.11 para que o usuário não possa entrar valores menores do que um
para as dimensões da matriz.
Exercício 10.7: ?
Escreva um programa em Java que declare e inicialize um vetor de booleanos (lendo-os do teclado), e
calcule quantos elementos são iguais a true.
Exercício 10.8: ?
Escreva um programa em Java que declare um array de inteiros e os popule de forma que o valor do
elemento do array seja igual ao dobro do seu índice (de forma que o elemento 15 do array valha 30).
Exercício 10.9: ?
Escreva uma classe em Java que encapsule um array de 12 bytes, onde cada elemento do array contém
o número de dias no mês correspondente, desconsiderando se o ano é bissexto ou não. Por exemplo, o
elemento 0 do array (correspondente a Janeiro) deve valer 31. Escreva um método que retorne o valor
encapsulado para determinado mês.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
132
Exercício 10.10: ?
Escreva um programa em Java que crie um array de Strings e o popule (através da leitura dos seus ele-
mentos pelo teclado). Após isto, faça com que o programa calcule e imprima quantas Strings tem menos
do que dez caracteres.
Exercício 10.11: ?
Escreva um programa em Java que crie um array de Strings e o popule (através da leitura dos seus ele-
mentos pelo teclado). Após isto, faça com que o programa imprima os três primeiros caracteres de cada
String do array. Dica: verifique se a String tem três ou mais caracteres antes de tentar imprimi-los.
Exercício 10.12: ?
Escreva um programa que declare um array bidimensional tabuada de 10 ⇥ 10 posições e popule os
elementos do array com os valores da tabuada para aquele elemento, de forma que, por exemplo, o
elemento tabuada[7][9] valha 63.
Exercício 10.13: ?
Escreva um programa em Java que crie um array de Strings a partir dos valores passados pela linha de
comando. Dica: os dados passados pela linha de comando já são um array, basta declarar um com o
mesmo tamanho e copiar elemento por elemento.
Exercício 10.14: ? ?
Usando o exercício 10.12 como base, escreva um programa que declare um array de cinco dimensões
tabuada de 10 ⇥ 10 ⇥ 10 ⇥ 10 ⇥ 10 posições e popule os elementos do array com os valores da tabuada
para aquele elemento, de forma que, por exemplo, o elemento tabuada[6][5][2][1][4] valha 240.
Quantas posições este array contém ?
Exercício 10.15: ? ?
Considere a classe ArrayDeFloats (listagem 10.8). Crie nesta classe mais três métodos que podem ser
eventualmente úteis: quantosZeros() que conta quantos elementos do array encapsulado são iguais a
zero, média() que calcula a média dos elementos no array encapsulado e existe() que recebe um valor
do tipo float e retorna true se este valor existe no array encapsulado ou false se não existir.
Exercício 10.16: ? ?
Escreva uma classe que represente uma matriz 2 ⇥ 2 usando um array de duas dimensões. Nesta classe,
escreva um método que calcule o determinante desta matriz, e um método que permita a impressão for-
matada dos seus valores (duas
✓ linhas com
◆ dois valores cada).
x00 x01
Se a matriz M é dada por: então o determinante é calculado como (x00 ⇥ x11 ) (x01 ⇥ x10 ).
x10 x11
Exercício 10.17: ? ?
Usando o exercício 10.16 como base, escreva uma classe que represente uma matriz 3 ⇥ 3 usando um
array de duas dimensões. Nesta classe, escreva um método que calcule o determinante desta matriz, e um
método que permita a impressão
0 formatada dos
1 seus valores (duas linhas com dois valores cada).
x00 x01 x02
Se a matriz M é dada por: @ x10 x11 x12 A então o determinante é calculado como (x00 ⇥ x11 ⇥ x12 ) +
x20 x21 x22
(x01 ⇥ x12 ⇥ x20 ) + (x02 ⇥ x10 ⇥ x21 ) (x00 ⇥ x12 ⇥ x21 ) (x01 ⇥ x10 ⇥ x22 ) (x02 ⇥ x11 ⇥ x20 )
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
133
Exercício 10.18: ? ?
Escreva um programa em Java que verifique se o usuário usou o argumento ”-help” ou ”-h” na linha de
comando.
Exercício 10.19: ? ?
Escreva uma classe em Java que encapsule um array de caracteres, simulando uma String. Esta classe deve
ter um construtor que recebe uma String como argumento - a partir desta String o número de elementos
do array e os valores de cada elemento podem ser obtidos.
Exercício 10.20: ? ?
Escreva uma classe que represente uma matriz de caracteres: o construtor desta classe deve receber a
largura e altura desta matriz e inicializar os elementos com caracteres aleatórios. A classe deve ter
um método para imprimir o array. Dica: caracteres aleatórios podem ser obtidos com a expressão
(char)(’A’+Math.random()*26).
Exercício 10.21: ? ?
Ao final da listagem 10.16 foi comentado que instâncias diferentes da classe Pessoa devem ser passadas
como argumento para o método setaDados() da classe ListaDePessoas. Podemos evitar esta impo-
sição se o método setaDados() receber, ao invés de uma instância da classe Pessoa, os dados que são
representados por esta classe (uma String, um byte e um int). Modifique o método setaDados() da classe
ListaDePessoas para refletir esta solução.
Exercício 10.22: ? ?
Considere o exercício 8.13. Reescreva a classe Histograma para que esta use um array de inteiros.
Os valores podem ser passados um a um para o array, usando um método similar ao seta() na classe
ArrayDeFloats (listagem 10.8).
Exercício 10.23: ? ?
Considere a classe ArrayDeFloats (listagem 10.8). Crie nesta classe o método troca() que recebe
dois valores inteiros como argumentos e troca os valores nas posições especificadas pelos argumen-
tos. Por exemplo, se o array encapsulado é {3.6, 2.7, 8.0, 9.2, 1.5, 4.1} e o método troca() for cha-
mado com os argumentos 1 e 4, os elementos nestes índices serão trocados de forma que o array será
{3.6, 1.5 , 8.0, 9.2, 2.7 , 4.1} (note os valores que foram trocados). Dica: só é possível fazer esta troca
usando um valor temporário do tipo float.
Exercício 10.24: ? ?
Usando o exercício 10.23 como base, reescreva o método para que este somente troque os valores caso
o valor indicado pelo primeiro índice passado como argumento seja menor que o valor indicado pelo
segundo argumento. Por exemplo, se o array encapsulado for {3.6, 2.7, 8.0, 9.2, 1.5, 4.1}, uma chamada
ao método troca(0,1) trocaria os valores nas posições 0 e 1, mas uma chamada ao método troca(1,2)
não trocaria os valores de índices 1 e 2 de posição.
Exercício 10.25: ? ?
Usando o exercício 7.2 como base, escreva um programa em Java que crie um array de instâncias da
classe RegistroDeAluno. Veja também a listagem 3.6.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
134
Exercício 10.26: ? ?
Crie uma classe em Java que encapsule um array de Strings, e um método nesta classe que retorne o
número de espaços em todas as Strings do array. Use o exercício 9.13 como base.
Exercício 10.27: ? ?
Crie um programa em Java que declare e inicialize três arrays de valores de ponto flutuante, popule os
dois primeiros com valores lidos do teclado, e calcule os valores dos elementos do terceiro array com a
soma dos elementos correspondentes dos dois primeiros arrays. Por exemplo, se os dois primeiros arrays
forem {0, 4, 2, 6} e {9, 2, 1, 1} o terceiro array deverá ser {9, 6, 3, 7}. O tamanho dos arrays também deve
ser lido do teclado.
Exercício 10.28: ? ?
Usando o exercício 10.27 como base, escreva um programa em Java que declare quatro arrays, sendo
que dois são de entrada (devendo ter seus valores lidos do teclado) e os outros dois vão conter, respecti-
vamente, os maiores e menores valores, tomados elemento a elemento, dos dois arrays de entrada. Por
exemplo, se os dois primeiros arrays forem {0, 4, 2, 6} e {9, 2, 1, 1} o terceiro array deverá ser {9, 4, 2, 6}
e o quarto, {0, 2, 1, 1}. O tamanho dos arrays também deve ser lido do teclado.
Exercício 10.29: ? ?
Escreva uma classe Menu em Java que encapsule um array de Strings. Nesta classe, crie o método
escolhe() que mostra as Strings com um número na frente, espere o usuário digitar um número e retorne
a String correspondente àquele número. Dicas: faça com que o usuário seja impossibilitado de digitar nú-
meros fora da faixa com um laço while, e faça com que os números a serem impressos antes das Strings
sejam mais amigáveis do que os índices - por exemplo, o valor do índice mais um é mais amigável para
usuários.
Exercício 10.30: ? ?
Reescreva o exercício 8.26 para que os valores sejam lidos da linha de comando. Dicas: os valores
numéricos terão que ser convertidos de Strings para valores de ponto flutuante: isso pode ser feito com
o método valueOf() da classe Double (seção A.2.2.7). O programa deve imprimir mensagens de erro
para divisões por zero e números de argumentos diferentes de três.
Exercício 10.31: ? ?
Crie um programa em Java que declare e inicialize dois arrays unidimensionais do mesmo tamanho,
e calcule o produto escalar destes dois arrays. Por exemplo, se os dois arrays forem {9, 2, 6, 7, 0} e
{1, 4, 5, 9, 2} o produto escalar será 9 ⇥ 1 2 ⇥ 4 6 ⇥ 5 + 7 ⇥ 9 + 0 ⇥ 2 = 34.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
135
Exercício 10.32: ? ? ?
Escreva um programa em Java que declare e inicialize dois arrays bidimensionais (matrizes) e multiplique
estras matrizes, criando uma terceira matriz como resultado. A multiplicação das matrizes A e B resul-
tando na matriz C pode ser vista como: 2 3
b11 b12 b13
6 b21 b22 b23 7
6 7
4 b31 b32 b33 5
b41 b42 b43
a11 a12 a13 a14 c11 c12 c13
a21 a22 a23 a24 c21 c22 c23
onde
c11 = b11 ⇥ a11 + b21 ⇥ a12 + b31 ⇥ a13 + b41 ⇥ a14 ,
c12 = b12 ⇥ a11 + b22 ⇥ a12 + b32 ⇥ a13 + b42 ⇥ a14 ,
c13 = b13 ⇥ a11 + b23 ⇥ a12 + b33 ⇥ a13 + b43 ⇥ a14 ,
c21 = b11 ⇥ a21 + b21 ⇥ a22 + b31 ⇥ a23 + b41 ⇥ a24 ,
c22 = b12 ⇥ a21 + b22 ⇥ a22 + b32 ⇥ a23 + b42 ⇥ a24 e
c23 = b13 ⇥ a21 + b23 ⇥ a22 + b33 ⇥ a23 + b43 ⇥ a24 .
Exercício 10.33: ? ? ?
Considerando o exercício 10.1, escreva uma classe Fatorial que contenha um construtor e um método
valor() que recebe um valor inteiro como argumento e que retorna um valor de ponto flutuante. O
construtor, quando chamado, deverá alocar um array de 150 posições e calcular o fatorial de 0 a 149,
guardando os resultados no array. O método valor(), quando chamado, deverá retornar o valor do
fatorial correspondente ao valor passado como argumento.
Exercício 10.34: ? ? ?
O crivo de Eratóstenes é um algoritmo usado para calcular números primos que primeiro popula um
array de valores sequenciais e vai peneirando os valores que são compostos de múltiplos. Implemente
um programa em Java que, usado o crivo de Eratóstenes, calcule os 10.000 primeiros números primos. O
programa pode começar com um array de valores booleanos, que são todos true, e a partir do valor 2 vai
peneirando (marcando como false todos os valores múltiplos de 2 maiores que 2, depois múltiplos de
3 maiores que 3, etc. Ao final do algoritmo, os valores que valerem true no array são números primos.
Dica: para entender melhor o algoritmo, rode uma simulação em papel antes.
Exercício 10.35: ? ? ?
Escreva um método que retorne true se os valores de um array (numérico) estão em ordem crescente ou
false se não estiverem. Veja o método imprimeArrayDeLongs() na classe DemoArray (listagem 10.3)
para ver como passar um array para um método.
Exercício 10.36: ? ? ?
Considere a classe ArrayDeFloats (listagem 10.8). Escreva nesta classe o método reverte() que re-
verte a posição dos elementos no array de forma que o primeiro passe a ser o último e vice-versa. Dica:
use o exercício 10.23 como base.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
136
Exercício 10.37: ? ? ?
Considere o exercício 10.29. Escreva uma classe ItemDeMenu que encapsule uma String com uma des-
crição de menu de restaurante, e um valor de ponto flutuante correspondente ao preço daquele item.
Modifique a classe Menu do exercício 10.29 para que esta encapsule um array de instâncias da classe
ItemDeMenu, e tenha um método que permita ao usuário fazer uma escolha. Dica: veja também a lista-
gem 10.16.
Exercício 10.38: ? ? ?
Usando o exercício 10.30 como base, escreva uma calculadora que aceite ao menos dois argumentos da
linha de comando, sendo que o primeiro deve ser uma String contendo ou o caracter ’+’ ou o caracter
’*’, e o resto da linha de comando devem ser valores de ponto flutuante. A primeira String determina a
operação que deve ser aplicada aos valores passados, de forma que se o programa for chamado com ”* 2
8 5” este deve imprimir o resultado 80.
Exercício 10.39: ? ? ?
Um algoritmo simples de ordenação de arrays que coloca os valores de um array numérico em ordem
crescente pode ser descrito como:
• Faça um laço do primeiro elemento do array até o penúltimo. Use a variável i para representar o
contador deste laço.
• Faça um laço dentro do anterior que percorra o array do elemento seguinte até o final do array. Use
a variável j para representar o contador deste laço.
• Se o valor indicado pelo índice i for menor do que o valor indicado pelo índice j, troque os valores
do array.
Exercício 10.40: ? ? ?
Crie a classe ArrayDeFloatsUnicos que herda da classe ArrayDeFloats (listagem 10.8). A diferença
entre as classes é que o método seta() da classe ArrayDeFloats deve ser sobreescrito para somente
colocar valores no array encapsulado na classe se este valor não existir ainda, fazendo com que todos os
valores do array encapsulado sejam únicos. Por exemplo, se já houver um valor 3.8 no array encapsulado,
o método seta() deve retornar sem modificar o array.
Exercício 10.41: ? ? ?
Crie uma classe Banco que encapsule um array de instâncias da classe ContaBancaria (mostrada na
listagem 3.8). Crie nesta classe um método total() que soma o total dos valores depositados nas diversas
contas bancárias no banco. Use a listagem 10.16 como referência.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
137
Exercício 10.42: ? ? ? ?
Crie uma classe EntradaEmAgenda que contenha os dados necessários para armazenar uma entrada
de agenda (hora, dia, mês, ano, assunto). Crie nesta classe, além do construtor vazio e um método
toString(), um método para inicializar os dados, um método éNoDia que recebe valores de dia, mês e
ano e retorna true se o dia, mês e ano daquela instância da classe forem iguais aos argumentos passados.
Crie um método similar chamado éNoMês que recebe valores de mês e ano somente e retorna true se o
mês e ano daquela instância da classe forem iguais aos argumentos passados.
Crie também uma classe Agenda que encapsule uma agenda de compromissos, que será representado por
uma rray de instâncias da classe EntradaEmAgenda. Crie um método listaDia() que recebe valores de
dia, mês e ano e lista todas as instâncias de EntradaEmAgenda que caem naquele dia, mês e ano, e um
método listaMês() que recebe valores de mês e ano e lista todas as instâncias de EntradaEmAgenda
que caem naquele mês e ano.
Exercício 10.43: ? ? ? ?
Considere o método existe() na classe ArrayDeFloats (que deve ter sido criado no exercício 10.15.
Este método deve percorrer todo o array para se certificar que o valor passado como argumento existe ou
não no array encapsulado. Existe um algoritmo mais eficiente de procura de valores em arrays chamado
busca binária, que somente funciona em arrays ordenados (veja o exercício 10.39). Os passos deste
algoritmo são:
Dica: eventualmente não haverá um índice entre F e L (por exemplo, se F=2 e L=5). Neste caso, qualquer
uma das alternativas para o índice do meio pode ser usada. Existem outras variações que dão resultados
melhores (buscas mais rápidas, com menos comparações) - você consegue imaginar alguma ?
Exercício 10.44: ? ? ? ?
Modifique a classe Menu criada no exercício 10.37 para que além do array de instâncias da classe
ItemDeMenu, a classe também armazene um array de valores inteiros com o mesmo número de elementos
do array de instâncias de ItemDeMenu. Este array adicional servirá para acumular pedidos, ou seja, para
cada item que for escolhido pelo método escolhe() o elemento correspondente do array será incremen-
tado em um. Escreva na classe Menu um método que imprima uma nota fiscal como as de supermercado,
contendo os totais parciais (valor de cada item vezes o preço de cada item escolhido) e o total geral.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
138
Exercício 10.45: ? ? ? ?
Crie uma classe que represente um jogo da velha, usando uma matriz de duas dimensões para representar
as posições do jogo. A matriz deve ser alocada no construtor da classe, ter o tamanho 3 ⇥ 3 e ser de um
tipo que suporte três estados possíveis: vazio, preenchido com ’O’ e preenchido com ’X’. A classe deve
poder ser usada para jogos com dois jogadores.
Dica: A classe deve ter os seguintes métodos:
• jogaO(), que aceita dois valores que são as coordenadas onde um ’O’ será jogado, e marca na
matriz a posição somente se esta estiver livre.
• jogaX(), que aceita dois valores que são as coordenadas onde um ’X’ será jogado, e marca na
matriz a posição somente se esta estiver livre.
• verifica(), que verifica a matriz para ver se existe algum ganhador (este método deve verificar se
existem três marcas iguais que não sejam vazias em uma horizontal, vertical ou diagonal da matriz).
• imprime(), que imprimirá a matriz do jogo com as posições atuais.
Escreva também um programa que use a classe. Este programa deve executar um laço no qual fica
perguntando as posições para os jogadores alternadamente, enquanto não houver vitória, desistência ou
acabarem as posições vazias da matriz.
Exercício 10.46: ? ? ? ?
O jogo japonês Go é jogado por duas pessoas em um tabuleiro quadrado de tamanho 19⇥19. Cada pessoa
recebe um conjunto de peças pretas e brancas que devem ser colocadas alternadamente no tabuleiro, na
posição que o jogador desejar. Ganha o jogo o primeiro jogador que conseguir colocar cinco de suas
peças em uma linha reta horizontal, vertical ou diagonal.
Crie uma classe em Java que represente um jogo de go, usando uma matriz de duas dimensões para
representar as posições do jogo. A matriz deve ser alocada no construtor da classe, ter o tamanho 19 ⇥ 19
e ser de um tipo que suporte três estados possíveis: vazio, preenchido com peça preta e preenchido com
peça branca. A classe deve poder ser usada para jogos com dois jogadores.
A classe deve ter os seguintes métodos:
• jogaPreta(), que aceita dois valores que são as coordenadas onde uma peça preta será jogada, e
marca na matriz a posição somente se esta estiver livre.
• jogaBranca(), que aceita dois valores que são as coordenadas onde uma peça branca será jogada,
e marca na matriz a posição somente se esta estiver livre.
• verifica(), que verifica a matriz para ver se existe algum ganhador (este método deve verificar se
existem cinco peças iguais que não sejam vazias em uma horizontal, vertical ou diagonal da matriz,
depois de cada jogada feita).
• imprime(), que imprimirá a matriz do jogo com as posições atuais.
Dica: O algoritmo do jogo não é tão diferente do jogo da velha (exercício 10.45), exceto pelo método
verifica(). Este método pode, para cada posição do array bidimensional, ver se existem linhas de cinco
peças iguais contadas a partir da posição sendo procurada. O único cuidado adicional é garantir que o
algoritmo não procurará peças fora do tabuleiro.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
139
Exercício 10.47: ? ? ? ?
Escreva uma classe em Java que use um array irregular para representar um Triângulo de Pascal. O
triângulo de Pascal é uma série de séries de valores onde cada valor é obtido somando-se o valor acima
(linha anterior) e o valor à esquerda do valor acima. Parte do triângulo de Pascal é mostrado abaixo.
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
Dicas: cada linha l do array irregular terá l + 1 colunas. A primeira coluna de cada linha do array vale 1,
e a segunda vale o índice da linha mais um. Cada linha do array é reflexiva, podendo ser lida da direita
para a esquerda ou da esquerda para a direita da mesma forma.
Exercício 10.48: ? ? ? ? ?
É possível embutir um pouco de Inteligência Artificial no jogo da velha do exercício 10.45, fazendo com
que um jogador jogue contra o computador. Quando for a vez do computador jogar, as coordenadas onde
este colocará sua peça não serão entradas via teclado: a própria classe pode escolher a melhor posição
vazia para jogar sua peça baseado na seguinte heurística (série de passos que podem levar à solução de
um problema): Para cada posição desocupada no tabuleiro, some:
0 0 +2
O X não −2 não
Neste exemplo, a melhor posição para o computador jogar seria aquela cujo valor é +2. As posições
marcadas com não já estariam ocupadas.
Usando o exercício 10.45 como base, escreva um método jogaComputador() que calcule a melhor
posição para jogo e efetue a jogada. Outras partes da classe deverão ser reescritas, por exemplo, para
permitir que o usuário decida se vai jogar com os ’X’ ou ’O’ e quem será o primeiro a jogar.
Dica: a classe pode conter outra matriz, do mesmo tamanho do tabuleiro do jogo da velha, que será
reinicializada e calculada com o algoritmo acima a cada jogada do computador.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
140
Exercício 10.49: ? ? ? ? ?
Também é possível adaptar a classe criada no exercício 10.46 para que o computador possa jogar com
o usuário, usando alguma inteligência para decidir onde posicionar suas peças. A heurística para que o
computador decida qual posição é melhor para jogar uma peça pode ser:
• Menos dois pontos para cada peça do adversário que estiver exer:arrays-menuitem2na vizinhança
direta 7 ⇥ 7 e mais dois pontos para cada peça do computador que estiver nesta vizinhança,
• Menos quatro pontos para cada peça do adversário que estiver na vizinhança direta 5 ⇥ 5 e mais
quatro pontos para cada peça do computador que estiver nesta vizinhança,
• Menos oito pontos para cada peça do adversário que estiver na vizinhança direta 3 ⇥ 3 e mais oito
pontos para cada peça do computador que estiver nesta vizinhança,
• Menos um ponto para cada peça do adversário que estiver na vizinhança indireta 7 ⇥ 7 e mais um
ponto para cada peça do computador que estiver nesta vizinhança.
A figura abaixo mostra, para uma determinada posição, quais são as posições que correspondem às
vizinhanças:
Posição central (sendo considerada)
Vizinhança direta 3x3
Vizinhança direta 5x5
Vizinhança direta 7x7
Vizinhança indireta 7x7
Usando o exercício 10.46 como base, escreva um método jogaComputador() que calcule a melhor
posição para jogo e efetue a jogada. Outras partes da classe deverão ser reescritas, por exemplo, para
permitir que o usuário decida se vai jogar com as peças pretas ou brancas e quem será o primeiro a jogar.
Dica: veja também o enunciado do exercício 10.48.
Exercício 10.50: ? ? ? ? ?
Adeque o exercício 10.44 para que este seja capaz de representar uma livraria. A classe Menu pode ser
chamar Livraria, e ao invés de usar um array de instâncias da classe ItemDeMenu deverá usar um array
de instâncias da classe LivroDeLivraria que deve representar o título do livro, o nome do autor, o preço
de revenda, o número de livros em estoque, o ISBN (índice único) e uma ou mais palavras-chave sobre o
tema do livro.
A classe LivroDeLivraria deve ter um método onde passamos os dados para encapsulamento, um
método toString() e métodos que permitam a procura por título, nome do autor e palavras-chave (este
métodos devem receber Strings e usar o método substring() para ver se o conteúdo é aproximadamente
equivalente).
A classe Livraria deve ter um construtor onde passamos o número máximo de títulos de livros que
teremos em estoque, e um método para procurar, no array de instâncias da classe LivroDeLivraria,
livros cujos títulos, autores ou palavras-chave correspondam a uma String entrada. Esta classe deve ter
um método menu que permita ao usuário sair do sistema, comprar um livro, fazer uma procura pelo nome
do autor, título ou palavra-chave e verificar sua lista de pedidos.
Dica: considere o funcionamento de uma livraria virtual na Internet para criar os métodos da classe
Livraria.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
141
Exercício 10.51: ? ? ? ? ?
O Jogo da Vida é um algoritmo de simulação com aplicações e resultados visuais interessan-
tes. Ele simula uma colônia de células em uma grade retangular onde cada elemento da grade
pode conter ou não uma célula (veja figura abaixo). O jogo se desenvolve em várias itera-
ções, onde a cada uma destas iterações o número de vizinhos populados imediatos (numa vi-
zinhança 3 ⇥ 3) de cada célula é calculado, e caso este número seja exatamente igual a três
(incluindo a própria célula), uma célula poderá existir naquela posição na iteração seguinte.
Situação Inicial Primeira Iteração Segunda Iteração
2
1 3 2 2 2 2 2
2 3 4 3 1 2 2 2 2
1 3 2 2 2 2 2
2 2
2 5
3 3 3 5 3 3 3 2 2 3 5 4 4 5 4
3 3 5 8 5 3 3 2 2 3 5 4 5 5 5 3
3 5 3 2 2 4 5 4
2 3
A figura acima mostra três iterações do jogo numa área 11 ⇥ 11, onde para cada célula seu nú-
mero de vizinhos é mostrado, para facilitar a compreensão. Na situação inicial, existem qua-
tro grupos distintos de células com formatos diferentes. Na primeira iteração, das três células
que existiam no canto superior esquerdo, somente a central sobreviveu, pois numa vizinhan-
ça 3 ⇥ 3 somente esta tinha 3 vizinhos. No grupo de células do canto superior direito, vemos
que a célula central, que tinha quatro vizinhos, desapareceu. Na segunda iteração vemos que
os grupos acabam se misturando. Uma sequência mais completa das iterações é mostrada na fi-
gura abaixo, que demonstra que eventualmente é possível que a colônia de células se estabilize.
Situação inicial Primeira iteração Segunda iteração Terceira iteração Quarta iteração Quinta iteração
Décima−primeira
Sexta iteração Sétima iteração Oitava iteração Nona iteração Décima iteração iteração
Escreva uma classe em Java que simule o jogo da vida para várias configurações (tamanho da matriz que
representará a colônia de células, número e posição da população inicial de células). Esta classe deve ter
os métodos sugeridos:
• construtor, que recebe o tamanho da colônia e inicializa uma matriz do tamanho especificado,
• popula(), que popula a colônia aleatoriamente com células,
• itera(), que calcula uma iteração da colônia,
• imprime(), que imprime a situação atual da colônia, usando caracteres ’*’ para representar células
e ’.’ para representar espaços em branco.
Dicas: O cálculo do número de vizinhos de uma célula entre uma iteração e outra deve envolver uma
matriz intermediária, caso contrário o número de vizinhos de células subsequentes serão calculados in-
corretamente !
O método Math.random() retorna um número aleatório entre zero e um.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
142
Capítulo 11
Funções Matemáticas
Listagem 11.1: Um programa que demonstra usos das constantes da classe Math
1 /* Uma classe com método main que demonstra as constantes da classe Math */
2 class DemoMath
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String args[])
6 {
7 double pi = Math.PI;
8 double e = Math.E;
9 System.out.println("O valor de pi é "+pi);
10 System.out.println("O valor de e é "+e);
11 } // fim do método main
12 } // fim da classe DemoMath
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
143
• O método min() recebe dois valores como argumentos e retorna o menor dos dois valores. Este
método também é polimórfico, seguindo as mesmas regras mostradas para o método max().
• O método abs() retorna o valor absoluto do argumento passado. Se o valor passado é x, o valor
absoluto corresponde a x se x 0 ou -x se x < 0. Este método é polimórfico, aceitando argumentos
do tipo int, long, float e double e retornando valores do mesmo tipo do argumento.
• O método round() retorna o valor inteiro mais próximo do valor de ponto flutuante passado como
argumento, descartando no processo as casas decimais, e pode ser usado para arredondamento de
valores de ponto flutuante. Este método também é polimórfico: se um argumento do tipo float for
passado, o método retornará um valor do tipo inteiro, mas se um argumento do tipo double for
passado o método retornará um valor do tipo long.
• O método floor() recebe um valor do tipo double como argumento e retorna um valor do tipo
double contendo o valor passado arredondado para baixo (mais próximo de in f ty).
• O método ceil() recebe um valor do tipo double como argumento e retorna um valor do tipo double
contendo o valor passado arredondado para cima (mais próximo de +in f ty).
Listagem 11.2: Um programa que demonstra usos de métodos de comparação e arredondamento da classe
Math
1 /* Uma classe com método main que demonstra os métodos de comparação e
2 conversão da classe Math */
3 class DemoMath
4 {
5 /* Método que permite a execução da classe */
6 public static void main(String args[])
7 {
8 float v1 = 123456.78f;
9 float v2 = -12.34f;
10 System.out.println("max("+v1+","+v2+")="+Math.max(v1,v2)); // 123456.78
11 System.out.println("min("+v1+","+v2+")="+Math.min(v1,v2)); // -12.34
12 System.out.println("abs("+v1+")="+Math.abs(v1)); // 123456.78
13 System.out.println("abs("+v2+")="+Math.abs(v2)); // 12.34
14 System.out.println("round("+v1+")="+Math.round(v1)); // 123457
15 System.out.println("round("+v2+")="+Math.round(v2)); // -12
16 System.out.println("floor("+v1+")="+Math.floor(v1)); // 123456.0
17 System.out.println("floor("+v2+")="+Math.floor(v2)); // -13.0
18 System.out.println("ceil("+v1+")="+Math.ceil(v1)); // 123457.0
19 System.out.println("ceil("+v2+")="+Math.ceil(v2)); // -12.0
20 } // fim do método main
21 } // fim da classe DemoMath
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
144
• O método tan() retorna o valor da tangente do ângulo especificado em radianos e passado como
argumento para o método. Tanto o valor do ângulo quanto o valor de retorno do método são do tipo
double.
Listagem 11.3: Um programa que demonstra usos de métodos trigonométricos da classe Math
1 /* Uma classe com método main que demonstra os métodos trigonométricos da
2 classe Math */
3 class DemoMath
4 {
5 /* Método que permite a execução da classe */
6 public static void main(String args[])
7 {
8 double ang0 = 0.; // zero graus = zero radianos
9 double ang45 = Math.PI/4.; // 45 graus = pi/4 radianos
10 double ang90 = Math.PI/2.; // 90 graus = pi/2 radianos
11 double ang135 = 3.*Math.PI/4.; // 135 graus = 3pi/4 radianos
12 System.out.println("seno("+ang0+")="+Math.sin(ang0)); // 0
13 System.out.println("seno("+ang45+")="+Math.sin(ang45)); // sqrt(2)/2
14 System.out.println("seno("+ang90+")="+Math.sin(ang90)); // 1
15 System.out.println("seno("+ang135+")="+Math.sin(ang135)); // sqrt(2)/2
16 System.out.println("coseno("+ang0+")="+Math.cos(ang0)); // 1
17 System.out.println("coseno("+ang45+")="+Math.cos(ang45)); // sqrt(2)/2
18 System.out.println("coseno("+ang90+")="+Math.cos(ang90)); // 0 (quase)
19 System.out.println("coseno("+ang135+")="+Math.cos(ang135)); // -sqrt(2)/2
20 System.out.println("tangente("+ang0+")="+Math.tan(ang0)); // 0
21 System.out.println("tangente("+ang45+")="+Math.tan(ang45)); // 1 (quase)
22 System.out.println("tangente("+ang90+")="+Math.tan(ang90)); // infinito (quase)
23 System.out.println("tangente("+ang135+")="+Math.tan(ang135)); // -1 (quase)
24 } // fim do método main
25 } // fim da classe DemoMath
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
145
Listagem 11.4: Um programa que demonstra usos de métodos exponenciais da classe Math
1 /* Uma classe com método main que demonstra os métodos exponenciais da
2 classe Math */
3 class DemoMath
4 {
5 /* Método que permite a execução da classe */
6 public static void main(String args[])
7 {
8 double v1 = 0.;
9 double v2 = Math.E;
10 double v3 = 49.;
11 double v4 = -1.;
12 double v5 = 1.;
13 System.out.println("sqrt("+v1+")="+Math.sqrt(v1)); // 0.0
14 System.out.println("sqrt("+v3+")="+Math.sqrt(v3)); // 7.0
15 System.out.println("pow("+v3+","+0.5+")="+Math.pow(v3,0.5)); // 7.0
16 System.out.println("pow("+1+","+v2+")="+Math.pow(1.,v2)); // 1.0
17 System.out.println("log("+v1+")="+Math.log(v1)); // -Infinity
18 System.out.println("log("+v2+")="+Math.log(v2)); // 1.0
19 System.out.println("log("+v4+")="+Math.log(v4)); // NaN
20 System.out.println("exp("+v1+")="+Math.exp(v1)); // 1.0
21 System.out.println("exp("+v5+")="+Math.exp(v5)); // Math.E
22 } // fim do método main
23 } // fim da classe DemoMath
Listagem 11.5: Um programa que demonstra usos do método random da classe Math
1 /* Uma classe com método main que demonstra o método random da classe Math */
2 class DemoMath
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String args[])
6 {
7 // Imprimimos 10 valores pseudo-aleatórios entre 0 e 9
8 for(int i=0;i<10;i++) System.out.print(random(10)+" ");
9 System.out.println();
10 // Imprimimos 10 valores pseudo-aleatórios entre 0 e 59
11 for(int i=0;i<10;i++) System.out.print(random(60)+" ");
12 System.out.println();
13 // Imprimimos 10 valores pseudo-aleatórios entre 0 e 99
14 for(int i=0;i<10;i++) System.out.print(random(100)+" ");
15 System.out.println();
16 } // fim do método main
17 /* Método que retorna um valor inteiro pseudo-aleatório entre 0 e max */
18 static int random(int max)
19 {
20 return (int)(max*Math.random());
21 } // fim do método random
22 } // fim da classe DemoMath
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
146
Exercício 11.2: ?
Para qualquer
q triângulo de lados A, B e C, o perímetro P é calculado como A + B +C e a área A é calculada
como P2 ⇥ ( P2 A) ⇥ ( P2 B) ⇥ ( P2 C). Escreva um programa em Java que receba os valores A, B e C
do teclado e calcule os valores P e S.
Exercício 11.3: ?
Escreva uma classe Dado que tenha um método estático arremesso() que ao ser chamado imprima um
valor entre 1 e 6 (veja o exercício 2.8).
Exercício 11.4: ?
Considere o exercício 8.31, que calcula usando uma série infinita o valor de π4 /90. Reescreva o programa
de forma a calcular a diferença entre o valor calculado com a série e o calculado com a constante Math.PI.
Teste os resultados com vários valores máximos para a série.
Exercício 11.5: ?
Considere o exercício 8.32, que calcula usando uma série infinita o valor de π2 /8. Reescreva o programa
de forma a calcular a diferença entre o valor calculado com a série e o calculado com a constante Math.PI.
Teste os resultados com vários valores máximos para a série.
Exercício 11.6: ?
Considere o exercício 8.35, que calcula usando uma série infinita o logaritmo de 2. Reescreva o programa
de forma a calcular a diferença entre o valor calculado com a série e o calculado com o método Math.log.
Teste os resultados com vários valores máximos para a série.
Exercício 11.7: ?
Escreva um programa que compare o resultado dos métodos calculaPi() (exercício 8.40) e
calculaPiDeOutraForma() (exercício 8.41) com o valor da constante Math.PI. Existe uma diferen-
ça significativa entre a constante e os resultados dos métodos ?
Exercício 11.8: ? ?
Escreva uma classe Triangulo que encapsule três valores de ponto flutuante correspondentes aos la-
dos do triângulo. Os valores devem ser passados para o construtor da classe. Nesta classe, escreva os
métodos calculaPerímetro() e calculaÁrea() que calculam o perímetro e área do triângulo (veja
exercício 11.2). Escreva também o método tipo() que retorna 1 se o triângulo for escaleno, 2 se o
triângulo for isósceles e 3 se for equilátero.
Exercício 11.9: ? ?
Escreva uma classe em Java que encapsule um array de 360 valores onde cada elemento corresponde ao
seno do ângulo daquele elemento, em graus. Os valores do array devem ser preenchidos pelo construtor
da classe. Um método deve ser criado para permitir o acesso aos valores do array. Dica: para converter
de radianos para graus, multiplique por π e divida por 180.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
147
Exercício 11.10: ? ? ⇣ p2 ⌘
p b2
+ log 4a+ bb +16a , onde
2
O comprimento do arco ABC de uma parábola é dada por 12 b2 + 16a2 + 8a
a é a altura da parábola e b é a distância entre A e C (veja figura abaixo). Escreva um programa em Java
que leia os valores a e b e calcule o comprimento do arco da parábola correspondente.
B
a
A b C
Exercício 11.11: ? ?
Usando o exercício 11.3 como base, crie uma classe DadoComHistorico que seja capaz de armazenar,
a cada vez que o dado é arremessado, o valor que saiu. Desta forma, depois de vários arremessos, a
qualquer momento é possível verificar quantas vezes cada número saiu.
Dicas: os métodos não devem mais ser estáticos, use um array de seis posições para acumular os resulta-
dos, veja também o exercício 2.9.
Exercício 11.12: ? ?
Escreva um programa que resolva uma equação do segundo grau. Este p programa deve
p ler os valores A,
B e C do teclado, calcular o valor ∆ = B 4AC e as raízes x1 = 2A e x2 = 2A ∆ . Dica: se ∆ for
2 B ∆ B
menor que zero, não existem raízes reais para a equação - o programa deve prever este caso e imprimir
uma mensagem correspondente.
Exercício 11.13: ? ?
O valor ex pode ser calculado com a série infinita mostrada no exercício 8.42 e com o método
Math.exp(). Escreva um programa em Java que compare os resultados das três abordagens, para vá-
rios valores máximos para a série infinita.
Exercício 11.14: ? ?
O seno de um ângulo x pode ser calculado usando as séries infinitas mostradas nos exercícios 8.43 e 8.44
ou usando o método Math.sin(). Escreva um programa em Java que compare os resultados das três
abordagens, para vários valores máximos para a série infinita.
Exercício 11.15: ? ?
O coseno de um ângulo x pode ser calculado usando as séries infinitas mostradas nos exercícios 8.45
e 8.46 ou usando o método Math.cos(). Escreva um programa em Java que compare os resultados das
três abordagens, para vários valores máximos para a série infinita.
Exercício 11.16: ? ?
A tangente de um ângulo x pode ser calculada usando a série infinita mostrada no exercício 8.48 ou usando
o método Math.tan(). Escreva um programa em Java que compare os resultados das duas abordagens,
para vários valores máximos para a série infinita.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
148
Exercício 11.17: ? ?
A cotangente de um ângulo x pode ser calculada usando a série infinita mostrada no exercício 8.49 ou
usando o valor de 1 dividido pelo resultado do método Math.tan(). Escreva um programa em Java que
compare os resultados das duas abordagens, para vários valores máximos para a série infinita.
Exercício 11.18: ? ?
A secante de um ângulo x pode ser calculada usando a série infinita mostrada no exercício 8.50 ou usando
o valor de 1 dividido pelo resultado do método Math.cos(). Escreva um programa em Java que compare
os resultados das duas abordagens, para vários valores máximos para a série infinita.
Exercício 11.19: ? ?
A cosecante de um ângulo x pode ser calculada usando a série infinita mostrada no exercício 8.51 ou
usando o valor de 1 dividido pelo resultado do método Math.sin(). Escreva um programa em Java que
compare os resultados das duas abordagens, para vários valores máximos para a série infinita.
Exercício 11.20: ? ?
O logaritmo natural de um número x pode ser calculado usando a série infinita mostrada no exercício 8.53
ou usando o método Math.log(). Escreva um programa em Java que compare os resultados das duas
abordagens, para vários valores máximos para a série infinita.
Exercício 11.21: ? ? ?
Escreva uma classe que represente polígonos regulares. O construtor deve receber o número de lados
e o comprimento de cada lado. O método área() deve calcular a área dos polígonos com a fórmula
1 2 cos(π/n)
4 nb sin(π/n) onde n é o número de lados e b o comprimento de cada lado, e o método perímetro() deve
calcular o perímetro como n ⇥ b. Escreva também um método que imprima o nome do polígono baseado
no seu número de lados (ex. “quadrado” para quatro lados, “octógono” para oito lados, etc.).
Exercício 11.22: ? ? ?
Escreva um programa em Java que sorteie 50 números entre 0 e 99 para jogar na Lotomania. O pro-
grama não deverá sortear duas vezes o mesmo número. Dica: use um array para armazenar os números
sorteados, veja o exercício 10.40.
Exercício 11.23: ? ? ?
Outra maneira de resolver o problema do exercício 11.22 é criar um array onde cada elemento vale o valor
do seu índice, escolher dois índices aleatoriamente e trocar os elementos destes índices. Se um número
suficientemente grande de trocas for feito, o array final estará embaralhado, e basta tomar os cinquenta
primeiros elementos para termos cinquenta valores aleatórios distintos. Implemente um programa em
Java que usa esta abordagem.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
149
Capítulo 12
Exceções
12.1 Introdução
É altamente desejável que os programas desenvolvidos em Java, como em qualquer outra linguagem de
programação, sejam livres de erros. Erros em programas escritos em Java podem ser divididos em duas
categorias básicas: erros de sintaxe, que ocorrem porque comandos, métodos ou classes foram escritas de
forma incorreta nos programas, e erros de lógica, onde comandos ou classes são usados de forma correta do
ponto de vista da sintaxe dos programas mas incorreta quando considerado o que se deseja que o comando,
classe, instância ou método realmente execute.
Erros de sintaxe são, em sua quase totalidade, localizados e apontados pelo compilador, que se recusa a
terminar a compilação da classe enquanto estes erros não forem corrigidos. Alguns erros de sintaxe são
mostrados na listagem 12.1, onde os comentários descrevem os erros cometidos nas linhas do programa.
Erros de lógica são, por sua natureza, muito mais difíceis de serem corrigidos. Alguns erros de lógica
são: laços que não começam ou terminam, métodos chamados recursivamente sem um ponto de término,
overflow de variáveis, tentativa de acesso à elementos de arrays e caracteres de Strings usando índices fora
dos valores válidos, divisões por zero, etc.
Vale a pena notar que nem todos os erros de lógica podem resultar em erros mostrados pelo programa
quando este é executado. Alguns dos erros que podem ser mostrados pelo programa quando executado são
mostrados pelo programa na listagem 12.2.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
150
O programa na listagem 12.2 espera que quatro valores sejam passados pela linha de comando, que es-
tes valores possam ser transformados em valores inteiros pelo método parseInt() da classe Integer
(seção A.2.2.4) e que duas operações de divisão sejam feitas com estes quatro valores. Como os valores
passados pela linha de comando serão convertidos em um array (o declarado como argumento para o mé-
todo main(), veja a seção 10.2.1), o programa considera que este array terá quatro elementos. Caso um
usuário passe menos do que quatro argumentos para o programa, um erro de acesso à elemento inexistente
do array ocorrerá nas linhas 9, 10, 11 ou 12 da listagem 12.2 (dependendo do número de argumentos pas-
sados para o programa).
Outro erro potencial do programa na listagem 12.2 é que um ou ambos os valores das variáveis a2 e b2
podem ocasionalmente ser iguais a zero, o que causaria um erro de divisão por zero na linha 14 da lista-
gem. Para que o programa funcione de maneira perfeita e à prova de erros, estes devem ser previstos. O
programa na listagem 12.3 tenta prever a possível ocorrência destes erros através da execução condicional
de partes do programa.
Alguns dos erros mostrados no programa na listagem 12.2 podem ser corrigidos facilmente usando blocos
de decisão if/else, como mostrado na listagem 12.3.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
151
Na listagem 12.3 dois blocos if/else controlam a execução de trechos do programa que somente serão
executados caso não haja nenhum problema em potencial.
O mecanismo de exceções permite que trechos do programa ou classe sejam executados, e caso um erro
ocorra no trecho, uma exceção correspondente será lançada ou levantada, e o programa passará o controle
para o bloco seguinte, que processará a exceção. Em outras palavras, este mecanismo permite que tentemos
(try) a execução de um bloco de comandos, e caso uma exceção seja lançada, o programa pegará (catch)
esta exceção em outro bloco. Opcionalmente temos a possibilidade de ao final dos blocos acima (finally),
executar alguns comandos. Este mecanismo é implementado através de um bloco try/catch/finally,
que é mostrado no trecho na listagem 12.4.
• Blocos try/catch/finally podem aparecer dentro de blocos if/else, while, etc. assim como
dentro de subrotinas, métodos de classes, etc.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
152
• Os blocos try, catch e finally devem ser cercados por chaves ({ e }), mesmo que sejam compos-
tos de uma única linha de programa.
• O bloco finally é opcional, e será executado independentemente da ocorrência de exceções no
bloco try/catch.
• Podemos ter quantos blocos catch quisermos, mas para cada um deve ser passado como argumento
uma instância de exceção de classes diferentes.
• Todas as exceções descendem da classe Exception - como existe uma hierarquia das exceções im-
plementadas através do mecanismo de herança, se formos usar mais do que um bloco catch devemos
tentar pegar as exceções mais especializadas antes das exceções mais genéricas.
O programa mostrado na listagem 12.3 foi reescrito de forma a usar exceções, e é mostrado na lista-
gem 12.5.
Outra maneira de escrevermos o programa na listagem 12.5 é usando um bloco catch para cada uma das
possíveis exceções que podem ocorrer no bloco try, como mostrado na listagem 12.6.
Listagem 12.6: Outro exemplo de programa que processa erros através de exceções
1 /* Classe que corrige erros em potencial em um programa exemplo */
2 class DemoExcecoes
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String args[])
6 {
7 try // tentaremos executar o bloco de comandos abaixo
8 {
9 // Supomos que quatro argumentos serão passados para o programa, e podemos
10 // transformar estes argumentos em valores inteiros.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
153
11 int a1 = Integer.parseInt(args[0]);
12 int a2 = Integer.parseInt(args[1]);
13 int b1 = Integer.parseInt(args[2]);
14 int b2 = Integer.parseInt(args[3]);
15 // Efetuamos uma operação simples com estes valores.
16 int resultado = a1/a2+b1/b2;
17 System.out.println("O resultado é "+resultado);
18 } // fim do if que verifica se quatro argumentos foram passados
19 catch (ArrayIndexOutOfBoundsException e) // pega exceções de índices inválidos para arrays
20 {
21 System.out.println("Um índice fora da faixa válida foi usado.");
22 System.out.println("A mensagem da exceção é "+e);
23 }
24 catch (ArithmeticException e) // pega exceções de aritmética
25 {
26 System.out.println("Um erro de aritmética ocorreu.");
27 System.out.println("A mensagem da exceção é "+e);
28 }
29 } // fim do método main
30 } // fim da classe DemoExcecoes
Na listagem 12.6 cada tipo de exceção é processado separadamente com um bloco catch, possibilitando a
geração de mensagens de erro mais detalhadas.
Todas as classes que representam exceções possuem o método printStackTrace(), que não recebe argu-
mentos e é chamado a partir da instância da exceção. Este método imprime o histórico das chamadas dos
métodos para facilitar a localização do erro e de suas causas.
Alguns tipos de exceções são opcionais: o uso de blocos try/catch não é necessário, e depende do pro-
gramador decidir entre o uso de blocos if/else ou try/catch para processar eventuais erros de execução
dos trechos de programas ou classes. Outros tipos de exceção são obrigatórias: para uso de algumas
classes ou métodos de classes, estes devem obrigatoriamente ser chamadas de blocos try, e as exceções
correspondentes devem ser pegas pelos blocos catch. Exceções obrigatórias serão vistas no capítulo 13.
• ArithmeticException: Esta exceção opcional é levantada quando alguns erros de cálculos ma-
temáticos ocorrem. O método pow() da classe Math pode lançar este erro quando executarmos
Math.pow(a,b) com a igual a zero e b menor que zero ou a menor que zero e b não-inteiro.
Uma divisão por zero de valores inteiros também pode causar esta exceção, como visto na lista-
gem 12.6. Vale a pena notar que em Java, uma divisão por zero de valores de ponto flutuante não
é considerada como um erro, e uma exceção não é lançada: divisões por zero de valores de ponto
flutuante são consideradas como infinitas e representadas pelo valor especial Infinity, e o valor
0/0 é representado pelo valor especial Nan (Not a Number).
• NumberFormatException: Esta exceção opcional é levantada quando tentamos converter uma String
para valor numérico usando, por exemplo, os construtores das classes Byte (seção A.2.2.1), Short
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
154
(seção A.2.2.3), Integer (seção A.2.2.4), Long (seção A.2.2.5), Float (seção A.2.2.6) e Double (se-
ção A.2.2.7). Se as Strings passadas para os construtores destas classes não puderem ser convertidas,
a exceção será lançada.
• ArrayIndexOutOfBoundsException: Esta exceção opcional é levantada quando tentamos acessar
um elemento em um array através de um índice não-válido, ou seja, um índice que é menor do que
zero ou maior ou igual ao número de elementos do array.
• StringIndexOutOfBoundsException: Esta exceção opcional é levantada quando tentamos acessar
um caracter ou substring em uma String usando índices não-válidos, ou seja, índices que são menores
do que zero ou maiores ou iguais ao número de caracteres da String.
• IllegalArgumentException: Esta exceção opcional é levantada quando um argumento não-válido
é passado para um método, que não pode ser executado por causa deste erro.
• RuntimeException: Esta é a super-classe (ancestral) de todas as classes que representam exceções
opcionais, e pode ser usada por programadores para criar exceções opcionais através de herança.
• EOFException: Esta exceção é lançada quando o final de um arquivo sendo lido é alcançado, e pode
ser usada para terminar um bloco de leitura de arquivos.
• FileNotFoundException: Esta exceção é lançada quando tentamos abrir um arquivo com um nome
para leitura e o arquivo não é encontrado.
• IOException: Esta é a exceção genérica para erros em processamento de arquivos. É aconselhável
o uso das classes herdeiras desta, mostradas acima, mas ao menos uma exceção herdeira desta classe
deve ser obrigatoriamente usada para processamento de arquivos.
• Exception: Esta é a classe ancestral de todas as exceções. Se for usada com outras exceções, ela
deve ser a última exceção a ser pega (deve estar no último bloco catch).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
155
Podemos escrever nossas próprias exceções e usá-las para documentar erros nas classes em português com
o nível de detalhe desejado. Ao escrever nossas próprias exceções, elas devem ser herdeiras da classe
Exception1 ou de uma das herdeiras desta classe. Para fazer uma exceção opcional, podemos fazer a
nossa classe de exceções herdar da classe RuntimeException, como visto na listagem 12.8.
A classe ExcecaoDeArrays, mostrada na listagem 12.8, consiste somente de um construtor que chamará
o construtor da classe ancestral através do super() e mostrará uma mensagem de erro ao ser chamado,
usando a String passada como argumento para o construtor (linha 13). Esta classe pode ser usada no lugar
das exceções de Java na classe ArrayDeFloats todas as vezes que um erro de índice de arrays ocorrer,
como mostrado na listagem 12.9.
Listagem 12.9: A classe ArrayDeFloats com métodos que lançam exceções ExcecaoDeArray
1 /* Esta classe encapsula um array de floats */
2 class ArrayDeFloats
3 {
4 private float array[]; // declaração do array que será encapsulado
5 /* Construtor, aceita um argumento que é o número de floats a serem armazenados. */
6 ArrayDeFloats(int número)
7 {
8 // Se o usuário passar um valor menor do que zero, criamos uma exceção
9 if (número <= 0)
10 throw new ExcecaoDeArrays("Tamanho "+número+" menor que zero");
11 array = new float[número]; // aloco memória para o array declarado anteriormente
1 Mais especificamente, da classe Throwable, mas como a classe Exception herda da Throwable podemos simplificar.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
156
12 }
13 /* Método que seta o valor na posição especificada */
14 void seta(int posição,float valor)
15 {
16 if ((posição >= 0) && (posição < array.length)) // somente se estiver na faixa de índices
17 array[posição] = valor; // válidos o valor será modificado
18 else // criamos uma exceção de tentativa de acesso indevido
19 throw new ExcecaoDeArrays("Tentativa de setar elemento "+posição+
20 " fora da faixa [0-"+(array.length-1)+"].");
21 }
22 /* Método que permite o acesso à um dos valores do array */
23 float valor(int posição)
24 {
25 if ((posição >= 0) && (posição < array.length))
26 return array[posição];
27 else // criamos uma exceção de tentativa de acesso indevido
28 throw new ExcecaoDeArrays("Tentativa de acessar elemento "+posição+
29 " fora da faixa [0-"+(array.length-1)+"].");
30 }
31 } // fim da classe ArrayDeFloats
Se um programa ou classe criar instância da classe ArrayDeFloats (mostrada na listagem 12.9) com
valores menores ou iguais a zero passados para o construtor, a exceção ExcecaoDeArrays (mostrada
na listagem 12.8) será levantada. É importante notar que como a exceção é opcional, se um programa
ou classe não pegar a exceção ExcecaoDeArrays em um bloco catch, além das mensagens da exceção
ExcecaoDeArrays outras mensagens poderão aparecer.
Programadores escrevendo classes podem forçar os programadores que usarão estas classes a processarem
as exceções previstas, usando exceções obrigatórias. Para fazer isto, o primeiro passo é criar uma classe
que representa uma exceção que herde de uma exceção obrigatória, como a classe Exception. Uma classe
que herda da classe Exception é mostrada na listagem 12.10.
Listagem 12.10: Uma classe que representa uma exceção que deve ser pega
1 /* Uma classe que representa uma exceção de acesso à Arrays. Esta classe herda da
2 classe Exception, indicando uma exceção que deve ser obrigatoriamente pega. */
3 class ExcecaoRigorosaDeArrays extends Exception
4 {
5 /* O construtor da classe recebe uma mensagem que será mostrada quando a exceção
6 ocorrer. */
7 ExcecaoRigorosaDeArrays(String mensagem)
8 {
9 // Chamamos o construtor da classe ancestral...
10 super();
11 // Imprimimos uma mensagem de erro - note que usamos System.err em vez de
12 // System.out para garantir que a mensagem será mostrada no terminal
13 System.err.println("Exceção de Arrays: "+mensagem+".");
14 }
15 } // fim da classe ExcecaoRigorosaDeArrays
Para lançarmos exceções do tipo ExcecaoRigorosaDeArrays devemos informar ao compilador que mé-
todos que podem lançar estas exceções. Isto é feito anexando-se à declaração dos métodos a palavra-chave
throws (notem que é plural) com o nome da exceção que será lançada. Várias exceções podem ser lança-
das por um método de uma classe, bastando declará-las desta forma, separadas por vírgulas.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
157
Listagem 12.11: A classe ArrayDeFloats com métodos que lançam exceções ExcecaoRigorosaDeArray
1 /* Esta classe encapsula um array de floats */
2 class ArrayDeFloats
3 {
4 private float array[]; // declaração do array que será encapsulado
5 /* Construtor, aceita um argumento que é o número de floats a serem armazenados. */
6 ArrayDeFloats(int número) throws ExcecaoRigorosaDeArrays
7 {
8 // Se o usuário passar um valor menor do que zero, criamos uma exceção
9 if (número < 0)
10 throw new ExcecaoRigorosaDeArrays("Tamanho "+número+" menor que zero");
11 array = new float[número]; // aloco memória para o array declarado anteriormente
12 }
13 /* Método que seta o valor na posição especificada */
14 void seta(int posição,float valor) throws ExcecaoRigorosaDeArrays
15 {
16 if ((posição >= 0) && (posição < array.length)) // somente se estiver na faixa de índices
17 array[posição] = valor; // válidos o valor será modificado
18 else // criamos uma exceção de tentativa de acesso indevido
19 throw new ExcecaoRigorosaDeArrays("Tentativa de setar elemento "+posição+
20 " fora da faixa [0-"+(array.length-1)+"].");
21 }
22 /* Método que permite o acesso à um dos valores do array */
23 float valor(int posição) throws ExcecaoRigorosaDeArrays
24 {
25 if ((posição >= 0) && (posição < array.length))
26 return array[posição];
27 else // criamos uma exceção de tentativa de acesso indevido
28 throw new ExcecaoRigorosaDeArrays("Tentativa de acessar elemento "+posição+
29 " fora da faixa [0-"+(array.length-1)+"].");
30 }
31 } // fim da classe ArrayDeFloats
Como as exceções previstas na classe ArrayDeFloats (listagem 12.11) devem ser obrigatoriamente pegas,
um programa que use instâncias de ArrayDeFloats deve cercar as chamadas aos métodos das classes que
podem levantar as exceções (inclusive o construtor de ArrayDeFloats) com um bloco try, e pegar no
bloco catch a exceção ExcecaoRigorosaDeArray, como mostrado no programa na listagem 12.12.
Listagem 12.12: Um programa que usa a classe ArrayDeFloats com exceções que devem obrigatoria-
mente ser pegas
1 /* Esta classe demonstra o uso da classe ArrayDeFloats */
2 class DemoArrayDeFloats
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 ArrayDeFloats af;
8 // Como a classe ArrayDeFloats tem uma exceção que deve obrigatoriamente ser pega,
9 // temos que envolver o uso da classe em um bloco try/catch
10 try // tenta executar os comandos relacionados com ArrayDeFloats...
11 {
12 af = new ArrayDeFloats(10);
13 af.seta(10,3.1416f);
14 }
15 catch(ExcecaoRigorosaDeArrays e) // se houver algum erro, imprima mensagem.
16 {
17 e.printStackTrace(); // imprimimos o histórico de chamadas
18 }
19 System.out.println("Fim do programa");
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
158
Exercício 12.2: ? ?
Modifique o programa na listagem 10.5 para que o acesso ao array seja feito dentro de um bloco
try/catch, e que a exceção ArrayIndexOutOfBounds seja pega. Dica: o bloco try/catch pode fi-
car dentro do bloco while.
Exercício 12.3: ? ?
Modifique a classe ArrayDeQuadrados (listagem 10.6) para que o método quadrado lançe uma exceção
ArrayIndexOutOfBounds ao invés de imprimir mensagens de erro e retornar 1.
Exercício 12.4: ? ? ?
Modifique a classe ListaDePessoas (listagem 10.16) para que o método setaDados lançe a exceção
ArrayIndexOutOfBounds. Modifique também o programa na listagem 10.17 para que as chamadas ao
método setaDados estejam dentro de um bloco try/catch.
Exercício 12.5: ? ? ?
Considere o exercício 9.27. Reescreva a calculadora básica de forma que os valores sejam passados pela
linha de comando. Alguns dos problemas que podem ocorrer na execução do programa são a passagem
de número de argumentos pela linha de comando incompatíveis com o esperado e conversão de Strings
para doubles impossível. Escreva este programa usando um bloco try/catch que pega estes tipos de
erros em potencial.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
159
Capítulo 13
13.1 Introdução
A manipulação de arquivos é uma das tarefas mais importantes de um computador, e portanto, de um pro-
grama de computador. Arquivos permitem o armazenamento permanente de informações em discos ou
outros dispositivos, fazendo com que um programa (que também é armazenado em um arquivo) não seja
limitado ao processamento de informações definidas em seu código-fonte ou lidas do teclado.
Existem diversos tipos de arquivos, que podem ser categorizados tanto pelo seu conteúdo quanto pela
maneira como este conteúdo é manipulado. Em relação ao conteúdo, e considerando as características da
linguagem Java, existem três categorias básicas de arquivos:
• Arquivos de texto: Estes tipos de arquivos contém somente texto, que pode ser lido por qualquer
editor ou mostrado nos terminais simples dos sistemas operacionais. Alguns exemplos de arquivos
de texto são arquivos com código-fonte de linguagens como Java, C, Pascal, Perl; arquivos de con-
figuração de sistemas operacionais, arquivos em HTML (que definem formatação básica de páginas
na WWW), etc.
É comum o uso de arquivos de texto simples para representar tabelas de bancos de dados em peque-
nas aplicações e protótipos de sistemas, o que dispensa um mecanismo de gerenciamento de bancos
de dados. Esta abordagem, porém, tem várias limitações para aplicações de médio e grande porte,
em especial, aplicações comerciais.
Em Java, arquivos de texto podem ser lidos e parte ou todo seu conteúdo podem ser armazenados em
Strings.
• Arquivos binários: Estes tipos de arquivos contém somente informações de forma binária, que ge-
ralmente representam uma codificação com uma finalidade específica. Para vermos o conteúdo de
arquivos binários, frequentemente é necessário usarmos um programa especial que decodifique os
dados do arquivo para mostrar o conteúdo. Arquivos de imagens, sons, programas compilados, uti-
litários de sistemas operacionais, etc. são exemplos de arquivos binários. Em Java, arquivos que
contém valores de tipos nativos são armazenados de forma binária.
• Arquivos de instâncias: Estes tipos de arquivos, particulares de Java, são uma subcategoria de ar-
quivos binários que representam instâncias de classes existentes. Arquivos de instâncias de classes
permitem a serialização das classes (gravação de estados de instâncias para processamento posteri-
or). Arquivos de instâncias somente podem ser lidos por máquinas virtuais Java que tenham acesso
às classes originais.
Para cada categoria de conteúdo de arquivos mostrada acima, veremos formas de manipular estes arquivos
através do uso de classes de Java.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
160
Quanto à forma de acesso, arquivos podem ser divididos nas seguintes categorias:
• Arquivos somente para leitura: São arquivos que contém dados que serão lidos do arquivo e pro-
cessados pelo programa, ou armazenados na memória. Para que os programas que dependem de
arquivos de leitura funcionem corretamente, estes arquivos devem existir e estar disponíveis para o
programa (ser acessíveis).
• Arquivos somente para escrita: São arquivos que serão criados com dados fornecidos pelo programa.
Se estes arquivos não existirem, serão criados para uso pelo programa. Arquivos somente podem ser
abertos para escrita se o sistema operacional onde a máquina virtual Java estiver sendo executada
permitir a operação.
• Arquivos para leitura e escrita: São arquivos que poderão, ao ser abertos, ser usados para leitura e
escrita, seguindo as regras acima.
• Arquivos de leitura e escrita sequenciais: Estes arquivos serão lidos em sequência, ou seja, informa-
ção por informação, quer se trate de texto ou dados binários. Para alcancar determinada posição dos
dados no arquivo deveremos ler todos os dados antes daquele. Pode-se pensar em uma analogia com
músicas armazenadas em uma fita cassete.
• Arquivos de leitura e escrita aleatória: Estes arquivos poderão ser lidos de maneira aleatória, ou
seja, podemos posicionar um ponteiro em qualquer posição existente no arquivo e escrever ou gravar
a partir daquela posição, sem necessidade de ler ou escrever dados anteriores1 .
As seções seguintes neste capítulo tratam de diversas classes em Java que permitem acesso a arquivos nas
diferentes formas descritas acima.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
161
À esquerda da figura 13.1 vemos o acesso à um arquivo encapsulado por uma classe que permite a leitura
e/ou gravação de bytes ou caracteres: as classes que encapsulam arquivos deste tipo possuem métodos que
permitem o acesso aos bytes ou caracteres. À direita da figura vemos um caso ligeiramente mais complexo:
uma classe que permite o acesso aos bytes ou caracteres do arquivo é encapsulada por outra classe que,
através dos seus métodos, permite o acesso à estruturas mais complexas como Strings e instâncias de clas-
ses. Todas as vezes que uma destas estruturas mais complexas é acessada, os métodos da classe de nível
mais alto chamam os métodos da classe de nível mais baixo, traduzindo os pedidos.
As classes que implementam mecanismos de representação e acesso à arquivos fazem parte de um pacote
ou biblioteca de classes chamada java.io. Para que possamos usar estas classes, devemos incluir no início
de todos os programas que fazem manipulação de arquivos a linha import java.io.*;, que importará
todas as classes do pacote java.io. Esta linha deve ser incluída antes da declaração das classes.
Todas as classes que implementam acesso à arquivos em Java contém possibilidades de ocorrência de
exceções obrigatórias, que devem ser pegas quando usamos as instâncias das classes.
Vale a pena lembrar que a forma de acesso de arquivos é diferente para diferentes sistemas operacionais,
especialmente se nomes de arquivos que não estão localizados no mesmo diretório dos programas for usa-
do. Em caso de dúvida consulte o guia de uso de seu sistema operacional ou o guru mais próximo.
FCC/UNIVAP Todos os arquivos deste capítulo podem ser acessados das contas no Linux nos la-
boratórios da Faculdade de Ciência da Computação, bastando usar o nome completo do arquivo, que é
composto do prefixo ”/home/tico/POO/” mais o nome do arquivo. Por exemplo, para acessar o arqui-
vo ”estoquelivraria.dat” nos programas desenvolvidos no laboratório, basta usar o nome completo
”/home/tico/POO/estoquelivraria.dat” quando for referenciar o arquivo.
1 2 3
l i n h a 1 S o u t r a l i n h a S ú l t i m a l i n h a S
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
162
A figura 13.2 representa um arquivo de textos contendo algumas Strings separadas pelos separadores mar-
cados como ’S’ (que dependem do sistema operacional sendo usado, podendo ser compostos de um ou
dois caracteres). Quando o arquivo é aberto, o ponteiro deste aponta para o primeiro caracter do arquivo
(posição 1). Após a leitura da primeira linha como uma String, o ponteiro estará apontando para a posição
2, e após a leitura da segunda linha, para a posição 3. O programador não tem acesso ou controle ao pon-
teiro.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
163
A criação das instâncias das classes FileReader (linha 15) e BufferedReader (linha 17) poderia ser feita
de uma só vez, como BufferedReader br = new BufferedReader(new FileReader(arquivo)).
Podemos implementar parte das funções de manipulação de arquivos dentro de métodos nas classes defi-
nidas pelo usuário, como no exemplo seguinte. Suponhamos que o estoque de uma livraria contenha, para
cada livro, o título do livro, o nome do autor, o número de livros em estoque, o preço de compra dos livros
(de uma editora, por exemplo) e o preço de venda final dos livros. Este estoque poderia ser representado
por um arquivo onde cada linha conteria informações sobre um livro, formatados de maneira a podemos
“cortar” a String com o método substring() e recuperar os diversos campos. Parte deste arquivo que
contém os dados dos livros é mostrado na listagem 13.2.
Listagem 13.2: Listagem parcial do arquivo que contém informações sobre livros de uma livraria
Dave Barry Talks Back Dave Barry 42 21.50 25.00
Introduction to Programming Using Java David Arnow, Gerald Weiss 10 42.50 58.00
Conectiva Linux Guarani Conectiva S.A. 9 55.00 62.00
Graphic Java 1.1 David M. Geary 18 70.00 90.00
Understanding Japanese Information Processing Ken Lunde 4 27.50 32.00
Uma classe que representasse os livros de uma livraria poderia ser capaz de inicializar suas instâncias atra-
vés da leitura do arquivo que contém dados desta, e da divisão das linhas de texto nos componentes que
representam o livro. A classe LivroLivraria, mostrada na listagem 13.3, mostra como isso pode ser feito.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
164
Com esta classe, podemos implementar programas que abrem um arquivo de texto e usam as linhas do
arquivo para inicializar instâncias da classe, como o mostrado na listagem 13.4.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
165
• BufferedWriter(): o construtor da classe. Este construtor espera um argumento que é uma instân-
cia da classe FileWriter, que por sua vez será criada usando um nome de arquivo como argumento.
Opcionalmente, podemos especificar um valor inteiro que será o tamanho para o buffer a ser criado
para a gravação dos caracteres: um buffer maior pode fazer com que o número de acessos ao disco
seja minimizado, fazendo com que o programa seja executado mais rapidamente, mas ao custo de
mais memória em uso. O tamanho default do buffer é 8192 bytes.
• write(): este método grava a String que for passada como argumento para ele no arquivo de saída,
respeitando as regras do buffer. Para compatibilidade, nenhum caracter de terminação de linhas
(’\n’, ’\r’, etc.) deverá ser usado na String passada como argumento para este método.
• newLine(): este método sem argumentos grava um terminador de linha (que será diferente depen-
dendo do sistema operacional sendo usado) no arquivo de saída, respeitando as regras do buffer. A
gravação deste terminador não implica no esvaziamento do buffer.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
166
• flush(): este método sem argumentos descarrega o buffer no arquivo e esvazia o buffer. Em casos
normais (escrita simples em um arquivo) não é usado diretamente.
• close(): este método fecha o arquivo associado com a instância da classe BufferedWriter, fechan-
do também o arquivo associado com a instância da classe FileWriter que foi usada para construir
a instância de BufferedWriter. Antes de fechar o arquivo, este método executa o método flush()
descrito anteriormente.
Toda a manipulação das instâncias destas classes, inclusive a sua criação, deve estar dentro de um bloco
try, e deve existir ao menos um bloco catch para a exceção IOException. O programa na listagem 13.5
mostra como podemos usar uma instância da classe BufferedWriter para gravar Strings lidas do teclado
em um arquivo de texto.
Arquivos também podem ser gravados a partir de classes, de forma que o acesso direto aos arquivos fique
de maneira análoga à mostrada no programa na listagem 13.3.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
167
Java tem classes que permitem a gravação e leitura de arquivos sequenciais de tipos nativos, que serão
gravados e lidos de arquivos binários. Neste modo de gravação, ponteiros que apontam para a próxima
posição de leitura e gravação também são usados, mas diferentemente do caso de arquivos de texto, se-
paradores não são usados, uma vez que cada tipo nativo tem um tamanho definido. Após cada leitura ou
gravação o ponteiro se moverá para a próxima posição, que é calculada levando em conta o tamanho em
bytes dos dados gravados. A figura 13.3 demonstra o funcionamento de ponteiros em um arquivo de leitura.
1 2 3 4 5
f f f f i i i i i i i i d d d d d d d d u u u u u u u u u u u u u
um float um int outro int um double uma String UTF
A figura 13.3 representa um arquivo binário contendo alguns dados de tipos nativos. Não existem separa-
dores entre os dados gravados. Quando o arquivo é aberto, o ponteiro deste aponta para o primeiro byte do
arquivo (posição 1). Após a leitura do primeiro dado como um float (4 bytes), o ponteiro estará apontando
para a posição 2. Após a leitura do segundo dado como um int (4 bytes), o ponteiro estará apontando para
a posição 3, e assim sucessivamente. O programador não tem acesso ou controle ao ponteiro.
A figura 13.3 mostra, na representação do arquivo, um tipo de dado não visto até agora: uma String UTF
(Unicode Transfer Format), que é uma representação de Strings que engloba também o tamanho da String,
dispensando separadores, mas com a limitação de 65535 caracteres. Este tipo de dado é útil para gravação
e leitura em arquivos juntamente de outros tipos nativos. Para os programas, estes tipos serão processados
como Strings normais, como será visto nos exemplos.
• DataInputStream(): o construtor da classe. Este construtor espera um argumento que é uma ins-
tância da classe FileInputStream, que por sua vez será criada usando um nome de arquivo como
argumento.
• available(): este método retorna o número de bytes que ainda pode lido do arquivo. Este método
pode ser usado para verificar o fim do arquivo, quando não houverem mais bytes disponíveis para
leitura.
• readBoolean(): este método lê e retorna um valor do tipo boolean do arquivo.
• readChar(): este método lê e retorna um valor do tipo char do arquivo.
• readByte(): este método lê e retorna um valor do tipo byte do arquivo.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
168
• readUnsignedByte(): este método lê e retorna um byte do arquivo, mas considera que este valor
não tem sinal (estando na faixa de valores 0 255), e retorna o valor lido como um inteiro.
• readShort(): este método lê e retorna um valor do tipo short do arquivo.
• readUnsignedShort(): este método lê e retorna um short do arquivo, mas considera que este valor
não tem sinal (estando na faixa de valores 0 65535), e retorna o valor lido como um inteiro.
• readInt(): este método lê e retorna um valor do tipo int do arquivo.
• readLong(): este método lê e retorna um valor do tipo long do arquivo.
• readFloat(): este método lê e retorna um valor do tipo float do arquivo.
• readDouble(): este método lê e retorna um valor do tipo double do arquivo.
• readUTF(): este método lê e retorna uma String codificada no formato UTF (Unicode Transfer
Format), que representa o tamanho da String junto com a própria String. Uma String representada
no formato UTF deve ter no máximo 65535 caracteres. Este método só deve ser usado para ler Strings
se estas forem escritas no formato UTF - veja o método writeUTF da classe DataOutputStream na
seção 13.3.2.
• close(): este método fecha o arquivo associado com a instância da classe DataInputStream, fe-
chando também o arquivo associado com a instância da classe FileInputStream que foi usada para
construir a instância de DataInputStream.
Da mesma forma com que outras classes, toda a manipulação das instâncias destas classes, inclusive a
sua criação, deve estar dentro de um bloco try, e deve existir ao menos um bloco catch para a exce-
ção IOException. O programa na listagem 13.6 mostra como podemos usar uma instância da classe
DataInputStream para ler um arquivo de valores do tipo float, um a um, até o fim do arquivo, calculando
o maior e menor valores no arquivo.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
169
28 if (valor < menor) menor = valor; // comparamos com o menor, e mudamos se for menor
29 }
30 } // sairemos do laço quando não houverem mais bytes a ser lidos
31 // Fechamos a instância da classe DataInputStream, o que fechará automaticamente a
32 // instância da classe FileInputStream
33 dis.close();
34 } // fim do bloco try
35 catch (FileNotFoundException e) // Se o arquivo não foi encontrado...
36 {
37 System.out.println("O arquivo não foi encontrado.");
38 }
39 catch (IOException e) // Se houve erros de I/O..
40 {
41 System.out.println("Houve um erro de leitura do arquivo.");
42 }
43 // Ao final, imprimimos o maior e o menor valores lidos do arquivo
44 System.out.println("O maior valor foi "+maior);
45 System.out.println("O menor valor foi "+menor);
46 }
47 } // fim da classe LeituraSequencialDeFloats
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
170
Um exemplo mais elaborado de uso das classes DataOutputStream e DataInputStream será mostrado a
seguir. O programa na listagem 13.7 mostra como podemos encapsular a capacidade de ler e gravar dados
de uma classe em um arquivo.
Listagem 13.7: A classe ContaBancaria que faz operações de gravação e leitura em um arquivo
1 import java.io.*; // Esta linha é obrigatória - permite o uso das classes de I/O
2
3 /* Esta é a classe ContaBancaria, com funções de entrada e saída dos dados através de
4 arquivos */
5 class ContaBancaria
6 {
7 /* Dados de uma conta bancária simplificada */
8 private String nome; // nome do correntista
9 private int número; // número da conta
10 private float saldo; // saldo da conta
11 private boolean éEspecial; // a conta é especial ou não ?
12 /* Construtor vazio - perguntará os dados para o usuário entrar pelo teclado */
13 ContaBancaria()
14 {
15 System.out.print("Entre o nome do cliente:");
16 nome = Keyboard.readString();
17 System.out.print("Entre o número da conta:");
18 número = Keyboard.readInt();
19 System.out.print("Entre o saldo inicial:");
20 saldo = Keyboard.readFloat();
21 System.out.print("Entre ’s’ para conta especial:");
22 éEspecial = Keyboard.readBoolean();
23 }
24 /* Construtor que inicializa os valores com argumentos */
25 ContaBancaria(String n,int num,float s,boolean e)
26 {
27 nome = n; // inicializa o nome
28 número = num; // inicializa o número da conta
29 saldo = s; // inicializa o saldo
30 éEspecial = e; // inicializa o booleano éEspecial
31 }
32 /* Construtor que inicializa os valores através da leitura de um arquivo */
33 ContaBancaria(DataInputStream dis) throws IOException
34 {
35 nome = dis.readUTF(); // lê o nome
36 número = dis.readInt(); // lê o número da conta
37 saldo = dis.readFloat(); // lê o saldo
38 éEspecial = dis.readBoolean(); // lê o booleano éEspecial
39 }
40 /* Método que grava os valores da classe em um arquivo */
41 void grava(DataOutputStream dos) throws IOException
42 {
43 dos.writeUTF(nome); // grava o nome
44 dos.writeInt(número); // grava o número da conta
45 dos.writeFloat(saldo); // grava o saldo
46 dos.writeBoolean(éEspecial); // grava o booleano éEspecial
47 }
48 /* Este método deposita um valor na conta bancária */
49 void deposita(float valor)
50 {
51 saldo = saldo + valor;
52 }
53 /* Este método retira um valor da conta bancária */
54 void retira(float valor)
55 {
56 if (valor > saldo) // se o valor a retirar é maior que o saldo
57 {
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
171
Instâncias desta classe podem ser construídas usando uma instância da classe DataInputStream, que deve
ser criada em um programa ou classe que contenha instâncias da classe ContaBancaria, como mostrado
no programa da listagem 13.8.
Listagem 13.8: Programa que usa instâncias da classe ContaBancaria (inicializadas a partir de um arqui-
vo)
1 /* Este programa demonstra o uso da classe DataOutputStream para gravar instâncias da classe
2 ContaBancaria. Várias instâncias serão criadas com dados lidos do teclado e gravadas em um
3 arquivo. */
4
5 import java.io.*; // Esta linha é obrigatória - permite o uso das classes de I/O
6
7 class CriaArqContaBancaria
8 {
9 /* O método main permite a execução da classe */
10 public static void main(String args[])
11 {
12 // Perguntamos em que arquivo deverão ser gravadas as instâncias de ContaBancaria
13 System.out.print("Nome do arquivo a ser criado:");
14 String arquivo = Keyboard.readString(); // lemos o nome do arquivo do teclado
15 // Perguntamos quantas contas bancárias serão gravadas no arquivo
16 System.out.print("Quantas contas bancárias serão criadas ?:");
17 int ncontas = Keyboard.readInt(); // lemos o número de contas do teclado
18 try // tenta abrir o arquivo, gravar dados e fechá-lo
19 {
20 // Criamos uma instância da classe FileOutputStream e a
21 // usamos no construtor da DataOutputStream
22 DataOutputStream dos = new DataOutputStream(new FileOutputStream(arquivo));
23 for(int i=0;i<ncontas;i++)
24 {
25 // O construtor vazio da classe ContaBancaria pede os dados pelo teclado
26 ContaBancaria cb = new ContaBancaria();
27 // Gravamos os dados no arquivo criado
28 cb.grava(dos);
29 }
30 // Fechamos a instância da classe BufferedReader
31 dos.close();
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
172
Exercício 13.2: ?
Modifique o programa na listagem 13.1 para que as Strings lidas sejam impressas no terminal.
Exercício 13.3: ?
Modifique o programa na listagem 13.1 para que o total de caracteres seja calculado, ao invés do total de
linhas. Dica: use o método length() da classe String.
Exercício 13.4: ?
Modifique o programa na listagem 13.1 para que todo o conteúdo do arquivo seja lido em uma única
String. Faça com que o programa imprima esta String no final. O resultado da impressão é igual ao
arquivo original ? Porquê ? Dica: use um arquivo bem menor do que o ”linux.words” para fazer os
testes.
Exercício 13.5: ? ?
Escreva um programa em Java que abra um arquivo de texto para entrada (usando a classe
BufferedReader) e um para saída (usando a classe BufferedWriter) e copie todas as linhas do ar-
quivo de entrada para o arquivo de saída.
Exercício 13.6: ? ?
Escreva um programa em Java que abra um arquivo de texto para entrada (usando a classe
BufferedReader) e calcule quantos espaços existem neste arquivo. Dica: use o método charAt()
da classe String.
Exercício 13.7: ? ?
Usando o exercício 9.15 como base, escreva um programa em Java que desacentue todas as Strings de um
arquivo.
Exercício 13.8: ? ?
Usando o exercício 9.17 como base, escreva um programa em Java que leia um arquivo linha por linha e
imprima somente as linhas que sejam palíndromas.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
173
Exercício 13.9: ? ?
Escreva um programa em Java que leia um arquivo de texto linha por linha e imprima somente as conso-
antes do texto contido no arquivo.
Exercício 13.10: ? ?
Usando o exercício 9.20 como base, escreva um programa em Java que leia um arquivo linha por linha e
imprima somente as linhas que contenham palavras com caracteres repetidos (”rr”, ”ee”, etc.)
Exercício 13.11: ? ?
Usando o exercício 9.23 como base, escreva um programa em Java que leia o arquivo linux.words
(seção 13.2.1) e imprima, para cada palavra no arquivo, o número de pontos que esta valeria no jogo de
palavras cruzadas.
Exercício 13.12: ? ?
Escreva um programa em Java que receba da linha de comando um nome de arquivo e uma String, abra o
arquivo indicado e leia todas as suas linhas, imprimindo somente as linhas que contém a String passada
como argumento. Dica: use o método indexOf() da classe String para verificar se a linha do arquivo
contém a String especificada.
Exercício 13.13: ? ?
Modifique o programa do exercício 13.12 para que somente as palavras do arquivo que começem ou ter-
minem com a String passada como argumento sejam impressas. Por exemplo, se o arquivo linux.words
for usado e a String passada for ”inter”, o programa deverá imprimir ”intersect” e ”pointer” mas
não deverá imprimir ”uninteresting”.
Exercício 13.14: ? ?
Escreva um programa em Java que leia um arquivo de palavras como o linux.words (veja seção 13.2.1)
e imprima a palavra mais curta e a mais longa deste arquivo.
Exercício 13.15: ? ?
Escreva um programa em Java leia um arquivo de palavras como o linux.words (veja seção 13.2.1) e
calcule quantas vezes um caracter (que pode ser passado pela linha de comando) ocorre naquele arquivo.
Exercício 13.16: ? ?
No programa na listagem 13.6 verificamos o fim de arquivo vendo quantos bytes ainda podemos ler -
se não pudermos ler mais nenhum, consideramos que o fim do arquivo foi alcançado. Outra maneira de
verificar fim de arquivo é capturando a exceção EOFException em um dos blocos catch, e fechando o
arquivo caso esta exceção ocorra. Modifique a listagem 13.6 para que use a exceção EOFException para
verificar se o fim de arquivo foi encontrado.
Exercício 13.17: ? ?
O programa na listagem 13.6 lê um arquivo de dados do tipo float. Escreva um programa em Java, usando
a classe DataOutputStream, que crie um arquivo de 10.000 valores aleatórios do tipo float, entre 0 e
1000.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
174
Exercício 13.18: ? ? ?
Escreva um programa em Java que abra um arquivo de texto para entrada (usando a classe
BufferedReader) e calcule quantos caracteres de cada tipo existem neste arquivo. Considere carac-
teres maiúsculos e minúsculos como sendo iguais. Considere 27 categorias de caracteres: uma para cada
letra e uma categoria “outros”, que receberá todos os caracteres que não são letras. Dicas: use o mé-
todo charAt() da classe String, e um array de 27 inteiros para receber os caracteres. Veja também o
exercício 13.15.
Exercício 13.19: ? ? ?
Escreva um programa em Java que leia um arquivo de texto de entrada, transforme todas as Strings deste
arquivo usando o algoritmo rot13 e as grave em outro arquivo de saída. Dicas: use o exercício 9.29 como
base, veja também o exercício 13.5.
Exercício 13.20: ? ? ?
Escreva um programa em Java que leia dois arquivos de texto simultaneamente e compare os conteúdos
destes arquivos (linha por linha). Se os arquivos forem iguais, uma mensagem apropriada deve ser im-
pressa. Se os arquivos forem diferentes, assim que a diferença for detectada, as linhas diferentes devem
ser impressas e o programa deve terminar. Dica: use a classe BufferedReader para ler os arquivos,
e compare-os com o método compare da classe String, que retorna zero somente se as Strings sendo
comparadas são iguais.
Exercício 13.21: ? ? ?
Escreva um programa em Java que leia um arquivo de palavras e crie três arquivos de saída. As palavras
lidas que tiverem menos do que seis caracteres devem ser gravadas no primeiro arquivo de saída, as que
tiverem entre seis e dez caracteres devem ser gravadas no segundo arquivo de saída e as que tiverem mais
de dez caracteres devem ser gravadas no terceiro arquivo de saída. Ao final da execução do programa
mostre no terminal quantas palavras foram gravadas em cada um destes arquivos.
Exercício 13.22: ? ? ?
Escreva um programa em Java que use o algoritmo de César (exercício 9.30) para codificar um arquivo
de texto, linha por linha. Faça com que o usuário possa entrar o nome do arquivo de entrada, o nome do
arquivo de saída e a chave a ser usada pela linha de comando.
Exercício 13.23: ? ? ?
Modifique o programa na listagem 13.4 para que este calcule o lucro total que seria obtido caso todos
os livros em estoque fossem vendidos. Para isto, será necessário modificar a classe LivroLivraria
(listagem 13.3), criando um método que retorne, para uma instância da classe, o lucro esperado (valor de
venda menos o valor de compra multiplicado pelo número de livros em estoque). O lucro total será dado
pela soma do lucro esperado de todos os livros.
Exercício 13.24: ? ? ?
Modifique o programa na listagem 13.6 para que todos os valores do tipo float sejam lidos do arquivo para
um array. Dica: É necessário saber o número de posições que o array deve conter, para isso podemos
verificar o número de bytes que ainda podem ser lidos do arquivo assim que este é aberto. Como cada
dado do tipo float ocupa quatro bytes, podemos calcular o tamanho do array necessário.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
175
Exercício 13.25: ? ? ?
Usando a classe ContaBancaria como base, escreva um programa em Java que abra um arquivo para lei-
tura e dele leia instâncias da classe ContaBancaria e imprima-as no terminal. O arquivo tababank.dat
pode ser usado para isto (veja seção 13.1.2 para informações sobre como obter este arquivo).
Exercício 13.26: ? ? ?
Usando o exercício exer:arquivos-lecontas como base, escreva um programa em Java que leia um arquivo
contendo dados de contas bancárias e imprima o maior saldo das contas naquele arquivo e a conta que
tem o maior saldo.
Exercício 13.27: ? ? ? ?
Modifique a classe LivroLivraria (listagem 13.3) para que esta tenha um método grava, que recebendo
uma instância da classe BufferedWriter como argumento, grave os dados do livro na mesma, de forma
que outras instâncias da classe LivroLivraria possam ler estes dados. Dica: é necessário formatar os
dados da instância de LivroLivraria para que estes ocupem o mesmo tamanho esperado pelo construtor
- algumas Strings deverão ser completadas com espaços para chegar no tamanho desejado, enquanto ou-
tras deverão ser cortadas. Alguns valores numéricos deverão ser transformados em Strings, veja também
o exercício 9.36
Exercício 13.28: ? ? ? ?
Escreva um programa em Java que, a partir de um arquivo de textos de entrada, leia todas as Strings deste
arquivo e como resultado imprima o código morse correspondente à elas. Use o exercício 9.37 como
base.
Exercício 13.29: ? ? ? ?
O programa da listagem 13.4 considera que existem 19 registros no arquivo de livros, mas raramente este
será o caso. O programa também é limitado: ele lê todos os dados em uma única instância da classe
LivroLivraria, o que impossibilita processamentos mais elaborados. Para melhorar a funcionalidade
do programa, considere que ele deve ler todas as instâncias da classe LivroLivraria em um array de
instâncias, podendo processar todos os livros simultaneamente. Para alocar memória para o array de
instâncias, é necessário saber quantos livros existem em um arquivo, bastando para isto ler o arquivo uma
vez para determinar o número de linhas que ele contém. Modifique o programa para que ele use um array
de instâncias da classe LivroLivraria. Dica: use também a listagem 13.1 como base.
Exercício 13.30: ? ? ? ?
Não é possível, com as classes vistas nesta seção, a abertura de arquivos para leitura e gravação simul-
tânea. Para incluir os dados de uma conta bancária em um arquivo já existente, este arquivo deverá ser
aberto como um arquivo de leitura, seu conteúdo copiado em outro arquivo (aberto para gravação) e os
novos dados entrados e gravados no arquivo de saída. Escreva um programa em Java que faça isto, usando
como argumentos passados pela linha de comando duas Strings, uma contendo o nome do arquivo origi-
nal e outra contendo o nome do arquivo a ser criado. Após a cópia dos dados velhos no novo arquivo, este
deve ser completado com algumas instâncias da classe ContaBancaria. Dica: use a listagem 13.8 como
base.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
176
Exercício 13.31: ? ? ? ? ?
Escreva um intepretador (programa que lê comandos de uma linguagem e os executa um a um) para a
linguagem PaleoBasic. Esta linguagem bastante simples serve para efetuarmos operações com variáveis
e imprimirmos os resultados no terminal. PaleoBasic reconhece 26 variáveis, chamadas a, b, etc., sendo
que todas são do tipo double. PaleoBasic reconhece os seguintes comandos:
• var = valor: coloca o valor valor na variável var. valor pode ser uma constante, uma outra
variável, ou uma expressão matemática simples. PaleoBasic somente conhece somas, subtrações,
multiplicações e divisões simples (com dois valores).
• print var: imprime na tela o valor da variavel var.
Cada comando em PaleoBasic é escrito em uma linha, e o interpretador deve ler estas linhas de um
arquivo. Para exemplificar, aqui está um exemplo de programa correto em PaleoBasic:
a = 12
b = 13
c = a + b
print c
Outro exemplo correto é mostrado abaixo. Este exemplo calcula o valor de delta para a solução de uma
equação do segundo grau:
a = -8
b = 7
c = -4
x = b*b
y = 4*a
z = y*c
d = x-z
print d
Um programa em PaleoBasic pode conter erros que devem ser identificados pelo interpretador. O progra-
ma abaixo contém erros de sintaxe:
a - 2
b = r = e
print
Dicas: em algumas ocasiões os espaços em uma String lida de um arquivo devem ser ignoradas. Para
verificar se a linha é um comando de atribuição, verifique se o segundo caracter da linha (após a remoção
de espaços) é um sinal ’=’. As variáveis podem ser representadas por um array de doubles.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
177
Capítulo 14
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
178
Apêndice A
Na linha 10 da listagem A.1, somente a parte inteira do resultado foi considerada, já que o tipo nativo
byte não pode representar casas decimais. A operação mostrada na linha 9 é válida (não gera erros de
compilação nem de execução) porque o resultado estará na faixa de valores válidos para o tipo nativo byte
e os valores da operação são constantes.
Podemos também notar que é possível declarar as variáveis sem inicializá-las imediatamente (linha 5) e
declará-las e inicializá-las ao mesmo tempo (linhas 8 a 10).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
179
Alguns exemplos de uso incorreto do tipo nativo byte são mostrados no programa na listagem A.2, com
comentários indicando o erro.
Na listagem A.2, vários erros ocorreram porque tentamos colocar valores incompatíveis com a capacidade
das variáveis tipo byte. Variáveis declaradas como sendo do tipo byte não podem receber valores do tipo
boolean, de qualquer tipo inteiro diferente de byte ou de qualquer tipo de ponto flutuante.
É possível converter forçadamente valores de outros tipos para o tipo byte: esta operação é conhecida
como cast, e geralmente envolve alguma perda de precisão. O programa na listagem A.3 mostra exemplos
de conversão que funcionarão para as linhas 6, 7 e 8, mas não para a linha 9, que ainda gerará um erro de
compilação:
No exemplo de conversão da linha 6 da listagem A.3, o valor inteiro 123456 foi convertido para 64. Vamos
examinar esta conversão com mais detalhes: um número inteiro é representado por 32 bits (veja seção A.1.4
abaixo), mas uma variável do tipo byte somente usa 8 bits, então os 24 bits superiores são eliminados (ze-
rados), como mostrado abaixo:
Para a conversão mostrada na linha 7 da listagem A.3, Java converterá primeiro o valor de ponto flutuante
para um valor inteiro de 32 bits, e eliminará os 24 bits superiores. Detalhes da conversão são mostrados
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
180
abaixo:
No exemplo de conversão acima, o primeiro bit do valor do tipo byte determina o sinal do valor, através
da subtração de 128 do valor expresso pelos sete bits restantes.
O tipo char é equivalente à um inteiro de 16 bits sem sinal, capaz de representar valores na faixa 0 a 65535,
que podem até mesmo ser usados para operações simples. O programa na listagem A.4 mostra alguns exem-
plos válidos de uso do tipo char, onde vemos caracteres especificados diretamente entre aspas simples (”)
ou por valores numéricos inteiros:
Alguns exemplos de uso incorreto para variáveis do tipo char são mostrados no programa na listagem A.5.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
181
5 {
6 char c1,c2,c3; // declaração das variáveis
7 c1 = 65536; // ERRO: valor inteiro diferente de char
8 c2 = -1; // ERRO: valor inteiro com sinal, diferente de char
9 c3 = 3.1416; // ERRO: valor de ponto flutuante
10 char c4 = false; // ERRO: constante do tipo boolean
11 char c5 = ’’; // ERRO: caracter vazio não pode ser usado
12 char c6 = ’AB’; // ERRO: mais de um caracter entre aspas
13 char c7 = ’A’+’$’; // Não é um erro, mas resultado é ’e’ (65+36)
14 char c8 = "A"; // ERRO: caracter deve ser especificado com aspas simples
15 }
16 }
Alguns dos erros do programa na listagem A.5 acima podem ser evitados através do cast dos valores, mas
mesmo assim perda de precisão pode ocorrer. Se o cast for feito nas linhas 6, 7 e 8 do trecho de progra-
ma acima, as variáveis c1, c2 e c3 valerão respectivamente 0, 65535 e 3. O cast de um valor booleano
para a variável c4 não poderá ser feito, assim como o cast de uma String para um único caracter na linha 13.
As linhas 10 e 11 da listagem A.5 apresentam erros de caracteres inválidos (constantes com menos ou mais
de um único caracter). A variável c7, embora não apresente erros de compilação ou execução, terá os
valores somados ao invés de concatenados.
É importante lembrar que variáveis do tipo básico char podem representar somente um caracter por vez.
Para representação de vários caracteres (cadeia de caracteres ou Strings), veja a seção A.2.1.
Alguns exemplos de uso incorreto de variáveis do tipo short são mostrados no programa na listagem A.7.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
182
Todos os erros acima serão indicados pelo compilador. Os erros das linhas 6, 7 e 10 poderão ser resolvidos
através do cast, mas com perda de precisão ou informação.
Alguns exemplos de uso incorreto de variáveis do tipo int são mostrados no programa na listagem A.9.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
183
Um erro particularmente grave é mostrado na linha 6: o compilador não indicará que a conta será calculada
incorretamente. Este erro é chamado de erro de overflow. Todos os outros erros serão indicados pelo
compilador, e o da linha 8 pode ser resolvido através do cast, mas com perda de precisão ou informação.
As linhas 6 e 7 da listagem A.10 mostram uma surpresa: mesmo com o cast feito na linha 7 o valor cor-
reto (9999999999) não foi aceito pela variável. A razão é que o valor foi considerado constante inteiro
(tipo int) antes de ser convertido para o tipo long através do cast, que não teve efeito. Para especificar
valores do tipo long como constantes em um programa, devemos anexar aos valores a letra L como mos-
trado na linha 8 da listagem A.10. Na linha 9, como o primeiro valor é do tipo long, o cast não é necessário.
Alguns exemplos de uso incorreto de variáveis do tipo long são mostrados no programa na listagem A.11.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
184
A maioria dos erros na listagem A.11 já foram vistos em exemplos de outros tipos de dados. O erro mais
crítico é o de overflow, que ocorre na linha 9. Vale a pena lembrar que este tipo de erro não é registrado
em tempo de compilação ou de execução, e pode ser difícil de ser identificado em um programa.
Outro erro interessante é mostrado na linha 13: o valor 3000000000 é considerado pelo compilador como
sendo do tipo int antes da conversão pelo cast, gerando um erro de compilação. A solução neste caso é
escrever o valor com a letra “L” anexada, como 3000000000L, para garantir que o compilador aceitará o
valor como long.
Para usar constantes do tipo float em programas, devemos colocar o sufixo ’F’ (maiúsculo ou minúsculo)
após as constantes, como mostrado na linhas 7, 10, 11 e 14 da listagem A.12. Os valores representados por
um float não são exatos, como pode ser visto nos comentários das linhas 6 e 7.
Algumas regras relativas às constantes também são válidas para o tipo float: constantes numéricas sem o
sufixo ’F’ nem pontos flutuantes são interpretadas como sendo do tipo int e tratadas como tal: a divisão
2 A notação xey onde x e y são valores numéricos é usada para representar alguns valores de ponto flutuante: xey corresponde
a x ⇥ 10y .
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
185
mostrada na linha 9 é considerada uma divisão de inteiros, e seu resultado é zero. Nas linhas 10 e 11, como
uma das constantes na divisão é de ponto flutuante (por causa do sufixo ’F’), o resultado é considerado
como ponto flutuante do tipo float.
Alguns exemplos de uso incorreto de variáveis do tipo float ou usos que podem dar resultados inespera-
dos são mostrados no programa na listagem A.13.
No programa na listagem A.13, temos mais problemas de arredondamento devidos à capacidade finita do
tipo float de representar dados: nas linhas 6 e 7 vemos o arredondamento dos valores, porque o tipo
float é incapaz de armazenar grandes valores em detalhes. Vale a pena notar que estes “detalhes” podem
fazer muita diferença - imagine usar um float para armazenar valores monetários e descobrir que muito
dinheiro está sumindo ou aparecendo do valor por causa de erros de arredondamento !
Outro erro de arredondamento ocorre na linha 8: a soma das frações mostradas deveria ser exatamente
zero, mas por causa do arredondamento das frações, o resultado é um valor muito pequeno mas diferente
de zero. Este erro pode causar problemas maiores em um programa caso façamos comparações entre pon-
tos flutuantes: se uma comparação entre (1f/7)+(1f/7)+(1f/7) e (3f/7) fosse feita, o resultado ia ser
false !
Nas linhas 9 e 10 da listagem A.13 vemos que o tipo float sofre das mesmas restrições dos outros tipos
de dados em relação aos tipos de variáveis que podem ser convertidas através do cast para float.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
186
No programa na listagem A.14 vemos que o tipo double pode representar valores com maior precisão do
que o tipo float, apesar de em alguns casos ocorrer o arredondamento, como nas linhas 7 e 8.
Constantes do tipo double devem ser escritas usando o sufixo ’D’ (maiúsculo ou minúsculo) ou um ponto
flutuante (.). O ponto flutuante pode ser usado mesmo em constantes sem casas decimais, como mostrado
nas linhas 10, 13 e 15. Constantes com valores muito grandes ou pequenos podem ser escritas com a nota-
ção xey ou diretamente, como mostrado nas linhas 15 e 16.
Alguns exemplos de uso incorreto de variáveis do tipo double ou usos que podem dar resultados inespe-
rados são mostrados no programa na listagem A.15.
No programa na listagem A.15 temos mais erros de arredondamento, nas linhas 6 e 7, e erros de tipos que
não podem ser convertidos, nas linhas 10 e 11.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
187
No programa na listagem A.16 vemos que podemos usar variáveis do tipo boolean para receber constantes
(linha 6) e resultados de expressões de comparação, que são booleanas por natureza (linhas 7 a 10). Para
operações com valores booleanos, usamos o sinal && para representar a operação booleana E, o sinal ||
para representar a operação booleana OU e o sinal ! para representar a operação booleana NÃO.
Alguns exemplos de uso incorreto de variáveis do tipo boolean são mostrados no programa na lista-
gem A.17.
No programa na listagem A.17, vemos que variáveis do tipo boolean não podem receber valores de tipos
inteiros ou de ponto flutuante, mesmo com cast (linhas 6 e 7). As constantes true e false devem ser
escritas com todas as letras minúsculas: variações não são reconhecidas (linha 8). O uso de constantes do
tipo char ou da classe String também não são aceitas, nem mesmo com o cast (linhas 9 a 11).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
188
Na linha 6 da listagem A.18, colocamos uma String vazia na instância s1 - Strings podem ter tamanhos
variados, diferente de variáveis do tipo char que devem ter sempre um único caracter. Similarmente, nas
linhas 7 e 8 usamos Strings que consistem de um e dois espaços, respectivamente. Vale a pena notar aqui
que as instâncias s1, s2 e s3 são diferentes, mesmo que aparentemente as Strings estejam “vazias”.
Na linha 9, a instância recebe um valor constante, e a linha 10 demonstra um dos conceitos mais impor-
tantes e usados da classe String: novas instâncias da classe podem ser criadas através da concatenação
de outras Strings, que é feita pelo operador +. A linha 11 mostra outro exemplo de concatenação de Strings.
A linha 12 do trecho de programa anterior mostra como caracteres especiais podem ser inseridos em
Strings, através do escape: se colocarmos uma barra (\), também conhecida como caracter de escape)
dentro de uma String, o caracter imediatamente após a barra será combinado com a barra dando um resul-
tado especial, no exemplo acima, a String contendo uma aspa. A tabela A.1 mostra algumas combinações
de caracteres e seus resultados.
Combinação Resultado
\" Insere uma aspa na String. Não podemos simplesmente inserir aspas
sem usar a barra porque as aspas são os próprios delimitadores das
Strings.
\n Insere uma quebra de linha na String, de forma que quando esta for
impressa no terminal ou em um arquivo de texto, os caracteres depois
de \n serão impressos em linhas subsequentes.
\t Insere uma tabulação na String. Esta tabulação será convertida em um
número adequado de espaços quando for a String for impressa.
\\ Insere a própria barra (\) na String.
Tabela A.1: Combinações especiais de caracteres e resultados em Strings
As regras de concatenação de Strings quando existem outros tipos de dados misturados não são muito óbvi-
as, e podem levar à erros de programação. Alguns exemplos de resultados de concatenação são mostrados
no programa na listagem A.19.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
189
No programa na listagem A.19, várias demonstrações de concatenação de Strings são feitas. Nas linhas 6
e 7, valores inteiros são concatenados com Strings, resultado em outras Strings. Na linha 8, a soma dos
valores 1 e 2 é feita antes da concatenação, e na linha 9 a soma não é feita, somente a concatenação. Na
linha 10, os parênteses forçam a soma antes da concatenação. As linhas restantes do trecho de programa
mostram como o resultado pode ser alterado dependendo dos termos da operação.
Em resumo, podemos considerar que a concatenação de valores de tipos misturados com Strings é feita da
esquerda para a direita, exceto quando existem parênteses, e levando sempre em conta a ordem de prece-
dência dos operadores (* e / antes de + e -, etc).
Alguns exemplos de uso incorreto de instâncias da classe String são mostrados no programa na lista-
gem A.20:
No programa na listagem A.20, vemos que não é possível simplesmente atribuir à instâncias da classe
String valores de outros tipos de dado, mesmo com cast (embora seja possível atribuirmos estes valores
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
190
através da concatenação de uma String vazia com o valor em questão). Vemos também que as regras de
escrita da linguagem exigem que uma String constante seja delimitada por duas aspas e não contenha ne-
nhuma aspa entre as duas, a não ser como uma sequência como mostrado na tabela A.1.
A classe String tem muitos métodos para processamento de caracteres nas Strings, que são descritos no
capítulo 9.
Existe, porém, uma desvantagem: valores representados por instâncias destas classes não podem ser usados
diretamente para operações. O uso normal destas classes envolve a criação de instâncias, uso dos métodos
das classes pelas instâncias e a conversão para tipos normais.
As classes para representação de valores nativos como instâncias tem constantes para representar os valores
mínimo e máximo possíveis para o tipo de dado correspondente assim como métodos para conversão de
Strings e tipos nativos para instâncias e vice-versa. Todas as classes mostradas a seguir (exceto as classes
Character e Boolean) tem os seguintes métodos de conversão:
• byteValue(): retorna o valor encapsulado pelas classes em um valor nativo do tipo byte. Se a classe
representa um tipo de dado diferente de byte (short, int, long, float, double), truncamento através do
cast pode ocorrer.
• shortValue(): retorna o valor encapsulado pelas classes em um valor nativo do tipo short. Se
a classe representa um tipo de dado com mais precisão do que um short (int, long, float, double),
truncamento através do cast pode ocorrer.
• intValue(): retorna o valor encapsulado pelas classes em um valor nativo do tipo int. Se a classe
representa um tipo de dado com mais precisão do que um int (long, float, double), truncamento
através do cast pode ocorrer.
• longValue(): retorna o valor encapsulado pelas classes em um valor nativo do tipo long. Se a classe
representa um tipo de dado com mais precisão do que um long (float ou double), truncamento através
do cast pode ocorrer.
• floatValue(): retorna o valor encapsulado pelas classes em um valor nativo do tipo float. Se a
classe representa um tipo de dado com mais precisão do que um long (tipo double), perda de precisão
através do cast pode ocorrer.
• doubleValue(): retorna o valor encapsulado pelas classes em um valor nativo do tipo double.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
191
Podemos ver nas linhas 7 e 8 que instâncias da classe Byte podem ser inicializadas com valores do tipo
byte e Strings que contenham valores compatíveis. Nas linhas 9 e 10 vemos exemplos de conversão da
instância da classe para tipos nativos. Nas linhas 11 e 12 vemos exemplos de inicialização das classes (sem
ser via construtores) usando Strings e bases numéricas diferentes de 10, e as linhas 13 a 15 mostram os
valores limites para o tipo byte (representados como constantes da classe Byte).
Alguns exemplos de uso incorreto da classe são mostrados no programa na listagem A.22.
Na linha 7 da listagem A.22 temos um erro porque o valor 200 é considerado implicitamente como um valor
do tipo inteiro, e não existe um construtor correspondente na classe Byte - é necessário o cast do valor 200
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
192
para o tipo byte. Nas linhas 8 e 9 temos erros de conversão (em tempo de execução) pois as Strings não
contém valores válidos para a conversão para bytes. Na linha 10, temos outro erro de conversão: não é
possível passarmos valores do tipo double para o construtor da classe Byte. Nas linhas 11 e 13 temos erros
de conversão pois os valores, depois de convertidos uasndo as bases especificadas, estarão fora da faixa de
valores válidos para bytes, enquanto que na linha 12 temos um valor em String incompatível com a base
de conversão especificada.
Alguns exemplos de uso de instâncias da classe Character são mostrados no programa na listagem A.23.
Nas linhas 7 a 10 temos exemplos de uso do construtor da classe Character, sendo que na linha 7 usamos
o valor numérico do caracter para inicialização. O cast é necessário para garantir que o valor 65 não será
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
193
considerado como sendo do tipo inteiro. As linhas 11 a 13 mostram usos do método estático isDigit()
que recebe um valor do tipo char e retorna um booleano. Para línguas ocidentais, somente os valores 0, 1,
2, · · · 9 são considerados dígitos.
As linhas 14 a 17 mostram usos do método isLetter() que retornará true para os caracteres que corres-
pondam a letras nos diversos alfabetos suportados. O método isLetterOrDigit() (mostrado nas linhas 18
a 20) retorna true se o caracter for dígito ou letra.
A classe Character fornece métodos para verificar se o caracter é minúsculo isLowerCase()) ou maiús-
culo (isUpperCase()), como mostrado nas linhas 21 a 26. Similarmente, caracteres podem ser testados
para verificar se são espaços em branco pelo método isWhitespace(), como mostrado nas linhas 27 a 30.
Os valores mínimo e máximo para dados do tipo char podem ser obtidos usando as constantes definidas na
classe Character, como mostrado nas linhas 31 a 33. Os valores foram modificados através do cast para
tipos inteiros para impressão.
A alguns exemplos de uso incorreto da classe são mostrados no programa na listagem A.24.
Nas linhas 7 a 10 da listagem A.24 temos exemplos de argumentos inválidos passados ao construtor da
classe Character: um valor inteiro (linha 7), uma String (linha 8), um caracter vazio (linha 9) e um valor
do tipo double (linha 10). O construtor mostrado na linha 11 não terá erros de compilação nem execução,
e a instância c5 representará o caracter cujo código Unicode é 65516.
Alguns exemplos de uso de instâncias da classe Short são mostrados no programa na listagem A.25.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
194
3 {
4 public static void main(String argumentos[])
5 {
6 Short s1,s2; // declaração das instâncias
7 s1 = new Short((short)9999); // s1 representará o short 9999
8 s2 = new Short("-1024"); // s2 representará o short -1024 - conversão será automática
9 int i = s1.shortValue()+s2.shortValue(); // i será a soma dos valores de s1 e s2
10 long l = s1.longValue()*s2.longValue(); // l será a multiplicação dos valores de s1 e s2
11 Short s3 = Short.valueOf("1000",16); // s3 representará 4096
12 Short s4 = Short.valueOf("zz",36); // podemos usar qualquer base entre 2 e 36 !
13 System.out.println("Faixa de valores do short:"+ // impressão dos valores-limite
14 Short.MIN_VALUE+" a "+
15 Short.MAX_VALUE);
16 }
17 } // fim da classe DemoShort
As linhas 7 e 8 da listagem A.25 mostram usos dos construtores da classe Short, que aceitam respecti-
vamente valores do tipo short e Strings contendo valores compatíveis. As linhas 9 e 10 mostram como
podemos recuperar um valor armazenado em uma instância da classe Short como valores dos tipos short
e long, respectivamente.
As linhas 11 e 12 mostram como podemos converter valores contidos em Strings para instâncias da clas-
se Short, usando bases numéricas diferentes. É possível o uso de qualquer base numérica entre 2 e 36
(inclusive), como mostrado nos exemplos. A base 36 usa os números 0 a 9 e os caracteres A a Z (maiúscu-
los ou minúsculos). Nas linhas 13 a 15 os valores mínimo e máximo para dados do tipo short são impressos.
Alguns exemplos de uso incorreto da classe são mostrados no programa na listagem A.26.
Nas linhas 7 e 10 da listagem A.26 vemos chamadas ao construtor da classe Short com valores de tipos
não válidos (não existem construtores para os tipos int e double). O valor passado na String da linha 8
não pode ser transformado em valor do tipo short. A String mostrada na linha 9 contém espaços entre os
caracteres numéricos, e não poderá ser convertida para um dado do tipo short, causando erro de execução.
A conversão mostrada na linha 11 pode ser feita, mas como o resultado não pode ser armazenado em
uma variável do tipo short, um erro de execução ocorrerá. Finalmente, a conversão mostrada na linha 12
causará erro de execução porque a base somente reconhecerá caracteres ’0’ e ’1’, e outros caracteres
estão presentes na String.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
195
Além do método polimórfico valueOf que permite a criação de uma instância da classe Integer através
de uma String contendo um valor numérico e uma base entre 2 e 36, a classe Integer possui os métodos
estáticos toBinaryString(), toOctalString() e toHexString() que permitem a conversão do valor
armazenado na classe para as bases binária, octal e hexadecimal, respectivamente.
Alguns exemplos de uso de instâncias da classe Integer são mostrados no programa na listagem A.27.
Nas linhas 7 e 8 da listagem A.27 vemos a criação de duas instâncias da classe Integer, usando um valor
inteiro e uma String contendo os caracteres que representam um valor inteiro. Nas linhas 9 e 10 vemos a
conversão dos valores contidos em instâncias da classe Integer em inteiros e floats, respectivamente. Nas
linhas 11 e 12 temos a conversão de Strings em instâncias usando duas bases diferentes.
Nas linhas 13 a 15 temos a conversão dos valores passados para os métodos estáticos toBinaryString(),
toOctalString() e toHexString() para Strings contendo as representações binária, octal e hexadeci-
mal, respectivamente. Nas linhas 16 e 17 temos a conversão dos valores armazenados nas instâncias para
tipos de dados com menos precisão numérica: a conversão é feita sem mensagens de erro, mas os valores
são truncados com perda de precisão similar ao cast. As linhas 18 a 20 imprimem os valores mínimo e
máximo representáveis pelo tipo int.
Alguns exemplos de uso incorreto da classe são mostrados no programa na listagem A.28.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
196
Na linha 7 da listagem A.28 vemos um erro de compilação causado pelo valor passado ao construtor, que
é inválido para um tipo inteiro (fora da faixa de valores representáveis). Na linha 8, o mesmo erro ocorrerá
mas em tempo de execução, pois o valor contido na String também está fora da faixa de valores represen-
táveis por um inteiro. A linha 9 causará um erro de execução pois existem caracteres que não permitem a
transformação da String em um inteiro e a linha 10 causará um erro de compilação pois não existe constru-
tor que aceita valor de ponto flutuante para a classe Integer.
As linhas 11 e 12 causarão erros de execução pois os valores representados na String estão fora da faixa de
valores representáveis e usam caracteres inválidos para a base usada, respectivamente.
Alguns exemplos de uso de instâncias da classe Long são mostrados no programa na listagem A.29.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
197
Nas linhas 7 e 8 da listagem A.29 temos a criação de duas instâncias da classe Long usando um valor inteiro
e uma String como argumentos para os construtores. Embora não exista um construtor para a classe que
aceite um valor inteiro, o construtor aceita um valor do tipo long pode receber valores do tipo int como
argumentos.
Nas linhas 9 e 10 vemos a conversão dos valores contidos nas instâncias para os tipos float e double, res-
pectivamente. Na linha 11 vemos a conversão de um valor na base 16 para uma instância da classe Long.
Na linha 12 temos a conversão de um valor long para short, com a perda de precisão esperada deste tipo de
operação. Finalmente, nas linhas 13 a 15 vemos a impressão dos valores mínimo e máximo para o tipo long.
Alguns exemplos de uso incorreto da classe são mostrados no programa na listagem A.30.
Na linha 7 da listagem A.30 temos um erro de compilação pois não existe construtor para a classe Long
que aceite valores de ponto flutuante. Na linha 8 o erro será de execução, o valor é muito grande para ser
armazenado na classe. Na linha 9, o erro será por causa do caracter ’L’ que não será reconhecido para
conversão para uma instância da classe Long. Na linha 10, o valor será novamente muito grande para ser
armazenado por um long, e na linha 11 existem caracteres que não serão aceitos para conversão por causa
da base passada como argumento.
Alguns exemplos de uso de instâncias da classe Float são mostrados no programa na listagem A.31.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
198
Nas linhas 7 e 8 da listagem A.31 temos a criação de duas instâncias da classe Float, uma com um valor
de ponto flutuante e outro com uma String que representa um valor de ponto flutuante. A classe tem cons-
trutores que aceitam valores dos tipos float e double. As linhas 9 e 10 mostram a conversão dos valores
das instâncias para os tipos float e double, e as linhas 12 e 13 mostram a conversão destes valores para
variáveis do tipo byte e int, respectivamente, com perda de precisão, da mesma maneira que ocorreria se
um cast fosse feito.
A linha 11 mostra outra maneira de inicialização de instâncias da classe Float através do método valueOf(),
que neste caso não aceita um argumento adicional especificando a base para conversão. Na String passada
vemos que a notação xey correspondente a x ⇤ 10y pode ser usada para conversão. As linhas 14 a 16 impri-
mem os valores mínimo e máximo para variáveis do tipo float.
Alguns exemplos de uso incorreto da classe são mostrados no programa na listagem A.32.
Na linha 7 da listagem A.32 vemos que não é possível inicializarmos uma instância da classe Float com
um valor booleano. Na linha 8 teremos um erro de execução uma vez que a String não contém um valor
válido para conversão. Na linha 9, nenhum erro ocorrerá, mas uma vez que o valor é muito grande para ser
armazenado em um float, será considerado internamente como o valor infinito (Infinity).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
199
Alguns exemplos de uso de instâncias da classe Double são mostrados no programa na listagem A.33.
Na linhas 7 e 8 da listagem A.33 temos a inicialização de duas instâncias da classe Double, uma com
um valor do tipo double e outra com uma String. Nas linhas 9 e 10 temos a recuperação dos valores das
instâncias para valores do tipo double. Na linha 11 temos a criação de uma instância através do método
valueOf, que somente trabalha com a base 10, e nas linhas 12 e 13 temos a conversão para outros tipos
com perda de precisão - no caso da variável f na linha 12 o valor do tipo float receberá o valor infinito. As
linhas 14 a 16 imprimirão os valores mínimo e máximo que podem ser representados por valores do tipo
double.
A alguns exemplos de uso incorreto da classe são mostrados no programa na listagem A.34.
Na linha 7 da listagem A.34 vemos que não é possível inicializarmos uma instância da classe Double com
um valor booleano. Na linha 8 teremos um erro de execução uma vez que a String não contém um valor
válido para conversão. Na linha 9, nenhum erro ocorrerá, mas uma vez que o valor é muito grande para ser
armazenado em um double, será considerado internamente como o valor infinito (Infinity).
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
200
Alguns exemplos de uso de instâncias da classe Boolean são mostrados no programa na listagem A.35.
Nas linhas 7 a 9 da listagem A.35 temos exemplos dos construtores da classe Boolean, recebendo um
valor do tipo boolean e duas Strings. Nos dois primeiros exemplos, o valor encapsulado será igual a true,
enquanto que no terceiro será igual a false pois a String é diferente de “true”. Na linha 10, convertemos
o valor contido numa instância da classe para uma variável do tipo booleano.
Alguns exemplos de uso incorreto de instâncias da classe são mostrados no programa na listagem A.36.
Nas linhas 7 e 8 da listagem A.36 temos duas chamadas incorretas ao construtor da classe Boolean, pas-
sando respectivamente um valor inteiro e nenhum valor ao construtor. Na linha 10 tentamos recuperar o
valor de uma instância da classe Boolean como um valor do tipo int, o que não é possível, causando um
erro de compilação.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
201
Apêndice B
A Classe Keyboard
Vale a pena notar que em aplicações reais, a entrada de dados via um terminal é cada vez mais rara - interfa-
ces gráficas permitem que dados sejam entrados via teclado, de forma mais elegante, como mostrado neste
livro. A classe Keyboard visa unicamente facilitar o uso da interação via teclado nos primeiros programas
em Java, para tornar estes programas mais flexíveis e interessantes.
A classe Keyboard foi adaptada do livro An Introduction to Computer Science Using Java, de Samuel N.
Kamin, M. Dennis Mickunas e Edward M. Reingold [1]. A versão apresentada neste livro foi digitada por
diligentes alunos da disciplina Programação Orientada a Objetos I (turma de 1999) e anotada depois para
mais clareza.
Para que os programas desenvolvidos possam usar a classe, é necessário que esta seja copiada para o di-
retório onde os programas estão sendo criados. Cópias da classe Keyboard (compilada e código-fonte)
podem ser obtidas no mesmo site que a última versão deste documento (veja seção 1.1).
FCC/UNIVAP Usuários de computadores que rodam Linux nos laboratórios da FCC podem copiar
a classe Keyboard para suas contas com o comando cp ˜POO/Keyboard.class . (note o ponto no
final do comando), sendo que os usuários devem estar no diretório onde desenvolvem programas em
Java. Caso o usuário use mais de um diretório para desenvolvimento de programas em Java, ele/a deve
copiar o arquivo para todos os diretórios.
A lista dos métodos da classe Keyboard exemplos de uso serão mostrados nas seções seguintes.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
202
Ambos os métodos acima reconhecerão os valores true, t, yes, y, v, s, sim ou verdadeiro (independente
de estarem em caracteres maiúsculos, minúsculos ou misturados) como sendo iguais à true e os valores
false, f, no, n, não, nao ou falso (independente de estarem em caracteres maiúsculos, minúsculos ou
misturados) como sendo iguais à false.
O programa na listagem B.1 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.
Listagem B.1: Exemplo de uso da classe Keyboard para leitura de valores tipo boolean
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor booleano:");
6 boolean b1 = Keyboard.readBoolean(); // se não digitar nada, aceitará como true
7 if (b1) System.out.println("Verdadeiro !");
8 else System.out.println("Falso !");
9
10 System.out.print("Entre outro valor booleano:");
11 boolean b2 = Keyboard.readBoolean(false); // se não digitar nada, aceitará como false
12 if (b2) System.out.println("Verdadeiro !");
13 else System.out.println("Falso !");
14 } // fim do método main
15 } // fim da classe demoKeyboard
• byte Keyboard.readByte(): Este método lê um valor do teclado e retorna um valor do tipo byte
correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor 0 (tipo
byte).
• byte Keyboard.readByte(byte cdefault): Este método lê um valor do teclado e retorna um
valor byte correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor
passado pela variável cdefault (tipo byte).
O programa na listagem B.2 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
203
Listagem B.2: Exemplo de uso da classe Keyboard para leitura de valores tipo byte
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor do tipo byte:");
6 byte b1 = Keyboard.readByte(); // se não digitar nada, aceitará como zero
7 System.out.println("Valor digitado: "+b1);
8
9 System.out.print("Entre outro valor do tipo byte:");
10 byte b2 = Keyboard.readByte((byte)-1); // se não digitar nada, aceitará como -1
11 System.out.println("Valor digitado: "+b2);
12 } // fim do método main
13 } // fim da classe demoKeyboard
• char Keyboard.readChar(): Este método lê um valor do teclado e retorna um valor do tipo char
correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o caracter espaço ’
’ (tipo char).
• char Keyboard.readChar(char cdefault): Este método lê um valor do teclado e retorna um
valor char correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o caracter
passado pela variável cdefault (tipo char).
O programa na listagem B.3 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.
Listagem B.3: Exemplo de uso da classe Keyboard para leitura de valores tipo char
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor do tipo char:");
6 char c1 = Keyboard.readChar(); // se não digitar nada, aceitará como zero
7 System.out.println("Valor digitado: "+c1);
8
9 System.out.print("Entre outro valor do tipo char:");
10 char c2 = Keyboard.readChar(’*’); // se não digitar nada, aceitará como ’*’
11 System.out.println("Valor digitado: "+c2);
12 } // fim do método main
13 } // fim da classe demoKeyboard
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
204
O programa na listagem B.4 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.
Listagem B.4: Exemplo de uso da classe Keyboard para leitura de valores tipo short
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor do tipo short:");
6 short s1 = Keyboard.readShort(); // se não digitar nada, aceitará como zero
7 System.out.println("Valor digitado: "+s1);
8
9 System.out.print("Entre outro valor do tipo short:");
10 short s2 = Keyboard.readShort((short)123); // se não digitar nada, aceitará como 123
11 System.out.println("Valor digitado: "+s2);
12 } // fim do método main
13 } // fim da classe demoKeyboard
• int Keyboard.readInt(): Este método lê um valor do teclado e retorna um valor do tipo int
correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor 0 (tipo int).
• int Keyboard.readInt(int idefault): Este método lê um valor do teclado e retorna um valor
int correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor passado
pela variável idefault (tipo int).
O programa na listagem B.5 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.
Listagem B.5: Exemplo de uso da classe Keyboard para leitura de valores tipo int
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor do tipo int:");
6 int i1 = Keyboard.readInt(); // se não digitar nada, aceitará como zero
7 System.out.println("Valor digitado: "+i1);
8
9 System.out.print("Entre outro valor do tipo int:");
10 int i2 = Keyboard.readInt(123); // se não digitar nada, aceitará como 123
11 System.out.println("Valor digitado: "+i2);
12 } // fim do método main
13 } // fim da classe demoKeyboard
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
205
• long Keyboard.readLong(): Este método lê um valor do teclado e retorna um valor do tipo long
correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor 0 (tipo
long).
• long Keyboard.readLong(long ldefault): Este método lê um valor do teclado e retorna um
valor long correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor
passado pela variável idefault (tipo long).
O programa na listagem B.6 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.
Listagem B.6: Exemplo de uso da classe Keyboard para leitura de valores tipo long
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor do tipo long:");
6 long l1 = Keyboard.readLong(); // se não digitar nada, aceitará como zero
7 System.out.println("Valor digitado: "+l1);
8
9 System.out.print("Entre outro valor do tipo long:");
10 long l2 = Keyboard.readLong(-100); // se não digitar nada, aceitará como -100
11 System.out.println("Valor digitado: "+l2);
12 } // fim do método main
13 } // fim da classe demoKeyboard
O programa na listagem B.7 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
206
Listagem B.7: Exemplo de uso da classe Keyboard para leitura de valores tipo float
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor do tipo float:");
6 float f1 = Keyboard.readFloat(); // se não digitar nada, aceitará como zero
7 System.out.println("Valor digitado: "+f1);
8
9 System.out.print("Entre outro valor do tipo float:");
10 float f2 = Keyboard.readFloat((float)3.1415); // se não digitar nada,
11 // aceitará como 3.1415
12 System.out.println("Valor digitado: "+f2);
13 } // fim do método main
14 } // fim da classe demoKeyboard
Listagem B.8: Exemplo de uso da classe Keyboard para leitura de valores tipo double
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor do tipo double:");
6 double d1 = Keyboard.readDouble(); // se não digitar nada, aceitará como zero
7 System.out.println("Valor digitado: "+d1);
8
9 System.out.print("Entre outro valor do tipo double:");
10 double d2 = Keyboard.readDouble(3.1415926535); // se não digitar nada,
11 // aceitará como 3.1415926535
12 System.out.println("Valor digitado: "+d2);
13 } // fim do método main
14 } // fim da classe demoKeyboard
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
207
Listagem B.9: Exemplo de uso da classe Keyboard para leitura de instâncias da classe String
1 class demoKeyboard
2 {
3 public static void main(String args[])
4 {
5 System.out.print("Entre um valor do tipo String:");
6 String s1 = Keyboard.readString(); // se não digitar nada, aceitará como zero
7 System.out.println("Valor digitado: "+s1);
8
9 System.out.print("Entre outro valor do tipo String:");
10 String s2 = Keyboard.readString("default"); // se não digitar nada, aceitará
11 // como "default"
12 System.out.println("Valor digitado: "+s2);
13 } // fim do método main
14 } // fim da classe demoKeyboard
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
208
27 System.out.print("Entre um char:");
28 c = Keyboard.readChar(); // lê um valor do tipo char do teclado
29 System.out.println("Os valores digitados são:"); // imprime resultados
30 System.out.println("O inteiro "+i);
31 System.out.println("O double "+d);
32 System.out.println("O boolean "+b);
33 System.out.println("A String "+s);
34 System.out.println("O char "+c);
35 } // fim do método main
36 } // fim da classe demoteclado
O segundo exemplo mostra como podemos usar os métodos da classe Keyboard de dentro de outra classe.
Especificamente, uma versão simplificada da classe Aluno será reescrita para que alguns dos seus métodos
usem métodos da classe Keyboard para leitura dos dados das instâncias da classe Aluno.
A listagem B.11 mostra a classe Aluno usando métodos da classe Keyboard dentro de seus próprios méto-
dos, e o programa na listagem B.12 mostra usos da nova classe Aluno.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
209
Listagem B.12: Exemplo de uso da classe Aluno com instâncias da classe Keyboard
1 class TesteAluno // uma classe que testa a classe Aluno
2 {
3 public static void main(String args[])
4 {
5 Aluno a1 = new Aluno(); // cria uma instância da classe Aluno
6 a1.lêDados(); // lê os dados deste aluno do teclado
7 Aluno a2 = new Aluno(); // cria outra instância da classe Aluno
8 a2.lêDados(); // lê os dados deste aluno do teclado
9 System.out.println("O aluno mais velho é:"); // imprime mensagem
10 if (a1.retornaIdade() > a2.retornaIdade()) // se a1 for mais velho que a2
11 a1.imprimeDados(); // imprime a1
12 else // senão
13 a2.imprimeDados(); // imprime a2
14 } // fim do método main
15 } // fim da classe testealunokey
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
210
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
211
59 else if
(s.trim().equalsIgnoreCase("f")) b = false; // falso se igual à f
60 else if
(s.trim().equalsIgnoreCase("yes")) b = true; // verdadeiro se igual à yes
61 else if
(s.trim().equalsIgnoreCase("no")) b = false; // falso se igual à no
62 else if
(s.trim().equalsIgnoreCase("y")) b = true; // verdadeiro se igual à yes
63 else if
(s.trim().equalsIgnoreCase("n")) b = false; // falso se igual à no
64 else if
(s.trim().equalsIgnoreCase("v")) b = true; // verdadeiro se igual à v
65 else if
(s.trim().equalsIgnoreCase("f")) b = false; // falso se igual à f
66 else if
(s.trim().equalsIgnoreCase("s")) b = true; // verdadeiro se igual à s
67 else if
(s.trim().equalsIgnoreCase("sim")) b = true; // verdadeiro se igual à sim
68 else if
(s.trim().equalsIgnoreCase("nao")) b = false; // falso se igual à nao
69 else if
(s.trim().equalsIgnoreCase("não")) b = false; // falso se igual à não
70 else if
(s.trim().equalsIgnoreCase("verdadeiro")) b = true; // verdadeiro se
71 // igual à verdadeiro
72 else if (s.trim().equalsIgnoreCase("falso")) b = false; // falso se igual à falso
73 return b; // retorna o valor de b
74 } // fim do método readBoolean
75
76 ///////////////////////////////////////////////////////////////////////////////
77 // MÉTODOS PARA LER BYTES
78 ///////////////////////////////////////////////////////////////////////////////
79
80 /* Lê um valor do tipo byte do teclado, retorna o valor default se nada é
81 digitado ou sai do programa se existe erro de leitura. Este método considera
82 que o default é retornar zero. */
83 public static byte readByte()
84 {
85 return readByte((byte)0); // chama o método genérico abaixo
86 }
87
88 /* Lê um valor do tipo byte do teclado, retorna o valor default se nada é
89 digitado ou sai do programa se existe erro de leitura. */
90 public static byte readByte(byte bdefault)
91 {
92 String s=""; // a String a ser lida do teclado e convertida em um byte
93 byte b; // o valor byte a ser retornado, inicializado
94 if (iseof) return bdefault; // se estamos no fim do arquivo, retornamos o default
95 System.out.flush(); // limpa o que existir no buffer do arquivo
96 try // tenta..
97 {
98 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
99 System.out.flush(); // limpa o que existir no buffer do arquivo
100 }
101 catch (IOException e) // se não der certo,
102 {
103 System.exit(-1); // sai do programa.
104 }
105 if (s==null) // se a String lida for nula, ou vazia,
106 {
107 iseof=true; // avisa que este é o fim do "arquivo"
108 return bdefault; // e retorna o valor default
109 }
110 // senão avalia o que foi digitado:
111 try // tenta
112 {
113 b=new Byte(s.trim()).byteValue(); // converter a String para byte...
114 }
115 catch (NumberFormatException e) // se não conseguir,
116 {
117 b = bdefault; // usa o valor default
118 }
119 return b; // retorna o valor de b
120 } // fim do método readByte
121
122 ///////////////////////////////////////////////////////////////////////////////
123 // MÉTODOS PARA LER CHARS
124 ///////////////////////////////////////////////////////////////////////////////
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
212
125
126 /* Lê um valor do tipo char do teclado, retorna o valor default se nada é
127 digitado ou sai do programa se existe erro de leitura. Este método considera
128 que o default é retornar um espaço. */
129 public static char readChar()
130 {
131 return readChar(’ ’); // chama o método genérico abaixo
132 }
133
134 /* Lê um valor do tipo char do teclado, retorna o valor default se nada é
135 digitado ou sai do programa se existe erro de leitura. */
136 public static char readChar(char cdefault)
137 {
138 String s=""; // a String a ser lida do teclado e convertida em um único char
139 char c = cdefault; // o valor char a ser retornado, inicializado
140 if (iseof) return c; // se estamos no fim do arquivo, retornamos o default
141 System.out.flush(); // limpa o que existir no buffer do arquivo
142 try // tenta..
143 {
144 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
145 System.out.flush(); // limpa o que existir no buffer do arquivo
146 }
147 catch (IOException e) // se não der certo,
148 {
149 System.exit(-1); // sai do programa.
150 }
151 if (s==null) // se o char lido for nulo, ou vazio,
152 {
153 iseof=true; // avisa que este é o fim do "arquivo"
154 return c; // e retorna o valor default
155 }
156 if (s.length() > 0) // senão verifica o tamanho do que foi entrado,
157 return s.charAt(0); // retorna o primeiro caracter do que foi digitado
158 else // ou então
159 return cdefault; // retorna o default
160 } // fim do método readChar
161
162 ///////////////////////////////////////////////////////////////////////////////
163 // MÉTODOS PARA LER SHORTS
164 ///////////////////////////////////////////////////////////////////////////////
165
166 /* Lê um valor do tipo short do teclado, retorna o valor default se nada é
167 digitado ou sai do programa se existe erro de leitura. Este método considera
168 que o default é retornar zero. */
169 public static short readShort()
170 {
171 return readShort((short)0); // chama o método genérico abaixo
172 }
173
174 /* Lê um valor do tipo short do teclado, retorna o valor default se nada é
175 digitado ou sai do programa se existe erro de leitura. */
176 public static short readShort(short sdefault)
177 {
178 String s=""; // a String a ser lida do teclado e convertida em um short
179 short sh = sdefault; // o valor short a ser retornado, inicializado
180 if (iseof) return sh; // se estamos no fim do arquivo, retornamos o default
181 System.out.flush(); // limpa o que existir no buffer do arquivo
182 try // tenta..
183 {
184 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
185 System.out.flush(); // limpa o que existir no buffer do arquivo
186 }
187 catch (IOException e) // se não der certo,
188 {
189 System.exit(-1); // sai do programa.
190 }
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
213
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
214
257
258 /* Lê um valor do tipo long do teclado, retorna o valor default se nada é
259 digitado ou sai do programa se existe erro de leitura. Este método considera
260 que o default é retornar zero. */
261 public static long readLong()
262 {
263 return readLong(0); // chama o método genérico abaixo
264 }
265
266 /* Lê um valor do tipo long do teclado, retorna o valor default se nada é
267 digitado ou sai do programa se existe erro de leitura. */
268 public static long readLong(long ldefault)
269 {
270 String s=""; // a String a ser lida do teclado e convertida em um long
271 long l = ldefault; // o valor long a ser retornado, inicializado
272 if (iseof) return l; // se estamos no fim do arquivo, retornamos o default
273 System.out.flush(); // limpa o que existir no buffer do arquivo
274 try // tenta..
275 {
276 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
277 System.out.flush(); // limpa o que existir no buffer do arquivo
278 }
279 catch (IOException e) // se não der certo,
280 {
281 System.exit(-1); // sai do programa.
282 }
283 if (s==null) // se a String lida for nula, ou vazia,
284 {
285 iseof=true; // avisa que este é o fim do "arquivo"
286 return l; // e retorna o valor default
287 }
288 // senão avalia o que foi digitado:
289 try // tenta
290 {
291 l=new Long(s.trim()).longValue(); // converter a String para long...
292 }
293 catch (NumberFormatException e) // se não conseguir,
294 {
295 l = ldefault; // usa o valor default
296 }
297 return l; // retorna o valor de l
298 } // fim do método readLong
299
300 ///////////////////////////////////////////////////////////////////////////////
301 // MÉTODOS PARA LER FLOATS
302 ///////////////////////////////////////////////////////////////////////////////
303
304 /* Lê um valor do tipo float do teclado, retorna o valor default se nada é
305 digitado ou sai do programa se existe erro de leitura. Este método considera
306 que o default é retornar zero. */
307 public static float readFloat()
308 {
309 return readFloat(0); // chama o método genérico abaixo
310 }
311
312 /* Lê um valor do tipo float do teclado, retorna o valor default se nada é
313 digitado ou sai do programa se existe erro de leitura. */
314 public static float readFloat(float fdefault)
315 {
316 String s=""; // a String a ser lida do teclado e convertida em um float
317 float f = fdefault; // o valor float a ser retornado, inicializado
318 if (iseof) return f; // se estamos no fim do arquivo, retornamos o default
319 System.out.flush(); // limpa o que existir no buffer do arquivo
320 try // tenta..
321 {
322 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
215
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
216
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
217
Apêndice C
ATENÇÃO: Este capítulo ainda está sendo escrito. Evite imprimi-lo, pois novas versões devem ser
liberadas em breve.
Interpretador Java
Bytecode (objeto)
(JVM, máquina virtual Java)
Navegador
Transporte via
Internet Interpretador Java
(JVM, máquina virtual Java)
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
218
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
219
Quando uma classe é declarada pública com a palavra-chave public ela deve ser colocada em um arquivo
com o mesmo nome da classe. Por exemplo, uma classe Aluno declarada como public class Aluno
deve ser escrita em um arquivo Aluno.java.
Quando uma classe depende de outra (por exemplo, a classe Turma contém uma instância da classe
Professor, significando que para compilar a classe Turma precisamos compilar a classe Professor antes),
o compilador tentará compilar todas as classes que são pré-requisitos para a classe que estamos compilan-
do. Seguindo o exemplo acima, se compilarmos a classe Turma o compilador, se necessário, compilará
automaticamente a classe Professor. Note que o reverso não é verdade: se compilarmos somente a classe
Professor teremos que compilar manualmente a classe Turma se esta não tiver sido compilada.
Alguns exemplos de nomes de arquivos e classes que serão criadas são mostrados na tabela C.1:
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
220
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
221
Apêndice D
ATENÇÃO: Este capítulo ainda está sendo escrito. Evite imprimi-lo, pois novas versões devem ser
liberadas em breve.
D.1 Introdução
D.2 A estrutura de arquivos e diretórios do Linux
usuário, usuário em rede, superusuário, permissões
REFAZER COMO FIGURA ?
/ /home /home/shinosuke /home/shinosuke/java /home/shinosuke/java/prog1.java /home/shinosuk
/home/shinosuke/c/prog1.c /home/shinosuke/docs /home/shinosuke/docs/carta.txt /home/shinosu
/home/sazae /home/sazae/java /home/sazae/java/prog1.java /bin /usr /tmp
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
222
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
223
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
224
Comando Efeito
ctrl+x ctrl+s Grava o buffer sendo editado.
ctrl+x ctrl+c Sai do emacs, perguntando se deve salvar buffers modifica-
dos.
ctrl+x ctrl+f Pede nome de novo arquivo para edição. O nome deve ser
digitado na barra de texto inferior do emacs.
ctrl+x ctrl+w Grava o buffer com novo nome (que deverá ser digitado na
barra de texto inferior do emacs).
ctrl+x k Elimina o buffer sendo editado do emacs (pede confirmação
para eliminação de buffers modificados).
ctrl+d Apaga o caracter sob o cursor.
ctrl+k Apaga a linha a partir do caracter sob o cursor, copiando
para a memória.
ctrl+y Copia o conteúdo da memória para a posição do cursor. Os
comandos ctrl+k e ctrl+y, usados em conjunto, podem
servir para duplicar trechos do programa.
ctrl+e Move o cursor para o final da linha.
ctrl+a Move o cursor para o início da linha.
esc+x goto-line Pede um número de linha e move o cursor para a linha es-
pecificada. O Xemacs aceita o comando abreviado esc+g,
com a mesma função.
ctrl+r Procura texto (desde o início do buffer até a posição do cur-
sor).
ctrl+s Procura texto (desde a posição do cursor até o fim do buffer)
esc+x replace-string Troca ocorrências de texto dentro do buffer (sem pedir con-
firmação).
esc+% Troca ocorrências de texto dentro do buffer (pedindo con-
firmação para cada troca).
ctrl+x 1 Muda o modo de tela para que somente um buffer seja exi-
bido de vez.
ctrl+x 2 Muda o modo de tela para que dois buffers sejam exibidos
de vez.
ctrl+x b Troca o buffer sendo mostrado.
Tabela D.1: Comandos básicos de teclado para o Emacs/Xemacs
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
225
Referências Bibliográficas
[1] Samuel N. Kamin, M. Dennis Mickunas, Edward M. Reingold, An Introduction to Computer Science
Using Java, WCB/McGraw-Hill, 1998.
[2] David Arnow, Gerald Weiss, Introduction to Programming Using Java - An Object-Oriented Appro-
ach, Addison-Wesley, 1998.
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
226
Índice Remissivo
Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)