0% acharam este documento útil (0 voto)
99 visualizações

Java Poo

O documento descreve um livro-texto sugerido para as disciplinas de Programação Orientada a Objetos I e II em cursos de Ciência da Computação e Engenharia da Computação. O livro introduz conceitos básicos de programação orientada a objetos em Java, incluindo classes, objetos, encapsulamento, herança e polimorfismo. Ele também fornece exemplos de código e exercícios para ajudar os alunos a aprender os princípios da programação orientada a objetos.

Enviado por

Igor Macedo
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
99 visualizações

Java Poo

O documento descreve um livro-texto sugerido para as disciplinas de Programação Orientada a Objetos I e II em cursos de Ciência da Computação e Engenharia da Computação. O livro introduz conceitos básicos de programação orientada a objetos em Java, incluindo classes, objetos, encapsulamento, herança e polimorfismo. Ele também fornece exemplos de código e exercícios para ajudar os alunos a aprender os princípios da programação orientada a objetos.

Enviado por

Igor Macedo
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 237

Material sugerido para as disciplinas

Programação Orientada a Objetos I e Programação Orientada a Objetos II


dos cursos de Ciência da Computação e Engenharia da Computação
da Faculdade de Ciência da Computação da Universidade do Vale do Paraíba

29 de maio de 2000
i

Sumário

1 Sobre este livro 1


1.1 O que é este livro ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Como usar este livro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 Sobre a organização deste livro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3.1 Planos para futuras versões deste livro . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.2 Convenções usadas neste livro . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3.2.1 Convenções para os exercícios propostos . . . . . . . . . . . . . . . . . 3
1.4 Porquê Java ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.4.1 Tipos de Programas em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.5 Informações para alunos da FCC/Univap . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.5.1 Sobre a disciplina Programação Orientada a Objetos I . . . . . . . . . . . . . . . 5
1.5.2 Sobre a disciplina Programação Orientada a Objetos II . . . . . . . . . . . . . . . 6
1.6 Agradecimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

2 Introdução a Programação Orientada a Objetos 7


2.1 O que são modelos ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 O que é POO ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.3 Classes, Objetos e Instâncias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Encapsulamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.5 Mais Exemplos de Classes e Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.6 Exercícios do capítulo 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

3 Criando Classes em Java 17


3.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2 Criando Classes em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.2.1 Atributos e dados são tipos nativos ou instâncias de outras classes . . . . . . . . . 19
3.2.2 Operações ou funções são Métodos . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.3 Exemplos de Classes em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.4 Exercícios do capítulo 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

4 Criando Programas em Java 33


4.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2 Criando Programas em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.2.1 Exemplos de programas em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.3 A palavra-chave new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4.4 Processando argumentos da linha de comando . . . . . . . . . . . . . . . . . . . . . . . . 36
4.5 Subrotinas em Programas em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
4.6 Exercícios do capítulo 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

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

8 Estruturas de Decisão e Controle 78


8.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
8.2 Operadores lógicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
8.3 A estrutura de decisão if/else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
8.4 A estrutura de decisão switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
8.5 Estruturas de repetição . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
8.6 A estrutura de repetição while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
8.7 A estrutura de repetição do-while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
8.8 A estrutura de repetição for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
8.9 Os comandos break e continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
8.10 Exercícios do capítulo 8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

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

10 Arrays em Java 116


10.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
10.2 Arrays de tipos nativos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
10.2.1 Caso especial: Processando a linha de comando . . . . . . . . . . . . . . . . . . . 123
10.3 Arrays Multidimensionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
10.3.1 Arrays Irregulares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
10.4 Arrays de instâncias de classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
10.5 Exercícios do capítulo 10 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
iii

11 Funções Matemáticas 142


11.1 Funções Matemáticas em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
11.2 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
11.3 Métodos de comparação e arredondamento . . . . . . . . . . . . . . . . . . . . . . . . . 142
11.4 Métodos trigonométricos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
11.5 Métodos exponenciais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
11.6 Outros métodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
11.7 Exercícios do capítulo 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

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

13 Entrada e Saída usando Arquivos 159


13.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
13.1.1 Acesso a arquivos em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
13.1.2 Sobre os arquivos usados neste capítulo . . . . . . . . . . . . . . . . . . . . . . . 161
13.2 Arquivos Sequenciais para Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
13.2.1 Leitura em arquivos sequenciais para Strings . . . . . . . . . . . . . . . . . . . . 162
13.2.2 Gravação em arquivos sequenciais para Strings . . . . . . . . . . . . . . . . . . . 165
13.3 Arquivos Sequenciais para Tipos Nativos . . . . . . . . . . . . . . . . . . . . . . . . . . 167
13.3.1 Leitura em arquivos sequenciais para dados de tipos nativos . . . . . . . . . . . . 167
13.3.2 Gravação em arquivos sequenciais para dados de tipos nativos . . . . . . . . . . . 169
13.4 Exercícios do capítulo 13 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

14 Estruturas de Dados Básicas em Java 177


14.1 A classe Vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
14.2 A classe Hashtable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

A Tipos de Dados em Java 178


A.1 Tipos de dados nativos em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
A.1.1 O tipo básico byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
A.1.2 O tipo básico char . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
A.1.3 O tipo básico short . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
A.1.4 O tipo básico int . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
A.1.5 O tipo básico long . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
A.1.6 O tipo básico float . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
A.1.7 O tipo básico double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
A.1.8 O tipo básico boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
A.2 Classes para representação de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
A.2.1 A classe String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
A.2.2 Classes para encapsulamento de tipos nativos . . . . . . . . . . . . . . . . . . . . 190
A.2.2.1 A classe Byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
A.2.2.2 A classe Character . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192
A.2.2.3 A classe Short . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
A.2.2.4 A classe Integer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
A.2.2.5 A classe Long . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
iv

A.2.2.6 A classe Float . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 197


A.2.2.7 A classe Double . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
A.2.2.8 A classe Boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200

B A Classe Keyboard 201


B.1 A classe Keyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
B.1.1 Usando a classe Keyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
B.1.1.1 Usando a classe Keyboard para leitura de valores tipo boolean . . . . . . 202
B.1.1.2 Usando a classe Keyboard para leitura de valores tipo byte . . . . . . . 202
B.1.1.3 Usando a classe Keyboard para leitura de valores tipo char . . . . . . . 203
B.1.1.4 Usando a classe Keyboard para leitura de valores tipo short . . . . . . . 203
B.1.1.5 Usando a classe Keyboard para leitura de valores tipo int . . . . . . . . 204
B.1.1.6 Usando a classe Keyboard para leitura de valores tipo long . . . . . . . 205
B.1.1.7 Usando a classe Keyboard para leitura de valores tipo float . . . . . . . 205
B.1.1.8 Usando a classe Keyboard para leitura de valores tipo double . . . . . . 206
B.1.1.9 Usando a classe Keyboard para leitura de instâncias da classe String . . 206
B.2 Outros exemplos de uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
B.3 Código fonte da classe Keyboard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210

C Usando o Java Development Kit 217


C.1 Sobre o Java Development Kit (JDK) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
C.1.1 Obtendo e Instalando o JDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
C.2 Como um programa em Java é compilado e executado . . . . . . . . . . . . . . . . . . . . 217
C.3 Usando o JDK no Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
C.3.1 Compilando e Executando Programas em Java no Linux . . . . . . . . . . . . . . 218
C.4 Usando o JDK no Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
C.4.1 Editores de Texto para o Windows . . . . . . . . . . . . . . . . . . . . . . . . . . 218
C.4.2 Compilando e Executando Programas em Java no Windows . . . . . . . . . . . . 218
C.5 Esclarecimentos Sobre Nomes de Classes e Arquivos . . . . . . . . . . . . . . . . . . . . 218
C.6 Possíveis Erros de Compilação e Execução . . . . . . . . . . . . . . . . . . . . . . . . . 219

D Usando o Sistema Operacional Linux 221


D.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
D.2 A estrutura de arquivos e diretórios do Linux . . . . . . . . . . . . . . . . . . . . . . . . 221
D.3 Uma introdução aos comandos básicos do Linux . . . . . . . . . . . . . . . . . . . . . . . 221
D.3.1 Executando comandos no Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
D.3.2 Comandos de listagem de diretórios e arquivos . . . . . . . . . . . . . . . . . . . 221
D.3.3 Comandos de criação, remoção e modificação de diretórios . . . . . . . . . . . . . 222
D.3.4 Comandos de cópia, remoção e modificação de arquivos e diretórios . . . . . . . . 222
D.3.5 Comandos de exibição do conteúdo de arquivos . . . . . . . . . . . . . . . . . . . 222
D.3.6 Editores de Texto para o Linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
D.3.6.1 Xemacs e Emacs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
v

Lista de Figuras

2.1 Uma classe veículo e vários objetos desta classe. . . . . . . . . . . . . . . . . . . . . . . 9


2.2 Uma lâmpada, seus atributos e operações . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.3 Uma data, seus atributos e operações . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.4 Um registro de aluno, seus atributos e operações . . . . . . . . . . . . . . . . . . . . . . . 12
2.5 Um modelo de computador, seus atributos e operações . . . . . . . . . . . . . . . . . . . 13
2.6 Uma conta bancária, seus atributos e operações . . . . . . . . . . . . . . . . . . . . . . . 13

10.1 Exemplo de arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116


10.2 Exemplo de arrays multidimensionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
10.3 Exemplo de arrays irregulares . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
10.4 Exemplo de arrays de instâncias de classes . . . . . . . . . . . . . . . . . . . . . . . . . . 128

13.1 Encapsulamento de arquivos por classes . . . . . . . . . . . . . . . . . . . . . . . . . . . 160


13.2 Funcionamento de ponteiros em arquivos sequenciais de texto . . . . . . . . . . . . . . . 161
13.3 Funcionamento de ponteiros em arquivos sequenciais binários . . . . . . . . . . . . . . . 167

C.1 Como um programa em Java é compilado e executado . . . . . . . . . . . . . . . . . . . . 217

D.1 Interface gráfica do Xemacs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222


D.2 Interface gráfica do Emacs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
vi

Lista de Listagens

3.1 Uma classe vazia em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18


3.2 Criação e inicialização de variáveis de tipos nativos em Java . . . . . . . . . . . . . . . . 20
3.3 Exemplo de alguns métodos em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.4 A classe Lampada (primeira versão) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.5 A classe Data (primeira versão) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.6 A classe RegistroDeAluno (primeira versão) . . . . . . . . . . . . . . . . . . . . . . . 25
3.7 A classe ModeloDeComputador (primeira versão) . . . . . . . . . . . . . . . . . . . . . 26
3.8 A classe ContaBancaria (primeira versão) . . . . . . . . . . . . . . . . . . . . . . . . . 27

4.1 Um programa mínimo em Java: HelloWorld.java . . . . . . . . . . . . . . . . . . . . 34


4.2 Um programa que usa instâncias da classe Lampada . . . . . . . . . . . . . . . . . . . . 34
4.3 Um programa que usa instâncias da classe Data . . . . . . . . . . . . . . . . . . . . . . 35
4.4 Um programa que conta quantos argumentos foram passados pela linha de comando . . . 36
4.5 Uma classe com o método main e uma subrotina . . . . . . . . . . . . . . . . . . . . . . 37
4.6 Uma classe cujas subrotinas chamam uma à outra . . . . . . . . . . . . . . . . . . . . . 38
4.7 Uma classe com variáveis estáticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.8 Uma classe com algumas variáveis e métodos estáticos . . . . . . . . . . . . . . . . . . . 39
4.9 Um programa que usa a classe com algumas variáveis e métodos estáticos . . . . . . . . . 39

5.1 A classe Veiculo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43


5.2 Criação de instâncias da classe Veiculo . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.3 A classe VeiculoTerrestre . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.4 Criação de instâncias da classe Veiculo e VeiculoTerrestre . . . . . . . . . . . . . . 45
5.5 A classe VeiculoTerrestre, segunda versão . . . . . . . . . . . . . . . . . . . . . . . 46
5.6 Problemas com sobrecarga de variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.7 Exemplo de problemas com variáveis privadas e herança . . . . . . . . . . . . . . . . . . 48
5.8 Solução do problema de variáveis privadas e herança . . . . . . . . . . . . . . . . . . . . 49
5.9 A classe Aluno (versão simples) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.10 A classe AlunoMestrado (primeira versão) . . . . . . . . . . . . . . . . . . . . . . . . . 51
5.11 A classe AlunoMestrado (segunda versão) . . . . . . . . . . . . . . . . . . . . . . . . . 52

6.1 A classe Hora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57


6.2 Um programa que demonstra usos da classe Hora . . . . . . . . . . . . . . . . . . . . . . 58
6.3 A classe Hora, com métodos polimórficos . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6.4 Um programa que demonstra usos da classe Hora que contém métodos polimórficos . . . 59
6.5 A classe Terminal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
6.6 A classe Livro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
6.7 A classe LivroComSoftware, herdeira da classe Livro . . . . . . . . . . . . . . . . . . 61
6.8 A classe MatBasica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.9 Um programa que demonstra a classe MatBasica . . . . . . . . . . . . . . . . . . . . . 63

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
vii

7.1 Um programa que usa instâncias da classe RegistroDeAluno . . . . . . . . . . . . . . . 67


7.2 A classe Lampada, com um construtor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
7.3 Classe que usa instâncias da classe Lampada com construtor . . . . . . . . . . . . . . . . 69
7.4 A classe Data com um construtor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
7.5 Classe que usa instâncias da classe Data com construtor . . . . . . . . . . . . . . . . . . 70
7.6 A classe Veiculo com construtores polimórficos . . . . . . . . . . . . . . . . . . . . . . 71
7.7 A classe VeiculoTerrestre com construtores polimórficos . . . . . . . . . . . . . . . . 72
7.8 Uma classe que usa instâncias da classe VeiculoTerrestre com construtores polimórficos 72
7.9 Uma classe que demonstra o uso implícito dos métodos toString . . . . . . . . . . . . . 73
7.10 A classe Data com um construtor e o método toString() . . . . . . . . . . . . . . . . . 74

8.1 Um programa que demonstra os operadores de comparação numérica de Java . . . . . . . 79


8.2 Um programa que demonstra combinações de operadores lógicos . . . . . . . . . . . . . 79
8.3 Um programa que demonstra as estruturas if e else . . . . . . . . . . . . . . . . . . . . 80
8.4 Um programa que demonstra aninhamento de if e else . . . . . . . . . . . . . . . . . . 81
8.5 Uma classe que usa estruturas if e else cascateadas . . . . . . . . . . . . . . . . . . . . 82
8.6 Trecho de programa que demonstra a estrutura switch . . . . . . . . . . . . . . . . . . . 83
8.7 Um programa que demonstra a estrutura switch . . . . . . . . . . . . . . . . . . . . . . 83
8.8 Uma classe que usa a estrutura switch . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
8.9 Uma classe com método main que usa o laço while . . . . . . . . . . . . . . . . . . . . 86
8.10 A classe Escolha . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
8.11 Exemplos de uso do laço while como contador . . . . . . . . . . . . . . . . . . . . . . . 87
8.12 Uma classe com método main que usa o laço do-while . . . . . . . . . . . . . . . . . . 88
8.13 Uma classe cujo construtor usa o laço do-while . . . . . . . . . . . . . . . . . . . . . . 89
8.14 Uma classe com método main que usa o laço for . . . . . . . . . . . . . . . . . . . . . . 90
8.15 A classe ProbabilidadeBasica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
8.16 Uma classe cujo construtor usa o laço while e o comando break . . . . . . . . . . . . . 91
8.17 Exemplo de uso do comando continue . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

9.1 Cálculo do comprimento de uma String (método length()) . . . . . . . . . . . . . . . . 99


9.2 Extração de caracteres (método charAt()) . . . . . . . . . . . . . . . . . . . . . . . . . 100
9.3 Comparações entre Strings (métodos equals() e equalsIgnoreCase()) . . . . . . . . . 101
9.4 Comparações entre Strings (método compareTo()) . . . . . . . . . . . . . . . . . . . . . 102
9.5 Comparações entre Strings (métodos startsWith() e endsWith()) . . . . . . . . . . . 102
9.6 Modificação de caracteres (métodos replace(), toLowerCase() e toUpperCase()) . . 103
9.7 Modificação de caracteres de Strings (métodos concat() e trim()) . . . . . . . . . . . 104
9.8 Seleção de trechos de Strings (método substring()) . . . . . . . . . . . . . . . . . . . 105
9.9 Procura de substrings em Strings (métodos indexOf() e lastIndexOf()) . . . . . . . . 106

10.1 Um programa que cria e popula um array de inteiros . . . . . . . . . . . . . . . . . . . . 117


10.2 Demonstração da inicialização imediata de arrays . . . . . . . . . . . . . . . . . . . . . 118
10.3 Um programa que demonstra a passagem de arrays como argumentos para métodos . . . 118
10.4 Um programa que mostra que arrays se comportam como referências . . . . . . . . . . . 119
10.5 Um programa que demonstra erros potenciais relacionados à índices de arrays . . . . . . 120
10.6 A classe ArrayDeQuadrados, que encapsula um array . . . . . . . . . . . . . . . . . . . 121
10.7 Um programa que usa a classe ArrayDeQuadrados . . . . . . . . . . . . . . . . . . . . 121
10.8 A classe ArrayDeFloats . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
10.9 Um programa que usa instâncias da classe ArrayDeFloats . . . . . . . . . . . . . . . . 123
10.10 Um programa que demonstra usos da linha de comando . . . . . . . . . . . . . . . . . . 124
10.11 Um programa que demonstra o uso de arrays multidimensionais . . . . . . . . . . . . . . 125

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
viii

10.12 Uma classe que encapsula um tabuleiro de jogo de damas . . . . . . . . . . . . . . . . . 126


10.13 Um programa que demonstra o uso de arrays multidimensionais irregulares . . . . . . . . 127
10.14 A classe Pessoa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
10.15 Uma classe que usa arrays de instâncias da classe Pessoa . . . . . . . . . . . . . . . . . 129
10.16 Uma classe que encapsula arrays de instâncias da classe Pessoa . . . . . . . . . . . . . . 129
10.17 Uma classe que demonstra o uso da classe ListaDePessoas . . . . . . . . . . . . . . . . 130

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

12.1 Vários erros de sintaxe em um programa exemplo . . . . . . . . . . . . . . . . . . . . . 149


12.2 Erros em potencial de um programa exemplo . . . . . . . . . . . . . . . . . . . . . . . . 150
12.3 Correção dos erros em potencial de um programa exemplo . . . . . . . . . . . . . . . . . 150
12.4 Estrutura de um bloco try/catch/finally . . . . . . . . . . . . . . . . . . . . . . . . . 151
12.5 Exemplo de programa que processa erros através de exceções . . . . . . . . . . . . . . . 152
12.6 Outro exemplo de programa que processa erros através de exceções . . . . . . . . . . . . 152
12.7 A classe ArrayDeFloats com métodos que lançam exceções . . . . . . . . . . . . . . . 154
12.8 Uma classe que representa uma exceção . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
12.9 A classe ArrayDeFloats com métodos que lançam exceções ExcecaoDeArray . . . . . 155
12.10 Uma classe que representa uma exceção que deve ser pega . . . . . . . . . . . . . . . . . 156
12.11 A classe ArrayDeFloats com métodos que lançam exceções ExcecaoRigorosaDeArray 157
12.12 Um programa que usa a classe ArrayDeFloats com exceções que devem obrigatoriamen-
te ser pegas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

13.1 Um programa que lê as linhas de um arquivo como Strings . . . . . . . . . . . . . . . . . 162


13.2 Listagem parcial do arquivo que contém informações sobre livros de uma livraria . . . . . 163
13.3 Classe que representa um Livro de Livraria . . . . . . . . . . . . . . . . . . . . . . . . . 164
13.4 Programa que usa a classe LivroLivraria e lê os dados de um arquivo . . . . . . . . . . 164
13.5 Um programa que grava Strings em um arquivo . . . . . . . . . . . . . . . . . . . . . . . 166
13.6 Um programa que lê valores do tipo float de um arquivo . . . . . . . . . . . . . . . . . . 168
13.7 A classe ContaBancaria que faz operações de gravação e leitura em um arquivo . . . . . 170
13.8 Programa que usa instâncias da classe ContaBancaria (inicializadas a partir de um arquivo)171

A.1 Programa que demonstra usos do tipo byte . . . . . . . . . . . . . . . . . . . . . . . . . 178


A.2 Programa que demonstra usos incorretos do tipo byte . . . . . . . . . . . . . . . . . . . 179
A.3 Programa que demonstra cast (conversão) de tipos . . . . . . . . . . . . . . . . . . . . . 179
A.4 Programa que demonstra usos do tipo char . . . . . . . . . . . . . . . . . . . . . . . . . 180
A.5 Programa que demonstra usos incorretos do tipo char . . . . . . . . . . . . . . . . . . . 180
A.6 Programa que demonstra usos do tipo short . . . . . . . . . . . . . . . . . . . . . . . . 181
A.7 Programa que demonstra usos incorretos do tipo short . . . . . . . . . . . . . . . . . . 182
A.8 Programa que demonstra usos do tipo int . . . . . . . . . . . . . . . . . . . . . . . . . 182
A.9 Programa que demonstra usos incorretos do tipo int . . . . . . . . . . . . . . . . . . . . 182
A.10 Programa que demonstra usos do tipo long . . . . . . . . . . . . . . . . . . . . . . . . . 183
A.11 Programa que demonstra usos incorretos do tipo long . . . . . . . . . . . . . . . . . . . 183
A.12 Programa que demonstra usos do tipo float . . . . . . . . . . . . . . . . . . . . . . . . 184
A.13 Programa que demonstra usos incorretos do tipo float . . . . . . . . . . . . . . . . . . 185

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
ix

A.14 Programa que demonstra usos do tipo double . . . . . . . . . . . . . . . . . . . . . . . 185


A.15 Programa que demonstra usos incorretos do tipo double . . . . . . . . . . . . . . . . . . 186
A.16 Programa que demonstra usos do tipo boolean . . . . . . . . . . . . . . . . . . . . . . . 186
A.17 Programa que demonstra usos incorretos do tipo boolean . . . . . . . . . . . . . . . . . 187
A.18 Programa que demonstra usos da classe String . . . . . . . . . . . . . . . . . . . . . . 188
A.19 Programa que demonstra usos de concatenação da classe String . . . . . . . . . . . . . 189
A.20 Programa que demonstra usos incorretos da classe String . . . . . . . . . . . . . . . . . 189
A.21 Programa que demonstra usos da classe Byte . . . . . . . . . . . . . . . . . . . . . . . . 191
A.22 Programa que demonstra usos incorretos da classe Byte . . . . . . . . . . . . . . . . . . 191
A.23 Programa que demonstra usos da classe Character . . . . . . . . . . . . . . . . . . . . 192
A.24 Programa que demonstra usos incorretos da classe Character . . . . . . . . . . . . . . . 193
A.25 Programa que demonstra usos da classe Short . . . . . . . . . . . . . . . . . . . . . . . 193
A.26 Programa que demonstra usos incorretos da classe Short . . . . . . . . . . . . . . . . . 194
A.27 Programa que demonstra usos da classe Integer . . . . . . . . . . . . . . . . . . . . . . 195
A.28 Programa que demonstra usos incorretos da classe Integer . . . . . . . . . . . . . . . . 196
A.29 Programa que demonstra usos da classe Long . . . . . . . . . . . . . . . . . . . . . . . . 196
A.30 Programa que demonstra usos incorretos da classe Long . . . . . . . . . . . . . . . . . . 197
A.31 Programa que demonstra usos da classe Float . . . . . . . . . . . . . . . . . . . . . . . 197
A.32 Programa que demonstra usos incorretos da classe Float . . . . . . . . . . . . . . . . . 198
A.33 Programa que demonstra usos da classe Double . . . . . . . . . . . . . . . . . . . . . . 199
A.34 Programa que demonstra usos incorretos da classe Double . . . . . . . . . . . . . . . . . 199
A.35 Programa que demonstra usos da classe Boolean . . . . . . . . . . . . . . . . . . . . . . 200
A.36 Programa que demonstra usos incorretos da classe Boolean . . . . . . . . . . . . . . . . 200

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

3.1 Tipos básicos de Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

A.1 Combinações especiais de caracteres e resultados em Strings . . . . . . . . . . . . . . . . 188

C.1 Exemplos de nomes de arquivos e classes geradas pelo compilador . . . . . . . . . . . . . 219


C.2 Alguns erros de compilação e execução, suas causas e possíveis soluções . . . . . . . . . . 220

D.1 Comandos básicos de teclado para o Emacs/Xemacs . . . . . . . . . . . . . . . . . . . . . 224

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
1

Capítulo 1

Sobre este livro

1.1 O que é este livro ?


Este livro contém o material sugerido para as disciplinas Programação Orientada a Objetos I e Pro-
gramação Orientada a Objetos II dos cursos de Ciência da Computação e Engenharia da Computação
oferecidos pela Faculdade de Ciência da Computação da Universidade do Vale do Paraíba (UNIVAP).

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.

Material complementar à este livro pode ser encontrado na página http://www1.univap.br/˜rafael,


assim como novas versões e últimas notícias. Eventualmente um manual do instrutor com todas as respos-
tas aos exercícios propostos será colocado à disposição de instrutores interessados em adotar o livro para
seus cursos. Adicionalmente, um site de suporte com exemplos, perguntas e respostas e listas de discussão
(ainda em desenvolvimento) será colocado à disposição de usuários, dependendo do interesse e do feedback
deste livro para o autor.

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.

Verifique regularmente a página http://www1.univap.br/˜rafael para novas versões, anúncios e in-


formações.

1.2 Como usar este livro


Esta versão deste livro está disponibilizada como um livro digital, no formato PDF, que pode ser lido pelo
software Adobe Acrobat Reader. Este software é distribuído gratuitamente pela Adobe, e pode ser copiado
do site da Adobe (http://www.adobe.com), onde versões para diversos sistemas operacionais podem ser
encontradas. Para usar este livro na sua forma eletrônica, basta copiá-lo para um computador com o Acro-
bat Reader instalado e abri-lo usando o Acrobat Reader.

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.

1.3 Sobre a organização deste livro


Cada capítulo deste livro é dedicado a um tema específico que pode ser coberto em uma ou mais aulas
teóricas e de laboratório. Os capítulos (presentes nesta versão) e seu conteúdo são:

• Capítulo 2: Introdução a Programação Orientada a Objetos apresenta conceitos básicos de pro-


gramação orientada a objetos, esclarecendo as diferenças e relações entre modelos, classes, objetos
e instâncias.
Neste capítulo, os conceitos apresentados são puramente teóricos, mas essenciais para a compreen-
são dos princípios básicos de orientação a objetos.

• 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.

• Apêndice B: A classe Keyboard apresenta a classe Keyboard, adaptada do livro An Introduction to


Computer Science Using Java, de Samuel N. Kamin, M. Dennis Mickunas e Edward M. Reingold,
que permite a leitura de valores de tipos nativos do teclado, adicionando flexibilidade aos programas.

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
3

1.3.1 Planos para futuras versões deste livro


Futuras versões deste livro conterão material sobre:

• Interfaces e mecanismo de herança com interfaces e implementações.

• O modificador final e suas aplicações.

1.3.2 Convenções usadas neste livro


Para simplificar a leitura deste livro, fontes diferentes serão usadas para destacar alguns elementos do texto.
Nomes de classes, métodos, pacotes, comandos, etc. serão mostrados em fonte proporcional. Conceitos
apresentados pela primeira vez serão mostrados em fonte itálica.

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.

1.3.2.1 Convenções para os exercícios propostos


Ao final de cada capítulo, alguns exercícios serão apresentados. Estes exercícios serão marcados com um
número de estrelas que indicam a sua dificuldade:

• 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

1.4 Porquê Java ?


Existem diversas linguagens de programação orientadas a objeto, cada uma com diferentes características
e apelos de mercado, educacionais ou acadêmicos. Nesta seção, as razões da escolha de Java sobre outras
possíveis linguagens (C++, Eiffel, Smalltalk) serão apresentadas.

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.4.1 Tipos de Programas em Java


Existem basicamente três tipos de programas que podem ser criados em Java:
Classes para representação de modelos. Classes são usadas para representar, em linguagem de progra-
mação, modelos e abstrações de dados como os mostrados no capítulo 2. Classes não podem ser
executadas diretamente, mas instâncias destas classes podem ser usadas dentro de aplicações e ap-
plets. Criação de classes em Java será vista na seção 3.2.
Classes como conjuntos de rotinas. Classes podem conter somente métodos (rotinas) ao invés de repre-
sentar dados. Estas classes funcionam como uma biblioteca de métodos ou funções que tem algo em
comum. A criação deste tipo de classes será vista na seção 4.5 (listagem 4.8).
Aplicações ou Programas. Aplicações ou programas podem ser executadas a partir de um terminal do
Linux ou da janela do MS-DOS, podendo envolver ou não maior interação com o usuário, e podendo
ou não ter uma interface gráfica. Criação de programas em Java será coberta no capítulo 4.
Applets. Applets são programas executáveis em Java que podem ser embutidos em páginas da Internet.
Sua execução é controlada pelo navegador que está sendo usado para ler as páginas. Por razões de
segurança, applets são limitadas nas tarefas que podem fazer, e obrigatoriamente devem ter interface
gráfica.
Para este curso, somente serão criadas e usadas classes e programas, dada a sua simplicidade e abrangência
de aplicações.

1.5 Informações para alunos da FCC/Univap


Esta seção contém informações sobre o uso deste livro na FCC/Univap nas disciplinas Programação Ori-
entada a Objetos I e Programação Orientada a Objetos II.

1.5.1 Sobre a disciplina Programação Orientada a Objetos I


A disciplina Programação Orientada a Objetos I visa levar os estudantes a:
• Compreender a metodologia de programação orientada a objetos;
• Compreender os conceitos e aplicações de encapsulamento, herança, polimorfismo e sobrecarga;
• Entender como os conceitos podem ser usados para criação de programas orientados a objetos na
linguagem Java;
• Entender os conceitos e funcionamento de algumas das classes mais comuns de Java.
As unidades da disciplina Programação Orientada a Objetos I (com os capítulos correspondentes neste
livro) são:

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

1.5.2 Sobre a disciplina Programação Orientada a Objetos II


A disciplina Programação Orientada a Objetos II visa levar os estudantes a:

• Compreender as vantagens e problemas da extensão de classes nativas de Java;


• Conhecer e ser capaz de criar programas com interfaces gráficas em Java;
• Compreender os mecanismos e a implementação de programas com eventos;
• Conhecer ferramentas da linguagem Java para interação pela Internet.

As unidades da disciplina Programação Orientada a Objetos II (com os capítulos correspondentes neste


livro) são:

• 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

Introdução a Programação Orientada a Objetos

2.1 O que são modelos ?


Modelos são representações simplificadas de objetos, pessoas, itens, tarefas, conceitos, idéias, etc., usados
comumente por pessoas no seu dia-a-dia, independente do uso de computadores.

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.

2.2 O que é Programação Orientada a Objetos ?


Programação Orientada a Objetos ou, abreviadamente, POO, é um paradigma de programação onde se
usam objetos, criados a partir dos modelos descritos anteriomente, para representar e processar dados usan-
do programas de computadores.

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.

2.3 Classes, Objetos e Instâncias


Embora o paradigma seja conhecido como “Programação Orientada a Objetos”, programadores que o usam
criam classes, que são relacionadas diretamente com os modelos descritos anteriormente.
1 Todomodelo, por se tratar de uma simplificação do mundo real, é um pouco artificial. Os termos “natural” e “artificial”
são usados para distinguir a linguagem usada para descrever os modelos: nos modelos imaginários apresentados nesta seção
podemos usar palavras para descrever os atributos e as operações em cada modelo, mas quando usamos uma linguagem de
programação estamos limitados ao vocabulário “artificial” desta, daí os termos usados na distinção.

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 Jato Comercial


− Número de passageiros: 260
− Velocidade Máxima: 950 km/h
− É aéreo ?: sim
Classe Veículo − É terrestre ?: não
− Número de passageiros
− Velocidade Máxima
− É aéreo ?
Objeto Motocicleta
− É terrestre ? − Número de passageiros: 2
− Velocidade Máxima: 250 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

Figura 2.1: Uma classe veículo e vários objetos desta classe.

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.

2.5 Mais Exemplos de Classes e Objetos


Para exemplificar melhor os conceitos de modelos, classes, objetos, encapsulamento e operações, veremos
alguns exemplos mais detalhados nesta seção.

Exemplo 1: Uma Lâmpada Incandescente

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

Figura 2.2: Uma lâmpada, seus atributos e operações

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.

Exemplo 2: Uma data

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.

Exemplo 3: Um registro acadêmico de aluno

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).

Exemplo 4: Um modelo de computador (para compra em loja virtual)

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

Figura 2.5: Um modelo de computador, seus atributos e operações

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.

Exemplo 5: Uma conta bancária simplificada

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

Figura 2.6: Uma conta bancária, seus atributos e operações

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).

2.6 Exercícios do capítulo 2


Para os exercícios deste capítulo, considere que as classes que são pedidas precisam apenas ter o nome e a
descrição de seus atributos e operações, conforme mostrado nas figuras dos exemplos da seção 2.5.
Exercício 2.1: ?
Considere a classe lâmpada mostrado no exemplo 1 da seção 2.5 (figura 2.2). Considere que uma lâmpada
possa ter um terceiro estado, queimada. Que atributos e operações deveriam ser então representados pela
classe ?

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

Criando Classes em Java

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.

3.2 Criando Classes em Java


Para criar uma classe você primeiramente precisará editá-la em um editor de textos de sua preferência.
Este editor de textos deve ser capaz de gravar arquivos em formato ASCII - editores como Microsoft Word
não são aconselháveis, uma vez que os arquivos criados são gravados em formato binário. Verifique o
apêndice C para informações sobre editores de texto sugeridos para uso em Windows e Unix e maiores
informações.

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.

Listagem 3.1: Uma classe vazia em Java


1 /* Esta é a nossa primeira classe, que deve estar
2 muito bem documentada.
3 Autor: Rafael Santos
4 Data: 10 de Março de 2000 */
5 class NomeDaClasse
6 {
7 // Tudo o que estiver entre as duas chaves pertencerá à classe
8 } // fim da classe NomeDaClasse

Algumas características importantes que podemos notar na listagem 3.1 são:

• 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.

3.2.1 Atributos e dados são tipos nativos ou instâncias de outras classes


Os atributos de uma classe, descritos no capítulo 2, são representados em Java por tipos nativos ou instân-
cias de outras classes já existentes. Para cada atributo da classe devemos escolher qual o tipo nativo ou
classe adequada e criar uma variável ou instância deste tipo ou classe para representá-lo.

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.

Algumas informações sobre variáveis em Java são mostradas abaixo:

• Variáveis em Java são declaradas como modificador tipo-da-variável nome-da-variável; -


note o ponto-e-vírgula ao final da declaração.
• O formato de declaração de variáveis que são instâncias de classes é modificador nome-da-classe
nome-da-variável = new nome-da-classe(); - note o ponto-e-vírgula ao final da declaração. O
comando new será visto com mais detalhes neste e no próximo capítulo.
• O controle de acesso as variáveis pode ser feito pelos modificadores private e public. Estes modi-
ficadores implementam a ocultação de informações vista na seção 2.4: variáveis que são declaradas
como public podem ser manipuladas (acessadas e modificadas) diretamente por programas que
usam a classe que contém esta variável, enquanto que variáveis que são declaradas como private
só podem ser manipuladas por métodos da classe que as contém.
• Os nomes de variáveis devem ser formados da mesma maneira que os nomes das classes: espaços
não são permitidos, os nomes devem começar com um caracter alfabético, e podem conter o caracter
sublinhado (_).
• Ao contrário dos nomes das classes, os nomes de variáveis podem conter acentos sem restrições.
• Para declararmos várias variáveis do mesmo tipo ao mesmo tempo, podemos usar modificador
tipo-da-variável nome1, nome2, nome3; - note que os diferentes nomes das variáveis são se-
parados por vírgulas, e que existe um ponto-e-vírgula no final da declaração. Não existem limites no
número de variáveis que podem ser declaradas em uma única linha, mas muitas variáveis em uma
linha podem comprometer a clareza e legibilidade do programa.
• É possível criar e colocar valores ao mesmo tempo nas variáveis com uma declaração modificador
tipo-da-variável nome-da-variável = valor;
• Variáveis podem ser criadas em qualquer ponto de um programa, classe ou rotina, mas algumas
regras devem ser observadas:

– 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

Tipo Faixa de valores Exemplos Notas


byte -128 a 127 byte x1 = -1; Inteiro de 8 bits de precisão, com sinal.
byte x2 = 123-2; Veja a seção A.1.1 no apêndice A.
char 0 a 65535 char c1 = ’a’; Caracteres representados em 16 bits,
char c2 = ’!’; com suporte multilíngue, podendo ser
char c3 = ’ã’; usados como tipos inteiros de 16 bits,
char c4 = ’ß’; com sinal. Veja a seção A.1.2 no apên-
dice A.
short -32768 a 32767 short s1 = -130; Inteiro de 16 bits de precisão, com sinal.
short s2 = 32000; Veja a seção A.1.3 no apêndice A.
short s3 = 20*30;
short s4 = 0;
int -2147483648 a 2147483647 int i1 = 0; Inteiro de 32 bits de precisão, com sinal.
int i2 = 1000*1000; Veja a seção A.1.4 no apêndice A.
int i3 = -999*999;
int i4 = 123456789;
long -9223372036854775808 a long l1 = 0; long l2 = -1; Inteiro de 64 bits de precisão, com sinal.
9223372036854775807 long l3 = -12345*67890; Veja a seção A.1.5 no apêndice A.
long l4 = 100000-99999;
float 1.40129846432481707e-45 a float f1 = 0.0; Ponto flutuante de precisão simples, ar-
3.40282346638528860e+38 float f2 = 3.1416; mazenados em 32 bits, com sinal. Veja
float f3 = -123.0/124.0; a seção A.1.6 no apêndice A.
float f4 = 2e5*3.2/2.7;
double 4.94065645841246544e-324 a double d1 = 0.0; Ponto flutuante de precisão dupla, arma-
1.79769313486231570e+308 double d2 = 3.141592654; zenados em 64 bits, com sinal. Veja a
double d3 = 0.01/1.07; seção A.1.7 no apêndice A.
double d4 = 2e+32*7e+18;
String Tamanho limitado à memória String s1 = ""; Cadeia de caracteres que usam dois by-
disponível. String s2 = " "; tes por caracter. Strings podem ser va-
String s3 = "3.1416"; zias (zero caracteres) e conter qualquer
String s4 = "nova\nlinha\n"; tipo de caracteres. Veja a seção A.2.1 no
apêndice A.

Tabela 3.1: Tipos básicos de Java

– 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.

Listagem 3.2: Criação e inicialização de variáveis de tipos nativos em Java


1 private boolean resultado; // Declaro que a variável resultado será do tipo boolean e que ela só
2 // poderá ser acessada de dentro da classe que a contém
3 resultado = true; // Digo que o valor da variável resultado será true - só podemos
4 // atribuir valores à variáveis depois que as declararmos.
5 int idade = 28; // Declaro a variável idade como do tipo int, e atribuo o valor 28
6 // à ela. Como esta variável não foi declarada com modificadores,

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
21

7 // ela será public, podendo ser acessada de dentro e de fora da classe


8 // que a implementa.
9 public char letra; // Declaro letra como sendo variável do tipo char, podendo ser acessada
10 // de dentro e de fora da classe que a contém
11 letra = ’S’; // A atribuo o valor ’S’ à variável letra
12 letra = ’Y’; // Posso mudar o valor das variáveis depois
13 private String palavra; // Declaro palavra como sendo instância da classe String que só poderá
14 // ser acessada de dentro da classe que a contém
15 palavra = "teste"; // Coloco um valor na variável palavra

É 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.

3.2.2 Operações ou funções são Métodos


Conforme visto no capítulo 2, classes representam modelos que tem atributos e operações. Os tipos de
dados servem para representar os atributos das classes, mas para representar (e implementar) as operações
nas classes, precisaremos criar estruturas chamadas Métodos, apresentadas nesta seção.

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:

• O formato de declaração de métodos é


modificador tipo-de-retorno nome-do-método(lista-de-argumentos). Note que o ponto-
e-vírgula não é colocado no final da declaração.
• Assim como as variáveis, o controle de acesso aos métodos de uma classe pode ser feito pelos mo-
dificadores private e public. Métodos que são declaradas como public podem ser executados
diretamente por classes e programas que usam a classe que contém este método, enquanto que mé-
todos declarados como private só podem ser executados por métodos da classe que os contém.
• Os nomes dos métodos podem ser formados da mesma maneira que os nomes das variáveis: espaços
não são permitidos, os nomes devem começar com um caracter alfabético, podem conter o caracter
sublinhado (_) e podem conter acentos sem restrições.
• Um método pode receber diversos argumentos de diferentes tipos: caso haja mais de um argumento
na lista de argumentos, cada argumento deverá ser precedido de seu tipo.
• Um método pode e deve retornar somente um único valor. Alternativamente, podemos ter métodos
que não retornam valores, devemos declarar o tipo de retorno destes métodos como void.
• Um método que retorne algum valor diferente de void deve conter em seu corpo o comando return
seguido de uma variável ou constante de tipo compatível com o tipo de retorno esperado.
• Tradicionalmente os nomes dos métodos começam com caracteres minúsculos, alternando a cada
palavra diferente. Alguns exemplos de nomes de métodos que seguem este estilo são calcula,
retornaValor, nomeDeMétodoMuitoComprido.
• Métodos não podem ser criados dentro de métodos, nem fora de classes.
• É aconselhável que o nome dos métodos represente de forma sumarizada a sua função no programa,
para maior clareza.

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.

Listagem 3.3: Exemplo de alguns métodos em Java


1 /* Este método não recebe argumentos, retorna um valor do tipo void e não faz absolutamente
2 nada. Como não tem modificadores, é considerado como public, podendo ser chamado de
3 dentro e de fora da classe que o contém. */
4 void métodoVazio()
5 {
6 }
7
8 /* Este método não recebe argumentos, retorna um valor do tipo double constante com o valor
9 de PI - a palavra-chave return força a interrupção do método, retornando o seu argumento.
10 Como o método é private, ele só poderá ser chamado de dentro da classe que o contém, por
11 outros métodos. */
12 private double valorDePi()
13 {
14 return 3.14159265358979;
15 }
16
17 /* Este método recebe um argumento do tipo byte mas não retorna nenhum valor. Quando o tipo
18 de retorno do método é void, o comando return é opcional. Como o método foi declarado
19 como sendo public, poderá ser chamado de dentro e de fora da classe que o contém. */
20 public void imprimeIdade(byte idade)
21 {
22 System.out.println("A idade é "+idade);
23 }
24
25 /* Este método recebe um argumento tipo int e retorna um valor do tipo double. A conversão é
26 feita através da multiplicação por 1.0. Um valor temporário de tipo compatível com o corpo
27 do método é declarado e retornado. Como não tem modificadores, é considerado como public. */
28 double converteParaDouble(int valor)
29 {
30 double temp = 1.0*valor;
31 return temp;
32 }
33
34 /* Este método recebe dois argumentos que são instâncias da classe String e retorna uma
35 instância da classe String (concatenação dos dois argumentos). Note que é preciso declarar
36 o tipo de cada um dos argumentos quando existem vários. O método é considerado public. */
37 String concatenaStrings(String a,String b)
38 {
39 return a+b;
40 }
41
42 /* Este método recebe cinco argumentos do tipo float e retorna a soma deles, que será de tipo
43 compatível com o declarado pelo método. Como o método é private, ele só poderá ser chamado
44 de dentro da classe que o contém, por outros métodos da mesma classe. */
45 private float somaCincoFloats(float f1,float f2,float f3,float f4,float f5)
46 {
47 return f1+f2+f3+f4+f5;
48 }

É 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

3.3 Exemplos de Classes em Java


Para exemplificar a transformação de um modelo em uma classe em Java, incluindo a seleção de tipos de
dados e métodos que podem ser usados, vamos usar os modelos mostrados na seção 2.5 do capítulo 2.

Exemplo 1: Uma Lâmpada Incandescente

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.

Listagem 3.4: A classe Lampada (primeira versão)


1 /* Esta é a classe Lâmpada (note que o nome da classe não contém acentos). */
2 class Lampada
3 {
4 /* Uma lâmpada pode estar ligada ou desligada, ou seja, o atributo "ligada" pode ser true
5 ou false. Usamos um valor booleano para representar o estado. Declaramos a variável como
6 sendo private para evitar o acesso direto à ela. */
7 private boolean ligada;
8 /* Este método acende a lâmpada, independente de seu estado atual */
9 void acende()
10 {
11 ligada = true;
12 }
13 /* Este método apaga a lâmpada, independente de seu estado atual */
14 void apaga()
15 {
16 ligada = false;
17 }
18 } // fim da classe Lampada

Exemplo 2: Uma data

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.

Listagem 3.5: A classe Data (primeira versão)


1 /* Esta é a classe Data */
2 class Data
3 {
4 /* Uma data contém dia, mês e ano. Dias e meses podem ser representados por bytes, mas o ano

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).

Exemplo 3: Um registro acadêmico de aluno

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.

Listagem 3.6: A classe RegistroDeAluno (primeira versão)


1 /* Esta é a classe RegistroDeAluno */
2 class RegistroDeAluno
3 {
4 /* Um Registro de Aluno contém o nome do aluno (que deve ser representado por uma String), um
5 número de matrícula (que pode ser um int), uma data de nascimento (que pode ser uma instância
6 da classe Data previamente construída), o ano no qual o aluno entrou no curso (que pode ser
7 um short, e é independente da data de nascimento), uma turma (que pode ser representada por
8 um char) e um valor para representar se o aluno é ou não bolsista (que pode ser um booleano).
9 Todas as variáveis são declaradas como private para evitar que sejam usadas diretamente fora
10 da classe. */
11 private String nome;
12 private int número;
13 private Data nascimento = new Data(); // Note que a declaração de uma instância é diferente da
14 // de uma variável de tipo nativo !
15 private short ano;
16 private char turma;
17 private boolean éBolsista;
18 /* Este método permite que inicializemos os valores da classe. */
19 void entraDados(String n,int num,Data nasc,short a,char t,boolean eb)
20 {
21 nome = n; /* inicializa o nome */
22 número = num; /* inicializa o noúmero de matrícula */
23 nascimento = nasc; /* inicializa a data de nascimento */
24 ano = a; /* inicializa o ano */
25 turma = t; /* inicializa a turma */
26 éBolsista = eb; /* inicializa o booleano éBolsista */
27 }
28 /* Este método imprime os valores da classe. Note que os valores de tipos nativos são impressos
29 com o método System.out.println, mas como nascimento é uma instância da classe Data,
30 simplesmente pegamos a data formatada (método formata da classe Data) ao invés de
31 imprimirmos o valor direto da variável nascimento, que iria dar resultados inesperados.
32 Note também o tratamento especial dado à variável booleana éBolsista. */
33 void imprime()
34 {
35 System.out.println("O nome do aluno é "+nome);
36 System.out.println("O número de matrícula é "+número);
37 System.out.println("A data de nascimento é "+nascimento.formata());
38 System.out.println("O ano em que o aluno está é "+ano);
39 System.out.println("A turma em que o aluno está é "+turma);
40 if (éBolsista) System.out.println("O aluno é bolsista.");
41 else System.out.println("O aluno não é bolsista.");
42 }
43 /* Este método calcula e retorna a mensalidade do aluno baseado em seus dados. Note que
44 nenhum argumento é passado ao método uma vez que todos os dados que são necessários */
45 float calculaMensalidade()
46 {
47 float mensalidade = 400; // mensalidade é quatrocentos reais para cada aluno.
48 if (éBolsista) mensalidade = mensalidade/2; // mas para bolsistas é reduzida à metade
49 return mensalidade; // retorna o valor da mensalidade
50 }
51 } // fim da classe RegistroDeAluno

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.

Exemplo 4: Um modelo de computador (para compra em loja virtual)

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.

A primeira versão da classe ModeloDeComputador é mostrada na listagem 3.7.

Listagem 3.7: A classe ModeloDeComputador (primeira versão)


1 /* Esta é a classe ModeloDeComputador */
2 class ModeloDeComputador
3 {
4 /* Um Modelo de Computador é composto do tipo de processador (que deve ser uma String,
5 já que existem diversos tipos de diversos fabricantes), de uma quantidade de memória
6 RAM expressa em megabytes, que pode ser representada por um short, de um disco rígido
7 cujo tamanho é expresso em gigabytes e pode ser representado por um float, e de um
8 tamanho de monitor em polegadas, que pode ser representado por um byte. Todas as
9 variáveis serão private para que só possam ser manipuladas pelos métodos desta classe. */
10 private String processador;
11 private short memóriaRAM;
12 private float disco;
13 private byte tamanhoMonitor;
14 /* Este método permite a inicialização dos valores da classe. */
15 void configura(String p,short r,float d,byte t)
16 {
17 processador = p; // inicializa o processador
18 memóriaRAM = r; // inicializa a memória RAM
19 disco = d; // inicializa o disco
20 tamanhoMonitor = t; // inicializa o tamanho do monitor
21 }
22 /* Este método imprime a configuração do computador */
23 void imprime()
24 {
25 System.out.println("A configuração do computador é:");
26 System.out.println("- Processador "+processador+".");
27 System.out.println("- "+memóriaRAM+" megabytes de RAM.");
28 System.out.println("- "+disco+" gigabytes de disco.");
29 System.out.println("- Monitor de "+tamanhoMonitor+" polegadas.");
30 }
31 /* Este método calcula o preço do computador */
32 float calculaPreço()
33 {
34 float preço = 200; // preço inicial é 200 reais (gabinete, etc.)
35 // Dependendo do tipo de processador, acrescento seu custo ao preço
36 if (processador.equals("Pentium II 400")) preço = preço + 500;
37 if (processador.equals("Pentium III 500")) preço = preço + 700;
38 // Dependendo do tamanho da memória, acrescento seu custo ao preço
39 if (memóriaRAM == 64) preço = preço + 200;
40 if (memóriaRAM == 128) preço = preço + 400;
41 if (memóriaRAM == 256) preço = preço + 800;
42 // Dependendo do tamanho do disco, acrescento seu custo ao preço
43 if (disco == 6.4) preço = preço + 250;
44 if (disco == 8.0) preço = preço + 350;
45 if (disco == 12.0) preço = preço + 450;
46 // Dependendo do tamanho do monitor, acrescento seu custo ao preço
47 if (tamanhoMonitor == 14) preço = preço + 120;
48 if (tamanhoMonitor == 15) preço = preço + 160;
49 if (tamanhoMonitor == 17) preço = preço + 320;
50 // retorno o valor calculado
51 return preço;
52 }
53 } // fim da classe ModeloDeComputador

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.

Exemplo 5: Uma conta bancária simplificada

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.

A primeira versão da classe ContaBancaria é mostrada na listagem 3.8.

Listagem 3.8: A classe ContaBancaria (primeira versão)


1 /* Esta é a classe ContaBancaria - note que não usamos acentos nos nomes de classes */
2 class ContaBancaria
3 {
4 /* Uma conta bancária simplificada contém o nome do correntista (uma String), um
5 número da conta (que pode ser um int), a data de abertura (que pode ser uma
6 instância da classe Data como visto no exemplo do Registro de Aluno), um saldo
7 (que pode ser float para simplificar), e um valor booleano que determina se a
8 conta é especial ou não. As variáveis vão ser todas private para garantir que
9 somente os métodos da classe serão capazes de mudar seus valores. */
10 private String nome;
11 private int número;
12 private Data abertura = new Data(); // Note a maneira de declarar e inicializar
13 // instâncias de classes !
14 private float saldo;
15 private boolean éEspecial;
16 /* Este método permite a inicialização dos valores da classe. */
17 void abreConta(String n,int num,Data a,float s,boolean e)
18 {
19 nome = n; // inicializa o nome
20 número = num; // inicializa o número da conta
21 abertura = a; // inicializa a data de abertura
22 saldo = s; // inicializa o saldo
23 éEspecial = e; // inicializa o booleano éEspecial
24 }
25 /* Este método imprime os dados da conta */
26 void imprime()
27 {
28 System.out.println("Dados da conta número "+número+":");
29 System.out.println("Nome do correntista: "+nome);
30 System.out.println("Data de abertura da conta: "+abertura.formata());
31 System.out.println("Saldo: "+saldo);
32 if (éEspecial) System.out.println("A conta é especial");
33 }
34 /* Este método deposita um valor na conta bancária, acumulando o valor na
35 variável saldo */
36 void deposita(float valor)
37 {
38 saldo = saldo + valor;
39 }
40 /* Este método retira um valor da conta bancária, descontando o valor da
41 variável saldo */
42 void retira(float valor)

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

3.4 Exercícios do capítulo 3


Exercício 3.1: ?
Considerando a tabela 3.1, escolha o tipo de dado ou classe mais adequada para representar:

• O número de dias em um ano.


• O número de bytes em um disco rígido de computador moderno.
• O número de bytes em um disquete de computador.
• O número de municípios de um estado do Brasil.
• O nome de um estado do Brasil.
• A população de um estado do Brasil.
• A área do Brasil em km2 .
• A população de todo o mundo.

Exercício 3.2: ?
Considerando a tabela 3.1, escolha o tipo de dado ou classe mais adequada para representar:

• O resultado do arremesso de uma moeda.


• O resultado do arremesso de um dado.
• O naipe de uma carta de baralho.
• A altura de uma pessoa em metros.
• O peso de uma pessoa em quilos.
• A temperatura de uma pessoa.
• O número de andares em um edifício.
• O número de páginas em um livro.

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.

Exercício 3.36: ? ? ? ? Novo !


Um número complexo é formado de uma parte real e uma imaginária. Sua notação é, de forma geral,
a + bi onde a é a parte real e b a imaginária.
A soma de dois números complexos é dada por (a + bi) + (c + di) = (a + c) + (b + d)i.
A subtração de dois números complexos é dada por (a + bi) (c + di) = (a c) + (b d)i.
A multiplicação de dois números complexos é dada por (a + bi) ⇤ (c + di) = (ac bd) + (ad + bc)i.
A divisão de dois números complexos é dada por (a+bi)
(c+di) = c2 +d 2 + c2 +d 2 i.
ac+bd bc ad

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

Criando Programas em Java

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.

4.2 Criando Programas em Java


Para que uma classe em Java possa ser executada como um programa, ela deve ter um ponto de entrada, que
é um método com nome, modificadores e argumentos especiais. O nome deste método deve ser main, e com
seus modificadores e argumentos, deve ser escrito como public static void main(String args[]).

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.

4.2.1 Exemplos de programas em Java


Programa mínimo: HelloWorld.java

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 !.

Listagem 4.1: Um programa mínimo em Java: HelloWorld.java


1 /* Esta é a classe HelloWorld, que não contém nenhum dado, somente o método main. */
2 class HelloWorld
3 {
4 /* Este é o método main, que será o ponto de entrada na execução do programa.
5 O método imprime uma mensagem simples. */
6 public static void main(String argumentos[])
7 {
8 System.out.println("Alô, Mundo !");
9 }
10 } // fim da classe HelloWorld

Alguns pontos de interesse do programa na listagem 4.1 são mostrados na lista abaixo:

• É absolutamente necessária a inclusão do método main em uma classe, na listagem de exemplo, a


classe HelloWorld (linhas 2 e 10).
• O método main deve ser declarado com os modificadores public static e o tipo de retorno void
(linha 6).
• O argumento passado para o método main deve ser um array de Strings (linha 6).
• Somente o que está contido dentro do método main (linhas 6 a 9) será executado, no caso, somente
a linha 8, que imprime a mensagem.

Programa que usa instância da classe Lampada

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.

Listagem 4.2: Um programa que usa instâncias da classe Lampada


1 /* Esta é a classe TesteLampada, que demonstrará como classes escritas anteriormente
2 podem ser usadas (instanciadas) em programas (classes com o método main). Este
3 programa criará várias instâncias da classe Lampada e as usará. */
4 class TesteLampada
5 {
6 /* Este é o método main, que será o ponto de entrada na execução do programa. */
7 public static void main(String args[])
8 {
9 // Criamos três instâncias da classe Lampada chamadas lâmpadaDaSala, lâmpadaDoQuarto

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
35

10 // e lâmpadaDaCozinha. Note que é necessário criar uma referência para a instância


11 // com a palavra-chave new.
12 Lampada lâmpadaDaSala = new Lampada();
13 Lampada lâmpadaDoQuarto = new Lampada();
14 Lampada lâmpadaDaCozinha = new Lampada();
15 // Acendo as três lâmpadas
16 lâmpadaDaSala.acende();
17 lâmpadaDoQuarto.acende();
18 lâmpadaDaCozinha.acende();
19 // Apago a do quarto
20 lâmpadaDoQuarto.apaga();
21 }
22 } // fim da classe TesteLampada

Programa que usa instâncias da classe Data

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.

Listagem 4.3: Um programa que usa instâncias da classe Data


1 /* Esta é a classe TesteData, que demonstrará como classes escritas anteriormente
2 podem ser usadas (instanciadas) em programas (classes com o método main).
3 Este programa criará várias instâncias da classe Data e as usará. */
4 class TesteData
5 {
6 /* Este é o método main, que será o ponto de entrada na execução do programa. */
7 public static void main(String args[])
8 {
9 // Criamos uma instância da classe Data chamada hoje. Note que é necessário
10 // criar uma referência para a instância com a palavra-chave new.
11 Data hoje = new Data();
12 // Chamamos o método ajustaData da classe Data (objeto hoje) com os argumentos
13 // 27, 3 e 1999. Note que já que os valores serão considerados como tipo int pelo
14 // compilador, é necessário o cast (conversão forçada) para os tipos esperados
15 // pelo método ajustaData, que são byte, byte e short.
16 hoje.ajustaData((byte)27,(byte)3,(short)2000);
17 // Criamos uma instância da classe Data chamada nascimento. Note que é
18 // necessário criar uma referência para a instância com a palavra-chave new.
19 Data nascimento = new Data();
20 // Chamamos o método ajustaDia da classe Data (objeto nascimento) com o argumento
21 // 30 - o valor deve ser convertido para byte para satisfazer o método.
22 nascimento.ajustaDia((byte)30);
23 // Chamamos o método ajustaMês da classe Data (objeto nascimento) com o argumento
24 // 7 - o valor deve ser convertido para byte para satisfazer o método.
25 nascimento.ajustaMês((byte)7);
26 // Chamamos o método ajustaAno da classe Data (objeto nascimento) com o argumento
27 // 1958 - o valor deve ser convertido para short para satisfazer o método.
28 nascimento.ajustaAno((short)1958);
29 // Peço que o objeto hoje chame seu método imprime - imprimirá os dados do objeto.
30 hoje.imprime();
31 // Mesmo para o objeto nascimento - resultados serão diferentes porque o conteúdo
32 // dos objetos é diferente.
33 nascimento.imprime();
34 // Imprimo uma mensagem
35 System.out.print("A data de hoje, formatada, é ");
36 // e imprimo o resultado do método formata da classe Data, que é uma String
37 System.out.println(hoje.formata());
38 }
39 } // fim da classe TesteData

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
36

4.3 A palavra-chave new


Nas listagens 4.2 e 4.3 pudemos notar que as instâncias das classes são criadas de maneira diferente das
variáveis simples: é necessário que referências às instâncias sejam criadas com a palavra-chave new con-
forme visto nas linhas 12 a 14 na listagem 4.2 e linhas 11 e 19 na listagem 4.3.

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.

4.4 Processando argumentos da linha de comando


O argumento passado para o método main (um array de Strings) conterá os dados passados na linha de
comando para o programa em Java. Por exemplo, caso a classe TesteLampada seja executada como java
TesteLampada uma string duas strings, o array args (argumento do método main) conterá quatro
Strings: “uma”, “string”, “duas” e “strings”. Estes valores são passados para o programa, que pode
ou não usá-los. Caso o programa seja chamado sem argumentos (por exemplo, java TesteLampada) o
array de Strings será vazio.

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

4.5 Subrotinas em Programas em Java


O modificador static permite que o método main seja chamado nas classes mostradas como exemplo
neste capítulo sem que seja necessário criarmos instâncias destas classes. Qualquer método que for decla-
rado com o modificador static seguirá as mesmas regras. Duas aplicações desta regra são a criação de
subrotinas dentro de uma classe que será executável e a criação de classes que não precisam ser instancia-
das para que seus métodos sejam usados.

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.

Listagem 4.5: Uma classe com o método main e uma subrotina


1 /* Classe executável que contém uma subrotina. */
2 class DemoSubrotinas
3 {
4 /* Método que possibilita a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Declaro duas variáveis do tipo double e guardo valores nelas
8 double x,y;
9 x = 9.15;
10 y = 9.12;
11 // Imprimo os valores através de uma subrotina
12 imprimeValores(x,y);
13 // Modifico os valores através de uma conta qualquer
14 x = x/2+x/3;
15 y = y/2-y/3;
16 // Imprimo os valores através de uma subrotina
17 imprimeValores(x,y);
18 }
19 /* Este método é a nossa subrotina. Note que ele deve ser decladaro static,
20 e nesse caso retorna void (ou seja, nada).
21 O método somente imprime as variáveis passadas para ele. */
22 static void imprimeValores(double x,double y)
23 {
24 System.out.println("O valor de X é "+x);
25 System.out.println("O valor de Y é "+y);
26 }
27 } // fim da classe DemoSubrotinas

Alguns pontos importantes sobre a criação de subrotinas em programas em Java são:

• 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.

Listagem 4.6: Uma classe cujas subrotinas chamam uma à outra


1 /* Classe executável que contém uma subrotina. */
2 class RecursivoInfinito
3 {
4 /* Este método chama o método pong */
5 static void ping()
6 {
7 pong();
8 }
9 /* Este método chama o método ping */
10 static void pong()
11 {
12 ping();
13 }
14 /* Método que possibilita a execução da classe */
15 public static void main(String parâmetros[])
16 {
17 // Aqui começa o ping-pong infinito !
18 ping();
19 }
20 } // fim da classe RecursivoInfinito

Listagem 4.7: Uma classe com variáveis estáticas


1 /* Classe executável que contém uma subrotina. */
2 class DemoSubrotinas
3 {
4 // Declaro as variáveis onde qualquer método possa vê-las - neste caso devem
5 // ser declaradas como static para uso dentro do método main
6 static double x,y;
7 /* Método que possibilita a execução da classe */
8 public static void main(String argumentos[])
9 {
10 // Guardo alguns valores nas variáveis globais do método
11 x = 9.15;
12 y = 9.12;
13 // Imprimo os valores através de uma subrotina
14 imprimeValores();
15 // Modifico os valores através de uma conta qualquer
16 x = x/2+x/3;
17 y = y/2-y/3;
18 // Imprimo os valores através de uma subrotina
19 imprimeValores();
20 }
21 /* Este método é a nossa subrotina. Note que ele deve ser decladaro static,
22 e nesse caso retorna void (ou seja, nada).
23 O método somente imprime as variáveis x e y, que foram declaradas como sendo globais. */
24 static void imprimeValores()
25 {
26 System.out.println("O valor de X é "+x);
27 System.out.println("O valor de Y é "+y);
28 }
29 } // fim da classe DemoSubrotinas

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.

Listagem 4.8: Uma classe com algumas variáveis e métodos estáticos


1 /* Uma classe simples, que contém algumas constantes e métodos estáticos. Esta
2 classe pode ser considerada como uma biblioteca - não precisamos criar
3 instâncias desta classe para usar suas variáveis e métodos. Para maior
4 utilidade, suas variáveis já recebem valores. */
5 class BibliotecaDeConstantes
6 {
7 // Declaro e inicializo duas constantes: "pi" e "e".
8 static double pi = 3.14159265358979;
9 static double e = 2.718281828459045;
10 // Declaro uma constante baseada em um valor "e" já declarado.
11 static double eQuadrado = e*e;
12 // Declaro um método que retorna um valor ("pi" dividido pelo argumento passado).
13 static double piDivididoPor(double valor)
14 {
15 return pi/valor;
16 }
17 // Declaro outro método que retorna um valor ("pi" multiplicado pelo argumento passado).
18 static double piMultiplicadoPor(double valor)
19 {
20 return pi*valor;
21 }
22 } // fim da classe BibliotecaDeConstantes

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

4.6 Exercícios do capítulo 4


Exercício 4.1: ?
O programa abaixo apresentará erros de compilação. Explique porquê.
1 public static void main(String parâmetros[])
2 {
3 float x,y;
4 x = 12;
5 y = x*x;
6 System.out.println("O quadrado de "+x+" é "+y);
7 }
8

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.

Exercício 4.16: ? ? ? Novo !


Escreva uma classe Conversao que contenha vários métodos para conversão entre medidas de compri-
mento, área e volume usadas no Brasil e nos Estados Unidos. Cada método deve receber um valor de
ponto flutuante e retornar o valor convertido para a unidade desejada. Por exemplo, um método double
PolegadaParaCentímetros(double pol) deve retornar o valor da variável pol convertida para centí-
metros.
Considere a lista de medidas abaixo como referência.

• 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).

Listagem 5.1: A classe Veiculo


1 /* Uma classe que representa um veículo genérico de transporte de passageiros. */
2 class Veiculo
3 {
4 // Os atributos do veículo genérico, representados por variáveis.
5 // Primeiro, a identificação do veículo.
6 String nome;
7 // Alguns dados do veículo
8 short númeroDePassageiros;
9 byte númeroDeRodas;
10 short velocidadeMédia;
11 // Algumas variáveis booleanos para classificação do tipo do veículo.
12 boolean éAéreo;
13 boolean éTerrestre;
14 boolean éAquático;

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
44

15 /* Um método para inicializar alguns valores do veículo genérico. */


16 void inicializa(String n,short np,byte nr,short vm)
17 {
18 nome = n;
19 númeroDePassageiros = np;
20 númeroDeRodas = nr;
21 velocidadeMédia = vm;
22 }
23 /* Um método para imprimir os dados do veículo genérico. */
24 void imprime()
25 {
26 // Imprime os dados de identificação
27 System.out.println("O veículo "+nome);
28 System.out.println("- carrega "+númeroDePassageiros+" passageiros");
29 System.out.println("- tem "+númeroDeRodas+" rodas");
30 System.out.println("- tem velocidade média "+velocidadeMédia+" km/h");
31 // Imprime seletivamente informações sobre tipo
32 if (éAéreo) System.out.println("- é aéreo");
33 if (éTerrestre) System.out.println("- é terrestre");
34 if (éAquático) System.out.println("- é aquático");
35 }
36 } // fim da classe Veículo

Uma classe executável que cria várias instâncias da classe Veiculo é mostrada na listagem 5.2.

Listagem 5.2: Criação de instâncias da classe Veiculo


1 /* Classe executável que cria instâncias da classe Veiculo */
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 para representar um jatinho Learjet
8 Veiculo learjet = new Veiculo();
9 learjet.inicializa("Jatinho Learjet",(short)16,(byte)6,(short)900);
10 learjet.éAéreo = true;
11 learjet.éTerrestre = false;
12 learjet.éAquático = false;
13 // imprimo os dados da instância learjet
14 learjet.imprime();
15 // Crio e inicializo uma instância para representar uma lambreta
16 Veiculo lambreta = new Veiculo();
17 lambreta.inicializa("Lambreta",(short)2,(byte)2,(short)40);
18 lambreta.éAéreo = false;
19 lambreta.éTerrestre = true;
20 lambreta.éAquático = false;
21 // imprimo os dados da instância lambreta
22 lambreta.imprime();
23 // Crio e inicializo uma instância para representar um navio de passageiros
24 Veiculo navio = new Veiculo();
25 navio.inicializa("Navio de Passageiros",(short)600,(byte)0,(short)80);
26 navio.éAéreo = false;
27 navio.éTerrestre = false;
28 navio.éAquático = true;
29 // imprimo os dados da instância navio
30 navio.imprime();
31 // Crio e inicializo uma instância para representar uma Fusca 66
32 Veiculo fusca66 = new Veiculo();
33 fusca66.inicializa("Fusca 66",(short)5,(byte)4,(short)60);
34 fusca66.éAéreo = false;
35 fusca66.éTerrestre = true;
36 fusca66.éAquático = false;
37 // imprimo os dados da instância fusca66

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

Alguns pontos interessantes das listagens 5.1 e 5.2 são:

• Para simplificar os exemplos, a classe Veiculo não apresenta variáveis privadas.


• O método inicializa da classe Veiculo inicializa somente os atributos básicos de uma instância -
detalhes são inicializados pelo acesso direto às variáveis das classes (por exemplo, nas linhas 18 a 20
da listagem 5.2).

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.

Listagem 5.3: A classe VeiculoTerrestre


1 /* Uma classe que representa um veículo terrestre de transporte de passageiros. */
2 class VeiculoTerrestre extends Veiculo
3 {
4 /* Não é necessário declarar nenhuma variável nesta classe: todas são herdadas
5 da classe Veiculo. Da mesma maneira não é necessário declarar nenhum método. */
6 } // fim da classe VeículoTerrestre

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.

Listagem 5.4: Criação de instâncias da classe Veiculo e VeiculoTerrestre


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 Veiculo onibus = new Veiculo();
9 onibus.inicializa("Ônibus de Passageiros",(short)50,(byte)6,(short)90);
10 onibus.éAéreo = false;
11 onibus.éTerrestre = true;
12 onibus.éAquático = false;
13 // imprimo os dados da instância onibus
14 onibus.imprime();
15 // Crio e inicializo uma instância da classe VeiculoTerrestre para representar

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
46

16 // outro ônibus de passageiros


17 VeiculoTerrestre outroÔnibus = new VeiculoTerrestre();
18 outroÔnibus.inicializa("Outro Ônibus de Passageiros",(short)42,(byte)6,(short)80);
19 outroÔnibus.éAéreo = false;
20 outroÔnibus.éTerrestre = false;
21 outroÔnibus.éAquático = true;
22 // imprimo os dados da instância outroÔnibus
23 outroÔnibus.imprime();
24 }
25 } // fim da classe TesteVeiculo

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.

5.2 O mecanismo de sobrecarga


Frequentemente teremos a necessidade de modificar um método de uma classe herdeira para que este
faça algo específico para a classe herdeira que não foi previsto na classe pai. O exemplo mostrado até
agora sugere que o método inicializa deva funcionar de maneira diferente para as classes Veiculo e
VeiculoTerrestre.

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.

Listagem 5.5: A classe VeiculoTerrestre, segunda versão


1 /* Uma classe que representa um veículo terrestre de transporte de passageiros
2 (segunda versão).*/
3 class VeiculoTerrestre extends Veiculo
4 {
5 /* Não é necessário declarar nenhuma variável nesta classe: todas são herdadas
6 da classe Veiculo, mas reescreveremos o método inicializa para que este predefina
7 os valores de algumas variáveis. Parte do método é exatamente igual ao método
8 inicializa da classe Veiculo. */
9 void inicializa(String n,short np,byte nr,short vm)
10 {
11 nome = n;
12 númeroDePassageiros = np;
13 númeroDeRodas = nr;

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

Usando a classe VeiculoTerrestre mostrada na listagem 5.5, poderíamos eliminar as linhas 19 a 21 do


programa na listagem 5.4, mostrando algumas vantagens do mecanismo de herança - a classe herdeira é
mais específica do que a Veículo, e seu uso é mais simples.

Alguns pontos importantes relativos ao mecanismo de sobrecarga são:

• 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).

Listagem 5.6: Problemas com sobrecarga de variáveis


1 /* Classe que representa uma identificação de uma pessoa */
2 class Identificacao
3 {
4 // String com a identificação
5 String ident;
6 /* Método para inicializar */
7 void inicializa(String id)
8 {
9 ident = id;
10 }
11 /* Método para imprimir */
12 void imprime()
13 {
14 System.out.println("Identificação:"+ident);
15 }
16 /* Método que permite a leitura da variável ident */

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

5.3 Herança de variáveis e métodos privados


Um problema que enfrentamos quando usamos o mecanismo de herança é que variáveis e métodos privados
não podem ser usados como mostrado até agora - métodos e variáveis privadas são herdados por classes
herdeiras, mas não podem ser acessados pela classe herdeira porque são privados da classe ancestral. Um
exemplo deste problema é mostrado nas classes na listagem 5.7.

Listagem 5.7: Exemplo de problemas com variáveis privadas e herança


1 /* Classe que representa um ponto em duas dimensões */
2 class Ponto2D
3 {
4 // Variáveis privadas
5 private short x,y;
6 /* Método para inicializar */
7 void inicializa(short _x,short _y)
8 {
9 x = _x;
10 y = _y;
11 }
12 /* Método para imprimir */
13 void imprime()
14 {
15 System.out.println("("+x+","+y+")");
16 }
17 /* Método que permite a leitura da variável x */
18 short qualX()
19 {
20 return x;
21 }
22 /* Método que permite a leitura da variável y */
23 short qualY()
24 {
25 return y;
26 }
27 } // fim da classe Ponto2D
28
29 /* Classe que representa um ponto em três dimensões, baseada na classe Ponto2D */
30 class Ponto3D extends Ponto2D
31 {
32 // Variáveis privadas
33 private short z;
34 /* Método para inicializar */
35 void inicializa(short _x,short _y,short _z)
36 {
37 x = _x;
38 y = _y;
39 z = _z;

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

Listagem 5.8: Solução do problema de variáveis privadas e herança


1 /* Classe que representa um ponto em duas dimensões */
2 class Ponto2D
3 {
4 // Variáveis privadas
5 private short x,y;
6 /* Método para inicializar */
7 void inicializa(short _x,short _y)
8 {
9 x = _x;
10 y = _y;
11 }
12 /* Método para imprimir */
13 void imprime()
14 {
15 System.out.println("("+x+","+y+")");
16 }
17 /* Método que permite a leitura da variável x */
18 short qualX()
19 {
20 return x;
21 }
22 /* Método que permite a leitura da variável y */
23 short qualY()
24 {
25 return y;
26 }
27 } // fim da classe Ponto2D
28
29 /* Classe que representa um ponto em três dimensões, baseada na classe Ponto2D */
30 class Ponto3D extends Ponto2D
31 {

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

Alguns pontos de interesse nas classes da listagem 5.8 são:

• 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.

5.4 Outros exemplos e mecanismos de herança


Nesta seção veremos alguns exemplos mais detalhados de herança e dos mecanismos relacionados. Como
mais exemplo de herança, considere a classe Aluno mostrada na listagem 5.9, que representa de maneira
simples os dados de um aluno de um curso superior.

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
51

Listagem 5.9: A classe Aluno (versão simples)


1 /* Esta classe representa os dados de um aluno de forma simples */
2 class Aluno
3 {
4 // Algumas variáveis para representar os dados do aluno
5 private String nome;
6 private long matrícula;
7 private float mensalidade;
8 /* O método que inicializa */
9 void inicializa(String n,long m)
10 {
11 nome = n;
12 matrícula = m;
13 inicializaMensalidade(400); // mensalidade fixa para os alunos - veja abaixo
14 }
15 /* Um método para inicializar só a mensalidade - pode ser que queiramos
16 chamá-lo separadamente do método inicializa, e este método também poderá
17 será herdado. */
18 void inicializaMensalidade(float m)
19 {
20 mensalidade = m;
21 }
22 /* O método que imprime os dados */
23 void imprime()
24 {
25 System.out.println("Dados do aluno "+matrícula);
26 System.out.println("Nome: "+nome);
27 System.out.println("Mensalidade: "+mensalidade);
28 }
29 /* Método para retornar o nome do aluno */
30 String qualNome()
31 {
32 return nome;
33 }
34 /* Método para retornar o número de matrícula do aluno */
35 long qualMatrícula()
36 {
37 return matrícula;
38 }
39 /* Método para retornar o valor da mensalidade */
40 float qualMensalidade()
41 {
42 return mensalidade;
43 }
44 } // fim da classe Aluno

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.

Listagem 5.10: A classe AlunoMestrado (primeira versão)


1 /* Esta classe representa os dados de um aluno de mestrado, herdando
2 o que já existe na classe Aluno */
3 class AlunoMestrado extends Aluno
4 {
5 // Variáveis adicionais para representar os dados do aluno
6 private String área; // a área de especialização

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
52

7 private String tese; // o título da tese


8 /* O método que inicializa */
9 void inicializa(String n,long m,String a,String t)
10 {
11 inicializa(n,m); // chama método que pode acessar nome e matrícula
12 área = a;
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 System.out.println("Dados do aluno "+qualMatrícula());
21 System.out.println("Nome: "+qualNome());
22 System.out.println("Mensalidade: "+qualMensalidade());
23 System.out.println("Área de especialização: "+área);
24 System.out.println("Título da tese: "+tese);
25 }
26 /* Método para retornar a área de especialização */
27 String qualÁrea()
28 {
29 return área;
30 }
31 /* Método para retornar o título da tese */
32 String qualTese()
33 {
34 return tese;
35 }
36 } // fim da classe AlunoMestrado

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.

Listagem 5.11: A classe AlunoMestrado (segunda versão)


1 /* Esta classe representa os dados de um aluno de mestrado, herdando
2 o que já existe na classe Aluno */
3 class AlunoMestrado extends Aluno
4 {
5 // Variáveis adicionais para representar os dados do aluno
6 private String área; // a área de especialização
7 private String tese; // o título da tese
8 /* O método que inicializa */
9 void inicializa(String n,long m,String a,String t)
10 {
11 inicializa(n,m); // chama método que pode acessar nome e matrícula
12 área = a;

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.

5.5 Exercícios do capítulo 5


Nem todos os exercícios apresentados nesta seção são diretamente relacionados com herança. Alguns ser-
vem para fixar os conceitos apresentados em capítulos anteriores.
Exercício 5.1: ?
Modifique o método imprime da classe Veiculo (listagem 5.1) para que caso o veículo não tenha rodas,
nada seja impresso (veja o resultado do programa na listagem 5.2).

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.

Listagem 6.1: A classe Hora


1 /* Esta classe representa uma hora (tempo) simples. */
2 class Hora
3 {
4 // Três variáveis para representar as horas, minutos e segundos
5 private byte horas;
6 private byte minutos;
7 private byte segundos;
8 /* Este método ajusta a hora com os valores passados */
9 void ajusta(byte phoras,byte pminutos,byte psegundos)
10 {
11 horas = phoras;
12 minutos = pminutos;
13 segundos = psegundos;
14 }
15 /* Este método imprime a hora formatada */
16 void imprime()
17 {
18 System.out.println(horas+":"+minutos+":"+segundos);
19 }
20 } // fim 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

Listagem 6.2: Um programa que demonstra usos da classe Hora


1 /* Esta classe demonstra usos da classe Hora */
2 class TesteHora
3 {
4 /* Este método faz com que a classe possa ser executada */
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);
10 Hora meianoite = new Hora();
11 meianoite.ajusta((byte)0,(byte)0,(byte)0);
12 Hora meiodia = new Hora();
13 meiodia.ajusta((byte)12,(byte)0,(byte)0);
14 Hora onzeemeia = new Hora();
15 onzeemeia.ajusta((byte)11,(byte)30,(byte)0);
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

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.

Listagem 6.3: A classe Hora, com métodos polimórficos


1 /* Esta classe representa uma hora (tempo) simples, e apresenta alguns
2 métodos polimórficos. */
3 class Hora
4 {
5 // Três variáveis para representar as horas, minutos e segundos
6 private byte horas;
7 private byte minutos;
8 private byte segundos;
9 /* Este método ajusta a hora, usando horas, minutos e segundos */
10 void ajusta(byte phoras,byte pminutos,byte psegundos)
11 {
12 horas = phoras;
13 minutos = pminutos;
14 segundos = psegundos;
15 }
16 /* Este método ajusta a hora, usando somente horas e minutos e considerando segundos como zero */
17 void ajusta(byte phoras,byte pminutos)
18 {
19 horas = phoras;
20 minutos = pminutos;
21 segundos = 0; // consideramos segundos como zero
22 }

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

6.2 Regras de polimorfismo


As regras para criação de métodos polimórficos são realmente simples: métodos polimórficos podem ser
criados se o número e tipo de argumentos passados aos métodos são diferentes - desta forma o compilador
sabe que método será chamado através da avaliação do número e tipos de dados.

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.

Listagem 6.5: A classe Terminal


1 /* Classe que demonstra alguns métodos polimórficos para esclarecer os conceitos
2 de polimorfismo. A classe contém somente métodos estáticos, significando que não
3 será precisa a criação de instâncias desta classe para usar seus métodos. A classe
4 serve como substituta do método System.out.println. */
5 class Terminal
6 {
7 /* Método que recebe uma String */
8 static void print(String a)
9 {
10 System.out.println(a);
11 }
12 /* Método que recebe duas Strings */
13 static void print(String a,String b)
14 {
15 System.out.println(a+" "+b);
16 }
17 /* Método que recebe três Strings */
18 static void print(String a,String b,String c)
19 {
20 System.out.println(a+" "+b+" "+c);
21 }
22 /* Método que recebe um boolean */
23 static void print(boolean a)
24 {
25 System.out.println(a);
26 }
27 /* Método que recebe um int */
28 static void print(int a)
29 {
30 System.out.println(a);
31 }
32 /* Método que recebe uma String e um double */
33 static void print(String a,double b)
34 {
35 System.out.println(a+" "+b);
36 }
37 /* Método que recebe um double e uma String */
38 static void print(double a,String b)
39 {
40 System.out.println(a+" "+b);
41 }
42 /* Método que recebe uma String e um int */
43 static String print(String a,int b)
44 {
45 return a+" "+b;
46 }
47 } // fim da classe Terminal

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.

6.3 Mais exemplos de polimorfismo


Métodos polimórficos podem ser criados na classe e herdado de outras, contanto que as regras básicas
mostradas na seção 6.1 sejam seguidas. Para demonstrar o uso de polimorfismo e herança, consideremos a
classe Livro (listagem 6.6) e a classe LivroComSoftware, herdeira de Livro, mostrada na listagem 6.7.

Listagem 6.6: A classe Livro


1 /* Esta é a classe Livro, que representa dados simples sobre um livro. */
2 class Livro
3 {
4 private String título; // O título do livro
5 private String autor; // O nome do autor do livro
6 private String editora; // O nome da editora do livro
7 private short númeroDePáginas; // O número de páginas do livro
8 /* Este método inicializa os quatro atributos do livro, passando-os como argumentos */
9 void inicializa(String t,String a,String e,short np)
10 {
11 título = t;
12 autor = a;
13 editora = e;
14 númeroDePáginas = np;
15 }
16 /* Este método imprime o conteúdo da classe de forma organizada */
17 void imprime()
18 {
19 System.out.println("Ficha do livro "+título+":");
20 System.out.println("Nome do Autor:"+autor);
21 System.out.println("Editora:"+editora);
22 System.out.println(númeroDePáginas+" páginas");
23 }
24 } // fim da classe Livro

Listagem 6.7: A classe LivroComSoftware, herdeira da classe Livro


1 /* Esta é a classe LivroComSoftware, que herda de classe Livro. Esta classe
2 representa um livro que vem acompanhado de software. */
3 class LivroComSoftware extends Livro
4 {
5 /* Além das variávels herdadas da classe Livro, esta classe define o nome do software que

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
62

6 acompanha o livro e um valor booleano que indica se a mídia do software é CD ou não. */


7 private String software;
8 private boolean éCD;
9 /* O método inicializa desta classe leva em consideração os dados herdados e os
10 declarados na própria classe */
11 void inicializa(String t,String a,String e,short np,String s,boolean cd)
12 {
13 super.inicializa(t,a,e,np); // Alguns dados podem ser inicializados pelo método
14 // inicializa da classe super (Livro).
15 software = s; // Os outros são inicializados no próprio método inicializa
16 éCD = cd;
17 }
18 /* O método imprime deve imprimir todos os atributos: os herdados e os declarados
19 na própria classe */
20 void imprime()
21 {
22 super.imprime(); // Os atributos herdados podem ser impressos pelo método imprime
23 // da classe super (Livro).
24 // Os outros são impressos aqui mesmo.
25 System.out.print("Inclui o software "+software+" ");
26 if (éCD) System.out.println("em CD-ROM");
27 else System.out.println("em disquetes");
28 }
29 } // fim da classe LivroComSoftware

A classe LivroComSoftware contém um método cujo nome simplificado é void inicializa(String,


String, String, short, String, boolean) (linha 11 da listagem 6.7), e herda da classe Livro o
método void inicializa(String, String, String, short np) (linha 9 da listagem 6.6).

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

Listagem 6.8: A classe MatBasica


1 /* A classe MatBasica contém alguns métodos estáticos para cálculos matemáticos básicos */
2 class MatBasica
3 {
4 /* Método que calcula e retorna a média de dois valores */
5 static double média(double a,double b)
6 {
7 return (a+b)/2;
8 }
9 /* Método que calcula e retorna a média de três valores */
10 static double média(double a,double b,double c)
11 {
12 return (a+b+c)/3;
13 }
14 /* Método que calcula e retorna o maior de dois valores */
15 static double maior(double a,double b)
16 {
17 if (a >= b) return a;
18 else return b;
19 }
20 /* Método que calcula e retorna o maior de três valores */
21 static double maior(double a,double b,double c)
22 {
23 double maiorAtéAgora = maior(a,b);
24 if (maiorAtéAgora >= c)
25 return maiorAtéAgora;
26 else return c;
27 }
28 } // fim da classe MatBasica

Listagem 6.9: Um programa que demonstra a classe MatBasica


1 /* Classe que demonstra a classe MatBasica */
2 class TesteMatBasica
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String args[])
6 {
7 // Calculamos e imprimimos algumas médias de dois e três valores
8 System.out.println(MatBasica.média(1,4));
9 System.out.println(MatBasica.média(1,2.2));
10 System.out.println(MatBasica.média(1.3,1.2,1.1));
11 System.out.println(MatBasica.média((byte)9,(short)9,(long)3));
12 // Calculamos e imprimimos os maiores valores de dois e três valores passados
13 System.out.println(MatBasica.maior(1,2L));
14 System.out.println(MatBasica.maior(3/7,4/9));
15 }
16 } // fim da classe TesteMatBasica

Alguns pontos interessantes das classes MatBasica e TesteMatBasica.java são:


• Na linha 8 da listagem 6.9 estamos passando valores inteiros para o método média, mas não ocorrem
erros de compilação porque o compilador aceita valores inteiros como argumentos para métodos que
esperam valores do tipo double.
Isto somente ocorre porque valores de tipo inteiro podem ser representados por valores do tipo dou-
ble, ainda que alguma precisão se perca. O mesmo ocorre na linha 11, uma vez que os valores dos
tipos byte, short e long serão convertidos automaticamente para double para uso pelo método média.
• Na linha 9 da listagem 6.9 um valor é do tipo int e outro do tipo double, o do tipo int (primeiro
argumento) será convertido automaticamente para double para uso pelo método média. O mesmo
ocorre na linha 13.

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.

6.4 Exercícios do capítulo 6


Nem todos os exercícios apresentados nesta seção são diretamente relacionados com polimorfismo. Alguns
servem para fixar os conceitos apresentados em capítulos anteriores.
Exercício 6.1: ?
Reescreva a classe Lampada (listagem 3.4) para que esta tenha dois métodos polimórficos de inicialização:
um ao qual se passa o valor booleano correspondente ao estado (acesa ou apagada) como argumento e
outro ao qual não se passam argumentos, desta maneira considerando-se a lâmpada como acesa.

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.

• static void print(String b)


• void print()
• static int print()
• static void print(double a,double b)
• void print(String a, int b)
• String print(int omega)
• boolean print(boolean funciona)
• static void imprime(int a)

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.

Listagem 7.1: Um programa que usa instâncias da classe RegistroDeAluno


1 /* Esta é a classe TesteRegistroDeAluno, que demonstrará o uso de instâncias da
2 classe RegistroDeAluno */
3 class TesteRegistroDeAluno
4 {
5 /* Método que permite a execução da classe */
6 public static void main(String params[])
7 {
8 // Criamos uma instância da classe RegistroDeAluno
9 RegistroDeAluno ana = new RegistroDeAluno();
10 // calculamos a mensalidade do alnno representado por esta instância
11 float mensalidade = ana.calculaMensalidade();
12 // imprimimos os dados deste aluno
13 ana.imprime();
14 }
15 } // fim da classe TesteRegistroDeAluno

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

que usa as classes.

É 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.

Listagem 7.2: A classe Lampada, com um construtor


1 /* Esta é a classe Lâmpada (note que o nome da classe não contém acentos).
2 Esta segunda versão contém um construtor para inicialização da classe. */
3 class Lampada
4 {
5 /* Os estados "ligado" e "desligado" são representados por um valor booleano -
6 true corresponde a "ligado" e false a "desligado". */
7 private boolean ligada;
8 /* O construtor da classe Lampada - deve ter o mesmo nome, nenhum valor de
9 retorno e nenhum modificador. Recebe como argumento um estado inicial. */
10 Lampada(boolean estado)
11 {
12 ligada = estado;
13 }
14 /* Este método acende a lâmpada, independente de seu estado atual */
15 void acende()
16 {
17 ligada = true;
18 }
19 /* Este método apaga a lâmpada, independente de seu estado atual */
20 void apaga()
21 {
22 ligada = false;
23 }
24 /* Este método imprime o estado da lâmpada */
25 void imprime()
26 {
27 if (ligada) System.out.println("ligada");
28 else System.out.println("desligada");
29 }
30 } // fim da classe Lampada

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.

7.1.1 O construtor default


Toda classe criada em Java já tem um construtor default, que não recebe nenhum argumento. O uso deste
construtor pode ser visto na linha 9 da listagem7.1 - a palavra-chave new chamará um construtor sem argu-
mentos da classe RegistroDeAluno.

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.

Listagem 7.4: A classe Data com um construtor


1 /* Esta é a classe Data, com um construtor */
2 class Data
3 {
4 private byte dia,mês; // dia e mês da data
5 private short ano; // ano da data
6 /* Este método ajusta o dia da data */
7 void ajustaDia(byte d)
8 {
9 dia = d;
10 }
11 /* Este método ajusta o mês da data */
12 void ajustaMês(byte m)

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

modificados, como mostrado nas linhas 10 e 12 da listagem 7.5.

É 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.

7.2 Construtores, herança e polimorfismo


As mesmas regras de polimorfismo e herança que se aplicam à métodos se aplicam aos construtores, com
poucas diferenças. Usando as regras de polimorfismo podemos criar vários construtores, só que estes não
retornam nenhum valor (nem mesmo void) nas suas declarações.

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.

Listagem 7.6: A classe Veiculo com construtores polimórficos


1 /* Uma classe que representa um veículo genérico de transporte de passageiros, com construtor */
2 class Veiculo
3 {
4 private String nome; // O nome do veículo
5 private short númeroDePassageiros; // Número de passageiros
6 private byte númeroDeRodas; // Número de rodas
7 private short velocidadeMédia; // Velocidade Média
8 private boolean éAéreo; // true se o veículo voa
9 private boolean éTerrestre; // true se o veículo é terrestre
10 private boolean éAquático; // true se o veículo é aquático
11 /* O construtor para inicializar todos os valores do veículo genérico */
12 Veiculo(String n,short np,byte nr,short vm,boolean ear,boolean ete,boolean eaq)
13 {
14 nome = n;
15 númeroDePassageiros = np;
16 númeroDeRodas = nr;
17 velocidadeMédia = vm;
18 éAéreo = ear;
19 éTerrestre = ete;
20 éAquático = eaq;
21 }
22 /* Um construtor mais simples que pressupõe veículos terrestres */
23 Veiculo(String n,short np,byte nr,short vm)
24 {
25 nome = n;
26 númeroDePassageiros = np;
27 númeroDeRodas = nr;
28 velocidadeMédia = vm;
29 éAéreo = false;
30 éTerrestre = true;
31 éAquático = false;
32 }
33 /* Um método para imprimir os dados do veículo genérico. */
34 void imprime()
35 {
36 // Imprime os dados de identificação
37 System.out.println("O veículo "+nome);
38 System.out.println("- carrega "+númeroDePassageiros+" passageiros");

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
72

39 System.out.println("- tem "+númeroDeRodas+" rodas");


40 System.out.println("- tem velocidade média "+velocidadeMédia+" km/h");
41 // Imprime seletivamente informações sobre tipo
42 if (éAéreo) System.out.println("- é aéreo");
43 if (éTerrestre) System.out.println("- é terrestre");
44 if (éAquático) System.out.println("- é aquático");
45 }
46 } // fim da classe Veículo

Listagem 7.7: A classe VeiculoTerrestre com construtores polimórficos


1 /* Uma classe que representa um veículo terrestre de transporte de passageiros
2 (com herança e construtores polimórficos) */
3 class VeiculoTerrestre extends Veiculo
4 {
5 /* Este é o construtor da classe VeiculoTerrestre */
6 VeiculoTerrestre(String n,short np,byte nr,short vm)
7 {
8 // Chamamos o construtor da classe super (Veiculo)
9 super(n,np,nr,vm); // todos os dados são inicializados
10 }
11 /* Este é outro construtor da classe VeiculoTerrestre, com menos argumentos */
12 VeiculoTerrestre(String n,short vm)
13 {
14 // Consideraremos o número de passageiros constante e igual a cinco, e o
15 // número de rodas constante e igual a 4
16 // Chamamos o construtor da classe super (Veiculo)
17 super(n,(short)5,(byte)4,vm);
18 }
19 } // fim da classe VeículoTerrestre

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.

7.3 O método toString()


Todas as classes em Java que não tem classe ancestral (ou seja, as classes que não usam herança) são mesmo
assim descendentes, implicitamente, de uma classe básica de Java chamada Object. Todas as classes cria-
das em Java tem, herdadas da classe Object, um método chamado toString(), que converte uma instân-
cia da classe para uma String, para fins de impressão. O método toString() é chamado automaticamente
quando tentamos passar uma instância de classe para o comando de impressão System.out.println ou
quando tentamos concatenar uma String à uma instância de classe com o sinal +.

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.

Listagem 7.10: A classe Data com um construtor e o método toString()


1 /* Versão simplificada da classe Data, com um construtor e o método toString */
2 class Data
3 {
4 private byte dia,mês; // dia e mês da data
5 private short ano; // ano da data
6 /* O construtor que recebe os três argumentos e inicializa os valores */
7 Data(byte d,byte m,short a)
8 {
9 dia = d;
10 mês = m;
11 ano = a;
12 }
13 /* Este método retorna a data formatada como uma String. */
14 public String toString()
15 {
16 String temporária = "Dia:"+dia+" Mês:"+mês+" Ano:"+ano;
17 return temporária;
18 }
19 } // fim da classe Data

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.

7.4 Exercícios do capítulo 7


Nem todos os exercícios apresentados nesta seção são diretamente relacionados à construtores. Alguns
servem para fixar os conceitos apresentados em capítulos anteriores.

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

Estruturas de Decisão e Controle

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.

8.2 Operadores lógicos


Todas as estruturas de controle são baseadas em operadores lógicos: estruturas de decisão executarão parte
do código se uma condição ocorrer ou não, e estruturas de repetição repetirão trechos de código até que
uma condição seja cumprida ou enquanto uma condição for válida. Operadores lógicos para controle des-
tas estruturas são operadores de comparação. Nesta seção veremos quais são os operadores de comparação
de Java e como eles podem ser usados.

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

Listagem 8.1: Um programa que demonstra os operadores de comparação numérica de Java


1 /* O programa nesta classe demonstra alguns operadores lógicos usados em comparações.
2 Note que após cada String dos comandos System.out.println, existe uma operação lógica entre
3 parênteses, cujo valor (true ou false) será concatenado à String para impressão. Os
4 resultados das comparações são mostrados em comentário ao final de cada linha. */
5 class DemoComparacoes
6 {
7 /* Este método permite a execução da classe */
8 public static void main(String argumentos[])
9 {
10 System.out.println("2 é igual a (3-1) ? "+ (2 == (3-1)) ); // true
11 System.out.println("2 é igual a (1-3) ? "+ (2 == (1-3)) ); // false
12 System.out.println("2 é diferente de (3-1) ? "+ (2 != (3-1)) ); // false
13 System.out.println("2 é diferente de (1-3) ? "+ (2 != (1-3)) ); // true
14 System.out.println("8 é maior que 7 ? "+ (8 > 7) ); // true
15 System.out.println("8 é maior que 12 ? "+ (8 > 12) ); // false
16 System.out.println("8 é menor que 7 ? "+ (8 < 7) ); // false
17 System.out.println("8 é menor que 12 ? "+ (8 < 12) ); // true
18 System.out.println("7+2 é maior ou igual a 12-4 ? "+ (7+2 >= 12-4) ); // true
19 System.out.println("7+2 é maior ou igual a 9 ? "+ (7+2 >= 9) ); // true
20 System.out.println("7+2 é maior ou igual a 15-4 ? "+ (7+2 >= 15-4) ); // false
21 System.out.println("5-1 é menor ou igual a 1+2 ? "+ (5-1 <= 1+2) ); // false
22 System.out.println("5-1 é menor ou igual a 4 ? "+ (5-1 <= 4) ); // true
23 System.out.println("5-1 é menor ou igual a 1+5 ? "+ (5-1 <= 1+5) ); // true
24 } // fim do método main
25 } // fim da classe DemoComparacoes

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.

Listagem 8.2: Um programa que demonstra combinações de operadores lógicos


1 /* O programa nesta classe demonstra algumas combinações de operadores lógicos.
2 Note que após cada String dos comandos System.out.println, existe uma operação lógica
3 entre parênteses, cujo valor (true ou false) será concatenado à String
4 para impressão. Os resultados das comparações são mostrados em comentário ao final
5 de cada linha. */
6 class DemoCombinacoes
7 {
8 /* Este método permite a execução da classe */
9 public static void main(String parâmetros[])
10 {
11 // Primeiro demonstraremos as combinações entre as constantes booleanas
12 System.out.println("true and true ? "+ (true && true) ); // true
13 System.out.println("true and false ? "+ (true && false) ); // false

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
80

14 System.out.println("false and true ? "+ (false && true) ); // false


15 System.out.println("false and false ? "+ (false && false) ); // false
16 System.out.println("true or true ? "+ (true || true) ); // true
17 System.out.println("true or false ? "+ (true || false) ); // true
18 System.out.println("false or true ? "+ (false || true) ); // true
19 System.out.println("false or false ? "+ (false || false) ); // false
20 System.out.println("not true ? "+ (!true) ); // false
21 System.out.println("not false ? "+ (!false) ); // true
22 // Agora demonstraremos combinações de comparações
23 int a = 17;
24 char b = ’J’;
25 double c = 1023.17;
26 System.out.println("a == 17 or b == ’J’ ? "+ ((a==17)||(b==’J’))); // true
27 System.out.println("a > 3 or c < 2000 ? "+ ((a>3)||(c<2000)) ); // true
28 System.out.println("a > 80 or c > 2000 ? "+ ((a>80)||(c>2000)) ); // false
29 System.out.println("a == 17 and b == ’J’ ? "+((a>17)&&(b==’J’)) ); // false
30 System.out.println("a == 17 and b == ’K’ ? "+((a==17)&&(b==’K’))); // false
31 System.out.println("a >= 17 and b <= ’J’ ? "+((a<=17)&&(b<=’J’))); // true
32 // Notem que em alguns casos foi necessário o uso de vários níveis de parênteses
33 // para evitar erros de sintaxe. O uso de parênteses para agrupar expressões booleanas
34 // é sempre aconselhável.
35 } // fim do método main
36 } // fim da classe DemoCombinacoes

8.3 A estrutura de decisão if/else


A estrutura de decisão mais simples é a if, que permite execução de um comando ou bloco de comandos
somente se a o operador ou expressão lógica avaliada tiver true como resultado.

A forma de uso da estrutura de decisão if é if (operador_lógico) comando_ou_bloco;, onde o opera-


dor_lógico pode ser qualquer operação, variável, constante ou combinação como as mostradas na seção 8.2
e comando_ou_bloco 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 }) e não precisa ser terminado com um ponto-e-
vírgula.

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.

Listagem 8.3: Um programa que demonstra as estruturas if e else


1 /* Esta classe demonstra os comandos if/else.
2 O preço de uma entrada de cinema é calculado da seguinte maneira:
3 - Se a pessoa tem menos de 14 ou mais de 65 anos, paga meia entrada (4 reais), caso contrário
4 paga 8 reais.
5 - Se o dia da semana for terça, quarta ou quinta, todos podem pagar meia entrada.
6 Para executar este programa você precisará da classe Keyboard. */
7 class Demoif
8 {
9 /* Este método garante a execução da classe */
10 public static void main(String argumentos[])
11 {
12 short idade; // a idade da pessoa

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
81

13 byte diasemana; // o dia da semana, de 1 a 7


14 float preço; // o preço a ser pago pelo ingresso
15 // Peço para que digite a idade
16 System.out.print("Entre a sua idade:");
17 idade = Keyboard.readShort();
18 // Peço para que digite o dia da semana
19 System.out.print("Entre o dia da semana (1=domingo, 2=segunda... 6=sexta, 7=sábado:");
20 diasemana = Keyboard.readByte();
21 // Se o dia da semana é entre 3 e 5, todo mundo paga meia
22 if ((diasemana >= 3) && (diasemana <= 5))
23 preço = 4;
24 else // então é outro dia da semana, vamos ver de acordo com a idade
25 {
26 if ((idade <= 14) || (idade >= 65))
27 preço = 4;
28 else
29 preço = 8;
30 } // fim do else do dia da semana
31 System.out.println("Você deve pagar "+preço+" reais");
32 } // fim do método main
33 } // fim da classe Demoif

É 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.

Listagem 8.4: Um programa que demonstra aninhamento de if e else


1 /* Uma classe que demonstra o aninhamento de blocos if/else */
2 class DemoIfElse
3 {
4 /* O método main permite a execução de uma classe */
5 public static void main(String args[])
6 {
7 boolean A=false,B=false; // Declaramos duas variáveis do tipo booleano
8 /* Neste bloco de if/else, o else está associado ao if mais próximo,
9 que é o if (B) */
10 if (A)
11 if (B) System.out.println("A e B são verdadeiros.")
12 else System.out.println("A é verdadeiro mas B é falso");
13 /* Neste bloco de if/else, o else está associado ao if mais próximo,
14 que é o if (A), porque o if (B) pertence a um bloco de comandos */
15 if (A)
16 {
17 if (B) System.out.println("A e B são verdadeiros.");
18 }
19 else System.out.println("A não é verdadeiro");
20 } // fim do método main
21 } // fim da classe DemoIfElse

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

Listagem 8.5: Uma classe que usa estruturas if e else cascateadas


1 /* Uma classe que representa um aparelho de TV com algumas características */
2 class AparelhoDeTV
3 {
4 /* Algumas variáveis relativas à uma TV */
5 private byte polegadas; // O número de polegadas da TV
6 private boolean SAP; // A TV tem Second Audio Program ?
7 private boolean PIP; // A TV tem Picture in Picture ?
8 /* O construtor que inicializará os valores */
9 AparelhoDeTV(byte p,boolean sap,boolean pip)
10 {
11 polegadas = p;
12 SAP = sap;
13 PIP = pip;
14 }
15 /* O método toString que permite a impressão formatada dos valores */
16 public String toString()
17 {
18 String resultado = "Televisão de "+polegadas+" polegadas";
19 if (SAP) resultado = resultado + " com SAP";
20 if (PIP) resultado = resultado + " com PIP";
21 return resultado;
22 }
23 /* O método calculaPreço calcula o preço de uma TV */
24 float calculaPreço()
25 {
26 float preço = 0; // é necessária a inicialização desta variável
27 // calcula um preço baseado no número de polegadas
28 if (polegadas == 14) preço = 320;
29 else if (polegadas == 21) preço = 660;
30 else if (polegadas == 29) preço = 810;
31 else if (polegadas == 34) preço = 1290;
32 if (SAP) preço = preço + 120; // 120 reais adicionais pelo SAP
33 if (PIP) preço = preço + 200; // 200 reais adicionais pelo PIP
34 return preço;
35 }
36 } // fim da classe AparelhoDeTV

8.4 A estrutura de decisão switch


É possível fazermos a avaliação de vários casos possíveis usando os encadeamento dos comandos if e
else, mas em casos onde existem muitas opções o código pode se tornar complexo e pouco legível.

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.

Listagem 8.6: Trecho de programa que demonstra a estrutura switch


1 /* Este é somente um trecho de programa para demonstração da estrutura switch */
2 switch(valor)
3 { // o bloco switch começa aqui
4 case 1:
5 {
6 // código a ser executado caso a variável valor valha 1
7 break; // vai para o fim do bloco switch
8 }
9 case 2:
10 {
11 // código a ser executado caso a variável valor valha 2
12 break; // vai para o fim do bloco switch
13 }
14 case 3:
15 {
16 // código a ser executado caso a variável valor valha 3
17 break; // vai para o fim do bloco switch
18 }
19 default:
20 {
21 // código a ser executado caso a variável valor valha qualquer valor
22 // que não seja os previstos acima
23 }
24 } // o bloco switch termina aqui

O uso principal da estrutura switch é o encaminhamento da execução do programa ou classe a um ponto.


Uma diferença essencial da estrutura switch para if e else encadeados é que a expressão que determinará
que trechos do programa serão executadas é avaliada só uma vez (no caso do switch), enquanto que para
cada if encadeado uma expressão será avaliada. A classe na listagem 8.7 contém um método main que
demostra um uso do comando switch.

Listagem 8.7: Um programa que demonstra a estrutura switch


1 /* Esta classe demonstra os comandos switch/case/default.
2 O usuário deve entrar um código que será avaliado pelo comand switch.
3 Para executar este programa você precisará da classe Keyboard. */
4 class DemoSwitch
5 {
6 public static void main(String argumentos[])
7 {
8 System.out.println("Enter um código de disciplina:");
9 System.out.println("1. Matemática:");
10 System.out.println("2. Física:");
11 System.out.println("3. Biologia:");
12 byte entrada = Keyboard.readByte();
13 switch(entrada)

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.

Listagem 8.8: Uma classe que usa a estrutura switch


1 /* Esta classe representa os dados de um aluno de forma simples */
2 class Aluno
3 {
4 // Algumas variáveis para representar os dados do aluno
5 private String nome;
6 private short curso; // curso será representado por um valor numérico
7 /* O construtor, que inicializará os dados */
8 Aluno(String n,short c)
9 {
10 nome = n;
11 curso = c;
12 }
13 /* O método que formata os dados e os retorna em uma String */
14 public String toString()
15 {
16 String dados = ""; // no início ela está vazia
17 dados = dados + "Dados do aluno "+nome+"\n"; // concatena o nome
18 // Ao invés de simplesmente concatenar o código numérico do curso vamos
19 // concatenar o nome do curso, que será decidido a partir do código
20 switch(curso)
21 {
22 case 23: // código para Engenharia Civil
23 {
24 dados = dados + "curso: Engenharia Civil\n";
25 break;
26 }
27 case 27: // código para Arquitetura
28 {
29 dados = dados + "curso: Arquitetura\n";
30 break;
31 }
32 case 34: // código para Ciência da Computação
33 {
34 dados = dados + "curso: Ciência da Computação\n";
35 break;

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

8.5 Introdução às estruturas de repetição


As estruturas de controle if/else e switch permitem que parte de um programa ou método sejam exe-
cutadas dependendo de uma condição, mas de maneira genérica elas somente mudam o fluxo do programa
de um ponto para outro, não servindo para que trechos de programas ou métodos sejam repetidos.

A capacidade de repetição de trechos de programas ou métodos é uma das características de linguagens


de programação que tornam os computadores mais úteis: dada uma tarefa ou rotina, esta pode ser repetida
inúmeras vezes de forma automática. Considere a tarefa de somar muitos valores ou procurar palavras em
um texto longo ou pesquisar vários registros de um banco de dados - tarefas tediosas se feitas por um ser
humano, mas que podem ser facilmente implementadas e repetidas por um computador.

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.

8.6 A estrutura de repetição while


Uma das estruturas que permite repetição em programas e classes em Java é a estrutura while, que tem co-
mo forma básica é while(condição) comando_ou_bloco;. A condição deve ser um valor ou expressão
booleana, e 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 }) e não precisa
ser terminado com um ponto-e-vírgula. O bloco ou comando associado ao laço será repetido enquanto o
valor booleano for verdadeiro. Se a condição for inicialmente false, o comando ou bloco de comandos
associado não será executado nem mesmo uma vez.

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

Listagem 8.10: A classe Escolha


1 /* Uma classe que permite a escolha de números em uma faixa */
2 class Escolha
3 {
4 private short início,fim; // a faixa de valores das quais poderemos escolher
5 /* O construtor (que receberá os valores que definem a faixa da escolha */
6 Escolha(short i,short f)
7 {
8 início = i;
9 fim = f;
10 }
11 /* Um método que permite a escolha de um valor, via teclado, dentro da faixa dos
12 valores especificados. */
13 short escolhe()
14 {
15 short valorEntrado = 0; // devemos inicializar esta variável com qualquer valor
16 boolean valorOK = false; // inicialmente consideraremos que o valor entrado não está OK
17 while(!valorOK) // enquanto o valor entrado não estiver OK
18 {
19 System.out.print("Entre um valor entre "+início+" e "+fim+":");
20 valorEntrado = Keyboard.readShort();
21 if ((valorEntrado >= início) && (valorEntrado <= fim)) // se estiver na faixa de valores
22 valorOK = true; // o valor será reconhecido como OK
23 }
24 return valorEntrado; // retornamos o valor entrado
25 } // fim do método escolhe
26 } // fim da classe Escolha

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.

Listagem 8.11: Exemplos de uso do laço while como contador


1 /* Uma classe que demonstra o uso do laço while como contador */
2 class Contador
3 {
4 public static void main(String argumentos[])
5 {
6 int valor; // uma variável que será usada para contagem
7 // contaremos de 1 até 20
8 valor = 1;
9 while(valor <= 20)
10 {
11 System.out.print(valor+" "); // imprimimos o valor do contador
12 valor++;
13 }
14 System.out.println(); // quebra de linha
15 // contaremos de 100 até 200, de 5 em 5
16 valor = 100;
17 while(valor <= 200)
18 {
19 System.out.print(valor+" "); // imprimimos o valor do contador
20 valor += 5;
21 }
22 System.out.println(); // quebra de linha

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
88

23 // contaremos de 1200 até 0, de 40 em 40 (regressivamente)


24 valor = 1200;
25 while(valor >= 0)
26 {
27 System.out.print(valor+" "); // imprimimos o valor do contador
28 valor -= 40;
29 }
30 System.out.println(); // quebra de linha
31 // contaremos de 1 até 100000, multiplicando o contador por dois a cada iteração
32 valor = 1;
33 while(valor <= 100000)
34 {
35 System.out.print(valor+" "); // imprimimos o valor do contador
36 valor *= 2;
37 }
38 System.out.println(); // quebra de linha
39 } // fim do método main
40 } // fim da classe Contador

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.

8.7 A estrutura de repetição do-while


Outra das estruturas que permitem repetição em programas e classes em Java é a estrutura do-while, cu-
ja como forma básica é do comando_ou_bloco while(condição);. A condição deve ser um valor ou
expressão booleana, e 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 })
e não precisa ser terminado com um ponto-e-vírgula. A cláusula while deve sempre ser seguida de um
ponto-e-vírgula.

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.

Listagem 8.13: Uma classe cujo construtor usa o laço do-while


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 do // pergunta 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 } while(nome.equals(""));
15 do // pergunta o e-mail até que seja dado um que não seja vazio
16 {
17 System.out.print("Entre o e-mail:");
18 email = Keyboard.readString();
19 } while(email.equals(""));
20 }
21 /* Este construtor receberá argumentos passados e inicializará as variáveis internas
22 com eles */
23 Agenda(String n,String e)
24 {
25 nome = n;
26 email = e;
27 }
28 /* Método que formata o conteúdo da classe e retorna como uma String */
29 public String toString()
30 {
31 return "Nome "+nome+" e-mail "+email+"\n";
32 }
33 } // fim da classe Agenda

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.

8.8 A estrutura de repetição for


Muitas vezes usaremos estruturas de laços para contagem ou repetição com um número definido de pas-
sos. Embora os laços while e do-while possam ser usados nestes casos, temos que tomar cuidado com a
inicialização e atualização dos valores das variáveis de controle e com as condições de parada.

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.

Listagem 8.15: A classe ProbabilidadeBasica


1 /* A classe ProbabilidadeBasica contém alguns métodos estáticos para cálculos básicos de
2 probabilidades */
3 class ProbabilidadeBasica
4 {
5 /* Método que calcula e retorna o fatorial de um valor */
6 static double fatorial(int val)
7 {
8 double f = 1;
9 for(int i=1;i<=val;i++) f *= i;
10 return f;
11 }
12 /* Método que calcula e retorna o número de combinações usando dois valores */
13 static double combinações(int quantos,int tomados)
14 {
15 return fatorial(quantos)/(fatorial(tomados)*fatorial(quantos-tomados));
16 }
17 /* Método que calcula e retorna o número de permutações usando dois valores */
18 static double permutações(int quantos,int tomados)
19 {

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

8.9 Os comandos break e continue


É possível interrompermos o fluxo normal de laços while, do-while e for usando os comandos break
e continue. Estes comandos, geralmente executados através de um if dentro dos laços, interrompem o
laço, mudando a execução do programa ou método para o final do laço (no caso do comando break) ou
para a próxima iteração do laço (no caso do comando continue).

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.

Listagem 8.17: Exemplo de uso do comando continue


1 /* Uma classe com método main que demonstra o comando continue */
2 class DemoContinue

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

8.10 Exercícios do capítulo 8


Exercício 8.1: ?
Modifique o programa na listagem 8.3 para que este verifique também que horas são, e cobre somente
meia entrada caso sejam antes das 4 horas da tarde.

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.22: ? Novo !


Escreva uma classe Loteria que tenha métodos estáticos para imprimir os cartões da Mega Sena e Lo-
tomania (somente os números de um cartão em branco, respeitando o número de linhas e colunas nos
cartões em papel).

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.36: ? ? Novo !


Escreva um programa em Java que imprima a série de Fibonacci até o N-ésimo elemento. A série de
Fibonacci é dada por 1, 1, 2, 3, 5, 8, 11, · · · onde cada valor é dado pela soma dos dois valores anteriores.
O número de elementos pode ser lido do teclado.

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.

9.2 Métodos básicos da classe String


Um método muito usado em Strings é o método length() que não recebe argumentos e retorna o número
de caracteres naquela instância da classe String, ou seja, o seu comprimento em caracteres. Alguns exem-
plos de uso deste método são mostrados na listagem 9.1.

Listagem 9.1: Cálculo do comprimento de uma String (método length())


1 /* Esta classe demonstra o método length para cálculo do número de caracteres
2 de Strings e comparação */
3 class DemoStrings
4 {
5 /* Este é o método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Criamos quatro Strings para comparação
9 String s1 = "string curta";

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
100

10 String s2 = "string pouco mais comprida";


11 String s3 = "string tão mais comprida do que as outras acima\nque ocupa duas linhas!";
12 // Imprimimos o comprimento destas Strings
13 System.out.println("Comprimento de "+s1+" é "+s1.length()); // 12
14 System.out.println("Comprimento de "+s2+" é "+s2.length()); // 26
15 System.out.println("Comprimento de "+s3+" é "+s3.length()); // 70
16 // Pode ser usado também com "constantes" de Strings
17 System.out.println(" Uma ’constante’ da classe String ".length()); // 36
18 }
19 } // fim da classe DemoStrings

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.

Listagem 9.2: Extração de caracteres (método charAt())


1 /* Esta classe demonstra usos do método charAt() para extração de
2 caracteres individuais de Strings. */
3 class DemoStrings
4 {
5 /* Este é o método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Criamos uma longa String
9 String s1 = "Máquinas tem menos problemas. Eu gostaria de ser uma máquina. "+
10 " -- Andy Warhol";
11 // Imprimimos o primeiro caracter da String
12 System.out.println(s1.charAt(0));
13 // Imprimimos o último caracter da String
14 System.out.println(s1.charAt(s1.length()-1)); // Notem a subtração de 1 do comprimento
15 // Outros caracteres da String são:
16 System.out.println(s1.charAt(9)); // ’t’
17 System.out.println(s1.charAt(45)); // ’s’
18 // Criamos uma String temporária para montagem com caracteres
19 String temp;
20 // E colocamos nela alguns caracteres da String longa. Note que a concatenação deve
21 // começar com uma String vazia ("") para garantir que o resultado será uma String
22 temp = ""+s1.charAt(7)+s1.charAt(36)+s1.charAt(38)+
23 s1.charAt(39)+s1.charAt(15)+s1.charAt(33);
24 System.out.println(temp); // imprimimos a String montada
25 // Usamos um laço for para imprimir os caracteres da posição 19 a 27
26 for(int i=19;i<28;i++)
27 System.out.print(s1.charAt(i));
28 System.out.println(); // Imprimimos uma quebra de linha
29 /* As linhas abaixo causarão erros de execução (exceções) do tipo
30 java.lang.StringIndexOutOfBoundsException ! */
31 char c = s1.charAt(-1); // Deve ser maior ou igual a zero
32 char d = s1.charAt(2048); // Deve ser menor que o tamanho da String
33 }
34 } // fim da classe DemoStrings

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
101

9.3 Métodos para comparação de Strings


Instâncias da classe String não podem ser comparadas com o sinal de igual (=). Para comparação entre duas
Strings, existem dois métodos que podem ser usados: equals() e equalsIgnoreCase(). Ambos devem
ser chamados como métodos de uma instância da classe String e recebem outra instância da classe como
argumento. Estes métodos retornam um valor booleano, true se a String passada como argumento é igual
à instância da classe String cujo método foi chamado, e false caso contrário. A diferença entre os dois
métodos é que o método equals() considera que caracteres maiúsculos e minúsculos que representam a
mesma letra são diferentes, enquanto que o método equalsIgnoreCase() não considera diferenças entre
caracteres maiúsculos e minúsculos. Resultados de comparação de Strings são mostrados no programa na
listagem 9.3:

Listagem 9.3: Comparações entre Strings (métodos equals() e equalsIgnoreCase())


1 /* Esta classe demonstra os métodos equals e equalsIgnoreCase de comparação de Strings */
2 class DemoStrings
3 {
4 /* Este é o método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Criamos três Strings para comparação
8 String s1 = "programação";
9 String s2 = "Programação";
10 String s3 = "PROGRAMAÇÃO";
11 System.out.println(s1+" é igual a "+s1+"?:"+s1.equals(s1)); // true
12 System.out.println(s1+" é igual a "+s2+"?:"+s1.equals(s2)); // false
13 System.out.println(s1+" é igual a "+s3+"?:"+s1.equals(s3)); // false
14 System.out.println(s1+" é igual (sem considerar maiúsculas/minúsculas) a "+s1+"?:"+
15 s1.equalsIgnoreCase(s1)); // true
16 System.out.println(s1+" é igual (sem considerar maiúsculas/minúsculas) a "+s2+"?:"+
17 s1.equalsIgnoreCase(s2)); // true
18 System.out.println(s1+" é igual (sem considerar maiúsculas/minúsculas) a "+s3+"?:"+
19 s1.equalsIgnoreCase(s3)); // true
20 // Comparação pode ser feita com "constantes" de Strings !
21 boolean resultado;
22 resultado = "PROGRAMAÇÃO".equals(s3); // true
23 resultado = "uma String".equalsIgnoreCase("Uma String"); // true
24 }
25 } // fim da classe DemoStrings

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.

Exemplos de uso do método compareTo() são mostrados na listagem 9.4.

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
102

Listagem 9.4: Comparações entre Strings (método compareTo())


1 /* Esta classe demonstra o método compareTo de comparação de Strings */
2 class DemoStrings
3 {
4 /* Este é o método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Criamos quatro Strings para comparação
8 String s1 = "teste de Strings";
9 String s2 = "teste de strings";
10 String s3 = "teste de comparação de Strings";
11 String s4 = "teste";
12 System.out.println("Comparação entre "+s1+" e "+s1+": "+
13 s1.compareTo(s1)); // 0: strings são iguais
14 System.out.println("Comparação entre "+s1+" e "+s2+": "+
15 s1.compareTo(s2)); // -32: diferença entre ’S’ e ’s’
16 System.out.println("Comparação entre "+s1+" e "+s3+": "+
17 s1.compareTo(s3)); // -16: diferença entre ’S’ e ’c’
18 System.out.println("Comparação entre "+s1+" e "+s4+": "+
19 s1.compareTo(s4)); // 11: diferença de comprimento
20 System.out.println("Comparação entre "+s2+" e "+s3+": "+
21 s2.compareTo(s3)); // 16: diferença entre ’s’ e ’c’
22 System.out.println("Comparação entre "+s2+" e "+s4+": "+
23 s2.compareTo(s4)); // 11: diferença de comprimento
24 System.out.println("Comparação entre "+s3+" e "+s4+": "+
25 s3.compareTo(s4)); // 25: diferença de comprimento
26 // Comparação pode ser feita com "constantes" de Strings !
27 int resultado;
28 resultado = "teste de comparacao".compareTo(s3); // -132: diferença entre ’c’ e ’ç’
29 resultado = "test string".compareTo("bem diferente"); // 18: diferença entre ’t’ e ’b’
30 resultado = "xxxx".compareTo("yy"); // -1: diferença entre ’x’ e ’y’
31 resultado = " ".compareTo(""); // 1: diferença de comprimento
32 }
33 } // fim da classe DemoStrings

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.

Listagem 9.5: Comparações entre Strings (métodos startsWith() e endsWith())


1 /* Esta classe demonstra os métodos startsWith e endsWith para comparação de Strings */
2 class DemoStrings
3 {
4 /* Este é o método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Criamos três Strings para verificação
8 String s1 = "Rio de Janeiro";
9 String s2 = "Rio Claro";
10 String s3 = "Juazeiro";
11 // Que strings começam com "Rio" ?
12 System.out.println(s1.startsWith("Rio")); // true
13 System.out.println(s2.startsWith("Rio")); // true
14 System.out.println(s3.startsWith("Rio")); // false
15 // Que strings terminam com "eiro" ?
16 System.out.println(s1.endsWith("eiro")); // true
17 System.out.println(s2.endsWith("eiro")); // false

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

9.4 Métodos para modificação de Strings


Podemos modificar o conteúdo de uma String de diversas maneiras: modificando seus caracteres, adicio-
nando caracteres às Strings, extraindo trechos das Strings, etc. Alguns dos métodos da classe String que
permitem modificações são mostrados nesta seção.

É 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.

Listagem 9.6: Modificação de caracteres (métodos replace(), toLowerCase() e toUpperCase())


1 /* Esta classe demonstra os métodos replace, toLowerCase e toUpperCase para troca
2 de caracteres de Strings */
3 class DemoStrings
4 {
5 /* Este é o método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Criamos três Strings para modificação
9 String s1 = "teste de modificação de strings";
10 String s2 = "String com diversos caracteres: 123#%[]{}()";
11 String s3 = "uma string com diversos espaços em branco";
12 // Trocamos os caracteres ’e’ por ’E’ na primeira e imprimimos
13 System.out.println(s1.replace(’e’,’E’));
14 // Trocamos os caracteres ’a’ por ’.’ na segunda e imprimimos
15 System.out.println(s2.replace(’a’,’.’));
16 // O resultado de um método replace é uma String, então podemos fazer o replace
17 // nela também, de forma encadeada: vamos trocar todas as vogais minúsculas
18 System.out.println(s2.replace(’a’,’.’).replace(’e’,’.’).
19 replace(’i’,’.’).replace(’o’,’.’).replace(’u’,’.’));
20 // Trocamos todos os espaços por sinais +
21 System.out.println(s3.replace(’ ’,’+’));
22 // Trocamos os caracteres minúsculos da primeira String por maiúsculos e imprimimos
23 System.out.println(s1.toUpperCase());
24 // Trocamos os caracteres maiúsculos da segunda String por minúsculos e imprimimos
25 System.out.println(s2.toLowerCase());
26 // Mudamos permanentemente os caracteres da terceira String para maiúsculos

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

Algumas notas importantes sobre modificação de caracteres:

• Os três métodos ( replace(),toLowerCase() e toUpperCase()) retornam novas instâncias da clas-


se String modificadas de acordo com o método - as instâncias originais não são modificadas pela
simples execução do método.
• O método replace() recebe dois caracteres, e não é possível passarmos Strings para trocar conjun-
tos de caracteres por conjuntos de caracteres: chamar o método como replace("não","sim") não
é possível, assim como não é possível especificar caracteres vazios (”).
• O método replace() considera caracteres maiúsculos e minúsculos como sendo diferentes.
• Os métodos toLowerCase() e toUpperCase() somente agem sobre caracteres que representam
letras, e consideram caracteres acentuados normalmente.

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.

Listagem 9.7: Modificação de caracteres de Strings (métodos concat() e trim())


1 /* Esta classe demonstra o método concat() para concatenação de Strings e o método
2 trim() para eliminação de espaços em branco no início e fim de uma String.*/
3 class DemoStrings
4 {
5 /* Este é o método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Criamos três Strings para concatenação
9 String s1 = "Uma das vantagens menos apreciadas de computadores é que ";
10 String s2 = "se eles fazem besteira, não existe nenhuma lei contra ";
11 String s3 = "bater neles um pouco -- Joe Martin";
12 // E uma nova String para conter todas elas
13 String s4;
14 // Concatenamos a segunda na primeira, e a terceira ao resultado
15 s4 = s1.concat(s2).concat(s3);
16 System.out.println(s4);
17 // Outra String para concatenação...
18 String s5 = s1+s2+s3;
19 System.out.println(s4.equals(s5)); // resultados da concatenação são iguais (true)
20 // Demonstramos também o uso do método trim()
21 String s6 = " Uma string com espaços no início e fim ";
22 String s7 = s6.trim(); // a mesma mas com os espaços iniciais e finais cortados

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.

9.5 Métodos para seleção em Strings


Em algumas rotinas e aplicações pode ser desejável o processamento de apenas parte de uma String, ou dos
caracteres individuais que a compõe. O método substring() retorna trechos de uma String, compostos
de um ou mais caracteres, como uma nova instância da classe String. Este método é polimórfico: em uma
forma deste, passamos um valor inteiro como argumento, e o método recortará da String que o chama os
caracteres cujo índice for maior do que o valor passado como argumento, e retornará esta String recortada.
A segunda versão do método aceita dois valores inteiros e retorna os caracteres da String cujos índices
sejam maiores ou iguais ao primeiro argumento e menores do que o segundo argumento.

Exemplos de uso do método substring() (inclusive as versões polimórficas) são mostrados no programa
na listagem 9.8.

Listagem 9.8: Seleção de trechos de Strings (método substring())


1 /* Esta classe demonstra usos do método substring() para seleção de trechos
2 de Strings. */
3 class DemoStrings
4 {
5 /* Este é o método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Criamos uma longa String
9 String s1 = "Existem dois tipos de tolos: os que nunca escalaram o Monte Fuji "+
10 "e os que o escalaram duas vezes - antigo provérbio japonês";
11 // Vamos extrair algumas substrings desta String
12 System.out.println(s1.substring(99)); // Da posição 99 até o final da String
13 System.out.println(s1.substring(116)); // Da posição 115 até o final da String
14 String s2 = s1.substring(54,64); // Da posição 54 até a posicão 63
15 System.out.println(s2);
16 String s3 = s1.substring(1,2); // Da posição 1 até a posicão 2
17 System.out.println(s3);
18 /* As linhas abaixo causarão erros de execução (exceções) do tipo
19 java.lang.StringIndexOutOfBoundsException ! */
20 System.out.println(s1.substring(-1)); // Deve ser maior ou igual a zero
21 System.out.println(s1.substring(20,18)); // Segundo valor deve ser maior do que o primeiro
22 System.out.println(s1.substring(32,32)); // Segundo valor deve ser maior do que o primeiro
23 }
24 } // fim da classe DemoStrings

9.6 Métodos para procura em Strings


A última categoria de métodos neste capítulo servem para procura de Strings dentro de Strings. Estes mé-
todos retornam um valor inteiro que é a posição da String procurada ou 1 se nada for encontrado.

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.

Listagem 9.9: Procura de substrings em Strings (métodos indexOf() e lastIndexOf())


1 /* Esta classe demonstra usos do método indexOf() e lastIndexOf() para
2 procura em Strings. */
3 class DemoStrings
4 {
5 /* Este é o método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Criamos uma longa String
9 String s1 = "Em três a oito anos nós teremos uma máquina com a inteligência "+
10 "de um ser humano médio ... a máquina irá começar a se educar com "+
11 "uma velocidade fantástica ... em alguns meses ela estará no nível "+
12 "de gênios e alguns meses depois seus poderes serão incalculáveis. "+
13 " -- Marvin Minsky, 1970";
14 // Procuraremos algumas substrings na String longa
15 System.out.println(s1.indexOf("máquina")); // 36
16 System.out.println(s1.indexOf("máquina",40)); // 92
17 System.out.println(s1.indexOf("máquina",125)); // -1
18 System.out.println(s1.indexOf("computador")); // -1
19 System.out.println(s1.indexOf("")); // String vazia: 0
20 // Procuraremos algumas substrings na String longa (a partir do fim)
21 System.out.println(s1.lastIndexOf("meses")); // 213
22 System.out.println(s1.lastIndexOf("meses",200)); // 168
23 System.out.println(s1.lastIndexOf("meses",40)); // -1
24 System.out.println(s1.lastIndexOf("semanas")); // -1
25 System.out.println(s1.lastIndexOf("")); // String vazia: 283
26 }
27 } // fim da classe DemoStrings

9.7 Exercícios do capítulo 9


Exercício 9.1: ?
Escreva um programa em Java que peça ao usuário que digite uma String, e só aceite Strings cujo com-
primento seja maior ou igual a 10 caracteres. Dica: use um laço while.

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:

• Para cada letra ’Q’ ou ’Z’ na palavra, some 10 pontos.


• Para cada letra ’J’ ou ’X’ na palavra, some 8 pontos.
• Para cada letra ’K’ na palavra, some 5 pontos.
• Para cada letra ’F’, ’H’, ’V’, ’W’ ou ’Y’ na palavra, some 4 pontos.
• Para cada letra ’B’, ’C’, ’M’ ou ’P’ na palavra, some 3 pontos.
• Para cada letra ’D’ ou ’G’ na palavra, some 2 pontos.
• Para todas as outras letras, some 1 ponto.

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:

• Se o comprimento das Strings for diferente, retorne 1.


• Se o comprimento das Strings for igual, faça os seguintes passos:
– Coloque o valor zero em um valor acumulador,
– Para cada posição nas duas Strings, compare os dois caracteres na posição,
– Se os caracteres forem exatamente iguais, some +3 pontos ao valor,
– Se os caracteres forem as combinações ’A’ e ’T’ ou ’T’ e ’A’, some +1 ponto ao acumula-
dor,
– Se os caracteres forem as combinações ’C’ e ’G’ ou ’G’ e ’C’, some +1 ponto ao acumula-
dor,
– Quando terminarem os caracteres das Strings, o valor acumulado será o valor a ser retornado
pelo método.

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:

• Alanine (A): GCU, GCC, GCA e GCG


• Arginine (R): CGU, CGC, CGA, CGG, AGA e AGG
• Aspartic Acid (D): GAU e GAC
• Arparginine (N): AAU e AAC
• Cysteine (C): UGU e UGC
• Glutamic acid (E): GAA e GAG
• Glutamine (Q): CAA e CAG
• Glycine (G): GGU, GGC, GGA e GGG
• Histine (H): CAU e CAC
• Isoleucine (I): AUU, AUC e AUA
• Leucine (L): UUA, UUG, CUU, CUC, CUA e CUG
• Lysine (K): AAA e AAG
• Methionine (M): AUG
• Phenylalanine (F): UUU e UUC
• Proline (P): CCU, CCC, CCA e CCG
• Serine (S): AGU, AGC, UCU, UCC, UCA e UCG
• Threonine (T): ACU, ACC, ACA e ACG
• Tryptophan (W): UGG
• Tyrosine (X): UAU e UAC
• Valine (V): GUU, GUC, GUA e GUG
• Sinais de término (.): UAA, UAG e UGA
Considerando a lista acima, escreva na classe StringRNA (exercício 9.39) um método que a partir da
String contendo RNA encapsulada na classe, varra a String de três em três caracteres e imprima o ami-
noácido correspondente. Escreva também um método que varra a String de três em três caracteres e
ao final retorne uma outra String contendo os símbolos dos aminoácidos: se a String encapsulada fos-
se ”CUGUAAGGGCCA” este método retornaria ”L.GP”. Ambos os métodos devem desconsiderar restos de
Strings que não formem três caracteres: uma String de oito caracteres corresponderá à dois aminoácidos
e dois caracteres sobrarão.
Dica: existe mais de uma maneira de calcular o aminoácido a partir das trincas de caracteres. Qual é a
mais simples ?

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"

Figura 10.1: Exemplo de arrays

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

10.2 Arrays de tipos nativos


A declaração de arrays em Java é feita usando colchetes: uma variável chamada números declarada como
números[] será automaticamente considerada um array. Antes de usarmos arrays, eles deve ter memó-
ria alocada para os dados que irão conter. Isto é feito através da palavra-chave new, na seguinte for-
ma: tipo_da_variável nome_da_variável[] = new tipo_da_variável[número_de_posições];.
Esta forma de declaração e alocação pode ser quebrada em duas partes, a primeira contendo a decla-
ração tipo_da_variável nome_da_variável[]; e a segunda contendo a alocação, onde a variável
que já foi declarada deve aparecer de maneira ligeiramente diferente, como: nome_da_variável = new
tipo_da_variável[número_de_posições]; (note que o nome da variável não tem colchetes, mas a va-
riável já deve ter sido declarada como array).

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.

Listagem 10.1: Um programa que cria e popula um array de inteiros


1 /* Esta classe demonstra o uso de um array de valores do tipo int - você
2 precisará da classe Keyboard para executar este programa. */
3 class DemoArray
4 {
5 /* Método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Declaro e ao mesmo tempo aloco um array chamado valores que conterá 10 ints
9 int valores[] = new int[10];
10 // Um laço de zero a nove lerá os valores do array

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
118

11 for(int contador=0;contador<10;contador++) // a variável contador só valerá dentro do for !


12 {
13 System.out.print("Entre o valor "+(contador+1)+":"); // note o (contador+1) para impressão
14 valores[contador] = Keyboard.readInt(); // de valores na faixa 1-10
15 }
16 // os valores já foram lidos, vamos imprimi-los
17 for(int contador=0;contador<10;contador++) // a variável contador deve ser redeclarada !
18 System.out.println("O valor "+(contador+1)+" é "+valores[contador]);
19 }
20 } // fim da classe DemoArray

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.

Listagem 10.2: Demonstração da inicialização imediata de arrays


1 /* Esta classe demonstra a inicialização imediata de arrays */
2 class DemoArray
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Declaro, aloco e inicializo ao mesmo tempo um array de valores inteiros
8 int fibonacci[] = {1, 1, 2, 3, 5, 8, 13, 21, 34}; // nove elementos
9 // Declaro, aloco e inicializo ao mesmo tempo um array de sete Strings
10 String nomes[] = {"Atchim","Dunga","Soneca","Mestre","Dengoso","Feliz","Zangado"};
11 // Declaro, aloco e inicializo ao mesmo tempo um array de shorts
12 short índices[] = {911, 912, 913, 914, 915}; // cinco elementos
13 // Os números da série de Fibonacci
14 for(int contador=0;contador<9;contador++) // a variável contador só vale no laço !
15 System.out.println(fibonacci[contador]); // imprime o elemento do array
16 // Os nomes dos sete anões:
17 for(int contador=0;contador<7;contador++) // a variável contador deve ser redeclarada
18 System.out.println(nomes[contador]); // imprime o elemento do array
19 // Os valores do array de shorts
20 for(int contador=0;contador<5;contador++) // a variável contador deve ser redeclarada
21 System.out.println(índices[contador]); // imprime o elemento do array
22 }
23 } // fim da classe DemoArray

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

5 static void imprimeArrayDeLongs(long esteArray[])


6 {
7 int númeroDePosições = esteArray.length;
8 for(int contador=0;contador<númeroDePosições;contador++)
9 System.out.println("O valor "+(contador+1)+" é "+esteArray[contador]);
10 }
11 /* Método que permite a execução da classe */
12 public static void main(String argumentos[])
13 {
14 int tam1,tam2; // tamanhos dos arrays
15 // pergunto os tamanhos dos arrays
16 System.out.print("Entre o tamanho do primeiro array:");
17 tam1 = Keyboard.readInt();
18 System.out.print("Entre o tamanho do segundo array:");
19 tam2 = Keyboard.readInt();
20 // Declaro e ao mesmo tempo aloco dois arrays de longs
21 long v1[] = new long[tam1];
22 long v2[] = new long[tam2];
23 // Um laço lerá os valores do array v1
24 for(int contador=0;contador<tam1;contador++) // a variável contador só valerá dentro do for !
25 {
26 System.out.print("Entre o valor "+(contador+1)+":"); // note o (contador+1) para impressão
27 v1[contador] = Keyboard.readInt(); // de valores na faixa 1-tam1
28 }
29 // Um laço lerá os valores do array v2
30 for(int contador=0;contador<tam2;contador++) // a variável contador só valerá dentro do for !
31 {
32 System.out.print("Entre o valor "+(contador+1)+":"); // note o (contador+1) para impressão
33 v2[contador] = Keyboard.readInt(); // de valores na faixa 1-tam2
34 }
35 // os valores já foram lidos, vamos imprimi-los
36 imprimeArrayDeLongs(v1);
37 imprimeArrayDeLongs(v2);
38 }
39 } // fim da classe DemoArray

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.

Listagem 10.6: A classe ArrayDeQuadrados, que encapsula um array


1 /* Esta classe encapsula um array de quadrados */
2 class ArrayDeQuadrados
3 {
4 private double quadrados[]; // somente declaramos o array aqui
5 /* Construtor, aceita um argumento que é o tamanho do array a ser alocado e calculado */
6 ArrayDeQuadrados(int número)
7 {
8 quadrados = new double[número]; // aloco memória para o array declarado anteriormente
9 // O construtor é o método mais adequado para a inicialização dos valores do array.
10 for(int contador=0;contador<número;contador++)
11 quadrados[contador] = contador*contador; // cada elemento conterá o quadrado do seu índice
12 }
13 /* Um método que permite o acesso às variáveis do array encapsulado */
14 double quadrado(int posição)
15 {
16 if ((posição >= 0) && // se a posição especificada for maior ou igual a zero e
17 (posição < quadrados.length)) // for menor do que o número de elementos...
18 return quadrados[posição]; // retorna o elemento desejado do array
19 else // imprimo uma mensagem de erro
20 {
21 System.out.print("Erro: não posso calcular o quadrado de "+posição);
22 System.out.println("(somente de 0 a "+(quadrados.length-1)+").");
23 System.out.println("O valor retornado está incorreto !");
24 return -1; // retorna um valor qualquer - ainda não é a melhor solução !
25 }
26 } // fim do método quadrado
27 } // fim da classe ArrayDeQuadrados

Esta classe pode ser usada em um programa, como mostrado na listagem 10.7.

Listagem 10.7: Um programa que usa a classe ArrayDeQuadrados


1 /* Esta classe usa uma instância da classe ArrayDeQuadrados */
2 class DemoArrayDeQuadrados
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Crio a instância do array de quadrados, com 1000 elementos
8 ArrayDeQuadrados aq = new ArrayDeQuadrados(1000);
9 // Fazemos um laço para leitura e exibição dos valores
10 boolean continua = true;
11 while(continua) // enquanto a variável continua for verdadeira
12 {
13 System.out.print("Entre um número de 0 a 999:"); // imprime a pergunta
14 int valor = Keyboard.readInt(); // declaro a variável, que receberá a resposta
15 // imprimo o valor entrado e seu quadrado - note que simplesmente chamo o método
16 System.out.println("O quadrado de "+valor+" é "+aq.quadrado(valor));
17 System.out.print("Quer continuar ? (S/N):"); // imprime a pergunta
18 continua = Keyboard.readBoolean(); // recebe a resposta na variável continua
19 } // fim do while
20 } // fim do método main
21 } // fim da classe ErroArray

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.

Listagem 10.8: A classe ArrayDeFloats


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 array = new float[número]; // aloco memória para o array declarado anteriormente
9 }
10 /* Método que retorna o tamanho do array encapsulado */
11 int tamanho()
12 {
13 return array.length;
14 }
15 /* Método que retorna o array, formatado como uma String */
16 public String toString()
17 {
18 String resultado = "O array tem "+array.length+" elementos:\n";
19 for(int c=0;c<array.length;c++) // para cada elemento
20 resultado += array[c]+" "; // concatena no resultado
21 return resultado; // retorna a String criada
22 }
23 /* Método que seta o valor na posição especificada */
24 void seta(int posição,float valor)
25 {
26 if ((posição >= 0) && (posição < array.length)) // somente se estiver na faixa de índices
27 array[posição] = valor; // válidos o valor será modificado
28 }
29 /* Método que permite o acesso à um dos valores do array */
30 float valor(int posição)
31 {
32 if ((posição >= 0) && (posição < array.length))
33 return array[posição];
34 else return 0; // valor qualquer a ser retornado
35 }
36 /* Método que retorna o menor dos elementos do array */
37 float menorValor()
38 {
39 float menorAtéAgora = array[0]; // o primeiro achado é o menor até agora
40 for(int c=1;c<array.length;c++) // verifica dentre os outros
41 if (array[c] < menorAtéAgora) // se um deles é menor do que o menor até agora
42 menorAtéAgora = array[c]; // o menor até agora passa a ser aquele elemento
43 return menorAtéAgora;
44 }

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
123

45 /* Método que retorna o maior dos elementos do array */


46 float maiorValor()
47 {
48 float maiorAtéAgora = array[0]; // o primeiro achado é o maior até agora
49 for(int c=1;c<array.length;c++) // verifica dentre os outros
50 if (array[c] > maiorAtéAgora) // se um deles é maior do que o maior até agora
51 maiorAtéAgora = array[c]; // o maior até agora passa a ser aquele elemento
52 return maiorAtéAgora;
53 }
54 } // fim da classe ArrayDeFloats

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.

Listagem 10.9: Um programa que usa instâncias da classe ArrayDeFloats


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 // Crio duas instâncias da classe ArrayDeFloats
8 ArrayDeFloats af1 = new ArrayDeFloats(10);
9 ArrayDeFloats af2 = new ArrayDeFloats(200);
10 // Populo a instância af1 (somente alguns de seus elementos)
11 af1.seta(0,3.141592f); // veja que os segundos argumentos são floats !
12 af1.seta(3,-9.8f);
13 af1.seta(4,1.3e25f);
14 af1.seta(-100,1.3e25f); // este comando não tem efeito !
15 // Populo a instância af2 através de um laço
16 for(int i=0;i<af2.tamanho();i++)
17 af2.seta(i,(float)((i-1.)/(i+1.))); // fórmula para popular o array
18 // Qual são os maiores e menores valores de cada array ?
19 System.out.println("O menor valor do primeiro array é "+af1.menorValor());
20 System.out.println("O maior valor do primeiro array é "+af1.maiorValor());
21 System.out.println("O menor valor do segundo array é "+af2.menorValor());
22 System.out.println("O maior valor do segundo array é "+af2.maiorValor());
23 // Imprimo o primeiro array
24 System.out.println(af1);
25 } // fim do método main
26 } // fim da classe DemoArrayDeFloats

10.2.1 Caso especial: Processando a linha de comando


Em diversos programas em Java (classes que implementam o método main()) vimos que para este método
um único argumento é obrigatoriamente passado, e este argumento é um array de Strings. Os valores con-
tidos neste array são criados pela máquina virtual Java quando esta tenta executar um programa, usando
os argumentos passados na linha de comando do sistema operacional em que esta máquina virtual esteja
sendo executado.

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().

Listagem 10.10: Um programa que demonstra usos da linha de comando


1 /* Esta classe demonstra o uso do array definido como argumento para a
2 linha de comando */
3 class DemoLinhaDeComando
4 {
5 /* Método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Algum valor foi passado para a linha de comando ?
9 if (argumentos.length == 0)
10 System.out.println("Nenhum argumento foi passado.");
11 else // existe alguma coisa no array !
12 {
13 for(int u=0;u<argumentos.length;u++) // imprime todos os argumentos
14 System.out.println("Argumento :"+(u+1)+":"+argumentos[u]);
15 }
16 } // fim do método main
17 } // fim da classe DemoLinhaDeComando
18
19 /* Para testar este programa, execute-o com os seguintes comandos:
20 java DemoLinhaDeComando
21 java DemoLinhaDeComando 1
22 java DemoLinhaDeComando a b c
23 */

10.3 Arrays Multidimensionais


Os exemplos de arrays vistos até agora são unidimensionais: um único índice é usado para determinar qual
dos elementos do array será acessado. Podemos também construir arrays multidimensionais, onde para
acessarmos um elemento precisaremos de mais do que um índice para identificá-lo.

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.

Na figura10.2 vemos, à esquerda, um array de caracteres de duas dimensões, cujo tamanho é 9 ⇥ 3. À


direita vemos uma representação de um array de três dimensões, onde cada elemento deve ser indicado por
três valores.

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

’a’ ’p’ ’c’ ’t’ ’ ’ ’z’ ’f’ ’l’ ’m’

’c’ ’6’ ’x’ ’w’ ’9’ ’@’ ’e’ ’k’ ’o’

’n’ ’!’ ’u’ ’1’ ’$’ ’j’ ’y’ ’/’ ’I’

Figura 10.2: Exemplo de arrays multidimensionais

Listagem 10.11: Um programa que demonstra o uso de arrays multidimensionais


1 /* Esta classe demonstra usos de arrays multidimensionais */
2 class DemoArraysMultidimensionais
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Declaramos um array de doubles duas dimensões, tamanho ainda desconhecido
8 double matriz[][];
9 int larg; // largura do array
10 int alt; // altura do array
11 // Lemos as dimensões do teclado
12 System.out.print("Entre a largura do array:");
13 larg = Keyboard.readInt();
14 System.out.print("Entre a altura do array:");
15 alt = Keyboard.readInt();
16 // Aqui alocamos memória para o array - note que cada dimensão tem um par
17 // de colchetes correspondentes
18 matriz = new double[alt][larg];
19 // Faremos uma iteração em todos os elementos do array para entrar seus dados
20 for(int linha=0; linha<alt; linha++)
21 for(int coluna=0; coluna<larg; coluna++)
22 {
23 // Uma mensagem é formatada para que os índices aparecam de forma "natural"
24 System.out.print("Entre o valor ["+(linha+1)+"]["+(coluna+1)+"]:");
25 matriz[linha][coluna] = Keyboard.readDouble();
26 } // fim dos laços
27 // Podemos imprimir o array com um laço duplo semelhante ao acima:
28 for(int linha=0; linha<alt; linha++)
29 {
30 for(int coluna=0; coluna<larg; coluna++)
31 // Imprimimos o dado e uma tabulação
32 System.out.print(matriz[linha][coluna]+"\t");
33 System.out.println(); // Ao fim de cada coluna, quebramos a linha
34 } // fim do laço para as linhas
35 } // fim do método main
36 } // fim da classe DemoArraysMultidimensionais

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

Listagem 10.12: Uma classe que encapsula um tabuleiro de jogo de damas


1 /* Esta classe encapsula o comportamento básico de um jogo de damas */
2 class JogoDeDamas
3 {
4 private char tabuleiro[][];
5 /* Construtor, que aloca memória para o tabuleiro e inicializa as casas */
6 JogoDeDamas()
7 {
8 // Alocação é simples, o tabuleiro tem sempre 8x8 posições
9 tabuleiro = new char[8][8];
10 // Para ter certeza, vamos inicializar todas as peças do tabuleiro
11 for(int l=0;l<8;l++)
12 for(int c=0;c<8;c++)
13 tabuleiro[l][c] = ’.’; // inicializadas com pontos
14 // Inicialmente, todas as peças estão em posições pré-definidas:
15 for(int l=0;l<=1;l++)
16 for(int c=0;c<8;c++)
17 tabuleiro[l][c] = ’o’; // peças normais de um jogador
18 for(int l=6;l<=7;l++)
19 for(int c=0;c<8;c++)
20 tabuleiro[l][c] = ’x’; // peças normais do outro jogador
21 } // fim do construtor
22 /* Método que retorna uma String representando o tabuleiro. Esta String terá várias
23 linhas, para que a impressão fique decente. */
24 public String toString()
25 {
26 String resultado = ""; // deve ser inicializada !
27 for(int l=0;l<8;l++)
28 {
29 for(int c=0;c<8;c++)
30 resultado += tabuleiro[l][c]; // o tabuleiro naquela posição
31 // Incluimos uma quebra de linha no final de cada linha do tabuleiro
32 resultado += "\n";
33 }
34 return resultado;
35 } // fim do método toString
36 } // fim da classe JogoDeDamas

10.3.1 Arrays Irregulares


Uma característica interessante da maneira em que arrays multidimensionais são implementados em Java
é que os arrays não precisam ter o mesmo número de valores para cada dimensão, ou seja, é possível de-
clararmos arrays que sejam irregulares. Por exemplo, um array irregular bidimensional poderia ter cinco
linhas, e cada linha pode ter um número diferente de colunas - não é obrigatório que cada linha tenha o
mesmo número de colunas.

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

de arrays irregulares é mostrado na listagem 10.13.

Listagem 10.13: Um programa que demonstra o uso de arrays multidimensionais irregulares


1 /* Esta classe demonstra usos de arrays irregulares */
2 class DemoArraysIrregulares
3 {
4 /* Método que permite a execução da classe */
5 public static void main(String argumentos[])
6 {
7 // Declaramos um array de doubles duas dimensões, tamanho ainda desconhecido
8 int mi[][];
9 int linhas; // Variável para conter o número de linhas no array
10 // Lemos as dimensões do teclado
11 System.out.print("Entre o número de linhas do array:");
12 linhas = Keyboard.readInt();
13 // Aqui alocamos memória para o array, mas somente para o número de linhas
14 // pedidas - para cada linha, um número diferente de colunas será usado
15 mi = new int[linhas][];
16 // Faremos uma iteração em todas as linhas do array para alocar um certo
17 // número de colunas
18 for(int linha=0; linha<linhas; linha++)
19 {
20 mi[linha] = new int[linha+1];
21 // Agora que a linha está alocada completamente, vamos inicializr os valores
22 for(int coluna=0; coluna<linha+1; coluna++)
23 mi[linha][coluna] = coluna;
24 }
25 // Faremos uma iteração em todos os elementos do array para entrar seus dados
26 for(int linha=0; linha<linhas; linha++)
27 {
28 // Imprimimos informações gerais sobre a linha do array irregular: note que
29 // podemos usar a variável interna length da forma abaixo:
30 System.out.println("A linha "+linha+" tem "+mi[linha].length+" colunas.");
31 System.out.print("Os valores são: ");
32 // Para cada linha, imprimimos as colunas
33 for(int coluna=0; coluna<linha+1; coluna++)
34 System.out.print(mi[linha][coluna]+"\t");
35 System.out.println(); // Quebra de linha ao final da impressão da linha
36 }
37 } // fim do método main
38 } // fim da classe DemoArraysIrregulares

10.4 Arrays de instâncias de classes


Assim como arrays podem representar várias variáveis de um mesmo tipo em uma única estrutura com um
único nome, podemos representar várias instâncias de uma classe em um array. Um exemplo ilustrativo de

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.

0 {nome:"José" idade:25 telefone:5552010}


1 {nome:"Maria" idade:22 telefone:5124005}
2 {nome:"Ilich" idade:31 telefone:8493819}
3 {nome:"Helga" idade:21 telefone:6495032}
Figura 10.4: Exemplo de arrays de instâncias de classes

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.

Listagem 10.14: A classe Pessoa


1 /* Classe que representa os dados de uma pessoa em uma agenda */
2 class Pessoa
3 {
4 // Variáveis representadas pela classe
5 private String nome;
6 private byte idade;
7 private int telefone;
8 /* Um construtor vazio - veremos a necessidade dele quando formos criar um array
9 de instâncias desta classe */
10 Pessoa()
11 {
12 }
13 /* Um construtor que inicializa todos os dados da classe através do método inicializa */
14 Pessoa(String n,byte i,int t)
15 {
16 inicializa(n,i,t);
17 }
18 /* Um método para inicializar os dados diretamente */
19 void inicializa(String n,byte i,int t)
20 {
21 nome = n;
22 idade = i;
23 telefone = t;
24 }
25 /* Um método para retornar o conteúdo da classe como uma String */
26 public String toString()
27 {
28 String x = "Nome:"+nome;
29 x += " idade:"+idade;
30 x += " telefone:"+telefone;
31 return x;
32 }
33 } // fim da classe Pessoa

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

Listagem 10.17: Uma classe que demonstra o uso da classe ListaDePessoas


1 /* Esta classe demonstra o uso da classe ListaDePessoas, que encapsula um array
2 de instâncias da classe Pessoa */
3 class DemoListaDePessoas
4 {
5 /* Método que permite a execução da classe */
6 public static void main(String argumentos[])
7 {
8 // Criamos uma instância da classe ListaDePessoas
9 ListaDePessoas festaDoBolinha = new ListaDePessoas(4);
10 // Criamos e inicializamos quatro instâncias da classe Pessoa
11 Pessoa b = new Pessoa("Bolinha",(byte)11,3104972);
12 Pessoa g = new Pessoa("Glorinha",(byte)10,3945123);
13 Pessoa r = new Pessoa("Raposo",(byte)12,6487325);
14 Pessoa l = new Pessoa("Luluzinha",(byte)10,4981027);
15 // Colocamos as quatro instâncias da classe Pessoa na instância da ListaDePessoas.
16 festaDoBolinha.setaDados(0,b);
17 festaDoBolinha.setaDados(1,g);
18 festaDoBolinha.setaDados(2,r);
19 festaDoBolinha.setaDados(3,l);
20 // Imprimimos todo o conteúdo da instância
21 System.out.println(festaDoBolinha);
22 }
23 } // fim da classe DemoListaDePessoas

É 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

10.5 Exercícios do capítulo 10


Exercício 10.1: ?
Escreva um programa em Java que crie um array de valores de ponto flutuante de 150 posições, calcule
o fatorial de cada uma destas posições e guarde o valor do fatorial no elemento correspondente do array.
Ao final do cálculo, a posição 0 do array deve conter 0, a posição 1 deve conter 1, a posição 2 deve conter
2, a posição 3 deve conter 6, a posição 4 deve conter 24 (4!), etc. Use a classe ProbabilidadeBasica
(listagem 8.15) para os cálculos.

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.

Dica: veja os exercícios 10.23 e 10.24.

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:

1. Considere o valor a ser procurado como sendo S.


2. Considere o primeiro valor do array como sendo F e seu índice iF.
3. Considere o último valor do array como sendo L e seu índice iL.
4. Localize o elemento cujo índice esteja no meio do array (exatamente entre as posições iF e iL).
Considere este valor como sendo M e seu índice iM.
5. Se S > M, faça iF = iM, faça F = M e vá para o passo 4.
6. Se S < M, faça iL = iM, faça L = M e vá para o passo 4.
7. Se S == M, S == F ou S == L termine o algoritmo retornando a posição onde o valor S foi encon-
trado (respectivamente iM, iF ou iL).
8. Se a diferença entre iF e iL for 1, termine o algoritmo retornando 1 (significando que o valor não
foi encontrado).

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:

• Mais dois pontos se a posição for a central,


• Mais um ponto se a posição for nos quatro cantos da matriz,
• Menos dois pontos se já houver uma ou mais peças do adversário na linha, coluna ou diagonal onde
a posição se encontra,
• Mais quatro pontos se a posição impedir a vitória do adversário,
• Mais quatro pontos se a posição levar a uma vitória,
• Ao final do cálculo, escolher a posição que teve maior número de pontos.
Para exemplificar, considere a matriz abaixo que representa um jogo em andamento, onde o computador
joga com as peças ’O’:
X −1 −2 não

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

11.1 Funções Matemáticas em Java


A classe Math, presente em todas as máquinas virtuais Java, contém algumas constantes e vários métodos
estáticos para cálculo de funções matemáticas diversas. Por serem estáticos, estes métodos devem ser
chamados com o nome da classe, por exemplo, Math.random(). Este capítulo apresenta alguns destes
métodos.

11.2 Constantes da classe Math


• A constante Math.PI, do tipo double, corresponde ao valor mais próximo de π (3.141592653589793)
que pode ser representado por um valor do tipo double.
• A constante Math.E, do tipo double, corresponde ao valor mais próximo de e (a base dos logaritmos
naturais, 2.718281828459045) que pode ser representado por um valor do tipo double.

Exemplos de uso destas constantes são mostrados no programa na listagem 11.1.

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

11.3 Métodos de comparação e arredondamento da classe Math


• O método max() recebe dois valores como argumentos e retorna o maior dos dois valores. Este mé-
todo também é polimórfico, aceitando argumentos do tipo int, long, float e double. O valor retornado
será do tipo mais apropriado: por exemplo, se o método for chamado com um valor do tipo float e
outro do tipo int, o resultado será do tipo float.

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).

Exemplos de uso destes métodos são mostrados no programa na listagem 11.2.

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

11.4 Métodos trigonométricos da classe Math


• O método sin() retorna o valor do seno do ângulo especificado em radianos e passado como ar-
gumento para o método. Tanto o valor do ângulo quanto o valor de retorno do método são do tipo
double.
• O método cos() retorna o valor do coseno 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.

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.

Exemplos de uso destes métodos são mostrados no programa na listagem 11.3.

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

11.5 Métodos exponenciais da classe Math


• O método sqrt() retorna a raiz quadrada do valor passado como argumento. Tanto o valor passado
quanto o valor de retorno do método devem ser do tipo double.
• O método pow() recebe dois valores do tipo double como argumentos e retorna o valor do primeiro
elevado ao segundo, como um valor do tipo double. Existem restrições aos valores que podem ser
passados para este método: se o primeiro valor é igual a zero, o segundo deve ser maior do que zero.
Se o primeiro valor é menor ou igual a zero, o segundo valor não pode ter casas decimais. Caso um
destes casos ocorra, o método causará uma exceção java.lang.ArithmeticException. Exceções
são vistas no capítulo 12.
• O método log() retorna o logaritmo natural (base e) do valor passado como argumento. Tanto o
valor passado quanto o valor de retorno do método devem ser do tipo double. Se um valor negativo
for passado como argumento, o método retornará a constante especial do tipo double NaN (número
inexistente).
• O método exp() retorna o resultado do valor e elevado ao valor passado como argumento. Tanto o
valor passado quanto o valor de retorno do método devem ser do tipo double.

Exemplos de uso destes métodos são mostrados no programa na listagem 11.4.

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

11.6 Outros métodos da classe Math


• O método random() retorna um valor pseudo-aleatório entre zero e um.

Exemplos de uso destes métodos são mostrados no programa na listagem 11.5.

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

11.7 Exercícios do capítulo 11


Exercício 11.1: ?
Escreva um programa que calcule a área de um círculo, usando o valor constante de π e o valor do raio
lido do teclado.

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.

Listagem 12.1: Vários erros de sintaxe em um programa exemplo


1 classe erro; // dois erros: "classe" em vez de "class" e linha terminada com ponto-e-vírgula
2 {
3 public stetic void main(char argc[]) // "stetic" ao invés de "static" e argumentos de tipo
4 // incorreto passados ao método main
5 {
6 For(boolean i=0;i<10;i++) // "For" com "F" maiúsculo, valores inválidos para booleans
7 println(j); // método println não existe, variável j também não
8 return false; // o método main não pode retornar valores pois é declarado como void
9 }
10 // falta fechar a classe com um "}" !

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

Listagem 12.2: Erros em potencial de um programa exemplo


1 /* Classe que demonstra 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 // Supomos que quatro argumentos serão passados para o programa, e podemos
8 // transformar estes argumentos em valores inteiros.
9 int a1 = Integer.parseInt(args[0]);
10 int a2 = Integer.parseInt(args[1]);
11 int b1 = Integer.parseInt(args[2]);
12 int b2 = Integer.parseInt(args[3]);
13 // Efetuamos uma operação simples com estes valores.
14 int resultado = a1/a2+b1/b2;
15 System.out.println("O resultado é "+resultado);
16 }
17 } // fim da classe DemoExcecoes

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.

Listagem 12.3: Correção dos erros em potencial de um programa exemplo


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 if (args.length == 4)
8 {
9 // Supomos que quatro argumentos serão passados para o programa, e podemos
10 // transformar estes argumentos em valores inteiros.
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 if ((a2 != 0) && (b2 != 0)) // então o erro de divisão não ocorrerá
16 {
17 // Efetuamos uma operação simples com estes valores.

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
151

18 int resultado = a1/a2+b1/b2;


19 System.out.println("O resultado é "+resultado);
20 } // fim do if que verifica se a2 ou b2 são iguais a zero
21 else // não podemos dividir, então imprimimos uma mensagem de erro
22 System.out.println("Erro: é impossível efetuar a divisão dos valores.");
23 } // fim do if que verifica se quatro argumentos foram passados
24 else // não existem quatro argumentos, então imprimimos uma mensagem de erro
25 System.out.println(args.length+" argumentos foram passados, 4 eram esperados.");
26 } // fim do método main
27 } // fim da classe DemoExcecoes

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.

12.2 O que são exceções ?


Java possibilita o controle de execução de blocos que contenham erros em potencial de outra maneira,
usando exceções. Exceções são objetos que são criados quando certas situações (geralmente erros) ocor-
rem em um programa ou classe quando este é executado. Exceções não correspondem diretamente à erros:
é possível usarmos algumas exceções para sinalizar condições especiais em rotinas, para que comandos
subsequentes possam usar esta informação para tratar estas condições - esta capacidade facilita a separa-
ção das classes, de forma que métodos de uma podem sinalizar à outras situações de erro de forma elegante.

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.

Listagem 12.4: Estrutura de um bloco try/catch/finally


1 try
2 {
3 // esta parte do código será executada, e caso haja alguma exceção ...
4 }
5 catch(ClasseDaExceção1 instância1)
6 {
7 // esta parte do código será executada caso a exceção seja da classe especificada
8 }
9 catch(ClasseDaExceção2 instância2)
10 {
11 // esta parte do código será executada caso a exceção seja da classe especificada
12 }
13 finally
14 {
15 // esta parte do código será executada independente da ocorrência de exceções
16 }

Algumas regras e informações sobre exceções são:

• 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.

Listagem 12.5: 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.
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 (Exception e) // se alguma exceção foi jogada, ela será pega por este bloco
20 { // é necessário passar uma instância de uma classe de exceções !
21 System.out.println("Uma exceção ocorreu: "+e);
22 }
23 } // fim do método main
24 } // fim da classe DemoExcecoes

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.

12.2.1 Tipos de exceções


Nos exemplos mostrados anteriormente, vemos que existem diversas classes de exceções, cujas instâncias
são criadas dentro dos blocos catch. A linguagem Java fornece vários tipos de exceções, implementados
em diferentes classes, que podem ser usados nos programas e classes.

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.

Algumas das classes de exceções mais usadas são:

• 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).

12.3 Usando exceções em classes desenvolvidas pelo programador


Métodos de classes desenvolvidas pelo programador podem lançar exceções usando a palavra-chave throw,
seguida de uma instância de uma exceção que pode ser criada com a palavra-chave new - quando uma
situação que gera exceções ocorrer, a exceção é lançada para que o código que chamou o método tome
conhecimento da situação. Isto é demonstrado na classe ArrayDeFloats da listagem 12.7.

Listagem 12.7: A classe ArrayDeFloats com métodos que lançam exceções


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 ArrayIndexOutOfBoundsException("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)
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 ArrayIndexOutOfBoundsException("Tentativa de setar elemento "+posição+

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
155

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 ArrayIndexOutOfBoundsException("Tentativa de acessar elemento "+posição+
29 " fora da faixa [0-"+(array.length-1)+"].");
30 }
31 } // fim da classe ArrayDeFloats

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.

Listagem 12.8: Uma classe que representa uma exceção


1 /* Uma classe que representa uma exceção de acesso à Arrays. Esta classe herda da
2 classe RuntimeException, indicando uma exceção que pode ser pega opcionalmente. */
3 class ExcecaoDeArrays extends RuntimeException
4 {
5 /* O construtor da classe recebe uma mensagem que será mostrada quando a exceção
6 ocorrer. */
7 ExcecaoDeArrays(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 ExcecaoDeArrays

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.

A classe ArrayDeFloats, modificada para usar exceções do tipo ExcecaoRigorosaDeArrays, é mostrada


na listagem 12.11.

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

20 } // fim do método main


21 } // fim da classe DemoArrayDeFloats

12.4 Exercícios do capítulo 12


Exercício 12.1: ?
Compile e execute o programa mostrado na listagem 12.5. Verifique os resultados que o programa dará
para a execução do programa como:
java DemoExcecoes 0 1 2
java DemoExcecoes a b c d
java DemoExcecoes 0 0 0 0
java DemoExcecoes 0 1 0 1
java DemoExcecoes

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

Entrada e Saída usando Arquivos

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.

Ainda em relação à forma de acesso dos arquivos, podemos classificá-los em:

• 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.

13.1.1 Acesso a arquivos em Java


Acesso a arquivos em Java é feito através da criação de instâncias de classes que representem os arquivos
e chamando métodos que permitam a leitura, gravação e manipulação dos arquivos. Desta forma, o acesso
direto ao arquivo somente pode ser feito por métodos específicos da classe, facilitando a interação com o
programa e protegendo os dados. Em alguns casos, é comum que existam mais de uma camada de classes
em volta de um arquivo: uma classe é responsável pela leitura em baixo nível do arquivo, e a classe que
encapsula esta classe é responsável pela “tradução” dos dados de baixo nível (caracteres ou bytes) para os
dados de nível mais alto (Strings ou instâncias de outras classes). Isto é mostrado na figura 13.1.

Classe que encapsula arquivo (nível mais alto)


Classe que encapsula arquivo Classe que encapsula arquivo Leitura de Strings ou
Leitura de bytes método
método instâncias de classes
ou caracteres método
Gravação de bytes Gravação de Strings ou
método método método
ou caracteres instâncias de classes
Arquivo
Arquivo

Figura 13.1: Encapsulamento de arquivos por classes


1 Classes que implementam arquivos de acesso aleatório não serão vistas nesta versão do livro, mas estarão presentes em
futuras versões.

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.

13.1.2 Sobre os arquivos usados neste capítulo


Para efeitos de ilustração e testes, alguns arquivos foram criados para uso nos programas e classes deste
capítulo. Estes arquivos fazem parte do pacote de distribuição deste documento, e foram compactados
juntamente com o arquivo do próprio livro. Verifique a distribuição original deste documento.

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.

13.2 Arquivos Sequenciais para Strings


Esta seção descreve as classes que implementam leitura e gravação de arquivos de texto usando Strings
para representar as linhas destes arquivos, de forma que a leitura e gravação seja feita sequencialmente.
Neste modo de acesso a arquivos, um ponteiro é criado e usado pela classe que encapsula o mecanismo
de acesso, de forma que depois de cada leitura ou gravação de Strings nos arquivos o ponteiro aponte para
a próxima posição de leitura. A figura 13.2 demonstra o funcionamento de ponteiros em um arquivo de
leitura.

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

Figura 13.2: Funcionamento de ponteiros em arquivos sequenciais de texto

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.

13.2.1 Leitura em arquivos sequenciais para Strings


A classe BufferedReader permite a leitura de Strings de arquivos de texto. A classe BufferedReader
implementa internamente um buffer de texto para leitura do arquivo: este buffer consiste de uma região
da memória especialmente reservada para minimizar o número de vezes que o acesso físico ao arquivo
será feito: cada vez que for necessário ler do arquivo, a classe verificará no buffer se a leitura é realmente
necessária, e ao ler, tentará ler do arquivo um número de caracteres suficientemente grande para que nas
próximas leituras o acesso seja feito à memória e não ao disco.

Alguns métodos úteis da classe BufferedReader são:


• BufferedReader(): o construtor da classe. Este construtor espera um argumento que é uma instân-
cia da classe FileReader, 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 leitura dos caracteres: um buffer maior pode fazer com que o acesso às linhas do arquivo seja
mais rápido, resultando em um programa mais eficiente, mas ao custo de mais memória em uso. O
tamanho default do buffer é 8192 bytes.
• readLine(): este método lê uma String completa do arquivo encapsulado pela instância da classe
BufferedReader e a retorna como resultado do método. A String será lida do arquivo até que seja
encontrado um caracter de nova linha (’\n’), retorno de carro (’\r’), uma combinação dos dois
ou o fim do arquivo seja encontrado. Quando o método não puder mais ler Strings do arquivo, ele
retornará o valor especial null, que pode ser usado para verificação de fim de arquivo. O caracter
terminador não é anexado à String.
• close(): este método fecha o arquivo associado com a instância da classe BufferedReader, fechan-
do também o arquivo associado com a instância da classe FileReader que foi usada para construir
a instância de BufferedReader.
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.1
mostra como podemos usar uma instância da classe BufferedReader para ler um arquivo de texto linha
por linha, até o fim do arquivo, calculando quantas linhas existem no arquivo.

Listagem 13.1: Um programa que lê as linhas de um arquivo como Strings


1 /* Este programa demonstra o uso da classe BufferedReader para ler Strings de
2 um arquivo. */
3 import java.io.*; // Esta linha é obrigatória - permite o uso das classes de I/O
4
5 class LeituraSequencialDeStrings
6 {
7 /* O método main permite a execução da classe */
8 public static void main(String args[])
9 {

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
163

10 String arquivo = "linux.words"; // o nome do arquivo é representado por uma String


11 int númeroDeLinhas = 0; // o número de linhas do arquivo é inicialmente zero
12 try // tenta abrir o arquivo, ler dados e fechá-lo
13 {
14 // Criamos uma instância da classe FileReader
15 FileReader fr = new FileReader(arquivo);
16 // E a usamos como argumento para o construtor da classe BufferedReader
17 BufferedReader br = new BufferedReader(fr);
18 boolean aindaTemMais = true; // enquanto não for fim de arquivo esta variável será true
19 while(aindaTemMais) // repetimos a leitura do arquivo enquanto aindaTemMais for true
20 {
21 String linha = br.readLine(); // lemos uma String do arquivo
22 if (linha == null) // se o resultado da leitura for null
23 aindaTemMais = false; // é sinal que o arquivo chegou ao fim
24 else // senão, podemos processar a linha lida
25 númeroDeLinhas++; // incrementamos o número de linhas lidas
26 } // quando acabarem as linhas (aindaTemMais for false) saímos do laço
27 // Fechamos a instância da classe BufferedReader, o que fechará automaticamente a
28 // instância da classe FileReader
29 br.close();
30 } // fim do bloco try
31 catch (FileNotFoundException e) // Se o arquivo não foi encontrado...
32 {
33 System.out.println("O arquivo não foi encontrado.");
34 }
35 catch (IOException e) // Se houve erros de I/O..
36 {
37 System.out.println("Houve um erro de leitura do arquivo.");
38 }
39 // Ao final, imprimimos o número de linhas lidas
40 System.out.println("O arquivo tem "+númeroDeLinhas+" linhas.");
41 }
42 } // fim da classe LeituraSequencialDeStrings

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

Listagem 13.3: Classe que representa um Livro de Livraria


1 /* Esta classe representa um livro de livraria. */
2 import java.io.*; // como vamos acessar métodos de classes de IO precisamos desta linha !
3
4 class LivroLivraria
5 {
6 /* Algumas variáveis privadas para representar o livro de livraria */
7 private String título,autor; // Título do livro e nome do autor
8 private short estoque; // Número de livros em estoque
9 private float pCompra,pVenda; // Preço de compra e venda
10 /* O construtor vazio para a classe LivroLivraria. É sempre uma boa idéia ter este
11 construtor, caso seja necessário alocar memória para uma instância sem inicializá-la. */
12 LivroLivraria()
13 {
14 }
15 /* O construtor para a classe LivroLivraria que recebe variáveis para inicialização. */
16 LivroLivraria(String tit,String aut,short est,float pc,float pv)
17 {
18 título = tit; autor = aut; estoque = est; pCompra = pc; pVenda = pv;
19 }
20 /* O construtor para a classe LivroLivraria que recebe uma instância da classe
21 BufferedReader como argumento. Este construtor tentará pegar os valores para
22 inicialização da instância de uma String a ser lida do BufferedReader.
23 Como é possível que não consigamos ler os dados do BufferedReader por alguma razão
24 (arquivo não aberto, ou sem dados), somos obrigados a declarar que o construtor pode
25 repassar a exceção para quem o chamou através da cláusula throws. Esta cláusula faz
26 o compilador esperar que a chamada ao construtor esteja dentro de um bloco try/catch. */
27 LivroLivraria(BufferedReader br) throws IOException
28 {
29 String registro = br.readLine(); // Lemos uma String do arquivo
30 título = registro.substring(0,49); // "Cortamos" o título do livro da String
31 autor = registro.substring(49,76); // "Cortamos" o nome do autor da String
32 // Para extrair o número de livros em estoque, temos que "cortar" a String,
33 // extrair os espaços em branco desnecessários com o método trim, criar uma instância
34 // da classe Short para representar o valor e finalmente pegar o valor da instância.
35 Short tempShort = new Short(registro.substring(76,79).trim());
36 estoque = tempShort.shortValue();
37 // Para extrair os preços dos livros efetuamos os mesmos passos mas usando a classe Float
38 Float tempFloatC = new Float(registro.substring(79,86).trim());
39 pCompra = tempFloatC.floatValue();
40 Float tempFloatV = new Float(registro.substring(86,93).trim());
41 pVenda = tempFloatV.floatValue();
42 }
43 /* Este método permite a impressão de instâncias da classe com System.out.println(). */
44 public String toString()
45 {
46 String res = "Título: \t"+título+"\n"; // Concatenamos os dados da classe em uma String
47 res = res + "Autor: \t"+autor+"\n";
48 res = res + "Estoque:\t"+estoque+"\n";
49 res = res + "Preço: \t"+pVenda;
50 return res; // e retornamos esta String
51 }
52 } // Fim da classe LivroLivraria

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.

Listagem 13.4: Programa que usa a classe LivroLivraria e lê os dados de um arquivo


1 /* Este programa demonstra o uso da classe BufferedReader para ler instâncias da classe
2 LivroLivraria de um arquivo. As instâncias serão lidas como Strings e decodificadas

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
165

3 por um construtor da classe LivroLivraria. */


4 import java.io.*; // Esta linha é obrigatória - permite o uso das classes de I/O
5
6 class LeituraSequencialDeLivros
7 {
8 /* O método main permite a execução da classe */
9 public static void main(String args[])
10 {
11 // Para evitar erros de escopo, inicializamos a instância que estaremos usando.
12 LivroLivraria lv = new LivroLivraria();
13 String arquivo = "estoquelivraria.dat"; // o nome do arquivo é representado por uma String
14 try // tenta abrir o arquivo, ler dados e fechá-lo
15 {
16 // Criamos uma instância da classe FileReader e a usamos no construtor da BufferedReader
17 BufferedReader br = new BufferedReader(new FileReader(arquivo));
18 for(int livro=0;livro<19;livro++) // temos 19 livros no nosso arquivo !
19 {
20 // Reinicializamos a instância lv através do construtor que aceita uma instância
21 // da classe BufferedReader
22 lv = new LivroLivraria(br);
23 System.out.println(lv); // Imprimimos a instância - o método toString será usado
24 }
25 // Fechamos a instância da classe BufferedReader
26 br.close();
27 } // fim do bloco try
28 catch (FileNotFoundException e) // Se o arquivo não foi encontrado...
29 {
30 System.out.println("O arquivo não foi encontrado.");
31 }
32 catch (IOException e) // Se houve erros de I/O..
33 {
34 System.out.println("Houve um erro de leitura do arquivo.");
35 }
36 } // fim do método main
37 } // fim da classe LeituraSequencialDeStrings

13.2.2 Gravação em arquivos sequenciais para Strings


A classe BufferedWriter permite a gravação de Strings em arquivos de texto, de maneira análoga à classe
BufferedReader. A classe BufferedWriter também implementa internamente um buffer de texto para
gravação no arquivo: todas as vezes que formos escrever no arquivo, os dados irão para o buffer. que só
será gravado fisicamente quando estiver cheio, minimizando o número de acessos à disco.

Alguns métodos úteis da classe BufferedWriter são:

• 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.

Listagem 13.5: Um programa que grava Strings em um arquivo


1 /* Este programa demonstra o uso da classe BufferedWriter para gravar Strings em
2 um arquivo. */
3 import java.io.*; // Esta linha é obrigatória - permite o uso das classes de I/O
4
5 class GravacaoSequencialDeStrings
6 {
7 /* O método main permite a execução da classe */
8 public static void main(String args[])
9 {
10 String arquivo = "saida.txt"; // o nome do arquivo é representado por uma String
11 System.out.println("Entre várias palavras, finalizando com uma String vazia");
12 try // tenta abrir o arquivo, ler dados e fechá-lo
13 {
14 // Criamos uma instância da classe FileWriter
15 FileWriter fw = new FileWriter(arquivo);
16 // E a usamos como argumento para o construtor da classe BufferedWriter
17 BufferedWriter bw = new BufferedWriter(fw);
18 while(true) // em princípio leremos as palavras do teclado para sempre...
19 {
20 String linha = Keyboard.readString(); // lemos uma String do teclado
21 if (linha.equals("")) break; // se for vazia, saímos do laço
22 else // a String não é vazia,
23 {
24 bw.write(linha); // escrevemos a String na saída
25 bw.newLine(); // escrevemos uma quebra de linha
26 }
27 } // este laço só terminará quando a condição do break ocorrer
28 // Fechamos a instância da classe BufferedWriter, o que fechará automaticamente a
29 // instância da classe FileWriter
30 bw.close();
31 } // fim do bloco try
32 catch (IOException e) // Se houve erros de I/O..
33 {
34 System.out.println("Houve um erro de leitura do arquivo.");
35 }
36 }
37 } // fim da classe GravacaoSequencialDeStrings

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

13.3 Arquivos Sequenciais para Tipos Nativos


As classes mostradas na seção anterior implementam leitura e gravação sequencial de Strings de arquivos -
para que possamos ler e escrever dados de tipos nativos como int, char, double, etc., precisamos converter
estes dados de e para Strings.

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

Figura 13.3: Funcionamento de ponteiros em arquivos sequenciais binários

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.

13.3.1 Leitura em arquivos sequenciais para dados de tipos nativos


A classe DataInputStream permite a leitura de dados de qualquer tipo nativo a partir de arquivos binários.
Alguns métodos úteis da classe DataInputStream são:

• 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.

Listagem 13.6: Um programa que lê valores do tipo float de um arquivo


1 /* Este programa demonstra o uso da classe DataInputStream para ler valores de tipos nativos
2 de um arquivo. */
3 import java.io.*; // Esta linha é obrigatória - permite o uso das classes de I/O
4
5 class LeituraSequencialDeFloats
6 {
7 /* O método main permite a execução da classe */
8 public static void main(String args[])
9 {
10 String arquivo = "floats.dat"; // o nome do arquivo é representado por uma String
11 // Inicializamos duas variáveis que conterão o maior e menor floats que serão lidos
12 // de um arquivo. Para inicializar o algoritmo, usamos os valores contrários.
13 float maior=Float.MIN_VALUE,menor=Float.MAX_VALUE;
14 try // tenta abrir o arquivo, ler dados e fechá-lo
15 {
16 // Criamos uma instância da classe FileInputStream
17 FileInputStream fis = new FileInputStream(arquivo);
18 // E a usamos como argumento para o construtor da classe DataInputStream
19 DataInputStream dis = new DataInputStream(fis);
20 while(true) // em princípio este laço se repetirá para sempre
21 {
22 float valor = dis.readFloat(); // lemos um único float do arquivo
23 if (dis.available() <= 0) // se depois da leitura não existirem mais bytes disponíveis,
24 break; // saímos do laço de leitura
25 else // senão, processamos o valor lido
26 {
27 if (valor > maior) maior = valor; // comparamos com o maior, e mudamos se for maior

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

13.3.2 Gravação em arquivos sequenciais para dados de tipos nativos


A classe DataOutputStream permite a gravação de dados de qualquer tipo nativo em arquivos binários.
Alguns métodos úteis da classe DataOutputStream são:

• DataOutputStream(): o construtor da classe. Este construtor espera um argumento que é uma


instância da classe FileOutputStream, que por sua vez será criada usando um nome de arquivo
como argumento.
• writeBoolean(): este método recebe como argumento e grava um valor do tipo boolean no arquivo.
• writeChar(): este método recebe como argumento e grava um valor do tipo char no arquivo.
• writeByte(): este método recebe como argumento e grava um valor do tipo byte no arquivo.
• writeShort(): este método recebe como argumento e grava um valor do tipo short no arquivo.
• writeInt(): este método recebe como argumento e grava um valor do tipo int no arquivo.
• writeLong(): este método recebe como argumento e grava um valor do tipo long no arquivo.
• writeFloat(): este método recebe como argumento e grava um valor do tipo float no arquivo.
• writeDouble(): este método recebe como argumento e grava um valor do tipo double no arquivo.
• writeUTF(): este método recebe como argumento e grava uma String no arquivo. Esta String
estará 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 gravar Strings se estas forem lidas posteriormente no
formato UTF - veja o método readUTF da classe DataInputStream na seção 13.3.1.
• flush(): este método sem argumentos força a gravação de quaisquer valores que ainda não tenham
sido gravados no arquivo.
• close(): este método fecha o arquivo associado com a instância da classe DataOutputStream,
fechando também o arquivo associado com a instância da classe FileOutputStream que foi usada
para construir a instância de DataOutputStream. Antes de fechar o arquivo, este método executa o
método flush() descrito anteriormente.

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

58 if (éEspecial) saldo = saldo - valor; // retira o valor


59 }
60 else // o valor não é maior que o saldo
61 saldo = saldo - valor; // retira o valor
62 }
63 /* Este método retorna o saldo da conta bancária */
64 float retornaSaldo()
65 {
66 return saldo;
67 }
68 /* Este método retorna o número da conta bancária */
69 int retornaNúmero()
70 {
71 return número;
72 }
73 /* Este método concatena os dados da conta bancária em uma String para impressão */
74 public String toString()
75 {
76 String res = nome+" "+número+" "+saldo;
77 if (éEspecial) res += " (conta especial)";
78 return res;
79 }
80 } // fim da classe ContaBancaria

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

32 } // fim do bloco try


33 catch (IOException e) // Se houve erros de I/O..
34 {
35 System.out.println("Houve um erro de gravação no arquivo.");
36 }
37 } // fim do método main
38 } // fim da classe CriaArqContaBancaria

13.4 Exercícios do capítulo 13


Exercício 13.1: ?
Modifique o programa na listagem 13.1 para que o nome do arquivo seja passado pela linha de comando.
O programa não deve ser executado se nenhum argumento ou mais do que um argumento forem passados
pela linha de comando.

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

Estruturas de Dados Básicas em Java

14.1 A classe Vector


14.2 A classe Hashtable

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
178

Apêndice A

Tipos de Dados em Java

A.1 Tipos de dados nativos em Java


Java possui vários tipos de dados nativos ou primitivos, que podem ser usados diretamente em programas
e classes, tanto para armazenamento de variáveis quando para operações simples. Por não serem imple-
mentados como classes, as operações possíveis com estes tipos são pouco flexíveis mas para compensar
estes tipos são eficientes no uso de memória e processamento. Os tipos nativos de Java serão apresentados
a seguir.

A.1.1 O tipo básico byte


Variáveis do tipo byte podem representar valores inteiros na faixa -128 a 127, que podem ser atribuídos
diretamente ou através de operações. Alguns exemplos de uso do tipo básico byte são mostrados no pro-
grama na listagem A.1.

Listagem A.1: Programa que demonstra usos do tipo byte


1 /* Esta classe demonstra usos do tipo byte */
2 class DemoByte
3 {
4 public static void main(String argumentos[])
5 {
6 byte b1,b2; // declaração das variáveis
7 b1 = -1; // b1 valerá -1
8 b2 = 123-2; // b2 valerá 121
9 byte b3 = 122-123; // b3 valerá -1
10 byte b4 = 12*10; // b4 valerá 120
11 byte b5 = 12/10; // b5 valerá 1 (divisão com valores inteiros)
12 }
13 }

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.

Listagem A.2: Programa que demonstra usos incorretos do tipo byte


1 /* Esta classe demonstra usos incorretos do tipo byte */
2 class DemoByte
3 {
4 public static void main(String argumentos[])
5 {
6 byte b1,b2,b3; // declaração das variáveis
7 b1 = 123456; // ERRO DE COMPILAÇÃO: valor fora da faixa válida para bytes
8 b2 = 1.24; // ERRO DE COMPILAÇÃO: valor de ponto flutuante
9 b3 = 12000.24; // ERRO DE COMPILAÇÃO: valor de ponto flutuante
10 byte b4 = true; // ERRO DE COMPILAÇÃO: constante do tipo boolean
11 byte b5 = 10; // Compilação sem problemas
12 byte b6 = b5*b5; // ERRO DE COMPILAÇÃO: resultado da operação * é do tipo int
13 }
14 }

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:

Listagem A.3: Programa que demonstra cast (conversão) de tipos


1 /* Esta classe demonstra exemplos de cast (conversão) do tipo byte */
2 class DemoByte
3 {
4 public static void main(String argumentos[])
5 {
6 byte x1,x2; // declaração das variáveis
7 x1 = (byte)123456; // converte 123456 para 64
8 x2 = (byte)1.24; // converte 1.24 para 1
9 byte x3 = (byte)12000.24; // converte 12000.24 para -32
10 byte x4 = (byte)true; // ERRO DE COMPILAÇÃO: impossível converter para byte
11 }
12 }

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:

123456 em 32 bits: 00000000000000011110001001000000


24 bits superiores eliminados ........................01000000 Resultado: 64

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:

12000 em 32 bits: 00000000000000000010111011100000


24 bits superiores eliminados ........................11100000 Resultado: -32

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.

A.1.2 O tipo básico char


O tipo char representa um único caracter em Java. Diferente de outras linguagens de programação, Java
representa um caracter com dois bytes, possibilitando a representação de caracteres em várias línguas si-
multaneamente, não somente como caracteres a serem lidos, processados ou impressos, mas como parte
dos próprios programas em Java1 . O suporte para línguas estrangeiras é dado pelo sistema operacional -
nem todos os caracteres poderão ser usados em qualquer sistema.

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:

Listagem A.4: Programa que demonstra usos do tipo char


1 /* Esta classe demonstra usos do tipo char */
2 class DemoChar
3 {
4 public static void main(String argumentos[])
5 {
6 char c1,c2,c3,c4; // declaração das variáveis
7 c1 = ’a’; // caracter ASCII normal
8 c2 = ’!’; // caracter ASCII normal (símbolo)
9 c3 = ’ã’; // caracter especial (português)
10 c4 = ’ß’; // caracter especial (alemão)
11 char c5 = ’a’+1; // operação válida: resultado ’b’
12 char c6 = ’B’-1; // operação válida: resultado ’A’
13 char c7 = 123; // valor especificado diretamente: caracter ’{’
14 char c8 = 7; // valor especificado diretamente: sinal sonoro
15 char c9 = ’7’; // caracter ASCII ’7’ - diferente do sinal sonoro
16 }
17 }

Alguns exemplos de uso incorreto para variáveis do tipo char são mostrados no programa na listagem A.5.

Listagem A.5: Programa que demonstra usos incorretos do tipo char


1 /* Esta classe demonstra usos incorretos do tipo char */
2 class DemoChar
3 {
4 public static void main(String argumentos[])
1 Caracteresnão-alfanuméricos (acentos, letras estrangeiras, símbolos especiais, etc.) podem até aparecer em nomes de clas-
ses, métodos e variáveis, mas na prática deve-se evitar o uso de caracteres não-alfanuméricos para nomes de classes para evitar
problemas com o sistema de arquivos dos computadores, que podem não reconhecer nomes de arquivos com estes caracteres.

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.

A.1.3 O tipo básico short


Variáveis do tipo short podem representar valores inteiros com 16 bits de precisão, na faixa -32768
a 32767. Variáveis deste tipo podem receber valores diretamente ou através de operações, como mos-
trado no programa na listagem A.6.

Listagem A.6: Programa que demonstra usos do tipo short


1 /* Esta classe demonstra usos do tipo short */
2 class DemoShort
3 {
4 public static void main(String argumentos[])
5 {
6 short s1,s2,s3; // declaração das variáveis
7 s1 = 1000; // s1 valerá 1000
8 s2 = 1-1000; // s2 valerá -999
9 s3 = 100*100; // s3 valerá 10000
10 short s4 = ’A’; // s4 valerá 65 (valor do caracter ’A’)
11 short s5 = s3; // s5 valerá 10000
12 short s6 = 1999/10; // s6 valerá 199 (divisão com valores inteiros)
13 short s7 = -’A’; // não-convencional mas válido: s7 valerá -65.
14 }
15 }

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

Listagem A.7: Programa que demonstra usos incorretos do tipo short


1 /* Esta classe demonstra usos incorretos do tipo short */
2 class DemoShort
3 {
4 public static void main(String argumentos[])
5 {
6 short s1,s2; // declaração das variáveis
7 s1 = 123456; // ERRO: valor fora da faixa válida para shorts
8 s2 = 100.1; // ERRO: valor de ponto flutuante
9 short s3 = true; // ERRO: constante de tipo boolean
10 short s4 = "A"; // ERRO: "A" não é um caracter, não pode ser convertido
11 short s5 = 999*999; // ERRO: resultado fora da faixa válida para shorts
12 }
13 }

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.

A.1.4 O tipo básico int


Variáveis do tipo básico int podem representar valores numéricos inteiros que estejam dentro da faixa
-2147483648 a 2147483647, usando 4 bytes para representá-los. Alguns exemplos de uso de variáveis do
tipo int são mostrados no programa na listagem A.8.

Listagem A.8: Programa que demonstra usos do tipo int


1 /* Esta classe demonstra usos do tipo int */
2 class DemoInt
3 {
4 public static void main(String argumentos[])
5 {
6 int i1,i2; // declaração das variáveis
7 i1 = -1000000; // i1 valerá -1000000
8 i2 = -i1*2; // i2 valerá 2000000
9 int i3 = i1+i2; // i3 valerá 1000000
10 int i4 = 123*200; // i4 valerá 24600
11 int i5 = 123/200; // i5 valerá 0 (divisão com valores inteiros)
12 int i6,i7; // declaração das variáveis
13 i6 = 123/120; // i6 valerá 1 (divisão com valores inteiros)
14 i7 = ’X’; // i7 valerá 88 (valor do caracter ’X’)
15 }
16 }

Alguns exemplos de uso incorreto de variáveis do tipo int são mostrados no programa na listagem A.9.

Listagem A.9: Programa que demonstra usos incorretos do tipo int


1 /* Esta classe demonstra usos incorretos do tipo int */
2 class DemoInt
3 {
4 public static void main(String argumentos[])
5 {
6 int i1,i2; // declaração das variáveis
7 i1 = 99999*99999; // ERRO GRAVE: Compilador não gerará erro, mas
8 // resultado será -1409865409 ao invés de 999998000001

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
183

9 i2 = 0.00001; // ERRO: valor de ponto flutuante


10 int i3 = true; // ERRO: constante do tipo boolean
11 int i4 = "X"; // ERRO: "X" não é um caracter, não pode ser convertido
12 }
13 }

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.

A.1.5 O tipo básico long


Variáveis do tipo básico long podem representar valores numéricos inteiros que estejam dentro da faixa
de valores -9223372036854775808 a 9223372036854775807, usando 8 bytes para representá-los. Alguns
exemplos de uso de variáveis do tipo long são mostrados no programa na listagem A.10.

Listagem A.10: Programa que demonstra usos do tipo long


1 /* Esta classe demonstra usos do tipo long */
2 class DemoLong
3 {
4 public static void main(String argumentos[])
5 {
6 long l1,l2,l3; // declaração das variáveis
7 l1 = 9999999999; // l1 valerá 1410065407
8 l2 = (long)9999999999; // l2 valerá 1410065407 (valor é considerado inteiro antes do cast)
9 l3 = 9999999999L; // l3 valerá 9999999999 (valor é considerado long)
10 long l4 = l3*999999; // l4 valerá 9999989999000001
11 long l5 = 1/2; // l5 valerá 0 (divisão com valores inteiros)
12 long l6,l7; // declaração das variáveis
13 l6 = 13/2; // l6 valerá 2 (divisão com valores inteiros)
14 l7 = ’A’*’B’*’C’; // l7 valerá 287430 (multiplicação dos valores 65,66 e 67)
15 }
16 }

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.

Listagem A.11: Programa que demonstra usos incorretos do tipo long


1 /* Esta classe demonstra usos incorretos do tipo long */
2 class DemoLong
3 {
4 public static void main(String argumentos[])
5 {
6 long l1,l2,l3,l4; // declaração das variáveis
7 l1 = 3.1415926536; // ERRO: valor de ponto flutuante, cast é necessário.
8 l2 = 10000*10000.1; // ERRO: um dos valores é ponto flutuante, cast necessário.
9 l3 = 9999999999999999L; // l3 valerá 9999999999999999 (veja o "L")
10 l4 = l3*l3; // ERRO DE OVERFLOW: l4 valerá -8834407033341083647

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
184

11 long l5,l6,l7; // declaração das variáveis


12 l5 = true; // ERRO: constante é boolean, cast não é possível.
13 l6 = "1234567890"; // ERRO: constante é String, cast não é possível.
14 l7 = (long)3000000000; // ERRO: o compilador não aceita o valor 3000000000, mesmo com o cast
15 }
16 }

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.

A.1.6 O tipo básico float


Variáveis do tipo básico float podem representar valores numéricos com ponto flutuante que estejam den-
tro da faixa 1.40129846432481707e-45 a 3.40282346638528860e+38 (positivos e negativos)2 mas sem
precisão exata. O tipo básico float usa a mesma memória do tipo int (4 bytes), mas os valores são
arredondados. Alguns exemplos de uso de variáveis do tipo float são mostrados no programa na lista-
gem A.12.

Listagem A.12: Programa que demonstra usos do tipo float


1 /* Esta classe demonstra usos do tipo float */
2 class DemoFloat
3 {
4 public static void main(String argumentos[])
5 {
6 float f1,f2,f3,f4,f5,f6; // declaração das variáveis
7 f1 = (float)3.1415926536; // f1 valerá 3.1415927 - note o arredondamento
8 f2 = 3.1415926536F; // f2 valerá 3.1415927 - note o arredondamento
9 f3 = f1-f2; // f3 valerá 0
10 f4 = 1/2; // f4 valerá 0 !
11 f5 = 1F/2; // f5 valerá 0.5
12 f6 = 1/2F; // f6 valerá 0.5
13 float f7,f8; // declaração das variáveis
14 f7 = ’A’*’B’*’C’; // f7 valerá 287430.0 (multiplicação dos
15 // valores 65,66 e 67)
16 f8 = 1F/’2’; // f8 valerá 0.02 (divide 1.0 pelo caracter ’A’
17 // que vale 50)
18 }
19 }

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.

Listagem A.13: Programa que demonstra usos incorretos do tipo float


1 /* Esta classe demonstra usos incorretos do tipo float */
2 class DemoFloat
3 {
4 public static void main(String argumentos[])
5 {
6 float f1,f2,f3,f4,f5; // declaração das variáveis
7 f1 = 1234567890; // f1 valerá 1.23456794E9 - note o arredondamento
8 f2 = 123456.0000000001F; // f2 valerá 123456.0 - note o arredondamento
9 f3 = (1f/7)+(1f/7)+(1f/7)-(3f/7); // f3 valerá 2.9802322E-8 - note o arredondamento
10 f4 = false; // ERRO: constante é um boolean, cast impossível
11 f5 = "3.1416"; // ERRO: constante é uma String, cast impossível
12 }
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.

A.1.7 O tipo básico double


Variáveis do tipo básico double podem representar valores numéricos com ponto flutuante que estejam
dentro da faixa 4.94065645841246544e-324 a 1.79769313486231570e+308 (positivos e negativos) mas
sem precisão exata. O tipo básico double usa a mesma memória do tipo long (8 bytes), mas os valores
são arredondados. Alguns exemplos de uso de variáveis do tipo double são mostrados no programa na
listagem A.14.

Listagem A.14: Programa que demonstra usos do tipo double


1 /* Esta classe demonstra usos do tipo double */
2 class DemoDouble
3 {

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
186

4 public static void main(String argumentos[])


5 {
6 double d1,d2,d3,d4,d5,d6; // declaração das variáveis
7 d1 = 1.2345678901; // d1 valerá 1.2345678901 - armazenado exato
8 d2 = 1.234567890123456789; // d2 valerá 1.2345678901234567 - armazenado arredondado
9 d3 = d1+999999; // d3 valerá 1000000.2345678901 - armazenado arredondado
10 d4 = 1/2; // d4 valerá 0! : divisão de inteiros
11 d5 = 1./2; // d5 valerá 0.5
12 d6 = 1/2d; // d6 valerá 0.5
13 double d7,d8,d9; // declaração das variáveis
14 d7 = 1./’2’; // d7 valerá 0.02 (divide 1.0 pelo caracter ’A’
15 // que vale 50)
16 d8 = 1e72; // d8 valerá 1x10^72 ou 1E72
17 d9 = 1000000000000000000000000000000000000000000000000000000000000000000000000.;
18 // d9 também valerá 1x10^72 ou 1E72
19 }
20 }

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.

Listagem A.15: Programa que demonstra usos incorretos do tipo double


1 /* Esta classe demonstra usos incorretos do tipo double */
2 class DemoDouble
3 {
4 public static void main(String argumentos[])
5 {
6 double d1,d2,d3,d4; // declaração das variáveis
7 d1 = 1000000.000000000001D; // d1 valerá 1000000.0 - note o arredondamento
8 d2 = (1/987654.)+(2/987654.)-(3/987654.);
9 // d2 valerá 4.2351647362715017E-22 - note o
10 // arredondamento
11 d3 = false; // ERRO: constante é um boolean, cast impossível
12 d4 = "3.1416"; // ERRO: constante é uma String, cast impossível
13 }
14 }

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.

A.1.8 O tipo básico boolean


Variáveis do tipo básico boolean podem representar valores booleanos (verdadeiros ou falsos). Java define
duas constantes, true e false, que representam os valores verdadeiro e falso, respectivamente. Alguns
exemplos de uso de variáveis do tipo double são mostrados no programa na listagem A.16.

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
187

Listagem A.16: Programa que demonstra usos do tipo boolean


1 /* Esta classe demonstra usos do tipo boolean */
2 class DemoBoolean
3 {
4 public static void main(String argumentos[])
5 {
6 boolean b1,b2,b3; // declaração das variáveis
7 b1 = true; // b1 recebe a constante true
8 b2 = (1>2); // valor lógico de uma expressão (false)
9 b3 = (2+3 == 6); // comparação de expressões (false)
10 boolean b4 = (1<2) && (3<4); // "E" lógico de duas expressões (true)
11 boolean b5 = (1<2) || (3<2); // "OU" lógico de duas expressões (true)
12 boolean b6 = !(true); // "NÃO" lógico de uma constante (false)
13 }
14 }

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.

Listagem A.17: Programa que demonstra usos incorretos do tipo boolean


1 /* Esta classe demonstra usos incorretos do tipo boolean */
2 class DemoBoolean
3 {
4 public static void main(String argumentos[])
5 {
6 boolean b1,b2,b3; // declaração das variáveis
7 b1 = 0; // ERRO: tipo diferente de boolean
8 b2 = (boolean)0; // ERRO: cast de int para boolean impossível
9 b3 = FALSE; // ERRO: constante não definida
10 boolean b4 = ’F’; // ERRO: tipo diferente de boolean
11 boolean b5 = "FALSE"; // ERRO: tipo diferente de boolean
12 boolean b6 = (boolean)"F"; // ERRO: cast de int para boolean impossível
13 }
14 }

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).

A.2 Algumas das classes mais usadas de Java para representação de


dados
A.2.1 A classe String
A classe String é uma classe de Java que permite a representação de cadeias de caracteres ou Strings de
maneira simples3 e eficiente. Alguns exemplos de uso de instâncias da classe String são mostrados no
3 Apesar de ser uma classe, não é necessário inicializarmos as instâncias da classe String com o comando new.

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
188

programa na listagem A.18:

Listagem A.18: Programa que demonstra usos da classe String


1 /* Esta classe demonstra usos da classe String e suas instâncias */
2 class DemoString
3 {
4 public static void main(String argumentos[])
5 {
6 String s1,s2,s3; // declaração das variáveis
7 s1 = ""; // s1 valerá "" (String vazia)
8 s2 = " "; // s2 valerá " " (espaço simples)
9 s3 = " "; // s3 valerá " " (dois espaços simples)
10 String s4 = "AB"; // s4 valerá "AB"
11 String s5 = s4+"C"; // s5 valerá "ABC"
12 String s6 = "1"+"2"+"3"; // s6 valerá "123" (não-numérico)
13 String s7 = "\""; // s7 valerá """ (um caracter: aspas)
14 }
15 }

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

Listagem A.19: Programa que demonstra usos de concatenação da classe String


1 /* Esta classe demonstra usos e formas de concatenação da classe String */
2 class DemoString
3 {
4 public static void main(String argumentos[])
5 {
6 String s1,s2,s3,s4,s5,s6; // declaração das variáveis
7 s1 = 0+""; // s1 valerá "0" (não-numérico)
8 s2 = 1+s1; // s2 valerá "10" (não-numérico)
9 s3 = 1+2+s1; // s3 valerá "30" (não-numérico) - soma primeiro
10 s4 = s1+1+2; // s4 valerá "012" (não-numérico) - soma não efetuada
11 s5 = s1+(1+2); // s5 valerá "03" (não-numérico) - soma primeiro
12 s6 = (s1+1)+2; // s6 valerá "012" (não-numérico) - concatena primeiro
13 String s7,s8,s9,s10,s11; // declaração das variáveis
14 s7 = 1+2+3+4+5+6+"7"; // s7 valerá "217" (não-numérico) - soma primeiro
15 s8 = ""+1+2+3+4+5+6+"7"; // s8 valerá "1234567" (não-numérico) - concatena primeiro
16 s9 = ""+2*3; // s9 valerá "6" (não-numérico), multiplicação tem
17 // precedência sobre concatenação
18 s10 = ""+1./2.+2; // s10 valerá "0.52" (não-numérico), divisão
19 // tem precedência mas concatenação é feita antes da soma
20 s11 = 1./2.+2+""; // s11 valerá "2.5" (não-numérico), divisão
21 // tem precedência e soma é feita antes da concatenação
22 }
23 }

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:

Listagem A.20: Programa que demonstra usos incorretos da classe String


1 /* Esta classe demonstra usos incorretos da classe String e suas instâncias */
2 class DemoString
3 {
4 public static void main(String argumentos[])
5 {
6 String s1,s2,s3,s4,s5,s6; // declaração das variáveis
7 s1 = 1; // ERRO: tipo diferente de String
8 s2 = false; // ERRO: tipo diferente de String
9 s3 = ’A’; // ERRO: tipo diferente de String
10 s4 = (String)3.1416; // ERRO: cast não pode ser feito para String
11 s5 = "Caracter " no meio"; // ERRO: existe uma aspa solta no meio da String
12 s6 = Esta é uma String; // ERRO: String deve ser delimitada por aspas
13 }
14 }

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.

A.2.2 Classes para encapsulamento de tipos nativos


Java provê algumas classes que permitem a representação de valores de tipos nativos como instâncias de
classes. Esta representação tem como vantagem o encapsulamento de métodos relativos a dados dos ti-
pos nativos (especialmente para conversão). A representação de dados nativos como instâncias de classes
também é necessária para algumas classes de Java (notadamente, Vector e Hashtable, descritas respecti-
vamente nas seções 14.1 e 14.2).

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.

As classes de representação de valores numéricos inteiros também implementam o método valueOf()


que recebe uma String e um valor inteiro entre 2 e 36 como argumentos, e retornam uma instância da
classe representando o valor numérico (valor passado como String) convertido para a base especificada
pelo argumento inteiro. As classes de representação de valores numéricos de ponto flutuante possuem o
mesmo método, mas sem o argumento inteiro opcional, para conversão entre Strings e os valores a serem
representados pelas classes.

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
191

A.2.2.1 A classe Byte


A classe Byte é uma classe de Java que encapsula valores nativos do tipo byte. Os construtores da classe
permitem a inicialização dos valores encapsulados através da especificação de um valor do tipo byte ou
de uma String que contenha um valor do tipo byte. Neste segundo caso, a String deve conter somente
e exatamente os caracteres necessários para que um byte seja representado. Alguns exemplos de uso de
instâncias da classe Byte são mostrados no programa na listagem A.21

Listagem A.21: Programa que demonstra usos da classe Byte


1 /* Esta classe demonstra usos da classe Byte e suas instâncias */
2 class DemoByte
3 {
4 public static void main(String argumentos[])
5 {
6 Byte b1,b2; // declaração das instâncias
7 b1 = new Byte((byte)12); // b1 representará o Byte 12
8 b2 = new Byte("-45"); // b2 representará o Byte -45 - conversão será feita automaticamente
9 int i = b1.byteValue()+b2.byteValue(); // i será a soma dos valores de b1 e b2
10 double d = b1.doubleValue()*b2.doubleValue(); // d será a multiplicação dos valores de b1 e b2
11 Byte b3 = Byte.valueOf("7f",16); // b3 representará 127
12 Byte b4 = Byte.valueOf("00101101",2); // b4 representará 45
13 System.out.println("Faixa de valores do byte:"+ // impressão dos valores-limite
14 Byte.MIN_VALUE+" a "+
15 Byte.MAX_VALUE);
16 }
17 } // fim da classe DemoByte

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.

Listagem A.22: Programa que demonstra usos incorretos da classe Byte


1 /* Esta classe demonstra usos incorretos da classe Byte e suas instâncias */
2 class DemoByte
3 {
4 public static void main(String argumentos[])
5 {
6 Byte b1,b2,b3,b4; // declaração das instâncias
7 b1 = new Byte(200); // erro: o valor passado é implicitamente um inteiro
8 b2 = new Byte("-2048"); // erro de execução: String não contém um byte
9 b3 = new Byte(" 120"); // erro de execução: String não contém somente um byte
10 b4 = new Byte(1.2); // erro: o valor passado é implicitamente um double
11 Byte b5 = Byte.valueOf("ff",16); // erro de execução: valor fora da faixa de bytes
12 Byte b6 = Byte.valueOf("1a",10); // erro de execução: valor e base incompatíveis
13 Byte b7 = Byte.valueOf("111000111000",2); // erro de execução: valor incompatível com byte
14 }
15 } // fim da classe DemoByte

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.

A.2.2.2 A classe Character


A classe Character é uma classe de Java que encapsula valores nativos do tipo char. O construtor da
classe permite a inicialização do valor encapsulado através da especificação de um valor do tipo char. A
classe Character tem, além dos métodos de conversão presentes em outras classes, métodos estáticos para
conversão entre caracteres maiúsculos e minúsculos e métodos para verificação do tipo do caracter (espaço,
dígito, letra, etc) - estes métodos estáticos não devem ser chamados como métodos de instâncias da classe
Character, e sim diretamente pela classe.

Alguns exemplos de uso de instâncias da classe Character são mostrados no programa na listagem A.23.

Listagem A.23: Programa que demonstra usos da classe Character


1 /* Esta classe demonstra usos da classe Character e suas instâncias */
2 class DemoCharacter
3 {
4 public static void main(String argumentos[])
5 {
6 Character c1,c2,c3,c4; // declaração das instâncias
7 c1 = new Character((char)65); // c1 representará o char 65 = ’A’
8 c2 = new Character(’!’); // c2 representará o char !
9 c3 = new Character(’ç’); // c3 representará o char ç
10 c4 = new Character(’ ’); // c4 representará o char espaço
11 System.out.println(’ ’+" é dígito ? "+Character.isDigit(’ ’)); // false
12 System.out.println(’1’+" é dígito ? "+Character.isDigit(’1’)); // true
13 System.out.println(’A’+" é dígito ? "+Character.isDigit(’A’)); // false
14 System.out.println(’ ’+" é letra ? "+Character.isLetter(’ ’)); // false
15 System.out.println(’1’+" é letra ? "+Character.isLetter(’1’)); // false
16 System.out.println(’A’+" é letra ? "+Character.isLetter(’A’)); // true
17 System.out.println(’Ó’+" é letra ? "+Character.isLetter(’Ó’)); // true
18 System.out.println(’ ’+" é letra ou dígito ? "+Character.isLetterOrDigit(’ ’)); // false
19 System.out.println(’1’+" é letra ou dígito ? "+Character.isLetterOrDigit(’1’)); // true
20 System.out.println(’A’+" é letra ou dígito ? "+Character.isLetterOrDigit(’A’)); // true
21 System.out.println(’a’+" é minúscula ? "+Character.isLowerCase(’a’)); // true
22 System.out.println(’Ã’+" é minúscula ? "+Character.isLowerCase(’Ã’)); // false
23 System.out.println(’ ’+" é minúscula ? "+Character.isLowerCase(’ ’)); // false
24 System.out.println(’i’+" é maiúscula ? "+Character.isUpperCase(’i’)); // false
25 System.out.println(’Î’+" é maiúscula ? "+Character.isUpperCase(’Î’)); // true
26 System.out.println(’ ’+" é maiúscula ? "+Character.isUpperCase(’ ’)); // false
27 System.out.println(’ ’+" é espaço ? "+Character.isWhitespace(’ ’)); // true
28 System.out.println(’\n’+" é espaço ? "+Character.isWhitespace(’\n’)); // true
29 System.out.println(’a’+" é espaço ? "+Character.isWhitespace(’a’)); // false
30 System.out.println(’!’+" é espaço ? "+Character.isWhitespace(’!’)); // false
31 System.out.println("Faixa de valores do char:"+ // impressão dos valores-limite,
32 (int)Character.MIN_VALUE+" a "+ // convertidos para int para impressão
33 (int)Character.MAX_VALUE);
34 }
35 } // fim da classe DemoCharacter

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.

Listagem A.24: Programa que demonstra usos incorretos da classe Character


1 /* Esta classe demonstra usos incorretos da classe Character e suas instâncias */
2 class DemoCharacter
3 {
4 public static void main(String argumentos[])
5 {
6 Character c1,c2,c3,c4,c5; // declaração das instâncias
7 c1 = new Character(200); // erro: o valor passado é implicitamente um inteiro
8 c2 = new Character("65"); // erro: construtor não aceita Strings
9 c3 = new Character(’’); // erro: caracter vazio não pode ser usado
10 c4 = new Character(1.2); // erro: o valor passado é implicitamente um double
11 c5 = new Character((char)-20); // não existe erro, mas o caracter valerá 65516
12 }
13 } // fim da classe DemoCharacter

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.

A.2.2.3 A classe Short


A classe Short é uma classe de Java que encapsula valores nativos do tipo short. Os construtores da classe
permitem a inicialização dos valores encapsulados através da especificação de um valor do tipo short ou
de uma String que contenha um valor do tipo short. Neste segundo caso, a String deve conter somente e
exatamente os caracteres necessários para que um valor do tipo short seja representado.

Alguns exemplos de uso de instâncias da classe Short são mostrados no programa na listagem A.25.

Listagem A.25: Programa que demonstra usos da classe Short


1 /* Esta classe demonstra usos da classe Short e suas instâncias */
2 class DemoShort

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.

Listagem A.26: Programa que demonstra usos incorretos da classe Short


1 /* Esta classe demonstra usos incorretos da classe Short e suas instâncias */
2 class DemoShort
3 {
4 public static void main(String argumentos[])
5 {
6 Short s1,s2,s3,s4; // declaração das instâncias
7 s1 = new Short(200); // erro: o valor passado é implicitamente um inteiro
8 s2 = new Short("999999"); // erro de execução: String não contém um short
9 s3 = new Short("1 2 3"); // erro de execução: String não contém somente um short
10 s4 = new Short(0.9); // erro: o valor passado é implicitamente um double
11 Short s5 = Short.valueOf("ffff",16); // erro de execução: valor fora da faixa de shorts
12 Short s6 = Short.valueOf("01234",2); // erro de execução: valor e base incompatíveis
13 }
14 } // fim da classe DemoShort

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

A.2.2.4 A classe Integer


A classe Integer é uma classe de Java que encapsula valores nativos do tipo int. Os construtores da classe
permitem a inicialização dos valores encapsulados através da especificação de um valor do tipo int ou de
uma String que contenha um valor do tipo int. Neste segundo caso, a String deve conter somente e exata-
mente os caracteres necessários para que um valor do tipo int seja representado.

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.

Listagem A.27: Programa que demonstra usos da classe Integer


1 /* Esta classe demonstra usos da classe Integer e suas instâncias */
2 class DemoInteger
3 {
4 public static void main(String argumentos[])
5 {
6 Integer i1,i2,i3; // declaração das instâncias
7 i1 = new Integer(100000); // s1 representará o int 100000
8 i2 = new Integer("100000"); // s2 representará o int 100000 - conversão será automática
9 int i = i1.intValue()-i2.intValue(); // i será a diferença entre os valores s1 e s2
10 float f = i1.floatValue()*i2.longValue(); // l será a multiplicação dos valores de i1 e i2
11 i3 = Integer.valueOf("7fffffff",16); // i3 representará 2147483647
12 Integer i4 = Integer.valueOf("java",36); // podemos usar qualquer base entre 2 e 36 !
13 String base2 = Integer.toBinaryString(2000); // 11111010000
14 String base8 = Integer.toOctalString(2000); // 3720
15 String base16 = Integer.toHexString(2000); // 7d0
16 byte b = i1.byteValue(); // b valerá -96: perda de precisão !
17 short s = i1.shortValue(); // s valerá -31072: perda de precisão !
18 System.out.println("Faixa de valores do int:"+ // impressão dos valores-limite
19 Integer.MIN_VALUE+" a "+
20 Integer.MAX_VALUE);
21 }
22 } // fim da classe DemoInteger

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

Listagem A.28: Programa que demonstra usos incorretos da classe Integer


1 /* Esta classe demonstra usos incorretos da classe Integer e suas instâncias */
2 class DemoInteger
3 {
4 public static void main(String argumentos[])
5 {
6 Integer i1,i2,i3,i4; // declaração das instâncias
7 i1 = new Integer(9999999999); // erro: o valor passado não é válido para inteiros
8 i2 = new Integer("9999999999"); // erro de execução: String contém valor muito grande
9 i3 = new Integer(" 100 "); // erro de execução: String não contém somente um int
10 i4 = new Integer(0.9); // erro: o valor passado é implicitamente um double
11 Integer i5 = Integer.valueOf("ffffffff",16); // erro de execução: valor fora da faixa de ints
12 Integer i6 = Integer.valueOf("abcdefg",16); // erro de execução: valor e base incompatíveis
13 }
14 } // fim da classe DemoInteger

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.

A.2.2.5 A classe Long


A classe Long é uma classe de Java que encapsula valores nativos do tipo long. Os construtores da classe
permitem a inicialização dos valores encapsulados através da especificação de um valor do tipo long ou
de uma String que contenha um valor do tipo long. Neste segundo caso, a String deve conter somente e
exatamente os caracteres necessários para que um valor do tipo long seja representado.

Alguns exemplos de uso de instâncias da classe Long são mostrados no programa na listagem A.29.

Listagem A.29: Programa que demonstra usos da classe Long


1 /* Esta classe demonstra usos da classe Long e suas instâncias */
2 class DemoLong
3 {
4 public static void main(String argumentos[])
5 {
6 Long l1,l2; // declaração das instâncias
7 l1 = new Long(99999999); // l1 representará o long 99999999
8 l2 = new Long("-360000"); // l2 representará o long -360000 - conversão automática
9 float f = l1.floatValue()+l2.floatValue(); // f será a soma dos valores de l1 e l2
10 double d = l1.doubleValue()*l2.doubleValue(); // d será a multiplicação dos valores de l1 e l2
11 Long l3 = Long.valueOf("ffffffff",16); // l3 representará 4294967295
12 short s = l1.shortValue(); // s valerá -7937 - perda de precisão !
13 System.out.println("Faixa de valores do long:"+ // impressão dos valores-limite
14 Long.MIN_VALUE+" a "+
15 Long.MAX_VALUE);
16 }
17 } // fim da classe DemoLong

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.

Listagem A.30: Programa que demonstra usos incorretos da classe Long


1 /* Esta classe demonstra usos incorretos da classe Long e suas instâncias */
2 class DemoLong
3 {
4 public static void main(String argumentos[])
5 {
6 Long l1,l2,l3; // declaração das instâncias
7 l1 = new Long(200.3); // erro: o valor passado é implicitamente um double
8 l2 = new Long("99999999999999999999"); // erro de execução: String não contém um long
9 l3 = new Long("L10000000"); // erro de execução: String não contém somente um long
10 Long l4 = Long.valueOf("ffffffffffffffff",16); // erro de execução: valor fora da faixa
11 Long l5 = Long.valueOf("01234",2); // erro de execução: valor e base incompatíveis
12 }
13 } // fim da classe DemoLong

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.

A.2.2.6 A classe Float


A classe Float é uma classe de Java que encapsula valores nativos do tipo float. Os construtores da classe
permitem a inicialização dos valores encapsulados através da especificação de um valor do tipo float ou
de uma String que contenha um valor do tipo float. Neste segundo caso, a String deve conter somente e
exatamente os caracteres necessários para que um valor do tipo float seja representado. A classe Float
não permite a conversão de bases como as classes que encapsulam valores inteiros.

Alguns exemplos de uso de instâncias da classe Float são mostrados no programa na listagem A.31.

Listagem A.31: Programa que demonstra usos da classe Float


1 /* Esta classe demonstra usos da classe Float e suas instâncias */
2 class DemoFloat
3 {
4 public static void main(String argumentos[])
5 {

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
198

6 Float f1,f2; // declaração das instâncias


7 f1 = new Float(100.0002); // l1 representará o float 100.0002
8 f2 = new Float("100.0002"); // l2 representará o float 100.0002 - conversão automática
9 float f = f1.floatValue()+f2.floatValue(); // f será a soma dos valores de f1 e f2
10 double d = f1.doubleValue()*f2.doubleValue(); // d será a multiplicação dos valores de f1 e f2
11 Float f3 = Float.valueOf("6.02e23"); // f3 representará 6.02 x 10^23
12 byte b = f1.byteValue(); // b valerá 100: perda de precisão !
13 int i = f2.intValue(); // i valerá 100: perda de precisão !
14 System.out.println("Faixa de valores do float:"+ // impressão dos valores-limite
15 Float.MIN_VALUE+" a "+
16 Float.MAX_VALUE);
17 }
18 } // fim da classe DemoFloat

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.

Listagem A.32: Programa que demonstra usos incorretos da classe Float


1 /* Esta classe demonstra usos incorretos da classe Float e suas instâncias */
2 class DemoFloat
3 {
4 public static void main(String argumentos[])
5 {
6 Float f1,f2,f3; // declaração das instâncias
7 f1 = new Float(false); // erro: o valor passado não pode ser convertido
8 f2 = new Float("1x10^23"); // erro de execução: String não contém um float
9 f3 = new Float("1e10000000"); // Não é erro, mas o valor armazenado é infinito.
10 }
11 } // fim da classe DemoFloat

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).

A.2.2.7 A classe Double


A classe Double é uma classe de Java que encapsula valores nativos do tipo double. Os construtores da
classe permitem a inicialização dos valores encapsulados através da especificação de um valor do tipo dou-
ble ou de uma String que contenha um valor do tipo double. Neste segundo caso, a String deve conter
somente e exatamente os caracteres necessários para que um valor do tipo double seja representado. A
classe Double não permite a conversão de bases como as classes que encapsulam valores inteiros.

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.

Listagem A.33: Programa que demonstra usos da classe Double


1 /* Esta classe demonstra usos da classe Double e suas instâncias */
2 class DemoDouble
3 {
4 public static void main(String argumentos[])
5 {
6 Double d1,d2; // declaração das instâncias
7 d1 = new Double(100000.000001); // l1 representará o double 100000.000001
8 d2 = new Double("100000.000001"); // l2 representará o double 100000.000001
9 double ds = d1.doubleValue()+d2.doubleValue(); // ds será a soma dos valores de d1 e d2
10 double dm = d1.doubleValue()*d2.doubleValue(); // dm será a multiplicação de d1 e d2
11 Double d3 = Double.valueOf("7.13e239"); // d3 representará 7.12 x 10^239
12 float f = d3.floatValue(); // f representará infinito !
13 short s = d1.shortValue(); // s representará -31072: perda de precisão !
14 System.out.println("Faixa de valores do double:"+ // impressão dos valores-limite
15 Double.MIN_VALUE+" a "+
16 Double.MAX_VALUE);
17 }
18 } // fim da classe DemoDouble

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.

Listagem A.34: Programa que demonstra usos incorretos da classe Double


1 /* Esta classe demonstra usos incorretos da classe Double e suas instâncias */
2 class DemoDouble
3 {
4 public static void main(String argumentos[])
5 {
6 Double d1,d2,d3; // declaração das instâncias
7 d1 = new Double(false); // erro: o valor passado não pode ser convertido
8 d2 = new Double("6.02x10^23"); // erro de execução: String não contém um double
9 d3 = new Double("1e10000000"); // Não é erro, mas o valor armazenado é infinito.
10 }
11 } // fim da classe DemoDouble

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

A.2.2.8 A classe Boolean


A classe Boolean possibilita o encapsulamento de valores nativos do tipo boolean. Os construtores da
classe permitem a inicialização dos valores encapsulados através da especificação de um valor do tipo bo-
olean ou de uma String que contenha um valor do tipo boolean. Neste segundo caso, se a String for igual a
“true” (independente de estar em caracteres maiúsculos, minúsculos ou misturados) o valor representado
será igual a true, caso contrário será igual a false. Não existem mecanismos nesta classe para conversão
de ou para valores numéricos.

Alguns exemplos de uso de instâncias da classe Boolean são mostrados no programa na listagem A.35.

Listagem A.35: Programa que demonstra usos da classe Boolean


1 /* Esta classe demonstra usos da classe Boolean e suas instâncias */
2 class DemoBoolean
3 {
4 public static void main(String argumentos[])
5 {
6 Boolean b1,b2,b3; // declaração das instâncias
7 b1 = new Boolean(true); // b1 representará o boolean true
8 b2 = new Boolean("true"); // b2 representará o boolean true
9 b3 = new Boolean("verdadeiro"); // b3 representará o boolean false
10 boolean b = b1.booleanValue(); // b valerá true
11 }
12 } // fim da classe DemoBoolean

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.

Listagem A.36: Programa que demonstra usos incorretos da classe Boolean


1 /* Esta classe demonstra usos incorretos da classe Boolean e suas instâncias */
2 class DemoBoolean
3 {
4 public static void main(String argumentos[])
5 {
6 Boolean b1,b2,b3; // declaração das instâncias
7 b1 = new Boolean(0); // não pode converter inteiro para boolean
8 b2 = new Boolean(); // um valor deve ser passado
9 b3 = new Boolean("true"); // b3 representará o boolean false
10 int x = b3.intValue(); // classe Boolean não tem métodos xxxValue exceto booleanValue
11 }
12 } // fim da classe DemoBoolean

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

B.1 A classe Keyboard


A linguagem Java não tem mecanismos simples de interação com o usuário via teclado e terminal - não
existem classes que formatem a entrada de dados via teclado de maneira simples e intuitiva. Embora possa-
mos associar um arquivo à entrada padrão de dados, isto é complicado e contra-intuitivo para principiantes
na linguagem.

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.

B.1.1 Usando a classe Keyboard


A classe Keyboard tem métodos estáticos (que permitem o seu uso sem a necessidade de criação de ins-
tâncias da classe) para leitura de todos os tipos básicos de Java e instâncias da classe String. Todos estes
métodos são polimórficos, permitindo que se passe um argumento default a ser usado caso o usuário dê
uma resposta vazia (pressionando Enter sem entrar um valor).

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

B.1.1.1 Usando a classe Keyboard para leitura de valores tipo boolean


Dois métodos da classe Keyboard podem ser usados para a leitura de valores booleanos do teclado:

• boolean Keyboard.readBoolean(): Este método lê um valor do teclado e retorna um valor boo-


leano correspondente ao que foi digitado. Caso nada seja digitado, o método retornará true.
• boolean Keyboard.readBoolean(boolean bdefault): Este método lê um valor do teclado e
retorna um valor booleano correspondente ao que foi digitado. Caso nada seja digitado, o método
retornará o valor passado pela variável bdefault.

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

B.1.1.2 Usando a classe Keyboard para leitura de valores tipo byte


Dois métodos da classe Keyboard podem ser usados para a leitura de valores do tipo byte do teclado:

• 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

B.1.1.3 Usando a classe Keyboard para leitura de valores tipo char


Dois métodos da classe Keyboard podem ser usados para a leitura de valores do tipo char do teclado:

• 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

B.1.1.4 Usando a classe Keyboard para leitura de valores tipo short


Dois métodos da classe Keyboard podem ser usados para a leitura de valores do tipo short do teclado:

• short Keyboard.readShort(): Este método lê um valor do teclado e retorna um valor do tipo


short correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor 0
(tipo short).

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
204

• short Keyboard.readShort(short sdefault): Este método lê um valor do teclado e retorna


um valor short correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o
valor passado pela variável sdefault (tipo short).

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

B.1.1.5 Usando a classe Keyboard para leitura de valores tipo int


Dois métodos da classe Keyboard podem ser usados para a leitura de valores do tipo int do teclado:

• 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

B.1.1.6 Usando a classe Keyboard para leitura de valores tipo long


Dois métodos da classe Keyboard podem ser usados para a leitura de valores do tipo long do teclado:

• 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

B.1.1.7 Usando a classe Keyboard para leitura de valores tipo float


Dois métodos da classe Keyboard podem ser usados para a leitura de valores do tipo float do teclado:

• float Keyboard.readFloat(): Este método lê um valor do teclado e retorna um valor do tipo


float correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor 0
(tipo float).
• float Keyboard.readFloat(float fdefault): Este método lê um valor do teclado e retorna
um valor float correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o
valor passado pela variável fdefault (tipo float).

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

B.1.1.8 Usando a classe Keyboard para leitura de valores tipo double


Dois métodos da classe Keyboard podem ser usados para a leitura de valores do tipo double do teclado:
• double Keyboard.readDouble(): Este método lê um valor do teclado e retorna um valor do tipo
double correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o valor 0
(tipo double).
• double Keyboard.readDouble(double ddefault): Este método lê um valor do teclado e retorna
um valor double correspondente ao que foi digitado. Caso nada seja digitado, o método retornará o
valor passado pela variável ddefault (tipo double).
O programa na listagem B.8 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.

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

B.1.1.9 Usando a classe Keyboard para leitura de instâncias da classe String


Dois métodos da classe Keyboard podem ser usados para a leitura de instâncias da classe String do
teclado:
• String Keyboard.readString(): Este método lê um valor do teclado e retorna uma instância da
classe String correspondente ao que foi digitado. Caso nada seja digitado, o método retornará uma
instância da classe String vazia (contendo zero caracteres).

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
207

• String Keyboard.readString(String ddefault): Este método lê um valor do teclado e retorna


uma instância da classe String correspondente ao que foi digitado. Caso nada seja digitado, o
método retornará uma cópia da String passada pela variável ddefault.
O programa na listagem B.9 demonstra o uso dos dois métodos da classe Keyboard descritos nesta seção.

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

B.2 Outros exemplos de uso da classe Keyboard


Nesta seção, outros exeplos de uso da classe Keyboard serão mostrados. O primeiro exemplo mostra vários
usos dos diversos métodos da classe, no programa na listagem B.10.

Listagem B.10: Mais exemplos de usos da classe Keyboard


1 /* Esta classe demonstra os métodos na classe Keyboard. Veja também outros
2 exemplos para mais detalhes. */
3
4 class demoteclado
5 {
6 /* Este método permite a execução da classe */
7 public static void main(String args[])
8 {
9 // declaro algumas variáveis
10 int i;
11 double d;
12 boolean b;
13 String s;
14 char c;
15 System.out.print("Entre um valor inteiro:");
16 i = Keyboard.readInt(); // lê um valor do tipo integer do teclado
17 System.out.print("Entre um valor double [default: -2]:");
18 d = Keyboard.readDouble(-2); // lê um valor do tipo double do teclado
19 // no exemplo acima, se o usuário não digitar nada como entrada o
20 // programa vai assumir o valor default -2.
21 System.out.print("Entre um valor booleano:");
22 b = Keyboard.readBoolean(); // lê um valor do tipo boolean do teclado
23 System.out.print("Entre uma String: [default: Java]");
24 s = Keyboard.readString("Java"); // lê um valor do tipo String do teclado
25 // no exemplo acima, se o usuário não digitar nada como entrada o
26 // programa vai assumir o valor default "Java".

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.

Listagem B.11: Exemplo de uso da classe Keyboard na classe Aluno


1 /* Classe que representa um aluno genérico */
2 class Aluno
3 {
4 private String nome; // o nome do aluno
5 private int idade; // a idade do aluno
6 private float mensalidade; // a mensalidade do aluno
7 /* Método que lê somente o nome do aluno do teclado */
8 void lêNome()
9 {
10 System.out.print("Entre o nome do aluno:"); // imprime uma mensagem
11 nome = Keyboard.readString(); // lê uma String para o nome
12 } // fim do método lêNome
13 /* Método que imprime somente o nome do aluno */
14 void imprimeNome()
15 {
16 System.out.println("Nome: "+nome); // imprime o nome
17 } // fim do método imprimeNome
18 /* Método que lê somente a idade do aluno do teclado */
19 void lêIdade()
20 {
21 System.out.print("Entre a idade do aluno:"); // imprime uma mensagem
22 idade = Keyboard.readInt(); // lê um int para a idade
23 } // fim do método lêIdade
24 /* Método que imprime somente a idade do aluno */
25 void imprimeIdade()
26 {
27 System.out.println("Idade: "+idade); // imprime a idade
28 } // fim do método imprimeIdade
29 /* Método que retorna o valor da variável privada idade */
30 int retornaIdade()
31 {
32 return idade;
33 } // fim do método retornaIdade
34 /* Método que imprime somente a mensalidade do aluno */
35 void imprimeMensalidade()
36 {
37 System.out.println("Mensalidade: "+mensalidade); // imprime a mensalidade
38 } // fim do método imprimeMensalidade
39 /* Método que lê somente a mensalidade do aluno do teclado */
40 void lêMensalidade()
41 {

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
209

42 System.out.print("Entre a mensalidade do aluno:"); // imprime uma mensagem


43 mensalidade = Keyboard.readFloat(); // lê um float para a mensalidade
44 } // fim do método lêMensalidade
45 /* Método para imprimir todos os dados do aluno */
46 void imprimeDados()
47 {
48 imprimeNome();
49 imprimeIdade();
50 imprimeMensalidade();
51 } // fim do método imprimeDados
52 /* Método para ler todos os dados do aluno */
53 void lêDados()
54 {
55 lêNome();
56 lêIdade();
57 lêMensalidade();
58 } // fim do método lêDados
59 } // Fim da classe Aluno

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

B.3 Código fonte da classe Keyboard


Para referência, a classe Keyboard completa está listada abaixo.

Listagem B.13: A classe Keyboard


1 /* A classe Keyboard (adaptada do livro "An Introduction to Computer Science
2 Using Java", de Samuel N. Kamin , M. Dennis Mickunas e Edward M. Reingold)
3 lê dados do teclado usando um pequeno truque: um BufferedReader criado a
4 partir da classe System.in.
5 Esta classe foi digitada por diligentes alunos da disciplina Programação
6 Orientada a Objetos I (turma de 1999) e anotada depois para mais clareza.
7 Alguns métodos e chamadas não estão otimizados para manter a clareza e
8 servir de referência aos estudiosos.
9 */
10
11 // importo as classes de E/S de Java
12 import java.io.*;
13
14 class Keyboard
15 {
16 /* Algumas variáveis são "globais" dentro da classe, sendo declaradas aqui */
17 static boolean iseof = false; // indica se é fim do "arquivo" de leitura
18 // declara e inicializa um BufferedReader a partir do System.in
19 static BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
20
21 ///////////////////////////////////////////////////////////////////////////////
22 // MÉTODOS PARA LER BOOLEANS
23 ///////////////////////////////////////////////////////////////////////////////
24
25 /* Lê um valor do tipo boolean do teclado, retorna o valor default se nada é
26 digitado ou sai do programa se existe erro de leitura. Este método considera
27 que o default é retornar true. */
28 public static boolean readBoolean()
29 {
30 return readBoolean(true); // chama o método genérico abaixo
31 }
32
33 /* Lê um valor do tipo boolean do teclado, retorna o valor default se nada é
34 digitado ou sai do programa se existe erro de leitura. */
35 public static boolean readBoolean(boolean bdefault)
36 {
37 String s=""; // a string a ser lida do teclado e convertida em um boolean
38 boolean b = bdefault; // o valor booleano a ser retornado, inicializado
39 if (iseof) return b; // se estamos no fim do arquivo, retornamos o default
40 System.out.flush(); // limpa o que existir no buffer do arquivo
41 try // tenta..
42 {
43 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
44 System.out.flush(); // limpa o que existir no buffer do arquivo
45 }
46 catch (IOException e) // se não der certo,
47 {
48 System.exit(-1); // sai do programa.
49 }
50 if (s==null) // se a String lida for nula, ou vazia,
51 {
52 iseof=true; // avisa que este é o fim do "arquivo"
53 return b; // e retorna o valor default
54 }
55 // senão avalia o que foi digitado:
56 if (s.trim().equalsIgnoreCase("true")) b = true; // verdadeiro se igual à true
57 else if (s.trim().equalsIgnoreCase("false")) b = false; // falso se igual à false
58 else if (s.trim().equalsIgnoreCase("t")) b = true; // verdadeiro se igual à t

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

191 if (s==null) // se a String lida for nula, ou vazia,


192 {
193 iseof=true; // avisa que este é o fim do "arquivo"
194 return sh; // e retorna o valor default
195 }
196 // senão avalia o que foi digitado:
197 try // tenta
198 {
199 sh=new Short(s.trim()).shortValue(); // converter a String para short...
200 }
201 catch (NumberFormatException e) // se não conseguir,
202 {
203 sh = sdefault; // usa o valor default
204 }
205 return sh; // retorna o valor de sh
206 } // fim do método readShort
207
208 ///////////////////////////////////////////////////////////////////////////////
209 // MÉTODOS PARA LER INTS
210 ///////////////////////////////////////////////////////////////////////////////
211
212 /* Lê um valor do tipo int do teclado, retorna o valor default se nada é
213 digitado ou sai do programa se existe erro de leitura. Este método considera
214 que o default é retornar zero. */
215 public static int readInt()
216 {
217 return readInt(0); // chama o método genérico abaixo
218 }
219
220 /* Lê um valor do tipo int do teclado, retorna o valor default se nada é
221 digitado ou sai do programa se existe erro de leitura. */
222 public static int readInt(int idefault)
223 {
224 String s=""; // a String a ser lida do teclado e convertida em um int
225 int i = idefault; // o valor int a ser retornado, inicializado
226 if (iseof) return i; // se estamos no fim do arquivo, retornamos o default
227 System.out.flush(); // limpa o que existir no buffer do arquivo
228 try // tenta..
229 {
230 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
231 System.out.flush(); // limpa o que existir no buffer do arquivo
232 }
233 catch (IOException e) // se não der certo,
234 {
235 System.exit(-1); // sai do programa.
236 }
237 if (s==null) // se a String lida for nula, ou vazia,
238 {
239 iseof=true; // avisa que este é o fim do "arquivo"
240 return i; // e retorna o valor default
241 }
242 // senão avalia o que foi digitado:
243 try // tenta
244 {
245 i=new Integer(s.trim()).intValue(); // converter a String para int...
246 }
247 catch (NumberFormatException e) // se não conseguir,
248 {
249 i = idefault; // usa o valor default
250 }
251 return i; // retorna o valor de i
252 } // fim do método readInt
253
254 ///////////////////////////////////////////////////////////////////////////////
255 // MÉTODOS PARA LER LONGS
256 ///////////////////////////////////////////////////////////////////////////////

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

323 System.out.flush(); // limpa o que existir no buffer do arquivo


324 }
325 catch (IOException e) // se não der certo,
326 {
327 System.exit(-1); // sai do programa.
328 }
329 if (s==null) // se a String lida for nula, ou vazia,
330 {
331 iseof=true; // avisa que este é o fim do "arquivo"
332 return f; // e retorna o valor default
333 }
334 // senão avalia o que foi digitado:
335 try // tenta
336 {
337 f=new Float(s.trim()).floatValue(); // converter a String para float...
338 }
339 catch (NumberFormatException e) // se não conseguir,
340 {
341 f = fdefault; // usa o valor default
342 }
343 return f; // retorna o valor de f
344 } // fim do método readFloat
345
346 ///////////////////////////////////////////////////////////////////////////////
347 // MÉTODOS PARA LER DOUBLES
348 ///////////////////////////////////////////////////////////////////////////////
349
350 /* Lê um valor do tipo double do teclado, retorna o valor default se nada é
351 digitado ou sai do programa se existe erro de leitura. Este método considera
352 que o default é retornar zero. */
353 public static double readDouble()
354 {
355 return readDouble(0); // chama o método genérico abaixo
356 }
357
358 /* Lê um valor do tipo double do teclado, retorna o valor default se nada é
359 digitado ou sai do programa se existe erro de leitura. */
360 public static double readDouble(double ddefault)
361 {
362 String s=""; // a String a ser lida do teclado e convertida em um double
363 double d = ddefault; // o valor double a ser retornado, inicializado
364 if (iseof) return d; // se estamos no fim do arquivo, retornamos o default
365 System.out.flush(); // limpa o que existir no buffer do arquivo
366 try // tenta..
367 {
368 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
369 System.out.flush(); // limpa o que existir no buffer do arquivo
370 }
371 catch (IOException e) // se não der certo,
372 {
373 System.exit(-1); // sai do programa.
374 }
375 if (s==null) // se a String lida for nula, ou vazia,
376 {
377 iseof=true; // avisa que este é o fim do "arquivo"
378 return d; // e retorna o valor default
379 }
380 // senão avalia o que foi digitado:
381 try // tenta
382 {
383 d=new Double(s.trim()).doubleValue(); // converter a String para float...
384 }
385 catch (NumberFormatException e) // se não conseguir,
386 {
387 d = ddefault; // usa o valor default
388 }

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
216

389 return d; // retorna o valor de d


390 } // fim do método readDouble
391
392 ///////////////////////////////////////////////////////////////////////////////
393 // MÉTODOS PARA LER STRINGS
394 ///////////////////////////////////////////////////////////////////////////////
395
396 /* Lê um valor do tipo String do teclado, retorna o valor default se nada é
397 digitado ou sai do programa se existe erro de leitura. Este método considera
398 que o default é retornar uma String vazia. */
399 public static String readString()
400 {
401 return readString(""); // chama o método genérico abaixo
402 }
403
404 /* Lê um valor do tipo String do teclado, retorna o valor default se nada é
405 digitado ou sai do programa se existe erro de leitura. */
406 public static String readString(String sdefault)
407 {
408 String s=""; // a String a ser lida do teclado e convertida em um outro String
409 String sd = sdefault; // o valor String a ser retornado, inicializado
410 if (iseof) return sd; // se estamos no fim do arquivo, retornamos o default
411 System.out.flush(); // limpa o que existir no buffer do arquivo
412 try // tenta..
413 {
414 s = input.readLine(); // ... ler uma string do "arquivo" de entrada
415 System.out.flush(); // limpa o que existir no buffer do arquivo
416 }
417 catch (IOException e) // se não der certo,
418 {
419 System.exit(-1); // sai do programa.
420 }
421 if (s==null) // se a String lida for nula, ou vazia,
422 {
423 iseof=true; // avisa que este é o fim do "arquivo"
424 return sd; // e retorna o valor default
425 }
426 if (s.length() == 0) // se a String lida for vazia
427 return sd; // retorna a default
428 else // senão
429 return s; // senão retorna o que foi digitado
430 } // fim do método readString
431
432 } // fim da classe Keyboard

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
217

Apêndice C

Usando o Java Development Kit

ATENÇÃO: Este capítulo ainda está sendo escrito. Evite imprimi-lo, pois novas versões devem ser
liberadas em breve.

C.1 Sobre o Java Development Kit (JDK)


C.1.1 Obtendo e Instalando o JDK
O JDK pode ser obtido, em diferentes versões, no Site da Sun (www.sun.com). Seguindo as instruções na
página da Sun, copie e instale o JDK na sua máquina.
FCC/UNIVAP Alunos da FCC/Univap já tem o JDK instalado e pronto para o uso: uma versão
atual do JDK 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.

C.2 Como um programa em Java é compilado e executado

Código−fonte em Java Compilador Java

Interpretador Java
Bytecode (objeto)
(JVM, máquina virtual Java)

Navegador
Transporte via
Internet Interpretador Java
(JVM, máquina virtual Java)

Figura C.1: Como um programa em Java é compilado e executado

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
218

C.3 Usando o JDK no Linux


C.3.1 Compilando e Executando Programas em Java no Linux
Se o JDK estiver instalado no computador ou terminal sendo usado (veja a seção C.1.1), programas em Java
podem ser compilados através de comandos entrados em um terminal como kterm, xterm ou similares.

C.4 Usando o JDK no Windows


C.4.1 Editores de Texto para o Windows
Qualquer editor de textos puro que seja capaz de ler e gravar arquivos em ASCII pode ser usado para editar
programas em Java. Exemplos destes editores são o Notepad (ou Bloco de Notas) e o EditPlus (que colore
a sintaxe das palavras-chave dos programas em Java). Editores de texto como o Microsoft Word e similares
não devem ser usados, uma vez que estes gravam arquivos em um formato interno que não é reconhecido
pelo compilador Java (este somente compilará programas que tiverem sido gravados em modo texto, o que
é default para os editores sugeridos acima). O compilador também espera que o programa em java seja
gravado com a extensão .java e não .txt.
Quando estiver editando arquivos em uma janela com o editor e compilando programas em Java em uma
janela do DOS, lembre-se de sempre gravar o programa antes de compilar.

C.4.2 Compilando e Executando Programas em Java no Windows


Depois de criar um programa em Java usando o editor de textos escolhido e gravá-lo no disco, você pode
usar o compilador Java para compilá-lo. De uma janela do MS-DOS COMO E QUE
CHAMA MESMO ?, mude o diretório atual para o diretório onde seu arquivo .java
está, usando o comando cd [nome do diretório].
Para compilar o programa, basta usar o comando javac [nome do arquivo com a extensão .java].
Este comando criará os arquivos .class correspondentes (veja a seção C.5).
A máquina virtual Java que executará as classes compiladas só pode executar arquivos com a extensão
.class que contenham o método main decladaro como public static void main e com um vetor de
Strings passado como parâmetro. Outras classes podem ser necessárias para a execução do programa, e
devem estar também compiladas.
Para executar uma classe que tenha o método main apropriado, basta executar o comando java [nome
da classe] sem a extensão .class. Caso haja uma interface gráfica para o programa, esta aparecerá na
tela do terminal ou computador, e caso a interação seja feita por entrada e saída normal, estas ocorrerão na
janela do MS-DOS COMO E QUE CHAMA MESMO ?.
C.5 Esclarecimentos Sobre Nomes de Classes e Arquivos
Diferentemente de compiladores de outras linguagens como C e Pascal, o compilador Java cria os nomes
das classes (bytecodes que podem ser executados pela máquina virtual) baseado nas classes existentes nos
arquivos e não nos nomes dos arquivos.
Quando um programa é compilado, dependendo do conteúdo do arquivo com o programa em java, uma ou
mais classes serão criadas e colocadas em arquivos com a extensão .class. Para cada classe existente no
arquivo, um arquivo de saída com o nome da classe e a extensão .class será criado.

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:

Nome do Arquivo Conteúdo do Arqui- Comando a ser exe- Resultado


vo cutado
aluno.java (com Uma classe chama- javac aluno.java O arquivo Aluno.class (com
“a” minúsculo) da Aluno (com “A” “A” maiúsculo).
maiúsculo)
alunos.java As classes Aluno, javac Os arquivos Aluno.class,
(com “a” minúscu- Aluno_Pre_Primario alunos.java Aluno_Pre_Primario.class
lo) e e
Aluno_Universitario. Aluno_Universitario.class.
A.java As classes B, C e D. javac A.java Os arquivos B.class,
A classe D depende da C.class e D.class (note
classe E, que ainda não que não existe a classe A então
foi compilada e está o arquivo A.class não é
no arquivo E.java. criado). O arquivo E.class é
criado (compilado automati-
camente) porque é necessário
para a classe D.
Tabela C.1: Exemplos de nomes de arquivos e classes geradas pelo compilador

C.6 Possíveis Erros de Compilação e Execução


Diversos erros podem acontecer no processo de compilação e execução de programas em Java. Alguns
mais frequentes são descritos na tabela C.2, com detalhes das causas e possíveis soluções:
Outros erros que podem acontecer por causa de erros de digitação, falta de comandos ou pontos-e-vírgulas,
aparecerão na linha de comando com o número da linha indicado, e o trecho onde o problema ocorreu. Use
estas indicações para achar os erros e corrigí-los.
FCC/UNIVAP Se você está usando o ambiente sugerido pelo professor (Linux, JDK, xemacs) o
editor automaticamente mostrará os erros na janela de compilação.

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
220

Erro ou Problema Possível Causa Possível Solução


Ao tentar compilar um arquivo O arquivo sendo compila- Renomeie ou salve o arquivo com
com um programa em Java, o com- do não está com a extensão a extensão .java
pilador javac mostra a mensagem apropriada .java.
invalid argument (argumento invá-
lido).
O compilador javac mostra uma O arquivo sendo compilado Renomeie o arquivo para o nome
mensagem de erro parecida com contém uma classe declara- da classe.
Public class ... must be defined in
da pública com um nome di-
a file called .... ferente do arquivo. Classes
públicas devem ser criadas
em arquivos com o mesmo
nome da classe.
O intepretador java mostra uma A classe sendo executada Recompile todos os programas
mensagem de erro parecida com não foi encontrada ou seu que sejam relacionados com a
Can’t find class.... nome foi dado incorreta- classe ou verifique se o nome
mente. da classe foi dado corretamente -
lembre-se que o nome da classe
passada para o interpretador não
deve conter a extensão .class.
O intepretador java mostra uma Uma classe que é necessária Recompile os programas neces-
mensagem de erro parecida com para a execução do progra- sários para a classe não encontra-
java.lang.NoClassDefFoundError. ma não foi encontrada. da.
Tabela C.2: Alguns erros de compilação e execução, suas causas e possíveis soluções

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
221

Apêndice D

Usando o Sistema Operacional Linux

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

D.3 Uma introdução aos comandos básicos do Linux


D.3.1 Executando comandos no Linux
D.3.2 Comandos de listagem de diretórios e arquivos
Alguns dos comandos mais usados para listagem de diretórios e arquivos são exemplificados na lista abai-
xo. Argumentos opcionais serão mostrados entre colchetes [ ].

ls [argumentos] [nome-de-arquivo-ou-diretório] O comando ls, sem argumentos, lista o con-


teúdo (nomes de arquivos) do diretório corrente, da maneira mais simples possível. Se o argumento
-l for passado, a listagem será detalhada (mostrando o nome do dono do arquivo, as permissões,
o tamanho em bytes e a data da última modificação). Se o argumento -R for passado, a listagem
será recursiva, ou seja, todos os arquivos em todos os diretórios a partir do diretório corrente serão
listados - esta opção pode resultar em listagens muito longas.
aa

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
222

D.3.3 Comandos de criação, remoção e modificação de diretórios


D.3.4 Comandos de cópia, remoção e modificação de arquivos e diretórios
D.3.5 Comandos de exibição do conteúdo de arquivos
D.3.6 Editores de Texto para o Linux
D.3.6.1 Xemacs e Emacs
Características: buffers, nomes, etc.
Cuidados: ao usar xemacs, o nome deve ser criado com a extensão correta.

Figura D.1: Interface gráfica do Xemacs

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)
223

Figura D.2: Interface gráfica do Emacs

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

Acrobat Reader, 2 new, 36


aplicações em Java, 5
applets, 5 Object,classe, 73
argumentos para o método main, 33 objetos
array, 33 definição, 9
ocultação de informação, 10
bibliotecas, 39 overflow
erro, 183
C++, 4
caracter de escape, 188 PDF, 2
cast, 179 polimorfismo, 57
classe POO
ponto de entrada, 33 definição, 8
classes POOI
definição, 8 Objetivos Gerais, 5
comentários em java, 18 POOII
construtor, 68 Objetivos Gerais, 6
Unidades, 5, 6
Eiffel, 4 private
encapsulamento, 10 métodos, 21
erro variáveis, 19
overflow, 183 public, 218
exercícios métodos, 21
categorias, 3 variáveis, 19
herança, 43 Smalltalk, 4
sobrecarga, 46 sobrecarga, 46
if static, 33, 37
aninhados, 81 Strings, 187
interface, 10 concatenação, 188
super, 52
java
comentários, 18 tipos de dados
nativos, 178
laço while, 86, 88
laços, 85 Unicode, 180

métodos, 21 variável de controle, 85


argumentos, 21 void, 21
main, 33
modelos
definição, 7
modificadores para o método main, 33

Clique aqui para ver como este documento pode ser personalizado para você ! (É necessário estar conectado à Internet.)

Você também pode gostar