Escolar Documentos
Profissional Documentos
Cultura Documentos
Intro Java CC PDF
Intro Java CC PDF
Intro Java CC PDF
Alfredo Goldman
Fabio Kon
Paulo J. S. Silva
ISBN: 85-88697-10-6
CDD 600
i
C O M M O N S D E E D
Atribuio-Uso No-Comercial-Compartilhamento pela mesma licena 2.5
Voc pode:
copiar, distribuir, exibir e executar a obra
criar obras derivadas
Sob as seguintes condies:
Atribuio. Voc deve dar crdito ao autor original, da forma especificada pelo autor ou
licenciante.
Uso No-Comercial. Voc no pode utilizar esta obra com finalidades comerciais.
Compartilhamento pela mesma Licena. Se voc alterar, transformar, ou criar outra obra
com base nesta, voc somente poder distribuir a obra resultante sob uma licena idntica a
esta.
Para cada novo uso ou distribuio, voc deve deixar claro para outros os termos da licena desta obra.
Qualquer uma destas condies podem ser renunciadas, desde que Voc obtenha permisso do autor.
Qualquer direito de uso legtimo (ou "fair use") concedido por lei, ou qualquer outro direito protegido
pela legislao local, no so em hiptese alguma afetados pelo disposto acima.
Este um sumrio para leigos da Licena Jurdica (que pode ser obtida na ntegra em
http://creativecommons.org/licenses/by-nc-sa/2.5/legalcode).
Termo de exonerao de responsabilidade
Esta Licena Simplificada no uma licena propriamente dita. Ela apenas uma referncia til para
entender a Licena Jurdica (a licena integral) - ela uma expresso dos seus termos-chave que pode ser
compreendida por qualquer pessoa. A Licena Simplifica em si no tem valor legal e seu contedo no aparece
na licena integral.
O Creative Commons no um escritrio de advocacia e no presta servios jurdicos. A distribuio,
exibio ou incluso de links para esta Licena Simplificada no estabelece qualquer relao advocatcia.
ii
iii
Sugestes e Correes
Se voc encontrar erros ou tiver sugestes para melhorias neste
livro, favor enviar para o email kon@ime.usp.br.
iv
v
Agradecimentos
Leo Kazuhiro Ueda e Nelson Posse Lago atuaram como assistentes de ensino
na primeira vez em que esta disciplina foi ministrada e foram responsveis
por inmeras contribuies. O apndice sobre o Dr. Java foi preparado pelo
Leo. Fabiano Mitsuo Sato, George Henrique Silva e Igor Ribeiro Sucupira
foram monitores da disciplina tambm em 2003 e colaboraram com alguns
exerccios.
Prefcio xv
1 Teatro de Objetos 1
1.1 Disputa de pnaltis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2 Histria da Computao 7
2.1 Histria da Computao e Arquitetura do Computador . . . . . . . . . . . . . . . . . . . . . 7
2.2 Evoluo das Linguagens de Programao . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3 Conversor de Temperaturas 15
3.1 Analogia entre dramatizao da disputa de pnaltis e Programao Orientada a Objetos . . . . 15
3.2 Um exemplo real em Java: um conversor de Celsius para Fahrenheit . . . . . . . . . . . . . . 16
4 Testes Automatizados 19
6 if else Encaixados 33
8 Laos e Repeties 45
8.1 Laos em linguagens de programao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
8.2 O lao while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
8.3 Nmeros primos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
ix
x SUMRIO
10 Mergulhando no while 61
10.1 Um pouco mais sobre primos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
10.2 Uma biblioteca de funes matemticas. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
10.3 do...while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
12 A Memria e as Variveis 73
12.1 A Memria do Computador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
12.2 O que so as Variveis? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
14 Arrays (vetores) 81
14.1 Criao de programas Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
20 Interfaces 115
20.1 O conceito de interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
20.2 Um primeiro exemplo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
20.3 Implementando mais de uma interface por vez . . . . . . . . . . . . . . . . . . . . . . . . . . 119
20.4 Um exemplo mais sofisticado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
20.5 A importncia de interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
21 Herana 129
21.1 O Conceito de herana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
21.2 Terminologia de herana . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
21.3 Implementao de herana na linguagem Java . . . . . . . . . . . . . . . . . . . . . . . . . . 130
21.4 Hierarquia de classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
21.5 Relacionamento um . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
21.6 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
22 Javadoc 135
Bibliografia 173
xii SUMRIO
Lista de Figuras
xiii
xiv LISTA DE FIGURAS
Prefcio
Caros leitores, sejam bem-vindos ao maravilhoso mundo da Cincia da Computao. Com este livro, vocs
tero a oportunidade de aprender os elementos bsicos da programao de computadores e tero contato com
alguns dos conceitos fundamentais da Cincia da Computao.
Este livro resultado da experincia dos autores na disciplina de Introduo Cincia da Computao
ministrada no IME/USP utilizando orientao a objetos e a linguagem Java de 2003 a 2006. Desde 2005,
esta abordagem tambm aplicada na USPLeste com os 180 alunos do curso de Sistemas de Informao.
Influenciada pelo mtodo proposto pela ACM (Association for Computing Machinery) e pelo IEEE (Institute
of Electrical and Electronics Engineers) em seu currculo Objects-first, nossa abordagem evita o problema de
se ensinar a programar sem o uso de objetos para depois exigir do estudante uma mudana de paradigma com a
introduo de objetos. Elimina-se assim a necessidade de dizer esquea a forma que programamos at agora;
agora vamos aprender o jeito correto.
Apresentando os conceitos de orientao a objetos desde o incio do ensino de programao, a abordagem
adotada aqui permite que o aluno inicie sua formao em programao de forma equilibrada. Aprendendo con-
ceitos tanto algortmicos quanto estruturais ao mesmo tempo em que toma contato com prticas fundamentais
de programao como testes automatizados e o uso de nomes claros para os elementos do cdigo, o leitor obtm
uma viso bsica porm ampla do que mais importante para o desenvolvimento de software.
Esperamos que este livro seja til tanto para alunos de cursos superiores de Informtica quanto para pro-
fissionais do mercado e outros curiosos que queiram adquirir conhecimentos na rea de desenvolvimento de
software. Nosso objetivo que este livro os ajude na fascinante empreitada de aprender a programar de forma
elegante e eficaz e que ele permita um bom incio rumo a uma formao slida em programao que uma
condio fundamental que os desafios da informtica do sculo XXI nos impem.
xv
xvi PREFCIO
Captulo 1
Teatro de Objetos
Vamos iniciar a nossa jornada ao fascinante mundo da orientao a objetos de forma dramtica: com um
Teatro de Objetos. Se voc est usando este livro em um curso, reserve juntamente com seu professor uma
parte da primeira aula para realizar a encenao descrita neste captulo. Se voc trabalha em uma empresa,
rena-se com colegas de trabalho ou com amigos interessados em programao para exercitar suas qualidades
dramticas. Liberte o artista que existe dentro de voc!
O objetivo do Teatro de Objetos fazer com que os alunos vivenciem um jogo interativo do qual participam
vrios objetos realizando diferentes formas de aes e comunicaes. Os conceitos de orientao a objetos
empregados no teatro no so explicitamente explicados j no primeiro captulo mas sero abordados ao longo
do livro. Em um curso de Introduo Cincia da Computao, normalmente a primeira metade da primeira
aula dedicada a uma conversa informal com os alunos explicando quais so os objetivos da disciplina (e
do curso inteiro, se for o caso). sempre interessante tambm conversar sobre contatos prvios que os alunos
tiveram com informtica e com programao. bom deixar claro que este livro pode ser acompanhado por uma
pessoa que nunca viu um computador na frente em sua vida, mas que aprender a programar no uma tarefa
fcil, preciso se empenhar. Na segunda metade da aula, exercitamos as habilidades dramticas: para ilustrar
o funcionamento de um programa de computador complexo, vamos fazer de conta que somos partes de um
programa de computador trabalhando em conjunto para atingir um certo objetivo. Se voc estiver organizando
a encenao com seus colegas, voc pode fazer um certo suspense sobre qual o objetivo (simular uma disputa
de pnaltis) e sobre como ele ser alcanado.
Tcnico (2 atores)
Juiz (1 ator)
Bandeirinha (2 atores)
Gandula (1 ator)
1
2 CAPTULO 1. TEATRO DE OBJETOS
O professor (ou o diretor da pea, que pode ser voc) ser responsvel por escolher as pessoas que desempenha-
ro cada papel. Se houver limitao de espao, conveniente que os 8 torcedores fiquem concentrados em uma
rea separada (por exemplo, em uma suas prprias carteiras, se o local for uma sala de aula) para no tumultuar
muito o ambiente. Obviamente, o diretor pode tambm aumentar ou diminuir o nmero de torcedores e de
batedores de pnalti. Para desempenhar o papel de torcedores, uma boa dica o diretor escolher pessoas que
paream bem barulhentas e faladoras (por exemplo, a turma do fundo numa sala de aula :-). Ao escolher os
atores, o diretor dever entregar um carto preso com um barbante que ficar pendurado no pescoo do ator e
conter informaes sobre o papel desempenhado pelo ator. As informaes so:
1. Nome do papel
3. Atributos do personagem
Os trs tipos de informao acima j devem vir pr-escritos caneta no carto mas os valores dos atributos
do personagem devem ser escritos na hora a lpis pelo diretor. Alguns papis, como o de juiz, no possuem
nenhum atributo. Outros papis podem possuir um ou mais atributos, o jogador, por exemplo, pode possuir
como atributos o nome do time ao qual pertence e o nmero da sua camisa. No caso de o jogador ser um
goleiro, o atributo nmero da camisa pode vir escrito a caneta como valendo 1.
Alm do carto que fica pendurado no pescoo do ator, cada ator recebe um script descrevendo o seu
comportamento: para cada mensagem recebida pelo ator, o script descreve quais aes devem ser tomadas pelo
ator.
O diretor no deve esquecer de trazer uma bola para esta atividade e deve tomar cuidado para que nenhuma
janela seja quebrada durante a realizao da atividade. O tempo total estimado para a realizao da atividade
de 50 minutos. A maior parte do tempo gasto explicando-se os procedimentos. A encenao em si, demora
entre 5 e 10 minutos dependendo da qualidade dos batedores de pnalti e dos goleiros.
Eis a descrio detalhada dos dados que devero aparecer nos cartes descritivos e no script (comporta-
mento) de cada um dos 26 atores participantes da encenao. Para obter verses PDF dos cartes prontas para
impresso, visite o stio deste livro: www.ime.usp.br/~kon/livros/Java
1.1. DISPUTA DE PNALTIS 3
1. Goleiro
Carto de Identificao
Nome do Papel: Goleiro
Mensagens que entende: SuaVez, Cobrana Autorizada, VenceuOTimeX
Atributos: Time: , Camisa nmero: 1
Comportamento (Script)
mensagem: SuaVez ao: posiciona-se na frente do gol e fica esperando pela cobrana do
pnalti.
mensagem: CobranaAutorizada ao: concentra-se na bola que ser chutada pelo ad-
versrio e faz de tudo para no deixar que a bola entre no gol. O goleiro no pode se adiantar
antes do chute do adversrio. Aps a cobrana sair do gol para dar lugar ao goleiro adversrio.
mensagem: VenceuOTimeX ao: se TimeX igual ao atributo Time no seu carto de iden-
tificao, comemore; caso contrrio, xingue o juiz (polidamente! :-).
2. Batedor de Pnalti
Carto de Identificao
Nome do Papel: Batedor de Pnalti
Mensagens que entende: SuaVez, CobranaAutorizada, VenceuOTimeX
Atributos: Time: , Camisa nmero:
Comportamento
mensagem: SuaVez ao: posiciona-se na frente da bola e fica esperando pela autorizao
do juiz.
mensagem: CobranaAutorizada ao: chuta a bola tentando marcar um gol. Aps a
cobrana voltar para junto do seu tcnico para dar lugar prxima cobrana.
mensagem: VenceuOTimeX ao: se TimeX igual ao atributo Time no seu carto de iden-
tificao, comemore; caso contrrio, xingue o juiz (polidamente! :-).
3. Torcedor Educado
Carto de Identificao
Nome do Papel: Torcedor Educado
Mensagens que entende: Ao, VenceuOTimeX
Atributos: Time: , Camisa nmero: 12
Comportamento
mensagem: Ao ao: assista ao jogo emitindo opinies inteligentes sobre o andamento
da peleja e manifestando o seu apreo e desapreo pelo desenrolar da disputa.
mensagem: VenceuOTimeX ao: se TimeX igual ao atributo Time no seu carto de
identificao, comemore e faa um comentrio elogioso sobre o seu time; caso contrrio, elogie
o adversrio e parabenize o seu time pelo empenho.
4 CAPTULO 1. TEATRO DE OBJETOS
4. Torcedor Mal-Educado
Carto de Identificao
Nome do Papel: Torcedor Mal-Educado
Mensagens que entende: Ao, VenceuOTimeX
Atributos: Time: , Camisa nmero: 12
Comportamento
mensagem: Ao ao: assista ao jogo emitindo opinies duvidosas sobre o andamento da
peleja e manifestando a sua raiva ou alegria pelo desenrolar do jogo.
mensagem: VenceuOTimeX ao: se TimeX igual ao atributo Time no seu carto de identi-
ficao, xingue o adversrio. Caso contrrio, xingue o adversrio desesperadamente (mas, por
favor, no se esquea que estamos em uma universidade).
5. Juiz
Carto de Identificao
Nome do Papel: Juiz
Mensagens que entende: Ao, Irregularidade
Comportamento
mensagem: Ao ao: coordene o andamento da disputa de pnaltis enviando mensagens
SuaVez para o tcnico do time batedor e para o goleiro defensor a cada nova batida. Quando os
personagens estiverem a postos, emita a mensagem CobranaAutorizada. Faa a contagem
de gols e quando houver um vencedor, emita a mensagem VenceuOTimeX onde TimeX o nome
do time vencedor. A disputa de pnaltis feita alternadamente, 5 cobranas para cada time. Se
no houver um ganhador aps as 5 cobranas, so feitas novas cobranas alternadamente at
que haja um vencedor.
mensagem: Irregularidade ao: se a mensagem foi enviada por um Bandeirinha, ignore
a cobrana recm-efetuada e ordene que ela seja realizada novamente enviando a mensagem
RepitaCobrana ao tcnico apropriado.
6. Gandula
Carto de Identificao
Nome do Papel: Gandula
Mensagens que entende: CobranaAutorizada
Comportamento
mensagem: CobranaAutorizada ao: preste ateno cobrana do pnalti. Aps a
concluso da cobrana, pegue a bola e leve-a de volta marca de pnalti.
1.1. DISPUTA DE PNALTIS 5
7. Tcnico
Carto de Identificao
Nome do Papel: Tcnico
Mensagens que entende: SuaVez, RepitaCobrana, VenceuOTimeX
Atributos: Time:
Comportamento
mensagem: SuaVez ao: escolha um dos seus jogadores para efetuar a cobrana e envie a
mensagem SuaVez. No repita jogadores nas 5 cobranas iniciais.
mensagem: RepitaCobrana ao: envie a mensagem SuaVez para o jogador que acabou
de efetuar a cobrana.
mensagem: VenceuOTimeX ao: se TimeX igual ao atributo Time no seu carto de iden-
tificao, comemore; caso contrrio, diga que o seu time foi prejudicado pela arbitragem e que
futebol uma caixinha de surpresas.
8. Bandeirinha
Carto de Identificao
Nome do Papel: Bandeirinha
Mensagens que entende: Cobrana Autorizada, VenceuOTimeX
Comportamento
mensagem: CobranaAutorizada ao: verifique se o goleiro realmente no avana antes
de o batedor chutar a bola. Caso ele avance, envie uma mensagem Irregularidade para o
Juiz.
mensagem: VenceuOTimeX ao: se TimeX no o nome do time da casa, distancie-se da
torcida pois voc acaba de se tornar um alvo em potencial.
6 CAPTULO 1. TEATRO DE OBJETOS
Captulo 2
Histria da Computao
A Computao tem sido considerada uma cincia independente desde meados do sculo XX. No entanto,
desde a antiguidade, a humanidade busca formas de automatizar os seus cmputos e de criar mquinas e m-
todos para facilitar a realizao de clculos. Neste captulo, apresentamos inicialmente uma linha do tempo
que indica alguns dos principais eventos ocorridos na histria da computao e na evoluo da arquitetura dos
computadores automticos. Em seguida, apresentamos uma linha do tempo da evoluo das linguagens de
programao.
Leibniz
7
8 CAPTULO 2. HISTRIA DA COMPUTAO
1790: criou um sistema de tear semi-automtico onde os desenhos de flores, folhas e figuras
geomtricas eram codificados em cartes perfurados
1812: havia cerca de 11 mil teares de Jacquard na Frana
a mquina despertou muitos protestos de artesos que temiam o desemprego que a mquina poderia
causar
a mquina era capaz de desenhar padres de alta complexidade como, por exemplo, um auto-retrato
de Jacquard feito com 10 mil cartes perfurados
1812: notou que muito do que se fazia em Matemtica poderia ser automatizado
iniciou projeto do "Difference Engine" (Mquina/Engenho/Engenhoca de Diferenas)
1822: terminou um prottipo da mquina e obteve financiamento do governo para constru-la
1823: iniciou a construo (usaria motor a vapor, seria totalmente automtico, imprimiria o resul-
tado e teria um programa fixo)
1833: depois de 10 anos teve uma idia melhor e abandonou tudo
Nova idia: mquina programvel, de propsito geral: "Analytical Engine" (Mquina Analtica)
manipularia nmeros de 50 dgitos
memria de 1000 dgitos
estaes de leitura leriam cartes perfurados similares ao de tear de Jacquard (nesta poca, o
auto-retrato de Jacquard pertencia a Babbage)
mas ele no conseguiu constru-lo
tecnologia mecnica da poca era insuficiente
pouca gente via a necessidade para tal mquina
Ada Lovelace (me da programao) escreveu programas para o engenho analtico; inventou a
palavra algoritmo em homenagem ao matemtico Al-Khawarizmi (820 d.C.)
Algoritmo: seqncia de operaes ou comandos que, aplicada a um conjunto de dados, permite
solucionar classes de problemas semelhantes. Exemplos: algoritmo da diviso, da raiz cbica, para
resoluo de equaes do segundo grau, etc.
a mquina foi finalmente construda pelo governo ingls nos anos 1990 (e funciona!)
MARK 1, criada em 1937 por Howard Aiken, professor de Matemtica Aplicada de Harvard
Rumo programabilidade
Alan Turing,
Trabalhou para o exrcito ingls ajudando a quebrar o cdigo criptogrfico da mquina Enigma
criada pelos alemes
Realizou importantes contribuies prticas e tericas Cincia da Computao
1912: nasce em Londres
1935: Ganha bolsa para realizar pesquisas no Kings College, Cambridge
1936: Elabora Mquina de Turing, pesquisas em computabilidade
1936-38: Princeton University. Ph.D. Lgica, lgebra, Teoria dos Nmeros
1938-39: Cambridge. apresentado mquina Enigma dos alemes
1939-40: The Bombe, mquina para decodificao do Enigma criada em Bletchley Park
1939-42: quebra Enigma do U-boat, aliados vencem batalha do Atlntico
1943-45: Consultor-chefe anglo-americano para criptologia
1947-48: Programao, redes neurais e inteligncia artificial
1948: Manchester University
1949: Pesquisas sobre usos do computador em clculos matemticos avanados
1950: Prope Teste de Turing para inteligncia de mquinas
1952: Preso por homossexualidade, perde privilgios militares
1953-54: Trabalho no finalizado em Biologia e Fsica; tem sua reputao e vida destrudas pelos
militares ingleses
10 CAPTULO 2. HISTRIA DA COMPUTAO
Aiken declarou em 1947 que nunca haveria necessidade de mais de um ou dois computadores
programveis e que os projetos neste sentido deveriam ser abandonados
Bill Gates declarou na dcada de 1980 que a Microsoft nunca desenvolveria um sistema ope-
racional de 32 bits
Anos 50
Anos 60
Anos 70
indo contra o modelo centralizador da IBM, gerao sexo, drogas e rock-and-roll da California
exige a democratizao da informtica
revista esquerdista da Universidade da Califrnia em Berkeley Peoples Computer Company de-
fende a criao de computadores pessoais e de cooperativas de informao
Steve Jobs cria a Apple em garagem em ~1975 e investe lucros do Apple II em shows de Rock (82)
nasce a Microsoft
governo da Califrnia apia microinformtica
12 CAPTULO 2. HISTRIA DA COMPUTAO
Anos 80
Anos 90
Microsoft pega carona na exploso de vendas de PCs, utiliza tcnicas de marketing agressivas
(consideradas por alguns como moralmente questionveis) para controlar o mercado de software,
estabelecendo quase um monoplio em certas reas
popularizao da Internet e criao da Web
intensifica-se o movimento do software livre
nasce o Linux e uma nova forma de desenvolvimento de software baseada em comunidades distri-
budas atravs da Internet
no final da dcada, o governo americano percebe o perigo que a Microsoft representa e inicia batalha
judicial contra a empresa (em 2002, aps a vitria dos conservadores na eleio nos EUA, o governo
termina um processo judicial que havia iniciado; as sanes empresa so mnimas)
Sculo XXI
1945, no ENIAC, a programao era feita mudando chaves e trocando a posio de cabos
2.2. EVOLUO DAS LINGUAGENS DE PROGRAMAO 13
1949-50, primeira linguagem binria, a programao era feita mudando os comandos de zero a um, e
vice-versa
1951, Grace Hooper cria o primeiro compilador, A0, programa que transforma comandos em 0s e 1s
1957, primeira linguagem de programao de alto nvel: FORTRAN (FORmula TRANslating) (John
Backus da IBM)
1958, criao de um padro universal de linguagem: ALGOL 58 (ALGOritmic Language) (origem da
maioria das linguagens modernas). Primeira linguagem estruturada
1958, John McCarthy do MIT cria o LISP (LISt Processing), inicialmente projetada para uso em inteli-
gncia artificial. Nela tudo se baseia em listas. Ainda usada hoje em dia
1959, FORTRAN era eficaz para manipulao de nmeros, mas no para entrada e sada: foi criada
COBOL (COmmon Bussines Oriented Language)
1964, criao do BASIC (Beginners All-purpose Symbolic Instruction Code)
1965, criao de uma linguagem especfica para simulao (SIMULA I) por Ole-Johan Dahl and Kristen
Nygaard da Universidade de Oslo. considerada a base das linguagens orientadas a objetos
1966, criao da linguagem Logo para desenhos grficos (a linguagem da tartaruga)
1967, Simula 67, uma linguagem de uso geral incluindo todos os conceitos fundamentais de orientao
a objetos
1968, criao da linguagem PASCAL por Niklaus Wirth. Principal interesse: linguagem para o ensino.
Combinou as melhores caractersticas de Cobol, Fortran e Algol, foi uma linguagem bem utilizada
1970, PROLOG, linguagem para programao lgica
1972, criao da linguagem C (Denis Ritchie). Supriu as deficincias da linguagem Pascal e teve sucesso
quase imediato
1972-1980, linguagem Smalltalk, desenvolvida por Alan Kay, da Xerox, utilizando as melhores carac-
tersticas de LISP, Simula 67, Logo e ambientes grficos como Sketchpad; Orientao a Objetos ganha
fora
1983, criadas extenses de C incluindo suporte para OO: C++ e Objective-C
1987, linguagens baseadas em scripts, como Perl, desenvolvida por Larry Wall. Ferramentas de UNIX
como sed e awk no eram suficientes
1994, Java lanada pela Sun como a linguagem para a Internet
2000, lanamento do C# pela Microsoft, combinando idias das linguagens Java e C++
2005, lanamento da verso 1.5 de Java
Neste livro, apresentamos, de forma muito sucinta, algumas das principais linguagens de programao. Para
referncias mais completas visite www.princeton.edu/~ferguson/adw/programming_languages.shtml e
en.wikipedia.org/wiki/Programming_language.
14 CAPTULO 2. HISTRIA DA COMPUTAO
Captulo 3
Conversor de Temperaturas
Na dramatizao, podamos enviar uma mensagem (dizer alguma coisa) para um ator. Na programao orien-
tada a objetos, podemos enviar uma mensagem para (ou chamar um mtodo de) um objeto.
Os cartes de identificao definem os papis dos atores e os scripts especificam o comportamento dos
atores no decorrer da pea. A linguagem Java permite que especifiquemos a mesma coisa. Um carto de
identificao tem 3 partes, essas mesmas 3 partes aparecem na definio de uma classe em Java. Por exemplo,
o bandeirinha em Java seria mais ou menos assim:
class Bandeirinha
{
CobranaAutorizada
{
/ / V e r i f i c a s e o g o l e i r o r e a l m e n t e no a v a n a a n t e s de o b a t e d o r . . .
}
VenceuOTime ( NomeDoTime )
{
/ / Se NomeDoTime no o nome do t i m e da casa , d i s t a n c i e s e da t o r c i d a . . .
}
}
15
16 CAPTULO 3. CONVERSOR DE TEMPERATURAS
F 32 C 9 9
= F 32 = C F = C + 32
9 5 5 5
Traduzindo esta frmula para Java temos F=9*C/5+32. A seguir iremos criar diversas classes para realizar
a converso entre Celsius e Fahrenheit.
1. Primeira tentativa: programa em Java para converter 40 graus Celsius para Fahrenheit.
c l a s s Conversor
{
int celsiusParaFahrenheit ()
{
r e t u r n 9 40 / 5 + 3 2 ;
}
}
para executar este conversor dentro do DrJava1 , podemos digitar o seguinte na janela do interpreta-
dor (chamada de interactions):
C o n v e r s o r c1 = new C o n v e r s o r ( ) ;
c1 . c e l s i u s P a r a F a h r e n h e i t ( )
2. Segunda tentativa: conversor genrico de temperaturas Celsius -> Fahrenheit. capaz de converter
qualquer temperatura de Fahrenheit para Celsius.
c l a s s Conversor2
{
int celsiusParaFahrenheit ( int c )
{
return 9 c / 5 + 32;
}
}
limitao: essa classe manipula apenas nmeros inteiros. Mas, em geral, temperaturas so nmeros
reais, fracionrios, ento nmeros inteiros no so suficientes. Quando o computador opera com
nmeros inteiros, os nmeros so truncados, ou seja, 30.3 se torna 30 e 30.9 tambm se torna 30.
Devido a esta limitao, se tivssemos escrito a frmula como 95 C + 32, o clculo seria errado,
uma vez que 59 = 1 se considerarmos apenas a parte inteira da diviso. Assim, o programa calcularia
apenas 1 C + 32.
Quando precisamos trabalhar com nmeros reais, usamos nmeros de ponto flutuante (floating point
numbers). Esse nome se deriva do fato de que internamente os nmeros so representados de forma
parecida a potncias de 10 onde, variando o expoente da potncia, movemos (flutuamos) o ponto decimal
para a esquerda ou para a direita. De floating point vem o tipo float da linguagem Java. Nmeros do tipo
float so armazenados em 4 bytes e tem uma preciso de 23 bits (o que equivale a aproximadamente
7 casas decimais). No entanto, quase sempre so utilizados nmeros de ponto flutuante com preciso
dupla que so chamados de double. Em Java, um double ocupa 8 bytes e tem preciso de 52 bits, o que
equivale a aproximadamente 16 casas decimais. Daqui para frente sempre que precisarmos de nmeros
fracionrios, vamos utilizar o tipo double. Mas lembre-se de que as variveis do tipo double so apenas
uma aproximao do nmero real, como podemos ver no exemplo abaixo:
Aps dividir o nmero 1.0 pelo nmero 310 = 59049 e depois multiplic-lo por este mesmo nmero,
obtivemos um valor diferente do inicial. Por este motivo, devemos ter muito cuidado com os erros de
arredondamento presentes quando utilizamos nmeros de ponto flutuante.
Note que, para que o seu programa fique bem legvel e elegante, muito importante o alinhamento dos
abre-chaves { com os fecha-chaves } correspondentes. Em programas mais complexos, esse correto
alinhamento (indentao) ajuda muito a tornar o programa mais claro para seres humanos.
Exerccios
1. Crie uma classe Conversor5 que inclua tambm a escala Kelvin (K). Esta classe deve conter conversores
entre as trs escalas de temperatura (Celsius, Fahrenheit e Kelvin), totalizando seis funes. A relao
entre as trs escalas dada por:
F 32 C K 273
= =
9 5 5
2. Iremos agora construir uma classe que calcula o valor de um nmero ao quadrado e ao cubo. Para tal, crie
uma classe que contenha dois mtodos. O primeiro mtodo deve receber um nmero e devolver o seu
quadrado e o segundo mtodo deve receber um nmero e devolver o seu valor ao cubo. Escolha nomes
para a classe e mtodos que facilitem a compreenso de seu funcionamento.
3. Neste exerccio iremos simular um jogo de tnis. A partida de tnis composta por diversos papis:
jogador, juiz de cadeira, juiz de linha, treinador, gandula, torcedor.
Para cada um destes papis, descreva as mensagens que os atores de cada papel devem receber, e seu com-
portamento para cada uma delas. Utilize como modelo a descrio do papel Bandeirinha apresentada
no incio deste captulo.
Captulo 4
Testes Automatizados
Desde o incio, a computao sempre esteve sujeita erros. O termo bug, para denotar erro, tem uma origem
muito anterior (vem de um inseto que causava problemas de leitura no fongrafo de Thomas Edison em 1889).
Vrias outras histrias reais, ou nem tanto, tambm apareceram no incio da informtica. Infelizmente, muito
difcil garantir que no existam erros em programas. Uma das formas de se garantir que certos erros no vo
ocorrer testando algumas situaes.
Apesar da clebre afirmao de Edsger Dijkstra 1 de que testes podem apenas mostrar a presena de erros e
no a sua ausncia, eles podem ser os nossos grandes aliados no desenvolvimento de programas corretos. Intui-
tivamente, quanto mais testes fizermos em um programa e quanto mais abrangentes eles forem, mais confiantes
podemos ficar com relao ao seu funcionamento. Por outro lado, podemos usar o prprio computador para nos
ajudar, isto , podemos criar testes automatizados. Em vez de fazermos os testes na mo, faremos com que o
computador seja capaz de verificar o funcionamento de uma seqncia de testes. Veremos neste captulo como
desenvolver testes automatizados, passo a passo, para os conversores de temperatura vistos anteriormente.
No incio da computao no havia uma preocupao muito grande com os testes, que eram feitos de forma
manual pelos prprios programadores. Os grandes testadores eram os usurios finais. interessante notar que
isto acontece com alguns produtos ainda hoje. Com o aparecimento da Engenharia de Software ficou clara
a necessidade de se efetuarem testes, tanto que em vrias empresas de desenvolvimento de software existe
a figura do testador, responsvel por tentar encontrar erros em sistemas. Hoje existe uma tendncia para se
1 Um dos mais influentes membros da gerao dos criadores da Cincia da Computao. A pgina http://www.cs.utexas.edu/
19
20 CAPTULO 4. TESTES AUTOMATIZADOS
considerar que testes automatizados so muito importantes, devendo ser escritos mesmo antes de se escrever o
cdigo propriamente dito, tcnica esta chamada de testes a priori.
Veremos como testar os diversos conversores de temperatura. Como testar o nosso primeiro programa em
Java (Conversor).
C o n v e r s o r c1 = new C o n v e r s o r ( )
/ / a r e s p o s t a e s p e r a d a o e q u i v a l e n t e a 40C em F
i f ( c1 . c e l s i u s P a r a F a h r e n h e i t ( ) == 1 0 4 )
System . o u t . p r i n t l n ( " F u n c i o n a " ) ;
else
System . o u t . p r i n t l n ( " No f u n c i o n a " ) ;
Note que para fazer o teste utilizamos o comando condicional if else. O formato genrico deste comando
o seguinte.
i f (CONDIO)
COMANDO1;
else
COMANDO2;
/ / c r i a duas v a r i v e i s i n t e i r a s
int entrada = 40;
int r e s p o s t a = 104;
/ / a r e s p o s t a e s p e r a d a o e q u i v a l e n t e e n t r a d a C em F
i f ( c2 . c e l s i u s P a r a F a h r e n h e i t ( e n t r a d a ) == r e s p o s t a )
System . o u t . p r i n t l n ( " F u n c i o n a " ) ;
else
System . o u t . p r i n t l n ( " No f u n c i o n a " ) ;
Note que, para realizar o teste acima, definimos duas variveis inteiras chamadas de entrada e resposta.
A linha
int entrada = 40;
faz na verdade duas coisas. Primeiro, ela declara a criao de uma nova varivel (int entrada;) e, depois,
atribui um valor inicial a esta varivel (entrada = 40;). Na linguagem Java, se o valor inicial de uma varivel
no atribudo, o sistema atribui o valor 0 varivel automaticamente. Note que isso no necessariamente
verdade em outras linguagens como, por exemplo, C e C++.
Podemos tambm testar o Conversor2 para outros valores. Por exemplo, para as entradas (e respostas): 20
(68) e 100 (212).
e n t r a d a = 2 0 ; / / como a s v a r i v e i s j f o r a m d e c l a r a d a s acima , b a s t a usl a s
r e s p o s t a = 68;
i f ( c2 . c e l s i u s P a r a F a h r e n h e i t ( e n t r a d a ) == r e s p o s t a )
System . o u t . p r i n t l n ( " F u n c i o n a " ) ;
else
21
entrada = 100;
r e s p o s t a = 212;
i f ( c2 . c e l s i u s P a r a F a h r e n h e i t ( e n t r a d a ) == r e s p o s t a )
System . o u t . p r i n t l n ( " F u n c i o n a " ) ;
else
System . o u t . p r i n t l n ( " No f u n c i o n a " ) ;
No programa acima o texto Funciona ser impresso na tela a cada sucesso, o que poder causar uma
poluio visual caso tenhamos dezenas ou centenas de testes. O ideal para um testador que ele fique silencioso
caso os testes dem certo e chame a ateno caso ocorra algum erro. Podemos ento mudar o programa para:
C o n v e r s o r 2 c2 = new C o n v e r s o r 2 ( ) ;
entrada = 20;
r e s p o s t a = 68;
i f ( c2 . c e l s i u s P a r a F a h r e n h e i t ( e n t r a d a ) ! = r e s p o s t a )
System . o u t . p r i n t l n ( " No f u n c i o n a p a r a 20 " ) ;
entrada = 100;
r e s p o s t a = 212;
i f ( c2 . c e l s i u s P a r a F a h r e n h e i t ( e n t r a d a ) ! = r e s p o s t a )
System . o u t . p r i n t l n ( " No f u n c i o n a p a r a 100 " ) ;
Note que o comando if acima foi utilizado sem a parte do else, o que perfeitamente possvel. Adicio-
namos tambm uma linha final para informar o trmino dos testes. Ela importante no caso em que todos os
testes do certo para que o usurio saiba que a execuo dos testes foi encerrada.
Uma forma de simplificar os comandos de impresso usar a prpria entrada como parmetro, o que pode
ser feito da seguinte forma:
System . o u t . p r i n t l n ( " No f u n c i o n a p a r a " + e n t r a d a ) ;
Criaremos agora os testes para o Conversor4. Mas, agora, devem ser testados os seus dois mtodos.
Introduziremos um testador automtico criando uma classe com apenas um mtodo que faz o que vimos.
class TestaConversor4
{
int testaTudo ()
{
C o n v e r s o r 4 c4 = new C o n v e r s o r 4 ( ) ;
double c e l s i u s = 1 0 . 0 ;
double f a h r e n h e i t = 5 0 . 0 ;
i f ( c4 . c e l s i u s P a r a F a h r e n h e i t ( c e l s i u s ) ! = f a h r e n h e i t )
System . o u t . p r i n t l n ( "C> F no f u n c i o n a p a r a " + c e l s i u s ) ;
22 CAPTULO 4. TESTES AUTOMATIZADOS
i f ( c4 . f a h r P a r a C e l s i u s ( f a h r e n h e i t ) ! = c e l s i u s )
System . o u t . p r i n t l n ( " F> C no f u n c i o n a p a r a " + f a h r e n h e i t ) ;
celsius = 20.0;
fahrenheit = 68.0;
i f ( c4 . c e l s i u s P a r a F a h r e n h e i t ( c e l s i u s ) ! = f a h r e n h e i t )
System . o u t . p r i n t l n ( "C> F no f u n c i o n a p a r a " + c e l s i u s ) ;
i f ( c4 . f a h r P a r a C e l s i u s ( f a h r e n h e i t ) ! = c e l s i u s )
System . o u t . p r i n t l n ( " F> C no f u n c i o n a p a r a " + f a h r e n h e i t ) ;
celsius = 101.0;
fahrenheit = 213.8;
i f ( c4 . c e l s i u s P a r a F a h r e n h e i t ( c e l s i u s ) ! = f a h r e n h e i t )
System . o u t . p r i n t l n ( "C> F no f u n c i o n a p a r a " + c e l s i u s ) ;
i f ( c4 . f a h r P a r a C e l s i u s ( f a h r e n h e i t ) ! = c e l s i u s )
System . o u t . p r i n t l n ( " F> C no f u n c i o n a p a r a " + f a h r e n h e i t ) ;
System . o u t . p r i n t l n ( " F i n a l d o s t e s t e s " ) ;
return 0;
}
}
Comentrios: Voc deve ter notado que, no meio de alguns exemplos de cdigo Java
deste captulo, ns introduzimos uns comentrios em portugus. Comentrios deste tipo
so possveis em praticamente todas as linguagens de programao e servem para ajudar
os leitores do seu cdigo a compreender mais facilmente o que voc escreveu.
Comentrios em Java podem ser inseridos de duas formas. O smbolo // faz com que
tudo o que aparecer aps este smbolo at o final da linha seja ignorado pelo compilador
Java; este o formato que utilizamos neste captulo e que utilizaremos quase sempre neste
livro.
A segunda forma atravs dos smbolos /* (que indica o incio de um comentrio) e */
(que indica o final de um comentrio). Neste caso, um comentrio pode ocupar vrias li-
nhas. Esta tcnica tambm til para desprezarmos temporariamente um pedao do nosso
programa. Por exemplo, se queremos testar se uma classe funciona mesmo se remover-
mos um de seus mtodos, no necessrio apagar o cdigo do mtodo. Basta acrescentar
um /* na linha anterior ao incio do mtodo, acrescentar um */ logo aps a ltima linha
do mtodo e recompilar a classe. Posteriormente, se quisermos reinserir o mtodo, basta
remover os smbolos de comentrios.
Outro uso para este ltimo tipo de comentrios quando desejamos testar uma verso
alternativa de um mtodo. Comentamos a verso antiga do mtodo, inserimos a verso
nova e testamos a classe. Podemos a decidir qual verso utilizar e, ento, remover a que
no mais ser usada.
Agora, vamos treinar o que aprendemos com alguns exerccios. Em particular, os exerccios 3, de refatora-
o, e 4, que indica quais casos devem ser testados, so muito importantes.
Exerccios
1. Escreva uma classe TestaConversor3 para testar a classe Conversor3.
23
3. Importante: Podemos criar testes para objetos de uma classe que no sabemos como foi implementada.
Para tal, basta conhecermos suas entradas e sadas. Escreva um teste automatizado para a seguinte classe:
c l a s s Contas
{
double c a l c u l a Q u a d r a d o ( double x ) ;
double c a l c u l a C u b o ( double x ) ;
}
Ao escrever o teste, pense em testar vrios casos com caractersticas diferentes. Em particular, no deixe
de testar os casos limtrofes que , geralmente, onde a maioria dos erros tendem a se concentrar. Na
classe Contas acima, os casos interessantes para teste seriam, por exemplo:
x = 0;
x um nmero positivo pequeno;
x um nmero negativo pequeno;
x um nmero positivo grande;
x um nmero negativo grande.
Alm disso, seria interessante que, em alguns dos casos acima, x fosse um nmero inteiro e em outros
casos, um nmero fracionrio.
4. Programas confiveis: Se conhecemos uma implementao e sabemos que a mesma funciona de maneira
confivel, ela pode servir de base para o teste de outras implementaes. Caso duas implementaes
diferentes produzam resultados distintos para os mesmos dados de entrada, podemos dizer que pelo
menos uma das duas est errada;
Supondo que a classe Contas do exerccio anterior confivel, escreva um teste automatizado que utiliza
esta classe para testar a classe ContasNoConfiavel dada abaixo:
c l a s s ContasNoConfivel
{
double c a l c u l a Q u a d r a d o ( double x ) ;
double c a l c u l a C u b o ( double x ) ;
}
Resolues
Exerccio 2
class TesteConversor4Refatorado
{
i n t t e s t e P o n t u a l ( double c e l s i u s , double f a h r e n h e i t )
{
C o n v e r s o r c4 = new C o n v e r s o r 4 ( ) ;
24 CAPTULO 4. TESTES AUTOMATIZADOS
i f ( c4 . c e l s i u s P a r a F a h r e n h e i t ( c e l s i u s ) ! = f a h r e n h e i t )
System . o u t . p r i n t l n ( "C> F no f u n c i o n a p a r a " + c e l s i u s ) ;
i f ( c4 . f a h r P a r a C e l s i u s ( f a h r e n h e i t ) ! = c e l s i u s )
System . o u t . p r i n t l n ( " F> C no f u n c i o n a p a r a " + f a h r e n h e i t ) ;
return 0;
}
int testaTudo ()
{
double c e l s i u s = 1 0 . 0 ;
double f a h r e n h e i t = 5 0 . 0 ;
testePontual ( celsius , fahrenheit );
celsius = 20.0;
fahrenheit = 68.0;
testePontual ( celsius , fahrenheit );
celsius = 101.0;
fahrenheit = 213.8;
testePontual ( celsius , fahrenheit );
System . o u t . p r i n t l n ( " F i n a l d o s t e s t e s " ) ;
return 0;
}
}
Exerccio 3
class TesteContas
{
int teste ()
{
C o n t a s c o n t a s = new C o n t a s ( ) ;
double v a l o r = 4 . 0 ;
i f ( c o n t a s . c a l c u l a Q u a d r a d o ( v a l o r ) != 1 6 . 0 )
System . o u t . p r i n t l n ( " No f u n c i o n a p a r a c a l c u l a r o q u a d r a d o de 4 " ) ;
i f ( c o n t a s . c a l c u l a C u b o ( v a l o r ) != 6 4 . 0 )
System . o u t . p r i n t l n ( " No f u n c i o n a p a r a c a l c u l a r 4 ao cubo " ) ;
return 0;
}
}
Captulo 5
No ltimo captulo, vimos um mtodo que recebe vrios parmetros. Apesar de no estarmos apresentando
nenhuma novidade conceitual, vamos reforar a possibilidade da passagem de mais de um parmetro.
Ao chamarmos um mtodo que recebe mltiplos parmetros, assim como no caso de mtodos de um pa-
rmetro, devemos passar valores do mesmo tipo que aqueles que o mtodo est esperando. Por exemplo, se
um objeto (ator) tem um mtodo (entende uma mensagem) que tem como parmetro um nmero inteiro, no
podemos enviar a este objeto um nmero double. Apesar de ser intuitivo, tambm vale ressaltar que a ordem
dos parmetros importante, de modo que na chamada de um mtodo devemos respeitar a ordem que est na
sua definio.
Vamos comear com o clculo da rea de uma circunferncia, onde necessrio apenas um parmetro, o
raio:
class Crculo1
{
double c a l c u l a r e a ( double r a i o )
{
return 3.14159 r a i o r a i o ;
}
}
25
26 CAPTULO 5. MTODOS COM VRIOS PARMETROS
Nota Lingstica: Em Java, o nome de variveis, classes e mtodos pode conter ca-
racteres acentuados. Muitos programadores evitam o uso de acentuao mesmo ao usar
nomes em portugus. Este costume advm de outras linguagens mais antigas, como C,
que no permitem o uso de caracteres acentuados. Voc pode usar caracteres acentuados
se quiser mas lembre-se que, se voc tiver uma varivel chamada rea, ela ser diferente
de outra chamada area (sem acento); ou seja, se voc decidir usar acentos, dever us-los
consistentemente sempre.
O seguinte trecho de cdigo calcula e imprime a rea e o permetro de uma circunferncia de raio 3.0:
C r c u l o 1 c = new C r c u l o 1 ( ) ;
System . o u t . p r i n t l n ( c . c a l c u l a r e a ( 3 . 0 ) ) ;
System . o u t . p r i n t l n ( c . c a l c u l a P e r m e t r o ( 3 . 0 ) ) ;
Vejamos agora uma classe Retngulo que define mtodos para o clculo do permetro e da rea de um
retngulo. Neste caso so necessrios dois parmetros.
c l a s s Retngulo1
{
i n t c a l c u l a r e a ( i n t lado1 , i n t lado2 )
{
return lado1 lado2 ;
}
i n t c a l c u l a P e r m e t r o ( i n t lado1 , i n t lado2 )
{
return 2 ( lado1 + lado2 ) ;
}
}
System . o u t . p r i n t l n ( r . c a l c u l a r e a ( 2 , 3 ) ) ;
System . o u t . p r i n t l n ( r . c a l c u l a P e r m e t r o ( 2 , 3 ) ) ;
5.1 Atributos
Assim como no exemplo do teatrinho dos objetos onde os jogadores tinham como caracterstica o time e o
nmero da camisa (atributos), tambm podemos ter algo semelhante para o caso dos retngulos. Podemos fazer
com que os dados sobre os lados sejam caractersticas dos objetos. Isto feito da seguinte forma:
5.1. ATRIBUTOS 27
c l a s s Retngulo2
{
int lado1 ;
int lado2 ;
int calcularea ()
{
return lado1 lado2 ;
}
int calculaPermetro ()
{
return 2 ( lado1 + lado2 ) ;
}
}
Na classe acima, lado1 e lado2 so atributos que faro parte de todas as instncias da classe Retngulo2.
Um atributo, por ser definido fora dos mtodos, pode ser acessados a partir de qualquer mtodo da classe onde
ele definido. Atributos so tambm chamados de propriedades ou variveis de instncia.
No entanto, no exemplo acima, ficou faltando algum mtodo para carregar os valores dos lados nas variveis
lado1 e lado2. Poderamos escrever um mtodo para cada atributo ou ento, apenas um mtodo para definir o
valor de ambos como no exemplo seguinte:
v o i d c a r r e g a L a d o s ( i n t l 1 , i n t l 2 ) / / e s t e mtodo no d e v o l v e nenhum v a l o r
{
lado1 = l1 ;
lado2 = l2 ;
}
Nota Lingstica: void em ingls significa vazio, nada ou nulidade. Assim, quando
temos um mtodo que no devolve nenhum valor, como, por exemplo, o mtodo
carregaLados acima, colocamos a palavra void antes da definio do mtodo para indi-
car que ele no devolver nada. Neste caso, no necessrio incluir o comando return
no corpo do mtodo. Mesmo assim, podemos usar um comando de retorno vazio para pro-
vocar o fim prematuro da execuo do mtodo, como em: return ; . O uso do return
vazio nem sempre recomendado pois, em alguns casos, pode gerar cdigo pouco claro,
mas uma opo permitida pela linguagem.
O funcionamento de um objeto da classe Retngulo2 pode ser verificado com o cdigo abaixo:
R e t n g u l o 2 r = new R e t n g u l o 2 ( ) ;
r . carregaLados (3 , 5);
System . o u t . p r i n t l n ( r . c a l c u l a r e a ( ) ) ;
System . o u t . p r i n t l n ( r . c a l c u l a P e r m e t r o ( ) ) ;
Para no perdermos o hbito, tambm veremos como testar esta classe. Neste caso, temos duas opes:
criar diversos objetos do tipo Retngulo2, um para cada teste, ou carregar diversos lados no mesmo objeto.
Abaixo, a cada chamada de TestePontual, um novo Retngulo2 criado:
28 CAPTULO 5. MTODOS COM VRIOS PARMETROS
class TestaRetngulo
{
void t e s t e P o n t u a l ( i n t l1 , i n t l 2 )
{
R e t n g u l o 2 r = new R e t n g u l o 2 ( ) ;
r . c a r r e g a L a d o s ( l1 , l 2 ) ;
i f ( r . c a l c u l a r e a ( ) != l 1 l 2 )
System . o u t . p r i n t l n ( " No f u n c i o n a r e a p a r a l a d o s "
+ l1 + " e " + l2 ) ;
i f ( r . c a l c u l a P e r m e t r o ( ) != 2 ( l 1 + l 2 ) )
System . o u t . p r i n t l n ( " No f u n c i o n a p e r m e t r o p a r a l a d o s "
+ l1 + " e " + l2 ) ;
}
void testaTudo ( )
{
t e s t e P o n t u a l (10 , 20);
testePontual (1 , 2);
testePontual (3 , 3);
}
}
Da mesma forma que os lados foram atributos para a classe Retngulo2, podemos fazer o mesmo para a
classe Crculo1.
class Crculo2
{
double r a i o ;
void c a r r e g a R a i o ( double r )
{
raio = r ;
}
double c a l c u l a r e a ( )
{
return 3.14159 r a i o r a i o ;
}
double c a l c u l o P e r m e t r o ( )
{
return 3.14159 2.0 r a i o ;
}
}
Assim como vimos anteriormente podemos tambm utilizar objetos de uma classe sem conhecer a sua
implementao. Por exemplo, suponha que temos acesso a uma classe Clculo que possui o seguinte mtodo:
int calculaPotncia ( int x , int n );
Exerccios
1. Neste exerccio, construiremos uma classe que calcula a mdia aritmtica de 4 notas e diz se o dono das
notas foi aprovado, est de recuperao ou foi reprovado. Por exemplo,
Entrada:
Sada:
Mdia: 8.15 -> aprovado.
Mdia: 4.3 -> recuperao.
Mdia: 2.9 -> reprovado.
Para isso, crie uma classe Aluno com mtodos que carreguem as 4 notas em variveis p1, p2, p3, p4 e
um mtodo responsvel por calcular a mdia aritmtica das notas e dar o veredito.
2. Escreva uma classe Ol com um nico mtodo cumprimenta que, a cada chamada, cumprimenta o
usurio de uma entre 3 maneiras diferentes. Dica: use um atributo para, dependendo de seu valor,
escolher qual das maneiras ser usada; depois de imprimir a mensagem, altere o valor do atributo.
3. Construa a classe Inteiro que representa um nmero inteiro. Essa classe deve ter os seguintes atributos
e mtodos:
Classe Inteiro
Atributos:
int valor
Valor do inteiro representado.
Valor: -473158.
Classe Inteiro
Se quiser, voc tambm pode fazer verses desses mtodos que no alteram o valor representado, apenas
devolvem o valor da conta.
5. Crie uma classe TestaInteiro que verifica o funcionamento correto da classe Inteiro em diversas
situaes. Lembre-se de verificar casos como a diviso por diversos valores. Ao escrever os testes, voc
notar que a classe Inteiro tem uma limitao importante no mtodo dividePor.
6. Crie uma classe Aluno2 para calcular a mdia aritmtica de 4 notas. Mas no lugar de um mtodo que
recebe 4 parmetros, a classe deve conter 4 mtodos recebeNotaX, onde X = 1, 2, 3 ou 4, para receber
as notas das provas, de modo que cada mtodo receba apenas uma nota. A classe deve conter ainda
um mtodo imprimeMdia que imprime a mdia final do aluno, dizendo se ele foi aprovado ou repro-
vado. Em seguida, escreva uma classe TestaAluno2 que verifica se a classe Aluno2 calcula as mdias
corretamente.
32 CAPTULO 5. MTODOS COM VRIOS PARMETROS
if else Encaixados
No Captulo 4, vimos pela primeira vez o conceito de desvio condicional atravs dos comandos if e else.
Entretanto, vimos exemplos iniciais onde apenas um comando simples era executado, no caso, comandos de
impresso. Na prtica, comandos if e else podem ser encaixados de forma a criar estruturas muito complexas.
Para isto, veremos inicialmente como criar blocos de comandos atravs do seguinte exemplo:
i f (CONDIO)
{ / / i n c i o do b l o c o
COMANDO1;
COMANDO2;
...
COMANDOn ;
}
Neste trecho de cdigo, caso a CONDIO seja verdadeira, os comandos, de 1 a n, so executados seqen-
cialmente. Veremos a seguir que comum que alguns destes comandos sejam tambm comandos de desvio
condicional.
Vamos iniciar programando uma classe para representar um tringulo retngulo. Ela contm um mtodo
que, dados os comprimentos dos lados do tringulo, verifica se o mesmo retngulo ou no.
class TrianguloRetngulo
{
void v e r i f i c a L a d o s ( i n t a , i n t b , i n t c )
{
i f ( a b c ! = 0 ) / / nenhum l a d o pode s e r n u l o
{
i f ( a a == b b + c c )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
i f ( b b == a a + c c )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
33
34 CAPTULO 6. IF ELSE ENCAIXADOS
i f ( c c == a a + b b )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
}
}
}
Limitaes:
1. mesmo que um if seja verdadeiro, ele executa os outros ifs. Em particular, se tivssemos um tringulo
retngulo para o qual vrios desses ifs fossem verdadeiros, ele imprimiria esta mensagem vrias vezes
(neste exemplo especfico, isto no possvel);
2. este mtodo s imprime uma mensagem se os dados correspondem s medidas de um tringulo retngulo,
se no um tringulo retngulo, ele no imprime nada. Atravs do uso do else podemos imprimir
mensagens afirmativas e negativas:
class TrianguloRetngulo2
{
void v e r i f i c a L a d o s ( i n t a , i n t b , i n t c )
{
i f ( a b c ! = 0 ) / / nenhum l a d o pode s e r n u l o
{
i f ( a a == b b + c c )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
e l s e i f ( b b == a a + c c )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
e l s e i f ( c c == a a + b b )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
else
System . o u t . p r i n t l n ( " No t r i n g u l o r e t n g u l o . " ) ;
}
else
System . o u t . p r i n t l n ( " No t r i n g u l o p o i s p o s s u i l a d o de c o m p r i m e n t o n u l o . " ) ;
}
}
Caso sejam necessrios outros mtodos, como um para o clculo de permetro, interessante colocar os
lados como atributos da classe.
class TrianguloRetngulo3
{
int a , b , c ;
void c a r r e g a L a d o s ( i n t l1 , i n t l2 , i n t l 3 )
{
a = l1 ;
b = l2 ;
c = l3 ;
35
}
int calculaPermetro ()
{
return a + b + c ;
}
void v e r i f i c a L a d o s ( )
{
i f ( a b c ! = 0 ) / / nenhum l a d o pode s e r n u l o
{
i f ( a a == b b + c c )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
e l s e i f ( b b == a a + c c )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
e l s e i f ( c c == a a + b b )
System . o u t . p r i n t l n ( " T r i n g u l o r e t n g u l o . " ) ;
else
System . o u t . p r i n t l n ( " No t r i n g u l o r e t n g u l o . " ) ;
}
else
System . o u t . p r i n t l n ( " No t r i n g u l o p o i s p o s s u i l a d o de c o m p r i m e n t o n u l o . " ) ;
}
}
Exerccios
1. Voc foi contratado por uma agncia de viagens para escrever uma classe em Java para calcular a conver-
so de reais para dlar de acordo com a taxa de compra e a taxa de venda. Para isso, escreva uma classe
ConversorMonetrio que inclua os seguintes mtodos:
Em seguida, escreva uma classe TestaConversorMonetrio que define diferentes taxas de compra e
venda de dlares e, para cada taxa de converso, realiza operaes de compra e venda.
2. Escreva uma classe Baskara que possui 3 atributos do tipo double correspondentes aos coeficientes a,
b e c de uma equao do segundo grau. Escreva um mtodo para carregar valores nestes atributos e, em
seguida, escreva os 4 mtodos seguintes:
Para calcular a raiz quadrada, voc pode utilizar o mtodo java.lang.Math.sqrt(double x), que
recebe um double como parmetro e devolve outro double. Voc pode supor que o primeiro coeficiente,
a, diferente de 0.
3. Crie uma classe contendo um mtodo que, dado um ponto determinado pelas suas coordenadas x e y,
reais, imprime em qual quadrante este ponto est localizado. O primeiro quadrante corresponde aos
pontos que possuem x e y positivos, o segundo quadrante a x positivo e y negativo e assim por diante.
Para resolver este exerccio, ser necessrio utilizar os operadores < e >. Sua utilizao similar do
operador == utilizado at agora.
4. [Desafio!] So apresentadas a voc doze esferas de aparncia idntica. Sabe-se que apenas uma delas
levemente diferente das demais em massa, mas no se sabe qual e nem se a massa maior ou menor.
Sua misso identificar essa esfera diferente e tambm dizer se ela mais ou menos pesada. Para isso
voc tem apenas uma balana de prato (que s permite determinar igualdades/desigualdades). Ah, sim,
pequeno detalhe: o desafio completar a misso em no mais que trs pesagens.
Escreva um programa que resolve esse desafio. O seu programa deve dar uma resposta correta sempre e
tambm informar as trs ou menos pesagens que permitiram concluir a resposta. Como esse problema
um tanto complicado, recomendamos que voc implemente o modelo descrito no quadro a seguir.
Cada esfera deve ser representada por um inteiro entre 1 e 12. Para representarmos a esfera diferente,
usaremos, alm do identificador inteiro, uma varivel booleana que receber o valor true se a esfera for
mais pesada ou o valor false se a esfera for mais leve.
Importante: note que, para que o problema tenha sentido, o mtodo resolveDesafioDasDozeEsferas no
deve de modo algum acessar os atributos esferaDiferente e maisPesada para inferir a resposta. Quem d
pistas para este mtodo sobre o valor desses atributos so os mtodos pesa#x#.
Lembre-se de que voc tambm pode implementar mtodos adicionais, se achar necessrio ou mais
elegante. Ou ainda, se voc j se sente seguro(a), voc pode implementar a(s) sua(s) prpria(s) classe(s).
Exemplo de uso no DrJava:
Note que a resposta est errada! (Alm disso, as pesagens no permitem dar a resposta certa.)
38 CAPTULO 6. IF ELSE ENCAIXADOS
Classe DesafioDasEsferas
Atributos:
int esferaDiferente
Identificador da esfera com peso diferente.
boolean maisPesada
Diz se a esfera diferente ou no mais pesada que as demais (isto , true
para mais pesada e false para mais leve).
int numPesagens
Representa o nmero de pesagens realizadas.
Mtodos para interao com o usurio:
void defineEsferaDiferente(int esfera, boolean pesada)
Determina qual a esfera diferente (parmetro esfera), e se ela mais pesada ou
no (parmetro pesada). Alm disso, reinicia as pesagens, isto , o nmero de
pesagens realizadas volta a ser zero.
void resolveDesafioDasDozeEsferas()
Resolve o Desafio das Doze das Esferas. Este mtodo deve imprimir as 3 (ou
menos) pesagens feitas, e no final a resposta correta. Este mtodo deve se utilizar
dos mtodos para uso interno descritos abaixo. Dica: na implementao deste
mtodo voc tambm usar uma quantidade grande de ifs e elses encaixados.
Mtodos para uso interno da classe:
int pesa1x1(int e1, int d1)
int pesa2x2(int e1, int e2, int d1, int d2)
int pesa3x3(int e1, int e2, int e3, int d1, int d2, int d3)
int pesa4x4(int e1, int e2, int e3, int e4, int d1, int d2,
int d3, int d4)
int pesa5x5(int e1, int e2, int e3, int e4, int e5, int d1,
int d2, int d3, int d4, int d5)
int pesa6x6(int e1, int e2, int e3, int e4, int e5, int e6,
int d1, int d2, int d3, int d4, int d5, int d6)
At agora, todos os programas que vimos lidavam com apenas um objeto. No entanto, podemos ter progra-
mas que lidam com vrios objetos. Estes objetos podem pertencer todos mesma classe ou a classes diferentes.
Exemplo:
floquinho . lata ( ) ;
mingau . mie ( ) ;
to poGi ggio . comaQueijo ( ) ;
mingau . p e r s i g a ( t o p o G i g g i o )
f l o q u i n h o . p e r s i g a ( mingau ) ;
mimosa . p a s s e P o r C i m a ( f l o q u i n h o , mingau , t o p o G i g g i o ) ;
39
40 CAPTULO 7. PROGRAMAS COM VRIOS OBJETOS
Vejamos agora um exemplo de utilizao de objetos de 3 tipos diferentes em conjunto. Neste exemplo,
teremos 3 classes representando prismas, quadrados e tringulos retngulos e criaremos uma instncia de
quadrado, uma de tringulo retngulo e duas de prismas.
Note, no exemplo abaixo, que utilizamos um padro diferente para nomear os mtodos que servem para
atribuir valores aos atributos. Segundo este padro, muito utilizado por programadores avanados em
linguagens como C++ e Smalltalk, o nome do mtodo exatamente o nome do atributo correspondente.
Por exemplo, o mtodo void altura(double a) utilizado para definir o valor do atributo altura
e assim por diante. Ao escrever seus programas, voc livre para escolher entre qualquer um dos pa-
dres existentes, mas importante que voc seja coerente, ou seja, aps escolher o padro de nomeao,
aplique-o consistentemente em todo o seu cdigo.
c l a s s Prisma
{
double a l t u r a ;
double reaDaBase ;
void a l t u r a ( double a )
{
altura = a;
}
d o u b l e volume ( )
{
return reaDaBase a l t u r a ;
}
}
c l a s s Quadrado
{
double l a d o ;
void l a d o ( double l )
{
lado = l ;
}
double r e a ( )
{
return lado lado ;
}
}
class TrianguloRetngulo
{
double c a t e t o 1 ;
double c a t e t o 2 ;
41
double r e a ( )
{
return c a t e t o 1 c a t e t o 2 / 2 . 0 ;
}
}
Agora, utilizando o interpretador, podemos criar objetos destes vrios tipos e utiliz-los em conjunto:
Quadrado q = new Quadrado ( ) ;
T r i a n g u l o R e t n g u l o t r = new T r i a n g u l o R e t n g u l o ( ) ;
P r i s m a p r i s m a B a s e Q u a d r a d a = new P r i s m a ( ) ;
P r i s m a p r i s m a B a s e T r i a n g u l a r = new P r i s m a ( ) ;
q . lado ( 1 0 . 0 ) ;
tr . cateto1 (20.0);
tr . cateto2 (30.0);
prismaBaseQuadrada . a l t u r a ( 3 . 0 ) ;
prismaBaseTriangular . altura ( 1 . 0 ) ;
prismaBaseQuadrada . reaDaBase ( q . r e a ( ) ) ;
p r i s m a B a s e T r i a n g u l a r . reaDaBase ( t r . r e a ( ) ) ;
Nota sobre o interpretador do DrJava: para conseguir digitar todos os ifs encaixados no interpretador
do DrJava sem que ele tente interpretar cada linha em separado, preciso utilizar Shift+Enter em vez de
apenas Enter no final de cada linha dos ifs encaixados. Apenas no final da ltima linha (a que contm o
println final) que se deve digitar apenas Enter para que o DrJava ento interprete todas as linhas de
uma vez.
Exerccios
1. Utilizando a classe Conversor5 definida no exerccio 1 do Captulo 3, escreva uma classe contendo trs
mtodos, onde cada mtodo recebe uma temperatura x utilizando uma escala de temperaturas e imprime
os valores de x nas demais escalas de temperatura.
2. Escreva uma classe Rendimentos que contenha os seguintes mtodos a fim de contabilizar o total de
rendimentos de uma certa pessoa em um certo ano:
42 CAPTULO 7. PROGRAMAS COM VRIOS OBJETOS
rendimentosDePessoaFsica(double);
rendimentosDePessoaJurdica(double);
rendimentosDeAplicaesFinanceiras(double);
rendimentosNoTributveis(double);
double totalDeRendimentosTributveis();
um mtodo alquota() que recebe como parmetro o total de rendimentos tributveis de uma
pessoa e devolve um nmero entre 0 e 1.0 correspondente alquota de imposto que a pessoa
dever pagar e
um mtodo valorADeduzir() que recebe como parmetro o total de rendimentos tributveis de
uma pessoa e devolve o valor a deduzir no clculo do imposto.
Agora escreva uma classe CalculadoraDeImposto que possui um nico mtodo que recebe como par-
metro o valor dos rendimentos tributveis de uma pessoa e devolve o valor do imposto a ser pago.
Finalmente, escreva um trecho de cdigo (para ser digitado no interpretador) que utiliza Rendimentos
para definir os vrios rendimentos de uma pessoa e CalculadoraDeImposto para calcular o imposto a
pagar.
class A
{
d o u b l e a ( i n t meses , d o u b l e t a x a )
{
r e t u r n Math . pow ( ( t a x a + 1 0 0 ) / 1 0 0 , meses ) 1 ;
}
}
class B
{
f i n a l d o u b l e TAXA = 1 . 2 ;
v o i d b ( d o u b l e v a l o r E m p r e s t a d o , i n t meses )
{
A a = new A ( ) ;
d o u b l e v a l o r D a D v i d a = v a l o r E m p r e s t a d o + ( a . a ( meses , TAXA) v a l o r E m p r e s t a d o ) ;
43
(a) O que fazem os mtodos a (da classe A) e b (da classe B)? No precisa entrar em detalhes. Dica:
para saber o que Math.pow faz consulte a pgina http://java.sun.com/j2se/1.5.0/docs/
api/java/lang/Math.html;
(b) Os nomes a e b (dos mtodos) e A e B (das classes) so pssimos. Por qu? Que nomes voc daria?
Sugira, tambm, outro nome para a varivel objeto (criada no interpretador);
(c) Acrescente alguns comentrios no cdigo do mtodo b;
(d) Seria mais fcil digitar o valor 1.2 quando necessrio, em vez de criar uma constante TAXA e utiliz-
la. Ento, por que isso foi feito? Cite, pelo menos, dois motivos. A palavra chave final faz com
que o valor da varivel TAXA, uma vez atribudo, no possa ser alterado.
44 CAPTULO 7. PROGRAMAS COM VRIOS OBJETOS
Captulo 8
Laos e Repeties
Welcome to DrJava.
> Conversor4 c = new Conversor4()
> c.fahrenheitParaCelsius(0)
-17.77777777777778
> c.fahrenheitParaCelsius(10)
-12.222222222222221
> c.fahrenheitParaCelsius(20)
-6.666666666666667
> c.fahrenheitParaCelsius(30)
-1.1111111111111112
45
46 CAPTULO 8. LAOS E REPETIES
> c.fahrenheitParaCelsius(40)
4.444444444444445
> c.fahrenheitParaCelsius(50)
10.0
> c.fahrenheitParaCelsius(60)
15.555555555555555
> c.fahrenheitParaCelsius(70)
21.11111111111111
> c.fahrenheitParaCelsius(80)
26.666666666666668
> c.fahrenheitParaCelsius(90)
32.22222222222222
> c.fahrenheitParaCelsius(100)
37.77777777777778
> c.fahrenheitParaCelsius(110)
43.333333333333336
>
Pronto, agora s copiar as linhas acima para um editor de textos, retirar as chamadas ao mtodo
fahrenheitParaCelsius (pois elas confundem) e imprimir a tabela.
Ser que existe algo de especial nas diversas chamadas do mtodo fahrenheitParaCelsius acima? Todas
elas so muito parecidas e fcil adivinhar a prxima se sabemos qual a passada. Ou seja, a lei de formao das
diversas chamadas do mtodo simples e bem conhecida. No seria interessante se fosse possvel escrever um
trecho de cdigo compacto que representasse essa idia? Para isso servem os laos: eles permitem a descrio
de uma seqncia de operaes repetitivas.
Welcome to DrJava.
> int a = 1;
> while (a <= 10)
{
System.out.println("O valor atual de a : " + a);
a = a + 1;
}
O valor atual de a : 1
O valor atual de a : 2
O valor atual de a : 3
O valor atual de a : 4
O valor atual de a : 5
O valor atual de a : 6
O valor atual de a : 7
O valor atual de a : 8
O valor atual de a : 9
O valor atual de a : 10
>
Vamos olhar com calma o cdigo acima. Primeiro criamos uma varivel inteira chamada a. O seu valor
inicial foi definido como 1. A seguir vem a novidade: o lao while. Como dissemos antes, ele faz com
que o cdigo que o segue (e est agrupado usando chaves) seja executado enquanto a condio a <= 10 for
verdadeira. Inicialmente a vale 1, por isso este o primeiro valor impresso. Logo depois de imprimir o valor
de a, o seu valor acrescido de 1, passando a valer 2. Neste momento o grupo de instrues que segue o
while terminou. O que o computador faz voltar linha do while e verificar a condio novamente. Como a
agora vale 2, ele ainda menor que 10. Logo as instrues so executadas novamente. Elas sero executadas
enquanto a condio for verdadeira, lembra? Mais uma vez, o valor atual de a impresso e incrementado de 1,
passando a valer 3. De novo o computador volta linha do while, verifica a condio (que ainda verdadeira) e
executa as instrues dentro das chaves. Esse processo continua at que o a passe a valer 11, depois do dcimo
incremento. Neste instante, a condio torna-se falsa e na prxima vez que a condio do while verificada,
o computador pula as instrues dentro das chaves do while. Ufa, isso! Ainda bem que o computador que
tem todo o trabalho! Uma das principais qualidades do computador a sua capacidade de efetuar repeties.
Ele faz isso de forma automatizada e sem se cansar. O lao uma das formas mais naturais de aproveitarmos
essa caracterstica da mquina.
Agora vamos ver como esse novo conhecimento pode nos ajudar a montar a nossa tabela de converso
de forma mais simples e flexvel. Se pensarmos bem, veremos que as operaes realizadas para calcular as
temperaturas para tabela so semelhantes ao lao apresentado. S que no lugar de simplesmente imprimir os
diferentes valores de uma varivel, para gerar a tabela chamamos o mtodo fahrenheitParaCelsius vrias
vezes. Vamos agora adicionar um mtodo novo classe Conversor4, que ter a funo de imprimir tabelas de
converso para diferentes faixas de temperatura. O cdigo final seria:
c l a s s Conversor5
{
/
C o n v e r t e t e m p e r a t u r a de C e l s i u s p a r a F a h r e n h e i t .
/
double c e l s i u s P a r a F a h r e n h e i t ( double c e l s i u s )
{
return c e l s i u s 9.0 / 5.0 + 32;
}
/
C o n v e r t e t e m p e r a t u r a de F a h r e n h e i t p a r a C e l s i u s .
/
double f a h r e n h e i t P a r a C e l s i u s ( double f a h r )
48 CAPTULO 8. LAOS E REPETIES
{
return ( f a h r 3 2 . 0) 5.0 / 9 . 0 ;
}
/
I m p r i m e uma t a b e l a de c o n v e r s o F a r a n h e i t => C e l s i u s .
/
void i m p r i m e T a b e l a F a h r e n h e i t P a r a C e l s i u s ( double i n i c i o , double fim )
{
double f a h r = i n i c i o ;
double c e l s i u s ;
w h i l e ( f a h r <= f i m )
{
celsius = fahrenheitParaCelsius ( fahr );
System . o u t . p r i n t l n ( f a h r + " F = " + c e l s i u s + "C" ) ;
fahr = fahr + 10.0;
}
}
}
Welcome to DrJava.
> 3 / 2
1
> 3 % 2
1
> 5 / 3
1
> 5 % 3
2
> int div = 7 / 5
> int resto = 7 % 5
> div
1
8.3. NMEROS PRIMOS 49
> resto
2
> div*5 + resto
7
>
Deu para pegar a idia, no?
Agora vamos escrever uma classe contendo um mtodo que verifica se um inteiro primo ou no, impri-
mindo a resposta na tela. O nome que daremos nossa classe GeradorDePrimos. A razo para esse nome
ficar clara no prximo captulo.
c l a s s GeradorDePrimos
{
/
I m p r i m e na t e l a s e um nmero i n t e i r o p o s i t i v o p r i m o ou no .
/
void v e r i f i c a P r i m a l i d a d e ( i n t x )
{
/ / Todos o s nmeros i n t e i r o s p o s i t i v o s s o d i v i s v e i s p o r 1 .
i n t nmeroDeDivisores = 1;
/ / O p r i m e i r o c a n d i d a t o a d i v i s o r no t r i v i a l o 2 .
int candidatoADivisor = 2;
/ / T e s t a a d i v i s o p o r t o d o s o s nmeros m e n o r e s ou i g u a i s a x .
w h i l e ( c a n d i d a t o A D i v i s o r <= x )
{
i f ( x % c a n d i d a t o A D i v i s o r == 0 )
nmeroDeDivisores = nmeroDeDivisores + 1;
candidatoADivisor = candidatoADivisor + 1;
}
/ / Imprime a r e s p o s t a .
i f ( n m e r o D e D i v i s o r e s == 2 )
System . o u t . p r i n t l n ( x + " p r i m o . " ) ;
else
System . o u t . p r i n t l n ( x + " no p r i m o . " ) ;
}
}
Ser que esta a forma mais eficiente de implementar este mtodo? Ser que podemos alterar o cdigo
para que ele fornea a resposta mais rapidamente? O que aconteceria se quisssemos verificar a primalidade de
387563973. Pense um pouco sobre isso e depois d uma olhada no exerccio 6 deste captulo.
Exerccios
1. Crie uma classe Fatorial com um mtodo calculaFatorial(int x) que calcula o fatorial de x se
este for um nmero inteiro positivo e devolve -1 se x for negativo.
Adicione o mtodo testaCalculaFatorial() que testa o mtodo calculaFatorial(int x) para
diferentes valores de x.
50 CAPTULO 8. LAOS E REPETIES
2. Crie uma classe Mdia contendo um mtodo calculaMdia(int n) que devolve a mdia dos valores 1,
2, 3, ..., n, onde n o valor absoluto de um nmero fornecido ao mtodo.
Adicione o mtodo testaCalculaMdia() que testa o mtodo calculaMdia(int n) para diferentes
valores de n.
F1 = 1;
F2 = 1;
Fn = Fn1 + Fn2 , para todo inteiro positivo n > 2.
5. Abaixo, apresentamos uma pequena variao do mtodo verificaPrimalidade. Ela no funciona cor-
retamente em alguns casos. Voc deve procurar um exemplo no qual esta verso no funciona e explicar
o defeito usando suas prprias palavras. Note que a falha sutil, o que serve como alerta: programar
uma tarefa difcil, na qual pequenos erros podem gerar resultados desastrosos. Toda ateno pouca!
/
I m p r i m e na t e l a s e um nmero i n t e i r o p o s i t i v o p r i m o ou no .
/
void v e r i f i c a P r i m a l i d a d e ( i n t x )
{
/ / Todos o s nmeros i n t e i r o s p o s i t i v o s s o d i v i s v e i s p o r 1 .
i n t nmeroDeDivisores = 1;
/ / O p r i m e i r o c a n d i d a t o a d i v i s o r no t r i v i a l o 2 .
int candidatoADivisor = 2;
/ / T e s t a a d i v i s o p o r t o d o s o s nmeros m e n o r e s ou i g u a i s a x .
w h i l e ( c a n d i d a t o A D i v i s o r <= x )
{
candidatoADivisor = candidatoADivisor + 1;
i f ( x % c a n d i d a t o A D i v i s o r == 0 )
nmeroDeDivisores = nmeroDeDivisores + 1;
}
/ / Imprime a r e s p o s t a .
i f ( n m e r o D e D i v i s o r e s == 2 )
8.3. NMEROS PRIMOS 51
6. O lao no nosso verificaPrimalidade executado mais vezes do que o necessrio. Na verdade po-
deramos parar assim que candidatoADivisor chegar a x/2 ou mesmo ao chegar raiz quadrada de x.
Pense como mudar o programa levando em considerao estes novos limitantes.
7. Escreva uma classe Euclides, com um mtodo mdc que recebe dois nmeros inteiros a1 e a2, estritamente
positivos, com a1 >= a2, e devolve o mximo divisor comum entre eles, utilizando o algoritmo de
Euclides.
Breve descrio do algoritmo de Euclides (para maiores detalhes, consulte seu professor de lgebra):
Nota importante: o operador binrio % calcula o resto da diviso de n por m, quando utilizado da seguinte
maneira: n % m. Curiosidade: ele tambm funciona com nmeros negativos! Consulte seu professor de
lgebra ;-)
52 CAPTULO 8. LAOS E REPETIES
Captulo 9
Welcome to DrJava.
> 2 > 3
false
> 3 > 2
true
> int a = 2
> a == 2
true
> a >= 2
true
53
54 CAPTULO 9. EXPRESSES E VARIVEIS LGICAS
> a < a + 1
true
>
Vejam que cada vez que digitamos uma condio o DrJava responde true (para verdadeiro) ou false (para
falso).
Para entender bem o que ocorre, melhor imaginar que em Java as condies so expresses que resultam
em um dos dois valores lgicos: verdadeiro ou falso. Neste sentido, Java tambm permite o uso de variveis
para guardar os resultados destas contas, como vemos abaixo.
Com isso, acabamos de introduzir mais um tipo de varivel, somando-se aos tipos int e double j conhe-
cidos: o tipo boolean, que usado em variveis que visam conter apenas os valores booleanos (verdadeiro ou
falso). O nome uma homenagem ao matemtico ingls George Boole (1815-1864). Em portugus este tipo
de varivel chamada de varivel booleana
Agora que comeamos a ver as comparaes como expresses que calculam valores booleanos, torna-
se mais natural a introduo dos operadores lgicos. Ns todos j estamos bem acostumados a condies
compostas. Algo como eu s vou praia se tiver sol e as ondas estiverem boas. Nesta sentena a conjuno
e une as duas condies em uma nova condio composta que verdadeira somente se as duas condies que
a formam forem verdadeiras.
Em Java o e lgico representado pelo estranho smbolo &&. Ou seja, uma condio do tipo 1 <= a <=
10 seria escrita em Java como a >= 1 && a <= 10. Da mesma forma temos um smbolo para o ou lgico. Ele
o smbolo ||. Isso mesmo, duas barras verticais. Por fim, o smbolo ! antes de uma expresso lgica nega o
seu valor. Por exemplo, a condio "a no igual a 0"poderia ser escrita em Java como !(a == 0)1 .
Tabelas da verdade contm todos os resultados que podem ser obtidos ao se aplicar uma ope-
rao lgica sobre variveis booleanas. Abaixo apresentamos as tabelas da verdade para os
operadores &&, || e !.
Por fim, podemos montar expresses compostas unindo, atravs dos operadores descritos acima, condies
simples ou respostas de expresses lgicas anteriores que foram armazenadas em variveis booleanas. Mais
uma vez um exemplo vale mais que mil palavras.
Welcome to DrJava.
> (2 > 3) || (2 > 1)
true
> boolean comp1 = 2 > 3
> comp1
false
> comp1 && (5 > 0)
false
> !(comp1 && (5 > 0))
true
> int a = 10
> (a > 5) && (!comp1)
true
> boolean comp2 = (a > 5) && comp1
> comp2
false
>
Tambm podemos misturar operadores aritmticos e comparadores, sempre que isso faa sentido. Por
exemplo,
Note que a ltima expresso resultou em um erro. Afinal de contas, ela pede para somar, a uma varivel
inteira, o resultado de uma expresso cujo valor booleano, misturando tipos. Isto no faria sentido em Java.
Outra coisa que pode ser feita a criao de mtodos que devolvem um valor booleano. Assim a resposta
dada por esses mtodos pode ser usada em qualquer lugar onde uma condio faa sentido, como um if ou um
while. Por exemplo, se alterarmos o mtodo verificaPrimalidade, dado no captulo anterior, para devolver
a resposta (se o nmero primo ou no), em vez de imprimir na tela, teramos o seguinte mtodo Primo:
/
V e r i f i c a s e um nmero i n t e i r o p o s i t i v o p r i m o ou no .
/
boolean Primo ( i n t x )
{
i f ( x < 2)
return f a l s e ;
/ / Todos o s nmeros i n t e i r o s p o s i t i v o s s o d i v i s v e i s p o r 1 .
56 CAPTULO 9. EXPRESSES E VARIVEIS LGICAS
i n t nmeroDeDivisores = 1;
/ / O p r i m e i r o c a n d i d a t o a d i v i s o r no t r i v i a l o 2 .
int candidatoADivisor = 2;
/ / T e s t a a d i v i s o p o r t o d o s o s nmeros m e n o r e s ou i g u a i s a x .
w h i l e ( c a n d i d a t o A D i v i s o r <= x )
{
i f ( x % c a n d i d a t o A D i v i s o r == 0 )
nmeroDeDivisores = nmeroDeDivisores + 1;
candidatoADivisor = candidatoADivisor + 1;
}
i f ( n m e r o D e D i v i s o r e s == 2 )
return true ;
else
return f a l s e ;
}
A construo acima deixa muito claro o significado da expresso, pois a lemos como se no primo x, o
que bem prximo do que seria uma frase falada em portugus: se x no primo. Quanto mais prximo for
o seu cdigo da linguagem falada, mais fcil ser para outras pessoas o compreenderem; e a clareza do cdigo
um dos principais objetivos do bom programador.
operadores unrios -!
operadores multiplicativos */%
operadores aditivos +-
operadores de comparao == != > < >= <=
e lgico &&
ou lgico ||
atribuio =
Entre operadores com mesma precedncia, as operaes so computadas da esquerda para a direita.
Note, porm, que, nos exemplos acima, abusamos dos parnteses mesmo quando, de acordo com a tabela de
precedncia, eles so desnecessrios. Sempre bom usar parnteses no caso de expresses lgicas (ou mistas),
pois a maioria das pessoas no consegue decorar a tabela acima. Assim, mesmo que voc tenha uma tima
memria, o seu cdigo torna-se mais legvel para a maioria dos mortais.
9.3. EXEMPLOS 57
9.3 Exemplos
Primeiro, vamos retomar o mtodo verificaLados da classe TianguloRetngulo3 vista no Captulo 6.
Nele, testamos se no h lado de comprimento nulo. Entretanto, parece mais natural e correto forar todos os
lados a terem comprimento estritamente positivo:
i f ( ( a > 0 ) && ( b > 0 ) && ( c > 0 ) )
{
/ / A q u i vo o s comandos p a r a v e r i f i c a r a c o n d i o p i t a g r i c a .
}
Podemos tambm usar condies compostas para escrever uma verso mais rpida do mtodo
Primo do captulo anterior.
/
V e r i f i c a s e um nmero i n t e i r o p o s i t i v o p r i m o ou no .
/
boolean Primo ( i n t x )
{
i f ( x < 2)
return f a l s e ;
/ / Todos o s nmeros i n t e i r o s p o s i t i v o s s o d i v i s v e i s p o r 1 .
i n t nmeroDeDivisores = 1;
/ / O p r i m e i r o c a n d i d a t o a d i v i s o r no t r i v i a l o 2 .
int candidatoADivisor = 2;
/ / T e s t a a d i v i s o p o r t o d o s o s nmeros m e n o r e s ou i g u a i s a x / 2 ou
/ / at encontrar o primeiro divisor .
w h i l e ( ( c a n d i d a t o A D i v i s o r <= x / 2 ) && ( n m e r o D e D i v i s o r e s == 1 ) )
{
i f ( x % c a n d i d a t o A D i v i s o r == 0 )
nmeroDeDivisores = nmeroDeDivisores + 1;
candidatoADivisor = candidatoADivisor + 1;
}
i f ( n m e r o D e D i v i s o r e s == 1 )
return true ;
else
return f a l s e ;
}
Melhor ainda podemos finalmente escrever a classe GeradorDePrimos de forma completa. O mtodo mais
interessante o prximoPrimo que devolve o primeiro nmero primo maior do que o ltimo gerado. Este
exemplo j bem sofisticado, vocs tero que estud-lo com calma. Uma sugesto: tentem entender o que o
programa faz, um mtodo por vez. O nico mtodo mais complicado o Primo, mas este ns j vimos.
c l a s s GeradorDePrimos
{
/ / L i m i t e i n f e r i o r p a r a b u s c a de um novo p r i m o .
int l i m i t e I n f e r i o r = 1;
/
58 CAPTULO 9. EXPRESSES E VARIVEIS LGICAS
P e r m i t e mudar o l i m i t e p a r a cmputo do p r x i m o p r i m o .
/
void c a r r e g a L i m i t e I n f e r i o r ( i n t l i m i t e )
{
limiteInferior = limite ;
}
/
V e r i f i c a s e um nmero i n t e i r o p o s i t i v o p r i m o ou no .
/
boolean Primo ( i n t x )
{
i f ( x < 2)
return f a l s e ;
/ / Todos o s nmeros i n t e i r o s p o s i t i v o s s o d i v i s v e i s p o r 1 .
i n t nmeroDeDivisores = 1;
/ / O p r i m e i r o c a n d i d a t o a d i v i s o r no t r i v i a l o 2 .
int candidatoADivisor = 2;
/ / T e s t a a d i v i s o p o r t o d o s o s nmeros m e n o r e s ou i g u a i s a x / 2 ou
/ / at encontrar o primeiro divisor .
w h i l e ( ( c a n d i d a t o A D i v i s o r <= x / 2 ) && ( n m e r o D e D i v i s o r e s == 1 ) )
{
i f ( x % c a n d i d a t o A D i v i s o r == 0 )
nmeroDeDivisores = nmeroDeDivisores + 1;
candidatoADivisor = candidatoADivisor + 1;
}
i f ( n m e r o D e D i v i s o r e s == 1 )
return true ;
else
return f a l s e ;
}
/
A cada chamada , e n c o n t r a um novo p r i m o m a i o r que l i m i t e I n f e r i o r .
/
i n t prximoPrimo ( )
{
/ / Busca o p r i m e i r o p r i m o d e p o i s do l i m i t e .
l i m i t e I n f e r i o r = l i m i t e I n f e r i o r + 1;
while ( ! Primo ( l i m i t e I n f e r i o r ) )
l i m i t e I n f e r i o r = l i m i t e I n f e r i o r + 1;
return l i m i t e I n f e r i o r ;
}
}
Note o uso do atributo limiteInferior no exemplo acima. Ele guarda uma informao importante:
o valor do ltimo nmero primo encontrado. importante que ele seja um atributo dos objetos do tipo
GeradorDePrimos e no uma varivel local do mtodo prximoPrimo() para que o seu valor sobreviva s
sucessivas chamadas ao mtodo prximoPrimo(). Se ele fosse uma varivel local, a cada nova execuo do
9.3. EXEMPLOS 59
Exerccios
1. Escreva uma classe TrianguloRetngulo com um mtodo denominado defineLados(double x1,
double x2, double x3) que recebe trs valores e verifica se eles correspondem aos lados de um tri-
ngulo retngulo. Em caso afirmativo, o mtodo devolve true, caso contrrio ele devolve false. Note
que o programa deve verificar quais dos trs valores corresponde hipotenusa. Construa duas verses do
mtodo, uma contendo trs ifs e outra contendo apenas um if! Em seguida, crie um novo mtodo que
verifica se ambos os mtodos retornam o mesmo resultado para diferentes combinaes de x1, x2 e x3.
2. Escreva uma classe Brincadeiras que possua 3 atributos inteiros. Escreva um mtodo para carregar
valores nestes atributos e, em seguida, escreva os seguintes mtodos:
(a) troca2Primeiros() que troca os valores dos dois primeiros atributos. Por exemplo, se antes da
chamada do mtodo o valor dos atributos <1, 2, 3>, depois da chamada, eles devero valer <2, 1,
3>.
(b) imprime() que imprime o valor dos 3 atributos.
(c) imprimeEmOrdemCrescente() que imprime o valor dos 3 atributos em ordem crescente.
3. A linguagem Java oferece operadores que, se usados corretamente, ajudam na apresentao e digitao
do cdigo, tornando-o mais enxuto. Veremos neste exerccio dois deles: os operadores de incremento e
de decremento. Verifique o funcionamento desses operadores usando os mtodos da classe abaixo.
class Experincia
{
void verIncremento ( i n t n )
{
int x = n ;
System . o u t . p r i n t l n ( " Nmero i n i c i a l x > " + x ) ;
System . o u t . p r i n t l n ( " x++ > " + x + + ) ;
System . o u t . p r i n t l n ( " Novo v a l o r de x > " + x ) ;
x = n;
System . o u t . p r i n t l n ( " Nmero i n i c i a l x > " + x ) ;
System . o u t . p r i n t l n ( " ++x > " + ++x ) ;
System . o u t . p r i n t l n ( " Novo v a l o r de x > " + x ) ;
}
void verDecremento ( i n t n )
{
int x = n ;
System . o u t . p r i n t l n ( " Nmero i n i c i a l x > " + x ) ;
System . o u t . p r i n t l n ( " x > " + x );
System . o u t . p r i n t l n ( " Novo v a l o r de x > " + x ) ;
60 CAPTULO 9. EXPRESSES E VARIVEIS LGICAS
x = n;
System . o u t . p r i n t l n ( " Nmero i n i c i a l x > " + x ) ;
System . o u t . p r i n t l n ( "x > " + x ) ;
System . o u t . p r i n t l n ( " Novo v a l o r de x > " + x ) ;
}
}
Entenda bem o cdigo e observe os resultados. Em seguida, tire suas concluses e compare-as com as
concluses de seus colegas.
Alm dos operadores de incremento e decremento, tambm existem os seguintes operadores resumidos:
+=, -=, *= e /=. Eles so teis quando queremos efetuar uma operao em uma varivel e guardar o
resultado na mesma. Isto , a = a * 2; completamente equivalente a a *= 2;.
Captulo 10
Mergulhando no while
61
62 CAPTULO 10. MERGULHANDO NO WHILE
return l i m i t e I n f e r i o r ;
}
Nosso prximo desafio criar uma nova classe ManipuladorDeInteiros. Ela deve conter o mtodo
fatoraInteiro que deve imprimir a decomposio em primos de um inteiro positivo maior ou igual a 2. Uma
dica importante usar o GeradorDePrimos Antes de ler soluo colocada abaixo, tente com afinco fazer o
exerccio sozinho.
class ManipuladorDeInteiros {
/
F a t o r a em p r i m o s um i n t e i r o > 1 .
/
void f a t o r a I n t e i r o ( i n t x )
{
System . o u t . p r i n t ( x + " = " ) ;
/ / Usa um g e r a d o r de p r i m o s p a r a e n c o n t r a r o s p r i m o s m e n o r e s ou i g u a i s a x .
G e r a d o r D e P r i m o s g e r a d o r = new G e r a d o r D e P r i m o s ( ) ;
i n t primo = g e r a d o r . prximoPrimo ( ) ;
/ / C o n t i n u a f a t o r a n d o o nmero a t que x s e t o r n e 1 .
while ( x > 1)
{
i f ( x % p r i m o == 0 )
{
System . o u t . p r i n t ( " " + p r i m o ) ;
x = x / primo ;
}
else
primo = g e r a d o r . prximoPrimo ( ) ;
}
/ / I m p r i m e um f i m de l i n h a no f i n a l .
System . o u t . p r i n t l n ( ) ;
}
}
Welcome to DrJava.
> ManipuladorDeInteiros m = new ManipuladorDeInteiros()
> m.fatoraInteiro(5)
5 = 5
> m.fatoraInteiro(10)
10 = 2 5
> m.fatoraInteiro(18)
18 = 2 3 3
> m.fatoraInteiro(123456)
123456 = 2 2 2 2 2 2 3 643
> m.fatoraInteiro(12345678)
10.2. UMA BIBLIOTECA DE FUNES MATEMTICAS. 63
12345678 = 2 3 3 47 14593
> m.fatoraInteiro(167890)
167890 = 2 5 103 163
>
Obs: Note que na soluo usamos uma rotina de impresso nova: System.out.print. Ela muito parecida
com System.out.println com a diferena de que no muda a linha ao terminar de imprimir.
2 4 6 k (2k)
cos(x) = 1 x2! + x4! x6! + . . . + (1) x
(2k)! +...
2 3 4 (k1) xk
ln(1 + x) = x x2 + x3 x4 + . . . + (1) k +...
Isso funciona bem sempre que |x| < 1.
O segredo para usar essas frmulas no computador continuar somando at que o mdulo do prximo
termo seja muito pequeno e por isso possa ser desprezado.
Antes de apresentarmos aqui a soluo que consideramos ideal, faa com cuidado e ateno os exerccios
1 (implementao das funes double pot(double x, int y) e double fat(double x)) e 2 (implemen-
tao da funo double sen(double x) usando as funes do exerccio 1.
Agora, aps termos feito os exerccios 1 e 2, iremos criar uma nova classe, que chamaremos Matemtica,
com mtodos para calcular funes como as apresentadas acima. Abaixo vemos a classe com uma funo que
calcula sen(x) implementada. Compare esta forma de implementar com as formas usadas no exerccio. Qual
mais rpida? Qual mais fcil de entender?
c l a s s Matemtica
{
/ / C o n t r o l a o s i g n i f i c a d o de " p e q u e n o " .
d o u b l e e p s i l o n = 1 . 0 e 8;
1 Mais informaes sobre sries de Taylor podem ser encontradas em livros de Clculo.
64 CAPTULO 10. MERGULHANDO NO WHILE
Um exemplo de uso:
Welcome to DrJava.
> m = new Matemtica();
> m.sen(0.3)
0.2955202066613839
> m.sen(0.5)
0.4794255386164159
> m.sen(3.141596/2.0)
0.9999999999925767
>
10.3 do...while
Para complementar os laos possveis em Java, vejamos uma pequena variao do while. Nele a condio
testada sempre antes de execuo do corpo de comandos que compe o lao. J o lao do...while tem a
condio testada apenas no final. Conseqentemente, no caso do do...while, existe a garantia que o contedo
no interior do lao ser executado pelo menos uma vez, enquanto no while este pode nunca ser executado. Na
prtica, a existncia destes dois tipos de laos uma mera convenincia sinttica, j que um pode ser facilmente
substitudo pelo outro.
Vejamos um exemplo de utilizao do do...while:
int f a t o r i a l ( int x)
{
int resultado = 1;
do
{
resultado = resultado x;
x = x 1;
} while ( x > 1)
return r e s u l t a d o ;
}
10.3. DO...WHILE 65
Exerccios
1. Implemente na classe Matemtica as funes double pot(double x, int y) que calcula xy e double
fat(double x) que calcula x! 2 .
2. Implemente na classe Matemtica a funo double sen(double x) utilizando-se das funes double
pot(double x, int y) e int fat(int x) do tem anterior.
3. Implemente na classe Matemtica funes para calcular cos(x) e ln(1 + x). Note que para implementar
o ln(1 + x) deve-se criar uma funo double ln(double x) e no interior da funo definir uma varivel
local x2 = 1 - x de modo que se possa calcular ln(1 + x2).
5. O enunciado deste exerccio bem mais complexo que a soluo, por isso no tenha medo! Imagine um
quadrado em um plano e uma reta paralela a um dos lados do quadrado: a projeo do quadrado sobre a
reta tem exatamente o mesmo comprimento que o lado do quadrado. Imagine agora que este quadrado
seja girado sobre o plano; a projeo do quadrado sobre a reta tem um novo tamanho. Crie uma classe
Projetor que possua um mtodo gira que aceite como parmetro o nmero de graus que o quadrado deve
girar em relao sua posio anterior e imprima na tela o tamanho da projeo do quadrado sobre a
reta. Note que se o usurio executar o mtodo duas vezes, com os parmetros 22 e 35, sua classe
deve responder qual o tamanho da projeo para inclinaes do quadrado de 22 e 57 graus.
Escreva 3 solues para este exerccio: uma que voc considere elegante e clara, uma com um
nico mtodo e uma com o mximo nmero possvel de mtodos. Utilize os mtodos sen() e
cos() desenvolvidos neste captulo.
Utilize agora os mtodos java.lang.Math.cos() e java.lang.Math.sin() disponveis na bi-
blioteca Java, que calculam, respectivamente, o coseno e o seno do ngulo passado como parmetro
em radianos (graus * PI/180 = radianos). Compare os resultados com os obtidos com nossas imple-
mentaes de sen() e cos().
2 Apesar do clculo de fatorial s usar inteiros, com o tipo int pode se calcular at 16!, e com o tipo long at 20!. Com o tipo
double possvel calcular fatoriais maiores, mas com menos dgitos significativos.
3 http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Math.html.
66 CAPTULO 10. MERGULHANDO NO WHILE
Captulo 11
No exemplo acima podemos ver que para se representar um caractere usamos aspas simples (). Tambm
podemos ver que os caracteres minsculos so diferentes do mesmo caractere maisculo.
Um outro exemplo um pouco mais elaborado pode ser visto abaixo:
class Caracteres
{
67
68 CAPTULO 11. CARACTERES E CADEIAS DE CARACTERES
v o i d i m p r i m e C a r a c t e r e s ( char ch , i n t n )
{
int i = 0;
while ( i < n )
{
System . o u t . p r i n t ( ch ) ;
i = i + 1;
}
}
}
Neste exemplo, so impressos diversos caracteres do mesmo tipo. Observe abaixo como podemos adicionar
um novo mtodo para desenhar letras grandes:
class Caracteres
{
v o i d i m p r i m e C a r a c t e r e s ( char ch , i n t n )
{
int i = 0;
while ( i < n )
{
System . o u t . p r i n t ( ch ) ;
i = i + 1;
}
}
void novaLinha ( )
{
System . o u t . p r i n t l n ( ) ;
}
v o i d i m p r i m e C a r a c t e r e s N L ( char ch , i n t n )
{
i m p r i m e C a r a c t e r e s ( ch , n ) ;
novaLinha ( ) ;
}
void desenhaE ( )
{
imprimeCaracteresNL ( , 2 0 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 1 5 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 1 4 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 3 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 3 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 1 3 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 1 3 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 3 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 3 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 1 4 ) ;
i m p r i m e C a r a c t e r e s N L ( E , 1 5 ) ;
imprimeCaracteresNL ( , 2 0 ) ;
}
}
11.2. CADEIAS DE CARACTERES (STRINGS) 69
A sada do programa :
********************
EEEEEEEEEEEEEEE
EEEEEEEEEEEEEE
EEE
EEE
EEEEEEEEEEEEE
EEEEEEEEEEEEE
EEE
EEE
EEEEEEEEEEEEEE
EEEEEEEEEEEEEEE
*********************
Para desenharmos letras onde necessrio intercalar espaos e letras em uma nica linha, a implementao
fica um pouco mais longa. Os diferentes mtodos que imprimem caracteres pulando ou sem pular linha sero
usados. Por exemplo, para a letra U, a primeira linha deve ser impressa como:
i m p r i m e C a r a c t e r e s ( U , 3 ) ;
imprimeCaracteres ( , 9); / / e s p a o tambm um c a r a c t e r e
i m p r i m e C a r a c t e r e s N L ( U" , 3 ) ;
Agora ns veremos com mais detalhes esta classe String . Podemos ver que o operador + tem um signifi-
cado natural o de concatenao. Logo, as seguintes operaes so vlidas:
S t r i n g a = " abc " ;
String b = " cdf " ;
String c ;
c = a + b;
System . o u t . p r i n t l n ( c ) ;
c = a + i;
System . o u t . p r i n t l n ( c ) ;
Alm disto, existem alguns mtodos pr-definidos na classe String. Entre eles podemos citar:
boolean endsWith(String suffix) - verifica se a String acaba com o sufixo dado. Usado, entre
outras coisas, para verificar as extenses dos arquivos. Por exemplo, verificar se o nome de um arquivo
termina com ".java".
int indexOf(char ch) - devolve o ndice da primeira ocorrncia de ch na String ou -1 caso o carac-
tere no ocorra na String. Exemplo:
S t r i n g s 1 = " EP1 . j a v a " ;
System . o u t . p r i n t l n ( s 1 . i n d e x O f ( . ) ) ; / / imprime 3
System . o u t . p r i n t l n ( s 1 . i n d e x O f ( x ) ) ; / / i m p r i m e 1
Exerccios
1. Escreva uma classe Linha que possua um mtodo imprimeLinha que, ao ser chamado, imprime uma
linha de caracteres X na diagonal, na tela de interaes do DrJava. Use laos while. DICA: voc vai
precisar do mtodo System.out.print(), que imprime seu argumento na tela mas no passa para a
linha seguinte; imprima linhas com nmero crescente de espaos no comeo e o caractere X no final.
11.2. CADEIAS DE CARACTERES (STRINGS) 71
2. Escreva uma classe contendo um mtodo que devolve o nmero de ocorrncias da vogal a em uma frase
contida em uma String. Crie um teste para verificar o funcionamento desta classe.
3. Implemente uma classe com um mtodo que determina a freqncia relativa de vogais em uma String.
Considere que as letras maisculas e minsculas no esto acentuadas. Crie um teste para verificar o
funcionamento desta classe.
72 CAPTULO 11. CARACTERES E CADEIAS DE CARACTERES
Captulo 12
A Memria e as Variveis
73
74 CAPTULO 12. A MEMRIA E AS VARIVEIS
outras formas de codificao, possvel armazenar na memria qualquer tipo de informao que podemos
imaginar: nmeros positivos e negativos inteiros e fracionrios, letras, textos, imagens, sons, vdeo, etc.
Quando dizemos que um computador tem 1GB de memria (1 Giga Byte), queremos dizer que sua memria
composta por 230 = 1.073.741.824 bytes. Podemos ento imagin-la como sendo uma rua com pouco mais
de 1 bilho de casas (comprida n?), cada uma composta por um byte. Nestes bytes, o computador armazena
os programas sendo executados, o cdigo-fonte dos programas Java que digitamos no DrJava, os bytecodes
correspondentes s classes Java depois que ns as compilamos, o contedo das variveis que fazem parte de
nossos objetos, etc.
Observamos que o preo da fruta a mudou. Isto ocorre porque, aps a terceira linha do trecho acima, a e b
passam a ser referncias para o mesmo objeto na memria; como dois apelidos para mesma pessoa. Qualquer
coisa que ocorre com o objeto usando um de seus apelidos se reflete para a viso do outro apelido. Esse
raciocnio explica porque alteraes em objetos complexos dentro de um mtodo se propagam para fora. O
parmetro associado a esse objeto tambm um apelido.
A diferena entre tipos primitivos e objetos tambm fica evidente quando lidamos com comparaes.
Quando se comparam dois tipos primitivos com o operador ==, os valores dos mesmos so verificados. O
mesmo no acontece com objetos, o que se comparam so as referncias. Veja o exemplo abaixo:
> int a = 5
> int b = 2 + 3
> a == b
true
> String s1 = "Bom dia"
> String s2 = "Bom"
> s2 = s2 + " " + "dia"
> s1 == s2
false
Vemos no exemplo acima que o operador == tem um significado diferente com relao a objetos. A com-
parao de igualdade verifica se as duas referncias se referem ao mesmo objeto. Na ltima linha do exemplo
acima, tanto s1 quanto s2 se referem ao texto "Bom dia" mas as variveis s1 e s2 so referncias a posies
diferentes da memria, se referem a dois objetos distintos; portanto, s1 == s2 false.
Exerccios
1. O comparador == no pode ser usado para comparar o contedo de objetos. Neste caso, usa-se o mtodo
equals, presente em todos os objetos. Este mtodo recebe como entrada uma outra String e retorna
true se as Strings so iguais e false caso contrrio. Faa uma classe com um mtodo que verifica se
duas Strings tm o mesmo contedo.
2. Vimos neste captulo que a mudanas no valor de um parmetro de tipo primitivo dentro de um mtodo
no se reflete fora dele. Mas no caso de objetos, alteraes em seu contedo dentro de um mtodo so
refletidas fora deste.
Suponha que voc deseje criar um mtodo que modifica os valores de um par de inteiros de modo que
estas modificaes se reflitam fora do mtodos. Um bom exemplo um mtodo que recebe como entrada
as coordenadas de ponto cartesiano e desloca este ponto em (+1,+1). Pense numa possvel soluo para
este problema. Em seguida, implemente sua soluo e verifique se ela funciona.
3. Verifique o seguinte trecho de cdigo:
Qual o valor da varivel s2 aps a execuo deste trecho de cdigo? Pense cuidadosamente na resposta
e em seguinte verifique-a utilizando o DrJava. Tente explicar o comportamento verificado.
Captulo 13
Neste captulo, aprenderemos como extrair e processar os dgitos de um nmero inteiro e como realizar a
converso de um nmero entre diferentes bases. Mas antes, faremos uma introduo aos principais sistemas de
numerao utilizados para representar nmeros inteiros.
77
78 CAPTULO 13. MANIPULANDO NMEROS UTILIZANDO DIFERENTES BASES
Apesar da representao binria ser aquela utilizada internamente pelo computador, esta de difcil leitura
para os seres humanos, devido s longas seqncias de algarismos 0 e 1. Para aliviar este problema, duas outras
bases so bastantes utilizadas na computao, a base octal e a hexadecimal.
A base octal corresponde concatenao de 3 bits, que combinados do origem a 8 diferentes valores,
representados pelos algarismos de 0 a 7. J a base hexadecimal corresponde concatenao de 4 bits, gerando
16 combinao diferentes. Como possumos apenas 10 algarismo numricos, utilizamos as letras do alfabeto
{A, B,C, D, E, F}. O nmero 1256 nestas bases seria ento dado por:
while ( n != 0){
/ p r o c e s s a um d g i t o b i n r i o /
d e c = d e c + n % 10 p o t 2 ;
n = n / 10;
pot2 = pot2 2;
}
return dec ;
}
1 Rastrear
a execuo de um programa significa construir uma tabela contendo colunas correspondentes s variveis do programa
e simular a sua execuo indicando os valores que as variveis recebem ao longo do tempo. Se o programa imprimir texto (usando
System.out.println) esse texto tem que ser indicado como sada e se os mtodos devolvem algum valor (com o comando return)
este valor tem que ser destacado.
13.2. CONVERSO ENTRE SISTEMAS DE NUMERAO 79
while ( n > 0) {
/ e x t r a i p r x i m o d g i t o b i n r i o menos s i g n i f i c a t i v o ( m a i s d i r e i t a ) /
dig = n % 2;
/ remove e s s e d g i t o do n /
n = n / 2;
/ a d i c i o n a o d g i t o como o m a i s s i g n i f i c a t i v o a t o momento /
bin = bin + dig pot ;
pot = pot 10;
}
return bin ;
}
}
Exerccios
1. Crie uma classes Contador com um mtodo que recebe um nmero natural n e devolve seu nmero de
dgitos. Em seguida, escreva uma classe TestaContador que testa o mtodo para diferentes valores de
n. No se esquea de testar o caso do nmero ser igual a zero!
2. Dado um nmero, verificar se o mesmo possui dois dgitos consecutivos iguais. Para resolver este pro-
blema podemos usar um tcnica denominada indicador de passagem, para isto, inicialmente vamos supor
que o nmero no contm dgitos iguais. Verificaremos cada par de dgitos consecutivos, caso algum
deles seja igual, saberemos que ele contm dgitos consecutivos iguais. Em outras palavras, vamos inici-
alizar uma varivel booleana com falso e testar a condio para todos os dgitos consecutivos; se forem
iguais mudamos a condio. Ao final, a resposta vai corresponder ao estado final desta condio.
3. Dado um nmero natural n, verificar se n palndromo. Um nmero palndromo um nmero que lido
de trs para frente o mesmo quando lido normalmente, por exemplo:
78087
1221
11111
3456 no palindromo!!!
Duas maneiras de se resolver estes problemas so apresentadas abaixo. Escreva as solues para cada
uma delas.
Se o nmero for negativo, considere apenas o seu valor absoluto (isso apenas uma conveno nossa
para este exerccio). Por exemplo, -2002 deve ser considerado palndromo.
Curiosidade: nmeros palndromos tambm so conhecidos por capicuas.
80 CAPTULO 13. MANIPULANDO NMEROS UTILIZANDO DIFERENTES BASES
4. Uma propriedade de nmeros naturais a seguinte: um nmero sempre maior do que o produto dos
seus dgitos. Faa uma classe com dois mtodos: int calculaProd(int n), que calcula o produto
dos dgitos de um nmero natural n e boolean verificaProp(int n), que verifica se a propriedade
vlida para um nmero n dado.
5. Crie mtodos para converter uma String contendo um nmero em algarismos romanos em um inteiro e
vice-versa. Crie testes para estes mtodos.
6. Crie uma classe contendo um mtodo que recebe um inteiro e o imprime representado em notao cien-
tfica. Por exemplo,
7. Implemente a operao de diviso de dois nmeros inteiros utilizando apenas laos e os operadores + e
-.
Captulo 14
Arrays (vetores)
Muitas vezes, precisamos que um objeto guarde um grande nmero de informaes. Por exemplo, se
precisamos calcular a temperatura mdia em um dado ms poderamos ter uma classe similar seguinte:
c l a s s TemperaturasDoMs
{
double t1 , t2 , t3 , t4 , t5 , t6 , t7 , t8 , t9 , t10 , t11 , t12
t13 , t14 , t15 , t16 , t17 , t18 , t19 , t20 , t21 , t22 , t23 ,
t24 , t25 , t26 , t27 , t28 , t29 , t30 , t31 ;
/ / etc .
}
onde cada varivel guarda a temperatura mdia de um dia do ms. Isso claramente indesejvel. Imagine ainda
se quisssemos uma classe para guardar as temperaturas mdias de todos os dias do ano. Precisaramos de 365
variveis? Felizmente no!
A linguagem Java possui o conceito de array que uma estrutura de dados que permite guardar uma
seqncia de valores (nmeros, caracteres ou objetos quaisquer) de uma forma nica e organizada. Utilizando
um array, a classe anterior ficaria assim:
c l a s s TemperaturasDoMs
{
d o u b l e [ ] t e m p e r a t u r a s = new d o u b l e [ 3 1 ] ;
/ / etc .
}
Note que, no exemplo acima, a linha que define o array temperaturas faz duas operaes simultanea-
mente. Esta linha poderia ser separada em dois passos:
double[] temperaturas; define um novo array chamado temperaturas que ir conter valores do tipo
double. Por enquanto, o array est vazio.
81
82 CAPTULO 14. ARRAYS (VETORES)
temperaturas = new double[31]; especifica que o array guardar exatamente 31 valores do tipo
double. Neste instante, o ambiente Java reserva a memria necessria para guardar estes 31 valores.
void defineDiasDaSemana ( )
{
diasDaSemana [ 0 ] = " domingo " ;
diasDaSemana [ 1 ] = " s e g u n d a f e i r a " ;
diasDaSemana [ 2 ] = " t e r a f e i r a " ;
diasDaSemana [ 3 ] = " q u a r t a f e i r a " ;
diasDaSemana [ 4 ] = " q u i n t a f e i r a " ;
diasDaSemana [ 5 ] = " s e x t a f e i r a " ;
diasDaSemana [ 6 ] = " s b a d o " ;
}
void calculaQuadrados ( )
{
int i = 0;
while ( i < 10)
{
quadrados [ i ] = i i ;
i ++;
}
}
void listaDiasDaSemana ( )
{
int i = 0;
while ( i < 7)
{
System . o u t . p r i n t l n ( diasDaSemana [ i ] ) ;
i ++;
}
}
void l i s t a Q u a d r a d o s ( )
{
int i = 0;
while ( i < 10)
{
14.1. CRIAO DE PROGRAMAS JAVA 83
O atributo length
Arrays so na verdade um tipo especial de objeto em Java. Qualquer array j vem com um atributo pr-
definido, chamado length, que contm o comprimento do array. Desta forma, o mtodo calculaQuadrados
acima poderia ser reescrito para
void calculaQuadrados ( )
{
int i = 0;
while ( i < quadrados . l e n g t h )
{
quadrados [ i ] = i i ;
i ++;
}
}
O valor do atributo length definido automaticamente pelo ambiente Java, o programador no pode alter-
lo. Assim, quadrados.length = 2 uma operao ilegal.
Inicializao de arrays
Existe tambm a opo de inicializar um array no momento em que ela declarada. Assim, podemos
inicializar arrays de inteiros e de Strings conforme o exemplo a seguir:
i n t [ ] primos = {2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23};
S t r i n g [ ] p l a n e t a s = { " M e r c r i o " , " Vnus " , " T e r r a " , " M a r t e " , " J p i t e r " , " S a t u r n o " ,
" Urano " , " Netuno " , " P l u t o " } ;
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g )
84 CAPTULO 14. ARRAYS (VETORES)
{
B r i n c a d e i r a s C o m A r r a y s b = new B r i n c a d e i r a s C o m A r r a y s ( ) ;
b . defineDiasDaSemana ( ) ;
b . calculaQuadrados ( ) ;
b . listaDiasDaSemana ( ) ;
b . listaQuadrados ( ) ;
b . imprimeArray ( arg ) ;
}
void imprimeArray ( S t r i n g [ ] a r r a y )
{
int i = 0;
while ( i < a r r a y . l e n g t h )
{
System . o u t . p r i n t l n ( a r r a y [ i ] ) ;
i ++;
}
}
}
Para executar o seu programa aps compilar a classe, basta abrir um shell (um interpretador de comandos
do sistema operacional; no unix pode ser, por exemplo, o bash; no windows pode ser, por exemplo, o command)
e digitar
onde, java o nome do interpretador Java, BrincadeirasComArrays o nome da classe que ser car-
regada e cujo mtodo main ser executado e um dois trs so apenas um exemplo de 3 argumentos que
estamos passando, poderia ser qualquer outra coisa.
Neste exemplo, o programa BrincadeirasComArrays geraria a seguinte sada:
domingo
segunda-feira
tera-feira
quarta-feira
quinta-feira
sexta-feira
sbado
0 ao quadrado 0
1 ao quadrado 1
2 ao quadrado 4
3 ao quadrado 9
4 ao quadrado 16
5 ao quadrado 25
6 ao quadrado 36
7 ao quadrado 49
8 ao quadrado 64
9 ao quadrado 81
14.1. CRIAO DE PROGRAMAS JAVA 85
um
dois
trs
portanto, para que uma classe possa ser executada a partir da linha de comando do sistema, necessrio
que ele possua um mtodo com a seguinte assinatura:
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g )
o nome do parmetro no precisa ser exatamente arg, qualquer nome funciona; mas o seu tipo tem que ser
obrigatoriamente um array de Strings. A partir do DrJava possvel executar o mtodo main pressionando a
tecla F2.
Exerccios
Testes: at este captulo, em diversos exerccios pedimos explicitamente para voc criar
testes para classes e mtodos escritos. Fizemos isto para enfatizar a necessidade de escre-
ver testes, um processo que deve ser realizado de modo automtico. A partir deste captulo
no iremos mais solicitar em cada exerccio que voc escreva testes. Voc dever, a partir
de agora, fazer isso naturalmente.
1. Escreva uma classe Simples contendo um mtodo que recebe um array de inteiros como parmetro e
que inicializa todos os elementos do array com um valor, tambm dado como parmetro. O mtodo deve
devolver o tamanho do array. A assinatura do mtodo deve ser a seguinte:
int inicializaArray ( int [] a , int v );
Escreva agora um mtodo que recebe um array de inteiros como parmetro e imprime o seu contedo:
void imprimeArray ( i n t [ ] a ) ;
Crie agora um mtodo que, dado um inteiro, verifica se ele est presente no array.
boolean estNoArray ( i n t [ ] a , i n t v ) ;
Finalmente, escreva um programa que cria um array, cria um objeto Simples e chama os seus trs
mtodos.
3. Crie um mtodo que, dados dois vetores a e b, verifica se o vetor de menor tamanho uma subseqncia
do vetor de tamanho maior.
Ex: O vetor [9, 5] uma subseqncia de [3, 9, 5, 4, -1].
86 CAPTULO 14. ARRAYS (VETORES)
4. Crie uma classe contendo um mtodo que, dado um vetor v de inteiros, imprime o segmento de soma
mxima.
Ex: No vetor [ -1, 5, -4, 7, 2, -3] o segmento de soma mxima [ 5, -4, 7, 2]
Captulo 15
void calculaQuadrados ( )
{
int i = 0;
while ( i < quadrados . l e n g t h )
{
quadrados [ i ] = i i ;
i ++;
}
87
88 CAPTULO 15. FOR, LEITURA DO TECLADO E CONVERSO DE STRINGS
/ / d e f i n e o c r i t r i o p a r a c o n t i n u a r m o s d e n t r o do l a o
while ( i < quadrados . l e n g t h )
{
quadrados [ i ] = i i ; / / a operao propriamente d i t a
i ++; / / comando de a t u a l i z a o p a r a p a s s a r m o s p a r a a p r x i m a i t e r a o
}
Aps muito observar este padro, projetistas de linguagens de programao decidiram criar um novo co-
mando para implementao de laos onde todas estas partes relacionadas com o lao fossem organizadas de
uma forma melhor. Assim, surgiu o comando for que, nas linguagens C, C++ e Java, adquirem o seguinte
formato:
for ( i n i c i a l i z a o ; condio para continuar ; a t u a l i z a o )
{
comando ;
}
onde as chaves so apenas necessrias se comando for composto. Com o for, podemos implementar
exatamente o mesmo que com o while mas, no caso do for, todas as operaes relacionadas com o lao ficam
na mesma linha, o que facilita a visualizao e o entendimento de quem olha para o cdigo.
c l a s s UsoScanner
{
15.2. LEITURA DO TECLADO 89
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s )
{
S c a n n e r s c = new S c a n n e r ( System . i n ) ;
int x = sc . n e x t I n t ( ) ;
System . o u t . p r i n t l n ( " O i n t e i r o l i d o f o i " + x ) ;
double d = sc . nextDouble ( ) ;
System . o u t . p r i n t l n ( " O d o u b l e l i d o f o i " + d ) ;
S t r i n g s = sc . next ( ) ;
System . o u t . p r i n t l n ( " A s t r i n g l i d a f o i " + s ) ;
}
}
Nela podemos ver que, para a leitura de dados a partir do teclado, primeiro precisamos instanciar um objeto
do tipo Scanner, para em seguida podermos usar mtodos como nextInt para a leitura de um nmero do tipo
int. Caso o dado lido no seja do tipo esperado, uma exceo1 lanada.
1 Excees (Exceptions) so representadas por um tipo especial de objeto e utilizadas em Java para o tratamento de erros. Este
recurso no exclusivo de Java, sendo utilizado tambm em outras linguagens, como o C++. Mais informaes sobre o uso de excees
em Java podem ser encontradas no site http://java.sun.com/docs/books/tutorial/essential/exceptions/index.html.
2 http://www.cs.ucsd.edu/users/savitch/java/SavitchIn.txt
3 http://www.sinc.sunysb.edu/Stu/fmquresh/SavitchIn.html
90 CAPTULO 15. FOR, LEITURA DO TECLADO E CONVERSO DE STRINGS
A palavra static na declarao de cada mtodo indica que este mtodo pode ser utilizado mesmo que no
existam instncias da classe. Para utiliz-lo basta fazer algo como no exemplo seguinte:
f o r ( i = 1 ; i <= 1 0 ; i ++)
{
i n t num = S a v i t c h I n . r e a d L i n e I n t ( ) ;
System . o u t . p r i n t l n ( i + " o nmero d i g i t a d o : " + num ) ;
}
Nota: Por uma limitao do DrJava, a classe SavitchIn ainda no funciona na janela Interactions. Segundo
os desenvolvedores do DrJava, esta limitao ser solucionada no futuro. Portanto, por enquanto, voc deve
utilizar a SavitchIn em programas a serem executados na linha de comando.
Exerccios
1. Usando o comando for, escreva um mtodo que recebe um array de doubles como parmetro e imprime
o seu contedo.
2. Usando o comando for, escreva um mtodo somaArrays que recebe 3 arrays de mesmo comprimento
como parmetro e que calcula a soma dos dois primeiros e a armazena no terceiro. A soma deve ser
implementada como soma vetorial, ou seja, soma-se a primeira posio de um vetor com a primeira
posio do segundo, armazenando-se o resultado na primeira posio do terceiro e assim por diante.
Nota: o terceiro array que passado como parmetro chamado de parmetro de sada. Quando o
mtodo se inicia, ele j contm um array que passado por quem chamou o mtodo somaArrays, mas o
seu contedo inicial no relevante. Isso funciona em Java apenas quando passamos uma referncia de
objeto como parmetro, como vimos no Captulo 12.
3. Escreva um mtodo que recebe um array de doubles como parmetro e imprime a mdia dos valores
nele contidos.
4. Escreva dois mtodos (min e max) que recebem um array de inteiros como parmetro e devolvem, res-
pectivamente, um inteiro correspondente ao menor e ao maior elemento do array.
(a) mtodo que recebe um array "vazio"como parmetro e que l valores double do teclado para serem
inseridos no array.
(b) mtodo que recebe 2 arrays de double como parmetro e devolve o valor do produto escalar (soma
dos produtos das posies de mesmo ndice dos dois arrays).
(c) mtodo main que, usando os mtodos anteriores, l do teclado o comprimento dos vetores, l do te-
clado o contedo de dois vetores com o tamanho comprimento, calcula o produto escalar e imprime
o resultado.
92 CAPTULO 15. FOR, LEITURA DO TECLADO E CONVERSO DE STRINGS
Captulo 16
A idia que, para cada iterao do for mais externo, o interpretador Java executa o for mais interno com
todas as suas iteraes. No exemplo acima, o println , portanto, executado 5*3 = 15 vezes.
Agora um exemplo mais complexo: um programa usado para calcular a mdia de vrias turmas na prova
P1 de uma disciplina:
c l a s s MediasNaP1
{
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g )
{
i n t nmeroDeAlunos , nmeroDeTurmas , turma , a l u n o ;
d o u b l e n o t a , soma ;
S c a n n e r s c = new S c a n n e r ( System . i n ) ;
93
94 CAPTULO 16. LAOS ENCAIXADOS E MATRIZES
soma = 0 ;
nota = 0;
System . o u t . p r i n t l n ( " D i g i t e a s n o t a s na P1 da t u r m a " + t u r m a ) ;
System . o u t . p r i n t l n ( " F i n a l i z e a s e q n c i a de n o t a s d i g i t a n d o 1. " ) ;
f o r ( nmeroDeAlunos = 0 ; n o t a >= 0 ; nmeroDeAlunos ++)
{
nota = sc . nextDouble ( ) ;
i f ( n o t a >= 0 )
soma += n o t a ;
}
System . o u t . p r i n t l n ( "A mdia da t u r m a " + soma /
( nmeroDeAlunos 1 ) ) ;
}
}
}
/ / a l o c a e s p a o p a r a uma m a t r i z de 5 l i n h a s e 7 c o l u n a s
m a t r i z = new i n t [ 5 ] [ 7 ] ;
matriz [0][ 0] = 3;
matriz [1][1] = matriz [3][4] + matriz [ 1 ] [ 2 ] ;
muito comum utilizarmos repeties encaixadas quando precisamos percorrer os elementos de matrizes
de duas dimenses ou mais:
int i , j ;
i n t [ ] [ ] t a b u a d a = new i n t [ 1 1 ] [ 1 1 ] ;
f o r ( i = 0 ; i <= 1 0 ; i ++)
f o r ( j = 0 ; j <= 1 0 ; j ++)
tabuada [ i ] [ j ] = i j ;
este trecho de cdigo cria uma matriz de duas dimenses contendo a tabuada de 0 a 10. Note que a primeira
linha e a primeira coluna no precisariam ser inicializadas com uma multiplicao, poderamos atribuir o valor
0 diretamente a elas.
Nota interessante: para Java, na verdade uma matriz bidimensional um array de arrays. Ou seja, tabuada
um array onde cada posio do tipo array de inteiros. Dito isto, pense como podemos fazer para descobrir
quantas linhas e quantas colunas possui uma matriz bidimensional. A resposta a seguinte:
void imprimeDimenses ( i n t [ ] [ ] m a t r i z )
{
System . o u t . p r i n t l n ( "A m a t r i z p o s s u i " +
matriz . length + " linhas e " +
16.3. EXEMPLO: LIFE, O JOGO DA VIDA 95
O processo de simulao iterativo, ou seja, as regras so aplicadas ao estado inicial que produz um
segundo estado. A este segundo estado so aplicadas as regras novamente e assim sucessivamente, criando
novas geraes de clulas ao longo do tempo. Veja um exemplo de implementao do LIFE abaixo. Estude
atentamente cada trecho do programa e depois o execute no DrJava.
class Life
{
i n t MAX = 1 0 ; / / Tamanho da m a t r i z
i n t [ ] [ ] m a t r i z = new i n t [MAX] [MAX] ;
void i n i c i a l i z a ( )
{
int i , j ;
/ / Os m a i s o b s e r v a d o r e s podem p e r c e b e r que a s b o r d a s da m a t r i z no
/ / f o r a m i n i c i a l i z a d a s . F i z e m o s i s s o p a r a d e i x l a s z e r a d a s ( o J a v a
/ / f a z i s t o a u t o m a t i c a m e n t e quando da a l o c a o da m a t r i z ( new i n t ) .
}
void imprimeTabuleiro ( )
{
int i , j ;
int [ ] [ ] iterao ()
{
i n t [ ] [ ] aux = new i n t [MAX] [MAX] ;
int i , j ;
/ / f a r e m o s a s i m u l a o de q u a n t o s c i c l o s
f o r ( i = 0 ; i < q u a n t ; i ++)
{
imprimeTabuleiro ( ) ;
m a t r i z = i t e r a o ( ) ; / / a m a t r i z da i t e r a o a n t e r i o r r e c o l h i d a
/ / p e l o c o l e t o r de l i x o .
}
}
}
16.3. EXEMPLO: LIFE, O JOGO DA VIDA 97
Exerccios
1. Escreva um mtodo para preencher uma matriz com nmeros inteiros lidos do teclado. O mtodo recebe
a matriz como parmetro.
Um mtodo que recebe 3 matrizes do tipo double como parmetro, calcula a soma das duas pri-
meiras e guarda o resultado na terceira.
Um mtodo que recebe 3 matrizes do tipo double como parmetro, calcula o produto das duas
primeiras e guarda o resultado na terceira.
Para os dois mtodos anteriores, escreva uma segunda verso que recebe apenas 2 matrizes como
parmetro e devolve o resultado atravs do comando return.
3. Adicionar classe do exerccio anterior um mtodo que recebe duas matrizes quadradas do tipo double
e devolve um boolean indicando se uma inversa da outra. Lembrando da impreciso das contas com
ponto flutuante considere que um nmero igual a zero se ele pertencer a [108 , 108 ]. De forma
anloga considere que um nmero igual a 1 se ele pertencer a [1 108 , 1 + 108 ].
4. Dizemos que uma matriz Anxn um quadrado latino de ordem n se em cada linha e em cada coluna
aparecem todos os inteiros 1,2,3,...,n (ou seja, cada linha e coluna permutao dos inteiros 1,2,...,n).
Escreva uma classe com os seguintes mtodos:
Veja um exemplo de uso de um objeto da classe nas seguintes iteraes. Aproveitamos o exemplo abaixo
para mostrar como podemos definir matrizes constantes (usando chaves).
Welcome to DrJava.
> QuadradoLatino a = new QuadradoLatino();
> int [][] matriz1 = {{1}};
> a.imprimeMatriz(matriz1)
1
> a.Latino(matriz1)
true
> int [][] matriz2 = {{1,2,3}, {2,3,1}, {3,1,2}};
> a.imprimeMatriz(matriz2)
1 2 3
2 3 1
3 1 2
> a.Latino(matriz2)
true
> int [][] matriz3 = {{1,2}, {1,2}};
> a.imprimeMatriz(matriz3)
1 2
1 2
> a.Latino(matriz3)
false
5. Dizemos que uma matriz Anxn um quadrado mgico de ordem n se o valor da soma dos elementos em
cada linha e em cada coluna o mesmo. Escreva uma classe que inclua mtodos para verificar se uma
dada matriz (recebida como parmetro em um de seus mtodos) um quadrado mgico ou no.
int pertence(int el, int v[], int tam) que verifica se um inteiro el ocorre em um array
v[] com tam elementos. Se ele ocorre, o mtodo devolve a posio da primeira ocorrncia, caso
contrrio devolve -1.
void freqncia(int v[]) que imprime a freqncia absoluta dos elementos em v.
Dica: para calcular a freqncia absoluta so necessrios dois vetores, um com os elementos dis-
tintos e outro com o nmero de ocorrncias. Percorra o array v verificando, para cada posio, se o
nmero armazenado j apareceu.
7. Um jogo de palavras cruzadas pode ser representado por uma matriz Amxn onde cada posio da matriz
corresponde a um quadrado do jogo, sendo que 0 indica um quadrado branco e -1 indica um quadrado
preto. Indicar na matriz as posies que so incio de palavras horizontais e/ou verticais nos quadrados
correspondentes (substituindo os zeros), considerando que uma palavra deve ter pelo menos duas letras.
Para isso, numere consecutivamente tais posies.
Exemplo: Dada a matriz:
16.3. EXEMPLO: LIFE, O JOGO DA VIDA 99
0 -1 0 -1 -1 0 -1 0
0 0 0 0 -1 0 0 0
0 0 -1 -1 0 0 -1 0
-1 0 0 0 0 -1 0 0
0 0 -1 0 0 0 -1 -1
A sada dever ser:
1 -1 2 -1 -1 3 -1 4
5 6 0 0 -1 7 0 0
8 0 -1 -1 9 0 -1 0
-1 10 0 11 0 -1 12 0
13 0 -1 14 0 0 -1 -1
8. (Difcil) Escreva uma classe com um mtodo que leia um inteiro n e as posies de n rainhas em um
tabuleiro de xadrez e determina se duas rainhas se atacam.
100 CAPTULO 16. LAOS ENCAIXADOS E MATRIZES
Captulo 17
Busca e Ordenao
17.1 Busca
Como j vimos, arrays podem guardar muita informao embaixo de uma nica varivel. Uma das opera-
es mais comuns que podemos fazer em um array buscar um elemento nele. Isso pode ser til para saber
se um elemento j est l para recuperar outras informaes dos objetos armazenados. Pense, por exemplo, na
busca de um CD pelo ttulo. Sabendo onde o CD est, podemos recuperar outras informaes, como as faixas
que o compem, sua durao, etc.
Mas como podemos buscar algo? Vamos primeiro aprender a forma mais simples de busca: a busca seqen-
cial. Neste caso, varre-se o array do incio ao fim at encontrarmos o elemento desejado. Isso pode ser feito
usando um simples lao while. Considere que biblioteca um array de objetos da classe Livro. O array
est cheio de livros vlidos, ou seja, tem elementos de 0 a biblioteca.length - 1. Considere ainda que esses
objetos disponibilizam um mtodo pegaNome que devolve o nome do livro. Veja abaixo um exemplo de cdigo
para buscar um livro de nome Amor em tempos de clera.
int i = 0;
w h i l e ( ( i < b i b l i o t e c a . l e n g t h ) &&
( b i b l i o t e c a [ i ] . pegaNome ( ) . e q u a l s ( " Amor em t e m p o s de c l e r a " ) == f a l s e ) )
i = i + 1;
i < bibliotecas.length: Neste caso o livro est na posio i do array. De posse desse ndice pode-
mos manipular o livro encontrado como quisermos.
101
102 CAPTULO 17. BUSCA E ORDENAO
Por fim, devemos destacar que h uma certa sutileza no cdigo acima. Note que no segundo caso no
poderamos acessar o array na posio i. Isso no ocorre devido ordem das condies do while. Como a
primeira condio falsa, o computador no precisa testar a segunda para saber que a expresso falsa, j que
a condio um e-lgico.
1. Seleo direta. Neste algoritmo, a cada passo buscamos o menor elemento no array e o levamos para o
incio. No passo seguinte buscamos o segundo menor elemento e assim por diante.
v o i d s e l e o D i r e t a ( i n t [ ] nmeros )
{
i n t i , j , ndiceDoMnimo , temp ;
i n t f i m = nmeros . l e n g t h ;
f o r ( i = 0 ; i < f i m 1 ; i ++)
{
/ / I n i c i a l m e n t e o menor e l e m e n t o j v i s t o o p r i m e i r o e l e m e n t o .
n di c eD o M n i m o = i ;
f o r ( j = i + 1 ; j < f i m ; j ++)
{
i f ( nmeros [ j ] < nmeros [ i n d ic e Do M ni m o ] )
nd i c eD o M n i m o = j ;
}
/ / C o l o c a o menor e l e m e n t o no i n c i o do s u b v e t o r a t u a l . Para i s s o , t r o c a
/ / de l u g a r o s e l e m e n t o s n o s n d i c e s i e n d i c e D o M n i m o .
temp = nmeros [ i ] ;
nmeros [ i ] = nmeros [ n d ic e Do M ni m o ] ;
nmeros [ n di c e Do M ni m o ] = temp ;
}
}
17.2. PONDO ORDEM NA CASA 103
2. Insero direta. A cada passo aumenta a parte ordenada do array de uma posio, inserindo um novo
elemento na posio correta.
v o i d i n s e r o D i r e t a ( i n t [ ] nmeros )
{
int i , j , nmeroAInserir ;
i n t f i m = nmeros . l e n g t h ;
/ / Cada p a s s o c o n s i d e r a que o a r r a y e s q u e r d a de i e s t o r d e n a d o .
f o r ( i = 1 ; i < f i m ; i ++)
{
/ / T e n t a i n s e r i r m a i s um nmero na p o r o i n i c i a l do a r r a y que
/ / j e s t o r d e n a d a empurrando p a r a d i r e i t a t o d o s o s e l e m e n t o s
/ / m a i o r e s do que n m e r o A I n s e r i r .
n m e r o A I n s e r i r = nmeros [ i ] ;
j = i;
w h i l e ( ( j > 0 ) && ( nmeros [ j 1] > n m e r o A I n s e r i r ) )
{
nmeros [ j ] = nmeros [ j 1 ] ;
j ;
}
nmeros [ j ] = n m e r o A I n s e r i r ;
}
}
3. Mtodo da bolha. Esse mtodo testa se a seqncia est ordenada e troca o par de elementos que gerou
o problema. Pense no array como um tubo de ensaio vertical onde os elementos mais leves sobem
superfcie como bolhas.
v o i d b o l h a ( i n t [ ] nmeros )
{
i n t i , j , temp ;
i n t f i m = nmeros . l e n g t h ;
f o r ( i = f i m 1 ; i > 0 ; i )
/ / V a r r e o a r r a y d e s d e o i n c i o p r o c u r a n d o e r r o s de o r d e n a o .
/ / Como a cada passagem o m a i o r e l e m e n t o s o b e a t s u a
/ / p o s i o c o r r e t a , no h n e c e s s i d a d e de i r a t o f i n a l .
f o r ( j = 1 ; j <= i ; j ++)
/ / Se a ordem e s t e r r a d a p a r a o p a r j 1 e j
i f ( nmeros [ j 1] > nmeros [ j ] )
{
/ / T r o c a o s d o i s de l u g a r
temp = nmeros [ j 1 ] ;
nmeros [ j 1] = nmeros [ j ] ;
nmeros [ j ] = temp ;
}
}
imprimeArray para que o computador mostre todos os elementos vlidos de seu array. Esse mtodo fcil,
basta percorrer o array e pedir a cada passo que o computador imprima o elemento atual (ou a parte dele que
nos interessa ver).
Exerccio
1. Os algoritmos de ordenao neste captulo foram desenvolvidos utilizando nmeros. Se quisermos orde-
nar uma seqncia de nomes, por exemplo, {Renault, McLaren, Ferrari, Toyota, Williams, Honda, Red
Bull, BMW Sauber}, preciso modificar estes mtodos. Escreva uma verso do mtodo da bolha que
ordena um array de String.
2. Vamos descobrir como os algoritmos acima descritos se comportam medida que aumentamos o tamanho
do array a ser ordenado? Para cada um dos algoritmos acima execute o algoritmo utilizando como
entrada arrays de diferentes tamanhos. O tempo gasto para realizar a ordenao cresce linearmente com
o tamanho do array?
3. Algoritmos de ordenao so freqentemente utilizados junto com outros algoritmos para torn-los mais
eficientes.
Escreva uma classe que contenha um mtodo atribuiArray que recebe um array de inteiros e o
armazena como um atributo da classe. Escreva ento um mtodo int nRepeties(int x) que
devolve o nmero de vezes que x aparece neste array
Escreva uma outra classe similar anterior cujo mtodo atribuiArray ordena os elementos do
array antes de armazen-lo como atributo da classe.
Fornea a cada uma das classes vetores de diferentes tamanhos contendo nmeros aleatrios. Para cada
caso, chame o mtodo int nRepeties(int x) utilizando diferentes valores de x.
Podemos argumentar que a primeira classe mais eficiente no caso em que so realizadas poucas consul-
tas a nRepeties e a segunda classe mais eficiente quando so realizadas muitas consultas. Justifique
esta argumentao.
Captulo 18
1. O objeto buscado tem a mesma chave do objeto do meio: ento j encontramos o que queramos e nosso
trabalho acabou;
2. O objeto buscado vem antes do objeto do meio: podemos ento concentrar a busca na poro inicial da
seqncia e esquecer a segunda metade;
3. O objeto buscado fica depois do objeto intermedirio: a busca deve continuar apenas na segunda metade.
105
106 CAPTULO 18. BUSCA BINRIA E FUSO
Ou seja, podemos, usando o elemento intermedirio, eliminar metade do trabalho a cada passo do nosso
algoritmo. Isso faz com que a busca fique muito mais rpida! Vejamos como fica a implementao da busca
binria para um array de inteiros. O mtodo abaixo retorna a posio do valor buscado caso este esteja presente
no array e -1 caso contrrio. Este cdigo pode ser facilmente adaptado para doubles, cadeias de caracteres ou
qualquer outro tipo de objeto.
int buscaBinria ( int valor , int [ ] vetor )
{
i n t esq = 0 ,
dir = vetor . length 1 ,
meio ;
w h i l e ( e s q <= d i r )
{
meio = ( e s q + d i r ) / 2 ;
i f ( v a l o r > v e t o r [ meio ] )
e s q = meio + 1 ;
e l s e i f ( v a l o r < v e t o r [ meio ] )
d i r = meio 1 ;
else
r e t u r n meio ;
}
r e t u r n 1;
}
possvel de iteraes do while do mtodo buscaBinria? A resposta simples: note que a cada iterao do
while, a parte que resta do vetor dividida ao meio. Ento a pergunta que devemos fazer : quantas vezes
eu consigo dividir ao meio um vetor de n elementos at que o vetor resultante contenha apenas um elemento?
Pense um pouco... Aqueles com os conhecimento matemticos em dia vo se lembrar... A resposta log2 n,
ou seja, o logaritmo de n na base 2. Portanto, a complexidade de pior caso do algoritmo de busca binria da
ordem de log2 n.
Voltemos ao exemplo da lista telefnica de nossa megalpole. Se nosso software demora, em mdia, 10s
para comparar dois nomes, ento utilizando o algoritmo da busca binria, demoraramos log2 18.000.000
10 10
1.000.000 = 24, 1 1.000.000 = 0.000241s, ou 0,24 milissegundos, o que bem melhor do que 3 minutos, no?
Portanto, quando nos deparamos com grandes volumes de dados ou problemas computacionalmente dif-
ceis, a escolha do algoritmo que utilizamos pode ter um grande impacto na eficincia do programa que estamos
criando. A rea de Anlise de Complexidade de Algoritmos estuda exatamente estas questes.
18.3 Fuso
Um outro algoritmo interessante ligado a seqncias ordenadas a fuso de duas delas. Ou seja, a unio
(preservando repeties) de duas seqncias ordenadas em uma nica seqncia maior ainda em ordem. Esta
operao conhecida como fuso. Vejamos como podemos implement-la:
/ / Combinao de d o i s v e t o r e s o r d e n a d o s em um novo v e t o r o r d e n a d o .
/ / N o t e que e s t e mtodo d e v o l v e um v e t o r .
int [] fuso ( int [] a , int b [ ] )
{
i n t posa = 0 ,
posb = 0 ,
posc = 0;
i n t [ ] c = new i n t [ a . l e n g t h + b . l e n g t h ] ;
/ / E n q u a n t o nenhuma d a s d u a s s e q n c i a s e s t v a z i a . . .
w h i l e ( p o s a < a . l e n g t h && p o s b < b . l e n g t h )
{
/ / Pega o menor e l e m e n t o a t u a l e n t r e a e b .
i f ( b [ p o s b ] <= a [ p o s a ] )
{
c [ posc ] = b [ posb ] ;
p o s b ++;
}
else
{
c [ posc ] = a [ posa ] ;
p o s a ++;
}
p o s c ++;
}
/ / C o m p l e t a com a s e q n c i a que a i n d a no acabou .
while ( posa < a . l e n g t h )
{
c [ posc ] = a [ posa ] ;
p o s c ++;
p o s a ++;
108 CAPTULO 18. BUSCA BINRIA E FUSO
}
while ( posb < b . l e n g t h )
{
c [ posc ] = b [ posb ] ;
p o s b ++;
p o s c ++;
}
return c ;
}
Exerccios
1. Implemente o algoritmo de busca ternria, que funciona de forma similar ao de busca binria mas que
divide o vetor em trs partes iguais a cada iterao.
2. Construa um programa que o auxilie a determinar qual algoritmo mais eficiente: a busca binria ou a
busca ternria.
4. Analise a complexidade do algoritmo de fuso para o caso em que ambos os vetores de entrada tm
tamanho n. Em outras palavras, qual a ordem do nmero de comparaes e atribuies utilizadas pelo
algoritmo no pior caso.
5. Analise a complexidade do algoritmo de ordenao por seleo direta que vimos no captulo passado.
Quantas comparaes e quantas trocas de elementos o algoritmo realiza? Dica: a frmula da PA (pro-
gresso aritmtica) pode ajudar.
Captulo 19
19.1 Construtores
Desde o incio deste livro, trabalhamos com diferentes tipos de objetos. Mas, antes de comear a usar um
objeto de uma classe ClasseX, devemos cri-lo. Isto foi feito at agora atravs de chamadas do tipo: ClasseX
x = new ClasseX(); na qual a varivel x passa a se referir a um novo objeto da classe ClasseX.
Na linguagem Java, quando no especificamos como um objeto deve ser criado, a prpria linguagem nos
fornece um construtor padro. Vejamos com mais detalhes um exemplo abaixo:
c l a s s Ex1
{
int a ;
double d ;
String s ;
boolean b ;
void imprime ( )
{
System . o u t . p r i n t l n ( "o i n t e i r o vale " + a ) ;
System . o u t . p r i n t l n ( "o real vale " + d ) ;
System . o u t . p r i n t l n ( "a String vale " + s ) ;
System . o u t . p r i n t l n ( "o boolean vale " + b ) ;
}
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s )
{
109
110 CAPTULO 19. CONSTRUTORES E ESPECIFICADORES DE ACESSO
No exemplo acima podemos ver que os nmeros foram inicializados automaticamente com zero, a String
com null e o boolean com false. A inicializao com a referncia nula, null, o padro para as referncias
a objetos em geral.
Mas, e se por alguma razo queremos que as variveis da classe tenham algum valor pr-definido ou,
melhor ainda, que seja definido durante a "construo"do objeto? Neste caso podemos definir explicitamente
um construtor. Veja o exemplo abaixo:
c l a s s Ex2
{
int a ;
double d ;
String s ;
boolean b ;
Ex2 ( i n t i 1 , d o u b l e d1 , S t r i n g s1 , b o o l e a n b1 )
{
a = i1 ;
d = d1 ;
s = s1 ;
b = b1 ;
}
void imprime ( )
{
System . o u t . p r i n t l n ( " o i n t e i r o v a l e " + a ) ;
System . o u t . p r i n t l n ( " o r e a l v a l e " + d ) ;
System . o u t . p r i n t l n ( " a S t r i n g v a l e " + s ) ;
System . o u t . p r i n t l n ( " o b o o l e a n v a l e " + b ) ;
}
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s )
{
/ / Ex2 e = new Ex2 ( ) ; ERRO no podemos m a i s u s a r o c o n s t r u t o r p a d r o
Ex2 o b j 1 = new Ex2 ( 2 , 3 . 1 4 , " Oi " , t r u e ) ;
Ex2 o b j 2 = new Ex2 ( 1 , 1 . 0 , " Tudo 1 " , t r u e ) ;
obj1 . imprime ( ) ;
System . o u t . p r i n t l n ( ) ;
obj2 . imprime ( ) ;
}
}
A primeira observao importante que no podemos mais usar o construtor padro. Se a prpria classe
nos fornece um construtor, de se esperar que devamos respeitar algumas regras na hora de construir o objeto,
logo o construtor padro no est mais disponvel.
Podemos tambm pensar em um exemplo um pouco mais sofisticado, criando uma classe que representa
contas em um banco. Como atributos bvios podemos pensar em ter o nome do titular e o saldo de cada conta.
natural que no possamos criar contas sem titular, logo no construtor sempre ser necessrio fornecer um
19.1. CONSTRUTORES 111
nome (String).
c l a s s Conta
{
String t i t u l a r ;
double s a l d o ;
Conta ( S t r i n g s , double v a l )
{
titular = s;
saldo = val ;
}
void imprime ( )
{
System . o u t . p r i n t l n ( "O c l i e n t e : " + t i t u l a r + " tem s a l d o " + s a l d o ) ;
}
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s )
{
C o n t a c1 = new C o n t a ( " J o s " , 1 0 0 ) ;
C o n t a c2 = new C o n t a ( " M a r i a " , 1 0 0 0 ) ;
c1 . i m p r i m e ( ) ;
System . o u t . p r i n t l n ( ) ;
c2 . i m p r i m e ( ) ;
}
}
Mesmo no exemplo bem simples acima podemos notar que uma operao usual a criao de contas com
saldo zero. Logo, parece natural que tenhamos um construtor que receba apenas o nome, e no o saldo (ficando
subentendido neste caso que no houve depsito inicial).
Conta ( S t r i n g s )
{
titular = s;
saldo = 0;
}
Pode-se observar tambm que podemos reescrever o construtor acima usando funcionalidades do primeiro
construtor.
Conta ( S t r i n g s )
{
this ( s , 0.0);
}
Para isso usamos uma palavra reservada da linguagem Java, a palavra this, que nada mais do que uma
referncia ao prprio objeto. Isto , quando o construtor Conta("Joo") chamado, ele repassa o trabalho ao
outro construtor usando saldo 0.
Tambm interessante notar a diferena entre os dois construtores: como eles tm o mesmo nome (nome
da classe), a nica diferena entre eles est nos parmetros recebidos. O compilador Java escolhe o construtor
112 CAPTULO 19. CONSTRUTORES E ESPECIFICADORES DE ACESSO
correto conforme a assinatura (parmetros e sua ordem). Esta mesma tcnica tambm pode ser usada se pre-
cisarmos de dois mtodos com o mesmo nome, mas que recebam parmetros diferentes. Isto chamado de
polimorfismo de nome.
Tambm interessante ressaltar um outro uso da palavra chave this. Vamos supor que adicionamos um
novo parmetro para as contas, o RG. Logo, teremos um atributo a mais: String RG. Se por acaso quisermos
criar um novo construtor que receba um parmetro tambm chamado de RG, isto se torna possvel.
C o n t a ( S t r i n g s , d o u b l e v a l , S t r i n g RG)
{
titular = s;
saldo = val ;
t h i s . RG = RG;
}
No caso, o this refora que estamos falando de um dos atributos do objeto. At o momento no havamos
usado o this pois tomamos o cuidado de escolher os nomes de parmetros e variveis locais diferentes dos
nomes dos atributos.
void d e p o s i t o ( double v a l )
{
saldo = saldo + val ;
imprime ( ) ;
}
No cdigo acima, no caso de saque, veramos mensagens avisando sobre o sucesso ou falha na operao.
Existem outras formas mais bonitas de mostrar as falhas atravs de excees (Exceptions), mas estas fogem
ao escopo deste livro. Entretanto, um usurio poderia autorizar saques quaisquer, da seguinte forma:
C o n t a c2 = new C o n t a ( " M a r i a " , 1 0 0 0 ) ;
c2 . i m p r i m e ( ) ;
c2 . s a l d o = c2 . s a l d o 1 0 0 0 0 0 ;
c2 . i m p r i m e ( ) ;
Pois, neste caso, o usurio do objeto do tipo Conta estaria interagindo diretamente com atributos do objeto,
mexendo nas suas partes internas. Para evitar isto podemos usar protees explcitas, indicando que s mtodos
19.2. ESPECIFICADORES DE ACESSO 113
do prprio objeto possam alterar os seus atributos. Isto feito com a palavra chave private, como neste
exemplo:
c l a s s Conta
{
private String t i t u l a r ;
p r i v a t e double s a l d o ;
p r i v a t e S t r i n g RG;
...
}
Neste caso, no existe mais o acesso direto aos atributos de objetos da classe Conta. O oposto de private
public que d acesso irrestrito. Os especificadores de acesso tambm podem ser usados com os mtodos.
Quando nenhum especificador utilizado, a linguagem Java usa o acesso amigvel (friendly) que s permite
a visibilidade dentro do mesmo pacote (por enquanto pode se pensar em pacote como sendo equivalente a um
diretrio).
Um outro qualificador interessante o static que indica quais atributos devem ser considerados como da
classe e no especficos a cada objeto. Veja o seguinte exemplo:
class TesteStatic {
s t a t i c int quantidade = 0;
TesteStatic ()
{
System . o u t . p r i n t l n ( " C r i a n d o um o b j e t o do t i p o T e s t e S t a t i c " ) ;
q u a n t i d a d e ++;
System . o u t . p r i n t l n ( " At a g o r a f o r a m c r i a d o s : " + q u a n t i d a d e + "
objetos TesteStatic " );
}
}
A cada objeto TesteStatic criado veremos quantos objetos deste tipo j foram criados anteriormente.
Observem que no uma prtica usual colocar impresses no construtor, mas de forma a apresentar um exemplo
simples optamos por tomar esta liberdade. Alm disto, mtodos static tambm so mtodos de classe, isto ,
podem ser chamados, mesmo que no existam objetos da classe criados. Um exemplo j visto so as funes da
classe Math como, por exemplo, Math.sin(double x). O mtodo main tambm esttico pois ao iniciarmos
a execuo de um programa no existe objeto criado.
Finalmente, um ltimo qualificador interessante o final que serve para definir variveis que no podem
mais ter o seu valor modificado, como, por exemplo, final double PI = 3.1415926538;
Exerccio
1. Reescreva a classe CalculadoraDeImposto descrita no exerccio 2 do Captulo 7, contendo um mtodo
que no recebe nenhum parmetro e devolve o imposto a ser pago. A classe CalculadoraDeImposto
deve possuir em seus atributos as classes Rendimentos e TabeladeAlquotas e receber como parme-
tros em seu construtor todos os valores necessrios para inicializar objetos destas classes. Compare a
abordagem do exerccio do Captulo 7 com a deste exerccio.
114 CAPTULO 19. CONSTRUTORES E ESPECIFICADORES DE ACESSO
2. Suponha que voc possua um programa de edio de imagens que manipula objetos geomtricos. Voc
deseja definir uma classe Quadrado contendo como atributos um inteiro cor e um String tamanho,
definidos pelo usurio no momento de sua criao, mas que no podem ser posteriormente modificados.
Como voc escreveria esta classe?
3. Modifique a classe Quadrado do Exerccio 2 de modo que a cor e o tamanho do objeto possam ser alte-
rados aps sua atribuio inicial. Alm disso, a classe deve garantir que sejam atribudos, para o campo
tamanho, apenas valores positivos e, para o campo cor, apenas as cores amarelo, azul, verde ou
vermelho.
4. (difcil): Como fazer para criar uma classe na qual s seja possvel construir um nico objeto. Este tipo
de objeto chamado de Singleton.
Dica: Limitar o acesso ao construtor.
Captulo 20
Interfaces
Interface: local onde dois sistemas independentes se encontram, atuam ou se comunicam. Webster.
nasa();
passeiePelaTela();
durma();
Mas, apesar de ser especialista em computao, voc conhece muito pouco a respeito de animais, logo voc
ter que pedir a outros programadores, que conhecem bem os animais, as seguintes classes: Ornitorrinco,
Morcego e Zebra. Neste caso, voc passar a seguinte especificao:
115
116 CAPTULO 20. INTERFACES
i n t e r f a c e Animal
{
void nasa ( ) ;
void p a s s e i e P e l a T e l a ( ) ;
v o i d durma ( ) ;
double peso ( ) ;
}
O programador que for implementar o morcego ter que dizer explicitamente que vai usar a interface
Animal, o que feito atravs da palavra chave implements. Como o objetivo apresentar como funcionam as
interfaces, o cdigo dos animais ser apenas composto de comandos de impresso de mensagens.
p u b l i c c l a s s Morcego implements Animal
{
public void nasa ( )
{
System . o u t . p r i n t l n ( " Nasce um l i n d o morcego " ) ;
}
public void p a s s e i e P e l a T e l a ( )
{
System . o u t . p r i n t l n ( " Voa de um l a d o p a r a o o u t r o " ) ;
}
p u b l i c v o i d durma ( )
{
System . o u t . p r i n t l n ( " Dorme de p o n t a c a b e a " ) ;
}
p u b l i c double peso ( )
{
r e t u r n 4 . 5 ; / / morcego : )
}
}
A palavra chave implements obriga o programador a escrever o cdigo correspondente a todos os mto-
dos com suas respectivas assinaturas. Alm disto, todos os mtodos da interface devem ser obrigatoriamente
pblicos. Vejamos as implementaes das outras classes:
p u b l i c c l a s s O r n i t o r r i n c o implements Animal
{
double peso ;
O r n i t o r r i n c o ( double p )
{
peso = p ;
}
p u b l i c double peso ( )
{
return peso ;
}
public void nasa ( )
{
System . o u t . p r i n t l n ( " Quebra o ovo p a r a s a i r " ) ;
}
20.2. UM PRIMEIRO EXEMPLO 117
public void p a s s e i e P e l a T e l a ( )
{
System . o u t . p r i n t l n ( " Anda e n a d a de um l a d o p a r a o o u t r o " ) ;
}
p u b l i c v o i d durma ( )
{
System . o u t . p r i n t l n ( " Dorme d e n t r o de t n e i s , d u r a n t e o d i a " ) ;
}
}
p u b l i c c l a s s Z e b r a implements Animal
{
int l i s t r a s ;
double peso ;
p u b l i c Zebra ( i n t l , double p )
{
l i s t r a s = l ; / / c r i a uma z e b r a com l l i s t r a s
peso = p / / e peso p
}
public void nasa ( )
{
System . o u t . p r i n t l n ( " Nasce m a i s uma z e b r a " ) ;
}
public void p a s s e i e P e l a T e l a ( )
{
System . o u t . p r i n t l n ( " G a l o p a p e l o campo " ) ;
}
p u b l i c v o i d durma ( )
{
System . o u t . p r i n t l n ( " Dorme em p " ) ;
}
p u b l i c double peso ( )
{
return peso ;
}
/ / nada i m p e d e que s e j a m i m p l e m e n t a d o s m t o d o s a d i c i o n a i s
public void c o n t a L i s t r a s ( )
{
System . o u t . p r i n t l n ( " E s t a z e b r a tem " + l + " l i s t r a s " );
}
}
Em tempo: Existe uma regra em Java com relao ao nmero de classes pblicas que
podem existir em um arquivo .java. Em cada arquivo deve existir no mximo uma classe
pblica, sendo que, caso exista uma, o nome do arquivo deve ser igual ao nome da classe
pblica. Logo, no exemplo acima, as classes Ornitorrinco, Morcego e Zebra devem
estar em arquivos separados, com os respectivos nomes: Ornitorrinco.java, Morcego.java
e Zebra.java.
118 CAPTULO 20. INTERFACES
Mas, o uso da interface um pouco mais amplo, pois podemos considerar que cada um dos animais alm de
ser um objeto da prpria classe tambm um objeto do tipo Animal. interessante ressaltar que no podemos
criar novos objetos a partir da interface Animal. Vejamos mais um exemplo:
class ZoolgicoVirtual
{
s t a t i c p u b l i c v o i d c i c l o D e V i d a ( Animal a n i m a l )
{
animal . nasa ( ) ;
animal . p a s s e i e P e l a T e l a ( ) ;
a n i m a l . durma ( ) ;
}
s t a t i c public void f a z F u n c i o n a r ( )
{
Zebra z1 = new Z e b r a ( 1 0 2 , 9 9 ) ; / / c r i a duas z e b r a s
Animal z2 = new Z e b r a ( 1 0 1 , 1 0 7 ) ; / / s e n d o uma do t i p o A n i m a l
Morcego m1 = new Morcego ( ) ;
O r n i t o r r i n c o o1 = new O r n i t o r r i n c o ( 2 5 ) ;
c i c l o D e V i d a ( z1 ) ;
c i c l o D e V i d a ( z2 ) ;
c i c l o D e V i d a ( m1 ) ;
c i c l o D e V i d a ( o1 ) ;
}
}
> ZoolgicoVirtual.fazFuncionar()
Nasce mais uma zebra
Galopa pelo campo
Dorme de p
Nasce mais uma zebra
Galopa pelo campo
Dorme de p
Nasce um lindo morcego
Voa de um lado para o outro
Dorme de ponta cabea
Quebra o ovo para sair
Anda e nada de um lado para o outro
Dentro de tneis, durante o dia
>
Observe que apesar de z2 ter sido definido como uma nova Zebra, a referncia para um objeto do tipo
Animal, de modo que chamadas do tipo z2.contaListras() no so vlidas, mas chamadas z1.contaListras()
o so.
Na verdade, seria interessante refatorarmos o mtodo fazFuncionar() da seguinte forma.
s t a t i c public void f a z F u n c i o n a r ( )
20.3. IMPLEMENTANDO MAIS DE UMA INTERFACE POR VEZ 119
{
Animal [ ] b i c h a r a d a = new Animal [ 4 ] ;
bicharada [ 0 ] = new Z e b r a ( 1 0 2 , 9 9 ) ;
bicharada [ 1 ] = new Z e b r a ( 1 0 1 , 1 0 7 ) ;
bicharada [ 2 ] = new Morcego ( ) ;
bicharada [ 3 ] = new O r n i t o r r i n c o ( 2 5 ) ;
f o r ( i n t i = 0 ; i < b i c h a r a d a . l e n g t h ; i ++)
cicloDeVida ( bicharada [ i ] ) ;
}
f o r ( i n t i = 0 ; i < b i c h a r a d a . l e n g t h ; i ++)
cicloDeVida ( bicharada [ i ] ) ;
}
interface TransportadorDePessoas
{
void entramPessoas ( ) ;
void saemPessoas ( ) ;
}
Agora vamos pensar em trs classes: Ave, nibus e Avio. As classes Ave e nibus podem implementar
a primeira e segunda interface, respectivamente.
c l a s s Ave implements Voador
{
p u b l i c v o i d voa ( )
{
System . o u t . p r i n t l n ( " B a t e a s a s a s bem f o r t e " ) ;
}
public void a t e r r i s s a ( )
{
120 CAPTULO 20. INTERFACES
c l a s s n i b u s implements T r a n s p o r t a d o r D e P e s s o a s
{
public void entramPessoas ( )
{
System . o u t . p r i n t l n ( " Abre a s p o r t a s e e n t r a m a s p e s s o a s " ) ;
}
public void saemPessoas ( )
{
System . o u t . p r i n t l n ( " Abre a s p o r t a s e saem a s p e s s o a s " ) ;
}
}
t . entramPessoas ( ) ;
t . saemPessoas ( ) ;
v . voa ( ) ; / / bate asas
v. aterrissa ();
/ / Com o n i b u s e Ave no podemos chamar a o u t r a i n t e r f a c e .
a . entramPessoas ( ) ;
a . voa ( ) ;
20.4. UM EXEMPLO MAIS SOFISTICADO 121
a. aterrissa ();
a . saemPessoas ( ) ;
v = a;
v . voa ( ) ; / / liga turbinas
}
}
Uma boa prtica seguida por bons programadores OO Programe para as interfaces, no para as imple-
mentaes. Em outras palavras, toda vez que voc escrever cdigo que utiliza outras classes, no pense em
como essas outras classes so implementadas internamente, pense apenas na sua interface. Nunca baseie o seu
cdigo em alguma idiossincrasia interna da classe, use apenas conceitos que so claros a partir das interfaces
das classes que voc usa.
F r u t a ( S t r i n g n , double v , double p )
{
nome = n ;
preo = v ;
peso = p ;
}
void imprime ( )
{
System . o u t . p r i n t l n ( nome + " p e s a " + p e s o
+ " gramas e c u s t a " + preo + " r e a i s " ) ;
}
}
Queremos criar um vetor de Frutas e orden-lo primeiro por preo e posteriormente por peso. Como
fazer isto? Observando os procedimentos de ordenao j vistos fcil ver que a nica mudana o critrio de
comparao. Veja uma implementao usando o algoritmo de insero direta visto no Captulo 17.
public c l a s s Quitanda
{
F r u t a [ ] f r u t a s = new F r u t a [ 5 ] ;
public Quitanda ( )
{
f r u t a s [ 0 ] = new Fruta ( " Laranja " , 0.5 , 100);
f r u t a s [ 1 ] = new F r u t a ( " Ma " , 0 . 8 , 1 2 0 ) ;
f r u t a s [ 2 ] = new F r u t a ( "Mamo" , 1 . 2 , 1 1 0 ) ;
f r u t a s [ 3 ] = new Fruta ( " Cereja " , 5.0 , 20);
122 CAPTULO 20. INTERFACES
p u b l i c void imprime ( )
{
f o r ( i n t i = 0 ; i < f r u t a s . l e n g t h ; i ++)
f r u t a s [ i ] . imprime ( ) ;
}
f o r ( i = 1 ; i < f r u t a s . l e n g t h ; i ++)
{
aInserir = frutas [ i ];
j = i;
w h i l e ( ( j > 0 ) && ( f r u t a s [ j 1 ] . p r e o > a I n s e r i r . p r e o ) )
{
f r u t a s [ j ] = f r u t a s [ j 1];
j ;
}
frutas [ j ] = aInserir ;
}
}
f o r ( i = 1 ; i < f r u t a s . l e n g t h ; i ++)
{
aInserir = frutas [ i ];
j = i;
w h i l e ( ( j > 0 ) && ( f r u t a s [ j 1 ] . p e s o > a I n s e r i r . p e s o ) )
{
f r u t a s [ j ] = f r u t a s [ j 1];
j ;
}
frutas [ j ] = aInserir ;
}
}
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s )
{
Q u i t a n d a x e p a = new Q u i t a n d a ( ) ;
No programa acima, fica claro que tivemos que duplicar o cdigo de ordenao, o que bem desagradvel.
Mas, e se existissem outros critrios para ordenao, teramos que criar um novo mtodo repetindo o cdigo de
ordenao para cada um dos critrios? Isso seria, com certeza, muito ruim.
Como regra geral, devemos sempre evitar cdigo repetido. Quando identificamos um trecho de cdigo que
aparece repetido em vrios lugares, como no caso acima, devemos tentar refatorar (reorganizar) o cdigo para
evitar a repetio. Neste caso, iremos manter o cdigo de ordenao em um mtodo e colocar em outros mto-
dos apenas aquele pequeno trecho que difere de um para outro (o critrio de comparao). Para implementar
esta nova soluo, utilizaremos uma interface definindo a interface de comparao:
i n t e r f a c e ComparadorDeFrutas
{
b o o l e a n Menor ( F r u t a a , F r u t a b ) ;
}
O significado do mtodo bvio: se a for menor que b, o mtodo devolve true, caso contrrio, devolve
false. O que a interface ComparadorDeFrutas no define o significado da palavra menor. Isso deixado
para cada classe concreta que ir implementar esta interface, como vemos abaixo, onde so definidas trs
implementaes diferentes para ComparadorDeFrutas que utilizam, como critrio de comparao, o peso, o
preo e o nome da fruta, respectivamente.
c l a s s ComparaPeso implements C o m p a r a d o r D e F r u t a s
{
p u b l i c b o o l e a n Menor ( F r u t a a , F r u t a b ) { r e t u r n ( a . p e s o < b . p e s o ) ; }
}
c l a s s ComparaPreo implements C o m p a r a d o r D e F r u t a s
{
p u b l i c b o o l e a n Menor ( F r u t a a , F r u t a b ) { r e t u r n ( a . p r e o < b . p r e o ) ; }
}
c l a s s ComparaNome implements C o m p a r a d o r D e F r u t a s
{
p u b l i c b o o l e a n Menor ( F r u t a a , F r u t a b ) { r e t u r n ( a . nome . compareTo ( b . nome ) < 0 ) ; }
}
Agora, basta colocar como parmetro adicional do mtodo de ordenao o comparador desejado:
public c l a s s Quitanda
{
F r u t a [ ] f r u t a s = new F r u t a [ 5 ] ;
public Quitanda ( )
{
f r u t a s [ 0 ] = new F r u t a ( " L a r a n j a " , 0 . 5 , 1 0 0 ) ;
f r u t a s [ 1 ] = new F r u t a ( " Maa " , 0 . 8 , 1 2 0 ) ;
f r u t a s [ 2 ] = new F r u t a ( "Mamo" , 1 . 2 , 1 1 0 ) ;
124 CAPTULO 20. INTERFACES
p u b l i c void imprime ( )
{
f o r ( i n t i = 0 ; i < f r u t a s . l e n g t h ; i ++)
f r u t a s [ i ] . imprime ( ) ;
}
f o r ( i = 1 ; i < f r u t a s . l e n g t h ; i ++)
{
aInserir = frutas [ i ];
j = i;
w h i l e ( ( j > 0 ) && ( c . Menor ( a I n s e r i r , f r u t a s [ j 1 ] ) ) )
{
f r u t a s [ j ] = f r u t a s [ j 1];
j ;
}
frutas [ j ] = aInserir ;
}
}
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s )
{
Q u i t a n d a x e p a = new Q u i t a n d a ( ) ;
1. Se os objetos interagem entre si atravs de referncias a interfaces e no a classes especficas, fica fcil
mudar as classes utilizadas em um sistema sem interferir com aquelas que as utilizam. Por exemplo, se
uma classe implementa uma certa interface, mudanas na implementao da classe que no alterem a
assinatura dos mtodos desta interface no so notadas ao se utilizar objetos atravs desta interface.
2. Fica fcil implementar algo chamado polimorfismo de comportamento, ou seja, podemos utilizar em di-
ferentes momentos classes com diferentes comportamentos, chaveando de um comportamento para outro
quando for necessrio. O uso de interfaces permite que este chaveamento seja feito tanto quando o pro-
grama compilado quanto durante a sua execuo. O exerccio do berrio (veja a seo de exerccios a
seguir) um exemplo deste polimorfismo onde interfaces so utilizadas para tornar um programa multi-
linge, ou seja, com muito pouco esforo pode-se escolher qual lngua (portugus, ingls, francs, etc.)
um programa ou sistema utilizar para interagir com seus usurios.
3. Se se est desenvolvendo um programa ou sistema muito grande e complexo, pode ser necessrio utilizar
vrios programadores ou, at mesmo, vrias equipes de programadores. Neste caso, o que se costuma
fazer dividir o sistema em sub-sistemas e definir muito bem as interfaces de cada sub-sistema. A partir
da, cada equipe pode desenvolver independentemente o seu sub-sistema sem necessitar de conhecimen-
tos sobre o funcionamento interno dos outros sub-sistemas; basta conhecer as suas interfaces. Aps esta
fase, passa-se fase de integrao, durante a qual os vrios sub-sistemas so compilados, executados e
testados em conjunto.
4. O uso de interfaces pode ajudar a eliminar cdigo repetido (como no exemplo anterior do ComparadorDeFrutas),
o que ajuda a melhorar muito a qualidade do cdigo.
5. Usando-se interfaces, possvel encomendar a terceiros a escrita de partes de um programa sem que
esta pessoa tenha que conhecer o resto do programa ou mesmo ter acesso ao seu cdigo-fonte. Veja
um exemplo desta prtica no exerccio das figuras geomtricas abaixo, que se utiliza de uma interface
Figura2D.
Exerccios
1. Seu chefe est fazendo um programa para manipulao de figuras geomtricas. Como o programa
muito complexo, ele pediu a sua ajuda encomendando a voc a implementao de trs classes (Quadrado,
Retngulo e Crculo). Voc livre para definir como ser a implementao mas seu chefe definiu que
as suas classes devem implementar a seguinte interface:
interface Figura2D
{
double calcularea ( ) ;
double calculaPermetro ();
void mudaCor ( S t r i n g c o r ) ;
String pegaCor ( ) ;
126 CAPTULO 20. INTERFACES
Agora, escreva um mtodo veculoPreferido() que recebe um array de veculos de corrida como
parmetro e, dentre os veculos vermelhos, imprime a marca e o modelo do que possuir a maior potncia.
3. Voc foi contratado para trabalhar em um berrio (!!!) e no seu primeiro dia de trabalho, deve escrever
uma classe para informar aos pais dados sobre os seus bebs. A dificuldade que muitos estrangeiros
freqentam esse berrio e o seu programa deve ser capaz de dar informaes em portugus e em ingls
(e, futuramente, em outros idiomas tambm). Para permitir isso, voc dever prover duas implementaes
da interface a seguir, que indica as mensagens de texto que devero ser mostradas aos pais:
interface MensagensSobreNeoNatal
{
String nomeDoBeb ( S t r i n g nome ) ;
String d a t a D e N a s c i m e n t o ( Beb b ) ;
String p e s o ( d o u b l e p e s oE m Q u i l os ) ;
String t e m p e r a t u r a ( double t e m p e r a t u r a E m C e l s i u s ) ;
}
Ao se chamar o mtodo nomeDoBeb, por exemplo, sua implementao deve devolver uma mensagem
como "O nome do beb Godofredo Manoelino de Moraes". Ao se chamar o mtodo peso, deve-se
devolver algo como "O peso do beb 3140 gramas ". A primeira implementao deve se chamar Men-
sagensBrasileiras e a segunda MensagensEstadosunidenses. As mensagens para os americanos devem
apresentar o peso em libras (pounds) e a temperatura em graus fahrenheit. A interface Beb, que vocs
no precisam implementar, pois podem supor que o berrio j possui as implementaes, a seguinte:
i n t e r f a c e Beb
{
S t r i n g nome ( ) ;
int diaNascimento ( ) ;
i n t m e s Na s c i m e nt o ( ) ;
i n t anoNascimento ( ) ;
d o u b l e p e s o ( ) ; / / SI , ou s e j a , em q u i l o s
d o u b l e t e m p e r a t u r a ( ) ; / / SI , ou s e j a , em c e l s i u s
}
A classe que o berrio vai usar para imprimir as informaes para os pais ter um mtodo similar ao
seguinte:
class Berrio
{
20.5. A IMPORTNCIA DE INTERFACES 127
Beb [ ] l i s t a D e B e b s ;
/ / a q u i vo o u t r o s m t o d o s p a r a i n s e r o e
/ / remoo de b e b s da l i s t a
v o i d i m p r i m e D a d o s S o b r e B e b ( Beb b , M e n s a g e n s S o b r e N e o N a t a l m)
{
System . o u t . p r i n t l n (m. nomeDoBeb ( b . nome ( ) ) ;
System . o u t . p r i n t l n (m. d a t a D e N a s c i m e n t o ( b ) ;
System . o u t . p r i n t l n (m. p e s o ( b . p e s o ( ) ) ;
System . o u t . p r i n t l n (m. t e m p e r a t u r a ( b . t e m p e r a t u r a ( ) ) ;
}
v o i d i m p r i m e ( i n t IDdoBeb , S t r i n g i d i o m a )
{
M e n s a g e n s S o b r e N e o N a t a l m;
i f ( idioma . equals ( " Portugus " ) )
m = new M e n s a g e n s B r a s i l e i r a s ( ) ;
else
m = new M e n s a g e n s E s t a d o s u n i d e n s e s ( ) ;
i m p r i m e D a d o s S o b r e B e b ( l i s t a D e B e b s [ IDdoBeb ] , m ) ;
}
}
4. Dada a classe
c l a s s Pessoa
{
S t r i n g nome ;
in t rg ;
int cpf ;
}
6. (Longo) Voc foi contratado para ajudar na implementao de uma loja virtual para venda, atravs da
Web, de livros, CDs, LPs, DVDs, filmes VHS, etc. No seu primeiro dia de trabalho, seu chefe lhe
mostrou a seguinte interface que utilizada para representar todos os produtos a serem vendidos pela
loja:
interface Produto
128 CAPTULO 20. INTERFACES
{
String ttulo();
int nmeroDeIdentificao(); // nmero nico identificando o produto
int ano();
String autor();
String mdia(); // devolve "livro", "CD", "DVD", etc.
}
No seu primeiro dia de trabalho, voc deve implementar uma classe contendo mtodos para:
(a) dada uma lista de compras (um array de Produtos), devolver uma nova lista de compras contendo o
mesmo contedo mas com os produtos ordenados de acordo com os seus nmerosDeIdentificao;
(b) dadas duas listas de compras, cada uma delas j ordenadas com o mtodo acima, gerar e devolver
uma nova lista ordenada resultante da fuso das duas listas iniciais; elementos que aparecerem nas
duas listas iniciais devero aparecer duplicados na lista final.
(c) Agora, escreva pelos menos duas classes que implementem a interface Produto e, em seguida, d
um exemplo de cdigo que cria duas listas de compras, as ordena, as funde, e finalmente imprime
de forma clara e organizada as informaes sobre os produtos contidos na lista resultante da fuso.
Captulo 21
Herana
129
130 CAPTULO 21. HERANA
c l a s s B extends A
{
i n t b1 ;
void vina ( )
{
pata ( ) ;
b1 = a1 ;
}
}
Note que B contm os mtodos e atributos de A e ainda acrescenta um novo atributo e um novo mtodo.
Vejamos agora um exemplo mais complexo que implementa, em Java, o diagrama de classes apresentado
no diagrama UML acima.
21.3. IMPLEMENTAO DE HERANA NA LINGUAGEM JAVA 131
c l a s s Pessoa
{
p r i v a t e S t r i n g nome ;
p r i v a t e char s e x o ;
p r i v a t e S t r i n g CPF ;
p r i v a t e S t r i n g RG;
p r i v a t e i n t a n oD e N a s ci m e n to ;
v o i d imprimeDados ( )
{
i f ( s e x o == F )
System . o u t . p r i n t l n ( "A S r a . " + nome + " n a s c e u no ano " + an o D e Na s c i m en t o +
" . CPF : " + CPF + " , RG " + RG ) ;
else
System . o u t . p r i n t l n ( "O S r . " + nome + " n a s c e u no ano " + an o D e Na s c i m en t o +
" . CPF : " + CPF + " , RG " + RG ) ;
}
}
c l a s s Aluno e x t e n d s P e s s o a
{
private String curso ;
private int anoDeIngresso ;
v o i d imprimeDados ( )
{
s u p e r . imprimeDados ( ) ;
System . o u t . p r i n t l n ( " I n g r e s s o u no c u r s o " + c u r s o + " em " +
anoDeIngresso ) ;
}
}
c l a s s P r o f e s s o r extends Pessoa
{
private String departamento ;
p r i v a t e i n t anoDeAdmisso ;
v o i d imprimeDados ( )
{
s u p e r . imprimeDados ( ) ;
System . o u t . p r i n t l n ( " I n g r e s s o u no d e p t . " + d e p a r t a m e n t o + " em " +
anoDeAdmisso ) ;
}
}
c l a s s ProfessorDoutor extends P r o f e s s o r
{
p r i v a t e i n t anoDeObtenoDoutorado ;
private String instituioDoDoutorado ;
v o i d imprimeDados ( )
{
s u p e r . imprimeDados ( ) ;
System . o u t . p r i n t l n ( " D o u t o r a d o o b t i d o em " + i n s t i t u i o D o D o u t o r a d o
+ " em " + a n o D e O b t e n o D o u t o r a d o ) ;
}
}
132 CAPTULO 21. HERANA
Um banco de dados da universidade pode armazenar objetos do tipo Pessoa da seguinte forma:
c l a s s ListaDePessoasDaUSP
{
P e s s o a [ ] membrosDaUSP ;
L i s t a D e P e s s o a s D a U S P ( i n t tamanho )
{
membrosDaUSP = new P e s s o a [ tamanho ] ;
}
/ / m t o d o s p a r a a c r e s c e n t a r e r e m o v e r p e s s o a s da l i s t a de p e s s o a s
void l i s t a T o d o s ( )
{
int i ;
f o r ( i = 0 ; i < membrosDaUSP . l e n g t h ; i ++)
membrosDaUSP [ i ] . imprimeDados ( ) ;
}
/ / demais mtodos . . .
}
Note que, para o mtodo listaTodos, no interessa qual o tipo especfico de cada pessoa (aluno, professor,
professor doutor) uma vez que ele manipula apenas os atributos da superclasse Pessoa.
Quando um programa possui uma srie de classes relacionadas atravs de herana, dizemos que temos uma
hierarquia de classes.
Apresentamos na figura 21.2 uma hierarquia de classes para representar os diversos tipos de seres vivos.
21.5 Relacionamento um
Nem sempre fcil determinarmos qual hierarquia de classes devemos utilizar. A relao superclasse-
subclasse deve necessariamente ser um relacionamento do tipo " um", ou seja, se B subclasse de A ento todo
B um A.
Em termos mais concretos, no exemplo dos seres vivos, Animal um SerVivo, e mais, todo animal um
ser vivo. No existe nenhum animal que no seja um ser vivo. Ento o relacionamento superclasse-subclasse
pode ser apropriado.
Outra possibilidade seria ter uma hierarquia como a seguinte:
A princpio, esta pode parecer uma hierarquia aceitvel. Mas na verdade ela est ERRADA. No podemos
dizer que "um reino um ser vivo", no faz sentido, no podemos dizer que "um filo um reino"porque no .
Ento a hierarquia no est boa.
21.6 Resumo
uma classe pode herdar de outra seus atributos e mtodos;
uma subclasse pode estender a funcionalidade de sua superclasse acrescentando novos atributos e mto-
dos.
Mas, e se uma subclasse implementar um mtodo com assinatura idntica a um mtodo da superclasse?
Neste caso, quem prevalece o mtodo da subclasse e dizemos que o mtodo da subclasse se sobrepe ("over-
rides") ao mtodo da superclasse.
Exerccios
1. Retornando hierarquia de classes apresentada na figura 21.2, pense em quais mtodos e atributos deve-
riam estar presentes nas classes superiores da hierarquia e quais deveriam estar nas partes inferiores da
hierarquia.
2. Figuras geomtricas so um bom exemplo para se construir um hierarquia de classes. Considere as figuras
quadrado, retngulo, tringulo (retngulo, acutngulo e obtusngulo) e losango. Construa duas diferentes
hierarquias para estas classes, uma com dois nveis e outra com trs nveis, colocando os atributos que
134 CAPTULO 21. HERANA
devem ser considerados comuns em cada nvel da hierarquia. Compare estas duas hierarquias, discutindo
suas vantagens e desvantagens.
3. Desenvolva um conjunto de classes para controlar o saldo, depsitos e retiradas de contas bancrias bem
como os dados do titular. Escreva inicialmente um diagrama modelando tanto contas corrente quanto
contas poupana e aplicaes em fundo. Em seguida, implemente estas classes em Java.
Captulo 22
Javadoc
Vimos nos ltimos captulos que um conceito fundamental em programao orientada a objeto a separao
clara entre implementao e interface. Ou seja, um programador que v usar objetos de uma classe deve se ater
poro pblica da mesma, desprezando detalhes de implementao e as pores privadas (que no estariam
acessveis de qualquer forma). Deste modo, passa a ser natural a exigncia de documentao de boa qualidade
que permita ao usurio de uma classe saber tudo o que precisa sem que necessite ler o cdigo que a implementa.
A entra o javadoc.
O javadoc um programa que permite extrair, de um arquivo com cdigo Java, a sua documentao (texto
explicativo). Essa documentao ento formatada em HTML (HyperText Markup Language), que a mesma
linguagem que descreve as pginas da Web, de modo a facilitar a sua consulta. Assim possvel consultar
a documentao de uma classe sem as distraes presentes sempre que esta est misturada ao cdigo. Um
exemplo disso que, em sua configurao padro, o javadoc processa apenas a documentao das partes
pblicas de seu cdigo, omitindo tudo o que privado.
Para facilitar a vida do programa javadoc existem algumas convenes que devem ser seguidas. A primeira
que apenas comentrios iniciados por /** (e terminados por */) so processados. Tambm o comentrio de
cada parte pblica deve preced-la imediatamente. Vejamos um exemplo simples.
p u b l i c c l a s s Quadrado implements F i g u r a G e o m t r i c a
{
p r i v a t e double l a d o ;
private String cor ;
p u b l i c Quadrado ( d o u b l e l , S t r i n g c )
{
lado = l ;
cor = c ;
}
p u b l i c double c a l c u l a r e a ( )
135
136 CAPTULO 22. JAVADOC
{
return lado lado ;
}
p u b l i c v o i d mudaCor ( S t r i n g c )
{
cor = c ;
}
}
1. A prpria classe, ou seja, todo mundo pode criar objetos baseados nela;
2. O construtor;
Cada um desses tens deveria ser antecedido por um comentrio explicando qual sua funo e como ele
deve ser usado. Lembrando as convenes de como demarcar os comentrios descritas acima, teramos:
/
Uma c l a s s e p a r a r e p r e s e n t a r q u a d r a d o s .
/
p u b l i c c l a s s Quadrado implements F i g u r a G e o m t r i c a
{
p r i v a t e double l a d o ;
private String cor ;
/
Construtor
E x i g e o c o m p r i m e n t o do l a d o e a c o r do q u a d r a d o .
/
p u b l i c Quadrado ( d o u b l e l , S t r i n g c )
{
lado = l ;
cor = c ;
}
/
C a l c u l a a r e a do q u a d r a d o b a s e a d a no s e u l a d o .
/
p u b l i c double c a l c u l a r e a ( )
{
return lado lado ;
}
/
A l t e r a a c o r do q u a d r a d o p a r a a c o r r e p r e s e n t a d a no S t r i n g c .
/
p u b l i c v o i d mudaCor ( S t r i n g c )
{
cor = c ;
}
137
Uma outra caracterstica interessante do javadoc que ele possui alguns marcadores especiais para que
possa extrair informaes relevantes dos comentrios e format-las de modo especial. Os marcadores mais
importantes so:
Marcador geral: @see. Pode ser usado em qualquer lugar para referenciar uma outra classe ou um mtodo
de outra classe; assume geralmente uma das duas forma a seguir.
@see nome-da-classe
@see nome-da-classe#nome-do-mtodo
/
Construtor
@param l d o u b l e r e p r e s e n t a n d o o c o m p r i m e n t o d o s l a d o s
@param c S t r i n g com o nome da c o r da f i g u r a
/
p u b l i c Quadrado ( d o u b l e l , S t r i n g c )
{
lado = l ;
cor = c ;
}
/
C a l c u l a a r e a do q u a d r a d o b a s e a d a no s e u l a d o
@param No h p a r m e t r o s
@return r e a computada
138 CAPTULO 22. JAVADOC
/
p u b l i c double c a l c u l a r e a ( )
{
return lado lado ;
}
/
A l t e r a a c o r do q u a d r a d o .
@param c S t r i n g com o nome da nova c o r
@return No h r e t o r n o
/
p u b l i c v o i d mudaCor ( S t r i n g c )
{
cor = c ;
}
}
Na figura 22.1 apresentada a documentao gerada pelo Javadoc para a classe Quadrado.
claro que para o marcador @see funcionar, voc tambm deve documentar a interface usando os padres
de javadoc. Ao documentar a interface voc pode usar os mesmos marcadores usados para classe.
Agora que temos nosso cdigo documentado de forma adequada, como podemos gerar a documentao em
html? Para isso, basta ir ao diretrio com os arquivos .java e digitar
A documentao ser ento gerada e os arquivos resultantes sero colocados dentro do subdiretrio doc do
diretrio atual. claro que o nome desse diretrio pode ser alterado mudando-se a palavra que segue o -doc
presente acima.
Por fim, podemos tambm documentar as pores privadas de nossas classes. Para forar o javadoc a gerar
documentao tambm para a parte privada, basta acrescentar o parmetro -private na linha de comando
acima.
Obs.: se desejado, os comentrios de javadoc podem conter comandos em HTML.
139
O C Que H em Java
como h apenas uma classe e no h atributos no possvel organizar o programa como diversos objetos,
eventualmente pertencentes a classes diferentes, interagindo;
como no h atributos s existem dois tipos de variveis: os parmetros e as variveis locais s funes;
como no h classes e objetos de verdade, todas as variveis so de tipos primitivos: int, double ou
char. Pelo menos h tambm a idia de array, ou vetor, e matrizes em C;
em C no h o tipo boolean. No seu lugar usamos inteiros com o 0 representando falso e qualquer
nmero no nulo representando verdadeiro. Note que as expresses lgicas passam ento a gerar valores
inteiros como resultados.
Esses pontos j so interessantes o suficiente para vermos o que acontece. Consideremos o primeiro exem-
plo visto neste livro: o conversor de temperaturas. Voc lembra que ele era um objeto sem atributos? Vejamos
o seu cdigo (adicionamos um main e os identificadores de acesso):
141
142 CAPTULO 23. O C QUE H EM JAVA
public c l a s s Conversor
{
s t a t i c double c e l s i u s P a r a F a h r e n h e i t ( double c )
{
return 9.0 c / 5.0 + 3 2 . 0 ;
}
s t a t i c double f a h r e n h e i t P a r a C e l s i u s ( double f )
{
return 5.0 ( f 3 2 .0 ) / 9 . 0 ;
}
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s )
{
double f a r , c e l ;
S c a n n e r s c = new S c a n n e r ( System . i n ) ;
double c e l s i u s P a r a F a h r e n h e i t ( double c )
{
return 9.0 c / 5.0 + 3 2 . 0 ;
}
double f a h r e n h e i t P a r a C e l s i u s ( double f )
{
return 5.0 ( f 3 2 . 0) / 9 . 0 ;
}
/ Oba , i m p r i m i r f i c o u m a i s f a c i l : o comando e m a i s c u r t o . /
23.2. DETALHES DE ENTRADA E SADA 143
p r i n t f ( " De um t e m p e r a t u r a em F a h r e n h e i t : " ) ;
/ A l e i t u r a tambem mudou , v e j a d e t a l h e s a b a i x o . /
s c a n f ( "%l f " , &f a r ) ;
cel = fahrenheitParaCelsius ( far );
p r i n t f ( "A t e m p e r a t u r a em C e l s i u s e : %f \ n " , c e l ) ;
p r i n t f ( " De um t e m p e r a t u r a em C e l s i u s : " ) ;
s c a n f ( "%l f " , &c e l ) ;
far = celsiusParaFahrenheit ( cel );
p r i n t f ( "A t e m p e r a t u r a em F a h r e n h e i t e : %f \ n " , f a r ) ;
1. printf: imprime na tela. O primeiro parmetro deve ser sempre uma string (texto entre aspas). Dife-
rentemente de Java, no podemos usar a soma para concatenar cadeias. Como apresentar ento variveis
no meio de uma string que ser impressa pelo printf? Usamos nesse caso marcadores especiais para
"deixar espao"para imprimir o valor da varivel e em seguida passamos estas variveis como parmetro.
Vejamos um exemplo.
p r i n t f ( " E s s e e i n t e i r o %d , e s s e d o u b l e %f e o u l t i m o um c h a r %c " ,
u m I n t e i r o , umDouble , umChar ) ;
Caso desejemos que o printf pule de linha ao final, devemos adicionar um \n no final da string do
printf:
p r i n t f ( " E s s e e i n t e i r o %d , e s s e d o u b l e %f e o u l t i m o um c h a r %c \ n " ,
u m I n t e i r o , umDouble , umChar ) ;
Vale a pena consultar um manual de C para ver o printf em ao. Ele um comando mais poderoso do
que parece.
2. scanf: para ler valores do teclado usamos o scanf. Ele tambm recebe uma string com marcadores
semelhantes do printf (a principal diferena que para ler um double usamos %lf e no %f). Depois
aparecem as variveis que devem ser lidas antecedidas de um &. Por exemplo, se queremos ler um inteiro
e um double fazemos:
s c a n f ( "%d%l f " , &u m I n t e i r o , &umDouble ) ;
144 CAPTULO 23. O C QUE H EM JAVA
/ T r o c a d u a s v a r i a v e i s de l u g a r /
v o i d swap ( i n t a , i n t b )
{
i n t temp ;
temp = a ;
a = b ;
b = temp ;
}
i n t main ( )
{
int c , d ;
c = 1;
d = 2;
swap(&c , &d ) ;
p r i n t f ( " c = %d , d = %d " , c , d ) ;
}
Outra mudana que os colchetes de parmetros que so vetores e matrizes devem vir aps os seus nomes
(e no antes como em Java). Alm disso, se o parmetro uma matriz, voc deve informar na declarao da
funo qual o nmero de linhas da matriz. Por exemplo
v o i d umaFuncao ( i n t umVetor [ ] , i n t u m a M a t r i z [ 1 0 0 ] [ ] )
# i n c l u d e < s t d i o . h>
v o i d s e l e c a o D i r e t a ( i n t numeros [ ] , i n t f i m )
{
i n t i , j , minimo , temp ;
for ( i = 0 ; i < fim 1 ; i = i + 1)
{
/ I n i c i a l m e n t e o menor e l e m e n t o j a v i s t o e o p r i m e i r o e l e m e n t o . /
minimo = i ;
for ( j = i + 1 ; j < fim ; j = j + 1)
{
i f ( numeros [ j ] < numeros [ minimo ] )
minimo = j ;
}
/ C o l o c a o menor e l e m e n t o no i n i c i o do s u b v e t o r a t u a l . /
temp = numeros [ i ] ;
numeros [ i ] = numeros [ minimo ] ;
numeros [ minimo ] = temp ;
}
}
i n t main ( )
{
/ A c e i t a no maximo 100 numeros no v e t o r . /
i n t numeros [ 1 0 0 ] ;
i n t i = 1;
/ Le o v e t o r . /
do
{
i ++;
s c a n f ( "%d " , &numeros [ i ] ) ;
} w h i l e ( numeros [ i ] > 0 ) ;
/ Ordena p a r a e n c o n t r a r a mediana . /
s e l e c a o D i r e t a ( numeros , i ) ;
/ Agora f i c o u f a c i l . /
p r i n t f ( "A m e d i a n a e : %d \ n " , numeros [ ( i 1 ) / 2 ] ) ;
/ O t a l return i n u t i l . /
return 0;
}
Exerccios
1. Escreva um programa em C que l uma sequncia de nmeros do teclado. Para cada valor x lido, o
programa deve imprimir o valor de x2 e x!. Se x for igual a 0 (zero), o programa termina. Alm da funo
main, seu programa dever conter as funes calculaQuadrado e calculaFatorial.
2. Escreva um programa em C que l um inteiro do teclado e verifica se este nmero palndromo. Um
146 CAPTULO 23. O C QUE H EM JAVA
nmero palndromo um nmero que lido de trs para frente o mesmo quando lido normalmente. Por
exemplo, os nmeros 11111, 64546 e 1001 so palndromos, mas 1232 no .
4. Escreva um programa em C que l um nmero real x do teclado e calcula os valores do seno e coseno de
x. Para tal, utilize as sries de Taylor descritas no Captulo 10.
5. Escreva um programa em C que l uma seqencia de nmeros inteiros terminada por 0 (zero) do teclado e
imprime estes valores ordenados. Para este exerccio, voc pode utilizar a funo de ordenao fornecida
no exemplo da Seo 23.5.
6. Escreva uma funo metodoDaBolha que recebe um vetor e o ordena utilizando o mtodo da bolha ex-
plicado no Captulo 17. Em seguida, modifique o programa do Exerccio 5 para utilizar esta nova funo
de ordenao. Para finalizar, escreva uma funo que testa automaticamente sua funo metodoDaBolha.
Resolues
Exerccio 1
# i n c l u d e < s t d i o . h>
i n t c a l c u l a Q u a d r a d o ( i n t numero ) {
i n t quadrado ;
q u a d r a d o = numero numero ;
return quadrado ;
}
i n t c a l c u l a F a t o r i a l ( i n t numero ) {
int f a t o r i a l = 1;
w h i l e ( numero > 1 ) {
f a t o r i a l = f a t o r i a l numero ;
numero = numero 1 ;
}
return f a t o r i a l ;
}
i n t main ( ) {
i n t numero ; / v a l o r l i d o do t e c l a d o /
i n t quadrado ; / armazena o q u a d r a d o de numero /
int f a t o r i a l ; / armazena o f a t o r i a l de numero /
w h i l e ( numero ! = 0 ) {
q u a d r a d o = c a l c u l a Q u a d r a d o ( numero ) ;
f a t o r i a l = c a l c u l a F a t o r i a l ( numero ) ;
p r i n t f ( "O q u a d r a d o do numero %d e %d \ n " , numero , q u a d r a d o ) ;
p r i n t f ( "O f a t o r i a l do numero %d e %d \ n " , numero , f a t o r i a l ) ;
23.5. UM LTIMO EXEMPLO 147
return 0;
}
Exerccio 2
# i n c l u d e < s t d i o . h>
i n t c a l c u l a R e v e r s o ( i n t numero ) {
int reverso = 0;
w h i l e ( numero ! = 0 ) {
/ a c r e s c e n t a m a i s um d i g i t o a d i r e i t a de r e v e r s o /
r e v e r s o = r e v e r s o 10 + numero % 1 0 ;
/ remove e s s e d i g i t o de numero /
numero = numero / 1 0 ;
}
return r e v e r s o ;
}
i n t main ( ) {
i n t numero ; / numero l i d o do t e c l a d o /
int reverso ; / armazena o numero i n v e r t i d o /
r e v e r s o = c a l c u l a R e v e r s o ( numero ) ;
return 0;
}
Exerccio 3
# i n c l u d e < s t d i o . h>
i n t d e c i m a l P a r a B i n a r i o ( i n t numero )
{
int digito ;
int binario = 0;
int potencia = 1;
w h i l e ( numero > 0 ) {
148 CAPTULO 23. O C QUE H EM JAVA
/ e x t r a i p r o x i m o d i g i t o b i n a r i o menos s i g n i f i c a t i v o ( m a i s a d i r e i t a ) /
d i g i t o = numero % 2 ;
/ remove e s s e d i g i t o de numero /
numero = numero / 2 ;
/ a d i c i o n a o d i g i t o como o m a i s s i g n i f i c a t i v o a t e o momento /
binario = binario + digito potencia ;
potencia = potencia 10;
}
return b i n a r i o ;
}
i n t main ( ) {
i n t numero ; / v a l o r na b a s e d e c i m a l l i d o do t e c l a d o /
i n t b i n a r i o ; / v a l o r c o n v e r t i d o para a base b i n a r i a /
b i n a r i o = d e c i m a l P a r a B i n a r i o ( numero ) ;
return 0;
}
Apndice A
Objetivos
Neste apndice forneceremos uma breve introduo ao uso do DrJava. O contedo limitado e especfico,
suficiente para que voc posteriormente seja capaz de conhecer melhor esta ferramenta por conta prpria.
Recomendamos para isso a consulta de manuais e outros documentos, no necessariamente sobre DrJava
apenas. As descobertas pelo prprio uso e atravs de dicas de colegas tambm so incentivadas.
Neste apndice voc aprender a utilizar o DrJava para:
O DrJava pode ser obtido no endereo http://drjava.org/. Neste stio possvel ainda encontrar
documentao detalhada sobre como instalar e utilizar o DrJava.
149
150 APNDICE A. UTILIZANDO O DR. JAVA
O painel de definies, indicado na figura acima, um editor de textos. nele que digitaremos o cdigo
Java que define a classe Conversor. Ele se parece muito com um editor de textos comum, exceto que possui
alguns recursos para facilitar a digitao de cdigo. Em particular, o comportamento das teclas <Enter> e
<Tab> favorece a indentao do cdigo. Outro recurso til a colorao e o destaque do texto.
Precisamos criar um arquivo novo para conter o cdigo da nossa classe. Para isso, bastaria escolher a
opo New do menu File. Porm, quando abrimos o DrJava, um novo arquivo sem nome j foi criado, ento
podemos us-lo nesse momento (em vez de criar um novo). Sendo assim, digite o seguinte cdigo no painel de
definies.
c l a s s Conversor
{
int celsiusParaFahrenheit ()
{
r e t u r n 9 40 / 5 + 3 2 ;
}
}
Ao digitar, note os recursos mencionados que ajudam a programao (principalmente o comportamento das
teclas <Enter> e <Tab>).
nome, estaremos na verdade acionando a opo Save as.... Por isso, surgir um dilogo para definirmos a
localizao e o nome do arquivo, como mostra a seguinte figura.
Podemos determinar a localizao, manipulando a combo box com rtulo Save In: (no topo do dilogo)
e escolhendo um diretrio na caixa abaixo dela, ou podemos deixar a localizao como est. Desse modo,
provavelmente o arquivo ser gravado no diretrio de onde o DrJava foi chamado.
Tambm precisamos escolher o nome do arquivo. Em algumas ocasies, este deve ser obrigatoriamente
idntico ao nome da classe, mais o sufixo .java. No o nosso caso, mas mesmo assim vamos chamar o arquivo
de Conversor.java. Como j digitamos o cdigo da classe, o DrJava preencheu o nome do arquivo no input field
de rtulo File Name: com o nome da classe. Note tambm que ele no acrescentou o sufixo .java no nome, o
que ser feito implicitamente quando finalizarmos (mas no h problema em digitar o sufixo mesmo assim).
Para confirmar a gravao, basta clicar no boto Save. As modificaes futuras podem ser gravadas com o
comando Save, sem precisar escolher o nome do arquivo novamente.
Com os arquivos das classes gravados em disco, podemos querer reutiliz-los no futuro. No DrJava, basta
escolhermos a opo Open do menu File e um dilogo permitir que voc escolha o arquivo que deseja abrir
novamente ( semelhante ao processo do Save as...).
Compilando a classe
Acabamos de definir a nossa classe, precisamos agora compilar para que possamos us-la. No menu Tools,
temos duas opes para fazer isso, Compile All Documents e Compile Current Document. Como s temos
um documento aberto (Conversor.java), qualquer uma das opes serve. Escolha ento Compile Current
Document.
Com isso compilaremos a nossa classe. Note que, no painel inferior da janela, a guia Compiler Output se
abre mostrando algumas mensagens. Se tudo der certo, a nossa janela se parecer com a seguinte.
Usando a classe
Podemos finalmente usar a guia Interactions, que chamaremos de janela do interpretador, para criar e usar
objetos da classe Conversor. Essa janela recebe comandos num prompt e a sintaxe desses comandos muito
parecida com a da linguagem Java.
Clique ento em Interactions e digite o seguinte.
C o n v e r s o r conv = new C o n v e r s o r ( ) ;
conv . c e l s i u s P a r a F a h r e n h e i t ( )
152 APNDICE A. UTILIZANDO O DR. JAVA
A ausncia de ; no final da linha do comando faz com que o interpretador imprima o valor devolvido pelo
comando.
A janela do interpretador dever se parecer com a figura abaixo.
Erros no cdigo
Feche o arquivo Conversor.java usando a opo Close do menu File e crie um novo arquivo (na verdade,
como havia apenas um arquivo aberto, um novo criado automaticamente).
Digite nesse arquivo o cdigo abaixo (h erros intencionais nele). Voc pode tambm usar o recurso de
copiar e colar (copy and paste).
A.2. TRATANDO ERROS 153
c l a s s Conversor4
{
double c e l s i u s P a r a F a h r e n h e i t ( double c )
{
double f = 9 . 0 c / 5 . 0 + 32.0
return f ;
}
double f a h r e n h e i t P a r a C e l s i u s ( double f )
{
double c = 9 . 0 ( f 3 2 . 0 ) / 9 , 0 ;
return c ;
}
}
Grave o arquivo e compile. Como o cdigo contm erros, o compilador no ter sucesso e imprimir
algumas mensagens. Algo como mostra a figura abaixo.
O primeiro erro pode ser eliminado acrescentando-se um ; no final da linha 5. Veja que o prprio compila-
dor sugere isso.
J a descrio do segundo erro pode ser um pouco confusa. importante saber que o compilador capaz
de encontrar erros no cdigo, mas nem sempre pode determinar a causa exata. Nesses casos, as mensagens de
erro apenas do pistas para descobrirmos o que est errado (algumas vezes pistas falsas). O segundo erro uma
vrgula no lugar de um ponto, no final da linha 10.
H outros tipos de erro os quais o compilador no tem condies de detectar. Um exemplo o erro na
frmula de converso da linha 10. H um 9.0 onde deveria estar um 5.0. No Captulo 4 apresentamos uma
maneira de detectarmos tais erros atravs de testes. Mas depois de detectarmos, precisamos descobrir a causa
deles. Veremos a seguir uma ferramenta til para essa tarefa. Mas antes corrija os erros e compile.
154 APNDICE A. UTILIZANDO O DR. JAVA
Depurador
Depurador (debugger) uma ferramenta que nos ajuda a corrigir erros (bugs) de programas. O depurador
do DrJava oferece apenas recursos bsicos: pontos de parada (breakpoints), execuo passo a passo (step)
e inspeo simples de variveis (watch). Mesmo assim, a classe Conversor4 no complexa o suficiente
para justificar a aplicao do depurador, vamos utiliz-la apenas para demonstrar rapidamente cada um desses
recursos.
Para ativar o depurador, escolha a opo Debug Mode do menu Debugger. Ao fazer isso, o painel de
depurao exibido na janela principal.
A execuo do mtodo ser interrompida antes da linha 10 ser executada. O destaque azul da linha indica
isso. Para continuar a execuo passo a passo (linha a linha), execute o comando step over algumas vezes
(pressionando a tecla <F11>). Dessa forma, possvel constatar quais trechos de cdigo so usados numa
execuo em particular.
A.2. TRATANDO ERROS 155
Um outro recurso bastante til, que deve ser usado em conjunto com esses que acabamos ver, a inspeo
de valores de variveis (watch). Esse recurso nos informa o valor de certas variveis durante a execuo passo a
passo. Para isso, necessrio preencher a coluna Name da tabela da guia Watches com os nomes das variveis
que se deseja inspecionar (uma varivel em cada linha da tabela). Basta clicar numa clula da coluna Name,
digitar o nome da varivel e pressionar <Enter>.
Faa este procedimento para as variveis c e f. Teremos algo como a prxima figura.
Repita a execuo passo a passo descrita anteriormente e observe o que ocorre com a tabela.
Dica: o interpretador armazena os ltimos comandos digitados na janela. Para acess-los, pressione as
setas para cima e para baixo do teclado. Esse recurso se chama History e possui algumas opes teis no menu
Tools.
156 APNDICE A. UTILIZANDO O DR. JAVA
Apndice B
Neste apndice, veremos um exemplo de como podemos desenvolver um programa ao mesmo tempo em
que desenvolvemos seus testes. Ou melhor, a idia at um pouco mais radical, criar os testes e ir adaptando o
programa at que o mesmo satisfaa a todos os testes criados. Esta abordagem chamada de Desenvolvimento
Dirigido por Testes (Test-Driven Development) e a prtica de escrever os testes antes do cdigo a ser testado
chamada de Programao com Testes a Priori (Test-First Programming). Para isto, devemos nos guiar pelo
seguinte ciclo, de forma incremental:
1. Escreva teste(s);
B.1 O Exemplo
Vamos comear do bsico. Inicialmente, queremos criar um teste que, nada mais natural, para o nmero 0
tenhamos como resultado um String vazio. Para isto usaremos uma palavra chave que existe a partir de Java
1.4: assert. Em linhas gerais, assert recebe um nico parmetro booleano e, se ele for verdadeiro, nada acon-
tece; no entanto, se ele for falso, o assert gera uma mensagem de erro e interrompe a execuo do programa.
interessante notar que necessrio ativar as verificaes do assert usando o parmetro -ea da mquina vir-
tual Java, ou seja o seguinte programa deve ser executado com: java -ea TesteConversorNmerosRomanos.
Usando o assert, o teste fica:
c l a s s TesteConversorNmerosRomanos
{
1 Na verdade existe toda uma teoria para isto, que se chama refatorao.
2A idia original para este exemplo foi encontrada em http://www.differentpla.net/node/58, mas o exemplo a seguir foi
criado de forma totalmente independente.
157
158 APNDICE B. DESENVOLVIMENTO DIRIGIDO POR TESTES
public void t e s t e s ( )
{
C o n v e r s o r c = new C o n v e r s o r ( ) ;
Como seria de se esperar, o trecho isolado acima nem mesmo compila, pois a classe Conversor ainda no
existe. Mas, podemos resolver isto criando a seguinte classe:
c l a s s Conversor
{
public String converte ( int x )
{
return " " ;
}
}
Agora, no s o programa compila, como executado sem erros. Logo, podemos aprimorar o nosso teste
com a verificao da converso do inteiro 1.
c l a s s TesteConversorNmerosRomanos
{
public void t e s t e s ( )
{
C o n v e r s o r c = new C o n v e r s o r ( ) ;
a t j a v a . l a n g . r e f l e c t . Method . i n v o k e ( Method . j a v a : 5 8 5 )
Esta mensagem indica que a segunda verificao falhou. O nosso prximo passo generalizar o programa
para que ele funcione para o teste atual:
c l a s s Conversor
{
public String converte ( int x )
{
i f ( x == 0 )
return " " ;
return " I " ;
}
}
Desta forma, o Conversor voltou a funcionar. Est na hora de aumentarmos a nossa classe de testes com
mais uma verificao:
a s s e r t ( c . c o n v e r t e ( 2 ) . compareTo ( " I I " ) = = 0 ) ;
Mas, quando acrescentarmos o teste para o nmero 3, o nosso conversor vai falhar novamente. Continuando
o desenvolvimento teremos:
c l a s s Conversor
{
public String converte ( int x )
{
i f ( x == 0 )
return " " ;
i f ( x == 1 )
return " I " ;
i f ( x == 2 )
return " I I " ;
return " I I I " ;
}
}
Olhando o cdigo acima, vemos um padro de repetio no uso de ifs e sempre que aparecem estas
repeties interessante encontrar formas de reduz-las. Podemos simplificar o exemplo acima usando um lao
simples:
160 APNDICE B. DESENVOLVIMENTO DIRIGIDO POR TESTES
c l a s s Conversor
{
public String converte ( int x )
{
String s = "" ;
while ( x > 0)
{
x;
s = s + "I";
}
return s ;
}
}
O novo cdigo continua passando pelo teste, mas ainda temos que ver o funcionamento para mais nmeros,
no caso o 4 e o 5.
c l a s s TesteConversorNmerosRomanos
{
public void t e s t e s ( )
{
C o n v e r s o r c = new C o n v e r s o r ( ) ;
c l a s s Conversor
{
public String converte ( int x )
{
String s = "" ;
i f ( x == 4 )
r e t u r n " IV " ;
i f ( x == 5 )
r e t u r n "V" ;
while ( x > 0)
{
x;
s = s + "I";
B.1. O EXEMPLO 161
}
return s ;
}
}
O nosso conversor j funciona para os inteiros de 0 a 5. Pensando um pouco, podemos ver que os nmeros
6, 7 e 8 tem construo anloga ao 1, 2 e 3, e o while no final pode nos ajudar. Logo, para a seguinte srie de
asserts:
assert (c. converte ( 0 ) . compareTo ( " " ) = = 0 ) ;
assert (c. converte ( 1 ) . compareTo ( " I " ) = = 0 ) ;
assert (c. converte ( 2 ) . compareTo ( " I I " ) = = 0 ) ;
assert (c. converte ( 3 ) . compareTo ( " I I I " ) = = 0 ) ;
assert (c. converte ( 4 ) . compareTo ( " IV " ) = = 0 ) ;
assert (c. converte ( 5 ) . compareTo ( "V" ) = = 0 ) ;
assert (c. converte ( 6 ) . compareTo ( " VI " ) = = 0 ) ;
assert (c. converte ( 7 ) . compareTo ( " V I I " ) = = 0 ) ;
assert (c. converte ( 8 ) . compareTo ( " V I I I " ) = = 0 ) ;
i f ( x == 4 )
r e t u r n " IV " ;
i f ( x >= 5 )
{
s = s + "V" ;
x = x 5;
}
while ( x > 0)
{
x;
s = s + "I";
}
return s ;
}
}
J que o programa funciona vamos aumentar os testes para os nmeros 9 e 10. Para sanar a nova falha,
vamos adicionar dois novos ifs:
c l a s s Conversor
{
public String converte ( int x )
{
String s = "" ;
i f ( x == 4 )
r e t u r n " IV " ;
162 APNDICE B. DESENVOLVIMENTO DIRIGIDO POR TESTES
i f ( x == 9 )
r e t u r n " IX " ;
i f ( x == 1 0 )
r e t u r n "X" ;
i f ( x >= 5 )
{
s = s + "V" ;
x = x 5;
}
while ( x > 0)
{
x;
s = s + "I";
}
return s ;
}
}
Novamente, aparece uma padro de repetio, ou duplicao, para simplificar o cdigo, apenas observando
o padro IV e IX:
c l a s s Conversor
{
public String converte ( int x )
{
String s = "" ;
i f ( ( x == 4 ) | | ( x == 9 ) )
{
s = s + "I";
x ++;
}
i f ( x == 1 0 )
r e t u r n s + "X" ;
i f ( x >= 5 )
{
s = s + "V" ;
x = x 5;
}
while ( x > 0)
{
x;
s = s + "I";
}
return s ;
}
}
Alm do que bem fcil corrigir o cdigo para que o mesmo funcione para os nmeros 11, 12 e 13, basta
trocar o if (x == 10) por:
i f ( x >= 1 0 )
{
s = s + "X" ;
B.1. O EXEMPLO 163
x = x 10;
}
Vamos agora, eliminar o cdigo duplicado criando um novo mtodo aux. Como este mtodo modifica tanto a
String como o valor de x, foi necessrio usar um objeto do tipo StringBuffer
c l a s s Conversor
{
p r i v a t e i n t aux ( i n t x , i n t v a l , S t r i n g B u f f e r s , char ch )
{
i f ( x >= v a l )
{
s . a p p e n d ( ch ) ;
x = x val ;
}
return x ;
}
i f ( ( x == 4 ) | | ( x == 9 ) )
{
s . append ( " I " ) ;
x ++;
}
x = aux ( x , 1 0 , s , X ) ;
x = aux ( x , 5 , s , V ) ;
while ( x > 0)
{
x;
s . append ( " I " ) ;
}
return s . t o S t r i n g ( ) ;
}
}
Continuando com os testes, para os nmeros 14 e 15, podemos verificar que basta repetir um trecho de
cdigo para que o programa funcione, logo vamos criar mais um mtodo:
c l a s s Conversor
{
p r i v a t e i n t aux ( i n t x , i n t v a l , S t r i n g B u f f e r s , char ch )
{
i f ( x >= v a l )
{
s . a p p e n d ( ch ) ;
x = x val ;
}
return x ;
}
p r i v a t e i n t aux2 ( i n t x , S t r i n g B u f f e r s )
164 APNDICE B. DESENVOLVIMENTO DIRIGIDO POR TESTES
{
s . append ( " I " ) ;
return x + 1;
}
i f ( ( x == 4 ) | | ( x == 9 ) )
{
x = aux2 ( x , s ) ;
}
x = aux ( x , 1 0 , s , X ) ;
i f ( ( x == 4 ) | | ( x == 9 ) )
{
x = aux2 ( x , s ) ;
}
x = aux ( x , 5 , s , V ) ;
while ( x > 0)
{
x;
s . append ( " I " ) ;
}
return s . t o S t r i n g ( ) ;
}
}
interessante notar que agora podemos adicionar os nmeros at 18 que o teste funciona. Mas, para o 19
o teste falha novamente. Com um pouco de observao podemos ver que com pequenas alteraes tudo volta a
funcionar, basta colocar uma chamada adicional ao mtodo aux. Mas, lembrando que teremos nmeros como
o 30, o melhor seria adicionar um outro lao ao programa:
c l a s s Conversor
{
p r i v a t e i n t aux ( i n t x , i n t v a l , S t r i n g B u f f e r s , char ch )
{
i f ( x >= v a l )
{
s . a p p e n d ( ch ) ;
x = x val ;
}
return x ;
}
p r i v a t e i n t aux2 ( i n t x , S t r i n g B u f f e r s )
{
s . append ( " I " ) ;
return x + 1;
}
w h i l e ( x >= 9 )
{
i f ( x == 9 )
{
x = aux2 ( x , s ) ;
}
x = aux ( x , 1 0 , s , X ) ;
}
i f ( x == 4 )
{
x = aux2 ( x , s ) ;
}
x = aux ( x , 5 , s , V ) ;
while ( x > 0)
{
x;
s . append ( " I " ) ;
}
return s . t o S t r i n g ( ) ;
}
}
Este novo conversor funciona at o nmero 39. Para que ele funcione para o nmero 40 temos que entrar
com uma nova letra, o L que corresponde ao 50. Agora que j conhecemos melhor o mecanismo de converso
de nmeros, podemos escolher alguns testes para adicionar, ao invs de colocar testes para todos os nmeros.
Para a nova srie de testes:
...
assert (c. converte ( 1 7 ) . compareTo ( " XVII " ) = = 0 ) ;
assert (c. converte ( 1 8 ) . compareTo ( " XVIII " ) = = 0 ) ;
assert (c. converte ( 1 9 ) . compareTo ( " XIX " ) = = 0 ) ;
assert (c. converte ( 2 0 ) . compareTo ( "XX" ) = = 0 ) ;
assert (c. converte ( 2 3 ) . compareTo ( " XXIII " ) = = 0 ) ;
assert (c. converte ( 3 4 ) . compareTo ( "XXXIV" ) = = 0 ) ;
assert (c. converte ( 3 9 ) . compareTo ( "XXXIX" ) = = 0 ) ;
assert (c. converte ( 4 6 ) . compareTo ( "XLVI" ) = = 0 ) ;
assert (c. converte ( 5 9 ) . compareTo ( " LIX " ) = = 0 ) ;
assert (c. converte ( 6 3 ) . compareTo ( " L X I I I " ) = = 0 ) ;
p r i v a t e i n t aux2 ( i n t x , S t r i n g B u f f e r s )
{
s . append ( " I " ) ;
return x + 1;
}
i f ( x >= 4 0 )
{
i f ( x < 50)
{
s . a p p e n d ( "X" ) ;
x = x + 10;
}
s . a p p e n d ( "L" ) ;
x = x 50;
}
w h i l e ( x >= 9 )
{
i f ( x == 9 )
{
x = aux2 ( x , s ) ;
}
x = aux ( x , 1 0 , s , X ) ;
}
i f ( x == 4 )
{
x = aux2 ( x , s ) ;
}
x = aux ( x , 5 , s , V ) ;
while ( x > 0)
{
x;
s . append ( " I " ) ;
}
return s . t o S t r i n g ( ) ;
}
}
Observe que colocar o X antes do L similar a colocar o I antes do X, ou do V, logo podemos mudar o nome
do mtodo aux2 para precede e us-lo tambm neste caso. Assim como o mtodo aux pode ser chamado de
colocaLetra e usado em outras partes:
c l a s s Conversor
{
p r i v a t e i n t c o l o c a L e t r a ( i n t x , i n t v a l , S t r i n g B u f f e r s , char ch )
{
i f ( x >= v a l )
{
s . a p p e n d ( ch ) ;
B.1. O EXEMPLO 167
x = x val ;
}
return x ;
}
p r i v a t e i n t p r e c e d e ( i n t x , i n t v a l , S t r i n g B u f f e r s , char ch )
{
s . a p p e n d ( ch ) ;
return x + val ;
}
public String converte ( int x )
{
S t r i n g B u f f e r s = new S t r i n g B u f f e r ( " " ) ;
i f ( x >= 4 0 )
{
i f ( x < 50)
{
x = p r e c e d e ( x , 1 0 , s , X ) ;
}
x = c o l o c a L e t r a ( x , 5 0 , s , L ) ;
}
w h i l e ( x >= 9 )
{
i f ( x == 9 )
{
x = precede (x , 1 , s , I ) ;
}
x = c o l o c a L e t r a ( x , 1 0 , s , X ) ;
}
i f ( x == 4 )
{
x = precede (x , 1 , s , I ) ;
}
x = c o l o c a L e t r a ( x , 5 , s , V ) ;
while ( x > 0)
{
x = colocaLetra (x , 1 , s , I );
}
return s . t o S t r i n g ( ) ;
}
}
Observando o cdigo acima vemos que existe uma correspondncia entre os valores e os nmeros romanos
I, V, X e L nas chamadas dos mtodos, logo, podemos criar um mtodo adicional que faz esta correspondncia,
simplificando as chamadas.
c l a s s Conversor
{
p r i v a t e char c o r r e s p o n d e ( i n t i )
{
i f ( i == 1 )
return I ;
168 APNDICE B. DESENVOLVIMENTO DIRIGIDO POR TESTES
e l s e i f ( i == 5 )
r e t u r n V ;
e l s e i f ( i == 1 0 )
r e t u r n X ;
else
r e t u r n L ;
}
private i n t c o l o c a L e t r a ( i n t x , i n t val , S t r i n g B u f f e r s )
{
i f ( x >= v a l )
{
s . append ( c o r r e s p o n d e ( v a l ) ) ;
x = x val ;
}
return x ;
}
i f ( x >= 4 0 )
{
i f ( x < 50)
{
x = precede ( x , 10 , s ) ;
}
x = c o l o c a L e t r a ( x , 50 , s ) ;
}
w h i l e ( x >= 9 )
{
i f ( x == 9 )
{
x = precede (x , 1 , s ) ;
}
x = c o l o c a L e t r a ( x , 10 , s ) ;
}
i f ( x == 4 )
{
x = precede (x , 1 , s ) ;
}
x = colocaLetra (x , 5 , s );
while ( x > 0)
{
x = colocaLetra (x , 1 , s );
}
return s . t o S t r i n g ( ) ;
}
B.1. O EXEMPLO 169
Olhando o cdigo acima parece existir um padro entre as chamadas aos mtodos precede e colocaLetra,
mas como ainda no est claro o que pode ser feito, vamos criar mais testes para que o conversor funcione com
nmeros maiores do que 89.
...
assert (c. converte ( 9 0 ) . compareTo ( "XC" ) = = 0 ) ;
assert (c. converte ( 9 4 ) . compareTo ( "XCIV" ) = = 0 ) ;
assert (c. converte ( 9 9 ) . compareTo ( "XCIX" ) = = 0 ) ;
assert (c. converte ( 1 0 3 ) . compareTo ( " C I I I " ) = = 0 ) ;
assert (c. converte ( 1 4 9 ) . compareTo ( "CXLIX" ) = = 0 ) ;
assert (c. converte ( 3 4 9 ) . compareTo ( "CCCXLIX" ) = = 0 ) ;
Para isto temos que alterar os mtodos corresponde, adicionando a nova letra (C), e o mtodo converte,
transcrito abaixo:
public String converte ( int x )
{
S t r i n g B u f f e r s = new S t r i n g B u f f e r ( " " ) ;
w h i l e ( x >= 9 0 )
{
i f ( x < 100)
{
x = precede ( x , 10 , s ) ;
}
x = c o l o c a L e t r a ( x , 100 , s ) ;
}
i f ( x >= 4 0 )
{
i f ( x < 50)
{
x = precede ( x , 10 , s ) ;
}
x = c o l o c a L e t r a ( x , 50 , s ) ;
}
w h i l e ( x >= 9 )
{
i f ( x == 9 )
{
x = precede (x , 1 , s ) ;
}
x = c o l o c a L e t r a ( x , 10 , s ) ;
}
i f ( x == 4 )
{
x = precede (x , 1 , s ) ;
}
x = colocaLetra (x , 5 , s );
while ( x > 0)
{
x = colocaLetra (x , 1 , s );
}
170 APNDICE B. DESENVOLVIMENTO DIRIGIDO POR TESTES
return s . t o S t r i n g ( ) ;
}
}
Neste momento, o padro de duplicao do cdigo fica mais visvel, e podemos buscar uma forma de
eliminar as repeties. Logo, foram feitas diversas modificaes no cdigo at chegarmos a verso seguinte
(como tnhamos os testes, a cada modificao, o correto funcionamento da nova verso pode ser verificado).
c l a s s Conversor
{
p r i v a t e char c o r r e s p o n d e ( i n t i )
{
i f ( i == 1 )
return I ;
e l s e i f ( i == 5 )
r e t u r n V ;
e l s e i f ( i == 1 0 )
r e t u r n X ;
e l s e i f ( i == 5 0 )
r e t u r n L ;
else
r e t u r n C ;
}
private i n t c o l o c a L e t r a ( i n t x , i n t val , S t r i n g B u f f e r s )
{
s . append ( c o r r e s p o n d e ( v a l ) ) ;
x = x val ;
return x ;
}
w h i l e ( x >= 9 0 )
{
i f ( x < 100)
{
x = precede ( x , 10 , s ) ;
}
x = c o l o c a L e t r a ( x , 100 , s ) ;
}
w h i l e ( x >= 4 0 )
{
i f ( x < 50)
{
x = precede ( x , 10 , s ) ;
}
B.1. O EXEMPLO 171
x = c o l o c a L e t r a ( x , 50 , s ) ;
}
w h i l e ( x >= 9 )
{
i f ( x < 10)
{
x = precede (x , 1 , s ) ;
}
x = c o l o c a L e t r a ( x , 10 , s ) ;
}
w h i l e ( x >= 4 )
{
i f ( x < 5)
{
x = precede (x , 1 , s ) ;
}
x = colocaLetra (x , 5 , s );
}
while ( x > 0)
{
x = colocaLetra (x , 1 , s );
}
return s . t o S t r i n g ( ) ;
}
}
Neste ponto, o padro ficou bem claro ( interessante notar que mesmo que alguns ifs tenham sido trocados
por whiles devido as caractersticas do programa o lao s executado no mximo uma vez). Vale ressaltar
mais uma vez que a garantia que o programa acima est correto vem da nossa classe de testes.
Com um pouco de pacincia, d para trocar os whiles acima por apenas 3, temos abaixo o programa mais
limpo:
c l a s s Conversor
{
p r i v a t e i n t v [ ] = {100 , 50 , 10 , 5 , 1};
p r i v a t e char c o r r e s p [ ] = { C , L , X , V , I } ;
while ( i < v . l e n g t h 1)
{
w h i l e ( x >= v [ i ] v [ i + 2 ] )
{
if (x < v[ i ])
{
x = p r e c e d e ( x , i +2 , s ) ;
}
x = colocaLetra (x , i , s );
}
w h i l e ( x >= v [ i + 1 ] v [ i + 2 ] )
{
i f ( x < v [ i +1])
{
x = p r e c e d e ( x , i +2 , s ) ;
}
x = c o l o c a L e t r a ( x , i +1 , s ) ;
}
i = i + 2;
}
while ( x > 0)
{
x = colocaLetra (x , v . length 1 , s );
}
return s . t o S t r i n g ( ) ;
}
}
interessante notar que o programa acima ainda pode ser simplificado, mas j chegamos a um conversor
que funciona at o nmero 399.
Os passos apresentados, foram na medida do possvel, muito prximos a um desenvolvimento real.
claro que durante o desenvolvimento do conversor ocorreram diversos erros, inclusive de compilao, mas os
mesmos foram omitidos pois no apresentam interesse didtico.
Exerccios
1. Verifique, atravs da metodologia testes primeiro, que o programa acima flexvel, adicionando os n-
meros romanos D e M.
2. Usando a mesma metodologia de testes primeiro, crie um programa que converte nmeros romanos em
nmeros decimais.
Bibliografia
Walter Savitch, Java, An Introduction to Computer Science & Programming, second edition, Prentice
Hall, 2001
Um bom livro de introduo computao escrito pelo prolfico Prof. Savitch da Universidade da Cali-
fornia em San Diego. Daqui foi tirada a classe para entrada de dados sugerida neste livro para verses de
Java anteriores 1.5.
Harvey Deitel e Paul Deitel, Java: Como Programar, sexta edio, Prentice Hall, 2005.
Livro em portugus para aqueles que desejam obter mais detalhes sobre como programar em Java. Possui
uma abordagem bastante acessvel e baseada em exemplos, alm de cobrir uma grande quantidade de
tpicos.
Jaime Nio e Frederick A. Hosch A Introduction to Programming and Object Oriented Design
Um bom livro de introduo Cincia da Computao. Possui algumas semelhanas com nosso livro
como o enfoque em orientao a objetos e nfase em testes e mesmo o uso do DrJava e seu painel
interativo. O livro possui vrios exemplos interessantes e bastante completo, usando suas 900 pginas
173
174 BIBLIOGRAFIA
para cobrir com profundidade vrios tpicos que apenas arranhamos ou nem citamos, como por exemplo
herana e polimorfismo, excees, interfaces grficas e iteradores.