Escolar Documentos
Profissional Documentos
Cultura Documentos
"Kathy Sierra 6 uma das poucas pessoas no mundo que consegue fazer coisas complicadas parecerem murto simple;. E
como se isso nio fosse suficiente, ela consegue fazer com que assuntos mon6tonos paregam interessantes. Sempre fico
ansioso para ler o que Kathy escreve - ela 6 uma de minhas autoras favoritas".
- Paul IYheaton, Chefe de Aconpanbamento da JauaRanch.com
"Quem melhor para escrever um guia de estudos sobre Java do que Kathy Si_err.a, que reina soberana quando se trata de
treLamento emlava? Kathy Sierr-a conseguiu novamente - aqui est6 um guia de estudos que j6 poder6 lhe garantir a
cenifica$o!"
- Jamu Cabeta, Engenheiro de Sistenaq SCI
"O que mais aprecio em Kathy 6 seu esforEo p arafaznr comque todosnos lembremos de que estamos ensinando pessoas
. nio aoenas fa"endo uma palestra sobre Tava. Seu entusiasmo e vontade em oferecer um treinamento da mais alta
ffi;#i. frffi;; #.##T; ;;;, ;;;
i; -
.. rreza nio encontra paralelo na sunEd. s.* a""iar, h6 centenas de I
q
- Victor Peters, fandador da Next Snp Education e Inslrutor Certifcado Jaua pela Sun
"Quero agradecer Kathy pelo EXCELENTE guia de esudos. O livro 6 bem.escrito,.informa especificamente o que voc6
a
aJq. ri'U.r.ro.*"-..."d,conceito 6 explicaio de maneiraclaracom autilizagio deum exemplo davidareal' Da
**Jira sentir6 em uma sala de aula como se algu6m estivesse realmente lhe ensinando os conceitos
orr. foi escrito, voc6 se
diiil;;; e fria. As perguntas no final dos capftulos tamb€m slo MUTIo boas e estou certo de
maneiraformal
"ilde
que aju&rio os candidatos a passarem no tesi. Fique alerta para esse livro incrivelmente astuto".
- Atfred RaouJ Desenuoluedor de Solugdu na IYeb
i
O exame de certificagio da Sun cerramente nio foi como um passeio no parque' mas o material de Kathy permitiu nio s6
que eu Passasse no exame, mas que passasse bem!"
- Mary lqhetsel, Etpecial^ta S1nior em Tecnologla, Integragdo e Estrategla de Aplicagdes, Tbc St. Paal Corapaniet
"Ben demonstra uma aptidio comprovada e fantistica de transformar com-plexidade em simplicidade ao oferecer um
percurso dirigido no aprendizado do que 6 necessirio para o exame da certificaqXo".
"Achei este livro exrremamente 6til para ajudar o candidato a passar no exame. Ele foi muito bem escrito, com a qtrantidade
ideal de come"."ri"r b.*-ftJ-oi p"At*r. .or' qrr. .'oo.? se esquega de que est6 estudando Para um teste tio dificil'
^Cit
ALTAMENTE RECOMENDADO!"
-Nico/e Y. McCallough
*Nunca me diveni tanto lendo um livro r6cnico quanto no caso deste aqui... Hoje de manhi, fiz o exame SCJP e consegu,i
ecertar 980/o(60 de 61). Esse sucesso nio teria sido possivel sem este livro!"
-Yaie Nagornl
,,EvfizoSCJp emJulho de 2004 e consegui 957o (58/.6l).Kathy e Ben t6m um estilo incrivel de escrever'
1.4
e
(
"Eu fiz meu teste de certificagio semana passada e fui aprovado com 95o/o de acertos. Se nio tivesse estudado por este livro,
teria poucas chances de obter um resultado tio bom. Obrigado, Kathy e Bert, pelo maravilhoso livro!"
"Nio hesite em fazer deste livro o seu principal guia para preparar-se para o SCJP 1.4. Os autores fizeram um trabalho
magnifico ao apresentar os fatos imponantei qe pricisar6 sabei para o exame, ao mesmo rempo deixaram de lado
"oc6
toneladas de outras informag6es que,em outro contextb, seriam importantes, mas que vlo al6m do escopo deste livro.
Ambos os autores participaram da criagio das quest6es reais do exame, fornecendo iessa forma um valiosissimo insight
sobre a verdadeira natureza do que vocA.encontrari no exame. Ao contririo de muitos outros guias de cenificagio. Esti aqui
6 uma leitura p razerosa. Neste livro, at6 os mais enfadonhos objetivos da Sun sio combinadoi com um revigo.*t. bo.ri-
humor."
lGthy Sierra
Bert Bates
tv
Certilicagiio Sun@ para Programador Java 5- Guia de Estudo @xame 310-055)
Do original Sun@ Certified Programmer for JavarM 5 Study Guide (Exam 3 I 0-05 5) - Copyright @ 2006 da Editora Alta Books Ltda.
Authorized translation from the English language edition, entitled Sun@ Certified Programmer for JavarM 5 Srudy Guide (Exam
310-055), by Sierra & Bates, published by Osborne/MacGraw-Hill, publishing as The MacGraw-Hill Companies, Copyright @
2006 by Osborne/MacGra,v-Hill.
PORTUGUESE language edition published by Editora Alta Bool<s, Copyright @ 2006 by Editora Alta Bool{s.
Todos os direitos reservados e protegidos pela Lei 5988 de I4ll2l73. Nenhuma parte deste livro, sem autorizagdo pr6via por escrito
da editora, poderS ser reproduzida ou transmitida sejam quais forem os meios empregados: eletr6nico, mecanico, fotogr6fico, gravag5o
ou quaisquer outros.
Todo o esforgo foi feito para fornecer a mais completa e adequada informagdo, contudo a(s) editora(s) e o(s) autor(es) nAo assumem
responsabilidade pelos resultados e usos da informagdo fornecida. Recomendamos aos leitores testar a informagdo bem como tomar
todos os cuidados necess6rios (como o backup), antes da efetiva fiilizagdo. Este livro n6o contdm CD-ROM, disquete ou qualquer
outramidia.
Produgiio Editorial: Editora Alta Books
Coordenagflo Editorial: Fernanda Silveira
Thadugiio: Marcelo Soares
Revis6o: Fernanda Silveira
RevisEo T6cnica: Leonardo Rota-Rossi
Colaboragflo T6cnica: Gabriel Fairbanks, Leonardo Gangemi eAnderson Xavier
Diagramagiio : Aldenir Gil
Erratas e atualizag6es: Sempre nos esforgamos para entregar a voc6 leitor um livro livre de erros t6cnicos ou de conteido, por6m nem
sempre isto 6 conseguido, seja por motivo de alteragilo de software, interpretagdo ou mesmo quando alguns deslizes constam na
versdo original de alguns livros que traduzimos. Sendo assim, criamos em nosso site www.altabooks.com.br a seg6o Erratas, onde
relataremos, com a devida corregSo, qualquer erro encontrado em nossos livros.
Aviso e Renfncia: Este livro 6 vendido como est6, sem garantia de qualquer tipo, seja expressa ou implicita.
Marcas Registradas: Todos os termos mencionados e reconhecidos como Marca Registrada e/ou comercial sdo de responsabilidade
de seus proprietiirios. A Editora informa n6o esfar associada a nenhum produto e/ou fomecedor apresentado no livro. No decorrer
da obra, imagens, nomes de produtos e fabricantes podem ter sido utilizados e desde j5 a Editora informa que o uso 6 apenas
ilustrativo e/ou educativo, ndo visando lucro, favorecimento ou desmerecimento do produto/fabricante.
O c6digo de propriedade intelectual de l'de Julho de 1992 proibe expressamente o uso coletivo sem autorizagdo dos detentores
do direito autoral da obra, bem como a c6pia ilegal do original. Esta pratica generalizada nos estabelecimentos de ensino
provocam uma brutal bqixa nqs vendas dos livros ao ponto de impossibilitar os autores de criarem novas obras.
A McGraw-Hill/Osborne d uma entidade sem ligaEdes com a Sun Microsystems e ndo tem nenhum vinculo de afiliaqdo com a
illtima. Essa publicaqdo pode ser usada como auxllio na prepqraqdo dos alunos para o exame de certificagdo da Sun em
Java 2. Nem a Sun Microsystems ou a McGraw-Hill/Osborne garqntem que o uso dessa publicagdo assegurard sucesso no
exame em questdo. Sun, Sun Microsystems e o logotipo da Sun sdo marcas registradas da Sun Microsystems.Inc. nos Estados
Unidos e em outros paises. Java e todas as marcas relacionadas sdo marcas registradas da Sun Microsystems Inc. nos
Estados Unidos e em outros paises. A McGraw-Hill/Osborne ndo tem ligaqdo com a Sun Microsystems, Inc.
ParaaComtrnida&Java
Sum6rio
capirulo | - DEclAnag6es E coNTRoLE DE AcEsSo.................................... I
a
Outros Modificodores de Closses (N6o-re{erentes o Acesso)
Exercicio l- | Criando uma Superclasse Abstrata e uma Subclasse Concreta .....' | 0
Literois
Volores literois poro strings......... ................ 05
Osconstrutoreswrqpper .........133
Os m6todos volueOf0 ... ... ............. ]34
Usando os utilitidos de conversio das classes wrapper .............. | 34
.l35
porseXrx$ e volueOffl . .... .. ............
Breokeopossogemcompletoemblocosswitch......... .....190
defoult
A instruE6o cose .........192
Exercicio 5- | Criando
O LoopforBdsico .................,l95
LoopforBdsico: Declorog6oeiniciolizoE6o................ .....|95
.|95
Loop for Bdsico: Express6o condicionol (booleono) .........
LoopforBdsico: Express6ode iterog6o.. ......196
LoooforB6sico:Corocleristicosdolooofor.............. ......196
O Loop forAprimorodo (poro Arroys) .........197
cApiTuLo7-GENfRlcosEcoNfuNToso.........o...o.ooo......o.o...................oo........zgs
Objetivo para a certificagio ............. .......296
Subscrevendo hashCode( ) e equals( ) (objetivo 6.2 do exame) ...296
hoshing
Entendendo os c6digos de ............300
................
lmplementondo hoshCodefl ......30'l
O conlroto de hoshCodefl ... ........302
Objetivo para a certificag6o ............. .......304
Conjuntos (Objetivo 6. I do exame) .......... 304
...................
Usondo o Cfosse PriorityQueue ..................322
Vis6o Gerql dos M6iodos poro Arroys e Coniuntos. .....32g
VisSo Gerql dos M6todos poro Lisl, Set, Mop e Queue...... ..............324
Objetivo para a Certificagio ..........32s
Tipos Gen6ricos (Objetivos 6.3 e 6.4 do Exame) .........325
Gen6rico
Criondo o suo Pr6prio Closse ......342
Criondo M6todos Gen6ricos ......................345
Criando
Closspoths
Declorondo e Usondo """""""' 436
Pocoleseo Procuro """""""'436
JAVA 5 )ry
Cominhos Relotivos e Absolutos ...... ....438
Objetivo para a Certifi cagio .............. 439
Arquivos JAR (Objetivo 7.5) .....439
APENDICE A..o..o.......o............................................................................................... 45 |
Requisitos do sistema ...............452
lnstalando e executando o MasterExam ....452
Sobre o LearnKey
O karnKey fornece conrerido de aprendizado que respeita o ritmo do aluno, e apresenta solug6es de distribuigio de
muldmidia para aprimorar habilidades pessoais e produiirridade empresarial. O_ LearnKey apresenta a maior biblioteca de
conterido di treinamento multimidia existent., fottt.." rlm dinAmico aprendizado, rico em diversas
"'q.r"l "o, "irrrro, animadas. O site do LearnKey na web 6
ilustrag6es
midias, como videoclips, 6udio, grificos totalmenfe animados e
www.kamKey.aorrl
Em primeiro lugar, ashonras vio para Kristin Stromberg - toda vez que voc6 vir um pon193-vilgula sendo usado
.orrit"-.rrt., alradega a Kristin. Em seguida vem Burk Hufnagel, que_ consertou mais c6digos d9 que estamos.dispostos a
admitir. Bill MiJtekkie Gian Franco Caiula corrigiram todos oJtipos dc erros que jogamos para eles - 6timo trabalho,
pessoal! Devender Thareja certificou-se de que nidest6vamos usando giria demais, e Mgk Sgrlzler manteve o bom humor.
ivfiU{ Z"it i" e Seema Manivannan fizerani impoftantes correg6es no livro todo, e Marilyn de Queiroz e Valentin Crettaz
novamente fizeram um trabalho espetacular (novamente salvando os nossos pescogos).
Marcelo Onega, Jef Cumps (outro veterano) , Andrew Monkhouse e Jeroen Sterken completam o nosso time de
rnp.r"rtror - o*brigado a todos voc6s. Jim Yingst panicipou da equipe de criagio do exame da Sun, e nos ajudou a escrever
algumas das quest6es mais dificeis do livro (muahahaha).
Como sempre, toda vez que voc6 vir uma plgina bem esc ita, agradegaaos nossos revisores e, se encontrar um erro' com
toda ceneza 6 por culpa dos autores. Ah sim,i um agradecimento final aoJohannes. VocA 6 demais, cara!
JAVA 5 )O/II
Agradecimentos
Kathy e Bert gostariam de agradecer as pessoas a seguir:
r Topas
1s egssoas
incrivelmente esforgadas da Osborne: Tim Green, Jim Kussow, Jody McKenzie e Jennifer Housh por
toda.a ajuda e por serem tXo compreensivas e pacientes - bem, certo, nem tio pacientes assim - mas muito
profissionais e o grupo mais agrad6vel de pessoas com quem sepoderiaesperartrabalhar.
I Os nossos anjos Solveig Haugland e Midori Batten, por virem nos salvar quando realmente esr6vamos em apuros!
r Akuns dos profissionais de software e amigos que nos ajudaram nos dias iniciais: Tom Bender, Peter Loerincs, Craig
Matthews, Dave Gustafson, konard Coyne, Mbrgan Poner e Mike Kavenaugh.
r Acima de tudo, a maravilhosa e talentosa equipe de cenificagio da Sun Educational Services, principalmente o Gerente
do Progtama de Cenificagio, Steve ('Gooie') Moore e a pessoa mais persistente que ji conhecemos quando se trata de
-
condrsio, Evelyn Cartagena (paraMnspelo rec6m-nascido, Evelyn).
r Nossos melhores amigos e especialistas emJava, Bryan Basham, Kathy Collina e SimonRoberts.
I As criangas, Eden e Skyler, por ficarem horrorizadas que os adultos - fora da escola - estivessem estudando tanto para
umexame.
r O chefe doJavaranch Trail, Paul \(heaton, por manter a melhor comunidadeJava da Internet.
I Todos os outros instrutores antigos e atuais de Java da Sun Ed por aju&rem a torn ar o aprendizado dessa linguagem
um1 expel6nciadivenida, (para nomear apenas alguns) : Alan Petersen, Jean Tordella, Georgianna MJa$ier,
_incluindo
Antho-ny Orapallo, Jacqueline Jones, James Cubeta, Teri Cubaa, Rob '$7eingruber, John Nyquist, AsJk Perumaiiar,
Steve Steltin_g,\a;reZaffery, KimberlyBobrow, Keith Ratliffe o conhecedordeJavamais dedicado einspiradordo
planeta,,JariPaukku.
r Darren e Mary, obrigado por nos manter sios e por nos ajudar com os nossos novos amigos peludos, Andi e Kara.
r Finalmente, Eric e Beth Freeman pelo incentivo continuo.
)o/il1
Preficio
O principal objaivo deste liwo 6 ajud6-lo a se preparar e passar no exame de cenificagio SCJP da Sun Microrystems referente
aJava 5. A boanoticia 6 que o exame tende a t6picos que a maioria dos desenvolvedoresJava encontrarlo nos seus
"borda.
tiabalhos. A noticia desafiadora 6 que o exame Java 5 tem escopo bem mais amplo do que o seu antecessor, o exame Java
1.4. Os novos objetivos passam poi muitas das-APIs mais utiliiadas emJava. A palavri-chave aqui 6 "passam por". A
intengio dos criadores io ex"*. foi qn representasse a certeza de que o candidato ente nde osfundanenns de
APIs, tais como aquelas usadas para E/S "diarquivos
"provagXo e express6es regulares. Este livro segue o miximo psssivel tanto o
escopo quanto a profundidade do exame real. Pbr exemplo, ap6s ler este livro voc6 provavelmente nXo vai acordar no outro
di" *-b ,rtn go* d. ,.gr*, mas, se estudar o material, e sair-se bem nos testes individuais, voc6 ter6 um entendimento
bisico de regei e se sairilemno exame. Depois de terminareste livro, voc|tericeneza de que estudoutodos os objetivos
estabelecidos pela Sun para o exame.
N este livro
Este livro foi organizado de maneira a otimizar o seu aprendizado dos t6picos abodados pelo exame SClPJava- f . Sempre
que possivel, n6-s organizamos os capitulos seguindo os objetivos da Sun, mas em.alguns casos misturamos objetivos ou
os repeumos parcialirente p"r" os t-6picos em uma ordem mais adequada para o esnrdo do material.
"prrs"nt"t
Em cada capitulo
N6s criamos um conjunto de blocos constituintes dos capitulos que chamario sua atengio.para itens importantes,
reforgarXo pontos deiestaque e fornecerXo dicas riteis para a hora do exame. Veja o que voc6 encontrar6 em cada capinrlo:
I Cada capitulo comegar6 com os Obietivos da Certificag5o - 9-guq vocA precisa saber para passar na seglo do exame que
tratar do t6pico refeiente ao capinrlo. Os objetivos serio identificados dentro do capinrlo por seus cabegdhos, portanto'
voc6 sempre saber6 qual6 o objetivo quando o vir!
I A notas Observag6es para o exame chamario a atengio para informag6es e possiveis armadilhas relacionadas ao
exame. LJma vez que eit6vamos na equipe que criou o exame, sabemos pelo que voc6 vai passar!
I As notas Ao trabalho descreverXo aspectos priticos de t6picos da certificagXo que podem nio aparecer no exame, mas
que serlo riteis no mundo real.
I Os exercicios priticos foram incluidos no decorrer dos capitulos. Eles o ajudario a aprimorar as aptid6es,que
possivelmenteirXo enfocadas no exame. NXo se limite a leios exercicios! Eles fornecem a pritica na execugio com a
qual voc6 teri que estar familiarizado. Aprender fazendo 6 uma maneira eficaz de aumentar sua capacidade.
I A segXo Nas salas de aula descrever6 as quest6es que surgem com mais freqiiAncia em cenirios de treinamento em salas
de aula. Essas barras laterais lhe darXo uma perspe&iva vfiosa sobre t6picoJ relativos i cenificagio e aos produtos. Elas
ressaltario alguns dos problemas mais comunJe confusos que os alunos encontram quando fazem um curso deJava.
P&R
I O Resumo para a Certificagio 6 uma revisio sucinta do capitulo e uma reiteraglo dos pontos importantes
relacionados ao exame.
I O Exercicio Mpido no finalde cada capitulo 6 umalistade verificaEio com os principais pontos do capitulo. Pode ser
usado para uma revisio de ultima hora.
I O Teste Individual oferece perguntas que simulam os t6picos, a estrutu ra e a naltezadas perguntas encontradas no
exame de certificagio. As resposras a essas perguruas, assim como suas explicag6es, podem ser encontradas no final de
cada capitulo. Aoiaznr oTeie Individual, depois da concluslo de cada capinrlo, vod reforgar6 o que aprendeu nele ao
mesmo tempo em que se fam liarizarS, coma estrutura das perguntas do exame.
JAVA 5 XIX
lntrodu96o
Organizagio
Este livro foi organizado de maneiraa servircomo um estudo aprofundado sobre o exame de Programador Cenificado
pela Sun na PlataformaJava 5 tanto para profissionais experientes na linguagem quanto para os que estiverem nos est6gios
iniciais de vi#ncia com as tecnologias Java. Cada capinrlo aborda um dos aspectos principais do exame, com Anfase em
perguntas como "por que" e'!olo" pJggramar na linguager-nJava. O livro tamb6m inclui um estudo detalhado dos itens
essenciais para obter uma avaliagio positiva no projeto enviado para o exame de DesenvolvedorJava Certificado pela Sun.
Tamb6m nio pretendemos ao mesmo tempo em que o preparamos para o exaffrc tund-|t un especialista n@lcto en Jaua.Esse 6
um guiade esrudos para o a(ame da cenifica$o e sua missio 6 muito clara.Isso nXo querdizer que apreparaSo para o exame
nio o ajudari a se tornar um programador Java mais avangado! Pelo contririo, mesmo os mais experientes desenvolvedores
Javageralmente relatam que o fato deterque se prepararpara o exame de cenificaSo ostornouprogramadores mais
informados e completos do que seriam sem o estudo dirigido para o exame.
No site
Para obter mais informag6es sobre os arquivos para download, consrlte o Apdndice A.
Algumas sugest6es
Quando tiver terminado de ler este livro, reserve algum te mpo parafazer uma revisio completa. Seria bom se voc6
retornasse ao livro v6rias vezes e fizesse uso de todos os m6todos que ele oferece para revisar o material:
L RebiatodososExerciciotRtipidotoupegaaalgu|mparalhefazcrasperguntas.Voc6tamb6mpodeusarosexercicioscomo
uma maneira de fazer uma revisio ripida antes do exame. Ou criar alguns cart6es pedag6gicos em fichas 3x5 contendo o
material dos Exercicios R6pidos.
Z Reteia todat as notas da segdo Alerta no Exame. Lembre-se de que essas observag6es foram escritas por autores que ajudaram
a criar o exame. Eles sabem com o que voc6 se deparar6 - e com o que dwe tomar cuidado.
3. Refapa wTestetIndiuidaais.Fazer os testes logo ap6s ter lido o capitulo 6 uma boa id6ia, porque as perguntas ajudario a
reforgar o que voc6 acabou de aprender. No entanto, uma ideia melhor ainda 6 voltar posteriormente e responder todas
as perguntas do livro de uma s6 vez. Imagine.que est6 fazendo o exame real. (Quando percorrer as perguntas pela
primeira vez, anote suas respostas em.um.pedago. de papel separado. Dessa forma, voc6 poderi responder as perguntas
quantas vezes precisar at6 que se sinta familiarizado com o material).
4. fez os exercicios quando leu cada capitulo? Se nlo os fez, faga-os agora! Esses exercicios foram
Faga ot exercicios.Voc6
elaborados para abordar t6picos do exame e nio hi maneira melhor de conhecer esse material do que praticando.
Certifiquese de compreender porque est6 executando cada etapa de cada exercicio. Se houver algo que nio tiver
entendido, releia essa se$o do capinrlo.
Somente a experiAncia nio o far6 chegar ao final do exame com uma nota que o aprove, porque mesm o o quevoc| arba qrrc
conhece pode funcionarde formaumpouco diferente do que imagina. Nio 6 o bastante conseguirque seuc6digo funcione
corretamente;voc|prccisacompreender os fundamentos bisicos de maneiraprofunda e com abrang6ncia suficiente para
xx
abordar tudo que possa surgir durante o uso da linguagem.
O Exame de Desenvolvedor Certificado pela Sun 6 rinico no universo de certificaglo em inform6tica, porque naverdade ele
avaliar6 sua habilidade como desenvolvedor, em vez de simplesmente seu conhecimento da linguagem ou das ferramentas.
Se tomar um DesenvolvedorJ avaCenificado envolve, por defini$o, experiAncia em desenvolvimento.
Mas isso significa que vocA realmente poderi desenvolver sofrwares emJava? Nio necessariamente, mas 6 uma boa
vantagem inicial. Para demonstrar efetivamente sua habilidade no desenvolvimento (em vez de apenas seu conhecimento da
linguagem) , voc6 deve corsiderar o Exame de Desenvolvedor, do qual receberi atarela decriar um programa, do inicio ao
fim, e envi6-lo para um avaliador que o examinar6 e lhe dari uma nota.
O exame de Associado foi elaborado para candidatos que acabaram de iniciar uma carreira em desenvolvimento &
aplicativos ou em ger6ncia de projetos de software usando tecnologiasJava. Este exame testa conhecimento bisico de
conceitos de programagio orientada a objetos, os fundamentos de LIML, os fundamentos da linguagem de programagio
Java e o conhecimento geral de plataformas e tecnologiasJava. E$e exame nio tem nenhum pr6requisito.
O exame de Programador foi projaado paratestar seu conhecimento na propria linguagem de programagio Java. Ele requer
um conhecimento aprofundado da sintaxe da linguagem, dos conceitos principais e de uma pequena quantidade de
interfaces de programagXo de aplicativos (APIs, Application Programming Interfaces). Este exame tamb6m testa o
conhecimento intermediirio de conceitos de projetos orientados a objetos. Nio avaliarinenhuma questio relacionada ao
projeto ou arquitetura do programa e nio perguntar6 por que uma abordagem 6 melhor do que a outra, mas, em vez disso,
estarApreocupadoseaabordagem dadafuncionariemumasitua$oespecifica.Estee:<ameniotemnenhumpr6requisito.
O exame de Desenvolvedor tem inicio onde o exame de Programador termina. Ser6 necess6rio passar no exame de
Programador antes que voc6 possa se dedicar ao exame de Desenvolvedor. Esse exame requer o desenvolvimento de um
programa real e, em seguida, uma justificativa para as decis6es tomadas no projeto. Ele foi elaborado para testar sua
compreensio do motivo pelo qual cenas abordagens sio melhores que outras em determinadas circunstAncias e para avaliar
sua habilidade em seguiruma especificagio e implementarum programa correto, funcional e amig6vel.
O exame de Desenvolvedor 6 composto de duas panes: a tarefa de criagXo de um projeto e um exame com quest5es
dissenativas como acompanhamento. Seri dado um periodo & tempo ilimitado para conclusio do projeto, por6m,
quando este for enviado, os candidatos terio que ir a um centro de testes e fazer um pequeno exame de acompanhamento
comquest6esdissertativas, elaborado, principalmente, paravalidareverificar sef.oram eletquem o projetaram e construiram.
JAVA 5 XXI
O exame de Desenvolvedor de componentes da Web (CX-3 10-08 l)
Desenvolvedor de Componentes da \ilfleb Cenificado pela Sun na PlataformaJava EE (SC\7CD)
O exame de desenvolvedor da \fleb tem como alvo as pessoas que estiverem usando o JSP $ava Server Pages) e o servlet da
tecnologiaJavap.ar3criaraplicativos\fleb.Ele foi baseado nas eipecificag6es do Servlet i ao jSn a.fUa"rna'JavaEnterprise
Edition fava EE). Parafazrr esteexame, 6 necessirio que o candidato seja um ProgramadoiJava Cenificado pela Sun. ^
Muitos candidatos expeientes em testes ndo voltam ds respostas para aberi-las a menos que tenham ama boa raqdo parafaqer isso. Sti altere
t'tlila rePorta qaando achar que pode ter interpretado mal ou se enganado na primeira kitura que
feq de ama perganta. O neruositmo pode
faler com que uoci encontre ama ugunda rerpotta para cada perganta deixando a cotrcta de lado.
Para desencorajar.a simples memorvaglo,os exames da Sun apresentam um conjunto potencialmente disinto de perguruas
para candidatos diferentes. Na elaboragio do exame, centenas de perguntas sio compiladas e aprimoradas pot t.tt"doi.t
beta. Desse co{gnto volumoso, sio extraidx as perguntas referentei a cada objetivo que, posteriormente, sio reunidas em
v6rias vers6es diferentes do exame.
xxtl
Cada exame da Sun tem uma quantidade especifica de perguntas (o exame de Programado r conr6:mT2 Perguntas) e uma
duragio para o teste (175 min.ttos p"t" o r*ame de Programador). Normalmente, otempo destinado ao teste 6 generoso' O
rcmpo remanescente 6 sempre exiLido no canto da tela-de teste, junto com a quantidade de perguntas que faltam. Se ele
expirar durante o exame, o ieste seri encerrado e as respostas incompletas serio consideradas incorretas.
No final do exame, seu teste ser6 imediatamente avaliado e o resultado exibido na tela. As notas obtidas em cada assunto
tamb6m serio fornecidas, mas o sistema nio indicar6 que pe{guntas especificas est avamincorretas. Um relat6rio seri
impresso automaticamente na mesa do inspetor para que voc6 possa arquiv6Jo. A nota do teste 6 transmitida
eletronicamente para a Sun.
oBSERVAQ6ESpeneTE)(AME
puando uocd n sentir confurc ao retponderpergantas de nilltipla escolha, use seu rascunho para anotar as duat ou h€s respostas que
conddera as mais pttadaeit e, em seguida, vtblinbe a @osta qw acha que possiuelmente i a corwta. Aqai utui un exemplo de como fcani seu
rascanho qaando uocljd tiuerpercorido 0 terte t/ma ueg
2l.BouC
)3.AouC
Iso uriexlrenamente titil paa uocl marcar a petgilflta e darpmsseguinenta Posteriorrzente, podeni retomar e resgatar inediatamente na
raciocinio deonde parou, Enpregte esa timica para euitar ter que reler e reaualiar ar pergantas. Voc6 tambim tenl que usar seu raseanho em
perguntat de andio nrnplexo, baseadas em texto, para criar imagens de nodo a compreender aelhor a qtestdo, Esa ticnica senl
especialmente itil se aocd tiuer naisfacilidadt em c@tar conceitot uisualmente,
r Sempre que possivel, as nossiu quest6es NAO lhe dirio quantas respostas corretas existem (diremos "marque todas as
corretas"). Faremos isso para lhe ajudar a dominar o material. Alguns alunos experientes com testes poderiam eliminar
t
.r tpott"s erradas se soubessem o nrlrmero de respostas corretas. Tamb6m 6 possivel, quando vocd sabe quantas e$eo
corretas, escolher as respostas mais plausiveis. Masb nosso trabalho 6 p repar!-lo paraas dificuldades que encontrarA no
enamereal!
I O exame real normalmente numera as linhas de c6digo de cada questio. N6s normalmente nlo as numeramos - a
principal razio 6 para termos espago para adicionar comentirios onde necessirio. No exame real, quando uma listagem
de c6&go comegar pelo 1, isso indicique se trata de um arquivofonte inteiro. Se a listagem comegar por um nfmero
maiordo que 1, significa que se trata de um arquivo-fonte parcial. Quando se tratar de um arquivo-fonte parcial, as$una
sempre q.ri a parte ausente do c6digo est6 correta (por exemplo, a nio ser qrre esteja dito explicitamente o contririo, voc6
pode assumir que um arquivofonte parcial tem as instrug6es impon e package corretas).
Quest6es de Arrastar-e-Soltar
Embora muitos outros exames de certificagio Java da Sun venham usando quest6es de arrastar-e-soltar h6 v{rios anos, esta
6 a primeira versio do exame SCJP que inclui esse tipo de questio. Como discutimos anteriormente, as questSes do exame
que voc0 recebe sio sorteadas aleatoriamente, mas voce pode esperar que cercade2) a25olo das quest6es serXo do tipo
arrastar+soltar,
As quest6es arrastar+soltar normalmente consistem de tr6s comPonentes:
I Uma tarefa parcidmente redizada Uma listagem de c6digo, uma tabela ou uma irvore de diret6rios. A tarefa
parcialmente realizxla conter6 espagos em bran6, indicadoJcom caixas (normalmente amarelas). Essas caixas devefro
ser preenchidas para se complet ar atarefa.
I Um conjunto de fragmentos r€presentando respostas possiveis VocA clica nos fragmentos (normalmente caixas
azuis) e os arrasta para o espago em branco correto. O cenario da questio lhe diri se voc6 pode reutilizar fragmentos.
A maioria das quest6es de arrastare.sohar teri cerca de 4 a L0 espagos em branco para serem preenchidos, e normalmente
mais fragmenros do que o necess6rio (alguns fragmentos sio deixados sem utilizagio). As quest5es de arrastar-e-soltar
freqiientemente sio as mais complexas do exame, e o ntlmero de possiveis combinag6es de respostas as tornam quase
impossiveis de "chutar".
JAVA 5 XXIII
oBSERVAe6rspeneonl<eME
No que n ,trto fu questdes de arrastar-e-soltar, h,l um grande problena com o software de teste em muitos dos centros Pmmetric em todo o
mundo. Em geral, o nfhaare lbe penzite reuisar at questdes que jd respondeu qilantas aerys quiw.
No caso dasqautdu de arrastar-e-so/tar, entretanto, maitos candidatos tim relatado qae, se eles pedirem para reuer a questdo, o nfwaru
aPaga a rerpo$a anteioreil CUIDADO! Ati qae ese problena s/a nrrigido, recomendamos qae aocd mantenba uma lista de quait quutdet
sdo de anastar-e-so/ta6 para que ndo reuise rma sem qaerer. Outra boa iddia d anotar as rerpostat duse tiPl de qilesfil, de modo qile se iltua
Isso nos rerlete a ouho problema que os candidatos tdm re/atado. O cenhx de teste deueia lhefornecer o ruateria/ necesnirio para que uoei
pora traba/har nas questdes En
algurc casos, os centrosfomeeeram marcadores e qaadm in@ropriadog por urem peqilefllr
por escrito.
denais e dficeis de uvr efetiuamente. Rtcomendamos qae uoc6 aeifque, antes do dia do examq se receber,l do cenhv kpis ou caneta e pelo
menos algumatfolhar de papel en branco.
Uma t6cnica ficil, que pode ser usada nos estudos para os exames de cenificagio, 6 a dedica$o durante 15 minutos di6rios.
Simplesmente, est;de aurante um minimo de 15 minutos todo dia. E um compromisso infimo, por6m, significativo. Se_
houver um dia em que voc6 nXo consiga se concentrar, entio, pare quando chegar aos 15 minutos. Se em outro dia o estudo
fluir muito bem, est^ude mais. Se a quintidade de dias em q,re i.rdo fluir bem fo-r maior, suas chances de ser bem sucedido
serio bastante altas.
E r.comendivel que voc6 use can6es pedag6gicos ao se preparar para o exame de Programador . O canio
"lt"-.trt. 6 simplesmente uma ficha 3X5 ou 4X6 com uma pergunta na frente e a resposta atris. Crie voc6 mesmo esses
pedag6gico
cart6is quando passar por um capinrlo e inclua qualquer item que considere precisar de mais memorizagio ou tempo de
pr6tica. Com elis, voc6 pode se iuto -avaliar fazendo a leitura da pergunta, buscando a reposta na mem6ria e depois virando
o cartio para ver se acertou. Ou pedir a outra pessoa que o ajude, segurando o cartio com o lado da pergunta virado para
voc6 e verificando a reposta em seguida. A maioria de nossos alunos achou esses cart6es extremamente iteis,
principalmente porqui sio tio pequenos que enquanto vod estiver estudando, poderi lev6-los para qualquer lugar. No
entanto, 6 melhor nlo us6-los ao dirigir, exceto quando parado no sinal vermelho. Levarnos os nossos para todos os
lugares - o consult6rio m6dico, restaurantes, teatros, onde puder imaginar.
Os grupos de e$udo para a certificaglo 6 outro recurso excelente e vocA nXo encontrar6 uma comunidade maior ou mais
participativa do que nos f6runs Big Moose Sallon do javaranch.com. Se tiver uma pergunta relacionada a este livro, ou de
qualquer outro eiame simulado com o qual se deparar, ao envi|-laparaumf6rum sobre a certificagXo voc6 obteri a resposta,
em quase todos os casos, dentro de um fi4 e na maioria das vezes, em algumas horas. VocA nos encontrari por [6 (os
autore$ v6rlsvezes por semana, ajudando as pessoas que estXo iniciando.sua jornada de preparagXo para o exame. (Voc6
nio conseguiri pensar em nada que soe tao bem como a p alavra"jornada" quando estiver se preparando para o exame).
Finalmente, recomendamos que voc6 escreva v6rios pequenos programas emJava! Durante a escrita deste livro, n6s
escrevemos centenas de pequenos programas, e se voc6 der ouvidos ao que dizem os candidatos mais bem-sucedidos (tipo
aqueles com m6dia 987o), eles sempre relatam que escreveram muito c6digo como pane do estudo.
xxtv
Agendando seu exame
Os exames slo contratados na propria Strn, mas sio agendados diretamente com a Sylvan Prometric. Para locais fora dos
Estados Unidos, o nimero de contato de onde voc6 estiver poder6 ser encontrado no site Web da Sylvan, que fica no
enderego http :/ /www.2tex.com. Os representantes da Sylvan poderio agendar seu exame, mas nio terio informag6es
sobre osprogramas de cenificagXo. Perguntas sobre a certificaglo devem ser dirigidaspara o depanamento de Treinamento
Internacional da Sun. Esses representantes estio suficientemente familiarizados com os exames para encontri-los por
nome, mas ser6 melhor se voc6 tiver o nrimero do exame especifico ) mio quando falar com eles. Afinal, voc6 nlo iria gostar
se lhe agendassem e cobrassem o exame errado.
Os exames podem ser agendados at6 com um ano de anteced6ncia, embora isso nio seja realmente necess6rio. Geralmente,
agendA-lo com uma ou duas semanas de anteced6ncia seri o suficiente para voc6 reservar o dia e a hora que preferir. No
momento do agendamento, os operadores procurario centros de teste em sua irea. Por conveniOncia, eles tamb6m poderio
informar em que centros de teste voc6 j6 esteve.
Quando voc6 se registrar no exame, o n{rmero de sua identificag1o ser6 solicitado. Esse nrimero ser6 usado no envio dos
resultados de seu exame para a Sun. E importante que voc6 use o mesmo nrimero de identificaglo sempre que se registrar,
para que a Sun possa acompanhar seu progresso. As informag6es de enderego fornecidas quando vocA se registrar pela
primeira vez tamb6m serio usadas pela Sun para enviar os certificados e outros materiais relacionados. Nos Estados
Unidos, geralmente o n{rmero de seu seguro social 6 usado como nrimero de identificagio. No entanto, a Sylvan pode lhe
fomecer um nirmero exclusivo de identificacio.
Chegue cedo no exame; isso lhe dar6 tempo para relaxar e revisar os fatos essenciais. Aproveite a opornrnidade pa ra rever
suas notas. Se estiver cansado de estudar, talvez possa comegar seu exame alguns minutos antes. Por outro lado, nio
recomendo chegar tarde. Seu teste poderia ser cancelado ou voc6 pode nio ter tempo nrficiente para concluir o exame.
Quando chegar no centro de testes, voc6 teri que se inscrever com o inspetor do exame. Para se inscrever, ser6 preciso
fornecer dois tipos de identificagio. Os tipos aceitos sio identificag6es emitidas pelo governo (por exemplo, passaporte
ou habilitagio de motorista), cart6es de cr6dito e crach6s de empresas. Sua fotografia deve consrar em uma das
identificag6es. Eles s6 estario se certificando se voc6 nio enviou, em seu lugar, seu vizinho brilhante emJava, a quem
pagou para fazer o exame.
Al6m de um c6rebro repleto de informag6es, vod nio precisar6levar nada mais para o exame. Na verdade, seu c6rebro ser6
tudo que poder6 levar! Todos os testes devem ser feitos com os livros fechados, o que significa que voc6 nio precisa levar
nenhum material de consulta. Tamb6m nXo poderi levar nenhuma nota ao sair da sala do exame. O inspetor do teste lhe
forneceri papel e caneta. Alguns centros & teste podem fornecer uma pequena prancheta em vez disso. Recomendamos que
voc6 leve uma garrafad'|goa. Duas horas 6 muito tempo para manter seu c6rebro em atividade e ele funcionar6 melhor se
estiver bem hidratado.
Deixe seu pager e telefone no carro ou desligue-os. Eles s6 deixario a situagio mais tensa, ji que nio sio permitidos na sala
do exame e talvez ainda possam ser ouvidos se tocarem fora da sala. Bolsas, livros e outros materiais devem ser deixados
com o inspetor antes que voc6 entre na sala do exame.
IJma vez na sala de testes, o inspetor se conectar6 com seu exame e vocO ter6 que verificar se seu nrimero de identificagio e o
ntmero do exame esteo corretos. Se for a primeira vez que voc6 estiver fazendo um teste da Sun, poder6 selecionar um
tutorial resumido existente no software do exame. Antes de o teste comegar,. serio dadas informag6es sobre o exame,
incluindo a duragio, a quantidade de perguntas e a nota exigida para passar. E bastante prov6vel que seja pedido que voc€
responda a uma breve pesquisa antes de o exame propriamente dito comeEar. Essapesquisa lhe perguntar6. sobre o seu
nivel de experiAncia em Java. O tempo que voc6 gastar n a pesquisa nio ser6 retirado do tempo propriamente dito do seu
teste - nem voc6 ter6 mais tempo se responder a pesquisa rapidamente. Lembre-se tamb6m de que as quest6es no seu
exarne ndo serio modificadas dependendo dx respostas que der i pesquisa. Em seguida, o rel6gio comegar6 a funcionar e a
diversioteriinicio.
O sofrware do teste 6 executado no rVindows, mas vod nXo ter6 acesso a 6rea de trabalho principal ou a qualquer acess6rio.
O exame ser6 apresentado em tela cheia, com somente uma pergtrnta por tela. Os bot6es de navegagio permitirio que voc6
se mova para baixo ou para cima entre as perguntas. No canto superior direito da tela, contadores mostrario a quantidade
de perguntas e o tempo remanescentes. O mais importante 6 que haver6 uma caixa de selegio chamada Mark no canto
superior esquerdo da tela - essa ser6 uma ferramenta importantissima, como explicaremos na segio seguinte.
JAVA 5 x)O/
T6cnicas para fazer o teste
Sem um plano de ataque, os candidatos serio subjugados pelo exame ou serio deixados para tris e ficario sem rempo.
Geralmente, quando.estamos familiarizados co- o material, o tempo estipulado 6 mais io que suficiente para a conclusio
^
do exame. O truque 6 nio perder tempo em algum problema especiiico.
O objetivo 6bvio de um exame 6 que as.perguntas sejam respondidasde maneira eficaz, mesmo que ourros aspecros
possam distraiJo. Aqui estlo algumas dicas paraf.azer o exzLme mais eficientemente.
Avalie o desafio
Primeiro, d6 uma passada r6pida por todas as perguntas do exame. Elimine as f6ceis, respondendo.as imediatamente. Leia
rapidamente.cada pergunta, observando seu tipoi assunto. Como diretriz, tente gastar^menos do que 25 por cento de seu
tempo nessa leitura.
Essa etaPa permitil6 q.ue vogQ
ryalie o escopo e a complexidade do exame, lhe ajudando a dererminar como conrrolar seu
tempo' Tamb6m dari uma id6ia de onde encontrar possiveis respostas para algumas das perguntar. As ,r.zes, redagio Je
umapergunta pode darpistas ou trazer a sua mem6iia outrapergurua. "
Se voc6 nXo estiver totalmente ceno de sua reposta a uma pergunta, responda assim mesmo, mas marque a caixa Mark para
indig.ar W9
fve
fazer uma revisio.posterior nela. Caso voc6 fiqrr. r.*
i.ntpo, pelo menos ter6 forneci'do r pri*.ir" t fjrt"
que lhe veio i cabega, em vez de deix6Ja em branco.
Em segundo lugar- rwise todg o teste, empregando a percepglo que obteve na primeira leitura. Por exemplo, se o teste
inteiro parecer dificil, voc6 saberi que nio poder6 gastar mais de circa de ,r- *irr.rto .- cada pergunta. Dirrij, o ..*po e*
pequenos blocos - Por exemplo, "Preciso responder L0 perguntas a cada 20 minutos".
Nesse estigio, provavelmente seri uma boa id6ia saltar as pergunras que exigirem mais rempo, marcando-as para a pr6xima
leitura. Tente terminar essa fase antes de chegar a 5G6O por cJnto doiempJdo teste.
Em terceiro lugar, leia todas as perguntas que voc6 marcou para revisar, usando o botlo Review Marked da tela de revisio de
Perguntas. Essa etapa inclui uma segunda leitura de todas as perguntas cujas respostas foram dadas sem cerreza, assim
como responder as que exigem maistempo e que ,rocA posteigori at6 agora. Responda como achar melhor esse conjunto de
perguntas ate que as tenha responctldo por completo.
Se voc6 estiver mais seguro para responder uma pergunta que marcou, desmarquea agora. Do contririo, deixe-a marcada.
V6 trabalhando nas perguntas que exigirem mais tempo, principalmente as qrr. n ..tiit"rcm de c6lculos manuais.
-
Desmarque-as quando estiver satisfeito com a resposia.
Ao final dessa etapa, voc6 ter6 respondido todas as pergpntas do_teste, apesar de nlo te r ceneza em alzumas das respostas.
Seficar sem tempo na pr6xima etipa nio perder6 pbntos pela falta de uma pergunta. Estar6 bem se aiida tiver 1O-2b por
cento de tempo remanescente.
O grande final
Quando estiverconfiante de todas as respostas, termine o exame enviando-o para avaliagio. Depois, do que parecerio os LO
segundos mais longos de sua vida, o software do teste retornar6 sua nota. Geialmente, ela 6 exibida em um gr6fico de
barras, que mostra a nota minima exigida, a nota obtida e um indicador PASS/FAIL.
Sevoc6 estiver curioso, poder6 ver sua m6dia de pontos nesse momento. Nio serio apresentadas as repostas a pergunras
as perguntasserio reunidas em categorias e serio registradoirenrltados para c.d, cat"gorl. Ett.
especificas; em vez disso,
detalhe tamb6m estari em um relat6rio que teri sido impresJo auromaticaminte na mesa do inspetor do exam?.
Quando voc6 sair do local do exame, ter6 que deixar seu rascunho para tris ou entreg6Jo ao inspetor. (Alguns centros de
teste registram o nfmero de folhas que sio fornecidas, para tetem certezade que tod-as serio devolvidas). Em troca, vocp
receber6uma c6pia do relat6rio do teste.
Esse relat6rio terl a marca do centro de testes gravada e voc6 deve guardiJo em um local seguro. Normalmente, os
resultados sio transmitidos automaticamente para a Sun, mm podi r.r q.te voc6 precise doielat6rio emitido para provar
que Passou no exame.
x)o/r
Em algumas semanas, a Sun lhe enviar6 um pacote pelo correio contendo um bonito cenificado, um alfinete de lapela e
uma carta. Tamb6m podem lhe enviar instrug6es di como contratar o tabalho artistico para criaSo de um logotipo que
voc6 poderiusar em cart6es de visitapessoais.
Paraconcluir,lembrese que as ceftificag6es daSun sXo vdiosas, pois sio dificeis deobter. Afinal, se qudquerpesoa
conseguisse, que valor teria? No final das contas, 6 necessirio uma atitude adequada e muito esnrdo, mas voc6 pode faz&lol
I
DeclaraE6es e
Controle de
"'
Acesso
Oblerlvos pqru o
Gerrlflcqf6o:
N6s partiremos do principio de que, uma vez que esti planejando obter a cettificagio, voc€ i6 sabe o bisico deJava. Caso seja
completamente iniciante na linguagem, este capinrlo - e o restante do livro - ser6 confusq entio, certifique-se de que voc6
sabe pelo menos o b6sico da linguagem antes de mergulhar neste livro. Dito isso, comegaremos com uma revisio para
refrescar a sua mem6ria sobreJava, caso tenha estado afastado da Jinguagem por algum tempo. i
Revisio de fava
Um programa emJava € principalmente uma colegdo de objetos falando com outros obf etos por meio da invocagio dos .
m6todos uns dos outros. Cada objeto 6 de um tipo, e esse tipo 6 definido por uma classe ou uma interface. A maioria dos
programas emJava usa uma colegio de objetos de muitos tipos diferentes.
I Classe Um modelo que descreve os tipos de estado e de comportamento que os objetos do seu tipo podem ter.
I ObietoNomomentodaexecugio,quandoaM6quinaVirtualJavaflavaVirtualMachine,ouJVlvf eflcontt^^p^l^.rra-
chave new, ela usa a classe aproprtadapara criar um objeto que seri uma instAncia dessa classe. Esse obieto ter6 o seu
pr6prio estado e ter6 acesso a todos os comportamentos definidos pela sua classe.
I Estado (vari6veis de instdncias) Cada objeto (instdncia de uma classe) ter6 o seu conjunto rinico de vari6veis de
instAncias conforme definido na classe. Coletivamente, os valotes atribuidos is variiveis de instincias de um obieto
compdem o estado do objeto.
I Comportamento (m6todos) Quando um programador cria uma classe, ele cria m6todos para essa classe. E nos
m6todos que a l6gica da classe 6. armazentda. Nos m6todos, o verdadeiro rabalho € rczLzado. E neles que os
algoritmos sio executados e que os dados s6o manipulados.
ldentificadores e Palavras-chave
Todos os componentes deJava de que acabamos de falar - classes, vari6veis e m6todos - precisam de nomes. EmJava,
esses nomes sio conhecidos como identificadores e, como seria de se esperar, existem regtas dizendo como devem ser os
identificadoresJava permitidos. Independentemente do que 6 permitido, no entanto, os programadoresJava (e a Sun)
cianmconveng6esparaafiome giodem6todos,vari6veiseclasses.Comotodasaslinguagensdeprogramagdo,Javatem
um coniunto de palavras-chaves internas. Essas palavras-chave nio podem ser usadas como identificadores. Mais adiante
neste capitulo, veremos os detalhes sobte essas regras e conveng6es de nomeagio, e sobre as palavtas-chaveJava.
Heranga
Fundamental pataJava e outras linguagens orientadas a objetos 6 o conceito de hetanga, que permite ao c6digo definido em
uma classe ser reutilizado em outras classes. EmJava, voc6 pode definir uma supetclasse geral (mais abstract), e depois
estend,3-la com subclasses mais especificas. A superclasse nio sabe nada sobre as classes que herdam dela, mas todas as
subclasses que herdam da superclasse ptecisam declarar explicitamente a relagdo de heranga. Uma subclasse que herda de uma
superclasse recebe automaticarnente as vari6veis de instAncias acessiveis e os m6todos definidos pela superclasse, mas 6
tamb6m livre para substituir m6todos da superclasse para definir comportamentos mais especificos.
Por exemplo, :uma npercIasse Carro poderia definir m6todos gerais comuns a todos os autom6veis, mas uma Jrlklasse
Ferrari poderia substituir o m6todo acelerar ( ) .
Interfaces
Um poderoso companheiro da heranga 6 o uso das interfaces. Ainterface 6 uma esp6cie de superclasse 100% abstricE
que define os m6todos que uma subclasse deve suportat, mas ndo como esse suporte deve ser implementado. Fm odtras
pilavras,umainterfaceAnimal poderiadeclanr que todas as classes de implementagio de Animal devem ter um m6todo
comer ( ) ,mas ainterfaceAnimalnlo fornecenenhumal6gicaparaom6todo comer ( ) .Isso significaque ftcaacargo
das classes que implementam ainterface Animal a definigio do c6digo para como cada tipo particular de Animal se
comporta quando o seu m6todo comer ( ) 6 invocado.
At6 mesmo programasJava simples usam obietos de muitas classes diferentes: algumas que voc6 criou, e algumas criadas
por outros (tais como as classesJava API da Sun).Jwa orgatizaas classes em pacotes, e usa declaragdes import pan dar
aos programadores uma forma consistente de gerenciat anomeagdo das classes de que precisam e o acesso a elas. O exame
aborda v6rios conceitos relacionados aos pacotes e ao acesso a classes; exploraremos os detalhes neste e em outros capitulos.
JAVA 5 3
Al_r r. ..t.
\Joleilvo poro o Lentttcocoo
^
l.4Desenuoluercddigoquedularemdtodosstatic en1o-sLaLic'e,seapropriado,usarnomesdemdtodosqueobedegamaospadrdu
Aldm disso, desenuo/uer nidigo que declare e t/se ama /ista de argamentos de extensio uai,iiel.
de nomeagdo JauaBeans.
Lembre-se de que, quando listamos um ou mais Objetivos pata a Certtftcagdo no livro, como acabamos de fazer, isso
significa que as seg6es a seguir abordario pelo menos parte desses objetivos. Alguns objetivos serio abordados em
v6rios capitulos diferentes, de modo que voc€ ver6 o mesmo obietivo em mais de um lugar do livro. Por exemplo, esta
segio cobre declarag6es, identificadores e nomeagioJavaBeans, mas o uso do que voc€ vai declant ser6.abordado em
capitulos posteriores.
Assim, comegaremos com os identificadotesJava. Os tr6s aspectos dos identificadoresJava que abordaremos aqui sio:
I Identificadores Legais As regras que o compilador usa para determinar se um dado nome 6legal.
I Conveng6es de C6digo Java da Sun As recomendag6es da Sun para nomeagio de classes, vari6veis e m6todos.
Normalmente n6s obedecemos a esses padr5es em todo o livro, exceto quando estivermos tentando lhe mostrar como
seria uma questio dificil do exame. Nio lhe ser6o feitas perguntas sobre as Conveng6es de C6digoJava, mas
recomendamos enfaticamente que os programadores as usem.
ldentificadores Legais
Tecnicamente, os identificadores legais devem ser compostos apenas de caracteres Unicode, nrimeros, simbolos de moedas e
caracteres de conexio (como underscores). O exame nio mergulha nos detalhes de quais falras do coniunto de caracteres
Unicode qualificam como letras e digitos. Assim, por exemplo, vocd n6o precisar{ saber que os drgrtos em Tibetano v6o de
\u0420 at6 \u0f29. Eis aqui as regras que voc6 precisa saber:
I Osidentificadoresdevemcomegarcomumaletra,umcifrio($)ouumcaracterdeconexdo,comoounderscore(_).Os
identificadores nio podem comegar com um nfmerol
I DePois do primeiro c^r^cter,os identificadores podem conter qualquer combinagio de letras, caracteres de moedas,
caracteres de conexio ou nfmeros.
I Na pr6tica, nio h6limite para o nrimero de caracteres que um identificador pode conter.
I Nio se pode usar uma palavta-chaveJava como identificador. A Tabela 1-1 lista todas as palavras-chave Java. incluindo
uma novidade da versio 5.0, enum.
I Os identificadores emJava si.o case-sensitive; foo e Foo sio dois identificadores diferentes.
Seguem alguns exemplos de identificadores legais e ilegais; primeirq identificadores legais:
I nf a .
int gc,'
int 2 w;
int _$;
int eis_um_nome_bastant.e_detalhado3ara_um_identif icador ;
Os seguintes sdo ilegais (agora voc€ ji sabe o por qud):
int :Jr;
i ht -A .
int e#;
I nr I .
anE. /9,.
4 Copftulo 1 : Declorog6es e Conlrole de Acesso
Tobelo 1-l Listo Completo de Polovros-Chove Jovo (ossert odicionodo em 1 .4, enum odicionodo em 1 .5)
Dito isso, vocd ver6 que muitas das quest6es do exame nio seguem as conveng6es de c6digo, devido is limitag6es do
programa de provas que 6 usado para minisftar o exame internacionalmente. Uma das boas coisas sobte as certificag6es da
Sun 6 que os exames sio administrados uniformemente em todo o mundo. Para se conseguir isso, as listagens de c6.ligos
que voc€ ver6 no exame real freqiientemerite sio bem bagungadas, e nlo seguem os padr6es de c6digo da Sun. Panprepat|-
lo pam o exame, n6s freqtientemente iremos apresentar listagens de ssdigos com uma aPar€ncia igualmente bagungada,
usando apenas dois espagos depatdgnfo em vez dos quatro espagos do padrio Sun'
N6s tamb6m bagungaremos nossas chaves de forma artificial, e, em alguns casos, colocatemos v6rias declatag6es na mesma
linha... oh nio! Por exemplo:
1. class Wombat implements Runnable {
2, private int i;
3. public synchronized void runO i
4. if (i*5 l= 0) { i++; i
5. for(int x=0; x<5; x++, i++)
6. { if (x > 1) Thread.yield0 ; }
7. System.out.print (i + " ") ;
8)
g. public st.atic void main(string[] args) t -
l-0. Wombat n = new wombat O ;
11. for(int x=100; x>0; --x) { new Thread(n).startO; }
L2. ) )
Considere-se avisado - voc€ ver6 v6rias listagens de c6digos, quest6es simuladas e quest6es de exames reais que serio
doentias e incompreensiveis dessa maneira. Ningu6m quer que voc6 escreva seu c6digo desse ieito. Nem o seu empregador,
nem os s..,s colegas de trabalho, nem n6s, nem a Sun e nem a equipe de elaboragdo do exame! Esse tipo de c6digo foi
criado apenas para que conceitos complexos pudessem ser testados usando-se uma ferramenta de provas universal. O rinico
padrio que 6 seguido tanto quanto possivel no exame rcaL6. o dos padr6es de nomeagio. Eis os padr6es de nomeagio
recomendados pela Sun, e que usamos no exame e na maior parte do livro:
I Classes e interfaces A primeira letra deve ser maifscula e, se v6rias palavras forem escritas iuntas para formar o nome, a
primeira leta d e cadapalavrainterna deve ser mairiscula (um formato chamado em inglBs de "camelCase'). Para classes,
os nomes devem normalrnente ser substantivos. Por exemplo:
Dog / /Cachorro
JAVA 5 5
Account / /Conta
Print.Wrj-ter / / Impressora
Para interfaces, os nomes devem normalmente ser adletivos, como:
Runnable //Execut6vel
Serializable / / Seria]-:-z5ivel
I M6todos A primeira letra deve set minriscula, e depois as regras camelCase normais devem ser usadas. Al6m disso, os
nomes devem normaknente ser pares de verbo-substantivo. Por exemplo:
getBalance / /obterBalango
doCalculat ion / / fazerC6lculo
setCustomerName / /de f inirNomeDoCl iente
I VariSveis Como nos m6todos, o formato camelCase deve ser usado, comegando com uma letra minriscula. A Sun
recomenda usar nomes curtos e significativos, o que nos parece uma boa id6ia. Alguns exemplos:
buttonWidth / / LarguraDoBotSo
accountBal ance / / balanqoDaConta
myString //minhaString
I ConstantesAsconstantesJavasdocriadasmarcando-sevariiveiscomostatic efinal.Elasdevemsernomeadas
usando-se leftas maifsculas com cafacteres underscore como seoaradores:
MIN_HEIGHT / /ALTURA_MINIMA
Padr6es favaBeans
A especificagioJavaBeans foiciadapanajudar os desenvolvedores a criarem componentesJava que possamser facilmente
usados por outros desenvolvedores em uma ferramenta de Ambiente de Desenvofvimento Integrado ("Integtated
. Development Environment, ou IDE), como o Eclipse ou o NetBeans. Como um programadorJava, voc6 desejard usar
componentes daAPIJava, mas seria excelente se voc€ pudesse tamb6m comp?br o componenteJava que quisesse no
"Mercado Beans", aquela loja de software queficana sua rua. E,-depois de enconffar os componentes, voc6 gostaria de
poder acessi-los atrav6s de uma ferramenta de desenvolvimento de forma tal que nio precise escrever todo o seu c6digo do
zero. Ao usar regras de nomeagio, a especificagdoJavaBeans ajuda a garantir que as ferramentas podetio reconhecer e usar
componentes criados por diferentes desenvolvedores. AAPIJavaBeans 6 um tanto complexa, mas voce s6 precisar6 estudar
alguns fundamentos para o exame.
Primeiramente,JavaBeans sio classesJava que tem propriedades. Para os nossos prop6sitos, pense nas propriedades como
vati6veis de instdncias private. Umavez que sdo private, a rinica maneira pela qual podem ser acessadas de fota da
sua classe 6 atav€s de m6todos da classe. Os m6todos que modificam o valor de uma propriedade sio chamados m6todos
tetter, e os m6todos que obt6m o valot de uma propriedade s6o chamados m6todos geLter. As regtas de nomeagio
JavaBean que vocd precisar6 saber par o exame sio as seguintes:
I Se a ptopriedade for booLeana, o prefixo do m6todo getter 6 ou get ou is. Por exemplo, tanto
getSt.opped ( ) quanto isstopped ( ) sio nomesJavaBeans vilidos pataum^ propdedade booleana.
I O ptefixo do m6todo setter deve ser set. Por exemplo, setsize ( ) 6 o nomeJavzBeanv|Idopar^lma
propriedade chzmada s i z e.
I Pa:,a ter o nome completo de um m6todo getter ou settef, passe a primeira letra do nome da propriedade para
mairiscula e depois anexe o prefixo apropriado (get, is ou set).
I As assinaturas de m6todos setter devem ser marcadas como public, com um tipo de retorno void e um
argumento que represente o tipo da propriedade.
I As assinaturas de mdtodos getter devem ser marcadas como pubL ic, nio usar argumentos e ter um tipo de
retorno que bata com o tipo do argumento do mdtodo s et ter pan a ptopiedade em questao.
Em segundo lugar, a especificagiloJavaBean tem suporte a euentos, os quais permitem aos componentes notificarem uns aos
outros quando algo acontece. O modelo de eventos geralmente 6 usado em aplicag6es GUI quando urn evenro, como urn
clique do mouse, 6 comunicado para muitos outros objetos que possam ter cgisas a fazet qtando ocore um clique do
6 Copftulo 1 : DecloroE6es e Controle de Acesso
mouse. Os objetos que recebem ainfornagdo de que ocorreu um dado evento sio chamados de /isteners. Para o exame, voc€
precisa saber que os m6todos usados pata adicionar ou remover listeners de um evento devem tamb6m seguir padr6es de
nomeacio JavaBean:
I Nomes de mdtodos listeners usados para remover ("desregistrar") um listener devem usar o prefixo remove, seguido
do tipo do listenel (usando-se as mesmas regras que o m6todo add de registro).
I O tipo de listener a ser adicionado ou removido deve ser passado como o argumento para o m6todo.
Alguns exemplos de assinaturas de mdtodos JavaBean vdl-idas:
public void setMyValue(int v)
public int getMyValue ( )
nrrlrl i a lrnnl
ysv4+v aan i cM\/ql-.1-rrc | )
O objetiuo diqque uoci precisa saber os identifcadoru legais para nzmes de uaridueis, mas as regras s6o ar nermas para TODOS os
sd
componentes Jaua. Assim, lenbre-rc d.e que un identifcador legalpara ilma aariduel tanbdn d legalpara un nitodo ou uma classe.
Entretanto, uocd deue distinguir entre os identifcadores legais e as conuengdes de norueagdo, tais como o: padrdet JauaBeafls, q//e indican cono
um determinado componente Jaua deue ser nomeado. En outras palauras, uocd deue ser capaqde reconheeer qae um dado identifcador d legal
mesml qile e/e ndo se conforme a padrdes de nomeapdo. Se a qaestdo do exame estiuer lhe perguntando sobre conuengdes de nomeapdo - e ndo
f lsiaul,er-Jpa-clas,sepubli-cemumarquiv.o-o..-el^"rg"*odevesere.mesmodaclassepubfic.por
exemplo, uma classe declandacomo public cl-ass Dos
chamado Dog. j ava.
{ } precisa esrar em rr- ".qrlirro'd. c6digo-fonte
I Se a classe ltzet panede um pacote, a declaragio package deve estar na primeira linha do arquivo do c6digo-fonte, antes
de quaisquerdeclarag6es import que estejam presentes.
r Se houver declarag6es import, elas devem frcar enhe a declangdo package (se houver) e a declaragio da classe. Se nio
houver uma declatagdo package, entio a(s) declaragzo(5es) impoit deie(m) estar na(s)
primeirals; Iinha(s) do arquivo
do c6digo-fonte. Se n6o houvet declaragSes package nem import, a declatagiodu.t"i..
d.rr..sti na primeira linha do
arquivo do c6digo-fonte.
.,!
r
\, r As declarag6es import e package aplicam-se a todas as classes denffo de um arquivo de c6digo-fonte. Em outras
p palavras' nio 6 possivel declarar multiplas classes em um atquivo e t6las em diferentes
pacot;s, ou usar diferentes
importag6es.
\
".\ I Um arquivo pode ter mais de uma classe nio-public.
( I Arquivos que nio tenham classes pub 1 i c podem ter um nome que nio seja o mesmo de nenhuma
das classes do arquivo.
No Capitulo 10' discutitemos mais de talhes sobre as regras envolvidas com a dec langdoe o uso de importag6es, pacotes e
um recurso novo doJava 5, importag6es estAticas.
class Myclass { }
Esse.c6digo iri compilat sem ptoblemas, mas yqgepqdelamb€lq adeio.nar
rao-digga4tr-es antes da de cla.r-ag,oda classe. Os
modificaderes ee dividemsnc duas..patsgp_r-ias :
r public,prolecLe4 pLivate.
_!t_"-aiq..aores de ac€sso:
I M-odificadoresquen6ose.r,eferemaacesso(incluindo strictfp, f inal eabstract).
Examinaremos os modificadores de acesso ptimeiro para que voc6 aprenda como restringir
ou permitir acesso a uma classe
que criar'o controle de acesso emJava 6 um pon.o porque pusterrr q\la$a ea.rtrok;de acesso (niveis dg qgesso)
--plicado
f0olep r-H#fI(!!frkdrcde-ageccq. Qqpa4q nivpl de-coqtrsle de acesso (cha-mado de acesso def ault oudep)iote){o
guq v-o-c€ oblim qual-{o ndo usa nenhunraostr€l-modi-fic4do{qs de acesso. E,m'outras
palavras, gggp13rr., m6todo ..'
Vgrpy..el{g inst{gci4 quevo-g6 {eclatar tem um controle Jieacisrq
-d.pqndentemente d;voc€ indi} um explicitamente ou
0.69' Embora tgd-g! 9-9^qF4trq gontrole; fg acesso (o que significa todos os tr€s modificadores) foncion
emparaa maroria das
declarag5es de m6todos e de variiveis, uma classipode.ser declarada.apenaS,.co5n,gcesso
pubt"ic ou d,ef ault; os outros
dois niveis de controle de acesso nio se aplicam paia classes, como voc6 ver6 adiante.
AO TRABALHO
Jaua d uma linguagen cenlrada n\Epa.rote|; os derenuoluedoret asrumiram qae,para uma boa organiqagdo e controle do escopo de nomes,
uocdpreferiria colocar todat as suas clasres empacotes. Eles estauam certoi, e iocd deuefaryr
i:i neino. Inagine o seguintepesadelo: trds
diferentet progmnadorer' na flrerma efitprestT, mas traba//tando em diferentes partu
de in prolen, escreuen ,oin o* una clasrc chamada
Utlities' Se essas trfu classes lJtilities ndo ,iuerem sido deltyadas in nenhin pacot, ,^pbrito, e utiuerem
no clasrpath, uoci ndo terd
nenhana maneira de diler ao compilador ou a
lwtL qual /as trds estd tentand) referencior. A Sun recomenda qae os desenuolaedoret
usem n1mes de doninio reuerso, anexados colr o nlme da diuisdo e oa doprojeto. Porexeupl0,
f ft 0 ltvne do siu doniniofor
geeksanonltmous'cLm' e estiaer traba/hando no aidigo do clienlepara oprograna
TwelaePoiitOStEt, aoc6 daria ao Jeil pacote ,/m //,me
camo com'geeksan0nlm0us.rteps.client. Isso modifcaria o oori do su) classe pnra
,o*.grr/"roronlroa1sEt.c/ient.(Jtilities. Ainda
astim, uocd poderia ter klisdes de nomer dentro da rila emprera, se ndo inuentai os
uus pidprios ujor*^ de' nomeagdo, mar
garantidamente ndo hausnl colisdes nm clasu duenuolaidas.fo* d: saa empreM
lassinlido qrr)/o, ngn* a conuengdo de nomeagdo da
Sury se e/as ndo o17(erem, bem, coisas bastante desagradriuiis poden aconticer). '
Acesso a Classes
o que significa acessar uma classe? Q-uando dizemos qug o g{dig-o-de uma classe.(a classe A) tem acesso a ou-tra-Gla-csE-E),
if gl-stgilfisa-Su-eaclAS!94-p-oi9g:9r-r1!tl.dlsp.g',rniq9coie4q;*
I Criar uma instdncia da classe B.
8 Copftulo 1 : DecloroE6es e Controle de Acesso
l-.i.a
pritica, acesso signific a uisibilidadp. Se. a c-lasse A nio puder uera classeB,o nivel de acesso dos m(lodos e variiveis dentro
da classe B n6o farS,dtfercnga; a classe A nio ter6 como acessar esses m6todos e vari6veis.
Esse6o
ASr.SgD_ =faprll-Upaclagge-comaqggq-gdefaul-t naotemnenhummodificadorprecedendo-a{radeclaragio!
iontrole de acesso que vo.e oUte- quando nio digrta um modificador na declaragdo daclzsse. Pense no acesso defaul-t
como um acesso de nivel de pacote, porque ulna class-e-com acesso de f aul t s6 pode ser vista por classes de dentro do
rnesmopacote.Porexemplo,seaclasseAeaclasseBestiveremempacotesdiferentes,eaclasseAtiveracessodefault,a
classe B nio set6 capazdJ criar uma instAncia da classe A, e nem mesmo declarar uma varidvel ou tipo de retorno da classe A.
Na verdade, a classe B precisa fingir que a classe A nem sequer existe, ou o compilad or ir6. reclamar. Observe o seguinte
arquivo-fonte:
package cert;
class eeverage { i
Agora observe o segundo arquir,'o-fonte:
package exam. stuff;
import cert . Beverage,'
class Tea extends Beverage { }
Como voc6 pode ver, a superclasse (Beverage) est6 em um pacote diferente da subclasse (Iea). A declaragio import no alto
do arquivo Tea esti tentando (cruze os dedos!) importar a classe Beverage. O arquivo Beverage compila sem problemas,
mas, quando tentamos compilar o arquivo Tea, obtemos algo como:
Can,t access class cert.Beverage. Class or interface must be public, in same package'
or an accessible member c1ass.
import cert.Beveraget
Tezndo compila porque a sua superclasse, Beverage, tem acesso def ault e est6 em um pacote diferente. Fora usat nomes
de classes totalmente qualificados, o que abordaremos no Capitulo 10, existem duas coisas que vocd pode fazet pan
consertar isso. Voc6 poderia colocar ambas as classes no mesmo pacote, ou poderia declarar Beverage como publ ic, como
descrito na seg6o seguinte.
Dessa
Quando v_oc_e yrgm? ques.t6o com lp"gga complexa,.certifique-se de olhar os modificadores de acesso primeiro.
uma classe de f aul- t
,forma, se descobrir uma violagio de acesso (por exemplo, uma classe do pacote A tentando acessar
do pacote B), yoc6 saber6 que o c6digo nao vai compilat, entio nio precisa nem se dar ao trabalho de tentar entender a
I6gica. Afin"i,i;;ai; -as o que fLrr ro ..rr,.-po fazer aptova.Simplesmente marque a resposta 'A compilagio
"o
falha'e passe para a questao seguinte.
.{ge.sqg Pirblico Uma declaragio de classe com publ i c dd alo-das as classes, de todos os pacotes, acesso.d
^p^lavr^-chave
p_-ni;qersoJava QU) tdm acesso a uma classe priblica. No entanto, ndo
-.l"sS.e pfbliC?. Em outras palavras, lg/a.s as classesdo
se esquega, de que, gg.ruLa-ela.s;g,pgbLq1.qqe estlyer terrta.ndo usar estiver em um pacote diferente do da classe que este
screrrendq vocgggd.U_ree!ca!--6 1r-nper!al?-@s€p'$!9.
No exemplo da segio anterior, talvez ndo queiramos colocar a subclasse no mesmo pacote que a superclasse. Para fazet o
c6digo funciona4precisamos adtcionar apalavra-chave pu-b1 ic na frente da declaragdo da superclasse @everage), da
seguinte forma:
n: nlz:na narf .
Isso modifica a classe Beverage para que ela se torne visivel a todas as classes em todos os Pacotes. Essa classe agora pode set
instanciada a partir de todas as outras classes, e qualquer classe est6 agora livre para subclassific6la (estender a partir dela) - a
ndo ser que a classe esteja marcada tamb6m com o modificador f inal .J5. falarcn:.os sobre isso.
ClassesFinaisQuandousadanadeclaragilodeumaclasse,ap.flV3;3;9bave-final significaqueaclasseemquestdonao
gg[gper subcla,ssificada' Em outras palavtas, ne*gblqggclr-g1a.ss-eppd-ejas.rar,s aslenJef
@erdar de) uma clasie f ina1, e
9gdWe1l9111aivade faz€-lolhe dard um erlo de compilag{q
Entio por que voc€ sequer m arcaiauma classe como f inal ? Afinal de contas, isso n6o viola to da a nogd.ode heranga
presente nas linguagens orientadas a obietos? !,oc€ s6-5!pv_g marc4r gp.qa.c,lasse como f ina] seprecisar de uma garantia
.
4lselu-ta dequ.g.ngghurlr dos m6todos dessa classe jamais vai ser substituido. Caso ieo c6digo seja profundamente
dependentedaimplementagiodecetosm6todos,usarfinal lhedar6asegur"ogad.qoe-ningu6mpoder;,modtficata
irslegrent?g5g .qem vo_qQ. s_4!e1.
IJ-q1!-e1e{c!o de se ter.classe$nao--f;pa1 6 neste cgn6rio: imagine que voc6 encontrou um problema com um m6todo
em
9$a,alasseque.qs?i usando, mas nio tem o c6digo.fionte. A;;!g1, vo;6 nio pode.mo-difiear a ionte para melhorar o m6todg,
tr-3-sj9g9:s.t9,!der a-classe e substituir o m6todo em questio na sua nova rob.lur.., e simplesmenl llr". u subclasse em
tg-,{1s31og;r-s10es em gue a superclasse original for esperada. No entanto, se a classe for f inal,
entao nao h6 nada que voc6
pcissa fazer.
O c6digo acima iti compilar sem problemas. Entretanto, se voce tentar instanciar um Car em outro corpo de c6digo,
receber6 eros de compilagio como o seguinte:
Examinaremos os m6todos abstract com mais detalhes mais adiante neste obietivo, mas lembre-se sempre de que, sq
mesmo um s6 m6todo fqr abs,tract,.toda a classe dever6 ser declarada como abstract*Um -m6todo alQstracL
clntamirra !o4a_a.!q!ma: Vocd pode,:ro entaoto, coloc-ar m6todos nio-abstract em uma classe abs-F-.ract' Por
.*.-plo, rro.6 poderia ter m6todos com implementag6es que nio devem mudar de acordo com o tipo deCx,tais como
get|olorO ousetPriceO.Aocolocarm6todosnZo-abstract emumaclasseabsEract,vocediatodasas
subclasses concletas (e concreto significa apenas nio-abs!.5agt) implementagSes de m6todos herdadas. A boa noticia 6
que as subclasses concretas herdam funcionalidad.r, . preiiii- implementar apenas os m6todos que definem
comportamentos especificos da subclasse.
(A prop6sito, se voc6 achou que usamos a expressio raison d'etre fora de contexto, anteriotmente, nio nos mande e-mail'
de certificagio PM Progr madores')
Queremos ver uoc6 colocarumra expressio dessas em um livro
programar com tipos de classes abstract (incluhdo interfaces, que serio discutidas mais adiante neste capitulo) permite
q..e voc6 tire vantagem do polimorfismo, e lhe d6 o maior grau possivel de flexibilidade e extensibilidade. Voc6 aprender6
mais sobre polimorfismo no Capitulo 2.
Nig €pqssiv€l mar:catrtm^classe como abstract e f inaf ao mesmo tempo. Elas t6m significados quase opostos'
Uf"C -.laeSe-abgLract-'p:ecisa-ser subclassificada, enquanto que uma classe f inaf nlo deve ser subclassificada. Se voc€
efinal,usadosparaumadeclatzglodeclasseoum6todo,oc6digo
"it"..rrfombinagiodemodificadoresabstract
nio ir6 compi-lar.
Exercfcio 1 - 1
nrrhtic
vuvr+v ehsl-recf class pruit{ /* insira qualquer c5digo que desejav */I
2. Ciea subclasse em um arquivo separado, da segrinte maneira:
import food.Fruit;
JAVAS II
class Apple extends Fruit{ ,/* insira qualquer c6digo que desejar */}
3. crie um diret6rio chamado food dentro do diret6rio configurado no seu class path.
4' Tente compilat os dois arquivos. Se quiser usar a classe Apple, certifique-se de colocar o arquivo Fruit.class no
subdiret6rio food.
Al .
Obietivo poro o CertificoE6o
void bounce( );
void setBounceFactor(int. bf) t
I
i
O que a classe
precisa fazer
Class Tire implements Bounceable
public void bounce( ) i... ] (todos os
public void setBounceractor(int bf)t )
mdtodos pre-
cisam ser
implementa-
dos e defini-
dos como
p{rblicos)
l-l A Re/ogdo Entre /nferfoces e C/osses
Figuro
Considete uma interface como uma classe 100%o abstract. Como uma classe abstract, a interface
define m6todos
abstract com a forma,
abstract void bounceo; // Termina com ponto-e-virgu1a, em vez de chaves
Mas, enquanto uma classe abstract pode definir tanto m6todos abstract quanto ndo-abstract,
r*najnferfacp
gggg.dt ter m€todos abstr-aqt. outro ponto em que as interfaces diferem das classes abstract 6 que elas
12 Copftulo 1 : DecloroE6es e Controle de Acesso
I Todososm6todosdeinterfacesioimpliciamentepublic eabstract.Emoutraspalavras'vocenaoprecisadigitar
realmente os modificadores publ ic ou abstract, na declaragio do m6todo, mas mesmo assim ele sempre ser6
PubIic eabstract.
,.' I Todasasvariaveisdefinidasemumainterfacedevemserpublic, static e f inal -emoutraspalavras,as
intetfaces s6 podem se declarar constantes e neo vari6veis de instAncia.
; I Osm6todosdeinterfacesn6opodemser static'
a Jaque os m6todos de interface sio abstract, nio podem ser marcados como f inal, native, strictfp ou
Examinamos z declaragdoda interface, mas agora nos aprofundaremos nos mdtodos de uma interface:
i
por6m, digitar os modificadores public e abstract nos m6todos 6 redundante, i6 que todos os m6todos de
interface slo implicitamente publ ic e abst,ract. Dada essa regta, vocd pode ver que o c6digo a seguir 6 exatamente
equivalente a interface antenor:
void bounce O ;
.,, public void bounce O ;
abstract void bounce O ;
: Fubf ic abstract void bounce O ,'
final voj-d bounceO; // f1-nal- e abstract jamais podem ser usados juntos' e
Ao colocar as constantes diretamente n ainterface,qualquer classe que impleme ntar aintefiace ter6 acesso
direto is
constantes, como se as tivesse herdado.
Yo4-ef9gi.tilg lembrar de- uma reg,ra fundamental para constantes de interfaces. Elas devem sempte se1
nrrhlin et=f i^ +inal.
Isso parece simples, certo? Afinal, as constantes de interfaces nio sio diferentes de quaisquer outras constantes acessiveis
publicamente, entio, obviamente elas precisam set declaradas como public, sLatic e f inal-. Mas, antes de pular o
restante desta discussio, pense nas implicag6es:.pelo.f3r!o dg_ a.s.constantes de interfaces serem definidas em uma
int-e-ttlqgrplas4ig.precig-arnsel.deg!4rqdascomopubflc,static oufinal.Flasdevemserpublic,
g!flq-*i.c g-f inal- ma's voc6 n6o ptecisa declarS-las explicitamente dessa maneiri. Assim como os m6todos de
interfacessiosemprepublic eabstract,independentementedevoc6indicarissoounionoc6digo.qualgref
v"*gttf"d€ggde."9!9'-9.1F'4 tnre{-faqe-deJe sskgsg*4ltaBe-tlle 6 uma constante publ i c . veja t. -'o.e .onr.grre perceber
-
o problema com o seguinte c6digo (assuma que sdo dois arquivos separados):
interface Foo {
int BAR = 42,.
void go O ;
)
l
Vocd nio pode alterar o valor de uma constante! I-lma vez que o valor tiver sido atribuido, nunca poder6 ser alterado.3!
qqP"iflg gtgr+-e.{?-ngptpgsaintedacq(onde-a constante for de't'ua&),
Rg!-tag-tofr-g1"... qlr. " .i1irr.., implementando
ggdglgaceg.la;!9 e us6-.!g, mas como um valor somente de leirura. Assim,l-atritdgao geR = 27 rdo complar6".
Procare defnigdes de intet'ace que utabe/egam constantes, pordm, sem usar exp/icitamente ot modifcadnres necessiriot. por
exenp/0, os
aidigos a seguir sio todos iddnticos:
vimos o que significa usar um modificadot em um a declangdo de classe, e agora veremos o que significa modificar uma
J6
declatagdo de um m6todo ou uma vari6vel.
Os m6todos e as vari6veis de inst6ncias (nioJocais) sio conhecidos coletivamente como membros. Voc6 pode modificar
um membro que tenha tanto modificadores de acesso como modificadotes que nio se referem a acesso, e vocd tem mais
modificadorei para escolher (e combinar) do que quando est6 declarando uma classe.
Modificadores de Acesso
Pelo fato de os m€todos e vari6veis normalmente receberem controle de acesso exatamente da mesmas forma, abordaremos
ambos nesta segio.
Enquantoumaclasrcs6podeusardoisdosquatroniveisdecontoledeacesso(default oupublic),osmembros
podem usar todos os quatro:
r public
I protect
I default
I private
A proteg6o padrdo6 o que voc€ recebe quando nio digita um modificador de acesso na de clatagdo do membro. Os tipos de
controledeac.ssodefault. eprotect t6mcomportamentosquaseidenticos,excetopolumadiferengaqueser6
mencionada posteriormente.
E crucial que voc6 saiba tudo sobre o controle de acesso par o exzme. Haver6 uma boa quantidade de Perguntas pataas
qoais voc6 dever6 usar o seu conhecimento sobre controle de acesso. Algumas quest6es testam v6rios conceitos de
controle
de acesso ao mesmo tempo, enrio o desconhecimento de uma pequena parte que seja do assunto poder6lhe custar uma
questio inteira.
O que signific a em uma classe ter acesso a um membro de outra classe? Por agora, ignore quaisquer
o fatode o c6digo
diferengas entre m6todos e vari6veis. Se a classe A tiver acesso a um membro da classe B, isso significa que o membro da
classe B est6 visivel para a classe A. Quando uma classe nZo tem acesso a ouffo membro, o compilador vai brigar
com voc6
por tentar acessar algo que voc6 nio deveria nem saber que existe!
O primeiro tipo de acesso ocorre quando um m6todo de uma classe tenta acessar um m6todo ou uma vari6vel de outra
.1"..., lrsr.rdo o operador ponto (.) para invocar um m6todo ou obter uma vari|veL Por exemplo:
class Zoo {
public String coolt"tethod ( ) i
return "Wow babv";
class Moo {
,'
nrrl.r'lin .___ rrqpZ-
rrnid *-_-\zoo(,) t
Zoo z = new ZooO;
/ / se a linha anterior compilar, Moo terS acesso
JAVA 5 15
// d classe zoo
/ / Mas'.. . ser6 que tem acesso a coolMethodO ?
System.out.println("A Zoo says, " + z.coolMethod() );
/ / A linha anterior funciona porque Moo pode acessar o
/ / mAraAn nrrl-r'] i a
l
O segundo tipo de acesso refere-se a quais membros de uma supetclasse (se 6 que existem) uma subclasse pode acessar
aftav€s da heranga. Nio
estamos querendo saber se a subclasse pode, digamos, invocar um m6todo para uma instincia da
supetclasse (o que seria aPenas um exemplo do primeiro tipo de acesso). Em vez disso, queremos saber se a subclasse pode
berdarum membro da sua superclasse. Lembre-se de que se uma subclasse herdaum membro, 6 exatamente como se a
subclasse tive sse declarado o membro ela mesma. Em outras palavras, se uma subclasse herdaummembro, efltao ela tem
esse membro.
class Zoo {
nrrhl i n (f ri na nnnl Morhnrl
uvvrrrLuarvs /\ /\ It
l
class Moo extends Zoo {
public void useMyCoo1MethodO {
/ / Ser6, que uma instAncia de Moo herda coolMethod ( ) ?
System.out.println("Moo says, " + this.coolMethodO );
/ / A J-inha anterior funciona porque Moo pode acessar o
/ / m6todo public
// Ser6. que uma instAncia de Moo pode invocar coolMethodQ em
A Figura 1,-2 faz a comparagdo entre uma classe herdando um membro de outra classe, e acessando um membro de outra
classe usando uma refer€ncia de uma inst6ncia dessa classe.
Muito do controle de acesso (ambos os tipos) se concentra em se as duas classes envolvidas estao no mesmo pacote ou em
Pacotes diferentes. N6o se esquega, no entanto, q,te se apnipria classe A nio puder ser acessada pela classe B, ent6o nenhum
membro da classe A poderi, ser acessado pela classe B.
Vocd precisa saber o efeito de diferentes combinag6es de acesso a classes e membros (por exemplo uma classe padrao com
uma vari6vel pubJ- ic). Para descobrir issq primeiramente observe o nivel de acesso da classe. Se a pr6pria classe nio for
visivel a outra, entio nenhum dos seus membros ser6 visivel, nem mesmo se forem declarados publ ie. Depois de
confirmar que a classe est6 visivel, 6 uma boa id6ia observar os niveis de acesso nos membros individuais.
Membros Public
Quando um m€todo - ou vatiivel-membro - 6 declarado publ i c, isso significa que todas as outras classes,
independentemente do pacote ao qual pertengam, podem acessar o membro em questao (assumindo-se que a pr6pria classe
esteia visivel).
16 Copftulo 1 : Declorog6es e Conlrole de Acesso
goFast (
dostuff (
goFast (
)
Convertible
doThings( ){
Sportscar sc = new Sportscar( )t
sc.goFas!( );
)
Driver
doDriverSEuff ( ){
Sportscar car = new Sportscar( )t
car.goFast( );
Convertible con = new Convertible ( ) ;
con.goFast( ),
)
Como vocd pode ver, Goo e Sludge estao em pacotes diferentes. Entretanto, Goo pode invocar o metodo em Sludge sem
problemas, porque t^nto a classe Sludge quanto o seu metodo test.It ( ) est6o marcados como public.
Pan uma subclasse, se um membro da sua superclasse for declatado pub 1 i c, a subclasse herda esse membto,
independentemente de se ambas as classes estarem no mesmo pacote ou nio:
JAVA 5 17
n:^Lrd6
^arf.
A classe Roo declara o membto doRooThings ( ) como publ i c. Assim, se criarmos uma subclasse de Roo, qualquer
c6digo presente nessa subclasse Roo poderi chzmar o seu pr6prio m6todo doRooThings ( ) herdado.
package notcert; / / NEo 6 o pacote em que Roo se encontra
import cert . Roo;
class CIoo extends Roo {
public void testcloo ( ) {
System. out . println (doRooThings ( ) ) ;
l
]
Repare no c6digo anteriot que o m6todo doRooThings ( ) 6 invocado sem a necessidade de prefixi-lo com uma
referdncia. Lembre-se de que se voc€ vir um mdtodo invocado (ou uma vad6.vel acessada) sem o operador ponto (.), isso
sigrrifica que o m6todo ou a vari6vel pertence i classe onde voc6 l'ru esse c6digo. Tamb6m significa que o m6todo ou a
vai6velest6 sendo implicitamente acessado(a) usando-se arefer€ncia this. Assim, no c6digo anteior,acharnadaa
doRooThings ( ) na classe Cloo poderia tet sido escrita como thi s . doRooThings ( ) . A refer6ncia thi s sempre
se refere ao objeto sendo executado atualmente - em outras palavras, ao objeto que esteja rodando o c6digo quando voc6
v6 a refer€ncia thi s. Pelo fzto de a rcfetdncia thi s ser impiicita, voc6 n6o precisa prefixar o seu c6digo de acesso a ela, mas
se o fizer nio havet6 nenhum problema. Alguns progtamadores o incluem p ar^ torn t o c6digo mais f6ci1 de l er p^ta,
programadores iniciantes ou desconhecedores deJava.
Al6m de poder invocar o m6todo doRooThings O para si mesmo, o c6digo de alguma outta classe pode chamar
doRooThings ( ) para uma instincia de Cloo, da seguinte forma:
class roon {
public static void main(StringtJ argrs) {
Membros Private
Membros marcados como private ndo podem ser acessados por c6digo em nenhuma ouffa classe que nio aquela na qual
o membro private foi declarado. Vamos fazer uma pequena modificagio na classe Roo apresentada em um exemplo
antedot.
package cert;
public class Roo {
private String doRooThings ( ) {
/ / Imagine o c6digo divertido que entra aqui , mas apenas
/ / a c]-asse Roo sabe disso
ratlrrn rrfrlnrr.
O m6todo doRooThings ( ) agora 6 private, entao nenhuma outra classe pode us6-lo. Se tentarmos invocar o
m6todo a partir de qualquer outra classe, teremos problemas:
1 I Copitulo 1 : DecloroE6es e Controle de Acesso
package notcert;
i mn^rf
+rrryv! e ^6rf D^^.
cl-ass useAr{oo t
public void testlt o tt
Roo r - new RooO; // Ate aqui, tudo bem; a classe Roo 6 prlblica
qvcfam
^,,f
nrintln (r.doRooThingsO ) i // Erro de compilaqdol
I)
.I
.l
O m6todo doRooThings ( ) agora est6 fora do alcance de todas as subclasses, at6 mesmo aquelas que esteiam no
mesmo pacote que a superclasse:
l
Se tentarmos compilar a subclasse Cloo, o compilador tet6prazer em apresentar um erro parecido com este:
?javac Cloo.java
Cloo. java:4 : Undefined method: doRooThings o
System. out. println (doRooThings ( ) ) ;
1 error
AO TRABALHO
Enboralhe s/a penaitido marcar uaiit'eis de instdnciat coma publ ic, napnitica qaase sempre d melhor nanter todas as uaridueis como
private ou protect. Se as uaidueit precisarem vr modficadat, defnidas oa /idas, os programadores deuem usar nitodos de ausso
public, para que ctidigos em quaisquer outras classes tenhan de pedirpara obter on defnir uma uariduel (passando atrauds de *m rudtodo),
em ueqde acerd-/a diretamente. Os ndtodos de acesso conpatiueis con JauaBeans t€m aforna get<noneDaPropriedade) ou, para booleanos,
f
is<noneDaPropriedade> e set<nomeDaPropriedade>, efornecem um lugar onde uocd pode uerifcar e oa ua/idar antes de retomar ou
JAVA 5 19
modficar um ualar.
Sem usaprotepdo, a uari,iuel weight ('pesa') de an objeto Cat, por exempl0, poderia ur defnida nmo tlm nilmem negatiuo caso o cddigo
in@npiado tenba acesso direto i uaiduel publ ic, coml em somecat . weight = -20. Mas un mdtodo dz acesto, setweight
(int wt), podeia uerifcar se o nilmem d @ropiado. (Ok, tudo isso d especulagdo, mat estamos partindo do prina?io de qae un peso negatiuo
poderia ser in@ropriado para am gato. Ou ndo.) O Capitalo 2 divutinl esta prutu(Ao de dadot (enc@ulanento) com mais detalhes.
E possivel um m6todo private ser substituido por uma subclasse? Essa 6 uma pergunta interessanre, mas a resposta,
tecnicamente, 6 nio. Uma vez qve a subclasse, como vimos, nio pode herdar um m6todo private, ela, portanto, nao
pode substituir o m6todo - a substituigio depende da heranga. Abordaremos as implicag6es disso com mais detalhes mais
adiante nesta segio, bem como no Capitulo 2,mas,por agora basta lembrar-se de que um m6todo marcado como pri -
vate nao pode ser substituido. A Figura 1-3 ilustra os efeitos dos modificadores publi-c e private em classes de
um mesmo ou de diferentes Dacores.
SportsCar
goFast ( ) {...}
dosEuff ( ) {
goFast ( ),
]
Convertible
Subclasse
Driver
doErrivy'sruff( ){
Spo9(sCar car = new Sportscar( );
c9r'.gd(ast( );
co\eZliUfe con = nehr convert.ible( );
l'
r'ffit"tt
Figuro l-3 Efeifos do ocesso plblico e privodo
woiri festTr () {L // O
/ /v faro dc nio haver modificador
LsLv
)
Em um outro arquivo de c6digo-fonte voce tem o seguinte:
package somethingElse ;
imnarf
+LLrFv! e
aarf i f i nrf i nr ntharr-l rae.
class AccessClass {
static public void main(Stringtl args) {
Othercl-ass o = new OtherClassO;
o. testIt O ;
j'
Como pode ver, o mdtodo testlt
( ) do ptimeiro arquivo tem acessopddr1o (ot seja, de niveldopacote). Repare tambem
que a classe OtherClass se encontra em um pacote diferente de AccessClass. Serl que AccessClass poder6 usar o m6todo
t
t e s t f O ? Vai causar um erro de compilagdo? Ser6 que o Daniel vai se cas ar colr, aFrancesca? Nio perca os pr6ximos
capitulos.
No method matching testlt O found in class
certification. Othercfass. o. testlt ( ) ,'
Pelosresultadosacima,voc€podeverqueAccessClassniopodeusarom6todotestlt O deOtherClassporque
test.It O temacessopadtio,eAccessClassnioest6nomesmopacotequeOtherClass.Assim,Accessclassn6opodev6-
la, o compilador reclama, e n6s nao temos nem id6ia de quem sejam Daniel e Ftancesca.
Os comportamentos def ault e protect diferem apenas quando falamos sobre subclasses. Se a palavra-chave
protected fotusadaparadefinirummembro,qualquersubclassedaclasseque fazadeclangdopodeacess6-lo atrauisda
heranga. N6o faz diferenga se a superclasse e a subclasse estao em pacotes diferentes, o membro da superclasse protect
ainda estard visivel para a subclasse (embora visivel apenas de uma formabastante especiftca, como veremos mais adiante).
Isso contrasta com o comportamento paddo,que nio permite que uma subclasse acesse um membro da superclasse, a nio
ser que a subclasse esteia no mesmo pacote que a superclasse.
Enquanto que o acesso padrio nio estende nenhum considetagdo especial is subclasses (ou voc6 est6 no pacote ou nio
esti), o modificador protected respeita a relagao parent-chjld, at6 mesmo quando a classe child se desloca (e iunta-se d
um novo pacote). Assim, quando pensar em acessopadrdo,pense em restrig6es depacote. Sem exceg6es. Mas, quando Pensar
em protect, pense em?acnte + kids.IJma classe com um membro protect esti marcando esse membro como tendo
acesso de nivel do pacote pata todas as classes, mas com uma excegio especial para subclasses fora do pacote.
Mas o que significa uma subclasse de fora do pacote ter acesso a um membro (parent) da supetclasse? Significa que a subclasse
herda o membro. Nio significa, no entanto, que a subclasse de fora do pacote possa acessar o membro usando uma refer6ncia a
umainstinciadasuperclasse.Emoutfaspalavfas,protecL =henn7a,Protect niosignificaqueasubclassepossatratar
o membro protect da superclasse como se ele fosse publ ic. Assim, se a subclasse de fota do pacote obtiver uma
refer6ncia i superclasse (cdando, por exemplq uma instAncia da superclasse em algum lugar no c6digo da subclasse), a subclasse
nio pode usar o opetador ponto na refet€ncia i superclasse para acessar o membro protec. Para uma subclasse de fora do
pacote, um membro protect poderia da mesma forma ser def aul-t (ou mesmo privado), quando a subclasse est6
usandoumarefer€nciaisuperclasse.Asubclasses6podeveromembroprotect atrav6sdaheranga.
Est6 confuso? N6s tamb6m. Agriente firme e tudo ficar6 claro com a s6rie de exemplos segrintes. (E ndo se Preocupe, na
verdade, nio estamos confusos. Estamos apenas tentando fazt-lo se sentir melhot caso voc6 esteia confuso. Sabe, tipo nio
tem problema se voc€ estiver achando que nada faz sentido, e ndo 4 culpa sua. Ou serd que 6? <insira isada mal€vola aqui>)
Detalhes de protect
Vamos dar uma olhada em uma vari6vel de instincia protect 0embre-se de que uma vari6vel de instdncia 6 um
membro) de uma superclasse.
package certif ication ;
public class Parent {
protected int x = 9; // acesso protect
I
O c6digo acima declara a vari6vel x como protected. Isso acersiael a todas as outfas classes dentm do Pacote
^totn
certification, bem como herdduelpor gttaisquer subclasses defora do pzcote. Agora vamos criar uma subclasse em um pacote
JAVA 5 21
O c6digo acima compila sem problemas. Repare, no entanto, que a classe Child estd acessando a vari6vel protect atrav6s
dahetanga. Lembre-se, sempre que falarmos de uma subclasse ter acesso a um membro de uma superclasse, podetiamos
estar falando de a subclasse herdar o membro, e nio simplesmente acess6-lo atrav6s de uma referdncia a uma ins tdtcia da
supetclasse (que 6 a forma como qualquer ouua nio-subclasse o acessaria). Repare no que acontece se a subclasse Child (fora
do pacote da superclasse) tentar acessar uma variivel protect usando uma referencia i classe Parent.
package other,.
import certif ication. Parent ;
class Child extends Parent {
.i^..^ir !^^FTl- () {
^,,L1
yulf fu vvfu LsDLru \/ L
l
O compilador alegtemente nos mostra qual 6 o problema:
9'i:rr=n -du . nl- ho- /alai
vurrLr/ I .l
Lrlf fu. i --'-
Jqva
other/Child.java:9: x has protected access in certification.Parent
Svsl-em otrt nrinf ln($X in naranf
yqlgllur9-y.^l' iq rt r n v\.
;;:.*belecemos que um membro p ro t e c t tem, essencialmente, acesso de nivel do pacote ou padrio a todas as classes,
^,u
exceto vimos que as subclasses de fota do pacote podem herdar um membro prot.ect. Finalmente, j6vimos
as subclasses.J6
que as subclasses de forado pacotenao Podem usarumafefer6nciadi superclasse paraacessarum membropratecl. Pera
uma subclnsse deforq do pacotq o membro protect stf pode ser acessado otraaes da heranqa.
Ainda h6 mais uma questZo que nao consideramos... Q"ul 6 a apar€ncia de um membro protect para outras classes que
tentem usar a subclasse de fora do pacote para obter o membro protect da superclasse que foi herdado pela subclasse?
Por exemplo, usando as nossas classes Parent/Child anteriores, o que acontece se uma outra classe - digamos, Neighbor -
do mesmo pacote que Child (subclasse) tiver uma refer€ncia a uma instincia de Child e queira acessar a vari6vel-membrox?
Em outras palavns, como esse membro protect se comporta depois que a subclasse o herdou? Ele mant6m o seu
status de protect, de forma tal que as classes no pacote de Child possam v6Jo?
Nio! Depois que a subclasse de fora do pacote herda o membro protect, ele (conforme herdado pela subclasse) torna-se
private para qualquer c6digo de fotada subclasse, com a excegio das subclasses dessa subclasse. Assim, se a classe
Neighbor instanciat um obieto Child, entdo mesmo se Neighbot estiver no mesmo pacote que Child, Neighbor nlo teri
acesso i vari6vel x herdada (mas protect) por Child. Resumo da hist6ria: quando uma subclasse de fora do pacote herda
um membto protect, esse membro torna-se essencialmente private dentro da subclasse, de forma tal que apenas a
subclasseeassuassubclassespodemacess6lo.AFigural-4ilustraoefeitodoacessoprotect sobreclassesesubclasses
no mesmo ou em diferentes pacotes.
Carambal Com isso terminamos protected, o modificador mais incompreendido emJava. Novamente, ele s5 6 usado
em casos muito especiais, mas pode ter certezade que aparecer6 no exame. Agora que j6 abordamos o modificadorpro-
tected, passaremos para o acesso padrio, uma molezacomparado a protect.ed.
22 Cqpitulo 1 : Declorog6es e Controle de Acesso
Detalhes de Default
Vamos comegar com o comportamento padrd.o de um membro de uma superclasse. Modificaremos o membro x de Parent
panrorn6-lo def ault.
package certif ication;
public class Parent {
int x = 9; / / Aus€ncia de modificadores de acesso
/ / indica acesso padrSo (de pacote)
)
Repare que nio colocamos um modificador de acesso na ftentedavai|vel x. Lembre-se de que, se voc€ nio di.grtar um
modificador de acesso antes da decla ragdo de uma classe ou um membro, o conrole de acesso 6 o padtdo, o que significa de
nivel do pacote. Agora tentaremos acessar o membro padrdo da classe Child que vimos anteriormente.
Pacote A Pacote A
goFast( )t ]
Convertible convergible
l--D'i'"'_l
T^^t,
I er," g t.
Pacote B
Convertible f c;;ctb;l
[H-el*l
f *1"".
Chave:
E-tr-ll
dofhings ( ){
r------------1
Sportscar sc = new Sportscar( ), I dot'tore( )( f
sc.goFast( ); I sorast( );I
l It
L-.r-F:'=*[
I.
i
)
O c6digo-fonte acima compila sem problemas, e a classe Child roda e exibe o valor e x. Basta se lembrar de que os membros
padrio ficam visiveis par:-as subclasses apenas se elas estiverem no mesmo pacote que a superclasse.
]
Pode ter certeza de que qualquer vari6vel local declarada com um modificador de acesso fieo vai compilar. Na verdade. s6
existe um modificador que pode ser aplicado avari6veis locais f inal_.
-
Isso termina a nossa discussio sobre modificadores de acesso de membros. A Tabela 1.-2 mostratodas as combinag6es de
acesso e visibilidade; 6 uma boa id6ia passar algum tempo estudando-a. Em seguida, vamos passar para os outros
modificadores (nio-referentes a acesso) que voc€ pode apltcar a declarag6es de membros.
A partir de qualquer classe que nio seja Sim Nio N6o Nio
uma subclasse e esteia fora do pacote
declaraE6es de classes anteriormente neste capitulo. Mas ainda temos de dar uma ripida olhada em trans ient, syn-
chroni zed, nat ive, strictf p, e depois uma longa olhada no grande modificadot - stat ic.
Veremos primeiro os modificadores aplcados a m6todos, seguidos pelos modificadores aplicados a vari6veis de instAncias'
Fecharembs esta segao com uma olhad" .- .orno stat ic funciona quando aplicado a vari6veis e m6todos.
M6todos Final
A palavra-chave f inal impede que um m6todo possa ser substituido em uma subclasse, e frequentemente 6 usada para
forg"r os recursos API de om m6toio. Por exemplo, a classe Thtead tem um mdtodo chamado i sAl- ive ) que verifica se
(
om^ determin adathread atndz est6 airva. Se voc6 estender a classe Thread, no entanto, realmente nio h6 como vocd sozinho
implementar corretamente esse m6todo (ele usa c6digo nativo, s6 para citar uma das taz6es), entao os elaboradores o
to-"rrr., f inal-. Assim como nio 6 possivel subclassificar a classe String (porque precisamos confiar no comPortamento
Essa
de um objeto String), vocd nio poder6 substituir a matorizdos m6todos nas bibliotecas de classes fundamentais.
restrigio quanto a soUstitoigao propicia boa seguranga, mas voc6 deve us6-la com muito cuidado. Impedir que uma
atravds
subclasse iubstitua um metodo invatida muitos dos beneficios da orientagao a obietos, incluindo a estensibilidade
do polimorfismo. Uma declaragio de m6todo f inal tipica se pareceria com isto:
class SuperClass{
public fj-na1 void showSamPle O {
System. out . println ( "One thing . " ) ;
E v6lido esrender SuperClass, umavez qwe a classe ndo esti marcada como f inal-, mas nio podemos substituit o mdtodo
f inaf showsample ( ) , como o seguinte c6digo est|tentando f^zetl
class SubClass extends SuperClassi
public void showSampleO { // Tentando substituir om6todo
/ / f:-na:-- da suPerclasse
System. out . println ( "Another thing . " ) ;
Se tentar compilar o c6digo acima, voc6 receberi uma mensagem como esta:
?javac FinalTest.java
FinalTest.java:5: The method void showsampleO decfared in class
subclass cannot override the final method of the same signature
declared in cl-ass SuPerClass.
Final methods cannot be overridden.
public void showSample O { }
1 error
Argumentos Final
Os argumentos de m6todos sio as declarag6es de varidveis que aparecem entre par€nteses na declatagio de um m6todo. Uma
declaragdo de m6todo tipica, com multiplos afgumentos, se Parece com o seguinte:
Argumentos de m6todos sio essencialmente o mesmo que variiweis locais. No exemplo_anterior,. as vari6veis
f ileNumber recordNuniber seguem todas as regras aplicadas avari6veis locais. Isso significa
e que elas tamb6m
podem ter o modificador f inal-:
public Record getRecord(int fileNumber, final int recNumber) { }
Nesteexemplo,avartfivelrecordNumber 6declaradacomofinal,oquesignificaobviamentequeelanlopoder6ser
modificada ientro do m6todo. Neste caso, "modificar" significa atribuir um novo valor d vari6vel. Em outras palavras, um
argumento f inal deve manter o mesmo valor que o pardmetro tinha quando foi passado para o m6todo.
M6todos Abstract
Um m6todo abstract um m6todo que foi declarado (como abstract) mas ndo implenentado. Em outras palavras, o
6
m6todo nio cont6m nenhum c6digo funcional. E, se vocd se lembrar da segio "Classes abstract", uma declaraqio de
m6todo abstract neo tem nem sequer chaves onde um c6digo de implementag6o pudesse ser colocado, terminando,
JAVA 5 25
emvez disso, com ponto-e-virgula. Em outras palavras, eIa ndo tem uru corpo de ndtodo. Voc6 marca um m6todo como
abstract quandoquerforgarassubclassesaforneceraimplementagloemquestao.Porexemplo,seescreverumaclasse
abstract Car com um m6todo goupHi 11 ( ) , voc6 poderia desejar forgai todos os subtipos de Car adefinir o seu
pr6pdo comportamento de goupHill ( ) , especifico dquele tipo determinado de carro.
public abstract void showSample O ;
Repare que o m6todo abstract termina com ponto-e-virgula emvezde chaves. E, inv,i,lido ter um rinico
m6todo
abstract. que seja em uma classe que n6o seia declarada explicitamente como abstractl Observe a seguinte
classeinvilida:
publi-c class I1lega1C1ass{
public abstract void dolt O ;
No exemplo anterior, goodMet.hod ( ) nio 6 abstract. Tr€s dicas diferentes lhe dizem que nio se trata cle um
m6todo abstract:
I O m6todo nio est6 marcado como abstract.
I A declaragio do m6todo inclui chaves, em vez de terminar com ponto-e-virgula. Em outras palavras, o m6todo tem um
corpo de m6todo.
I O m6todo inclui c6digo de implementagio.
Qualquer classe que estenda uma classe abstract deve implementar todos os m6todos abstract da superclasse. a
nio ser que a subclasse tambdn seia abst.ract. A tegra 6 a seguinte:
Aprimeirasubclasseconcretadeumaclasseabatraet deveimplernentattoda.sosm6todosabst,ract da
supetclasse.
Concretosignificaapenasnio-abstract,entao,sevoc€tiverumaclasseabstract estendendooutraclasseab-
stract, a subclasse abst.ract nio precisa fornecerimplementag6es para os m6todos abstract herdados. Mais
cedo ou mais tatde, no entanto, algu6m vai ctiat uma subclaise nio-abstract (em outras palavras, uma classe
que pode
serinstanciada), e essa subclasse teri de implementar todos os m6todos abstract de cima para baixo na 6rvore de-
heranga. O seguinte exemplo demonstra umaLrvorede heranga com duas classes abstract e uma concreta:
public abstract class Vehicle {
private String type;
public absrract void goUpHitl O ; / / M6tod.o abst.ract
public String gerType O { / / M6rodo neo-absrract
return t)4)et
l
public abstract class Car extends Vehicle {
public abstract void goUpHill O ; / / X:-naa abstract
nrrhl
yqvrf i a
v rrni
vvrq r{ dan--TLi
uvvqr rrrrrrgD
-^^ /\ \/ I
t
/ / C6digo especial para o carro entra aqui
26 Copitulo I : Declorocoes e Controle deAcesso
I
)
l
l
public class Mj-ni extends Car i
public void goUpHilI ( ) t
/ / c6digo especifico para o Mini subir ladeiras
i
]
Entio, quantos m€todos tem a classe Mini? Tr6s. Ela herda os m6todosgetType O e doCarrhings O , porque eles
sio pfblicos e concretos (nio-abstract). Mas, pelo fato de goupHill ( ) ser abst.ract na superclasse Vehicle, e
nunca ser implementado na classe Car (permanecendo abstract, portanto), isso significa que a classe Mini - como a
primeiraclasseconcretaabaixodeVehicle-precisaimplementatom6todogoupHill O.Emoutraspalavras,aclasse
Mini nio pode deixar a implementagio do m6todo abstract pa:.aapr6xjrr'a classe abaixo dela na 6rvote dehetanga,
mas a classe Car pode, porque Car, como Vehicle,6 abstract. A Figura 1-5 ilustra os efeitos do modificador ab-
stract sobre subclasses conctetas e abstratas.
absttact Car
startEngine( )
abstract gaFor'ward( )
abstract reverse( )
stop( )
abstract turn(int whichWay)
absEracE SW
startEngine( ) // opcional enable4wd( )
rd( | // requerido goForward( )
reverse( ) // requerido reverse ( )
turn ( int rdhichway) //requerido abst.ract gooffRoad( )
/
//
I
rttrn{\
vsLLL nin imnlamenEado
.lJrtyrvttt.
classBextendsA{
void foo(int r) { }
i
A classe B nio vai compilar porque ela ndo implementa o m6todo abstract herdado f oo O . Embora o m6todo
f oo int I ) da classe B parega ser uma
( implementagio do m6todo abstract da superclasse, na verdade €
simplesmente um m6todo sobrecarregado (um m6todo que usa o mesmo identificador, mas diferentes argumentos)' enteo
ele nio atende ao requisito de implementagdo do m6todo absLract da superclasse. Veremos as diferengas enre
substituigio e sobrecarga com mais detalhes no Capitulo 2.
Um m6todo nio pode nunca, jamais, ser marcado como abstract e f inal ao mesmo tempo, nem como ab-
stracL e private ao mesmo tempo. Pense um pouco - os m6todos abstract precisam ser implementados (o
JAVA 5 27
que na pr6tica significa serem substituidos por uma subclasse), enquanto que m6todos f e inal private
ndo podem
jamais ser substituidos por uma subclasse. Ou, dizendo de outra forma, uma designagio
abstract
significa que a
superclasse nlo sabe nada sobre como as subclasses devem se comportar no m6todo Lm questio,
enquanro que uma
designagio f ina l- significa que a superclasse sabe tudo sob.r como todas as subclasses
lpor -"1, afastadas qr.re estejam na
6rvore de heranga) devem se comPortarno m6todo em quest6o. Os modificadores ef abst;act inal- sio
praticamente opostos. Pelo fato de os m6todos private nio poderem nem mesmo ser vistos pof uma
subclasse
(_quanto mais herdados), eles tamb6m nio podem ser substituidoi, entio eles tamb6m
nao podem ser marcados como
abstract.
Finalmente,voc6precisasaberqueomodificadorabstract niopodenuncasercombinadocomomodificador
stat ic. Abordaremos os m6todos stat ic mais adiante .r.rt. obl.ti-ro,
mas, por zgora,bastalembrar que o seguinte
seria inv6lido:
M6todos Synchronized
A palavra-chave s)mchroni zed indica que um mdtodo s6 pode ser acessado por um thread de cada vez. N6s
discutiremos isso i exaustio no Capin lo 9, mas, por agora, tud; o que nos intereisa 6 saber que o modificador synchro_
nized s6podeseraplicadoamdtodos-ndoavari6viis,nemclasses,apenasam6todos.Umadeclarag6osynchronized
tipica se parece com a seguinte:
public synchronized Record retrieveUserlnfo(int id) { }
Voc6 precisa saber tambdm que o modificador synchroni zed. pode ser acompanhado por qualquer um dos quatro
niveis de controle de acesso (o que significa que ele pode ser usado juntamente com qualqueiu-" d", t C, palavras-chave
modificadoras de acesso).
M6todos Nativos
O modificador native indica que o m6todo est6 seodo implementado conforme aplataformz,freqtientemente e C.
Voc6 n6o precisa saber como usar m6todos nativos pano etim.,basta saber qu. tr-ii.re € um modificador (e, ponantq
uma palavra-chave reservada) e-que nat j-ve s6 pode ser aplicado a mdtodos ndo a classes, nem avai6veo,
- "p..rui
a
m6todos. Repare que o corPo de um m6todo nativo deve ser ponto-e-virgula
O (como m6todos abstraci), indicando
que a implementagao foi omitida.
M6todos Strictfp
Vimos anteriormente o uso de strictfp como modificadot de classe, mas, mesmo que voc6 nio declare uma classe
como str j-ct f p, ainda assim voc€ poderi declarar um m6todo individual como strictf p. Lembre-se de que
strictfp forgaospontosflutuantes(equaisqueroperagoescompontoflutuante)aaderirem aopadriolEil,ET54.
Com strictf p,6 possivel prever como os seus pontos flufuantes se comportarao,independentemente daplatafotma
subjacente na qual aJ\M esti rodando. O inconveniente disso 6 que, se aplitaformasubjacente for capazde srrportar 11ma
maior precisio, um mdtodo strictfp n6o poderd se beneficiar dessa capacidade.
Voc6 s6 deseiati estudar o IEEE 754 se precisa r de algo para aiud6Jo a cak no sono. Para o exame, no entanto, voc6
nio
ptecisasabernadasobrestrictfp al6mdasuautilidade,dofatodequepodemodificarumad,eclangdodeclasseoude
m6todo, e que uma vad6vel nunca pode ser declarada como strictfp.
Apenas para informagio, gostariamos de esclarecer como iremos usar os termos "argumento" e "parAmetro" ao longo
deste
Livro.
I argumentos Aquilo que voc6 especifica entre pardnteses quando est6 inuocantlowm m6todo:
dostuff("a", 2l; // estamos invocando dostuff, entdo a & 2 sao argumenros
I patdmettos Aquilo na assinatura dom6todo indica o que o m6todo deve receber quando forinvocado:
rraid daQt-rrff ,r /Qf-]-^
roirro9 s,
^ l-nt
l-r a)
-\ \f jI // estamos esperando dois
28 Copftulo 1 : Declorog6es e Conlrole de Acesso
I Tipo var-atg Quando declara um pardmeftovar-arg, vocd deve especificar o tipo do(s) argumento(s) que esse
p"ia-.t.o do seu m6todo pode recebet. @ode ser um tipo primitivo ou um tipo de obieto.)
I Sintaxe b4sica Para declarar um mdtodo usando um parAmetro vat-arg, voc€ escreve depois do tipo um sinal de
retic€ncias (...), um espagq e depois o nome do array que ir6armazenar os parimetros recebidos.
I Outfos pardmetros E v6lido tef outfos parametros em um m6todo que use um vaf-afg.
I Lirnites dos var-args O var-arg deve ser o riltimo parametro na assinatura do metodo, e voc€ s6 pode ter um var-arg
por m6todo.
Vejamos algumas declarag6es com var-argvdlidas e invilidas:
Vdlidas:
void doStuff (int... x) { } espera de 0 a muitos ints
como parAmetros
void doStuff2 (char c, int x) t ) / / es9era Primeiramente um char,
// e depois de o a muitos ints
void doStuff3 (Animal-... animal) { } tt de 0 a muitos Animals
Invdlidas:
void doStuff4(int x...) { } / / sin1caxe incorreta
void doStuffs(int . x, char... y) { } //mais deumvar-arg
void doStuff6 (String. . . s, byte b) { i / / var-arg tem de vir por rlltimo
Declarag6es de Construtores
EmJava, os obietos sio construidos. Sempre que voc€ cria um novo obieto, pelo menos um construtor 6 invocado. Toda
classe tem um construtor, e, se voc6 nio criar um explicitamente, o compilador vai criar um para voc€. Existem
toneladas de
regtas relativas aos construtores, e iremos deixar a discussio detalhada para o Capinrlo 2.Por agota,vamos nos concentrar
flas regras b6sicas de declaragio. Eis um exemplo simples:
class r.oo t
protected FooO { } / / este 6 o construtor de Foo
^^-6herr,
yvr
rrilida
)
A primeira coisa a se reparar 6 que os construtores se parecem um bocado com m6todos. Uma diferenga fundamental 6 que
11rrl .orrrtr.rtor n6o poie nonca, i"mais, ter um tipo de retorno.., Nunca! As declarag6es de construtores podem ter, no
entanto, todos os modificadores de acesso normais, e podem usar argumentos (incluindo var-args), da mesma forma como
os m6todos. A outra REGRA IMPORTANTE a se entender sobre os constmtores 6 que eles devem ter o mesmo nome
que a classe no qual sio declarados. Os construtores nio podem ser matcados como s t at i c (afinal eles sio associados
com instanciaminto de objetos), nio podem ser marcados como f inaL nem abstract (porque ndo podem ser
substituidos), Eis algumas declarag6es de construtores v6lidos e invalidos:
cJ-ass Eooz I
/ / consLrutores vSlidos
Foo2O { }
private Foo2 (byte b){}
Foo2 (int x) { i
Fnal/inf v inl-
v) t)
JAVA 5 29
/ / constTutores invSLidos
Declarag6es de Variiveis
Existem dois tipos de vari6veis emJava:
I Primitivos Um primitivo pode ser de oito tipos diferentes: char, boolean, byte , short , int ,
long, double ou f l-oat. IJmavez declarado, o seu tipo primitivo nio pode nunca ser modificado, embota na
maioria dos casos o seu valor possa se modificar.
I Vari6veis de refet€ncia As vari6veis de referdncia sio usadas para se referir (ou acessar) um objeto. Uma variavel de
referdncia 6 declarada como sendo de um tipo especifico, e esse tipo nio pode nunca ser modificado. Uma vari6vel
de
refer€ncia pode ser usada para referit-se a qualquer objeto do tipo declarado ou de tm subtipo do ipodeclarado (um
,
tipo compativel). Falaremos muito mais sobre o uso de uma vari6vel de referCncia para referir-se a tlm subtipo no
Capitulo 2, onde discutiremos o polimorfismo.
byte b,'
boof ean myBooleanprimit ive ;
l nf v
/ / decl-ara tr6s primi_tivos j_nt
Em vers6es anteriores do exame, voc€ precisava saber como calcular intervalos para todos os primitivos ava. Para o exame
J
atual, voc€ pode pular alguns detalhes, mas ainda 6 impotante entender que, para os tipos intiiros, a seqtidncia 6 (do
menot
para o maior) byte, short, int e long, e que doubles sio maiores do que floats.
Voc€ tamb6m precisar6 saber que os tipos num6ricos (tanto inteiros quaflto de ponto flutuante) sio todos assinalados, e
como isso afeta os seus intervalos. Pdmeiramente, vamos revisar os conceitos.
Todos os seis tipos num6ricos emJava sio feitos de um certo nrimero de bltes de 8 bits, e s2to assinalados,significando que
podem ser negativos ou positivos. O bit mais i esquerda (o digito mais significativo) 6 usado para representar o sinal, em
que 1 significa negativo e 0 sigmfica positivo, como mostrado na Figura 1-6. O resto dos bits ..p..r..rturn o valor. usando a
notaqao de base 2.
A Tabela 1-3 mostra os tipos pdmitivos com os seus tamanhos e intervalos. A Figura 1-6 mostra que com um byte, Por
exemplo, h6256 nimeros possiveis (ou 2). Metade deles sio negativos, e metade - 1 sio positivos. A faixa positiva tem
um valor a menos da que a negativo porque o niimero zero 6 armazenado como um ntimero bin6rio positivo. IJsamos a
t) voc€
f6rmula -2&it" -r) pa112- calcular o intervalo negativo, e usamos -l&its - - 1 pata o intervalo positivo. Novamente, se
b)'t' 21 -1
)15 a15 1
short t6
1nt 5Z
.r3r )3r 1
163 a63_L I
long oz+ L
O intervalo para nimeros de ponto flutuante 6 complicado de determinar, mas felizmente voc6 nZo precisa sab6-los para o
exame (embora 6 esperado que voc6 saiba que um double 64 bits, e um float armazena32).
^rmazen^
Para tipos booleanos nlohdum intervalo; um booleano s6 pode ser true ou false. Se algu6m lhe perguntar a
profundidade de bits de um tipo booleano, olhe bem nos olhos da pessoa e diga "depen de da mdqutna vktual" . F,la
ficar6 impressionada.
O tipo char (um caracter) cont6m um s6 caracter Unicode de 16 bits. Embora o coniunto ASCII estendido conhecido como
ISO Latin-1 precise de apenas 8 bits Q56 carzcteres diferentes), 6 necess6rio um intervalo maior pata rePresent^t car^ctetes
encontrados em linguas diferentes do ingl6s. Os caracteres Unicode, na verdade, sdo representados por ndmeros inteiros de
16 bits nio-assinalados, o que significa 216 tipos possiveis, que vio de 0 a 65535 Q\ -1. No Capitulo 3, voc6 aprender6 que,
pelo fato de um char ser na verdade um tipo de nrimero inteiro, ele pode ser atribuido a qualquer tipo de nfmero grande o
suficiente p^tz 65535 (o que significa qualquer coisa maior do que um tipo short. Embora tanto chars quanto
^rm^zenar
shorts sejam tipos de 16 bits, lembre-se de que um short usa l bitpara rePresentar o sinal, de modo que menos nfmeros
positivos sio aceit6veis em um short).
Object o;
Dog myNewDogRe f erenceVariable ;
Variiveis de lnstincias
As varidveis de instdncias sio definidas dentro da classe, mas fora de qualquer m6todo, e s6 stro inrcia\zadas quando a classe
6 instanciada. As vari6veis de instincias sio os campos que pertencem a cada obf eto fnico. Por exemplo, o seguinte c6digo
define campos (vari6veis de instAncias) par^name (nome), tide (tftulo) err:'ar'aget (gerente) para obf etos employee
(funcion4rio):
n l : cc E'mnl nrrao {
J6 abordamos os efeitos de se aplicar controle de acesso a vari6veis de instincias (funciona da mesma maneira que para
m6todos membros). Um pouco adiante neste capin:lo, veremos o que significa aplicar o modificador f inal oo t.ran-
sient zumavari|ve.Tdeinstincia.Primeiro,daremosumar6pidaolhadanadiferengaentrevari6veisdeinstAnciase
variiveis locais. A FiguraT-7 compara amaneirapelaqual os modificadores podem set aplicados a m6todos em contraste
com varidveis.
protected hr^|-a-l-aA
Fr vevv ues
private nrirr.f-a
transient
volatile abstract
synchronized
c|-ri al-fn
native
As declarag6es de varidveis locais nio podem usar a maioria dos modificadores que podem ser aplicados a vari6veis de
instincias, tais como public (ou os outros modificadores de acesso), transient, vo1ati1e, abstract ou
static, mas, como vimos anteriormente, as vari6veis locais podem ser marcadas como f ina1. E, como voc€ aprender6
no- Capitulo 3 (mas aqui vai um adianto), antes que uma vari6vel local possa ser usada,ela precisa ser inicialiTada.o- ,r-
valor. Por exemplo:
32 Copitulo I : Decloroc6es e Controle de Acesso
class Testserver {
public void loglnO {
int count = 10;
l)
l
l
Na maioria dos casos, voc€ vai iticiahzat umavariivel local na mesma linha em que a declarar, embora voc6 possa ainda ter
de rcintciall2|-la depois, no m6todo. A chave 6 se lembrar de que uma vari6vel local precisa s er iniciabzada antes de voc6
tentar us6-1a. O compiladot rejeitar6 qualquer c6digo que tente usar uma vari6vel local que ndo tenha recebido um valor,
porque - ao conffario das vari6veis de instAncias - as vadiveis locais n6o recebem valores-padrio.
Uma varidvel local nio pode ser referenciada em nenhum c6digo fora do m6todo no qual foi declztzdz. No exemplo de
c6digo anterior, seria impossivel referir-se dvari|vel count em qualquer outro lugar da classe exceto dentro do escopo do
m€todo logln ( ) . Novamente, nio queremos dizer com isso que o valor de count n6o possa ser passado pan fon do
m6todo para comegar uma nova vida. Mas a vari6vel que armazena esse valor, count, nio pode ser acessada depois de o
m6todo frnaltzar, como o seguinte c6digo inv6lido demonstra:
class Testserver {
public void logInO {
int. count = 10;
)
nrrl.r"l in rrnid dnenmafhina/int i \
'...-', t
count = i; // Ndo vai compilarl Nao 6 possivel acessar count
// de fora do m6todo logino
I)
)
,4
E possivel declarar uma.vari6vel local com o mesmo nome que uma vari6vel de instincia. Isso 6 conhecido como
sonbreamento, como o seguinte c6digo demonstra:
class Testserver {
int count = 9; / / Declara uma vari6vel de instAncia chamada count
public void logInO {
int count = 10; // Declara uma vari6vel 1oca1 chamada count
System.out.println("1ocal variable count is " + count),'
I
)
i
i
O c6digo acimaproduz a seguinte saida:
loca1 variable count is 10
class Foo {
int size = 27;
JAVA 5 33
hrr'|.\'l i r'^.i raf qi to
vvfu A Deuer-s\frrL (inf <.i zo\
ofzs/ I
IJu!fre ^ I
]
Entio vocd decidiu que - para melhor Iegibilidade - voc€ qu er dx ^o parrametro o mesmo nome que a vari6vel de instincia para
aqual o seuvalor se destina, mas como resolver a cotseo dos nomes? Use a palavrz-chavethis. Apalavn-chave this
sempre, sempre, semPre se refere ao ob,eto sendo executado atualmente. O seguinte c6digo mosta isso na pretica:
class Foo {
int size = 2'7 ;
public void setsize(int size) {
this. size = size ; / / L}ris. size significa a vari6vel de instAncia
/ / do objeto atual , slze. O valor de size
// d, direita 6 o parametro
l
l
l
Declarag6es de Arrays
EmJava, os arrays sio objetos qve m mriltiplas vari6veis do mesmo tipo, ou varilveis que sio todas subclasses do
^rmazen
mesmo tipo. Os attays podem arm^zeflar owprimitivos ou referdncias a obf etos, mas o pr6prio anay serS,sempre um
obieto no heap, mesmo se o array for declarado paraarmzrzerrar elementos primitivos. Em outras palavras, nio existe um
array primitivo, mas vocd pode criar um array de primidvos.
Para este obietivo, voc6 s6 ptecisar6 saber como declarar um array; n6s abordaremos a construgio e airttciilrzagdode artays no
Capitulo 3.
AO TRABALHO
Os analt sdo efcientes, mat muitat uerys uoci det/ard usar am dos tipos Collecion fu j ava . ut i 7 (incluindo HashlvIap,
ArrayList e TreeSet). At classes Collection oferecen maneiras na*fuxzueis de acessar am objeto (para inurgdo, apaganentl,
/eitara por diante) e, ao contniio dos ara1s, podem se expandir ou contrair dinamicamente i medida que uoci adiciona ou remoae
e assim
elementos. Existe un tipo Collection para ltma amp/a gama de necessidadu. Vocd precisa de una classifcagdo nipida? De /4n grupt de objetot
sen dup/icatas? De uma maneira dn acessar um par de nome-ualor? O Capituk 7 os aborda com nais detalbes.
Os arrays sio declarados informando-se o tipo de elementos que o alray iri arrnazefl r (um objeto ou um primitivo),
seguido por colchetes em um dos lados do identificador.
AO TRABALHO
Ao declarar ama referincia a anq,\ uoci deue sempre co/ocar o: colchetet do aralt imediatamente depois do tipo du/arado, em ueqde depois do
identfrcador (nome da uariduel). Dusaforma, qualqaer um qae leia o aidigo sabertlfaci/menh qaq por exenpl0, ke1 i uma referlncia a um
objXo de arrEt int, e ndo um pimitiuo int.
34 Copiiulo 1 : Declorog6es e Controle de Acesso
Podemos tamb6m declarar arrays multidimensionais, que, na verdade, s6o arrays de arrays. Isso pode ser feito da seguinte
maneira:
String[ J t ] [ ] occupantName;
String I J ManagerName [ ];
O primeiro exemplo 6 um array ridimensional (um array de arrays de anzys), e o segundo 6 bidimensional. Repare no
segundo exemplo, o quzltnz um par de colchetes antes do nome da vari6vel e um par depois. Isso 6 perfeitamente v6lido
para o compilador, provando mais uma vez que o fato de ser vdlido nio necessariamente indica que 6 bom.
Nanca d adlido inclair o tamanho do arral na saa declaragdo. Sim, n6s sabertos que uocd podefaryr isso em algumat outras linguagens, que i
a raqdo pela qual uoci podeni uer uma questdo ou duas que ineluam aidigo parecido com o seguinte:
fa1 dtferenga.
No Capitulo 3, passaremos um bom tempo discutindo arrays, como os trnciahzar e usar, e como lidar com arrays
multidimensionais... Fique l-igado!
Variiveis Final
Declararumavari6velcom^palaw^-ch^vefinal impossibilitaareutilizagiodessavari6veldepoisdeelatersido
iniciahzada com um valor explicito (repare que dizemos explicito, e nio padrio). Para primitivos, isso significa que, uma vez
que avai|vel tecebeu um valor, esse valor n6o poder6 ser alterado. Por exemplo, se voc6 atribuit 70 d,vai|veI int x, entio x
vai permanecer como 10 para sempre. Isso 6 bem simples para primitivos, mas o que significa terwmavai|vel de referdncia
aobjeto f inal?Umavari6veldereferdnciamarcadacomo f inal- nSopode jamaisserrearibuidaparareferir-seaum
objeto diferente. Os dados dentro do objeto podem ser modificados, mas a varidvel de refer€ncia n6o pode set modificada.
Em outras palavras, uma referdncia f inal- ainda lhe permite modificar o estado do objeto ao qual se refere, mas voc6 nio
pode modificar avairdveldercfer€nciaparafaz€-laserefeir a um obieto difetente. Decore isto: nio existem objetos f inal,
apenas referdncias f inal. Explicaremos isso com mais detalhes no Capinrlo 3.
Agora jd estudamos como o modificador f inaL pode ser aplicado a classes, m6todos e vad6veis. A Figura 1-8 mostra as
principais caracteristicas e diferengas das virias aplicag6es de final.
rinaffid so ( )
Vari6veis Volatile
Omodificadorvolatile diziJVMqueumthreadqueacesseavari6veldevesemprereconci-liarasuac6piaprivate
da vari6vel com a c6pia master ptesente na mem6ia. Como 6 que 6? Nio se preocupe com isso. Para o exame,tudo o que
voc6precisasabersobrevolatile 6que,assimcomotransient,essemodificadors6podeseraplicadoavari6veis
de instAncias. Nio se engane, a id6ia de multiplos threads acessando uma vari6vel de instAncia € assustadora, e 6 muito
importante que todo progtamadorJava a entenda. Mas, como ver6 no Capinrlo 9, voc6 provavelmente usar6 a
sincronizagio, em vez do modificador vol-at i l-e ,p^rz.torrr r seus dados i prova de threads.
O modift.cad.orvolaLile ("vol6til') tambdm pode ser apl:icado a gerentes de proJetos )
Vari6veis e M6todos Static
Omodificadorstatic 6usadoparacizrvai|veisem6todosqueirioexistirindependentementedequaisquerinstdncias
criadasparaaclasse.Emouftaspalavras,osmembrosstatic existemantesmesmodevoc6criarumanovainstinciade
uma classe, ehaver| apenas uma c6pia do membro stat ic, independentemente do nrimero de instdncias dessa classe.
Em outras palavras, todas as instAncias de uma dada classe compartilham o mesmo valor para qualquervait6vel stat ic.
Falaremos de membros static com mais detalhes no pr6ximo capitulo.
O que voc6 pode marcar como static:
I M6todos
I Vari6veis
I Uma classe aninhada dentro de outra classe, mas n6o dentro de um m6todo (falaremos mais sobre isso no Capitulo 8).
I Blocos de inicializagdo
I Interfaces
Declarando Enums
A partit da versio 5.0,Java lhe permite restringir uma vari6vel para ter um de apenas uns poucos valores prd-definidos em outras
-
palawas, um valor de uma lista enumerada. ( Os itens da lista enumerada sio chamados, sulpreendentemente, de enums.)
O uso de enums pode ajudar a reduzir os bugs no seu c6digo. Por exemplo, na sua aplicagio de automagio de
lanchonetes, voc6 poderia desejar reduzir os tamanhos de caf6s possiveis a BIG ("gande"), HUGE ("enorme') e OVER-
WHELMING ('absurdo'). Se voc6 deixar a possibilidade que um pedido de tamanho LARGE ("grande') seja feito, isso
poderia causar um erro. Entram em agdo os enums. Com a simples declatagio a seguir, vocd poder6 garantir que o
compilador o impedir6 de atribuir qualquer coisa a um Coffeesize que nio seja BTG, HUGE ou OVERWHELMING:
Os componentes b6sicos de um enum sio as suas constantes (ou seja, BIG, HUGE e OVERWHELMING), emboravoc€
v6 ver logo adtante que pode haver muito mais em um enum. Os enums podem ser declarados como as suas pr6prias
classes separadas, ou como membros de classes, mas nlo podem ser declarados dentro de um m6todo!
class Coffee {
CoffeeSize size;
l
J
]
O c6digo acima pode fazer parte de um s6 arquivo. (Lembre-se, o arquivo deve set nomeado como CoffeeTestl.iava,
porque esse 6 o nome da classe pfblica do arquivo.) A principal coisa a se lembrar 6 que o enum pode ser declarado somente
comomodificadorpublic ouodefault,assimcomoumaclassenio-interna.Eisumexemplodedeclaragiode
errum dentro de uma classe:
c-Lass uorreez { ^l
CoffeeSize size;
I)
As principais coisas a se lembrar desses exemplos sio que: 1) enums podem ser declarados como as suas pr6prias classes,
ou podem ser incluidos em outra classe; e 2) que a sintaxe para se acessar os membros de um enum depende de onde o
enum foideclarado.
O seguinte exemplo NAO 6 v6lido:
public class CoffeeTestl i
public static void main(Stringtl argts) {
enum coffeesize { erc, HUGE, oVERWHELMTNG } // ERRADo! Nao se
/ / pode declarar enums
// em m6todos
Coffee drink = new Coffee O ;
drink. size = CoffeeSize.BIG;
)
I)
Panfazer as coisas ficarem mais confusas pzravoc€,os elaboradores da linguagem Java frzeram opcional a colocagdo de
JAVA 5 37
ponto-e-virgula no final da declatagdo do enum:
public cl-ass CoffeeTestl- i
P"lT,o que 6criado quando voc6 cria um enum? O mais importante a se lembrar 6 que enums nlo sio Strings nem
ints! CadaumdostiposenumeradosdeCoffeeSize 6naverdadeumainstinciadeCoffeeSize.Emou-tras
palavras, BIG 6 do tipo Cof f eeSize. Pense em um enum como um tipo de classe, que 6 parecido (mas nio
exatamente) com isto:
class CoffeeSize {
public static final CoffeeSize BTG =
new Cof f eeSize (..BIG,' , 0) ;
public static flnal CoffeeSize HUGE =
new CoffeeSize ('.HUGE,,, I) ;
public static final CoffeeSize OVERWHELMTNG =
Voc6poderia criar algtm tipo de tabela de busca, usando alguma outra estrutura de dados, mas isso seria um design ruim e
dedificilmanutengio.Amaneiramaissimples 6ttataro.r."lo.e.dosseusenums (BIG,HUGE eOVERWHELMING)
como obietos que podem ter as suas pr6prias vari6veis de instincias. Ent5o, voc€ poder6 atribuir esses valores no momento
em que os enums forem inicializados, passando um valor ao construtor do enum. Isso precisa ser explicado com um
pouco mais de detalhes, mas, primeiramente observe o seguinte 6fdigo:
enum CoffeeSize {
38 Copitulo I : Declorqc5es e Conlrole de Acesso
CoffeeSize(int ounces) {
this.ounces = ounces; / / atrtbu]. o valor a
/
t | .._^ ----r:-re1
/ uttt4 vd!r4! de instancia
)
private int ounces; / / uma vari6vel de instdncia que o valor
de cada enum tem
publj-c int getounces Oi
ral- rrrn nrrndac.
i
)
cJ_ass colIee
a
t
CoffeeSize size; cada instAncia de Coffee tem um
enum CoffeeSize
]
Os principais pontos a se lembrar sobre os constflrtores de enums sio:
f NUNCA 6 possivel invocar um construtor de enum diretamente. Esse construtor 6 invocado automaticamente! com
os argumentos que vocd define ap6s o valor da constante. Por exemplo, BIG ( I ) invoca o construtor Cof f eeSize
que usa um int,
passando o literal 8 ao construtor. (I',los bastidores, 6 claro, voc6 pode imag1nar que BIG
int
tamb6m 6 passado ao construtor, mas nio precisamos saber - nem nos importarmos com - os detalhes.)
I Vocd pode definir mais de um argumento para o construtor, e pode sobrecarregat os construtores do enum, assim
como pode sobrecarregar um construtor normal de classes. Discutiremos os construtores com muito mais detalhes no
Capitulo 2.ParairuciaJtzar um Cof f eeType contendo ao mesmo tempo o nfmero de ongas e, digamos, um tipo de
lid, voc6 passaria dois argumentos ao construtor, ta fotma BIG ( I , "A" ) , o que significa que voc6 tem um
construtor em Cof f eeSize que usa tanto um int quanto uma string.
E, finalmente, voc6 pode definir algo realmente estranho em um enum, que se pafece com uma classe intema an6nima
(sobre a qual falaremos no Capinrlo 8). E o chamado corpo de classe especifico da constate, e voce pdoe us6Jo quando
precisar que determinada constante substitua um metodo definido no enum.
Imagine este cen6rio: voc6 quer que os enums tenham dois m6todos - um para ongas e um para c6digo de registro (uma
String). Agora imagine que a muorja dos tamanhos dos caf6s usa o mesmo c6digo, "8", mas o tamanho OVERWHELM-
ING usa o tipo "A'. Voc6 pode definir um m6todo getlidcode ( ) no enum Cof f eesize que retorne "8", mas
..rr. ."ro rro.6 precisa de uma forma de substinriJo para OVERWHELMING. Voc6 nio quer colocar um c6digo if / then
de dificil manutengio no m6todo getlidcode ( ) , entio a melhor saida poderia ser fazer com que a constante OVER-
WHELMING de alguma forma substitua o m6todo getlidCode O .
Isso parece esttanho, mas voc6 precisa entender as regras bisicas de declaragio:
JAVA 5 39
(-nffcaQ i za I
BIG(8),
HUGE (r_0) ,
Ap6s absorver o material d,este capitulo, voc€ dever6 estar familiarizado com algumas das nuances da linguagemJava. Voc6
poder6 talvez se sentir confuso sobre por que teve a id6ia de fazer este exame. Iiso 6 normal a esta altura. Caio esteia
ouvindo a si mesmo dizendo "onde eu estava com a cabega?",basta se deitar e descansar at6 que isso passe. N6s
gostariamos de poder dizer que fica mais f6cil, que este foi o capitulo mais dificil e que daqui em diante fica tudo menos
complicado...
Haverd muitas quest6es indiretamente relativas a palavras-chave, entao, certifique-se de que sabe identificar quais sio
palawas-chave reais e quais ndo sio.
Embora as convengoes de nomeagio como o uso de camelCase nao caiam diretamente no exatne, ainda assim voc6 ter6 de
entender os fundamentos da nomeagioJavaBeans, a qual usa camelCase.
Voc€ precisa entender as regras associadas com a criagio de identificadores v{-lidos, e as regras associadas com declarag6es de
c6digo-fonte, incluindo o uso de declarag6es package e import.
Agora voc6 tem um bom entendimento do controle de acesso no que se refere a classes, m6todo e vari6veis. Voc6 j6 viu
como os modificadores de acesso @ub1ic, protected e private) definem o controle de acesso de uma classe ou
um membro.
Voc€ aprendeu que as classe,s abstract podem conter tanto m6todos abstract quanto nio-abstract., mas que
se um s6 m6todo for marcado como abstract, entao a classe deve ser marcada como abstract.
Nio se esquega de
que uma subclasse concreta (nio-abstract) de uma classe abstract deve fornecerimplementagdes para t;dos
os
m6todos abstract da superclasse, mas que uma classe abstract nio precisa implerientar os m6todos ab-
stract da sua superclasse . Uma subclasse abstract pode "passar a boli" paraapiimeira subclasse concreta.
Examinamos a implementagio de interfaces. Lembre-se de que as interfaces podem estender uma outra interface (ou
mesmo multiplas interfaces), e que qualquer classe que implemente uma interface deve implementar todos os m€iodos de
todas as interfaces da drvore de heranga da interface que a classe est6 implementando.
40 Copftulo I : Decloroc6es e Controle de Acesso
Tamb6m vimos os outros modificadores, incluindo static, f inal-, abstract, synchronized e assim por
diante. Voc6 aprendeu como alguns modificadores nunca podem ser combinados em uma declangdo,pot exemplo,
misfurar abstract com f inal- ou pri-vate.
Tenha em mente que nio existem obietos f inal ernJzva. Uma variivel de refer6ncia marcada como f inal- nunca
poder6 ser modificada, mas o objeto a que se refere pode ser modificado.
Voc6 viu que f inal aplicado a m6todos significa que uma subclasse nio os poder6 substituir, e, quando aplicado a uma
classe, a classe final nio poder6 ser subclassificada.
Lembre-se que, a partir d oJava 5,os m6todos podem ser declarados com um parimetro var- arg (que pode usar de zeto
a muiros argumentos do tipo declarado), mas que voc€ s6 pode ter um var - arg por m6todo, e ele deve ser o ultimo
parAmetro do m6todo.
Certifique-se de estar famt\arizado com os tamanhos relativos dos primitivos num6ricos. Lembre-se de que, enquanto os
valores de vad6veis nio- f i na l- podem ser modificados, o tipo de uma vari6vel de refer6ncia nio pode.
Voc€ aptendeu tamb6m que arrays s5o obietos que contdm muitas variiveis do mesmo tipo. Os arrays podem tamb6m
contef ouffos aftays.
Lembre-se do que aprendeu sobre varidveis e m6todos static, especialmente que os membros static sio usados
por-classe emvez de por-instincia. Nio se esquega de que um m6todo stat ic nio pode acessar diretamente uma
vairivel de instincia apartu da classe onde reside, porque ele nio tem uma referdncia explicita a nenhuma instencia
particular da classe.
Finalmente, abordamos rrn recurso novo doJava 5, enums. Um enum 6 uma forma muito mais segura e fleivel de se
implementar constantes do que era possivel em vers6es anteriores deJzva. Pelo fato de serem um tipo especial de classe, os
enums podem ser declaiados de forma bastante simples, ou podem ser bem complexos - incluindo atributos tais como
m6todos, varidveis, construtores e um tipo especial de classe interna chamada de corpo de classe especifico da constante.
Antes de fazet o teste de treinamento, passe algum tempo com o otimistamente chamado "Exercicio Ripido". Volte a
consultat esse teste freqrientemente, dL medida que for lendo este livro e especialmente quando estiver perto da prova e voc6
estiver tentando memorizar tanto quanto conseguir. Porque - e eis aqui o conselho que voc6 gostaia que sua mie tivesse
lhe dito antes de voc6 ir p^tz^ faculdade - nio importa o que voc6 sabe, o que importa 6 quando voc6 sabe.
Para o exame, saber o que voc6 ndo pode fazer com a linguagemJava 6 tio importante quanto saber o que voc6 pode fazer-.
Experimente as quest6;s de amostra! Elas sio bastante semelhantes i dificuldade e ) estrutura das quest6es do exame real, e
deverio lhe abrir bs olhos para o quio dificil o exame pode ser. Nao se pre ocupe se errar vdrias delas. Se voc6 perceber que -
tem dificuldade em um t6pico especifico, passe mais iempo revisando-o e estudando-o. Muitos programadores precisam de
duas ou tr6s leituras s6rias de um capitulo (ou um objetivo individual) antes de conseguirem respondet is quest6es com
confianca.
{ Exercicio Ripido
Lembre-se de que quando falamos de classes neste capihio, estamos nos referindo a classes n6o-internas, ou classes de nivel
mais alto. Dedicaremos todo o Capitulo 8 is classes internas.
O Se nao houver instrugio de pacote, as instrug5es de importagio terZo que ser as primeiras (fora os comentArios) do
arquivo de c6digo-fonte.
fl As instrug6es de pacote e de importagio slo aplicadas a todas as classes do arquivo.
E As interfaces podem ser implementadas por qualquer classe, de qualquer drvore de heranga.
E A interface 6 como uma classe 100%o abstract, e ser6 implicitamente abstract caso voc6.ligite ou nio o
modificadot abs t rac t na declaragd.o.
E Uma interface s6 pode ter m6todos abstracts, nenhum m6todo concreto 6 permitido.
El Osm6todosdasinterfacessio,porpadrio,public eabstracts -adeclaragioexplicitadessesmodificadores6
opcional.
E Asinterfacespodemterconstantes,quesiosempreimplicitamentepublic, staticefinal.
E Asdeclarag6esdaconstantedeinterfacecompublic,static efinal sioopcionaisemqualquercombinagio.
E Uma classe de implementagio nio-abst.ract va)tdatefi.as propriedades a seguir:
E Fornecer6 implementag6es concretas dos m6todos da interface.
E Deve seguir todas as regras de sobrecarga v6lidas para os m6todos que implementa.
E Ndo deve declarar nenhuma excegio nova do m6todo de implementagio.
E Nio deve declarar nenhuma exceg6o que seja mais abrangente do que as declaradas no m6todo da interface.
E Pode declarar exceg6es de tempo de execugio em qualquer implementagio de mdtodo da interface, independente do
que coostar na declarag6o da interface.
E Deve manter a assinatura (sio permitidos retornos covariantes) e o tipo de retorno exatos dos m6todos que
implementa (mas nio precisa declarar as exceg6es da interface).
E Umaclassequeestiverimplementandoumainterfacepodeelapt6priaserabstract.
E Umaclassedeimplementagioabstract nloprecisaimplementarosm6todosdainterface(masaprimeirasubclasse
concreta pfecisa).
E A classe s6 pode estender uma classe (sem heranga multipla), por6m, pode implementar v6rias.
E As interfaces podem estender uma ou mais interfaces.
E As interfaces nio podem estender uma classe ou implementar uma classe ou interface.
E Quando ftzer o exame,vetifique se as declaragSes de interface e classe sio v6lidas antes de verificar outras
l6gcas do c6digo.
42 Copftulo I : Decloroc6es e Controle de Acesso
D Um membro protect herdado por uma subclasse de outo pacote nio pode ser acessado por nenhuma outra
classe do pacote da subclasse, exceto Pelas pr6prias subclasses dessa.
E Aprimeiraclassenio-abstrata(concreta)aestenderumaclasseabstract deveimplementartodososmdtodosab-
stract dessa.
D O modificador synchroni zed s6 6 aplicado a m6todos e a blocos de c6digo.
O Osmdtodos synchronized podemterqualquercontroledeacessoetamb6mseremmarcadoscomo f inal.
E Os mdtodos abstract devem ser implementados por rxna subclasse, porantq tem de ser herdados. Por essarzzdo:
E Os m6todos absuract ndo podem ser private.
E Os m6todos absLract nio oodem ser f inal.
JAVA 5 43
E O modificador nat ive s6 6 aplicado a m6todos.
E Asvaridveisderefer6nciafinal devemseriniciahzadasantesqueaexecugiodoconstrutorsejaconcluida.
E N6o existem obietos f inal-. Uma refer€ncia a obf eto marcadacomo f inal- n5o significa que o obieto propriamente
dito seja inaltet6vel.
E o modificadot t rans ient s6 pode set aplic ado a vaifiveis de instdncia.
D o modificador vol at i 1e s6 pode ser aplicado avzi|veisde instdncia.
E Os construtores enum nuncapodem ser chamados diretamente no c6digo.Eles sio sempre chamados
automaticamente quando um enum 6. irttcidtzado.
deum enum 6 opcionar Ambos sio v6ridos:
"
r':f *:j ilt il:i;l:*io
Teste Individual
As seguintes quest6es o ajudardo a ava\ar sua compreensio do material apresentado neste capinrlo. Leia todas as opg6es
cuidadosamente, porque poder6 haver mais de uma respostacorreta. Selecione todas as resPostas corretas para cada quest6o.
Mantenha o foco.
Caso tenha dificuldades com as perguntas no inicio, nio se desespere. Pense positivo. Repita boas afirmag6es para si mesmo
do tipo "Eu sou inteligente o suficiente para entender enum" e "Tudo bem, aquele canaitentende mais de enum do que
eu, mas aposto que ele nio consegue <insira algo em que voc6 defato seia bom) como eu."
2. Qual das seguintes opg6es declara uma classe abstract compil6vel? (Marque
todas
as €orretas.)
A. public abstract cl-ass Canine { public Bark speakO; }
B. public abstract cl-ass Canine { public eark speak O t i }
C. public class Canine { public abstract Bark speak ( ) ; }
D. public class Canine abstract { public abstract Bark speak O ; }
F. int *divide;
G. int central_sales_region_Summer_200S_gross_sa1es ;
6. Dado o c6digo:
l-. cl-ass voop {
2. public static voi_d main(String tJ args) {
3. doStuff (1) ;
4, doStuff (7,2) ;
Fl
l
Qual destas opg6es, inseridas independentemente na l-inha 6, ir6 compilar? (N{arque todas as correras.)
A. static void doStuff(int... doArgs) { }
B. static void doStuff (int [ ] doArgs) { }
C. static void doStuff(inr doArgs...) { }
D. static void doStuff(int... doArgs, int y) t i
E. static void doStuff(int x, int... doArgs) { }
7. Quais das seguintes opg6es sao declarag6es v6lidas? (Marque todas as corretas.)
A. short x [ ];
B.shorttly;
C. short[5] x2;
D. short z2 [5] ;
E. short t I z I I t l;
F, short t I y2 = [s] ;
46 Copitulo 1 : DecloroE6es e Controle de Acesso
8. Dado o c6digo:
1. enum Animals i
2. DOG("woof"), CAT(*meow"), FISH("burble") ;
3. String sound;
4- Animals(String s) { sound = }
",
6. class TestEnum {
7. static Animals a;
8. public static void main(StringtJ args) {
9. System.out.println(a.DoG.sound + r\ * + a.FISH.sound) ;
r-0. )
11. )
Qual 6 o resultado?
A. woof burble
B. Multiplos erros de compilagio
C. A compilagio falha devido a um erro na linha 2
9. Dado o c6digo:
r. enum A t A ]
2. class E2 {
3. enum B t iJ l
4. voidcO {
s. enumo{o}
b. l
7. j
Quais das aEtrmaivas sio verdadeiras? (I\{arque todas as corretas.)
A. O c6digo compila.
B. Se apenas a linha 1 for temovida, o c6digo compila.
C. Se apenas ahnha3 for removida, o c6digo compila.
D. Se apenas a linha 5 for removida, o c6digo compila.
E. Se as linhas 1 e 3 forem removidas, o c6digo compi,la.
F. Se as linhas 1,3 e 5 forem removidas, o c6digo compila.
A est6 incorreta porque as classes implementam interfaces, mas nio as estendem. B est6 incorreta porque as interfaces
s6 "herdam de" ouffas interfaces. D est6 incorreta com base nas regras anteriores. (Objetivo 1.2)
Obierivos pqrq q
certificog6o
I Decloror Interfoces
I Descrever o Encopsulomento, o
Acoplomenlo e o Coes6o
I Usoro Polimorfismo
I Relocionor Modificodores e HeronEo
l/ Exercfcios r6pidos
Ser um SCJP I .5 signi{ico que voc6 tem de estor completomenie imerso nos ospectos orientodos o obieios de Jovo. Voc6 preciso
sonhor com hierorquios de heronEo, o poder do polimo#ismo lem de fluir otrov6s dos suos veios, o coesoo e o ocoplomento
froco precisom se tornor t6o noturois poro voc6 quonto ondor, e o composiE6o preciso se lornor o seu feiioo com orroz. Esle
copftulo ird prepord-lo poro todos os obietivos e quest6es relocionodos d orientoE6o o obletos que voc6 enconlrord no exome.
Conhecemos muitos progromodores Jovo experientes que, no verdode, n6o s6o muito {luentes no utilizoq6o dos {erromentos de
orientoE6o o obietos fornecidos por Jovo, portonto, comeeoremos pelo inicio.
nl . r. ..1.
\.roleTtvo poro o centttcocoo
Beneficios do encapsulamento (Objetivo 5. I do exame)
5./ Dercnaoluer aldigo que implemente encapsulamento igido, acoplanento Jraco e alta coetdo em classes, e desreaer os benefcios.
Suponhamos que voc6 escrevesse o c6digo de uma classe e virios programadores de sua empresa escrevessem programas
que a usassem. Agora imaginemos que nio tivesse gostado da maneira como a classe se comportou, porque algumas de
suas variiveis de instAncia estavam sendo configuradas (por outros programadores em seus c6digos) com valores que voc6
nlo previu. O c6digo deles resultou em erros no seu c6digo (relaxe, isso 6 apenas uma hip6tese...). Bem, trata-se de um
programaJava, portanto, voc6 deve simplesmente langar uma versSo mais recente da classe, que eles poderio substituir em
seus programas sem alterar nada no c6digo que criaram.
Esse cenario ressalta duas daspromessas/beneficios da OO: flexibilidade e f6cil manutengXo. Mas os beneficios nlo surgem
automaticamente. VocA tem quefaryralgo.Precisa escrever suas classes e c6digos de man eka que di sapore i flexibilidade e
f6cil manutengio. Portanto, e reJava der suporte a OO? Ela nlo projetar6 szu c6digo para voc6. Por exemplo, imagine se
voc6 criasse sua classe com variiveis de instAncia publ ic e os programadores citados acima as configurassem diretamente,
como o c6digo aseguirdemonstra:
public class BadOO i
public int size;
public int weight;
i
public cl-ass ExploitBadoo {
public static void main (String [] args) {
BadOOb=newBadOOO;
b.size = -5; ll velido, mas ruim!!
]
Agora voc6 esti encrencado. Como modificar6 a classe de uma maneira que permita resolver os problemas que surgirem
quando algu6m alterar a vari6vel s i z e para um valor inadequado? Sua rinica opgio 6 voltar ao script, escrever o c6digo de
umm6tododeajusteparasize (umm6todosetsize(int a),porexemplo)e,emseguida,protegeressavari6vel
com, digamos, um modificador de acesso private. Por6m, logo que voc6 fizer essa alt eragdo em seu c6digo, innnonper,l o dos
outros!
A capacidade de fazrr alterag6es no c6digo de implementagio seminterromper o c6digo das outras pessoas que o estiverem
usando, 6 um beneficio essencid do encapsulamento. Voclpode ocultardetalltes da inplenmtapdoportnis de uma interface dc
prugranEioprtblic. Por interface, querernos dizer o conjunto de m6todos que seu c6digo tornar6 disponivel para outros
c6digos chamarem - em outras palavras, a API de sea cridigo. Com a ocultagio dos detalhes da implementaglo, vocA
poder6 trabalhar novamente o c6digo de seu m6todo (podendo tamb6m alterar a maneira como as vari6veis serXo
usadas por sua classe) sem forgar uma alteragio nos c6digos que chamarem o m6todo modificado.
Se voc6 quiser obter f6cil manutengio, flexibilidade e extensibilidade (e 6 claro que voc6 quer), seu projeto deve
incluir o encapsulamento. Como fazer isso?
I Mantenha suas variiveis de instAncia protegidas (com um modificador de acesso, geralmente privat.e).
I Crie m6todos de acesso public, e exija que o c6digo chamador use esses m6todos, emvez de acessar
diretamente a vari|vel de instAncia.
B b = new BO;
int x = b.getSize0; Qretsize ()
b.setsize(34); setSize ()
size = newSize;
)
i
Espereumminuto...quantodoc6digoanterior6ritil?Elenemmesmoexecutaalgumavalidagioouprocessamento!
Que
beneficio pode haver em ter m6todos capturadores e configuradores que neo adicionem uma funcionalidade extra? A
questeo 6 a seguinte, uocd pode mudar de idiia depoit e adicionar mais alguma codificagio a seus m6todos sem
interromper a API. Mesmo se achar que nao precisari realmente de validagio ou processamento dos dados, um
bom projeto de OO Preconiza o planejamento para o futuro. A fim de ficar seguro, exija um cddigo chamador que acere
nus mdtodos em ueqde pennitir o acesso direto is uaridueis de insthnria. Sempre. Assim, poder6 trabalhar de novo as
52 Copitulo 2: Orientog6o o obietos
implementag6es de seus m6todos posteriormente, sem correr o risco de ter que enfrentar a fiiria dos diversos
programadores que sabem onde voc6 mora.
class Foo {
n,rl-r"l in ihf r6ft - 9.
public int right = 3;
public void setleft(int IeftNum) i
left = leftNum;
right = leftNum/3;
)
Agora considere essaperganta: O ua/or da direita serd umpre ilm terp do ua/or da esquerda? Sua reposta senl sim, ati que perceba que os
usudiot da classe Foo ndo precisam usar o mitodo setl,ef t ( ) ! Eles poden simplesnente ir direto ds uaridaeis de instincia e alteri-
/as com qualqur ualor int aleahirio.
A heranga esti por toda pane emJava. E seguro dizer que 6 quase (quase?) impossivel escrever at6 mesmo pequenos
programas em java sem usar a heranga. Para explorar esse t6pico, iremos usar o operador instanceof , o qual
discutiremos com muito mais detalhes no Capitulo 4. Por agora, basta lembrar de que instanceof retorna tnre se a
vari6vel de referAncia testada for do tipo ao qual est6 sendo comparada. Este c6digo:
class Test {
public static void main (String [ ] args) {
TesL t1 = new Test ( );
Test t2 = new Test ( );
if ( !tl.equals (t2) )
System.out.println ( "they' re not equal" ) ;
if (t1 instanceof Object)
System.out.println ( "t1's an Object" ) ;
)
E ptt um minuto... como t1 pode ser uma instAncia do tipo Object, se acabamos de dizer que ela era do tipo
Test? Tenho cerreza de que voc6 esti muito na nossa frente aqui, mas o que ocorre 6 que toda classe em Java 6
uma subclasse de Object, (exceto, 6 claro, a pr6pria classe Object). Em outras palavras, toda classe que voc€ venha
a usar ou a escrever iri herdar da classe Object. Voc6 sempre ter6 um m6todo equals, um m6todo clone,
notify, wait e outros, disponiveis para usar. Sempre que criar uma classe, voc6 automaticamente herdari
todos os m6todos da classe Obiect.
Por qu6? Examinemos esse m6todo equals, por exemplo. Os criadores de Java presumiram corretamente que
seria bastante comum os programadores Java quererem comparar instAncias das iuas classes para verificar se sio
iguais. Se a classe Object nio tivesse um m6todo equals, voc6 teria de escrever o seu pr6prio; voc6 e todos os
outros pr,ogramadoresJava. Esse m6todo equals ji foi herdado bilh6es de vezes. (Para ser exaro, equals foi
sobrescrito bilh6es de vezes, mas falaremos mais sobre isso no devido tempo)
Para o exame, voc6 ter6 de saber que pode criar relag6es de heranga em Java utendendo uma classe. Tamb6m 6
imponante entender que as duas raz6es mais comuns para se usar a heranga sio:
I Para promover a reutilizagilo de c6digos
r Para usar o polimorfismo
Vamos comegar com a reutilizagio.Uma abordagem de projetos comum 6 criar uma verslo um ranto gen6rica de
uma classe, com a intengio de criar subclasses mais especializadas que herdem dela. Por exemplo:
class GameShape {
public void displayShape ( ) {
System. out.println ( "displ_aying shape,, ) ;
]
// maiq c6dia
/ / ma:-s c6digo
)
shape . movePiece ( ) ;
]
)
displaying shape
moving game piece
O segundo (e relacionado) uso da heranga 6 para permitir que as suas classes sejam acessadas polimorficamente -
uma capacidade fornecida tamb6m pelas interfaces, mas falaremos disso em um instante. Digamos que voc6 tenha
uma classe Gamelauncher que queira fazer tm loop atrav6s de diferentes tipos de objetos GameShape, e
chamar display ( ) em cada um deles. No momento em que est6 escrevendo essa classe, voc6 nio conhece todos
os tipos possiveis de subclasses de GameShape que ainda serlo escritos por outros programadores. E voc6 com
certeza nio quer ter de ref.azer seu c6digo apenas porque algu6m decidiu criar uma forma chamada Dice seis
meses depois.
A beleza do polimorfismo (significa "rnuitas formas") 6 que voc6 pode tratar qualquer subclase de GameShape
como se fosse uma GameShape. Em outras palavras, voc6 pode escrever c6digo na sua classe Gamelauncher
que diga, "nio me importa que tipo de objeto voc6"6, desde que herde de.(estenda) GameShape. E, no que me diz
respeito, se voc6 estender GameShape entio voc6 com toda certeza ter6 um m6todo display ( ) , entio eu sei
que posso cham6-1o."
Imagine que n6s tenhamos agora duas subclasses especializadas que estendam as classes mais gen6ricas
GameShape, PlayerPiece e TilePiece:
cl-ass GameShape {
public void displayShapeO {
System. out.print1n ( "displaying shape" ) ;
)
/ / mai s cridiag vvv4Y
1
J
)
// mais crldio6
vvs4Y
)
class TilePiece extends GameShape {
n"l.'l
yulfre in rzniA
vvfs na|-aAi:nanf
Yeu^sJqeslru\/
1\ I
L
// nais c6dioo
\
Agora imagine que uma classe de teste tenha um m6todo com um tipo de argumentodeclarado GameShape; isso
rifrtifi." qn'..Ia pode usar qualquer tipo de GameShape. Em outras palavras, qualquer subclasse de GameShape pode
sei p"s"dr a trnm6todo co- ltrn atg,rmento do tipo GameShape. Este c6digo
i
Gera a saida:
displaying shape
displaying shape
JAVA 5 55
O ponto principal 6 que o m6todo doShapes ( ) 6 declarado com um argumento GameShape, mas pode receber
qualquer subtipo (neste exemplo, uma subclasse) de GameShape. O m6todo pode entio chamar qualquer m6todo de
GameShape, sem nenhuma preocupagXo sobre o real tipo de classe de tempo de execugXo do objeto passado ao m6todo.
Existem implicag6es, no entanro. O m6todo doShapes ( ) sabe apenas que os objetos sio um tipo de GameShape,
uma vez que o parimetro foi declarado assim. E usar uma variivel de referAncia declarada como do tipo GameShape -
independentemsffs r{f se a vari6vel 6 um parAmetro de m6todo, uma variivel local ou uma variivel de instAncia - significa
qu-e apenas os m6todos de GameShape podem ser chamados para ela. Os m6todos que voc6 chama p^t^i^
refer6ncia sio totalmente dependentes do tipo dularado da variivel para a qual a refer6ncia aponta, nio importando
o que seja o objeto. Isso significa que voc6 nio pode usar uma vari6vel GameShape para chamar, digamos, o
m6todo getAdjacent ( ), nem mesmo se o objeto passado for do tipo TilePiece. (Veremos isio
novamente quando falarmos sobre as interfaces.)
E-um
Na OO, o conceito E-UU 6 baseado na heranga de classes ou implementagio de inrerfaces. O termo E-UM 6r.rma
maneira de dizer, "esse item d un tipo desse outro'.?or exemplo, um Mustang 6 um tipo de cavalo, portanto, na
terminologia da OO poderiamos dlzer, "Musta"g f-UIvt Cavalo". Subaru E-UU Carro. Broccoli f-'l-IM Vegetal
(!io muito atraente, mas mesmo assim conta). O relacionamento E-UM 6 expresso emJava por meio das piavras-
chave extends (para heranga de classes) e implements (para implementagio de interface$:
public class Car {
/ / C6digo de Car aqui
]
public class Subaru extends Car {
/ / Coisas importantes de Subaru aq"ui
/ / Nd,o se esqueqa que Subaru herda membros acessjveis de Car,
/ / o qte pode incluir tanto m6todos quanto vari6vers
]
Ocarro(Car)6umtipodeveiculoffehiclQ,pofianto,aArvoredeveterinicio apartirdaclasseVehiclecomoveremosabaixo:
public class Vehicle { ... }
public class Car extends Vehicle { ... }
public cl-ass Subaru extends Car { ... }
Na terminologia da OO, vod pode dizer o seguinte:
Vehicle 6 a zuperclasse de Car.
Car 6 a subclasse de Vehicle.
Car 6 a superclasse de Subaru.
CarherdadeVehicle
Subaruherdade Car
Subaru herda de Vehicle.
TEM-UM
Os relacionamentos TEM-UM sXo baseados na utilizagio , em vez de na heranga. Em outras palavras, classe A
TEM-UM B ocorreri se o aldrgo da classe A apresentar una referdncia a uma in$dncia da classe B. Por exemplo, voc6 pode
dizer o seguinte,
Um Cavalo ftIorse) f-UnA Animal. Um Cavalo TEM-UMA R6dea (Flalter).
E o c6digo teria o formato a seguir:
public class animal { }
public class Horse extends Animal- {
nri rraf e Hel ter mVHalter;
)
No c6digo anterior, Horse tem uma variivel de instAncia do tipo Halter, Poftanto' voc6_pode dizer que
a classe
"Horse ffU-UVt Halter". Em outras palavras, Horse aprercnta uma refeftncia a Halter. O c6digo de Horse.pode usar a
refer6ncia a Halter para chamar m6todlos dessa classe e .tsat seu comportamento sem ter um c6di_go (-og{..9
relacionado a ela ni pr6pria classe Horse. A Figura 2-3 ilustra o relacionamento TEM-IIM entre Horse e Halter.
Os relacionamenros TEM-UM permitirio que vocA projete classes que sigam as boas Priticas da OO sem que
sejam necess6rias classes monoliticas que eiecutem milhares de coisas diferentes. As classes (e, Portanto, os objetos
instanciados a paftir delas) devem ser especialistas. Como diz o nosso amigo.Andrew, 'as classes especializadas
de fato podem r a redvzir bugs". Qiuanto mais especializada. a classe, mais prov6vel que possa ser reutilizada
"jnd, Se voc6 inserir todos o. c6digoJrelacionados a Halter diretamente na classe Horse,
.* o.rt.o, aplicativos.
terminar6 diplicando o c6digo na classe Cow, Unplid.Intern e em qualquer outra classe que Possa precisar do
comportamento de Ftal ter. Mantendo o c6digo de Hal ter em uma classe especializada e separada, voc6 teri a
chance de reutilizila em v6rios aplicativos.
Horce
Halter halt Halter
tie(Rope r) """ tt"(""p" r)
Os usu6rios da classe Horse (isto 6, um c6digo que chamar m6todos em uma instAncia de Horse), achardo que
essa classe tem o comportamento de Halter. A classe Horse pode ter um m6todo tie (LeadRope rope) ,
por exemplo. Esses usu6rios nunca saberio que quando chamarem o m6todo tie ( ) , o objeto Horse delegari
essa tarefa para sua classe Halter chamando myHalter . tie ( rope ) . O cen6rio que acabou de ser descrito
ter6 um formato semelhante ao seguinte:
public class Horse extends animal {
private Halter myHalter;
public void tie(LeadRope rope) {
myHalter.tie(rope) ; / / DeIega o comport.amento de tie para
// n nhiafn l{alfar
)
public class Halter {
public void tie(LeadRope aRope) {
/ / Faz o trabalho propriamente dito de tie aqui
Na OO, nio queremos que os chamadores se preocupem com que classe ou objeto ser6 o que realmente executari
a taref.a. Para que se d6 dessa forma, a classe Horse ocultar6 de seus usu6rios detalhes da implementaQio. Os
usu6rios de Horse solicitario a esse objeto que execute tarefas (nesse caso, a si mesmo) .
^marrar para o chamador
Horse o far| ou, como nesse exemplo, solicitarA a outrem parafaz6-lo. No entanto, ".lasse
sempre
pareceri qli;e 0 pniprio objeto Horse feqtado. Os usu6rios de Horse nio precisario nem mesmo saber que ha algo
chamado classe Halter.
Na sala de aula
Projeto orientado a obietos
Os relacionamentos f-Ulrt e TEM-UM sio apenas a ponta do iceberg quando se rrara de projeto orientado a
objetos.. Muito.s livros e.teses de graduaEio t6m sido dedicados a esse t6pico. A, razilo pari a Anfase no projeto
apropnado 6 simples: dinheiro. O custo de distribuigio de um aplicativo tem sido estimado como 10 vezis mais
caro para programas mal projetados. Tendo visto os resultados de projetos fracos, posso assegurar que essa
esrrmauva nio 6 irreal.
At6 os melhores projetistas que usam o modelo orientado a objetos cometem er.os. E dificil visualizar os
relacionamentos entre centenas, ou at6 milhares, de classes. Quando os erros sio descobertos durante a fase de
implementagXo_(criagio do c6digo) de um projeto, a quantidade de c6digo a ser reescrita is vezes pode fazer com
que as equipes de programagio tenham que comegar tudo novamente.
A indristria de software tem evoluido para auxiliar o projetista. As linguagens visuais de modelagem de objetos,
como a Unified Modeling Language (UML), permitem que os projetistas criem e alterem facilrnente classes sem
ter que escrever o c6digo primeiro, porque os componentes orientados a objetos sio representados graficamente.
Isso permite que o projetista crie um mapa com os relacionamentos de classe ajudando-b a reconhecer erros antes
que a codificaglo comece. Outra inovagio recente no projeto orientado a objetos est6 relacionada aos padr6es de
projeto. Os projetistas perceberam que muitos projetoi orientados a objetos sio aplicados de maneiraionsisrente
de um projeto para outro, e que seria ritil aplicar os mesmos projetos porque isso reduziria a possibilidade de
introdugio de novos erros. Assim, os projetistas usu6rios do modelo orieniado a objetos comig"ram a
companilhar esses projetos entre si. Atualmente, hi muitos catilogos desses padr6es de projetos tanto na Internet
quanto em livros.
Embora para passar no_exame de certificaglo em Java voc6 nio precise compreender o projeto orientado a objetos
com esse nivel de detalhes, essas informag6es auxiliares o ajudario a entender melhor porqn. os criadores do teste
optaram por incluir o encapsulamento e os relacionamentos d um e tem a?n no exame.
I Jonathan Meeks, Programador Certificado em Java pela Sun
58 Copftulo 2: OrientoEdo o obietos
kmbre-se de que qualquer objetoJava que possa passar em mais de um teste E-UM pode ser considerado polim6rfico.
Fora os objetos do tipo Object, todotos objetosJava sio polim6rficos, no sentido de que eles passam no teste E-IIM feito
em relaSo ao seu proprio tipo e em relagio ) classe Object.
Lembrese de que a rinica maneira de acessar um objeto 6 atrav6s de uma vari6vel de refer6ncia, e h6 algumas coisas
imponantes a memorizar sobre as refer6ncias:
I Uma vari6vel de refer6ncia s6 pode ser de um tipo e, uma vez declarado, esse tipo nunca pode ser modificado (embora o
objeto que referencie posa se modificar).
r Uma referOncia 6 uma variivel, de forma que pode ser reatribuida para outros objetos (a nio ser que a refer6ncia seja
declaradacomo f inal).
r O tipo de uma variivel de refer6ncia determina os m6todos que podem ser chamados no objeto o qual a vari6vel est6
referenciando.
r Uma vari6vel de refer6ncia pode apontar para qualquer objeto do mesmo tipo que a refer6ncia declarada, ou - isto 6
muito importante - pode se referir a qualquer subtipo do tipo declarado!
I Uma variivel de referAncia pode ser declara& como um tipo de classe ou um tipo de interface. Se a vari6vel for declarada
como um tipo de interface,ila pode referenciar qualquer objeto de qualqu er classe que impbmente a interface.
Anteriormente, n6s criamos uma classe GameShape que foi estendida por duas outras classes, PlayerPiece e
Tilepiece. Agora, imagine quevoc6 deseje animar algumas das formas no quadro do jogo. Masnem todasasformas
podem ser animadas, entio, o que voc6 faz com a heranga da classe?
Poderiamos criar uma classe com um m6todo animate ( ) , e fazer somente algumas das subclasses de GameShape
herdar dela? Se pudermos, entlo poderiamos fazer PlayerPiece, por exemplo,estender tanto a classe GameShape
quanro a classe Animatable, enqu-anto que TilePiece estenderia apenas GameShape. Mas nio, isso nio funciona!
Javatem supofte a apenas uma heranga! Isso signi{ica que uma classe s6 pode ter uma superclasse imediata. Em outras
palavras, se PlayerPiece for uma classe, nlo 6 possivel dizer algo como:
AOTRABALHO
Algurzas ltngaagens (cono C++) permitem qae ana classe e$enda nais do que uma classe. Essa capacidade d conhecida como "heranga
ntiltipla". A raTdo criadoru de Jaua decidiram ndo permitir a beranga nilltipla d qae ela pode acabar bagungando o c,idigo.
pela qual os
Basicaaente, o prob/ena i qae se uma clasv estender dttas oatras c/astes, e ambat as superc/asses tiuerem, digamoq um mitodo
f f
doStuf ( ) , qaal uersdo de doStuf ( ) a subclasse herdaria? Essa quut1o poderia leaar a un ceniio conhecido como o 'Dianante
da Morte", por causa daforrna do diagmna dt clasm qae pode ser criado en pmjetot com heranga nilltipk. O dianante iformado qaando
tantoaclasseBquantrac/asseCestendemA,etantoBquantoCherdamummitododeA.Seac/asseDestendertantoBquantoC,e
tanto B quanto C tiaerem sobrescito o mitodo de A, a claste D tenl, na teoia, herdado duas imp/erttentagdes dtferentes do mesmo mitodo.
Duenhada cumo ilm dngmma de classes, aforma das qaatro c/ases se parece com um dmmante.
Assim, se isso nio funciona, o que mais voc6 poderiaf.azer?Poderia simplesmente colocar o c6digo de animate ( ) em
GameShape, e depois desabiliiar o m6todo im classes que nio possam ser animadas. Mas essa 6 uma decisio ruim para
um prorero por murras raz6es, incluindo a de que isso o torna mais propenso a erros, torna a classe GameShape menos
coesa (falaremos mais sobre a coesio em instantes), e significa que a API de GameShape "anuncia" que todas as formas
podem ser animadas, mas isso nlo 6 verdadeiro porque apenas algumas das subclasses de GameShape poderio rodar
com sucesso o m6todo animate ( ) .
Entdo o que mais voc6 poderia fazer? VocA j6 sabe a resposta - criar uma interface, Animatable, e fazer com que
apenas ai subclasses di cameshape q.rc possam sei animadas implementem essa interface. Eis o seu c6digo:
JAVA 5 59
Agora n6s temos uma classe PlayerPiece que passa no teste E-LIM tanto para a classe GaneShape quanto para a
interface Animatable. Isso significa que um PlayerPiece pode ser tratado polimorficamente com uma das quatro
seguintes opg6es a qualquer momento, dependendo do tipo declarado da variivel de refer€ncia:
r Um obj ect (uma vez que qualquer objeto herda de Obj ect)
I Um GameShape (umavez que PlayerPiece estende GameShape)
Quais m6todos podem ser chamados quando o objeto PlayerPiece e$6 sendo referido por meio de uma refer6ncia
declarada como do tipo animatable? Apenas o m6todo animate O . E claro que o interessante aqui 6 que qualquer
classe, de qualquer irvore de heranga, pode tamb6m implementar Animatatle; enteo isso significa qn., s.voc6
-
tiver um m6todo com um argumento declarado como do tipo Animatable, poder6 passar objetos
PlayerPiece, objetos spinninglogo e qualquer coisa que seja uma instAncia dl uma classe que
implemente Animatabl-e. E voc6 pode usar esse parAmetro (do tipo Animatable) para chamar o m6todo
animate ( ) ,.mtr nio o m6todo display ( ) (que pode nem existir) ou qualquer outro que nio seja conhecido
pelo compilador com base no tipo da refer6ncia. O compilador sempre sabe, nb entanto, que voc6 pode chamar os
m6todos da classe obj ect em^qualquer objeto, entXo 6 seguro chami-los independentemente da iefer6ncia -
classe ou interface - usada para apontar para o objeto
Deixamos de fora uma grande pane deste assunto: o fato de !lue, mesmo que o compilador s6 conhega o tipo de
refer6ncia declarado, a JVN[, em tempo de execugio, sabe o que o objeto iealmente 6. E isso significa que, mesmo
que o m6todo displJy ( ) de PlayerPiece seja chamadb usando-se uma variivel de referTncia Gimeshape,
a JVM chamari a verslo do m6todo display ( ) presente em PlayerPiece, caso PlayerPiece sobrescreva
esse m6todo! A Jyry o!se_rv1 o objeto real do outro lado da refer6ncia, "v6' que ele sobrescreveu o m6todo do tipo
da vari|vel de refer|ncia declarada, e chama o m6todo da classe verdadeira do objeto. Mas uma coisa a se ter eni
mente:
As chamadas de m6todos polim6rficos se aplicam somente a nitodos de in$6ncias. VocA sempre pode se referir a um
objeto com um tipo de va?iivel de refer6ncia mais geral (uma superclasse ou interface), -"r, .- tempo de
60 Copitulo 2: Orientogdo o obietos
execuglo, ONTCAS coisas que sio selecionadas dinamicamente com base no pr6prio objeto (em vez de no tipo
da referincia)"ssio os m6todos de instincias. Nio m6todos uttiticos. Nio uaridueis. Apenai m6todos de instAncias
sobrescritas slo chamados dinamicamente com base no tipo real do objeto.
IJma vez que essa definigio depende de um entendimento claro da sobrescrigio, e da distingio entre m6todos
estiticos e m6todos de instincias, falaremos sobre eles em seguida.
5.4 Dado am cendio, desenuoluer cddigo qae declare ef ou chame mdtodos sobrescritos ou sobrecarregados, e devnuoluer cddigo que declare ef ou
chame conshatores de superc/asses, cznstfl.rtzre! sobrescritos oa sobrecatregados.
M6todos Sobrescritos
Sempre que vocd tiver uma classe que herde o m6todo de uma superclasse, poderi sobrescrever esse m6todo (a
menos que, como aprendeu anteriormente, ele tenha sido marcado com f inal). O beneficio chave da
sobrescrigio 6 o recurso de definir um comportamento que seja especifico de determinado tipo de subclasse. O
exemplo a seguir demonstra a subclasse Horse penencente i classe Animal sobrescrevendo a versio do m6todo
eat( )dessaclasse.
public cl-ass animal {
public void eat ( ) t
System. out.println ( "Generic animal Eating Generically" ) ;
)
]
class Horse extends Animal {
public void eat ( ) {
q\/qj-
rf Fm nrrf nrintln
ousrL'.vuL.P!
(.'Horse
\ frvrrE gqLrrlY i-^
eaf 1-'r.'
rrsJ r veev, c
^^f =-4 hOrSe tfeats");
errv
]
)
Para os m6todos abstract que voc6 herdar de uma superclasse, nio hi escolha. E preciso implementar o
m6todo na subclasse a menos que ela tambdm seja abstract. Os m6todos abstract devem ser inplementados ,
pela subclasse concreta, -as isio virtualmente 6 o mesmo que dizer que a subclasse concreta sobrescreae os m6todos
abst.ract da superclasse. Portanto, voc6 deve considerar os ndtodos abstract
como aqueles ot quair ser,iforpado a
sobrescreuer.
O criador da classe Animal pode ter decidido que para fins de polimorfismo, todos os subtipos de Animal
precisario de um m6todo eit ( ) definido de maneira .rp..ifi." e.exclusiva. Coq o polimorfismo, quando
algu6m tiver uma referAncia a Animal que aponte nio para uma instAncia de Animal, mas para a instAncia de uma
su-bclasse de Animal, o chamador deveria chamar eat ( ) na referAncia a Animal, mas o objeto real do tempo de
execuglo (digamos, uma instAncia de Horse) executari seu pr6prio m6todo eat ( ) especifico. Marcar o
m6todo eaJ( ) como abstract 6 a maneira de o programador de Animal informar a todos os
desenvolvedores de subclasses: "Nio tem sentido s.n novo subtipo usar um m6todo eat( ) gen6rico, portanto, voc6
teri que criar sua pr6pria implementagio do m6todo eat ( ) !". lJm exemplo (nlo-abstract) do uso do
polimorfismo 6 apresentado abaixo:
pubJ-j-c cl-ass TestAnimals {
public static void main (String [] args) t
Animal a = new Animal0;
Animal b = new lrorEe () t / / Refer6ncia Animal, rnas 6 tut objeto Horse
a.eat\\; // Executa a versdo Animaf de eato
b.eat (\; / / Executa a versSo Horse de eato
JAVA 5 6I
]
class animal {
public void eat ( ) t
System.out.println( "Generic Animal Eating Generically" ) ;
)
class Horse extends Animal {
public void eato {
System.out.println("Horse eating hay, oats, and horse treats"),'
i
public void buck0 { }
)
No c6digo anterior, a classe de teste usa uma refer6ncia a Animal para chamar o m6todo em um objeto Horse.
Lembre-se de que o compilador s6 permitir6 que os m6todos da classe Animal sejam chamados quando a
referAncia a um objeto Animal for usada. O c6digo a seguir nio seria vilido dado o c6digo anterior:
Animalc=newHorse0;
c.buck(l; / / rmpossivel chamar buckO;
| / A cl'aes'e Aninral nio possui asse m6todo
O compilador s6 verificari o tipo da referdncia e nio o da instdncia. O polimorfismo permitir6 que voc6 use a
refer6ncia a um supeftipo mais abstrato (incluindo uma interface) para acessar um de seus subtipos (inclusive
os implementadores da interface).
O m6todo novo ndopodertl ter um modficador de acesso mais restritiuo do que o m6todo que foi sobrescrito (por exemplo,
voc6 nio pode sobrescrever um m6todo marcado com public f.azendo com que ele se torne protected).
Pense bem: se a classe Animal apresentar um m6todo eat ( ) public e algu6m tiver uma referAncia a Animal
(em outras palavras, uma referencia declarada com o tipo Animal), essa pessoa presumiri ser seguro chamar
eat ( ) na refer€ncia a Animal independente da instAncia real para a qual a refer6ncia estiver apontando. Se
fosse permitido que uma subclasse se infiltrasse e alterasse o modificador de acesso no m6todo novo, enteo,
repentinamente no tempo de execuglo - quando a JVM chamar a verseo real do m6todo no objeto ftIorse) em vez
da versio do tipo da referincia (Animal) - o programa seria interrompido (sem mencionar o stress emocional sofrido
por quem foi traido pela subclasse embusteira). Alteremos o exemplo de polimorfismo que vimos anteriormente:
public class TestAnimals {
public static void main (String [] args) {
Animal a = newAnimalo;
Animal b = new Horse() i / | Refer6ncia Animal, nag 5 urn objeto Horse
a.eat); // Executa a versao Animal de eato
b.eatO; // Executa a versdo Horse de eato
]
]
cl-ass Animal {
public void eat ( ) {
System.out.println( "Generic Animal Eat.ing Generically" );
]
]
class Horse extends Animal {
priwate void eat ( ) {
System.out.printl-n( "Horse eating hay, oats,
+"and horse treats");
)
Se esse c6digo pudesse ser compilado (o que nio acontecer6) o descrito a seguir falharia no tempo de execugio:
62 Copitulo 2: Orientogdo o obietos
A vari6vel b 6 do tipo enimal, que possui um m6todo eat ( ) public. Contudo, lembre-se de que no tempo de
execugio,alinguagemJavausaachanadaaumnitodovirtaalparaselecionardinamicamenteaverseo realdom6todoqueser6
executado, com base na instAnciareal.IJmarefer6ncia aAnimal sempre poderiapontatparauma instincia de Horse, porque
Horse E-UM Animal. O que torna possivel a essa superclasse refererr.i", r.r*" iortAncia da subcl asse 6 a certery dc qui)
subcksse pode faqgr tuda que a superclasn pode
faqer. Se a insdncia de Horse sobrescrever os m6todos herdados de Animal
ou simplesmente herd6los, qualquer pessoa com uma refer6ncia de Animal ) instAncia de Horse poder6 chamar
todos os m6todos disponiveis em Animal. Por essa razio, o m6todo novo deve seguir o contraro da superclasse.
I A llsta de argumentot deae coincidir exatamente com a do m6todo sobrescrito. Se nXo coincidirem, voc6 poder6 acabar
com um m6todo sobrecarregado que nio queria usar.
I O tipo dz retomo deae ser o mesmo, ou um subtipo, do tipo de retorno declarado no m6todo sobrescrito original da
superclasse (Falaremos mais sobre isso daqui a algumas piginas, quando discutirmos os retornos covariantes).
I O nfuel de acesso n6o deue ser nais rutritiuo que o do m6todo sobrescrito.
I Os m6todos de instAncias somente podem ser sobrescritos se forem herdados pela subclasse. lJma subclasse
dentro. do mesmo pacote que a superclasse da instincia 6 capaz de sobrescrever qualquer m6todo de
superclasse que nio seja marcado com private ou f inal. Uma subclasse de um pacote diferente somente
pode sobrescrever os m6todos nio-f inal marcados com public ou protecteA (uma vez que os
m6todos protect.ed sio herdados pela subclasse).
I O m6todo sobrescritor PODE langar qualquer excegio (de tempo de execugio) nio-verificada,
independentemente de o m6todo sobrescrito declarar ou nio a excegio. (Mais sobre isso no Capitulo 5.)
I O m6todo novo ndo deae langar excegdes ueifcadas flnuas 0a mais abrangentes que as declaradas pelo m6todo sobrescrito.
Por exemplo, um m6todo que declare uma excegio FileNotFoundException nio poder6 ser sobrescrito
Por um m6todo que declare uma excegio SQlException, Except.ion ou qualquer outra excegio que nio
seja de tempo de execugio, a menos que ela seja uma subclasse de FileNotFoundException.
I O ndtodo noao podeni langar excegdes nais restritiuas oil nefilr abrangentes. 56 por que o m6todo sobrescrito "se arriscou',
nio quer dizer que a excegio da nova subclasse deva contemplar os mesmos riscos. Conclusio: O m6todo
novo nio precisa declarar nenhuma excegio que nunca langar6, independente do que o m6todo sobrescrito
tenha declarado.
I Voc6 n6o pode sobresmuer um mdtodo marcado com f :-na]-.
I Voc6 nio pode sobrescrever um m6todo marcado com static. Veremos um exemplo daqui a algumas
p6ginas, quando discutirmos os m6todos static com mais detalhes.
I Se u, mdtoda ndo puder rcr lterdado, uocd ndo poderi sobrewaiJo. Lembre-se de que a sobrescrigio implica que voc6 esti
reimplementando um m6todo herdado! Por exemplo, o c6digo a seguir nio 6 vllido, e mesmo se voc6 adicionasse um
m6todo eat ( ) a Horse, ele nio seria uma sobrescriqXo do m6todo eat ( ) de Animal:
public class TestAnimals {
public static void main (String [] args) i
Horse h = new Horse0;
h.eat l); / / Nio 6 w61ido, Dorque Horse nio herdou eat()
)
]
^1 -^^
L!d>D n-l--r
rurltrdf t
)
class Horse extends aninal { }
JAVA 5 63
chamando a versio da superclasse de um m6todo sobrescrito
Geralmente, voc6 iri se. beneficiar de algum c6digo da versio da superclasse para um m6todo, ainda assim,
sobrescrevendo-o para fornecer um comport"-.ito especifico adicional. Seri como dize., li"ecrrte a versio
da
superclasse o m6todo e' em seguida, volte aqui e tirmine com o c6digo adicional d. mirrh" subclasse para
p-a.ra.
-
1y 3€t$g"lf !:"* ressaltar qry
:,.t?o
6 preciso que a versio da superclassZ t.1"
suDclasse)' t tacrl tazer lsso no codrgo usando a palavra-chave super, como vemos a
.".."r.J"";;;;i;;dt;;'d"
seguir:
public class Animal {
public void ear O { }
ntthlin rznid nrint-Vnrrrcalf
rvstpsr! \/\ / t/
]
class Horse ext.ends Animal {
nrrl-r'lic rrnid
wvfu nr.infv^rrra6lf
yrfrrurvq!osr! /\
\/
/I
Observagio: IJsar super para chamar um m6todo sobrescrito somenre se aplica a m6todos de instAncias. (Lembre-
se de que m6todos static nio podem ser sobrescritos.)
class Animal i
public void eat ( ) throws Exception {
i
Este aldigo ndo coapilanl deuido exce\zo dularada no mdtodo eat ( ) de Aninal. Isso ocom mesmo qtle, em tempo de exuugdo, 0 mit4do
)
eaL ( asado sela a uertdo de Dog a qual ndo dulara a excegdo.
64 Copitulo 2: OrientoE6o o obietos
A Tabela 2-1 lista exemplos de sobrescrig6es nio-viLlidas Odo m6todo eat ( ) de Animal, dada a verslo anterior da
classe Animal.
M6todos sobrecarregados
VocA deve estar pergtrntando o que os m6todos sobrecarregados estio fazendo em um capido sobre OO, mas os
se
incluimos p.lt fa:to de uma das coisas com as quais os deienvolvedoresJava novatos mais se confundem serem
"q.ri
justamente as sutis diferengas entre m6todos sobrecamgados e sobrescitos.
Os m6todos sobrecarregados permitirio que voc6 reutilize o mesmo nome de m6todo em uma classe, mas com
;g";;; dif.rentes (e Spciori"l*..rr., .or.r um tipo de retorno diferente). A sobrecarga de um m6todo geralmente
,ifnifi." q.r..,o.6.rt"ri r"ndo um pouco mais condescendente com as Pessoas que chamarem seus m6todos, po^rque razr
..iaig" *]"*r ,^^tirf.^d{idar coirrtipos de argumentos diferentes eri vezdeiorgar o rhamadorafaznr convers6es antes de
chamar seu m6todo. As regras sio simples:
t Um mttodo podeser sobrecarregado na mesma classe ou em uma subclasse. Em outras palavras, se a classe A
definirum m6todo doStuf f (int i), a subclasse B poderia definirum m6todo doStuf f (String s)
sem sobrescrever a versio da superclasse que usa um int. Assim, dois m6todos com o mesmo nome, mas em
diferentes classes, ainda podem'r.r corrsid.rados como sobrecarregados, caso a subclasse herde uma versio do
m6todo e depois decl^ri outr^versio sobrecarregada na sua definigio de classe.
Sobrecargas vilidas
Examinemos um m6todo que queremos sobrecarregar:
nrrhlic
Puvfrv
rrnid
vvrs chanaesizc(inf
vlrgrrYe size. String name, float pattern) { }.
Os m6todo a seguir sio sobrecargas u,itidas do m6todo changeSize ( ) :
throws rOException { }
JAVA 5 65
oBsERvAe6ns pene o ExAME
Tome caidado 41ando tiuer qae reconbecer se um mitodo d nbrecarregado em ueTde sobrucrito. Voc€ pode aer am mdtodo
qae parega uio/ar
uma regra da nbrucrigdo, mar qae na uerdade senl uma sobrecarga u,i/ida, como ueruos a seguir:
Quando.um m6todo for chamado, pode existir mais de um m6todo com o mesmo nome para o ripo de objeto em
que voc6 o estiver chamando. Por exemplo, a classe Horse pode ter-tres m6todos com o ;esmo nbme, por6-,
com listas de argumentos diferentes, o que significa que o m6todo foi sobrecarregado.
A decisio sobre qual dos m6todos coincidentes chamar ser6 baseada nos argumenros. Se voc6 chamar o m6todo
com um argumento String, a versAo sobrecarregada que usar uma String ser6 chamada. Se chamar um m6todo com
o mesmo nome' mas Passar Para ele um tipo f 1oat, a versio sobrecarregada que usar um tipo f loat ser6
executada. Se chamar um m6todo com o mesmo nome, mas passar para el=e um-objeto roo e nio houver uma
versio.sobrecarregada que use esse objeto, enteo, o compi]xdel aviJar6 que nio est6 conseguindo encontrar uma
coincid6ncia. A seguir temos exemplos de chamadas a m6todos sobrecarregados:
class Adder {
public int addThem(int x, int y) {
return x + v;
)
int c = 3;
int result. = a.addThem(b,c) ; ll euaL addTtren 6 chanado?
double doubleResult = a.addThem(22.5,89.36) ; // euaL addlltrern?
]
No c6digo TestAdder anterior, a primeira chamada a a. ad.dThem (b, c) passa dois tipos int para o
m6todo, portanto, a primeira versio de addThem ( ) - a versio sobrecarregada que usa doii argumen^tos de tipo
int -ser6chamada.Asegundachamadafeitaaa.addThem (22.5, 89.361 passadoistiposdouble-
para o m6todo,.portanto, a segunda verseo de addThem ( ) - a versio sobrecarregadl que usa dois argumentos
double - ser6 chamada.
66 Copitulo 2: Orientoqdo o obietos
Chamar m6todos sobrecarregados que usem refer6ncias a objetos_ em vez de tipos primitivos 6 um pouco mais
inr.r.rr"rri.. Oig"r"ot qrr. v&e tive'sse um m6todo sobre.a.i.g"do em qu9 -uma versio usasse um objeto Animal e
a outra;"b,;?;H;rr'. 1r"b"i"rt. Je Animal). Se voc6 p"tt"t"o- objeto Horse na chamada do m6todo, chamarh
a versio sobrecarregada que usa esse objeto. Ou pelo menos 6 o que Parece i primeira vista:
class animal { }
class Horse extends animal { }
class UseAnimals {
public void doStuff(Animal a) t
s\/qt-Fm orri- nrint-ln("Tn the Animal version");
uJ e uer( .
]
public void doStuff (Horse h) {
svsl-cm orrf nri nf l n ( "Tn fhe Horse version"
vJrevlrr! vse.y!4^re+ ) ;
]
public static void main (String [] args) {
Qual das vers6es sobrecarregadas seri chamada? Voc€ pode estar querendo responder: "A ,9ge usa qm objeto
liorr., jL que 6 esse objeto que est6 sendo passado parJo m6todo no tempo de execugio". Mas nio 6 assim que
funciona. O c6digo anterior na verdade exibiria:
in the Animal version
Ainda que o objeto real no tempo de execugXo seja Sli*ll, a opgio por qual
um objeto llgrse e."q" m6todo
sobrecamgado chamar (em outras palavras, a assinatura do m6todo) nio 6 decidida dinamicamente no tempo de
execugi6. Apenas lembre-se de q.te o tipo da referdncia (e ndo o tipo d9 objeto) d(emiry 4!al ndto(o sobrecamgado.unl chamado!
Resumindo,^o m6todo sobresnito a chamar (em outras palavris, de qual classe da 6rvore de heranga)- 6 decidido.no
tempo de exuipao com base no tipo do objeto, mas qual versio sobreearegado do m6todo chamar 6 baseado no tipo da
referdnciapassado no rempo de tonp;kgi. Se voc6 chamar um m€todo passando a ele uma referdncia Animal a um
oblrto Horr., o compilador s6 saberi do Animal, portanto, ele escolhe a. verslo sobrecarregada do m6todo que
,rr" rr* Animal. Nio impona, em tempo de execugio, que na verdade seja um Horse sendo passado.
yslf
.ia rrniA
nrrh'l re vvfq a:|- tqt-rind c\ II
cqu \uL!frrY o/
Observe que a classe Horse tanto sobrep6s quanto sobrescreveu o m6todo eat ) . A Tabela 2-2 mostra que (
versao dos tr6s m6todos (
eat ) ser6 executada dependendo de como forem chamadas.
Animal a2 = newAnimal ( ) Erro do compilador! O compilador percebeu qtre a classe Animal nio possui
a2,eaX ("treats"); um m6todo eat( ) que use uma String.
)
A elasseBar tem dois mdtodot doStuf f ( ): a uersdo sem argamentls qae herdou deFoo (e ndo sobresmuel e a nbrecamgada
doStuf f (String s) defnida na classe Bar. O aidigo con uma refer€ncia ao objeto Foo pode chamar somente a aersdo sem
argilnentLr' mN 0 que ten a refer€ncia a am objeto Bar pode chamar qua/.quer uma das uersdes sobrecamgadas.
Acesso Pode ser aherado Nio deve se tornar mais restritivo (pode
ser menos restritivo)
Sobrescrito Sobrecarregado
Tree Tree
Oak Oak
O objetivo atual (5.4) aborda tanro a.sobre carga de m6todos quanto de construtores, por6m, a iltima ser6 abordada
na proxlma segao, na qual tamb6m discutirernos os outros t6picos-relacionados a construtores que aParecerio no
."".n.. A figuia 5-4 ilustra a maneira como m6todos sobrecarregados e sobrescritos sio tratados em
relacionamentos de classes.
saber dferenciar enor de conrpilagdo de erms de tempo de execapdo relacionados i conuersio de refer4ndas a objetos.
de objetos
J6 vimos que 6 possivel e comum usar tipos gen6ricos de variiveis de ref_9r6ncia pa?:.ap2+tar.para,tipos
mais especifi.oi. kto forma a base do poli*orfir-o. Por exemplo, esta linha de c6digo lhe deveri Parecer natural
a esta altura:
Animaf animal = new DogO;
Mas o que acontece quando voc6 deseja usar a variivel de refer€ncia do animal a fim de chamar um m6todo que -
apenas a classe oog possui? VocA sabe que esti se referindo a um Dog, e deseja fazer algo que 6 especifico.a Dog?
No c6digo seguinti, f.*or rr* array deanimals e, sempre que. acharmos um Dog no array, queremo^s fazer
algo espe"cific6 d. pog. Vamos coniordar por agora que todo o c6digo est6 correto, exceto pelo fato de nio
estarmos ceftos sobre a linha que chama o m6todo playDead.
class Animal {
void makeNoise ( ) {System.out.println( "generic noise") ; }
)
class Dogr extends Animal {
JAVA 5 69
void makeNoiseO {System.out.println(..bark,,) ; }
void playDead ( ) i System. out.println ( ', roll over,, ) ; )
]
class CastTest2 {
public static void main(String IJ args; {
Anima] tl a = inew Animal O , new DoSO , new Animal O );
for(Animal animal : a) {
animal.makeNoise ( ) ;
if (animal instanceof Dogr) {
animal .playDead(li // lentou realizar um coq)orta.m€nto de D,og?
Isso pode ser enlouquecedor! O c6digo compila! Mas quando tentamos executAlo, recebemos uma excegeo parecida
com esta:
j ava. 1ang. ClassCastException
Por que nio podemos confiar que o compilador vai nos a.judar aqui? Ser6 que ele nio consegue ver que animal 6
do tipo Animaf ? Tudo o que o compilador pode fazer 6. verificar se os dois tipos esrio na mesma iwore de
heranga, de forma que, dependendo se houve ou nio algum c6digo antes da conversio, 6 possivel que animal
seja do tipo Dog. O compilador precisa permitir coisas que possivelmente vio funcionar no mominro da
execugio. Entretanto, se o compilador souber com certeza que a conversi.o nio poder6 funcionar de jeito nenhum,
-
a compilagio faihar6',. O seguinte bloco de c6digo substiruto NAO compilari:
class DogTest {
nrrlr]in c{-:fia void main(St.ring [] args) {
Dog d = new Dogo;
Anina1 a1 = d; / / converslo generalizadora ok sem nenhunr converEio e:rglicita
Ani.mal a2 s (Animal) dt ll cornwergio generalizadora ok co umr conversio otrllicit,a
)
Ambas as convers6es acima irio compilar e rodar sem exceg6es, porque um Dog n-UVt Animal, o que significa
que qualquer coisa que um Animal possa fazer, um Dog tamb6m poder6. Um Dog pode f.azer mais, 6 claro, mas-a
questao 6: qualquer um que tenha uma referAncia a Animal pode chamar, com seguranga, os m6todos de Animal
em uma instincia de Dog. Os m6rodos de Animal podem ter sido sobrescritos na classe Dog, mas tudo que nos
importa agora 6 que um Dog sempre pode tazer, no m(nimo, tudo o que um Animal puder. O compilador e a JVM
tamb6m sabem disso, entlo a conversio generalizadora implicita 6 sempre v6lida para atribuir um objeto de um
subtipo a uma referencia de uma das classes (ou interfaces) do seu supertipo. Se Dog implementar Pet, e Pet
definir beFriend.ly ( ) , entio um Dog pode se converter implicitament. .tn n.tiPrt, mas o 6nico m6todo de
Dog que voc6 poder6 chamar enteo ser6 beFriendly ( ) , que Dog foi forgado a implementar porque Dog
implementa a interface Pet.
Mais uma coisa... Se Dog implementa Pet, entXo se Beagle estender Dog, mas Beagle nio fuclarar que esti
implementando Pet, Beagle ainda ser6 um Pet! Beagle 6 um Pet simplesmente porque estende Dog, e Dog jlt
cuidou dos seus pr6prios comportamentos Pet, e os de todos os seus descendentes. A classe Beagle sempre pode
sobrescrever quaisquer m6todos que herdar de Dog, incluindo m6todos que Dog implementou para satisfazer o
contrato da sua interface.
E s6 mais uma outra coisa... se Beagle de fato declarar que est6 implementando Pet, apenas para que as pessoas
gue olharem a API. da classe Beagle possam ver facilmente que Beagle E-IIM Pet, sem ter de olhar nas superclasses
de Beagle; Beagle ainda assim nlo precisarl implementar o m6todo beFriendly ( ) caso a classe Dog (a
superclasse de Beagle) jS,tenha cuidado disso. Em outras palavras, se Beagle E-UM Dog, e Dog E-UM Pet, entio
Beagle E-IIM Pet, e ji atendeu is suas obrigag6es de Pet de implementar o m6todo beFrien-dly ( ) , uma vez que
ele [erda esse m6todo. O compilador 6 espirio o suficiente pira dizer, "Eu j6 sei que Beagle 6 UM Pet, mas nio
tem problema em tornar isso mais 6bvio".
Assim, nio se deixe enganar por um c6digo que mostre uma classe concreta que declare estar implementando
uma interface, mas que nio implemente os mitodos da interface. Antes de poder dizer se o c6digo 6 vilido ou nio,
vocA precisa saber o que as superclasses dessa classe concreta declararam. Se qualquer classe da sua irvore de
heranla jitiver forneiido implementag6es concretas (ou seja, nio-abstract) doi m6todos, e tiver declarado que
ela (a superclasse) est6 implementando a interface, enteo a subclasse nXo tem obrigagio nenhuma de
reimplementar (sobrescrever) esses m6todos.
Animala=newDogO;
Dogd= (Dog) a;
: rlnnnacrrrff
s.uvsvvvesr! /\
\ / ,
Quando voc€ implementar uma interface, estari concordando em aderir ao conrraro definido nela. Isso significa
que estari concordando em fornecer implementas6es v6lidas de cada m6todo definido na inrerface e que
{ualquer
pessoa que.souber como sio os m6todos da interface (nio a maneira como sio implementados, *"r .&.to
irod6m
ser chamados e o que retornam) poderi cham6-los na instAncia de uma classe sua que a implementar.
Por exemplo, se voc6 criar uma-classe que implemente aintertace Runnable (de modo que seu c6digo possa ser
executado por um thread especifico), ter6 que fornecer o m6todo public void run ( I . Oo conlririo, o
coitado do thread_ poderia ser informado para executar o c6digo de seu objeto Runnable e - surpresa - iria
descobrirqueo objetoniopossui o m6todo run( ) !(Momentoemque, othreadseriainterrompidoeaJVM
encerrado em uma finalizagi"o espetacular, por6m, horrivel). Felizmenle, a linguagem Java impedlr6 que isse dano
ocorra pela execugio de uma verificagio do compilador em cada classe que tentaiimplementar uma interface. Se
a classe informar que esti implementando uma interface, 6 melhor que tinha uma implementagio de cada m6todo
da interface (com algumas exceg6es que examinaremos em breve).
Assumindo-se que temos uma interface Bounceable, com dois m6todos: bounce ( ) e setBouneeFactor () , a
seguinte classe ir6 compilar:
Cefto, sabemos o que voc6 esti pensando: "Essa deve ser a pior classe da hist6ria das classes de implementagio". No
entanto, ela ser6 compilada. E executada. O contrato di interface garante que uma classe tenha o m6todo (em
outras palavras, classes diferentes poderio chamar o m6todo, sujeito a conirole de acesso), mas nunca garantirS,
uma implementagio adequada - ou mesmo algum c6digo de implementaEio real no corpo do m6todo-O
compilador nunca lhe dir6, "Desculpe, mas voc6 nlo quer mesmo inserir nada entre essas chaves? ATENQAO: ji
que se trata de um m6todo, ele nio deveria executar algo?".
As classes de implementagio devem estar sujeitas as mesmas regras de implementagio do m6todo como uma
classe estendendo uma classe abstract. Para ser uma classe de implemintagio v6lida, uma classe de
implementagio nio abstract deve fazer o seguinte:
I Fornecer implementag6es concretas (nio abstract) de todos os m6todos da interface declarada.
r Seguir todas as regras de sobrecarga vilidas.
I Nio declarar exceg6es existentes em m6todos de implementagio que nio sejam as declaradas pelo m6todo da
interface, ou subclasses que nio sejam as declaradas por esse m6todo.
I Manter a assinatura e o mesmo tipo de retorno do m6todo da interface (por6m, nXo sendo preciso declarar as
exceg6es existentes na declaragio do m6todo da interface).
Mas.espere_, hi mais! Uma_classe de implementagio pode ser ela pr6pria abstract! Por exemplo, o c6digo a
seguir 6 v6lido para uma classe Ball que implemente a interface Bounceable:
abstract class Ball implements Bounceable { }
Notou algo faltando? Nio fornecemos os m6todos de implementagio. E isso esti certo. Se a classe de
implementagio for abstract, ela pode simplesmente passar atarefa para sua primeira subclasse concreta. Por
exemplo, se a classe BeachBall estender Ball e nio for abstract, entXo, reri que fornecer todos os m6todos de
Bounceable:
class eeachBall extends Ball {
/ / F;rnbora nao o digamos na declaragd.o de classe acima,
// BeachBall implement.a Bounceable, uma vez que a superclasse abstract de
/ / BeachBall (8a11) implementa Bounceable
]
72 Copftvlo 2: OrientoEdo o objetos
public void setBounceFactor(int bf) {
/ / c6digo bounce especifico de BeachBall aqui para definir um fator de bounce
Procure m6todos que informem implementar uma interface, mas nXo fornegam-as implementag6es de m6todo
correras. A menos'que a classe de implementagio seja abstract, elaterS, que fornecer implementag6es de
todos os m6todos definidos na interface.
VocA precisa conhecer mais duas.regras para que.possamos, entio, encerrar esse t6pico (ouIaz voc6 dormir
sempre, pois nunca nos confundimos com uma dessas op96es):
1.. Uma classe pode implementar mais de uma interface.
vilido informar, por exemplo, o. seguinte:
E perfeitamente
public class Ball implements Bounceable, Serializable, Runnable { ... }
VocA pode esrender somente uma classe, mas implementar muitas. Por6m, lembre-se de que a criaglo de sub-
classei define quem e o que 6 a classe, enquanto I implementagio define uma fungio que ela.poderi desempenhar
ou algo que poderi usar, apesar do quanto possa ser diferente de outra classe que estiver implementando a mesma
interface (por6m, apartir de uma 6wore de heranga diferente). Por exemplo, uma pessoa estenderia HumanBeing
(embora isso possa ser discutivel para alguns). Mas tamb6m poderia implementar programmer, snowboarder,
employee, parent ou personcrazyenoughtotakethisexam.
2. A pr6pria inter{ace pode estende r outra interf.ace, mas nunca implementar algo.
O c6digo abaixo 6 perfeitamente v6lido:
public interface Bounceable errtends rdoveable { }
O que isso significa? A primeira classe concreta (nio abstract) de implementagio de Bouceable deve
implementar todos os m6todos dessa interface, al6m de todos os m6todos de Moveable! A subinterface, como a
chimamos, simplesmente adicionari mais requisitos ao contrato da superinterface. VocA veri esse conceito
aplicado em muitas 6reas da linguagem Java, principalmente no J2EE, onde geralmente temos que construir
nossas pr6prias interfaces para estender uma das suas.
No entanto, agoarde, porque 6 agora que comega a ficar estranho. Uma interface pode estender mais de uma
interface! Pense bem por um momento. Voc6 sabe que quando se trata de classes, o que vemos abilxo nio 6 vlilido:
frublic cLass PrograrEner extends Eqrloyee, Geek { , || I,rrvlLj-Aol
Como mencionamos anteriormente, uma classe nio pode estender virias outras em Java. No entanto, uma
interface pode estender virias interfaces.
inlerf,ace BounceabLe extends Dloveable, spherical {
void bounce O ;
void setBounceFactor(int bf ) ;
)
interface Moveable {
void moveft O ;
)
interface Spherical {
void doSphericalThing( ) ;
Ball 6 necess6ria na implementagio de Bounceable, al6m de todos os m6todos das interfaces que Bounceable
estende (incluindo qualquer interface que essas interfaces estendam, e assim por diante, at6 que vocb alcance o
inicio da pilha - ou seria o fim da pilha?). Portanto, Ball teria que ter o seguinte formato:
class Ball implemenLs Bounceable {
interface Bounceable
void bounce( ); abstract Ball implements Bounceabl-e
void setBounceFacEor(int bf) ;
Devido oo foto de BeochBoll ser o primeiro closse concreio poro implemenlor Bounceoble, elo deve
fornecer implementog6es poro todos os m6todos de Bounceoble, excelo oqueles de{inidos no closse
obstroct Boll. Como boll n6o forneceu implementoE6es dos m6todos Bounceoble, BeochBoll foi referido
poro implemenlor lodos.
A Figuro 2-5 comporo o uso vdlido e o n6o volido de exlens6es e implementoq6es, tonto poro
closses quonlo poro inferfoces.
class foo { } // oK
ala<< R:r imnlamanfc E'^^ f J // Ndo! Ndo 6 trtossiveL impTementar uma cLasse
74 Copftvlo 2: OrientoE6o o objetos
interface eaz { } // oK
interface Fi { i // oK
interface Fee implements Baz { } // Ndo! A interface ndo Pode
/ / impTementar uma interface
interface Zee implement.s Foo { } // Ndo! A interface ndo Pode
fasse
/ / im9sTementar uma c
MemoiTe isto e pmcare abusos cometidos petgilntar qae estiuerem n0 exame. IndEendente do que as perguntas parEam aualiar, o
nas
pmbhna real pode Antes de cair na arwadilha, digaruos, de acompanbar o fluxo de am thread
ser a declaragdo da classe ou interface.
mmplexo, ueifqae sepelo nenos o cddigo ser,l compilado. (Srlporessa dica,jd meruemls ettarem seu testamento!) (I'zoc6fcari
impressionado com o empenho dos elaboradtres do exame en desuid-lo do pmblena real). (Cono as pessnar cznsegt'/iam redigir alg antes dos
pa ftfl teret nre m i n ue n tadot ?).
String go(int x) {
return nu11;
JAVA 5 75
O_bserve que a versio da classe Bar para o m6todo usa um tipo de retorno diferente. Isso 6 perfeitamente
adequado' Contanto que voc6 tenhi alterado a lista de argumentos, esrari sobrecarregando'o m6todo, porranto, o
tipo de retorno nio precisar6 coincidir com o da versio da superclasse. O que voc6 n?o pode fazer 6 isto:
public class Foo{
void go0 { }
]
public class Bar ext,ends Foo {
String go0 { // Inv6lidol Ndo 6 possivel modificar apenas o tipo de rerorno
return null;
Outras regras slo aplicadas i sobrecarga, inclusive as dos modificadores de acesso e exceg6es declaradas, mas elas
nio sio relevantes para a discussio sobre o tipo de retorno.
No exame, voc6 ter6 que saber que os m6todos sobrecarregzdos podem ter o tipo de retorno alterado, mas os m6todos
que estiverem sobrerreuendo outros sri poden fa$-/o dentro dot linitu dos retnftilr couariantes. 56 por ter conhecimento disso
voce conseguiri responder v6rias perguntas do exame.
Retornando um Yalor
VocA ter6 que lembrar de apenas seis regras para o retorno de um valor:
1. Voc6 pode retornar null em um m6todo que tenha como tipo de retorno a referAncia a um objeto.
public Button doStuff ( ) {
return nu11;
)
2. O array 6 um tipo de retorno perfeitamente v6lido.
public String tl goo {
return new St.ring[] {"Fred", "Barney", "Wi1ma"};
3. Em um m6todo com tipo de retorno primitivo, voc6 pode retornar qualquer valor ou variivel que possa ser
76 Copitulo 2: Orientoq6o o obletos
4. Em um m6todo com tipo de rerorno primitivo, voc6 pode retornar qualquer valor ou vari|vel que Possa ser
explicitamente convertido parao tipo de retomo declarado.
public int foo ( ) {
float f = 32.5f;
return (i-nt) f;
]
5. Y oc€ ndo deve retornar nada de um m6todo com tipo de retorno void.
public void bar ( ) {
return "this is it"; /,/ rnv6lido! !
]
6. Em um m6todo que tenha como tipo de retorno a refer6ncia a um objeto, voce pode retornar qualquer tipo de
objeto que possa ser implicitamente convenido paraotipo de retorno declarado.
public Animal- getAnimal ( ) {
return new Horse (\ ; / / Assuma que Horse estenda Animal
)
]
]
Esse aldigo ini compilar, o ualor de retorno i um subtipo.
JAVA 5 77
5.4 Dado um nndrio, desenuo/ueraidigo que declare efou chame nitodos sobrescritos ou sobrecanegados, e cddigo qae dec/are efou cbane
cznJtratlres de superc/assu, con$rutoret sobrescritot ou sobrecanegados.
Os objetos sio construidos. Voc| ndo pode criar am nouo o[eto sem chamar am clnstratzn Na verdade, nio pode criar um
novo objeto sem chamar nio s6 o constnrtor do tipo de classe real do objeto, como tamb6m o construtor de cada ana de
suas superclassetlConstrutores sio o c6digo que serl executado sgTple. q.Ye voc6 usar a palavra-chave new. OK, para
sermos um pouco mais precisos, pode haver tamb6m blocos de inicializagio que executem quando voc6 usar new,
mas iremos abordiJos (os blocos de inicializagio), e as suas contrapartes estiticas, no pr6ximo capitulo. Temos
muito que discutir aqui - examinaremos como os construtores sXo codificados, qaem os codifica e como funcionam
no tempo de execugXo. Portanto, pegue seu capacete e um martelo e executemos a construgio de alguns objetos.
class Foo {
roo0 ( | ll o constrirtor para a claEse foo
)
Notou o que est6 faltando? I'{do htl tipo de retomolLembre-se de que um construtor nio possui tipo de retorno, e seu
nome deve coincidir exatamente com o nome da classe. Normalmente, os construtores sio usados para inicializar
o estado de variiveis de instAncia. como descrito abaixo:
class Foo {
int size;
Qlri nd nama.
Fan
r vv I\ve!+rrY
efri nn nam6 i nf ci za\ {
this.name = name;
this.size = size;
No c6digo do exemplo anterior, a classe Foo n5o possui um construtor sem argumentos. Isso significa que o
c6digo a seguir ndo seri compilado,
Foo f = new Foo O ; / / Ndo vai compilar, nao h5 um construtor correspondente
mas a linha a seguir ser6 compilada,
Foo f = new Foo("Fred", 43); // problemas. os argumentos correspondem ao
Sem
//construtor de Foo.
Portanto, 6 muito comum (e desejivel) que uma classe tenha um construtor sem argumentos, independente de
quantos outros construtores sobrecarregados existam nela (sim, os construtores podem ser sobrecarregados). Voc6
nno conseguiri fazer com que isso funcione sempre em suas classes; ocasionalmenrc terh uma classe em que nio
far6 sentido criar uma instAncia sem fornecer informag6es para o constnrtor. IJm objeto j ava. awt.Color, por
exemplo, nio pode ser criado com uma chamada a um construtor sem argumentos, porque isso seria o mesmo que
dizer iJVM: "Crie um novo objeto Color para mim e nio vou me preocupar com a cor real que ele ter6,...Vocd
escolhe". Voc6 realmente quer que a JVM tome as decis6es est6dcas no seu lugar?
Cadeia de construtores
Sabemos que os construtores serXo chamados no tempo de execugio quando voc6 digitar new em algum tipo de
classe como vemos abaixo:
Horseh=newHorseo;
78 Copitulo 2: OrientoEdo o obietos
Mas o que ocorreri realmente quando voc6 digitar new Horse ( ) ? (Assuma que Horse estende Animal e que
Animal estende Object.)
1. O construtor de Horse ser6 chamado. Todo constnrtor chama o construtor da sua superclasse com uma
chamada (implicita) a super ( ) , a nlo ser que o construtor chame um construtor sobrecarregado da
mesma classe (falaremos mais sobre isso em instantes).
2. O construtor de Animal seri chamado (Animal 6 a superclasse de Horse).
3. O construtor de Object ser| chamado (Object 6 a superclasse final de todas as classes, portanto, a classe
Animal estenderi Object ainda que voc6 nio digite realmente "extends Object" em sua declaraEio. Estari
implicito). Nesse ponto estaremos no inicio da pilha.
4. As vari6veis de instAncia de Object receberio seus valores explicitos. Por explicitos, queremos dizer os
valores que slo atribuidos no momento em que as varilveis sio declaradas, como "int x = 27", onde
"27" 6 o valor explicito (e nio um vaTor padrio) davariSvel de instAncia.
5. A execuEio do construtor de Object ser6 concluida.
6. As variiveis de instAncia de Animal receberio seus valores explicitos (se houver).
7. A execuglo do construtor de Animal ser6 concluida.
8. As vari6veis de instAncia de Horse receberio seus valores explicitos (se houver).
9. A execugio do construtor de Horse seri concluida.
A Figura 2-6 mostra como os construtores funcionam na pilha de chamadas.
4. Object o
3. Animal O calls super ( )
T Uma chamada a super ( ) pode ser sem argumentos ou incluir os argumentos passados para o construtor da
zuperclasse.
IJm construtor sem argumentos nio ser6 necessariamente o constnrtor padrio (ou seja, o fornecido pelo
compilador), apesar de ele nunca ter argumentos. O coushzrtorpadrio i o que o nntpikdorfomecelEmborio
JAVA 5 79
construtor padrio nuncatenha argumentos, voc6 pode inserir seu pftipit construtor sem argumentos.
t podeni,fazer uma chamada ao m6todo de uma instAncia, ou acessar uma vari6vel de instAncia, at6 que
ndo
Y?:€
tenha executado o construtor da superclasse.
I Apenas vari6veis e m6todos static p9{eqr s9r acessados como pafte da chamada a super ( ) ou this (
) . (Exemplo: super (Animal . NAME )) 6 v6lido, porque NAME 6 declarada como uma variivel static.
I As classes abstract t6m construtores e eles sio chamado s serupre que uma subclasse concreta 6 instanciada.
r As interfaces ndo t6m construtores. Elas nio fazem pane da irvore de heranga de um objeto.
r A
$i1 maneira pela qual um constmtoS pode ser chamado 6 dentro de outro construtor. Em outras palavras,
voc€ nio pode escrever um c6digo que chame efetivamente um construtor como vemos abaixo:
class Horse {
Horse0{}//construtor
rroid dnQirr+Fl\ I
class Horse ( )
no ponto exato. O compilador gerarS,tmconstnrtor padrXo para a classe anterior, porque nio foi
{Bpr3,chegamos
celrnroo nennum construtor para ela.
Certo, e quanto a esta classe?
rlaqq IJ^rc6 f 1
void Horse( ) { }
i
Pode paruer que o compilador nlo crrari um construtor, porque ji existe um na classe Horse. Existe mesmo?
\-rDserve novamente a classe Horse anterior.
Oque hi de errado com o constnrtor Horse( )?.Ele nio 6 de forma alguma um consrrutor! E simplesmente um
m6todo que por acaso tem o mesmo nome da classe. Lembre-se de que o tipo de retorno 6 uma
fista certa de que
estamos olhando para um m6todo, e nio um constnrtor.
Como voce pode ter a certeza de que um construtor padrio seri criado?
Isso ocorreri quando aocd ndo criar nenhum construtor em sua classe.
Como voc6 poder6 reconhecer o construtor?
Da forma a seguir:
I O construtor padrXo te ri o mesmo modfirador dt acesso da classe,
A Tabela 2-4 mostrao que o compilador gerari (ou nio) para sua classe.
class Foo {
roo( ) {
cfass Foo { } Eulrer ( );
)
)
class Foo {
cfass Foo { } Foo( ) {
FooO {} Euper( ),
] )
]
class Foo {
public roo() {
nrr].'linalaceFnn {l super( );
)
]
class Foo {
class Foo { } F^^/qfrinn q\ I
I,OO(Srrngs) tJ auper( );
) ]
)
class Foo { }
!oo(Scrfngsl tj Nenhum , o compilador nao precisa inserir
super ( ) ;
]
]
cfass Foo {
void Foo O {}
class Foo { ) roo() (
voidFooO {} super( );
] )
]
(void Foo O 6 um m6todo, nao um construtor.
O compilado r avrsarique voc6 nio pode chamar takeInt ( ) sem passar um tipo int. E 9laro. qg9-o- .
compil;dor aprecia urrenigma ocasional, portanto, a mensagem que exibir6 em algumas vers6es da JVM (pode
variar com a verseo) nio seri tio clara:
UseBar.java:7: takelnt(int) in Bar cannot be applied to o
b. takelnt O ;
Mas voc6 a entender6. A conclusio 6 que deve haver uma corresponden cia para o m6todo. Por correspondAncia,
queremos dizer que os tipos dos argumentos devem poder aceitar.os valores ou varilveis que voce estiver
passando e na oraem em que forempassados. O que nos conduz de volta aos constnrtores (e voc6 Pensou que
nunca chegariamos neles), que funcionam exatamente da mesma maneira.
JAVA 5 8I
Assim, se o construtor de sua superclasse (isto 6, o constnrtor de sua superclasse,/parent imediata) tiver
argumentos, voc6 teri que inserii a chamada a super ( ) , fornecendo os argumenros apropriados. Ponto crucial:
sesua suPerclasse ndo tiver um constnrtor sem argumentos, voc6 tenl qte ins#. rr* .orrt-ior em sua cl"rse (a
subclasse) Porque precisard de um local para inserir a clianado ao nnstrutor da s'upockss, cvm 0r atgamentus
@ropiadot.
O c6digo a seguir 6 um exemplo do problema:
^l ^^^
Lfq-r rulrrrrqa
^61*-l 1
super0; // Problernal
j
E, novamente, o compilador nos tratari com uma clareza impressionante:
Horse. java:7: cannot resolve symbol
symbol : constructor Animal_ ( )
location: class Animal
superO; // Problema!
Se voc6 tiver sorte (e for lua cheia), seu compilador talvez seja um pouco mais explicito. Mas novamente, o
problema ser6 o.fato de nlo haver uma corrispondAncia para o q.ri.rt"*os tentando chamar com super ( )
um construtor de Animal sem argumentos.
Outra maneira de colocar isso 6 que se sua superclasse ndo tiaer am consttator tem argllmentus, entio, em tua tubc/asse
uoc6 nio
podenl usar o conshvtorpadrdofomecidipek nrpilador. E simples assim. que o coirpilador s6 pode inserir a chamada a
Ji -
um construtor super ( j sem arg,rmerrios, voc6 nio conseg,riri rr.* -.r-o compilar;lg" .;;; ; lafii.
segurr: "--
class Clot.hing i
Clothing(String s) { }
)
class TShirt extends Clothing { }
IJma.tentativa de compilar esse c6digo nos traria o mesmo erro que obtivemos quando inserimos um construtor
na subclasse com uma chamada i versio sem argumentos de super ( ) :
Clothing. java: 4: cannot resolve symbol
<rmlrnl . .^ncf rrr^f ar ll nrlr.ir1f1r9
na / \
\ /
Na verdade, o c6digo anterior de cloching e TShirt 6 implicitamente o mesmo mostrado a seguir, no qual
fornecemos um construtor para TShirt que 6 id6ntico ,o .onrt*tb, padrlo fornecido pelo compilador: "
class Clothing {
Clothang(String s) t )
]
class Tshirt extends Clothino {
t t constrl.,,tor identico ao construtor cadrdo
,/ / f ornaai dn nal n anmni I
^^^-
Tshirt ( ) {
supero; // Ndo vai funcionar!
j // Chama um construtor sem argumentos Clothing( )
normalmente o sio.
Construtores sobrecarregados
Sobrecarregar um consrruror significa inserir v6rias vers6es dele, cada uma tendo uma lista de argumentos
diferente, como nos exemplos a seguir:
class Foo {
roo0 { }
Foo(String s) { }
A classe Foo anterior possui dois construtores sobrecarregados, o que usa.uma string e outro sem argumentos. Ji
que nio h6 um c6digo na versXo sem argumentos, na verdade, idAntica ao construtor padrio. que o
essa classe 6
compilador fornece."Mas, lembre-se de que como j6 existe um construtor nessa classe (o que usa uma string), o
.o*pil"dor nio fornecer6 um construtor padrXo. Se quiser que um construtor sem argumentos sobrecarregu.e a
lr.rrio com argumentos que voc6 j6 tem, tir6 que inseii-lo por sna conta, exatamente como no exemplo de Foo.
A sobrecarga de um construtor normalmente 6 usada para fornecer maneiras alternativas de os clientes
instanciareir objetos de uma classe. Por exemplo, se o-cliente souber o nome d9 animal, poderi pass6-1o para
".-
um construtor de Animal que use strings. Mas se ele nio souber o nome, poderi chamar o constnrtor que nio usa
argumentos, e este fornecei6 n* tto-. padrlo. Veja como funciona:
1. public class enimal {
2. String name;
3. Animal(String name) {
4. this.name = name;
s. )
7. Animal O {
8. this (makeRandomName O) ;
10.
11. Etatic String makeRandomNameo {
1,2. int x = (int) (Math.random(1 * 5);
1-3. String name = new Stringi] {"Fluffy", "Fido"'
"Rover", "Spike",
"Gigi"] [x] ;
L4. return name;
15. )
]-6.
17. public static void main (String [] args) i
18. Animal a = new animal0;
L9. System.out.println(a.name) ;
20. Animal b = new animal("zeus");
21. System.out.println(b.name) ;
22. ]
23. \
A execuglo desse c6digo quatro vezes produzir| a saida:
t java Animal
Gisi
Zeus
JAVA 5 83
I java Animal
Fluffy
Zeus
t java Animal
Rover
I java Animal-
Fluffy
Zeus
Muita coisa aconteceu no c6digo anterior. A Flgur_a 2-7 mostra a pilha de chamadas de construtores quando um
constnrtor 6 sobrecarregado. Examine a pilha de chamadas e, em seguida, percorreremos o c6digo desde o inicio.
r Linha 2 Declara avari|vel de instAncia de String nana
r Linhas3 a5 Insereoconstrutorqueusastringseoatribuiavari6vel deinstincianane.
r r,inha
T P ^qy;que fica divertido. Suponhamos que cada animal precise de um nome, mas o cliente (o c6digo
chamador) pode nio saber qual deve ser usado, porta.rto, voc6 attuir6 um nome aleat6rio. O construtor seir
argumentos gerarS, vm nome chamando o m6todo makeRandomName( ).
4. object ( )
r Linha 13 Sabemos que 6 uma sintaxe estranha. Estamos criando um novo objeto String (apenas uma instincia
de String), mas. queremol gue a string seja selecionada aleatoriamente em uma-lista. 56 {ue nio temos a lista,
portanto, precisamos cri6-la. Assim, apenas nessa linha de c6digo:
1. Declaramos uma vari6vel de String, nane.
r Linha 18 Estamos chamando a versio sem argumentos do construtor (fazendo com que um nome aleat6rio
da lista seja selecionado e passado para o outro construtor).
84 Copitulo 2: Orientog6o o objetos
f Linha 20 Estamos chamando o constnrtor sobrecarregado que usa uma string representandQ o nlme.
O ponto chave a exrrair desse exemplo de c6digo esta na finha 8. Emvez de chamar super ( ) , estamos
chimando this ( ) que nmpre tWtf* una chinad.a a uatro cunstrator da mesma classe. Certo, mas o que aconteceri
depoisdachamada a this ( )i CJo outarde o construtor super ( ) ser6 chamado, nXo 6? L6gico..Uma.
cfr"-"d" a this ( ) significa apenas que vocA esti retardando o inevit6vel. Algum construtor' em algum local,
ter6 que Iazer a chamada a super ( ) .
Regra chave: a primeira linha de um construtor deve ser uma chamada a super ( ) ou a thig ( ).
Sem exceg6es. Se voc6 nXo tiver nenhuma dessas chamadas em seu construtor, o compilador inserir6 a chamada
semargumenrosasuper( ).Emoutraspalavras,seoconstrutorA( )tiverumachamadaathis( ),o
compiLdor saberi que ndo seri esse construtor que chamari super ( ) .
A regra anterior quer dizer que um construtor nunca pode ter tanto uma chamada a super ( ) quanto a this (
I . J6 que essas chamad"r p.eiim* ser a primeira instrug-Xo de um construtor, voc6. nio.pode usar de maneira
^.onrtrutor.
vilida as duas no -.r-o Issb tamb6m significa que o compilador nio inserir6 uma chamada a su-
per ( ) em um construtor que possua uma chamada a uhis ( ) .
Pergunta a se considerar: O que vocA acha que acontecerisetentar compilar o c6digo a seguir?
class A {
AO{
this("foo");
)
A(String s) {
this O ;
)
)
Seu compilador pode nio captar o problema (isso variari dependendo do compiladgl ml1 a maioria nXo
perceberi o pro6lema). Ele presumir6 que voc€ sabe o que esti fazendo. Conseguiu identificar a falha?-Dado. que o
'.onrt*to,
d. .t-" superclaise deve seriempre chamado, onde a chamada a super ( ) seria inserida? Lembre-se
de que o compilador nio vai inserir rr- .onit*tor padrio se voc6 i6tiver um ou mais construtores em sua classe.
Mesmo assim, ele aindainsere uma chamada a super ( ) em algum construtor que nlo tenha explicitamente uma
chamada ao construtor da superclasse - a menos que o construtor_ ji tenhauma chamada a this ( )' Ponanto, no
c6digo anterior, onde srrpei ( ) pode ser inserido? Os rinicos dois construtores da classe t6m chamadas a
thi; ( ), evoc6 obter6e*at"metrte o mesmo que conseguiria se digitasse o c6digo do m6todo aseguir:
public void goo t
doStuff ( ) ;
)
public void doStuff ( ) {
go(),.
)
AgoravocE consegue enxergar o problema? E claro que sim. Apithafoi exndida!Elaficou maior e maior, a!6 qu9 .
siirplesment. r. e o i6dig" do m6todo foi deiramado, esvaindo-se parafora daJVM e.caindo no chio. Dois
ibtin
.orrit-tor.r robrecarregados chinando this, sio dois construtores chamando um ao outro. Repetidamente, resultando em
* java A
Exception in thread \\main" java. Iang. StackOverflowError
O beneficio de ter consrrutores sobrecarregados 6 que voc6 oferecer6 maneiras flexiveis para a instanciagio de
objetos de sua classe. A vantagem de um construtor que chame outro construtor_sobrecarregado 6 evitat a
duplicaglo do c6digo. No exeLplo de Animal, nio hlvia nenhum c6digo a16m da co_nfiguragio do nome, mas
i*agine se depois d-a linha 4 houvesse ainda mais trabalho a ser feito no construtor. Pela insergio de tod-as as
t"raLt um constnrtor e, em seguida, fazendo 9om qge outros construtores o chamassem, voc6 nio teria
"ttr "p6tt"r
que escrerrei e fazer a manutengio de v6rias vers6es do c6digo desse construtor imponante. Basicamente, os
.b.rrt*to.., que nio fossem ,.iarr"rrt., chamariam esse outro constnrtor sobrecarregado, passando para ele os
dados que precisasse (dados que o c6digo-cliente nio forneceu).
Os construtores e a instanciagio se tornarXo ainda mais interessantes (agora que vocA achou que estava livre) _
quando chegarmos )s classes internas, mas sabemos q-ue voc6 s6 poder6 suportar tanta diversXo em outro capitulo,
ponanro, esramos guardando o resto da discussio sobre instanciagio de classes internas para o Capitulo 8.
JAVA 5 85
Obletivo poro o CertificoEdo
Imaginemos outro cen6rio: suponha-que voc6 quisesse ter uma contagem ininterrupta de todas as instAncias
criadas _a partir de uma classe ispecifi-a. Onde irmazenaria essa variivel? Nio funcionar6 mant6la em uma
vari6vel de instAncia dentro da Classe cujas instAncias voc€ est6 registrando, porque a contagem ser6 reinicializada
com um valor padrlo a cada nova instAncia.
$ lesposta tanto parao cenlrio do m6todo utilitirio, sempre executado da mesma forma, quanro para a contagem
ininterrupta do total de instAncias 6 usar o modificador static. As variiveis e m6todos marcados co"m static
Pertencem i
classe, emvez de a qualquer instAncia especifica. Na verdade, vocA pode usar um m6todo ou variivel
static sem ter absolutamente nenhuna in$incia dessa classe. 56 precisa ter a classe disponivel para poder chamar um
m6todo static ou acessar uma variivel As variiveis static. tamt6tn static poi.-
ier acessadas sem ter
a instincia de uma classe. Mas se houver instAncias, avari|vel static
dessa classe ier6 companilhada por todas
as instAncias da classe; s6 haveri uma c6pia.
No c6digo anterior, a vari|vel static frogCount 6 configurada com zero, quando a classe Frog 6 carregada pela
priqgira vez pela JVM , antes que qualqaer a)aat (A prop6sito, ioc€. nilo precisard rellmente "
instdncia de Frog rc1a '
inicializar uma vari6vel static com zero; as variiveis est6ticas iecebem ot
-"r*or-rralores padrlo que as
varilveis de instAncia). Sempre que uma instAncia de Frog for criada, o construror ser6 executado e arrmlentari o
valor da vari6vel est6tica f rogCount. Quando esse c6digo for executado, tr6s instAncias de Frog serio criadas
emmain( ) e o resultadoser6:
Frog count is now 3
Agora imagine o que aconteceria se frogCount fosse uma variivel de instAncia (em outras palavras, ndofosse unidc):
Quando c6digo for executado, ainda criari tr6s instAncias de Frog em main ( ) , mas o resultado seri... Um
esse
erro do compilador! Nunca poderemos fazer esse c6digo ser executado, porque nem ele mesmo ser6 compilado.
class Frog {
i nf f rnaanrrhf - n. // DecTara e inicializa a vari6vel de instAncia
nrrhlin !E'r^ft/\
+vv \ / /L
fr^d/l^rrnf
rrvvvvsrrL r-,
-
1.
r, / / Nlodifica o valor do construtor
1
)
86 Copitulo 2: OrientoE6o o obietos
public static void main (String [] args) {
new FrogO;
new Frogo;
new FrogO;
System.out.println("Frog count is now " + frogcount);
]
AJVM nio sabe que objeto Frog de frogCount voc6 est6 tentando acessar. O problema 6 que opr6prio m6todo main (
) E estitico ., po.t*to, nio e# sendo"executado em relagio a lenhuma initAncia espegiTil" 4 classe, em vez disso
est6 relacionadb apenas a classe. Um m6todo static nXo pode acessar uma vari6vel (de instincia) nlo static,
porque falar que nio h6 instincias da-classe ativa na mem6ria e, mesmo se houvesse, o m6todo
ndo b,l ana instincialSem
nio O mesmo se aplica a m6todos de instAncia; um m6todo static nio pode
saberia nada sobre elas.
"trti. diretamente um m6todo nio staLic. Considere static : classe, nlo stat.ic : instlncia. Tornar o
chamar
m6todo chag{9 pelaJVM-(main ( ..)) static significa que aJVM nio teri que criar uma instAncia de sua classe
apenas para iniciar a execugio do c6digo.
class Foo {
int x = 3;
public static void main (String [] args) t
System.out.println("x j-s " + x) ;
)
]
E bon qae aoc6 saiba qae use aidigo nunca uri compilado, porque n6o 6 possiuel acessar uma uariiuel n6o sEaLic (de instdnciQ a patir
de um mitodo static. Apenas inagine o compilador diqpndo 'Ei, ndo tenbo iddia de que uaiduel x do objeto Foo aocd ettui tentando
exibir!" I-,embre-rc de qae t4 a cksse que execata o mitodomain ( | e ndo uma instdncia da classe. E claro que aparte corrplicada no
exane seni qae a perglnta ndo pareceni tdo 6bria quanto o c1digo anterior. O problena sobre o qual uocd estari sendo aualiado acesiar tlma -
uariduel ndo sLatic a paftir de am mitodo static senl. canuflado no aidigo qle pareceni aaa/iar oatra qautdo, Por exempk, seria
-
mais prouduel que o cddigo acina aparecese naforwa:
class Foo {
int x = 3;
fl-oatY=4.3f;
public static void main (String 1l args) {
for (int z = x; 7 < ++xi z-, Y = Y + z\ {
/ / c6digo complicado de looping e branching
)
Portanto, efiquantr uoc6 ertiaesse tentando acompanbar a hgica, o problena real seia qile x ey ndo poden ser ttsados dentro de main (
),porquesdoaaridaeisdeinstdnciaendostaticlOmetnose@/icaa0acervdemdtodosndosLaLic apanirdcummdtodo
static. Aregrai,omitodo static deumaclassendopodeacessarilmnembro-mitodoouaariiuel-ndouhitico(deinstdncia) de
int frogSize = 0;
nrrhlia
vgvf!v+fr9Yv9rrvVv*!v\,
in{- aat-FranQizaI\ I
return frogSize,'
JAVA 5 87
public Frog(int s) {
frogSize = s;
)
public static void main (String [] args) {
Frog f = new Frog(25);
System.out.println(f.getFrogsizeO); / / Acessa o m6todo da instAncia usando f
)
No c6digo anterior, criamos uma instAncia de Frog, a atribuimos a variavel de refer6ncia f e, em seguida, usamos
essa referenciapara chamar um m6todo na instdnciaFrogque acabartos rriar.Emoutras palavras, o m6toio
getFrogsize ( ) est6 sendo chamado em um objei6 Frog especifico na memona.
Mas essa abordagem (usar a refer6ncia a um obieto) nio 6 apropriada para acessar um m6todo static. Doroue
pode nio haver absolutamente nenhuma insdncia da classei Portanto, a maneira de acessarmor .rm '
static (ou vari6vel static) serl usar o operador ponto n0 nome da classe, e nio na refer6ncia a uma-6ioldo
instAncia,
como vemos abaixo:
c]ass Frog {
static int frogCount = 0; // Dec]ara e inicializa a vari6vel static
public rrog O t
frogCount += !; / / Modifica o valor do construt.or
]
]
c]ass TestFrog {
public static void main (Stri_ng [] args) {
new FrogO;
new FroqQ;
new FrogO;
System.out.print("frogCount: "+Froq.frogCount.); //Acessa a vari5vel static
Mas apenas. p ar.a.tornar isso realmente confuso, a linguagem Java tamb6m permite que voc6 use uma uai,iuel de
refer€ncia de objeto para acessar um membro static:
Frogf=newFrog0;
int frogs = f.getFrogCount()t // Acessa o m6todo est6tico getFrogCount usando f
No c6digo anterior, instanciamos um objeto Frog, atribuimos esse novo objeto a variivel de refer0ncia f e, em
seguida, usamos a referAncia I para charnar um m6todo static! Mas mesmo que tenhamos usado uma instAncia
especifica de Frog.para acessar o m6todo static,-as^regras nio.foram alteradas. Isso 6 simplesmente um truque de
sintaxe para permitir que voc6 ase rrma uariduel de refer6ncia de objeto (mas nXo o objeto que ila referencia) pari
acessar uma variivel ou m6todo static, mas o membro stat.icainda nio tem conhetimento da instAncia
especifica usada para cham6lo. No exemplo, o compilador sabe que a refer6ncia f 6 do tipo Frog e, porranro, o
m6todo staticda classe Frog 6 executado sem conhecer ou se preocupar com a instAncia na outri exremi&de da
refer6ncia f. Em outras palavras, o compilador s6 se preocupari com o fato de a referdncia f ser declarada com o
tipo Frog. A Figura 2-8 ilustra os efeitos do modificador stat.ic sobre m6todos e variiveis.
Outro ponto a lembrar 6 que os n,itodos static ndopodem sersobrecarregadar! Isso nXo significa que eles nio possam
ser redefinidos em uma subclasse, mas redefinir e sobrecarregar ndo sio a mesma coisa.
)
class Dog extends Animal- {
static void dostuffO { // 6 uma redefinigd.o,
88 Copftulo 2: Orientogdo o objetos
/ / nd'o uma sobrescrj-qdo
System.out.print ( "d ") ;
)
public static void main(string [] args) {
Animal tl a = {new Animal O , new DoSO ' new Animal O };
for(int x = 0,' x < a.length; x++)
alxl.dosuuf,f Ot | / cli;ama o m6todo static
)
)
Lembre, a sintaxe a [x] .doStuf f ( ) 6 apenas um atalho (o truque da sintaxe)... O compilador usar6' emvez
disso,algocomoAnimal .doStuff O.Reparequenlousamosaquioloop for apimoradoloJava1.5
(abordaJo no Capitulo 5), embora pud6ssemos t6lo feito. Espere ver uma mistura de estilos de programaglo e
pr6ticas deJava 1.4 eJava 5 no exame.
classe Foo
int size = 42; O m6todo static neo 6 capaz de
slatic void doMore( ){ acessar uma variivel de inst6ncia
int x = sVe; (nio-static)
]
classe Bar
void go ( ); O m6todo static ndo 6 capaz
stat,ic. void doMore ( ){ de acessar um m6todo nio-
J
fft ); static
classe Baz
sEatic int count; O m6todo static 6 copoz de
static void woo( ){ } acessar um m6todo ou uma
static void doMore( ){ variivel static
woo( );
i nF v .
- ^^irnF
)
Ji vamos admitir logo de cara. As definig6es do exame da Sun para coeslo e acoplamento gi9 u-m tanto subjetivas, de
modo que o que e$;mos discutindo neste capitulo 6 do ponto de,vista do exame, que nio 6 de forma nenhuma a
verdade absoluta sobre esses dois principios OO de projetos. Pode nio ser exatamente a forma como voc6 os
aprendeu, mas 6 o que vocA precisa entinder para responder as quest6es. Haveri bem poucas quest6es sobre
acoplamento e coesio no exame real.
JAVA 5 89
t6picos, acoplamento e coesio, t6m a ver c.om a qualidade de um projeto oo. Em geral, o bom projeto
RXt l?k acoplamentofraco
oo pede e evita o fofte, e pede tamb6m aha coetdo e evita a baixacoesio. ComJ na maioria ias'
drscuss6es sobre projetos OO, os objetivos para a aplicaqio sio
r Facilidade de criagio
I Facilidade de manurengio
r Facilidade de melhorias
Acoplamento
Vamos comegar f.azendo uma tentativa de definigio do_ acoplamento. Acoplamento 6 o grau em que uma classe
conheceoutraclasse.Seorinicoconhecimentoque.aclasseAtemsobreaclasseB6oqieaclasseBexp6satrav6s
dasua interface, entio diz-se das classes A e B qui-elas t6m acoplamento fraco... E isso 3 bom. Se, por o^utro lado,
a classe A,depende de panes da classe B quc nib fazemparte da interface da classe B, entio o
as classes 6 mais forte... E isso nlo 6 bom. Em outras palavras, se A ".oplr*.nro."r..'
sabe mais do que deveria sobre a maneira pela
qual B foi implementada, entio A e B t6m acoplamenio forte.
lJsandocste segundo cenirio, imagine o que acontece quando a classe B 6 aprimorada. E bem possivel que o
desenvolvedor que esteja aprimorando.a classe B ne* saib" da exist6ncia da classe A, afinal po. qrr. dev'eria? O
desenvolvedor da classe B deve panir do principio que quaisquer melhorias que nio danifiqfuem a interface da
classe deverlo ser seguras, entio.ele pode modificar pirte da classe que nlo se refira ) interface, o que
entio f.az a classe A ser danificada. "lg,rm"
Opiorcasopossivel6ahorrivelsituagioemqueaclasseAsabedecoisasnio-relativas)APlsobreaclasseB,ea
classeB sabe de coisas nio-referentes i API sobre a classe A... Isso 6 MUITO RUIM. Se qualquer uma das claises
for modificada, 6 possivel que a outra seja danificada. Vejamos um exemplo 6bvio de ..opl"-.rrto fone, que
resultou de um encapsulamento mal feito:
class DoTaxes {
float rate;
float doColorado O {
SalesTaxRates str = new SalesTaxRates ( ) ;
rate = str.salesRatei // oh nio
// isi.o deveria ser uma chamada a m6t.odo:
/ / raLe = str.qetSalesRate (..CO', ) ;
/ / faz coi-sas com rate
)
)
class SalesTaxRates {
guJrlic float salesRate; / / deveria ser private
pubJ.ic float adjustedSalesRat-e; / / deveria ser private
]
Todas as aplicag6es OO nietriviais slo uma mistura de muitas classes e interfaces rabalhando juntas. O ideal seria que
todas.as interag6es entre objetos em um_sistema OO usassem as APIs, ou seia, os contratos, das respectivas'classes
dos objetos. Teoricamente, se todas as classes de uma aplicagio tiverem APis bem elaboradas, entXo deveria ser
possivel que todas as interag6es interclasses as usassemtxclusivamente. Como discutimos anteriormente neste
capitulo, um aspecto do bom projeto de classes e de APIs 6 que as classes devem ser bem encapsuladas.
A questio 6 que o acoplamento 6 um conceito um tanto subjetivo. Por causa disso, o exame ir6 lhe testar em
exemplos realmente 6bvios de acoplamento forte; nio lhe ser6 pedido que faga julgamentos sutis sobre o assunto.
Coesio
Enquanto que o acoplamento tem a ver com a forma como as classes interagem umas com as ouuas, a coesio se refere a como
uma determinada classe foi elaborada. O termo coudo 6. usado para indicar o grau em que uma classe tem um rinico e
90 Copitulo 2: Orieniog6o o obietos
bem-focado prop6sito. Tenha em mente que a coeslo 6 um conceito subjetivo. Quanto mais focada for uma classe,
maior a ,rr" io.ieo - isso 6 bom. O principal beneficio da alta coesio 6 que tais classes normalmente sXo de
manutenglo muito mais f6cil (e sio modificadas com meno.s freq-ii6ncia) do.que as classes com baixa coesio. Outro
beneficio'da alta coesio 6 que as classes com um prop6sito bem focado tendem a ser mais reutiliziveis do que outras'
Vejamos um exemplo de pseudoc6digo:
'ld;ri:':::T*::::.i.
{ }
void saveToFil-eO { }
void print0 { }
j
Agora imagine que o seu gerente chegue e diga "Ei, sabe aquela aplicagio de contabilidade em que estamos
tribalhand6t Oiclientes icabaram dJdecidiique eles tamb6m vio querer gerar um relat6rio de projegio de
receitas, ah, e eles tamb6m querem fazer alguni relat6rios de inventirio._Mas eles gostaram dos nossos recursos de
relat6rios, entio certifiqu.-r. d. que todos-esses relat6rios permitam a eles escolher um banco de dados, escolher
uma impressora e salvar os relat6rios gerados em arquivos"... Oh, nXo.
Em vez de colocar todo o c6digo de impressio em uma s6 classe de relat6rios, provavelmente ser6 melhor usar o
seguinte projeto desde o comego:
class BudgetReport {
Options getReportingOptionsO { }
void generateBudgetReport(Options o) { }
cl-ass Connect.ToRDBMS {
DBconnectj-on getRDBMSO { }
l
class PrintStuff t
PrintOptions getPrintoptionsO { l
)
class Fil-eSaver {
SaveOptions getFileSaveoptionsO { }
Este projeto 6 muito mais coeso. Em vez de uma classe que faz tudo, dividimos o sistema em quatro classes principais, ca&
tr-" iom .rm papel bastante especifico, ort clero. Uma vei que n6s construimos essas classes esp eirafizadas e reuttlrzl.veis,
serl muito rnaii f6cil .t..err.i um novo relat6rio, vmavez que j6 temos a classe para a conexio ao banco de dados,
a classe para impressXo e a classe que salva os arquivos, e isso significa que elas podem ser reutilizadas Por outras
classes que possam querer imprimir um relat6rio.
Abordamos E-UM e TEM-IIM. n-UVt 6 implementado usando-se a heranga, e TEM-UM 6 implementado usando-se
variiveis de instAncias para se referirem a outros objetos.
O polimorfismo veio em seguida. Embora o tipo de uma variivel de refer0ncia nio possa ser modificado, ele pode ser
*rdo p".* r. .eferir a um o6jeto cujo tipo seja um subtipo do seu pr6prio. Aprendemos como determinar quais m6todos
sio invociveis para determinada variivel de referOncia.
JAVA 5 9I
Examinamos. a diferenga entre m6todos sobrescritos e sobrecarregados, aprendendo que o m6todo sobrescrito
ocorre quando umasubclasse herda o m6todo da superclasse, e, entio, o reimpleme ni^ p^r^adicionar um
comPortamento mais especializado. Aprendemos que no tempo de execugio, a
JVM chamar6 a versio da
subclasse em uma instAncia dessa subclasr. . .rr.rr^io da superclass" .* u*" instAncia da superclasse. Os
"
m6todos abstract deuem. ser.sobrescritos (ncnicaruente os m6todos abstract devem ser ifihnentados, endo
sobrescritos, j6 que, na verdade , niolrd nada asobrescrever).
Vimos que os m6todos novos devem manter a mesma lista de argumentos e tipo de retorno (ou, do
Java 5 em
diante,, eles podem retornar um.subtipo do tipo de retorno decllrado do m6todo sobrescrito da srp.rclasr.f do
m6todo sobrescrito e que o modificador de acesso nio pode ser mais restritivo. O m6todo nono t"-b6* nio pode
langar nenhuma excegio verificada nova ou mais abrangente que nlo tenha sido declarada no m6todo ,obr.rcrito.
Voc6 tamb6m aprendeu que o m6todo sobrescrito pode ser chamado com o uso da sintaxe
super.doSomething( ) ;.
Os m6todos sobrecarregados permitem que voc6 reutilize o mesmo nome de m6todo em uma classe, mas com
argumentos diferentes (e op.cionalmente, um tipo deretorno diferente). Enquanto os m6todos q,a,e sobrcsTeuem
outros ndo devem alterar a lista de argumentos, os m6todos sobruanegaiot preiso, faz|-lo. Por6m, diferente dos
m6todos novos, os sobrecarregados podem variar o tipo de retorno; o modificador de acesso e as exceg6es
declaradas da maneira desejada.
Aprendemos o funcionamento da conversio (em geral redutora), das vari6veis de referdncia, quando ela 6
necess6ria e cemo usar o operador insLanceof .
A implementagio de interfaces veio em seguida. As interfaces descrevem um contrato que a classe implementadora
deve segu.ir. As regras para s€ implementar uma interface sio semelhantes )quelas p".a i. estender rr*" .lass.
abstract. Lembre-se tamb6m de que uma classe pode implementar mais d. n*" interface, e que as interfaces
podem estender outra interface.
Tamb6m examinamos os tipos de retorno dos m6todos, e vimos que voc6 pode declarar o tipo de retorno que
quiser (supondo-se. que tenha acesso a uma classe para usar um tipo de retorno de refer6ncia a objeto), *.not
que esteja sobrescrito um m6todo. Com a excegio de um retornocovariante, um m6todo novo deve ier" o mesrrro
tipo de retorno do m6todo sobrescrito da superclasse. Vimos que enquanto os m6todos novos ndodevem alterar o
tipo de retorno, os sobrecarre gados poden fai€-lo (contanto que tanbi) alterem a lista de argumentos).
Para concluir, voc6 aprendeu que 6 vilido retornar qualquer valor ou variivel que possa ser implicitamente
convertido no tipo-de retorno declarado. Portanto, pbr eiemplo, short pode ier ietornado quando o tipo de
retorno declarado for um int. E uma referAncia a Horse pode ser retornada quando o tipo de-retorno declarado
for um objeto Animal (supondo que Horse estenda Animil).
Abordamos os constftrtores em detalhes, aprendendo que, se voc6 nio fornecer um construto r para a sua classe, o
compiladorinserir6um. O construtorgeradopelo compilidor6 chamado de consrrutorpadrio, e6 sempreumcon$ruror
sem argumentos com uma chamada sem argumentos a super ( ) . O construtor padrionunca seri gerldo se houver um
s6 construtor que seja na sua classe (independentemente dos argumentos que ele r.rse), entio, se voc6
lrecisar de mais de um
constnrtor na sua classe e_quiser usar um sem argumentos, ter6 de escrevA-lo voc6 mesmo. Tamb6m vimos que os
constnrtores nio sio herdados, e que voc6 pode se confundir com um m6todo que tenha o mesmo nome da classe
(9 lue_6 vilido). O tipo de retorno indica que um m6todo nio 6 um consrruror, uma vez que este riltimo nio tem
tipos de retorno.
N6s vimos como todos os construtores da 6rvore de heranga de um objeto serio sempre chamados quando o
o.bjel^g 6 instanciado usando-se new. Tamb6m vimos que os construtores podem ser sobrecarregados, o que
significa definir construtores com listas de argumentoi dife.etrt.r. Um construtor pode chamaioutro dimesma
classe com a palavra-chave this O , como se o constnrtor fosse um m6todo chamado this O . Vimos que todo
construtor precisa ter ou this ( ) ou super ( ) como a sua primeira instrugio.
Vimos os m6todos e variiveis static. Os membros static se associam ) classe, e nio a uma instAncia, de
modo que s6 existe uma c6pia de cada membro static. lJm erro comum 6tentar referenciar uma variivel de
instancia a partir de um m6todo static. IJse o nome da classe com o operador ponto para acessar membros
static.
N6s discutimos dois conceitos da programagio orientada a objetos, que sio o acoplamento e a coesio. O
acoplamento fraco,6 o estado desejivel para duas ou mais classes que-interajam rrriras.orn as outras atrav6s das
zuas_respectivas APIs. O acoplamento fone 6 o estado indesej6vel para duas ou mais classes que conhegam
detalhes internos sobre outra classe, detalhes nio revelados na API da classe. A alta coesio 6b estado desei6vel
para uma classe cujos prop6sitos e responsabilidades sXo limitados e bem focados.
E, s6 para lembrar, vocA aprendeu que o exame inclui perguntas ambiguas, elaboradas basicamerite para restar sua
habilidade no reconhecimento do quanto elas podem ser enganosas.
{ Exercicios r6pidos
Aqui estXo alguns dos pontos-chave de cada objetivo para certificagio deste capitulo.
92 Copitulo 2: OrientoE6o o obietos
tr TEM-UM significa que a instincia de uma classe 'tem uma" refer6ncia I instAncia de outra classe, ou a outra
instAncia da mesma classe.
tr 56 os m6todos herdados podem ser sobrescritos, e lembre-se de que os m6todos private nio sio herdados.
E Uma subclasse usar6 super. overridenMethodName ( )para chamar a versio da superclasse de um
m6todo sobrescrito.
EJ Sobrecarga significa reutllizar o mesmo nome de m6todo, mas com argumentos diferentes.
fl Os m6todos sobrecarregados:
D Devem ter listas de argumentos diferentes;
fl Podem ter tipos de retorno diferentes, contanto que as listas de argumentos tamb6m sejam diferentes;
El Podem ter modificadores de acesso diferentes;
E Podem lancar exceQ6es diferentes.
JAVA 5 93
E os m6todos de uma superclasse podem ser sobrecarregados em uma subclasse.
tr O polimorfismo 6 aplicivel i sobrescrigio e nio )sobrecarga.
Q O tipo de objeto (e nio o tipo da vari6vel de refer€ncia) determina qual m6todo sobrescrito seri usado no ternpo
cte execugao.
tr O tipo de refer6ncia determina qual m6todo sobrecarregado ser6 usado no tempo de compilaglo.
tr M6todos com um tipo de retorno que 6 uma referOncia a um objeto podem retornar um subtipo.
E M6todos com um tipo de retorno que 6 uma interface podem retornar qualquer implementador.
E O construtor chamari o construtor de sua superclasse, que chamar6 o construtor de sua superclasse, e assim por
diante, at6 alcangar o consrrutor de Objea.
E O construtor de Object seri executado, retornando em seguida ao construtor chamador, que ser6 processado at6 sua
-eqii6nCia
conclusio, e por sua vez retornar6 ao construtor que o chamou; dando prosseguimento a essa at6 a execugio
do construtorda instAncia que estiver sendo criada.
E A primeira instrugio de todo construtor deve ser uma chamada a thi s ( ) (um construtor sobrecarregado) ou
super ( ).
94 Copitulo 2: Orientogdo o obietos
tr O compilador adicionarS,umachamada a super ( ),a menos que voc€ i|tenhainserido uma chamada a
this( ) ouasuper( ).
D Os membros de instAncia s6 podem ser acessados dqoir de o construtor da superclasse ser executado'
E As classes abstract possuem constnrtores que sio chamados quando uma subclasse concreta 6 instanciada.
O Chamadas a this ( ) e super ( ) ndo poden ficar no mesmo construtor. Voc6 pode ter um ou outro' mas
nunca os dois.
D A coesio refere-se ao nivel em que uma classe tem um rinico e bem definido papel ou responsabilidade.
E A alta coesio 6o estado desej6vel de uma classe cujos membros dio suporte a um rinico e bem definido papel ou
responsabilidade.
D A baixa coesio 6 o estado indesejivel de uma classe cujos membros dlo suporte av6rios pap6is ou responsabilidades
nio-focados.
Teste individual
l. Quais afirmativas sio verdadeiras? (Marque todas as corretas)
A Os relacionamentos Tem-Um sempre dependem da heranga.
B. Os relacionamento Tem-Um sempre dependem das vari6veis de instAncias.
C. Os relacionamento Tem-Um sempre precisam de pelo menos dois tipos de clasess.
JAVA 5 95
D. Os relacionamento Tem-Um sempre dependem do polimorfismo.
E. Os relacionamento Tem-Um sempre t6m acoplamento forte.
2. Dado:
class Clidders {
public final void flipperO { System.out.println("Clidder"l; }
]
public class Clidlets extends Clidders {
public void flipperO {
System. out.println ( "Flip a Clidlet" ) ;
super. flipper O ;
]
public static void main(String [] args) {
E. A compilagio falha
3. Dado:
public abstract interface Frobnicate { public void twiddle(String s); }
4. Dado:
class Top {
public Top(String s) { System.out.print("8"); }
]
Qual 6 o resultado?
A. eo
B. DB
C. eoc
D. DBC
E. A compilagio falha.
5. Selecione as duas afirmativas que melhor indiquem uma situagio com baixo
acoplamento. (Marque duas)
,4. Os atributos da classe sio todos privados.
E
F 14.
E
t
improvivel
I
que modificag6es feitas em uma classe vXo exigir modificag6es em outra.
6. Dado:
cfass Clidder {
private final- void flipperO { System.out.prj-ntln(..C1idder,'l; }
)
public class Clidlet extends Clidder {
public final void flipperO { System.out.println("C1idlet"); }
public static void main(String [] args) {
new Clidlet ( ) . flipper( ) ;
)
Qual6 o resultado?
,{. Clidlet
B. Clidder
C clidder
Clidlet
D. Clidlet
Clidder
E. AcompilaSofalha
JAVA 5 97
7. Usando os fragmentos abaixo, complete o seguinte c6digo de forma que ele com-
pile. ObseruagSo, talvez nio seja preciso preencher todos os espagos em branco.
C6digo:
class AgedP {
public AgedP(int x) {
]
i
public class Kinder extends AgedP {
public Kinder(int x) {
o;
j
)
Fragmentos: Use cada um dos seguintes fragmentos quantas vezes for preciso, ou deixe sem uso:
AgedP this
( ) t
8. Dado:
1. class Plant {
2. String getNameO { return "p1ant"; }
9. Dado:
1. class Zing {
2. protected Hmpf h;
E nl:cc umnf I )
10. Dado:
1. class Programmer {
2. Progranmer debugrO { return this; }
3. )
4. class SCJP extends Programmer {
5. // jtnsira o c6digo aqui
6. )
Qual op91o, inserida na linha 5, iri compilar? (Marque todas as corretas)
A. Programmer debug ( ) { return this,' }
B. SC.fP debugfo { return this; }
C.object debugr0 { return this; }
D. i-nt debug ( ) { return 1; }
E. int debug(int x) { return l-; }
F.Object debug(int x) { return this; }
I l. Dado:
class Uber {
staticinty=);
Uber(int x) { thiso; y = y * 2; }
Ubero { y++; i
)
class Minor extends Uber i
Minor0 { super(y) ; y = y + 3; }
public static void main(String [] arqs) {
na\^t Mi nnr 1\ .
])
Qual6 o resultado?
4.6
8.7
c.8
D.9
E. A compilagio falha.
F. SerS langada uma exceglo.
D. A coesio 6 o principio daprogramagio OO mais intimamente associado com o ato de se permitir que um mesmo
objeto seja visto como tendo muitos tipos.
JAVA 5 99
13. Dado:
1. class DoS { }
2. cl-ass Beagle extends DoS { }
3.
4. class Kennel {
5. public static void main(String [] arfs) {
6. Beagrle b1 = new Beagle ( ) ;
7. Dog dogl = new DogO;
8. Dog dog2 = b1-;
9. // insira o c6digo aqui
10. ) )
Qual opgio, inserida na linha 9, ir6 compilar? (Marque todas as corretas)
4. class Chrome {
5. public static void main(String [] args) {
6. X x1 = new XO;
7. X x2 = new yO;
8. Y yl = new YO;
9. // inslra o c6digo aqui
10. ) )
Qual opgXo, inserida na linha 9, ir6 compilar? (tr4arque todas as corretas)
A. x2.do2O;
B. (Y) x2.do2O;
C. ((Y)x2).do2O;
D. Nenhuma das instrug6es acima ir6 compilar.
Respostas
1 Best6correta.
A e D descrevem outros t6picos relativos ) programagXo OO. C est6 incorreta porque uma classe pode ter uma instAncia
de simesma. E estiincorretaporque, enquanto relacionamentostem-umpodemlevar aum acoplamento forte, nio 6
sempre que isso ocorre. (Objetivo 5.5)
3. B estl correta, uma classe abstract nio precisa implementar quaisquer m6todos de uma interface.
D est6 incorrera porque sobrecarregar um m6todo nio 6 o mesmo que o implementar. (Objetivo 5.4)
4. E est6 correta. A chama implicita a super ( ) no construtor de Bottom2 nlo pode ser satisfeita, porque nio hL
um constnrtor sem arg.rmentos em Top. lJm construtor padrlo, sem argumentos, 6 gerado pelo compilador
somente se a classe nio tiver nenhum construtor definido explicitamente.
5. E e F estio corretas. O fato de se ter acesso a um pequeno nrimero de m6todos implica um acoplamento
limitado. Se o acesso 6 feito atrav6s de uma referAnia do tipo interface, pode-se argumentar que existem ainda
menos oponunidades para o acoplamento , umavez que o pr6prio tipo da classe nio se encontra visivel. Dizer
que modificag6es em uma parte de um programa provavelmente nio causario conseqiiOncia em outra, 6
realmente a ess€ncia do acoplamento fraco. Nlo existem variiveis an6nimas. Referir-se apenas a um pequeno
nrimero de outros objetos poderia implicar um acoplamento fraco, mas se cada objeto tiver muitos m6todos, e
todos forem usados, entio o acoplam-nto seri forte. As vari6veis (atributos) de uma classe devem
normalmente ser private, mas isso descreve o encapsulamento e nXo o baixo acoplamento. E claro que um
bom encapsulamento tende a reduzir o acoplamento, como conseqii6ncia.
6. A esti correta. Embora um m6todo f inal nio possa ser sobrescritos, neste caso o m6todo 6 private, e,
portanto, escondido. O efeito 6 que um novo e acessivel m6todo f lipper 6 criado. Assim, nXo ocorre
polimorfismo neste exemplo; o m6todo chamado 6 simplesmente o da classe-child, e neo ocorre nenhum erro.
Como nio existe um tile descan6vel para avari|vel x e os par6nteses (no constnrtor Kinder) j6 estio no seu lugar e
estio vazios, nio 6 possivel criar uma chamada ao construtor da superclasse que usa um argumento. Poftanto, a
rinica possibilidade restante 6 criar uma chamada ao construtor sem argumentos da superclasse. Isso 6 feito assim:
super ( ) ;. A linha nio pode ser deixada em branco, uma vez que os par6nteses j6 estio no lugar. Al6m disso, uma
vez que o construtor da superclasse chamado 6 a verslo sem argumentos, esse construtor precisa ser criado. Ele
nio seri criado pelo compilador porque jl existe um outro construtor. (Objetivo 5.4)
A, C e D estio corretas. A e D sloexemplosde retornos covariantes, ouseja, Flower e Tulip sio ambos
subtipos de Plant.
B est6 incorreta, String nlo 6 um subtipo de Plant. (Objetivo 1.5)
l0.A,B,EeFestiocorretas.AeBsioexemplosdesobrescrigXo;especificamente,B6umexemplode
sobrescrigio usando-se um retorno covariante. E e F sio exemplos de sobrecarga.
C e D estio incorretas. Sio de sobrescrigio inv6lidas, porque os seus tipos de retorno sio incompativeis. E sio
sobrecargas invilidas porque os seus argumentos nio se modificaram. (Objetivo 5.4)
lL Dest6correta.OconstnrtordeMinorfazumacharnadaoplicitaaoconstrutorcomumargunentodelJber,quefazumadramada
enplicia(trLis) aoconstrutorsemargumentosdeubeqqueporsuavezincrementayedepoisretomaparaoconstrutorcomum
argurnentqoq'.ulmuhiplicay'r2edepoisretomaparaoconstrutordeMinor,queadicioru3 ay.
13. A e B estio corretas. Entretanto, no tempo de execugio, A langari uma ClasscastException porque dogl
refere-se a um objeto Dog, o qual nio necessariamente s ericapaz de realtzar tarefx deBeagle.
14. C est6 correta. Para poder chamar o m6todo do2 de v, voc6 precisa converter x2 para que ele se torne do tipo Y. A
instrugio B parece ser uma conversio correta, mas, sem o segundo conjunto de pardnteses, o compiladorpensari que se
trata de uma instrugXo incompleta.
Obiefivos pqrq q
certificqe6o
I Usor Membros de Closses
I Desenvolver C6digos Wropper e de
Autoboxing
I Determinor os Efeitos de se Possor
Vqri6veis o M6todos
r Reconhecer Quondo os Obietos se
Tornom Quolificodos ooro o Coleto
de Lixo
I Argumentos de linho de comondo
poro o m6todo Moin
t Exerc(cios r6pidos
B.
9. Dog d; / / vari1vel 1oca1: d
l-0. d = new DogO;
i-1. d.so(d);
1.2. ]
13. void go(Dog dog) { // vari6veL Local: dog
L4. c=newCollaro;
1-5 . dog. setName ( "Fido" ) ;
16. )
I7. void setName(String dogName) { / / variSvel local: dogrName
18. name = dogName;
19. / / faz mais coisas
20. )
21.. j
A Figura 3-1 mostra o estado da pilha e do heap depois que o programa atinge a linha 19. Em seguida, apresentamos
alguns pontos principais:
objeto String
Vari6veis de
instAncias
setName O dogName - name
go O dog
main ()
pbleto co11ar
r Linha 13 - o m6todo go ( ) 6 colocado na pilha, com o parimetro dog como umavariivel local.
r Linha 14 - um novo objeto co11ar 6 criado no heap, e atribuido ) vari6vel de instAncia de Dog.
r Linha17-setName() 6adicionadoipilha,comoparAmetrodogName comoasuavari6vellocal.
r Linha 18 - a variivel de instincia name agora tamb6m se re{ere ao objero String.
I Repare que duas vari6veis locais difermtesreferem-se ao mesmo objeto oo9r.
I Repare que uma vari6vel local e uma variivel de instAncia referem-se ambas ) mesma String aiko.
I Depois que a Linha 19 fnal:.aa, setName ( ) termina e 6 removido da pilha. Nesse ponto, avari6vel local dogName
tamb6m desaparece, embora o objeto String ao qual ela se referia ainda esteja no heap.
7,6 Evreaer aidigo qw @kque coffetamente ot operadores @mpiados, incluindo os de atribaigdo (initados a =, *=, -=)...
Literais inteiros
Hi tr6s maneiras de representar nrimeros inteiros na linguagemJava: decimal (base 10), octal (base 8) e hexadecimal (base
16). A maioria das perguntas do exame que envolve literais inteiros usa representag6es decimais, mas vale a pena estudar
para as poucas que usam a representagio octal ou hexadecimal. Mesmo com as chances de voc6 algum dia usara
representagXo octal no mundo real, sendo extraordinariamente pequeni$, elas foram incluidas no exame apenaspor
dversao.
Literais decimais Os inteiros decimais nio precisam de explicagio; voc6 os tem empregado desde a primeira s6rie escolar
ou at6 antes disso. Hi
chances de que os esteja usando, j6 que voc6 nio preenche seus cheques em notagio hexadecimal. (Se
exiuerfaqgndoisso, nlo se preocupe, h6 um grupo de Nerds An6nimos (NA) pronto para ajudar). Na linguagemJavao eles
sio representados da maneira tradicional, sem prefixo de nenhum tipo, como descrito a seguir:
int length = 343;
Literais octais Os inteiros octais usam somente digitos de 0 a7 .Emlava, o inteiro 6 representado na forma octal com a
inclusio de um zero na frente do nrimero. como vemos abaixo:
class Octal {
public static void main(String [] args) t
int six = 06i // Igual ao 6 decimal
int seven = 07; / / Igual ao 7 decimal
int eight = 010; // IguaI ao 8 decimal
int nine = 011; / / Igual- ao 9 decimal
104 Copftulo 3: Atribuigoes
System.out.println("Octa1 010 = " + eight);
Observe que quando passamos do sete e nio temos mais digitos para usar (s6 podemos usar os digitos de 0 a 7 nos
nrimeros octaii), voltamos ao ponto de partida,ewznro 6, adicionado ao inicio do nrimero. Voc6 pode ter at62t digitos
em um n6mero oaal, nio incluindo o zero inicial. Se executarmos o programa anterior, ele exibiri o seguinte:
Octal 010 = 8
Literais hexadecimais Os nrimeros hexadecim is (hexnaabreviatura) slo construidos com o uso de 16 simbolos
distintos. J6 que nunca foram inventados simbolos num6ricos unit6rios para os algarismos que vlo de 10 a L5, usamos
caracteres alfab6ticos para representar esses digitos. A contagem de 0 a 15 na representagio hexadecimal ficaria assim:
0L23456'789abcdef
A linguagemJava aceita letras mairisculas ou minrisculas para os digitos adicionais (um dos poucos momentos em que nXo
diferencia mairisculas de minusrohr!). Voc6 pode us ar fie 76 didtos em um ndmero hexadecimal, nlo incluindo o prefixo
Oxou a extensio do sufixo opcional I. que serlo explicados depois. Todas as atribuig6es hexadecimais a seguir sio vilidas:
class HexTest {
public static void main (String [] args) {
int x = 0X0001-;
int v = }xlfffffff;
in|' z = 0xDeadCafe;
System.out.println("x = " + x + + y + " z = " + z);
)
double d = 11301-874.9881-024:
No exemplo anterior, o nime ro I1,3QI87 4.9881024 6 o valor literal. Os literais de ponto flutuante sio definidos como
double (64 bits) por p adrio, ponanto, se vocA quiser atribuir um literal de ponto flutuante a.umavariSvel do tipo
f loat (32 bits), tenl que anexar o sufixo F ou f
ao nimero. Se nio o fizer, o compilador reclamar6 de uma possivel
falta de precisio, porque voc6 estari tentando inserir o nrtmero em um "contAiner" (potencialmente) menos preciso. O
sufixo F fornece uma maneira de voc6 informar ao compilador: "Ei, sei o que estou fazendo e correrei o risco, muito
obrigado".
float f = 23.467890; // zrro de compilador, possivel perda da precisdo
ffoat s = 49837849.029847F; // ox; possui o sufixo "F"
Opcionalmente, voc6 tamb6m pode anexar um D ou d a literais double, mas nio 6 necess6rio, pois esse 6 o
compoftamentopadrio.
double d = 110599.995011D; // opcional, n5o 6 obrigat6rio
double S = 987.89'7; // Ndo 6 um sufixo 'D', mas est6 OK, pois 6 um literal- double
Procure literais num6ricos que incluam umavirgula, por exemplo,
int x = 25,343; // Nd.o ser6 compilado por causa da virguJ-a
JAVA5 IO5
Literais booleanos
Os literais booleanos sio a representaglo do c6digo-fonte para valores boolean. Um valor boolean s6 pode ser
definido como true ou f alse. Embora em C (e algumas outras linguagens) seja comum o uso de nrimeros para
rePresentart.rue oufalse,isondofuncionaniemJaua.Novamente,repitacomigo,Javanio6C++".
boolean t = true; // V6l-ido
bool-ean f = 0; // Erro do compilador!
Procure perguntas que usem nrimeros onde os booleanos seriam obrigat6rios. Voc6pode veruma avaliagio de
instrugio i f que use um nimero, como na linha a seguir:
int x = 1; if (x) { } // Erro do compilador!
Literais de caracteres
O literal char 6 representado porum fnico caractere entre aspas simples.
char a = 'a';
char b = 'G';
VocA tamb6m pode digitar o valor Unicode do caractere, usando a notaglo Unicode que acrescenta o prefixo \u ao valor,
como vemos nessalinha:
char letterN = '\u004e'; // e letra 'N'
Lembre-se de que os caracteres, na verdade, slo simplesmente inteiros de 16 bits sem sinal. Isso significa que voc6 pode
atribuir um literal num6rico, contanto que ele esteja no intervalo de 16 bits sem sinal (65535 ou menor). Pbr exemplo, as
linhas a seguir sio todas vllidas:
chara=0x892; //literalhexadecimal
char b -- 982; // literal inteiro
char c = (char) 70000; // A conversS.o 6 necess6ria; 70000 est6 fora do intervalo char
char d = (char) -98; // Absurdo, mas v61ido
E as descritas abaixo nlo sio vilidas e produzirlo erros de compilador:
char e = -29; // Possivel perda de precisSo; precisa de uma conversSo
char f = 70000 // Possivel perda de precisSo; precisa de uma conversSo
VocA tamb6m pode usar um c6digo de escape se quiser representar um caractere que nio possa ser digitado como um literal,
incluindo os caracteres de alimentaglo de linha, nova linha, tabulagio horizontal, backspace e aspas simples e duplas.
char c = '\"'; // Aspas duplas
char d = '\n'; // Nova linha
Agora que voc6 est6 familiarizado com os tipos de dados primitivos e seus intervalos, precisa ser capaz de identificar o tipo
de dado apropriado a ser usado em uma situagio especifica. A seguir serio apresentados alguns exemplos de quantidades
no mundo real. Tente selecionar o tipo primitivo que melhor represente a quantidade.
Embora strings nio sejam primitivas, foram incluidas nesta segio porque podem ser representadas com valores literais
as -
em outras palav.ras, digitadat dnetanente no aidigo. O rinico outro tipo nio primitivo que possui uma representagio literal 6 o
array, que examinaremos mais adiante neste capinrlo.
Thread t = ??? / / qtal vafor literal poderia ir aquil
Operadores de atribuigio
Atribuir um valor a uma variivel parece bem simples; simplesmente insira o valor i direita do s tnd, : para atribuilo )
variivel que estar6 i esquerda. Bem, certo, mas nio espere ser avaliado com algo do tipo:
x=6;
NXo, voc6 nio ser6 avaliado com atribuig6e s que selarnfchinha (termo t6cnico). No entanto, ser6 avaliado em atribuig5es
mais ambiguas que envolvam conversio e express6es complexas. Examinaremos atribuig6es primitivas e de vari6veis de
106 Copftulo 3: AtribuiE6es
referAncia. Mas antes de comegarmos, retomaremos um pouco para examinar uma variAvel por dentro. O que i uma
variivel? Com o a uariiuel e setr uabrestio relacionados?
As vari6veis sio simplesmente dep6sitos de bits, com um tipo.designado. VocA podeter um dep6sito int, umdouble,
um Butron e at6 um-dep6sito Stiing [ ] . Dentro desse dip6sito, teriamos um conjunto de bits representan{o g v.alor.
Para tipos primitivos, o1 bits representam um valor num6rico (embora nio saibamos qual o formato desse padrio de bits
p"r" o tipo noolean, mas nlo achamos isso importante). Um tip o futte devalor igual a 6, por exemplo, significa que o
padrXo de bits davariivel (o dep6sito de tipos @t) 6 igual a 000001.1.0, representando os 8 bits.
Portanro, o valor de um avariLvelprinitiw6 evidente, mas o que estaria dentro de um dep6sito de objea? Sevoc|escrever:
Buttonb=newButtono;
o que estar6 dentro do dep6sitg Bgaon blseria,o.objeto Button? N;o/Uma vari6vel referenciando um objeto seria
exaramenre rs so - ono ,oidatl de refeftncia. O dep6sito de bits de uma vari6vel de refer6ncia cont6m bits que representam
uma maneira d.e acessar o objeto.Nio iabemos qual-6 o formato; a maneira pela qual as referAncias ao objeto sio armaz.enadas 6,
especifica de miquinas virtuais (6 um ponteiro para algt, apenas nio sabemos o que esse algo 6 realmente). Tudo que
podemosdizer,iomcerteza,6 que ovdordavari6velnio 6 o objeto, masemvezdisso, umvalorrepresentar'dov.ggQea
itoecifuo danentiria. Ou ovalornull. Se umvalor nio tiversido atribuido avariivel de referAncia ou tiver sido atribuido
expiicitamente um valor nu11, a vari6vel armazenarL bits que representario - voc6 adivinhou - o valor nul1. VocA pode
h
Button b = nu1l;
da seguinte forma: "A vari6vel Button / nio est6 referenciando nenhum objeto".
Portanto, agora que sabemos que um avar:iilel|, apenas um pequeno dep6sito de bits, podemos dar prosseguimento e
trabalhar com a altera$o desses bits. Examinaremos, primeiro, a atribuigXo de valores a tipos primitivos e terminaremos
com as atribuig6es avari6veis de refer6ncia.
Atribuig6es primitivas
O sinal de igualdade ( = ) 6 usado para a atribuSno de umvalor a uma variivel e foi chamado adequadament e de Eeradar dz
atribuigdo.Naverdade, h6 12 operadores de atribuigio, mas apenas os cinco mais freqiientemente usados caem no exame, e
eles serio abordados no Capitulo 4.
byLe b = 27;
mas somente porque o compilador compafiaautomaticanenrao valor literal para o tamanho de um tipo byte. Em outras
palavras, o compilador executa a conuersdo. O c6digo anterior 6 id6ntico ao seguinte:
vrus
k,,F^ ! -- /L,-r^\
h
\!rus/ 27;
' // Converte explicitamente o valor literal inteiro para um tipo byte
Parece que o compiladorlhe deuumachance e permitiu quevod tomasse um atdho com atribuig6es avari6veis inteiras
menorel que um tipo int. (fudo que estamos dizendo sobre o tipo byte se aplica igualmente a char e short, ji
que os dois sio menores do que um tipo int). A prop6sito, ainda nio entramos realmente na parte estranha.
Sabemos que um inteiro literal 6 sempre um tipo int, mas o que 6 mais importante 6 que o resultado de uma expresseo
que envolva qualquer item do tamanho de um tipo int, ou menor, ser6 sempre um tipo int. Em outras palavras, some
dois tipos byce e vocd ter6 um tipo int
- mesmo se esses tipos byte forem muito pequenos. Multiplique um tipo
int por um shorte ter6 um tipo int. Divida um tipo short
por um byte e ter6... Um tipo Certo, agora int.
chegamos )pane estranha. Veja isto:
bytec="lo'
Tentamos atribuir a uma vari6vel do tipo byte a soma de dois @tes culo resultado (11) foi pequeno o suficiente para caber
em um tipo byte, mas o compilador nio aceitou. Ele conhece a regra aplicivel a express6es "int ou de tipos menores"
sempre resultando em um tipo int. A compilagio teria sido executada se tMssemos feito a conversio explicita:
byte c = (byte) (a + b) ;
As convers6es podemser implicitar ou explicitat.Uma conuersdo inpliatasignifica que.voc6 nio precisa escrever um c6digo para
elE a conversao ocorTera automatrcamente. I\onnalmente, unVI conversao lmplrclta ocorre quancto lazemos uma
transformagio que envolva anpl)agno.Em outras palavras, quando inserimos'um item menor (digamos, um tipo byte) em
umcontein-ermaior(comoumtipoint).Lembradaqueleserrosdecompilador"possintiloss of freci-'
sion" que vimos na secio de atribuiE6es? Eles ocorrem quando tentamos inserir um item maior (digamos, um tipo
long) emumcont6ineimenor (comoumtipo sho.rt). Atransformaglo "valormaioremumcontdinermenor"6
conhecida como compactaglo e requer uma c onversio.explhita,em que voc6 esari informando ao compilador que conhece o
perigo e aceita toda a r?:sponsabilidade. primeiro, exarunaremos uma conversio implicita:
int a = 100;
long b = a; / / Conversdo implicita, um valor int sempre cabe em um long
(Jma conversio explicitatem o formato a seguir:
float a = 100.001f;
int b = (int)a; // ConversSo explicita, um tipo de float pode perder informag6es como
um tipo de j-nt
Os valores inteiros podem ser atribuidos a uma variivel double sem a conversio explicita, porque qualquer valor inteiro
pode ser inserido ein um tipo double de 64 bits. A linha a seguir demonstra isso:
double d = 100L; // ConversSo implfcita
Na instrucio anterior. um tiDo double 6 inicializado com um valor do dpo lonq (como indicado pelo L depois do
valor num6rico). Nenhuma ionversio 6 necessiria nesse caso porque um tipo dgu5le po{e ar.mqzenir todas ai
informag6es que um tipo l ong poderia conter. Se, no entanio, q-uisermos atribuir um valor do tipo doubl e a um tipo
rntefo, estafemos tentancto uma conversao Por compactagao eo comPilactor sabera drsso:
^1 ^^^ r
UIdDD LqDLTITIJ
^-^Ll-^ \
]
Se tentarmos compilar o c6digo anterior, o erro a seguir ser6 produzido:
Sjavac Casting.java
Casting.java:3: Incompatible tlpe for declaration. Explicit cast
needed to convert doub]e to int.
int x = 3957.229; // nd.o 6 v51ido
1 error
No c6digo anterior, um valor de ponto flutuante este sendo atribuido a uma vari6vel inteira. Ji que um inteiro nio
consegri armazer,tar casas decimais, um erro ocorrer6. Para fazer isso ftmcionar, converterem6s o ndmero de ponto
ilutuante emum lntero:
class Casting i
public static voj-d main(String [] args) {
int x = (int)3957.229; // conversSo v5lida
System.out.println("int x = " + x);
108 Copftulo 3: AtribuiE6es
)
Quando voc6 converter um nrimero de ponto flutuante em um tipo inteiro, o valor perder6 todos os digitos depois do
- I ' r r r I r. a 1 . , ,l
POntOdecmal. A^ execugao do coctrgo antenor proctuara a sarch a seguf:
Bjava Casting
int x = 3957
Tamb6m podemos converter um tipo de nrimero maior, como long, em um menor, como b1te. Observe o c6digo abaixo:
nla<c l-acfina I
O c6digo anterior seri compilado e executado adequadamente. Mas, o que aconteceria se o valor long fosse muor que t27
(o maior nrimero que um byte pode armazenar)? Alteremos o c6digo para descobrir:
ala<c l-acf ira I
]
O c6digo ser6 compilado adequadamente, e quando o executarmos, obteremos o resultado a seguir:
O; --.-
tJovd l
ud>Lf119
^-^r --
Exercicio 3- |
Examinemos o que aconteceri no c6digo anterior. Nele, 128 6 o pa&io de bits 10000000. Esse pa&io usa exatamente 8
bits para representar o nfmero 128. Mas j6 que o literaJ,I2S 6umtipo int, na verdade, obteremos 32 bits, estando o
nrimero 128 nos 8 bits da extrema direita (ordem inferior). Portanto, 128 seria realmente igual a:
000000000000000000000000L0000000
Vocd tem nossa palavra; hL 32bits u.
Para compactar os 32 bits que representam o nrimero 128, a linguagemJava simplesmente elimina os 24 bits da esquerda
(ordem superior). Ficamos apenas com 10000000. Mas lembrese que um byte tem sinal e o bit da extrema esquerda
representa esse sinal (e nio pane do valor da vari6vel). Ponanto, terminamos com um ntimero negativo (o nrimero 1 que
usamos para representar llS,agorarrepresentao bit do sinal negativo). Nio se esquega: para descobrir ovalor de um
nrimero negativo usando a notagio biniria complementar, inverta todos os bits e, em seguida, adicione 1. Ao inverter os
oito zeros ficaremos com 011111 1 1 e adicionando L a esse resultado obteremos 10000000 ou novamente 128! E quando
aplicarmos o bit do sinal, terminaremos com -128.
VocA precisa usar uma conversio explicita para atribuir 128 a um tipo byte e a atribuigio resultar6 no valor -1.28. Uma
converseo nada mais 6 do que sua maneira de dizer ao compilador, "Confie em mim. Sou um profissional. Assumo total
responsabilidade por qualquer coisa estranha que possa vir a ocorrer quando esses bits superiores forem eliminados".
Isso nos leva aos operadores compostos de atribuigXo. O c6digo a seguir seri compilado,
byte b = 3;
// Sem problemas - adiciona 7 a b (o resultado 6 10)
e equivalente a:
byte b = 3;
b = (byte) (b + '1 l; / / Nd.o ser6 compilado sem a
// aantrers1o. iA en:e b + 7 resulta em um tioo int
O operador de atribuigio composto + = permitir6 que voc6 adicione o valor ) b, sem incluir uma conversio explicita. Na
: :
verdade, * =, - : r'r e / usario todos uma conversio implicita.
Atribuindo uma vari6vel primitiva a outra vari6vel primitiva Quando voc6 atribuir uma vari6vel primitiva aoutra, 0
conteildo da aari,iuel da direita seni copiado, por exemplo,
int a = 6;
intb=a;
O c6digo anterior pode ser lido como: "Atribui o padrio de bits do ntmero 6 I variivel int a. Em seguida, copia o
padrio de bits de a e insere a c6pia na variivel b.
Portanto, as duasvari6veis, agora, contem o padrio de bits do nrimero 6, mas nio apresentam outro relacionamento.
IJsamos a vari6vel , somente para copiar seu conterido. Nesse momento, as duas vari6veis possuem conteridos id6nticos
(emoutraspalavras,uakresid€nticos),massealterarmososconteidosdea oub,aoutravari6velnloser6afetada".
Examine o exemplo abaixo:
class Val-ueTest {
public static void main (String ll args) {
int a = 1-0; // Atribui-se um valor a a
I l0 Copfiulo 3: Atribuig6es
System.out.println("a = " + a);
intb=a;
tjava ValueTest
a=10
a = 1-0 after change to b
Observe que o valor de a permaneceu igual a 10. O ponto chave a lembrar 6 que mesmo depois que voc6 atribuir a a b, as
duas variiveis nio referenciario o mesmo local da mem6ria. As vari6veis a e b nio companilham apenas um valor; elas
t|m aipiasid|nricas.
Button c = null;
A linha anterior cria umespago para a vari 6vel de rcfer1neiaButton (o dep6sito de bits para um valor de refer6ncia) , mas nio
gera realmente um objeto Buuon.
Como discutimos no Capinrlo anterior, voc6 tamb6m pode usar uma vari6vel de referdncia para referenciar qualquer objeto
que seja uma zubclasse do tipo declarado para a vari6vel, como descrito a seguir:
)
i
publj-c class Bar extends Foo i
public void doBarStuff O { }
]
)
class Test {
public static void main (string [] args) {
Foo reallyABar = new BarO; // V6lido, pois Bar 6 uma subclasse de Foo
Bar reallyAFoo = new FooO; / / Ndo 6 v6lido! Foo ndo 6 uma subclasse de Bar
A regra 6 que voc6 pode atribuir uma subclasse do tipo declarado, mas neo uma zuperclasse desse tipo. Lembrese de que
um objeto Bar , com cfrtez4pode fazer o mesmo que Foo, portanto, qualquer pessoa que tiver uma refer6ncia a Foo poder6
chamar m6todos Foo, mesmo se o objeto na verdade for um objeto Bar.
No c6digo anterior, vimos que Foo possui um m6todo doFooStuf (
f ) , que algu6m com uma refer6ncia a essa classe
poder6 tentar chamar. Se o objeto referenciado pela variivel Foo for realmente um objeto Foo, nXo haverl problemas. Mas
tamb6mniohaver6problemasseeleforumobjetoBar,jiqueBarherdouom6tododoFooStuff ( ).Voc6niopode
JAVA 5 'I1I
fazer isso funcionar de maneira inversa, no entanto. Se algu6m tiver uma refer6ncia aBar, poderi chamar
(
doBarStuf f ) , mas se o objeto referenciado na verdade for um objeto Foo, ele nio saber6 como responder.
Escopo Vari6vel
Depois que vod declarou e inicializou uma variivel, uma questlo naturd 6 "por qwmto tempo essa vari6vel vai existir?"
Essa_ 6 uma,pergunta que se refere ao escopo das vari6veis. E o escopo nXo 6 ipenas uma coisa imponante & se entender de
modo geral, mas ele tamb6m tem um papel imponante no exame. Comecemos examinando um arquivo de classe:
alaqc T.2\r^rrf I / / classe
stati-cints=343; // vari6vel est6tica
int x; // var!6ve1 de instAncia
{x=7;intx2=5;} // bLoco de inicializaqdo
Layouto { x += B; int x3 = 6;} // construtor
rrnid dnQFrr++l\ I // m6Lodo
inty=6; // vari6vel 1ocal
for(intz=0iz<4;z++li // bl-oco de c6digo 'for'
y+=z+x;
]
]
]
Como acontece com as vari6veis em todos os programas Java, as deste programa (s, x, x2, x3, y e z) t6m todas um
escoPo:
I s 6 umavariivelstatic.
I x 6umavariiveldeinstAncia.
I y 6 uma vari6vel local Qs vezes chamada de vari6vel "local de m6todo").
I z E.umavariiveldebloco.
I x2 |umavarilvel de bloco init, um tipo de variivel local.
I x3 6 uma variivel de construror, um tipo de vari6vel local.
Para o prop6sito de explicagio do escopo das vari6veis, podemos dizer que existem quatro escopos bisicos:
I Asvari6veisstatic t6moescopomaislongo;elassiocriadasquandoaclasse6carregada,eduramportodoo
tempo em que a classe permanecer carregada naJVM.
r As vari6veis de instAncia sio o segundo tipo mais longevo; elas sio criadas quando uma nova instAncia 6
criada, e existem at6 que a instAncia seja removida.
I As vari6veis locais v0m em seguida; elas existem durante todo o tempo em que o seu m6todo permanecer na pilha.
Como veremos em breve, no entanto, as variiveis locais podem estar vivas e ainda assim estar "fora de escopo".
I As vari6veis de bloco s6 existem durante o tempo em que o bloco de c6digo esti sendo executado.
Os erros de escopo t6m muitos tamanhos e formas. IJm engano comum acontece quando umavarihvel| sonbreadaedois
escopos interferem um com o outro. Veremos o sombreamento com detalhes daqui a dgumas p6ginas. A razio mais
comum Para acontecerem erros de escopo 6 quando vod tenta acessarumavariivel que nio est6no escopo. Vejamos tr6s
exemplos comuns desse tipo de erro:
r Tentaracessarumavari6veldeinstAnciaapartirdeumcontexto static (normalmenteapartirdemain () ).
class ScopeErrors {
i-nt x = 5;
public static void main(Stringll args) 1
]
I Tentar acessar uma vari6vel local a partir de um m6todo aninhado.
Quando um m6todo, por exemplo go ( ) , chama outro m6todo, por exemplo so2 O, 9o2 ( ) nio ter6 acesso is
vari6veis locais de go ( ) . Enquanto so2 ( ) esr6 rodando, as vari6veis locaii de go O ainda estXo atiuar, mas estio fora
deescopo.Quando go2O f:urralua'.6removido&pilhaego () continuaasuaexecugio.Nesseponto,todasasvarilveis
I 12 Copitulo 3: AtribuiE6es
int Y = 5'
902();
Y++ i // depois que go2O finaliza, y volta ao escopo
]
vvrv vv! \, L
y++; t/
/ / Ltav
^<^ LUrttIJf
^^-^il- Jqr ,,;'lnaal
y E rvuqt :
q nn/\
vv \ /
]
I Tentar usar uma vari6vel de bloco depois que o bloco de c6digo jA terminou de executar.
E bastaote co-n- declarar e usar uma variivel dentro de um bloco de c6digo, mas cuidado para neo tentar usar a vari6vel
depois que o bloco finalizou:
void so3 O {
for(int z=0; z<5; z++l {
boolean test = false;
if(z == 3) {
test = true;
break;
]
)
System. out.print (test ); // 'test' 6 uma ex-vari6vel,
t | ^1 ^ -=^ ^-.1 ^ts^ -,ila]-s. . .
]
Nos dois ultimos exemplos, o compilador dir6 algo como:
cannot find symbol
Essa 6 amaneira de o compilador dizer "aquela vari6vel que voce tentou usar? Bom, ela pode ter sido vllida no passado
remoto (por exemplo, urna linha de c6digo atris), mas estamos na era da Internet, baby, nio tenho nenhuma lembranga
dessavari6vel".
Quando o programa for iniciado, atribuir6 o valor zero avari|vellear, o vaior padrXo para variiveis de instAncia primitivas
relacionadas a nfmeros.
char '\u0000'
AOTRABALHO
Voc6 deue inicialiqar todas as suat uariiueis, nesnl se estiuer atribaindo a elas o ualor padrdo. Sea cr6digo fcanl nais fricit de ser lido; os
pmgramadores qtre precisarem faryr a manutengdo en sea aidigo (dEois qae uoc6 ganbar na loteria e mudar para o Taiti)
fcardo gratos.
ratrrrn |. if16.
]
public static void main(String [] args) {
Bookb=neweook0;
String s = b.getTitle0; // Ser6 compilado e executado
String t = s.tolowercaseO; // Exceqdo de tempo de execuqSol
)
)
public static void main(String [] args) {
Book b = new Booko;
String s = b.getTitle(l; // Ser6 compilado e executado
if (s != nu]I) {
String t = s.tolowercase0;
)
O c6digo anrerior verificou se o objeto referenciado pela variivel s nio 6 nulo antes de tentar us6Jo. Fique atento
p"r" ..i6rior do exame em que voc6 tenha q.te procrrrat no c6digo se a referAncia a um objeto possui.o valor
nul-1. No c6digo anterior, por exemplo, examinamos a declaraglo da variivel de instAncia title, vimos que nio
houve inicializigio explicita, confirmimos que avai|vel title recebeu o valor padrXo nu11 e, em seguida,
vimos que a vari6vel s tamb6m apresentari o valor nul-I. Lembre-se, o valor de r 6 um1 c6pia do de title
(como retomado pelo m6todo gretiitte ( )), portanto, se title for uma variivel de referdncia nulI, s tamMm ser5"
Quando inicializarmos um array, os elementos de refer6ncia ao objeto serio iguais a nuI1, se nio forem
inicializados individualmente com valores. Se houver tipos primitivos em um array, eles receberio seus resPectivos
vdores padrio. Por exemplo, no o6digo abaixo, o array year ter6 1@ inteiros todos iguais a zero por padrio:
JAVA5 I15
public class BirthDays i
static int [] year = new int[100];
public static void main(String [] args)
f or ( int i.=0; j-<l-00 ; i++ )
Syst.em.out.println("year[" + i + "] = + rrarrIi]\.
' Jve+ L1J
'
I
Quando o c6digo anterior for executado, a saida indicari que todos os 100 inteiros do array sio iguais azero.
)
As uaidueis kcais, incluindo w tipos prinitiuos, senprq nmprq sempre deuem rcr iniciali4adas antes de aocd tentar rcd-las (embora nXo
necessariamentenamesmalinhadec6digo).AlinguagemJavaniofome,aalsvariiveislocais,umvalorpadrio; wcdtenlque
infuiali4i-las explicianntecom um valor, como no exemplo anterior. Se tentar usar um tipo primitivo nlo inicializado em
seu c6digo, receber6 um erro do compilador:
public class TimeTravel {
public static void main(String [] args) {
int year; / / YariSvel local (declarada, mas nao utilizada)
System.out.println("The year is '* + year) i // E,rro de compilaqSo
)
A compila$o produziri a saida a seguir:
I j avac TimeTravel . java
TimeTravel.java:4: Variable year may not have been initialized.
System.out.println("The year is " + year);
l- error
Paracorrigir seu c6digo, precisamos fornecer um valor para o inteiro year. Neste exemplo atualizado, ele foi declarado em
uma linha separada, o que 6 perfeitamente vilido:
public class TimeTravel {
public static void main(String [] arqs) {
int year; / / DecLarada, mas n5o inicializada
int day; / / DecTarada, mas nio j-nicj-alizda
System. out . println ( "You step into the port.al . ,, ) ;
year - 2050; // Inieialj-zada (nm valor foi atribuido explicitamente)
1 16 Copitulo 3: AtribuiE6es
System.out.print.ln("Welcome to the year " + year);
]
Observe no exemplo anterior que declaramos um inteiro chamado day que nio 6 inicializado e mesmo assim o
c6digo foi compilado e executaao adequadam.nt.. E v6lido declarar uma variivel local sern inicializ|-la, contanto
que ela nlo seja usada, mas convenhamos, se voc6 a declarou, provavelmente tinha umarazaa para isso. (Embora
tenhamos ouvido falar de programadores que declaram variiveis locais aleatoriamente s6 por diversio, para ver se
elas conseguem descobrir como e porque estio sendo usadas).
AO TRABALHO
O compilador ndo podeni irforrnar sempre se uma uaiduel localfoi inidaliqada antes do uto. Por exempl0, n uoci inicialiqti-la dentro de um
bloco condicional ldgico (en outras palauras, am bloco de aidtgo que pode ndo ser executado, como o bloco de uma instrugdo if
, ou }oop
f or rcm un ualor literal true
ou f a l- s e como altematiua), o conpi/ador saberd que a inicialiTgjdo talueq nio ocorra e podeni produ{r
um effo. O cddigo a seguir deixani o compilador confuso:
Date date;
iF (Aaf a == nrrl I I
]
A compila$o do c6digo resukarino erro abaixo:
B j avac TimeTravel . j ava
TimeTravel.java:5: Variable date may not have been initialized.
rf (date == nu11)
1 error
JAVA 5 117
As refer6ncias de vari6veis de instAncia recebem sempre um valor padrio igual a nu1l, at6 serem inicializadas
explicitamente- com outro valor. No entanto, as refer6ncias locais nio recebem um valor padrXo; em outras palavras,
ndo sdo nwII. Se voc6 nio inicializar uma vari6vel de refer6ncia local, enteo, por padrio,ieu valor ser6... Bem 6 ai que
-
est, todo o problema - ela nio teri absolutam ente nenham valor! Portanto, simplilcaremos a questeo: configure o
item incompleto com null explicitamente, at6 que esteja pronto para inicializi-lo com outro valor. A vaii6vel local
a seguir ser6 compilada apropriadamente:
Arrays locais
Exatamente como em qualquerorrtra refer6ncia aobjeto, deve-se atribuirumvaloris refer€ncias de arrays declandasdentro de
um m619d9 ante; que sejamusadas.Isso significa apenas que voc6 precisadeclarar e constnriro nio ser6
necessirio.inicializar explicitamente os elementos de um array.J6dissemos iso antes, mas 6 imponante "o"y.Irio.ntanto,
o srficiente para que
seja repetido: Elementos de arrE recebem seas ualorespadrio (0, fa1se, nu11, ' \u0000 '
e asimpordiante) indepentte;tu d0;ffq
-
terida &ckrarlo como umauaitluel local oa de instincia. O proprio objeto de affay, contudo, nio ser6 inicializado se for declarado
localmente. Em outras palavras, vod ter6 que irnci.altzar exphcitamente a referAncia a um array, se ela for declarada e usada dentro
de um m6todo, mas, no momento em que construir um objeto de array, todos os elementos receberio seus valores padrio.
class ReferenceTest {
public static void main (String [] args) {
Dimension a = new Dimension(5,10);
SvStCm ottf nrinFlh/\\-
eJeuerlr.vqury!rlrurrr\ 1-'^i^Lf
q.rrsIVIIu \\ _,
+ a hoiahf
4.rrurVrrL/, \
--
Dimension b = a,-
vi4re+Y11u Jv,
-
]
No exemplo anterior, um objeto Dimension a 6 declarado e inicializado com uma largura igual a 5 e altura igual a 10. A
seguir, o objeto Dimension b 6 declarado e o valor de a the 6 atribuido. Nesse momento, is duas vari6veiJ(a e n)
cont6m valores id6nticos, porqr,re o conterido d9 a foi copiado em b. Ainda hi apenas um objeto Dimension- aquele que
tanto a quantob estio referenciando. Para concluir, a propriedade de altura 6 alterada com o uso da referOncia a b. Agora,
Pense Por um minuto: Isso tamb6m irimudar apropriedade de altura de a? Vejamos qual ser6 o resultado:
Bjava ReferenceTest
a.height. = 10
a.height = 30 after change to b
Por essa saida, podemos concluir que as duas vari6veis referenciama mesmainstAncia do objeto Dimension.
Quando
fizemos a alteragio em b, a propriedade de altura tamb6m foi alterada em a
Encontramos uma exceglo ) maneira como as refer€ncias a objetos sXo atribuidas no objeto String. EmJava, esses objetos
recebem-tratamento especial. Em primeiro lugar, os o\etor.stringtdo inalteniueir,vocA nlo pode alter:ar o ,ralor de um objeto
String. Mas is so parece ser realmente possivel. Examine o c6digo a seguir:
class Strinqs {
public static void main(String [] args) {
String x = "\Tava"; ,// Atribui- valor a x
af ri
eulfrrv na
! - ^t // Agora, y e x referenciam o mesmo objeto String
)
VocA pode achar que o objeto String y
armaz.enar| os caracteres Java Bean depois que a variivel x for alterada, porque
as strings sXo objetos. Examinemos qual seri a saida:
9'i:rr: cf ri nft
Y Strr-ng = ,Java
Y string = ,Java
Como vocA pode ver, mesmo se y for uma vari6vel de refer6ncia ao mesmo objeto que x referencia, quando alterarmos x isso
nio dterari l Com qualquer outro tipo de objeto, onde dtras refer6ncias apontem para o mesmo objeto, se uma delas for
usada para aher6Jo, as duas saberio da aheragio, porque ainda haveri somente um obj eto. Mas sempre qnf4tmot alteraldes dc
qaaQaer tipo em urua String, o I,/M ataaliqani a uai,iuel d.e refer€nciaparafa(-k @ontarpara am objeto dtfermte. O objeto diterente
poderiserumnovo objeto ounio, masdefinitivamente serlumobjetodiferente. ArazAopelaqudniopodemos dizercom
ceneza se foi criado um novo objao reside no pool de corstantes Strings, que abordaremos no Capinrlo 6.
VocA precisa memorizar o que ocorre quando usamos umavari6vel de refer6ncia Stringpara aheraruma$ring:
r [Jma nova string 6 criada, deixando o objeto String original intocado.
I A referAncia usada para alterar o objeto String (ou em vez disso, para criar um novo objeto String pela alteragio de uma
c6pia do original) seri atribuida ao novo objeto String.
Os m6todos podem ser declarados para usar refer6ncias primitivas e/ou de objetos. Voc6 teri que saber como (o9 se) a
valiavel do chanadorpoderi ser afetada pelo m6to do chanadt. A drlerenga entre variiveis primitivas e de refer6ncia de obieto,
quando passadas para m6todos, 6 grande e importante. Para compreender esta segio, voc6 teri que estar familiaizado coma
segXo de atribuig6es abordada naprimeirapane deste capinrlo.
dim = 11
Observe que a paftir do momento em que o objeto Dimension da linha 4 for passado para o m6todo modi fy ( ) ,
qudquer alteragXo que ocorrer dentro do m6todo estari sendo feita no objao cuja refer6ncia foi passada. No exemplo
anterior, tanto a variivel de refer6ncia d quanto d.im apontam para o mesmo objeto.
E se voc6 estiver passando uma vari6vel de refer6ncia de objeto, estari pas sando wa aipiados bits que represenram a
refer6ncia a um objeto. Assim o m6todo chamado obter6 sua propria c6pia da variivel & refer6ncia e far6 com ela o que
quiser. Mas j6 que duas variiveis de refer6ncia id6nticas referenciam exatamente o mesmo objeto, se o m6todo chamado
dteraro objeto (chamando m6todos de configuragio, porexemplo), o chamadorperceber|,qteo o$eaque suavariivel
origind referenciou tamb6m ter6 sido aherado. Na pr6xima segfo, examinaremos iomo o cenirio se ahera quando falamos
sobre tipos primitivos.
A conclusio sobre a passagem por valor 6 a seguinte: o m6todo chamado nlo pode alterar a uairlaeldo chamador, embora
no que diz resp eito avariiveis de reter|ncia deobjeto, o m6to do chamado pdc aherar o objao que avari|velreferencia. Qual
a diferengaentre alterar
l variivel e alterar o objao? Quanto )s referAncias a objetos, significa que o m6todo chamado nio
pode reatribuir avariivel de referAncia original do chamador e fazer com que ela referencie um objeto diferente ou ovdor
nu1l. Porexemplo, no c6digo abaixo,
void bar( ) t
Foof=newFooO;
doStuff ( f) ;
)
void dostuff (Foo g) {
'120
Copfiulo 3: Atribuig6es
q.setName("Boo");
9 = new FooO;
)
reatribuir g nio reatribuir6 f ! Quando a execugeo do m6todo bar ( ) for concluida, dois objetos Foo terio sido
criados, um referenciado pela vari6vel local f e outro pela vari6vel local (vari6vel de argumento) 9r. J6 que o
m6todo doStuf f ( ) possui uma c6pia davari|vel de referAncia, tem uma maneira de acessar o ob)eto Foo
original,porexemplo parachamar om6todo setName ( ). Por6m, doStuf f ( ) ndotemc0m0acessarauariduelde
referlncia f. Assim,( ) pode alterar o que f estiverreferenciando, mas nio o conterido real (padrio de
doStuf f
bit$ deste. Em outras palavras, dostuf f ( ) pode modificar o estado do objeto a que f se refere, mas nio pode
fazer com que f se refta a um objeto diferente!
class ReferenceTest {
public static void maj-n (String [] args) {
int a = l-;
ReferenceTest rt = new ReferenceTest ( ) ;
Aftermodifvl) a=1
Observe que a nio se alterou depois que foi passada para o m6todo. Lembre-se de que somente uma alpia de a
foi m6todo. Quando uma vari6vel primitiva 6 passada para um m6todo, ela 6 pasadapor ualor, o que
passada para o
significa "passar por c6pia dos bits davari|vel,.
Na sala de aula
O mundo sombrio das variiveis
No momento em que vod pensou que havia decifrado tudo, viu um trecho de c6digo com variiveis que nlo estavam se componando da maneira
que, na sua opiniio, deveriam estar. VocA pode ter encgntradg c6digo variiveis sombreadas. E possivel sombrear uma variSvel de v6rias
-um .com
manerras; examinaremos apenas a que mais provavelmente the confundir6 - omltaruma uarihnl fu iutdncia sombreanda-a com ama uarirhnl locaL
O sombreamento envolve redeclarar uma vari6vel que j6 tenha sido declarada em algum outro local. O efeito do sombreamento 6 a ocuha$o
&variAveldeclaradaanteriormente, detalmodo quepossaparccerqlrevod estiusando avariiveloculta, mas o queestar6realmenteusando
ser| avai|vel de sombreamento. VocA pode encontrar raz6es para sombrear uma variAvel intencionalmente, mas normalmente
ocorre por acaso, causando erros dificeis de detectar. No exame, vocA pode esperar perguntas nas quais o sombreamento teri uma
panicipagio.
VocA pode sombrear uma variivel de instAncia declarando uma variivel local com o mesmo nome, diretamente ou como
parte de um argumento, como vemos abaixo:
class Foo {
JAVA 5 I2I
static int size = 7;
static void changelt(int size) {
size=size+200;
System.out.println(..size in changelt is .. + size);
)
)
O c6digo anterior parece alterar a variivel de instAncia size, no m6todo changert ( ) , mas ji que changert ( ) possui um
parimetro chamado s i z e, a variivel local s i z e ser6 alterada enquanto a vari6vel de instAncia a1e permaneieri intocada. A execu$o da classe
Fooexibirl
Sjava Foo
size = 7
size in chandcTr- is 207
size after changelt is 7
Tudo fica mais interessante quando a vari6vel sombreada 6a referOncia a um objeto, em vez de um tipo primitivo:
class Bar {
int barNum = 28;
]
class Foo {
myBar.barNum
= 99;
System.out.println("myBar.barNum in changelt is " + myBar.barNum);
myBar = new BarO;
myBar.barNum = 420;
System.out.println("myBar.barNrm in changelt is now " + myBar.barNum);
]
changelt (f.myBar) ;
Al . ,.1.
\-/oleTrvo po ro o cenrTrcocoo
Declaragio, construsio e inicializagdo de arrays
(Objetivo I.3 do exame)
1.3 Desenuoluercddigo qae dulare, inicialiry e unpimitiuos, affEtq ertramt e obletos como aaidueis esfliticag de instincias e /orais.Akn
disso, usar ident'ficadores uilidos para nomes de aaridaeis.
EmJava, os arrays sio objetos que armazenam diversas variiveis do mesmo tipo. Eles podem conter variiveis de refer6ncia
primitivas ou de objeto, mas o array propriamente dito sempre ser6 um objeto da pilha, mesmo se for declarado para
armazenarelementos primitivos. Emoutraspalavras, nXo exise algo comoumarrayprimitivo,mxvoc|podccriarum array
de elementos primitivos. Para esse objetivo, vocd teri que conhecertr6s itens:
H6v6rias maneiras diferentes de executar cadauma dessas tarefas e voc6 teri que conhecertodas para o exame.
AOTRABALHO
Ot aralt fio efcientes, mas na rzaioria das sitaagdu seri melhor uocd asar ilrt dos tipot Collection da claxe jaua.util (incluindo HathMap,
ArrEList e TreeSet). As classes de co@unto oferuem mandras maisflexiueis de acessar un o\eto (para insergdo, exclusdo, leitura e assim
por diante) e diferente dos an'a1s, poderdo rcr expandidat ou mnhaidas dinamieamente quando uocd adicionar ou remouer elementos (na
uerdade e/as s6o arrals gerencidueiq jd H,i am tipl Cnlkctinn para ama grand.e uariedade de neces$dades. Vocd
que os usam em sua estruturQ.
precisa de ama classficagdo nlpida? De un gwpo de objetos rcm repetigdu? Uma maneira de acersar um plr nomef ualor? Una lista
encadeada? O Capitalo 7 os abordani com mais detalhes.
Declarando um array
Os arrays sio declarados atrav6s da descriglo do tipo de elemento que armazenario, os quais podem ser um objeto ou um
tipo primitivo, seguido de colchetes ) esquerda ou direita do identificador.
Tamb6m podemos declarar arrays multidimensionais, que, na verdade, sio arrays com outros arrays
armazenados. Isso pode ser feito da maneira a seguir:
Nunca 6 considerado vilido incluir o tamanho do array na declaraEio. Sim, sabemos que voc6 pode fazer isso em
algumas outras linguagens, e 6 por isso que poder6 se deparar com uma ou duas perguntas que incluam um c6digo
semelhante ao seguinte:
int[5] scores;
O c6digo anterior nio conseguir6 passar pelg compilador. Lcmbre-se de.que a JVM nio alocarS.espago at6 que
voc6 instancie realmente o objeto de array. E ai que o tamanho importari.
Construindo um array
Construir vm array significa criar o objeto de array na pilha (onde todos os objetos residem) - em outras palavras,
trarapalavra-chavenew comotipo doarray.Paracrnrumobjeto dearray,aJavateriquesaberquant;espago
alocar na pilha, ponanto, voc6 precisa especificar o tamanho do array na hora da const^glo. Esse tama.rho seri
igud a quantidade de elementos que o array armazenar|.
varidvel de
refer€ncia do
array int[ ]
FFT;T;I
0123
Valores
Indices
Lembre-se de que os arrays devem senpreterum tamanho atribuido no momento em_que forem construidos. A
de array. Nunca 6
JVM precisa do tamanho a fim de alo."r o espago apropriado na pilha para o novo objeto
considerado vilido, por exemplo, fazer o seguinte:
Portanto, nlo o faga, e se voce ver isso no teste, nio hesite em marcar a resPosta "A compilagio falhar| '
pilha;'. Essas pilanas tanbdm inplicam qae 0 cunstrutor do objeto senl executado, como resultado d.o aidigo de nnstragdo/triaydo/
-instanciagdo.
itodeno, di7,er con cirteqa, ltor exenplo, qae qua/.quer aidigo que use a palawa-chaue r,ew (se for exuutado eon sucesso) fanl
com qae o construtor da classe e todot os clnstrxttores de saperr/asses sqiam exeratados.
Al6m de ser consrruido com new, os arrays tamb6m podem ser criados com o uso de um tipo de abreviatura na sintaxe que
gerari o array, ao mesmo tempo em que inicializari seus elementos com valores fornecidos no c6digo (e nlo com valores
iadrXo) Examinaremos isso com detalhes na segio sobre inicializagXo. Por enquanto, memorize que, Por causa desses
atalhos tra ritttaxe, os ob.ietos ainda poderio ser criados mesmo que voc6 nXo use ou veja a palavra-chave new.
Os elementos individuais do array podem ser acessados com um ntmero de indice. O nrimero de indice sempre comega no
zero' Portanto' Para um array de dez objetos os nrtmeros de indice irio de 0 a 9. Suponha que cri6ssemos um .lrray com tr6s
Animais como descrito a seguir:
OBSERVAQ6ESPARAOE)(AME
Procure aidigos qae tentem acetsar um indice de arralfora do intervalo. Por exerup/0, re am affal tiaer trls e/enentot, a tentatiua de acessar o
elemento pl knpani a excegdo ArraylndexOutOfBoundsExcept ion, pois em ltm affal de tu€s elementos, os ualores atllidos
para os indices serdo 0, I e 2, Voci tambin pode
uer a tentatiua de utiliqagdo de um nilmero negatiuo clmo am indice do anE. seguir, A
temos exenplot de tentatiuat ud/idas e inud/idas de acesso ao affaJ. Certfique-w de reconhecer quando elas causam exagdes de tempo de
exuagdo e ndo erms de nmpilador! puase todas as petgtlntas do exame listam tanto exngdu de tempo de execugdo quanto envs de
compilador como re spostas possiueis.
Um array bidimensional (um array preenchido com outros arrays) pode ser inicializado da maneira a seguir:
inttl tl scores = new int[3] [];
/ / Declara e cria um array contendo tr6s refer6ncias a arravs int
scores[0] = new int[4];
/ / o primeiro elemento do array scores estii em um array int de quatro elementos int
scores[1] = new int[6];
/ / o segundo elemento do array scores est6 em um array int de seis elementos rnt
scores[2] = new int[1];
/ / o terceiro elemento do array scores est6 em um array int de um el-emento int
126 Copftulo 3: AtribuiE6es
Inicializando elementos em um loop
Os objetos de array possuem somente uma vari6vel priblica, length (tamanho), que {ornece a quantidade de
elementos do array.-Port"trto, o valor do riltimo indice 6 sempre uma unidade menor do.que essa variivel. Por
exemplo, se o tarnanho de um array for igual a 4, os valores dos indice irio de 0 a 3. Geralmente' vemos os
elementos do array incializados em um loop conforme descrito abaixo:
Dog[] myDogs = new Dogt6l; // cria um array de 6 referQncias a Dogi
A variivel length nos informa quantos elementos o array cont6m, mas n6o se esses elementos foram
inicializados. Como veremos no Cipitulo 5, a partir do Java 5 n6s poderiamos ter escrito o loop f or sem usar a
vari6vel length:
for(Dog d: myDogs)
d = newDog( );
vori6vel de
re{er6ncio do orroy oog [ ]
O c6digo anterior criouum array int com tr6s elementos, inicializou os tr6s com os valores 4, 7 e 2, e, em segu^ida,
atribuiu o novo array i variivel de refer6ncia testscore s do array int declarado anteriormente. Chamamos
essa operagio de criagio le array an6nimo, porque com essa sintaxe, voc€ nem mesmo precisa atribuir algum
valor ao novo array. Voc6 pode estar pensando, "Qual a vantagem do array, se ele nXo for atribuido a umivari6vel
de refer6ncia?" Ele pode_ser usado na criagio de um array just-in-tine a ser empregado, por exemplo, como
argumento de um m6todo que use lm arr^y como parAmetro. O c6digo abaiio demonstra um argumento de array
,u$-rn-ume:
public class Foof {
void takesAnArray(int [] someArray) {
/ / usa o array como pardmetro
)
public static void main (String [] args) {
128 Copftulo 3: Atribuig6es
Foof f = new Foof();
f . takesAnArray (new int [] {1 ,'7,8,2,5}); / / precisamos de um argumento aray
5 obietos cat
OBSERVAQ6ESpeneoE)(AME
Itmbre-se de ndo especifcar am tarnanho quando usar a intaxe da criagdo de arral an6nimo. O tamanho d deiuado da quantidade de itens
(separadot por uiryu/a) existentes entre as cbauer. Preste bastante atengdo na intaxe de arals usada nas pergantar do exame (e bauer,i
ntuitas). Vocd pode aer xtrta czmo essa
/| // '^x^ : --<r
Ltsv s I r^,
varauq; o tamanho nao deve ser especificado
class Car { }
class Subaru extends Car { }
class Ferrari extends Car { }
Se o array for declarado como um tipo de interface, seus elementos poderAo fazer refer|ncia a qualquer instAncia das classes
que implementem a interface declarada. O c6digo a seguir demonstra o uso de uma interface como tip o de auay:
interface Sporty {
void beSporty( );
]
class Ferrari extends Car implements Sporty {
nrrhlia rznid
v v+\4
l-raannrtrr/\
vvvyv! ef \ /
t
)
class RacingFlats extends AthleticShoe implements Sporty {
public void beSportyO {
)
class GolfClub { }
class festsportyThings {
public static void main (String [] args) {
Sportyl] sportyThings = new Sporty [3];
sportyThinss[0] = new Ferrari); // OK, Ferrari implementa Sporty
sportyThings [1] = new Racingplats ( ) ;
/ / OIr., RacingFlats implementa Sporty
sportyThinSs[2] = new GolfClubO;
/ / I{Eo 6 v6l.ido; GolfClub (clube de golfe) ndo implementa Sporty
/ / Nao importa se as pessoas n5o me considerarem moderna por causa disso
I30 Copftulo 3: AtribuiE6es
A conclusio 6 a seguinte: qualquer objeto que passe no teste "E-MEMBRO" aplicado ao tiPo de array declarado
pode ser atribuido a um elemento desse array.
oBSERVAQoESPARAOE)(AME
Un anal Car nio pode ser atibuido ao anal Honda. Nem todo carro i da marca Honda,
Vocd ndo pode inuerter at atribai{6e! udlidas.
portanto, te uoc6 tiuesse an aral Honda, ele ndo comportaria o arral Car atribaido a aai,iael de refer1ncia Honda. Pens bem: am
dtclarado
anal Carpodeia conter ama referdncia a Fenari, e algudm qae achasse ter am arral de Hondas se depararia repentinamente com a Fenai.
L.cmbn+e qae o teste E-MEMBRO pode ser executado no nidigo, atrauds do operador instanceof .
A regras de atribui$o de arrays se aplicam tanto a interfaces quanto a classes. IJm array declarado como um tipo de interface
pode referenciar um array de qualquer tipo que implemente a interface. le mbrese de que qualquer objao de uma classe que
implemente uma interface especifica passari no teste E-MEMBRO (instanceof) dessa interface. Por exemplo, se Box
implementar Foldable, o c6digo a seguir ser6 v6lido:
Foldable [ ] foldingThings;
Box[] boxThings = new eox[3];
foldingThings = boxThings;
/ / oK, Box implementa Fo1dab1e, portanto. Box f-MeMeRo de Foldable
int[] blots;
inttl tl squeegees = new intt3l tl;
blots = squeegees; // NAo ti v:furoo, squeegees 6 um array bidimensional de arrays int
int[] bl-ocks = new int[6];
blots = blocks; / / OK, blocks 6 um array int
JAVA 5 I3I
Preste.atengao elpgcialmente nas atribuig6es de arrays envolvendo dimens6es dif".ente". VocA pode, por exernplo,
ser i.r.rdagado se 6.vilido atribuir um array int ao primeiro elemento de um array composro de arrays int, c&no
nas linhCI a seguir:
Blocos de Inicializageo
falamos sobre dois lugares de uma classe onde voc6 pode colocar c6digo que realize operag6es: m6todos e contrutores.
E
Os blocos de inicializagio.sio o terceiro lugar, em um programaJava, onde as operag6ei poi.- t.t r."lir*I"r. Os blocos de
y".ldrye.- t"fap quando aclasse€ garregadapeQprimelavez (umbloco deitticializ"gio esrfuico) ouquandouma
insdncia6 criada (um bloco de inicializagio de instAncia). Vejamoi um exemplot
class SmallInit {
sLatic int x;
int y;
i Cat obj6to
cat obj€to cat
aluffy
Variavel de referencia ao
ArayCatllll2-D
A variavel d6 refer€ncia 2-D o .loato d. u dj.ro e .rr.y
SOMENTE pode s€ referir a cahtl Il2-D8mrbd...
um array Cat 2-O r.l.rlr I u E!.y Cat l-D
new InitO;
new Init(7) t
]
]
Para descobrir a resposta, lembrese destas regras:
r Osblocosde'tncialuagXoest6ticosrodamumavez,quandoaclasre.6.carregadapelaprlmeiravez.
I Os blocos de inicializagio de instincias rodam sempre que uma instl.ncia de classe 6 criada.
I Os blocos de inicializagio de instAncias rodam depois da chamada que o construtor faz a super ( ) .
OBSERVAQ6ESpeneoEJ(AME
Porconuengdo, os b/ocos de inicialiqagdo nonzalmente aParecempertt do inicio do arquiuo da c/asre, en algum lugarpefto rlot construtores.
Entretanto, utamosfalandn do exame SCJP aqui. Itfdo se surpreenda se acharum bloco de inicialiqg4do esconditlointre alguns ndtodos,
di$argado de um en'o de nmpilapao prlnta para acontecer!
nl .r. ..f.
\,roleTtvo poro o cefitttcocoo
Usando classes wrapper (Obietivo 3.1 do exame)
J.IDesenuoluer aidigo que ase ar classes wr@perprinitiuas (tais como Boolean, Character, Doable, Integer, etc.), ef ou autoboxing e
unboxing. Discutir as dzferenpas entre as classes Sting, StingBuilder e StringBffin
Os construtores wrapper
Todas as classes wrapper exceto Character fornecem dois construtores: um que usa como argumento o tipo
primitivo que esta sendo criado e outro que usa uma representagio em String do tipo sendo Jonstruido. Pbr
exemplo,
i1
fntegfer = new Integer(42);
hteger i2 = new Integer (,.42,, 1 ;
ou
Fl-oat f1 new Float (3.IAf\ ;
Os m6todos valueOf( )
Os dois (bem, geralmente dois) m6todos estiticos valueof ( ) fornecidos na maioria das classes wrapper lhe
proporcionario outra abordagem paraacriaglode objetos wrapper. Os dois m6todos usam uma Stringpara representar o
iipo apropriado de seu primeiro argumento, sendo que o segundo m6todo (quando fornecido) usa um argumento
a&cional, int radix, que indica em que base (como 6in6ria, octal ou hexadecimal) o primeiro argumento foi representado.
Por exemplo,
Integer i2 = Integer.valueOf("101011". 2); / / converte 1-0101-1 em 43 e
/ / atrlbui o val-or 43 ao
/ / nbi'ero
t I vv)Yvv Tnfcacr i2
m<Value( )
Quando voc6 precisar converter o valor de um objeto wrapper num6rico em um tipo primitivo, use um dos
muitos m6todos xxxValue ( ) . Todos os m6todos dessa familia sio m6todos sem argumentos. Como voc6 pode
ver na Tabela 3-3, existem 32 m6todos xxxValue ( ) . Cada uma das seis classes v/rapper num6ricas possui seis
m6todos, de modo que todos os objetos wrapper num6ricos podem ser conveftidos em qualquer tipo primitivo
num6rico. Por exemplo,
JAVAs 135
Integer i2 = new Integer(42); / / cria um novo objeto wrarx)er
byte b = i2.byteValue0; // conwerte o valor de i2's em um
/ / nrimi t- i rrn ].xrf a
M6todo
s=static
n=excegeoNFE Boolean Byt€ Character Double Float Integer Iong Short
ByeVdue
doubleValue
FloatVdue
IntValue
IongVahre
ShortMue
ParseX:o<42
valueOf. s,n
Tosfting
toStringi(primitivQ x
toString s (primitivo, base)
pansexuO e valueOf( )
Os seis m6todos parsexxx ( ) (um de cada tipo wrapper num6rico) estio intimamente relacionados com o m6todo
va]ueof ( ) que existe em todas as classes wrapper num6ricas. Tanto parsexxx ( ) quanto valueof ( ) usam
uma String como argumento, langamuma excegio NuberFonnatException se o argumento Stringnio estiver no
formato apropriado e podem convener objetos String de diferentes bases (radicais), quando o tipo primitivo subjacente for
qualquer um dos quatro tipos inteiros (consulte a Tabela 3-3). A diferenga entre os dois m6todos 6 que:
I parseXxx( ) retornaotipoprimitivonomeado.
I ValueOf ( ) retorna um objeto wrapper rec6m<riado do tipo que chamou o m6todo.
toString( )
A classe Object, que 6 a classe primordial, o item superior, possui um m6todo toString ( ) . Como sabemos
que todas as outras classes Java sXo herdadas da classe Object, tamb6m sabemos que todas elas t6m um m6todo
toString( ). Oobjetivodom6todo toString( ) 6permitirquevoc6obtenhaalguma representagdosrgnficatiua
de determinado objeto. Por exemplo, se voce tiver um conjunto de v6rios tipos de objetos, poderi percorrA-lo e
exibir alguma forma de representagio significativa de cada objeto usando toString (
) , que com cefteza pode
ser encontrado em todas as classes. Discutiremos mais o m6todo toString (
) no capitulo sobre Conjuntos,
mas, por enquanto, enfocaremos como esse m6todo est6 relacionado com as classes wrapper que, como sabemos,
sio marcadas com f ina1. Todas as classes wrapper possuem a versio de uma in$6ncia de ) sem toString (
atgamentls e ndo-sLaLic. Esse m6todo retorna uma String com o valor do tipo primitivo encapsulado no objeto.
Por exemplo,
Double d = new Doubl-e("3.14");
System.out.println("d= " +d.tostring0 l; // o resuLtado6 "d= 3.14"
Todas as classes wrapper num6ricas fornecem um m6todo static toString ( ) sobrecarregado que usa o
tipo num6rico primitivo apropriado (oouble. toString ( ) usa um double, Long. toString ( ) usa um
long, e assim por diante) e, 6 claro, retorna uma String.
Stri-ng d = Double.toString(3.14) ; / / d = "3.t4"
Para concluir, as classes Integer e Long fornecem um terceiro m6todo toString ( ) . Ele 6 sLatic, seu
primeiro argumento 6 o tipo primitivo apropriado e o segundo 6.luma bas, O argumento da base informa ao
m6todo p^r^ peg r o primeiro argumento (que, por pa&io, estari na base 10 ou teri o radical 10) e convert6Jo
para a base fornecida, retornando, em seguida, o resultado como uma String. Por exemplo,
Autoboxing
Introduzido emJava 5, este recurso 6 conhecido por vlrios nomes: autoboxing, auto-unboxing, boxing e unboxing.
IJsaremos os termos boxing ("encaixotar") e unboxing ('desencaixotar'). Boxing e unboxing tornam mais conveniente o
uso de classes wrapper. Antigamente, no mundo pr6-Java 5, se voc6 quisesse criar um w rapper, abriJo, usiJo e depois
fech6lo novamente, vocA poderia fazer algo como:
Integer Y = new Integer(5671; / / cria
int x = y.intValueO; / / abre
x++,' / / rrca aql-a
JAVA 5 I37
y = new fnteger(x),' / / fecha novamente
Svstem orrl- nrinf
vgu.yt4rrUJlr\f_ lnI"rr = " + it. / / exibe
Y=568
E sim, voc6 leu corretamente. O c6digo parece estar usando o operador de p6s-incremento em uma vari6vel de referdncia a
objeto! Mas isso 6 simplesmente uma conveniAncia. Nos bastidores, o compilador faz o unboxing e a reatribuigio para
voc6. Anteriormente, n6s mencionamos que os objetos wrapper sio imut6veis... Este exemplo parece contradizer isso.
y
Com certeza parece que o valor de mudou de 567 para 568. Mas o que realmente aconteceu foi que um segundo objeto
wrapper foi criado, e o seu valor foi definido como 568. Se pelo menos n6s pud6ssemos acessar aquele primeiro objeto
wrapper, poderiamos provar isso...
Boxing, ==r€equalsQ
Acabamos de usar ::
parafaznr uma pequena exploragio dos wrappers. Vamos dar uma olhada com mais detalhes em
como os wrappers trabalham com : : , ! : e equal s O . Falaremos muito mais sobre o m6todo equal s O em
capitulos posteriores. Por agora, tudo o que temos de saber 6 que a intengio do m6todo equals ( ) 6 determinar se duas
instAncias de uma dada classe slo "significativamente equivalentes". Essa definigSo 6 subjetiva de prop6sito; fica a cargo do
criador da classe determinar o que significa "equivalente" para os objetos da classe em questio. Os desenvolvedores da API
decidiram que, para todas as classes wrapper, dois objetos sio iguais se forem do mesmo tipo e tiverem o mesmo valor.
Nio deve ser surpreen&nte que
Integer i1 = 1000;
Integler i2 = 1000;
if (i1 != i2) System.out.println("different objects") ;
if (i1. eguals (i2) ) System. out.println( "meaningfully egual" ) ;
138 Copfiulo 3: AtribuiE6es
Produza a saida:
different objects
meaningfully equal
SXo apenas dois objetos wrapper que, por acaso, tAm o mesmo valor. Pelo fato de eles terem o mesmo valor int, o
m6todo equals ( ) os consi&ra iomb sendo "significativamente equivalentes", e, portanto, retorna true. E quanto a
isoaqui:
Integer i3 = 10;
Integer i4 = L0;
if (i3 == i4) System.out.println("same object") ;
if (i3.equa1s (i4) ) System.out.print.ln( "meaningfullv equa1" ) ;
Este exemplo produz a saida:
sameobject
meaningfully equal
Ugh! O maodo equals ( ) parece estar funcionando, mas o que aconteceu com : : s : Por que razio : est6 nos
! ? !
)
static void doStuff(int z) {
inX z2 = 5:
System.out.println(22 + zl ;
JJ
Ette aidigo conpila unproblemas, mat aJI/M knga umaNullPointerException quando tenta ehamardoSXuf f (?<),
Pzrqae x nio se refere a um oQeto Integec pnftantl, ndo hi nenbum ualor para abir.
r Ampliago
I Autoboxing
f Var-arp
Quando umaclassetem m6todos sobrecarregados, umadastarefas do compilador6 determinar qual m6todo usarsempre
que encontrarumachamadaao m6todo sobrecaregado. Vejamos umexemplo que nlo usanenhumrecurso novo deJava5:
class EasyOver {
static void go(int x) { System.out.print("int "); }
sLatic void go(long x) { System.out.print("1ong "); }
static void go(double x) { System.out.printl"double "); }
public static void main(String [] args) t
byte b = 5;
short s = 5;
long 1 = 5;
float f = 5.0f;
go (b) ;
go (s) ;
so (1) ;
go(f );
class AddBoxing {
static void gro(Integer x) { System.out.println("Integer"); }
int i = 5;
9o (i) ; / / q)al go O ser6 chamado?
]
]
Como vimos anteriormente, se a tnica versio de go ( ) fosse a que usa um Integer, o recurso de boxing de Java 5
permitiria que go ( ) fosse chamado com sucesso. Da mesma forma, se apenas a verseo long existisse, o comPilador a
usaria para lidar com a cham adaago ( ) . A questXo 6, dado que ambos os m6todos existem, qual deles ser6 usado? Em
outras palavras, seri que o compilador pensa que ampliar um parAmetro primitivo 6 melhor do que realizar uma operaEio
de autoboxing? A resposta 6 que o compila dor preferirlaampliagio, entio a saida seri:
long
Os elaboradores deJava 5 decidiram que a regra mais imponante deveria ser que os c6digos pr6existentes devem continuar
funcionando como antes, entio, uma vez que o recurso de ampliagio j6 existia, um m6todo chamado por meio da
ampliaglo n5o deveria ser trocado por um m 6todo rec6m-criado que depende do boxing. Com base nessa regra, tente prever
a saida do seguinte c6digo:
class Addvarargs {
static void go(int x, int y) { System.out.println("int,int");}
static void go(byte... x) { System.out.println("byte... "); }
int, int
Porque, mais uma vez, mesmo que cada chamada requeira algum tipo de conversio, o compilador escolher6 o estilo antigo
em vez do estilo novo, mantendo os c6digos existentes mais robustos. At6 aqui, vimos que:
r A ampliagio 6 preferida em vez do boxing
r A ampliagio 6 preferida em vez dos var-args
Neste ponto, as mentes curiosas querem saber: o boxing 6 preferido em relaglo aos var-args?
class BoxOrVararg {
static void gro (Byte x, Byte y)
{ System.out.println("Byte, Byte") ; }
static void go(byte... x) { System.out.println("byte... "); }
JAVA 5 I4I
E a saida 6
Byte, Byte
IJma boa maneira de memori zar essa regra t.perceber que o m6todo var-args 6 mais "solto" que o outro m6todo, no
sentido de que ele pode lidar com chamadas contendo qualquer nrimero de parAmetros int. Um m6todo var-args funciona
mais como um m6todo de captura total, em termos & quais chamadas ele pode lidar; e, como veremos no Capitul o 5,faz
mais sentido que recursos de captura total sejam usados c omo vm illtimo recurso.
Sem problemas! O m6todo go ( ) precisa de um Animal, e Dog3 f-UM Rni*al. (I-embre-se de que o m6todo go ( )
pensa que est6 recebendo um objeto Animal, entXo ele lhe pediri que faga apenas coisas referentes a Animal, as quais, 6 claro,
qualquer coisa que herdar de Animal tamb lmpoderifazer.) Assirn, neste caso, o compilador amplia a referAncia Dog3 para
um Animal, e a chamada tem sucesso. A principal questlo aqui 6 que a ampliagio da refer6ncia depende da heranga" em
outras palavras do teste E-IJM. Por causa disso, nio 6 vilido ampliar de uma classe wrapper para outra, porque as classes
wrappersXo semelhantes entre si. Porexemplo, NAO 6 vfido dizerque Short E-UM Integer.
oBSERVAq6ESpeneoE)(AME
E tentadorpensar que uocd poderia atnpliar am wr@perlntegerpara torniJo an un@per l-ang, mas 0 seguinte exemp/o I\AO rcrrpilar,i:
class DagL {
pubfic static void main(String [] args) {
Dog4d=newDog4O;
d. test (new Integer (5) ) ; ,/,/ impossivel ampliar um Inteqer
| / ^^-^ q ..* T
/ / IJAL UrL ^6-
!V1r9
]
void test (Long x) { }
]
I--embre-sedequenenhartadasclasseswr@perpodeseamp/iardeumaparaoutralByLes ndoseampliamparashorts,Shorts
ndo se ampliamparaLongs, etc.
)
Isso 6 &mais para o compilador:
WidenAndBox.java: 5 : gto ( java. lang.Long) in WidenAndBox cannot be
applied to (byter
Mas o 6 estranho que o compiladorPODE fazerumaoperagio de boxingseguidaporumaopera$o de ampliagio para
criar uma corresponddncia entre chamada e m6todo. Este exemplo podera lhe deixar confuso:
class goxAndWiden {
static void go(Object o) {
Byte b2 = (Byte) o; / / ok - 6 um objeto Byte
qrrqf6m .
sJ p Lvlr!. vqu.}/t nriniln
nrrt- frrufLL /Lr?\
\p- t,
)
public static void main(String [] args) t
byte b = 5;
go(b); // este byte pode ser transformado em um Object?
)
)
Esse exemplo compila (!), e produz a saida:
Uau! Eis o que aconteceu nos bastidores quando o compilador, e depois aJVM, chegou i linha que chama o
m6todo go O :
1. O byte b foi encapsulado com boxing em um Byte.
2. A refer€ncia Byte foi ampliada para se tornar um Object (uma vez que Byte estende Object).
3. O m6todo go ( ) recebeu uma refer6ncia Object que, na verdade, aponta para um objeto Byte.
4. O m6todo so ( ) convefteu a referOncia Object de volta para uma refer6ncia Byte (embre-se, nunca houve
um objeto do tipo Object neste cenirio, apenas um objeto do tipo Byte!).
5. O m6todo so ( ) exibiu o valor de Byte.
Porque o compiladorniotentouusaral6gicaboxingdepois-amplia$o quando tentoulidarcom aclasse
WidenAndBox? Pense nisso... Se ele tentasse fazer boxing primeiro, byte seria convertido em um Byte. E ai estariamos de
volta i situagio & tentar ampliar um Byte para um Long e, 6 claro, o teste E-UM falha.
]
Esse exemplo compila eproduz:
long. . .
Integer...
Como podemos ver, 6 possivel combinar com sucesso var-args corn ampliagio ou com boxing. Eis uma revisio das regras
para m6todos sobrecarregados que usem ampliaglo, boxing e var-args:
Existem aspectos mais complexos relativos i sobrecarga, mas, tirando algumas poucas regras referentes aos gen6ricos (que
abordaremos no Capinrlo /), isso 6 tudo o que voc6 percisarl saber para o exame. Caramba!
O gerenciamento da mem6ria 6 um elemento crucial em muitos tipos de aplicativos. Considere um programa que leia
grandes quantidades de dados, digamos, em algum local de uma rede e, em seguida, os grave em um banco de dados na
unida& de disco rigido. Umpro.ieto tipico serialeros dados em algumtipo de conjunto namem6ria, executar algumas
operag6es com eles e grav6Jos no banco de dados. Depois que os dados fossem gravados, o conjunto que os armazenou
temporariamente precisaria eliminar os dados antigos ou ser excluido e recriado antes do processamento do pr6ximo lote.
Essaopera$opodeserexecutadavAiuvezns,eemlinguagenscomoCouC+ +,queniooferecemacoletaautom6ticade
lixo; uma pequena falha na l6gica que ewazie ou exclua as estruturas de &dos do conjunto pode permitir que pequenas
quantidades da mem6ria sejam inadequadamente recuperadas ou perdidas. De maneira definitiva. Essas pequenas
perdas sXo chamadas de uaTamentot de memriia, e depois de virias iterag6es podem tornar inacessivel uma quantidade
suficiente de mem6ria para finalmente causar a interrupgio dos programas. A criagio de um c6digo que execute o
gerenciamento manual da mem6ria de maneira limpa e completa 6 uma tarefa complicada e nio trivial, e embora
as estimativas variem, 6 discutivel se esse gerenciamento manual pode dobrar o esforgo de desenvolvimento de um
programa complexo.
O coletorde lixo dalinguagemJavaforneceumasolugio automhticaparaogerenciamento damem6ria. Namaioriados
casos ele o livrari de ter que adicionar alguma l6gica de gerenciamento da mem6ria em seu aplicativo. A &wantagem da
coleta de lixo autom6tica 6 que voc6 nlo poder6 controlar exatamente quando ela ser6 ou nio executada.
Portanto, todo o assunto da coleta de lixo gira em torno de assegurar que o heap tenha tanto espago disponivel
quanto possivel. Para os fins do exame, isso se resume em excluir qualquer objeto que nAo possa mais ser
alcangado pelo programa Java que estiver sendo executado. Discutiremos melhor o que significa "poder ser
alcangado", mas antes nos aprofundaremos no assunto em questao. Quando o coletor de lixo for executado, sua
finalidade ser6 encontrar e excluir objetos que nio possam ser alcangados. Se voc6 imagina o programa Java em
um ciclo constante de criagio dos objetos que precisa (o que ocupa espago no heap) e, em seguida, descartando-os
quando nio forem mais necess6rios, criando novos objetos e descartando esses objetos, e assim por diante, a pega
perdida do enigma 6 o coletor de lixo. Quando ele for executado, procurari esses objetos descartados e os excluiri
da mem6ria para que o ciclo de uso e liberagio da mesma possa continuar. Ah, o fant6stico ciclo vital!
Com base neisa definigio, o coletor de lixo executa algumas operag6es desconhecidas e quando descobre um
objeto que nlo pode ser alcangado por nenhum thread ativo o considera qualificado para a exclusio, e pode at6
exclui-lo em algum momento. Ou tamb6m pode nio exclui-lo nunca. Quando falamos sobre alcanparum objeto, na
verdade estamos falando sobre ter uma variivel de refer€ncia ahangiuel que aponte para o objeto em questao. Se
nosso programa Java tiver uma variivel de refer6ncia que aponte para um objeto, e se ela estiver disponivel para
um thread ativo, entio, esse objeto ser6 considerado alcanp,iuel. Discutiremos mais sobre como os objetos podem se
tornar inalcang6veis na segio seguinte.
Um aplicativo Java pode ficar sem mem6ria disponivel? Sim. O sistema de coleta de lixo tentarS.remover os objetos
da mem6ria quando eles nio forem usados. No entanto, se voc6 tiver muitos objetos ativos (objetos referenciados por
outros objetos ativos), o sistema poder6 ficar sem mem6ria disponivel. A coleta de lixo nio pode assegurar que haja
mem6ria suficiente, somente que a mem6ria disponivel ser6 gerenciada tio eficientemente quanto possivel.
i
Os objetos criados em um m6todo tamb6m precisam ser considerados. Quando um m6todo for chamado, qualquer
vari6vel local que for criada s6 existir6 durante a execugio do m6todo. Uma vez que o m6todo tiver sido concluido, os
objetos criados nele estario qualificados para a coleta de lixo. H6 uma excegio 6bvia, no entanto. Se um objeto for retornado
do m6todo, sua refer6ncia pode ser atribuida a uma variivel do m6todo que o chamou; assim, ele nio estari
qualificado para a coleta. Examine o c6digo abaixo:
import j ava. util . Date t
Date d = getDateo
doComplicatedstuff ();
System.out.println("d = " + d) ;
)
n"k] .i^ -f-f.i^ nrl6 d6l-n:f6/\ tL
PUUIIL DUaUfL uqus YeLUqre\/
IZ .I i3; // i2 refere-se a i3
lJ.a i4; // i3 refere-se a i4
i4.i i2; // i4 refere-se a i2
nrrl l .
:A - nrr'l I.
1-6. ]
Agora, executaremos o programa e verificaremos os resultados:
Total J\,rM memory: 1048568
Before Memory = 703008
Aft.er Memory = 458048
After cC Memory = 8L8212
Como podemos ver, o VM realmente decidiu coletar (isto 6, excluir) os objetos qualificados. No exemplo anterior,
sugerimos I JVM que executasse a coleta de lixo com 458.048 bytes de mem6ria restantes e ele atendeu nossa
solicitaglo. Esse programa s6 tinha o thread de um usuirio sendo executado, portanto, nio havia nada mais
acontecendo quando chamamos rt. gc ( ) . Nio se esquega de que o comportamento quando gc ( ) 6
chamado pode ser diferente em JVMs distintos, de modo que nio haver| garantias de que os objetos nXo utilizados
serlo removidos da mem6ria. A rinica coisa garantida 6 que se voce estiver ficando com muito pouco espago na
mem6ria, o coletor de lixo ser6 executado antes que uma exceglo outofMemoryException seja langada.
Exercfcio 3-2
Experimente modificar o programa CheckGC colocando as linhas 13 e 14 dentro de um loop. VocA poder6 ver que
nem toda a mem6ria 6 liberada com uma passada de GC.
Revisamos os literais v6Llidos para tipos primitivos e Strings, e depois discutimos os fundamentos da atribuigio de valores a
tipos primitivos e a vari6veis de refer6ncia, al6m das regras para conversXo de primitivos.
Em seguida, discutimos o conceito de escopo, ou "por quanto tempo esta vari6vel viver6?" Lembre-se dos quatro escopos
bisicos, do maior para o menor tempo de vida: static, instance, local, block.
JAVA 5 I49
Abordamos as implicag5es de se usar variiveis nio-inicializadas, e a imponincia do fato de que as vari6veis locais
deaem receber um valor explicitamente. Falamos sobre alguns dos aspectos complicados de se atribuir uma variivel
de referAncia a outra, e alguns dos detalhes sobre a passagem de variiveis para m6todos, incluindo uma discussio
do "sombreamento".
O t6pico seguinte foi a criagio de arrays, no qual falamos sobre declarar, construir e inicializar arrays uni e multidimensionais.
Falamos sobre arrays an6nimos e sobre arrays de referOncias.
Em seguida, revisamos os blocos de inicializagio est6ticos e de instAncias, qual a apar6ncia deles e quando eles sio chamados.
Caramba!
Continuamos o capitulo com uma discussio das classes wrapper, usadas para se criar objetos imut6veis que armazenem um
tipo primitivo, e usadas tamb6m para fornecer capacidades de conversio para primitivos: memorize valueof ( ) ,
xxxValue ( ) eparsexxx () .
Falamos sobre um novo e importante recurso deJava 5, que e$a intimamente relacionado aos wrappers: o autoboxing.
Boxing 6 uma maneira de automatizar o uso de wrappers, e abordamos alguns dos seus aspectos mais complexos, tais
como a forma como wrappers trabalham com : : e com o m6todo equals ( ) .
Tendo adicionado o boxing I nossa caixa de ferramentas, passamos a dar uma olhada com mais detalhes na sobrecarga de
m6todos e como o boxing e os var-args, em conjunto com convers6es ampliadoras, tornam a sobrecarga mais complicada.
Finalmente, nos dedicamos ) coleta de lixo, o recurso de gerenciamento automitico de mem6ria deJava. Aprendemos que 6
no heap que os objetos residem, e 6 tamb6m onde toda a interessante atividade de coleta de lixo se realiza. Aprendemoi
que, no fim das contas, a JVM far| a coleta de lixo quando ele quiser. VocA (o programador) pode pedir que seja
feita uma coleta, mas nio pode forgiJa. Falamos sobre a coleta de lixo aplicar-se apenas a objetos que estio
qualificados, e que qualificados significa "inacessiveis para qualquer thread ativo". Finalmente, discutimos o
raramente rltil m6todo f inalize ( ), e o que vocA precisari saber sobre ele para o exame. No fim das contas, um
capitulo fascinante.
{ EXERCICIO RAPIDO
Eis alguns dos pontos principais deste capitulo.
Pilha e Heap
E Asvariiveis locais (vari6veis de m6todo$ residem napilha.
E Os objetos e as suas variiveis de instincias residem no heap.
fl As vari6veis locais vivem pelo mesmo tempo que os seus m6todos na pilha; entretanto, se o m6todo chamar outro
m6todo, elas ficam temporariamente indisponiveis.
D As vari6veis de bloco (p.ex. em um f or ou em um if) vivem at6 a conclusio do bloco.
Usando uma yari6vel ou elemento de array que nao tenha sido inicializado ou atribuido
(Objetivos 1.3 e 7.6)
D Quando um array de objetos for instanciado, os objetos do array nio serio instanciados automaticamente, mas todas as
refer6ncias receberio o valor padrio nul1.
tr Quando um array de tipos primitivos for instanciado, todos os elementos receberio seus valores padrio.
tr As vari6veis de insAncia serio sempre inicializxlas com um valor padrlo.
E As vari6veis locais/autom6ticas/de m&odo nunca recebem um valor padrio. Se voc6 tentar usar uma antes de inicializ6-
la, receberiumerro do compilador.
D Os argumentos dos m6todos nunca sio objetos reais (podem ser refer€ncias a objetos)
E Voc6.precisa incluir o tamanho de um array quando o construir (usando new) a menos que esteja criando um array
anorumo.
E Os elementos de um array de objetos nio sio criados automaticamente, embora os elementos de arrays primitivos
recebam valores padrto.
fl Voc€ receber6 uma excegio NullPointerException se tentar usar o elemento de um array de objetos e esse elemento nio
referenciar um objao reai.
tr O ultimo indice que voc6 poder6 acessar seri sempre uma trnida& menor do que o tamanho do array.
E Os arrays multidimensionais sio apenas arrays compostos por outros arrays.
E Um array de tipos prirnitivos aceitar6 qualquer valor que possa ser promovido implicitamente ao tipo declarado para o
array. Por exemplo, uma vari6vel q6e
pode ser inserida em um array int.
E Um array de objetos pode conter qualquer objeto que passe no teste E MEMBRO (ou instanceof) aplicado ao tipo
declarado para o array. Por exemplo, se Horse estender a classe Animal, entio o objeto Horse poderi ser inserido em um
arraydeanimais.
E Se vod atribuir um array a uma referAnc ia de array ji declarada, o array ter6 que estar na mesma dimensXo & refer6ncia ao
JAVA 5 'I5I
I Se existirem v6rios blocos init em uma classes, eles seguem as regras indicadas acima, e rodam na ordem em que
aparecem no arquivo-fonte.
0 Encapsular tipos primitivos para que possam ser manipulados como objetos;
D Usar :- com wrappers 6 complicado; v/rappers com os mesmos valores baixos (normalmente os menores
que I27) serio : :, rnzs yalores maiores nlo serio ::.
tr A finalidade da coleta de lixo 6 excluir objetos que nio possam ser alcangados.
J 56 a II'/M decide exatamente quando executar o coletor de lixo; voc6 (o programador) s6 pode recomendar que
seja feita essa operagio.
Teste Individual
l. Dado:
a'laq< Qcnnn {
2. Dado:
class CardBoard {
Short sEory = 5,'
CardBoard go(CardBoard cb) i
cb = nul1;
r6f r!rh
^h.
)
public static void main(String11 args) {
3. Dado:
class alien {
String invade(short ships) { return ..a few,.; }
String invade(short... ships) { return ..many,'; }
i
class oefender {
public st.atic void main(String [] args) {
System. out.println (new Alien ( ) . invade (7) ) ;
Qual6oreruhadol
,{. many
B. a few
C Acompilagofalha-
D A saida nio pode ser prevista.
E. E langda uma o<cegXo no tempo de execu$o.
4. Dado:
1. class Dims {
2. public static void main(String[] args) {
3. inrtJU a= {{1,2,}, {3,4}};
4. int[] b = (inttl) atll;
5. Object 01 = a,
6. inttl tl a2 = (inrt] [] ) o1;
7. inttl b2 = (int[]) o1;
8. System.out.println(bt1l ) ;
10. ]
Qual6 o resuhado?
L2
B.4
C f langda uma exce$o em rempo de exeor$o.
D A compila$o falha devido a um erro na linha 4.
E. A compilaglo falha devido a um erro na linha 5.
E A compilagio falha devido a um erro na linha 6.
G A compilagXo falhadevido aum erro na linha 7.
5. Dado:
class Eggs {
int doX(Long x, Long y) { return 1-; }
int dox(Iong. .. x) { return 2; }
int dox(Integer x, Integer y) { return 3; }
1 54 Copitulo 3: AtribuiE6es
int doX(Number n, Number m) { return 4; }
public static void main(String[] args) {
new Eggs O .goO ;
]
void go0 {
short s ='7;
System.out.print(dox(s,s) + " ");
System. out.println (doX (1, I | ) ;
))
Qual6 o resultado?
,d11
8.21,
c31-
D.4 r-
8.2 3
833
G43
6. Dado:
class Mixer {
Mi-xer O { }
Mixer (Mi-xer m) { ml- = m; }
Mixer m1;
public static void main(string[] argrs) {
Qual6 o resultado?
A" hi
B. hi hi
\- nl- n]- nl_
D. Acompilaglofalha
E. hi, seguida de umaexcegio
E hi hi,seguidadeumaexcegAo
7. Dado:
1. class zippy t
2. String[] x;
3. int[] a [] = {LL,2}, {1}};
4. Object c = new long[4];
5. Objectl] d=x;
6. )
Qual6 o resultado?
JAVAs I55
A. A compilagio tem sucesso.
8. Dado:
class Fizz {
int. x = 5;
public static void main(Stri-ng[] args) {
A. t.ruetrue
B. fal-se true
C true false
D. fa]se false
E. Acompila$ofalha.
-r.: '4r | ry
E rangaoa uma excegao no tempo de execu$o.
9. Dado:
class Knowing t
static final long tooth = 343L;
L4UIU
-^F-ts.i^ f1^h^
Vrr\j Uvf u tlnnn
\ rvrry fnnfh\
uvvutl/ It
^^Tf
System.out..print(++tooth + " ");
return ++tooth;
]
public static void main(stringll args) {
System.out.print(tooth + " ");
final long tooth = 340L;
new KnowinS ( ) .dolt (tooth) ;
Qarcram
u uvrrr. hFl n I f^^th \ .
eJ vuu
^rrf ^ri rrruf
. Pr
]
)
Qual6 o resultado?
A. 343 340 340
B. 343 340 342
c 343 34L 342
D. 343 341, 340
E. 343 341, 343
E Acompilagofalha.
ari'tt.
\r E rangact:I uma excegao no tempo de execugio.
156 Copilulo 3: AtribuiE6es
|0. Quais das afirmativas abaixo s6o verdadeiras? (Marque todas as corretas)
A. A chamada ao m6todo f inalize O de um objeto 6 sempre a fltima coisa a acontecer antes de um objeto ser
coletado como lixo.
B. Quando uma variivel da pilha sai de escopo, ela se torna qualificadapara coleta de lixo.
C. Algumas variiveis de refer6ncia residem na pilha, e algumas residem no heap.
D. Apenas objetos que nio tenham variiveis de refer0ncia apontando para eles podem ser qualificados para coleta
de lixo.
E. E possivel requisitar a coleta de lixo atrav6s de m6todos das classes j ava . 1ang. Runtime ou
j ava. 1ang. System.
I l. Dado:
1. class Convert {
2. public static void main(String[] args) {
3. Long xL = new Long(456l);
4. long x1 = Long.valueOf("123");
5. Long x2 = Long.valueOf("L23");
6. long x3 = xl,,longValue$;
7. Long x4 = xl,.longValue0;
8. Long x5 = Long.parselong:("456");
9. long x6 = Long.parselong("123");
10. )
l_1. ]
Qual ir6 compilar usandose laval,mx ndocompilari com Javat.4? (Marquetodas as corretas)
A. Linha4
B. Linha 5
C. Linha6
D. LinhaT
E. Linha 8
F. Linha9
12. Dado:
1. class Eco {
2. public static void main(stringll args) {
3. Eco e1 = new EcoO;
4. Eco e2 = new EcoO;
5. Eco e3 = new EcoO;
6. e3.e = e2;
'7. e1 .e = e3;
8. e2 = nuI1;
9. e3 = nul1;
l-0. e2.e = e\;
l-1. e1 = nu1l;
L2. )
1-3. Eco et
t-4. )
Em que ponto hi apenas um objeto qualificado paracoletade lixo?
JAVA 5 I57
A. Ap6s a execugio da linha 8.
| 3. Dado:
1. class Bigger {
2. public static void main(Stringl] args) {
3. // insira o c6digo aqui
4. )
q1
5. class Better {
. enum Faster {Higher, Longer};
"l
8. ]
Qual op@o, inserida independentemente na linha 3, ir6 compilar? (Marque todas as corretas)
,{.Faster f = Faster.Higher;
B. Faster f = Better.Faster.Higher;
C Better.Faster f = Bett.er.Faster.Higher,'
D. gigger.Faster f = Bigger.Faster.Higher;
E. Better.Faster f2; f2 = Better.Faster.Longer;
E BetLer b; b.Faster = f3; f3 = Better.Faster.Longer;
14. Dado:
class Bird {
{ system. out.print (,'bL " ) ; }
public BirdO { System.out.print("b2 "); }
)
class Raptor extends gird {
static { System.out.print("r1 "); }
public RaptorO { System.out.print("r2 "1, 1
{t q\rql-
vtsLe!.r. am 611l- nri hf f \\r? \\ \t I. }J
new HawkO;
System. out.println ( *hawk tt ) ;
Qual6 o resultado?
,4.pre bL b2 13 r2 hawk
B. pre b2 b1 r2 13 hawk
C pre b2 b1 12 13 hawk 11 14
158 Copitulo 3: AtribuiE6es
D, 11- 14 pre b1 b2 13 r2 hawk
E. 11, 14 pre b2 bI 12 13 hawk
F. pre rL 14 b1 b2 13 12 hawk
G. pre r! 14 b2 bl- r2 13 hawk
H. A ordem da saida nio pode ser prevista.
I. A compilagio falha.
Respostas
I D esti correta,avari|vel x s6 est6 no escopo dentro do bloco de c6digo try, mas nXo quando est6 dentro dos blocos
catch ou f inal1y. (Para o exame, acostume-se com esses fechamentos horriveis com ) ) ) .)
A, B, C e E estio incorretas com base no exposto acima. (Objetivo 1.3)
2. C est6 correta. Apenas um ob.ieto Cardnoard ( c1 ) est6 qualificado, mas ele tem um objeto wrapper Shon que
tamb6m est6 qualifi cado.
3. C est6 correta, a compilagdo falha. A declaragio dos var-args est A correta, mas invade usa um tipo shorL, de modo que
o argumento 7 precisa ser convertido para esse tipo. Com a conversio, a resposta 6 B, 'a f el'/.
4. C est6 correta. Uma ClassCastExcept.ion 6langada na linha 7 porque o1 refere-se a um int [ ] [ ] , e nlo a um
int t I . Se a linha 7 fosse removida, a saida seria 4.
5. G esti correta. Duas regras se aplicam i primeira chamada a doX ( ) . Nio 6 possivel ampliar e depois fazer boxing de
uma s6 vez, e os var-args sio sempre escolhidos por ultimo. Portanto, vocd nio pode ampliar shorts para ints nem
longs, a fim de fazer boxing deles para Integers ou Longs depois. Mas voc6 pode fazer boxing de shons para
Shorts e depois ampli6-los para Numbers, e isso tem prioridade em relagio a usar um m6todo com var-args. A
segunda chamada usa um simples boxing de int para Integer.
6. F esti correta. A vari6vel de instAncia m1 do objeto m2 nunca 6inicializad4 enteo, quando m5 tentar us6-la,
seri langada uma Nu1 1 PointerExcept ion.
7. A estl correta, todas essas declarag6es de arrays sio v6lidas. As linha 4 e 5 demostram que arrays podem ser
convertidos.
9. D esti correta. Existem tr0s variiveis long diferentes chamadas tooth. Lembre-se de que voc6 pode aplicar
o modificador f inal a vari6veis locais, mas neste caso as duas vers6es de tooth marcadas com f inal
nXo sio modificadas. O rinico tooth cujo valor se modifica 6 o que nio est6 marcado com f ina1. Este
programa demonstra uma mA pritica conhecida como sombreamento.
10. C e E estio corretas. Quando um objeto tem uma vari6vel de refer6ncia, essa variivel reside dentro do objeto,
no heap.
JAVA5 159
A est4 incorreta porque se o objeto for salvo da coleta de lixo na primeira vez que o seu m6todo f inalize ( )
forexecutado,enteo,nasegundavezqueoobjetoestiverprestesasercoletado, finalizeO nlorodar6.B
esr6 incorreta
- a coleta de lixo nXo lida com variiveis de pilha. D est6 incorreta porque os objetos podem
residir em "ilhas de isolamento" e serem qualificadas para coleta de lixo. (Objetivo 7.4)
11. A, D e E estio corretas. Por causa dos tipos de retorno dos m6todos, essas chamadas requerem o autoboxing para
compilar.
13. C e E apresentam sintaxe correta para se acessar um enum a paftir de outra classe.
A, B, C, E, F, G, H e I estio incorretas com base no exposto acima. Observagio: voc6 provavelmente nio ter6 nenhuma
questao no exame real com tantas opg6es assim! (Objetivo 1.3)
160 Copftulo 3: Atribuiq6es
,rffi
.:,. -
:. :.
Operadores
,'
ffi,'
': Oblerlvos pqru o
.; I
cerllflco96o
I Usondo Ooerodores
t Exercicios r6pidos
i.i
l:ri
,"
':,,
'162 Copftulo 4: Operodores
Sevoc€tivervai6veis,k6alter6-las.Aumentariseuvalor,assomar6,deslocar6seusbits,asinverter6ecompataxdumas com
as outras. Neste capinrlo, voc6 aprender6 como fazer tudo isso emJava. Adicionalmente, voce aprender6 como fazer coisas
que provavelmente nurlca usar6 no mundo reil, mas que 6 quase certo de estafem no exame.
Os operadoresJava produzem novos valores apattt de um ou mais operandos (apenas par^ que fique rudo bem claro, os
operandos silo itens i esquerda ou direita do operador). O resultado damuonadas operag6es 6 um valor booleano ou
num6rico. E como voc6 j6szbe qweJaaa ndo d C**,ndo ftcar| suqpreso com o fato de seus operadores nio poderem ser
sobrecarregados. No entanto, h6 alguns operadores que j6 v6m sobrecarregados:
r O operador * pode ser usado para adicionar um primitivo num6rico a outro, ou para rea)tzar :uma operagdo de
concatenagio se um dos operandos for uma String.
I Os operadores &, I e ^ podem todos eles ser usados de duas maneiras diferentes, apesar de que, nesta verslo do exame,
as suas funcionalidades pa:aopengdo com bits nio sio cobradas.
Fique alerta. A parte do exame referente aos operadores e atribuig5es normalmente 6 aquela em que os candidatos
conseguem menos pontos. Al6m disso, operadotes e atribuig6es acabam entrando em muitas quest6es de outros t6picos...
Seria uma pena voc6 conseguit destrinchar uma questio realmente complexa sobre threads, s6 para ertar a resposta por causa
de uma instrugio de prd-incremento.
Operadores de Atribuigio
Abordamos a maior parte da funcionalidade do operador de atribuig6o,"=",no Capinrlo 3. Para resumir:
I Ao se atribuir um valor a um primitivo, o tamanho faz drfetenga. Certifique-se de saber quand o uma corrvetsdo implicita
ir6 ocorrer, quando a conversio explicita 6 necessiria, e quando poderao ocoffer cortes.
I Lembre-se de que uma variivel de referdncia nio 6 um obf eto; 6 uma maneira de se chegar a um obieto (Sabemos que
todos os leitotes que sZo programadores de C++ estao loucos para nos ouvir dizer "6 um ponteiro", mas nio iremos
fazer isso).
I Ao se atribuir um valor aumavai|vel de refer€ncia,o tipo faz diferenga. Lembre-se das regras para supertipos, subtipos
e arTays.
Em seguida, abordaremos mais alguns detalhes sobre os operadores de atribuigio que caem no exame e, quando
chegarmos no Capitulo 7, veremos como o operador "=" trabafhacom Strings (que s6o imut6veis).
Ndo derperdice teupo preparando-se para tuipicos que ndo utqam mais no exanel Resumindo, o exame Jaua 5 difere do exame / .4 por e
afastar dos bits e se
@roxinar da APL Muitos 1 .4 relacionados a lperadzres
tripicos da uersd.o flram remouidos do exame, de modo qile neste
capitulo uoc€ IIJAO uenl
I Complementosbindrios
I Assuntos referentes i divisio porzero
Ndo 6 que uns tdpicos ndo s/am importantes, d @enas qae e/es ndo caem mab n0 exane, e nosso objetiuo i nos concentranros no exame.
Y = Y - 6;
x = x +2 * 5;
E agora com operadores compostos:
Y-=6;
x+=2*5;
As duas ultimas atribuigSes d6o o mesmo resultado que as duas primeiras.
Versduantigasdoexameco/ocaaamumagrandeOnfatenaprueddnciadeoperadoresQono:pualrioresultadode:x=y+++++xf
z). f
Tirando am conhecimento ba$ante bdsico nbre a preceddncia (qae + e tin prued1ncia sobre *e -, por exemplo), uocd ndo precisard
estudarapreced1ncia de operadoru, exceto ofato de qae, ao asarilm operadorcorrposto, a expreudo no lado direito do = senPre senl aualiada
prineiro. Por exempl0, uoc6 podeia esperar qae
x*=2+5;
fosse aualiada duta forna:
x = (x * 2) + 5; // preced€ncia incorreta
uma ue<que a nuhiplicapdo tdn preced€nda sobre a adigdo. Pordrz, em ueTdisso, a exprer1o ti direita senQre 6 cokcada entrc paftnleses. E
aualiada destafonna:
x = x * (2 + 5);
Operadores de comparagao
O exame aborda seis operadores de comparagio ((, <=, ), )=, == e l-) Os operadores de comparagio sempre resultam
em um valor booleano (true ou f alse). Esse valor booleano 6 usado com mais freqri6ncia em testes if , como
vemos a seguir:
int x = 8;
r_r (x<v) 1
/ / faz al-go
\)
mas o valor resultante tamb6m pode ser atribuido diretamente a um tipo bool-eano primitivo:
class CompareTest {
public static void main(String [] args) t
booleanb=100>99;
System.out.printl-n("The value of b is " + b) ;
Java tem quatro operadores de comparagio que podem ser usados para comparar qualquer combinagio de inteiros,
nrimeros de ponto fluruante ou caracteres:
I > maior que
I >= maior ou igual a
I < menor que
t <= menot ou igual a
Examinemos algumas comparag6es v6lidas:
class GuessAnimal {
public static void main(String [] args) t
String animal = "unknown",.
int weight = 7OO;
char sex = 'm' ;
doubl-e colorwavelength = 1.530;
164 Copitulo 4: Operodores
if (weight >= 500) animal = "elephant";
if (colorWavelength > 1.627) animal = \'gray " + animal ,'
No c6.ligo anteriot, usalnos um operador de comparagio entre caracteres. Tamb6m 6 v6lido comparar um tipo primitivo de
c ractere com qualquer nrimero (embora nio seia um estilo de programagio adequado). A execugio da classe anterior exibfu6
o seguinte:
The animal is a gray elephant
Mencionamos que os caracteres podem ser usados com operadores de comparagio. Quando compara um caractere com
outfo ou um caractete com um nrimerq a linguagemJava usa o valor Unicode do caractere como o valor num6rico e
compara os nrimeros.
Operadores de igualdade l
J^v^tem tamb6m dois operadores de comparagio (chamados de "operadores de igualdade') que compa:-arndois itenr
semelhantes e retofnam um valor booleano que representa o que 6 verdadeiro sobre os dois itens serem iguais. Esses
operadores sio
I == g"al (tamb6m conhecido como "igual a')
I != difetente (tamb6m conhecido como "diferente de")
Cada compatagio pode envolver dois nfmeros (incluindo o tipo char), dois valores booleanos ou duas vad6veis de
teferdncia de objeto. Voc€ nio pode comparar tipos incompativeis, no entanto. O que significaria perguntar se um tipo
booleano €igoal,aum tipo char? Ou se um objeto Button 6 igual String? (Exatamente, neo tem
^!mafiay
sentido,e6porissoquen6opodemos faz€-lo).H6guatrotiposdiferentesdeitensquepodemsertestados:
I Nrimeros
I Caractetes
Por6m, o que o operador == examina realmente? O valor da vari6vel - em outras palavras, o padreo de bits.
class ComparePrimitives {
public static void main(String, [] args) {
System.out.println("character 'a' == 'a'? " + ('a' == 'a'));
System.out.println("character'a' =='b'? " + ('a' =='b'));
system.out.println("5 != 6? 't + (5 t= 6)) ;
System. out.println ( "5. 0 == 5L? " + (5. 0 == 5L) ) ;
System.out.println("true == false? " + (true == false) );
I
Esse progtama ptoduzir6. a saida abaixo:
l]-.booleanb=false;
L2. if (b = Lrue) i System.out.println("b is true");
l-3. i else { System.out.println(.,b is false,,) ; }
Olhecuidadovmente! Voc6podtfcartentadoapensarqaeauidarcni'b ts faIse", matexamineote$ebooleanodatinha2.A
aari,iuel booleanab ndo eshi sendo nmparada com lcr:ue, e$d sendo confgtrada com true, portanto, prinEJ.n nri execatado e
obteremos 'b i s t rue ". O resultado de qaalquer expressdo de ahibuSdo i igaal ao aahr da uariiael apris a atribuQdo. Essa ub$ituigdo
d0 inal = Pell nperador = = sdfxndona com uaridaeisbooLeanas, jd qile 0 terte if pode vrfeito apeltar em expresrdu booleanas.
Portanto, o aldigo abaixo ndo senl conpilada:
7.intx=1;
8.if(x=o) i)
Jd qw x i um inteim (e ndo un booleano/, o resultado de (x = vr
A) ser,i 0 (o resuhado da aaibtig1o) Os inteimt ndo pod.em
trvdos onde ttm aalor booleano i esperado, portanto, o aidigo da linba 8 ndofuncionanl a menlr qile sgja aherado de una ahibuigdo (=) para
rm tette de tgualdade (= =) como uemot a segxir:
8. if (x == 0) i )
'JButton b = a;
Depois que esse c6digo for executado tanto avai|vela quanto b referenciario o mesmo obieto (um obietoJButton com
o r6nrlo Exit). As vari6veis de refer6ncia podem ser testadas com o operador == para sabermos se estao referenciando um
obieto em comum. kmbre-se de que o operadot == estar6 examinando os bits da vari6vel, portantq com relagio is vari6veis
de referdncia, se os bits das duas variiveis forem id6nticos, elas estario referenciando o mesmo obieto. Examine o c6digo
abaixo:
I
Bt..s$digo cria tr€s vari6veis de refer€ncia. As duas primeiras, a e b, sio objetosJButton diferentes, que por acaso tem o
mesmo nome. A terceira r,zri6vel de referdncia, c, 6 inicializadapatarcferenciar o mesmo objeto que a esta referenciando.
Quando esse prograrna for executado , a seida a seguir ser6 produzida:
Is reference a == b? false
Is reference a == c? true
Ela nos mostra que a e c esteo referenciando a mesma inst6ncia de um objeto ,JButton. O operador == nio testar6 se
dois objetos sio "significativamente equivalentes", um conceito que veremos com muito mais detalhes no Capitulo 7, onde
abordaremos o m6todo equals ( ) (nio confundfu colr:;, o operadorde igualdade que examinamos aqui).
)i
O"Oj:"r o quanto ) i e feio, mas estamos preparando voc€ pa:ir- o exame). Esse exemplo produz a saida:
dot equals
4+
f! |^ : F^+-h^6^f
frrDudrrus9r Cf r.i na\
oLrrrrY,/ I
\E t
]
)
edbeisto:sisaString
Mesmo se o objeto testado nio for realmente uma instanciagio do tipo de classe que estiver do lado direito do operador,
instanceof ainda retornari verdadeiro se o obfeto puder ser atribuido a esse tipo.
O exemplo a seguir demonstra o teste em um obf eto com o uso de instanc eof ,p^r saber se ele 6 a instAncia de um
dos seus subtipos, antes de se tentar urna conversio "redutora":
class A i )
cl-assBextendsA{
public static void main (String IJ args) {
AmyA=newBO;
m2 (myA) ;
]
public static void m2 (A a){
if (a instanceof B)
( (B) a) . doBstuff ( ) ; / / convertendo uma refer6ncia A
/ / em ttma refer6neia B
]t
public static void doBstuff O {
SysLem.out.println(\\a' refers to a B");
]
]
O c6digo acima compila e produz esta saida:
'a' refers to a B
Emexemploscomoesse,ousodooperadorinstanceof protegeoprograrnacontraatenativadetentarumaconversio
invdlida.
Voc6 pode testar a referencia a um objeto confrontando-a com seu pr6pdo tipo de classe ou com qualquer uma de suas
superclasses. Isso significa que quaQaerreferdncia a um obieto seriavahada como verdadeira se voc6 usar o operador
instanceof junto ao tipo Obj ect, da seguinte forma,
JAVA 5 167
Bb=newBO;
if (b insranceof Object) {
System.out.print("b is definitely an Object,,) ;
i
que edbit6:
b is definitely an Object
interface roo { }
class A implements Foo { }
classBextendsAi )
Aa=newAO;
Bb=newBO;
ot rerultados a seguir rcrdo aerdadeims:
a instanceof Foo
b instanceof A
b instanceof Foo // implementado indj-retamente
Un objeto seri considerado de un tipo de inhrface especifn (igfieando que pasuni no te$e lnsEanceof) se algama de suas
wperclasnt implementar a inteface.
Al6m dissq 6 vilido testar se a refer6ncia de um objeto nu11 6a instincia de uma classe. Isso sempre resultar6 em
f aI se, € claro, Por exemplo:
class InstanceTest {
public static void main(String [1 args) t
String a = null;
boolean b = nul1 instanceof String;
boolean c = a instanceof String;
System.out.println(b + " " + c) ;
)
)
exibe isto: f al, se f al- se
class cat { }
class Dog {
public static void main(String tl args) {
Dogd=newDogO;
System.out.println (d inst.anceof Cat) ;
)
)
A compilagio fdha - d iamais poder6 se referir a um Cat, ou a um subtipo de Cat.
168 Copirulo 4: Operodores
oBSERVAQ6ES pene o EXAME
I-embre-v que os aralr sdo objetos, mesmo quando armaqenam tipos prinitiuos. Procure ddigot qae Po$am ter e$a @at€ncia na petganta:
Foo[ ] Object
Operadores aritm6ticos
Temos certeza de que vocd est6 familiaizado com os operadores aritrn6ticos b6sicos.
I + adiglo
I - subtragio
I x multiplicagio
I / divisio
EIes podem ser usados da maneira padrio:
int x = 5 * 3;
intY=x-4;
system.out.println("x - 4 is " + y); // Exibir6 11
)
JAVA 5 169
A execugSo da classe MathTest exibiri a linha a seguir:
The resul-t of 15 ? 4 is the remainder of 15 divj-ded by 4. The remainder is 3
(I-embre-se: As express6es sio avaliadas da esquerda p an dlteita,por padrio. Voc6 pode modificar essa seqriencia, ou
pmceddncia, adicionando parenteses. Lembre-se tamb6m de^que os opetadores *, / e %o tdm maior preced€ncia do que os
operadores * e -.)
i-nt c = 7,'
System. out.println (a + b + c) ,.
O operador * atuafi, como um sinal de adigZo quando somar as vari6veis int de b + c? Ou ftatara 3 e 7 como
caracteres e os concatenard individualmente? O resultado ser6 Stringl O ou St.ring3 7? Certo, voc€ teve tempo
suficiente para pensar sobre isso. Os valores int foram simplesmente tratados como caracteres e acrescentados i direita
da string. Portanto, o resultado 6:
String3 7
A regra a lembrar 6:
Se um dos operandosfor ama String, o operador I atuari c0m0 um operador de concatenagdo de SLrings, Se ot dois @erandot
forem nilrterot, o operador * funcionani como o operador de adipio.
Em algumas situag6es voc6 poderi ter problemas para descobrir se, digamos, o operador da esquerda 6 ou nio uma
String. No exame, nio espere que isso seja 6bvio. (I.{a verdade, i6 que mencionamos nisso, nunca espere que seja 6bvio).
Examine o c6digo a seguir:
System.out.println (x.foo O + 7) ;
Voc6nioter6meiosdesabercomoooperador* est6sendousadoat6quedescubraoqueom6todo foo ( ) tetotnarilt,
Se retornar uma seri concatenado a string retornada. Mas se f oo (
SLring, entio,T ) retornar um nfmero, o
operador* serdusadoparasomaro algarismo 7 comovalorretornadopor foo ( ).
Finalmente, voc€ ptecisa sabet que 6 v6lido mistutar o operador aditivo composto (*=) com Strings, desta forma:
String s = \\A23"i
s += "45";
s += 67;
System. out. printl_n (s) t
Umavez que nos dois casos o operador += foi usado, e o operando da esquerda era uma String, ambas as operagdes foram
concatenag6es, resultando em
L234567
I Z0 Copitulo 4: Operodores
oBSERVAQoTSpeneTXAME
Se aocd ndo compreendtr eomo a couatenaj1o de Stringsfunciona, principalmente dentm de ma instrufio de saida, podeni realmente ser mal
sucedido tt7 examq mesmo y soaber o retto da reposta i pergunta! Ji que tantas petglntat indagam, "pual rcni o resultado?", uoc| ptvcisa
taber tdo s6 qual a saida do ctidigo que eftiuerrcndo mas tambdm c0m0 esse resultado rcni. exibido. Mesmo bauendo pelo menot
neia di{a peryuntas que nriarAo diretamente seu conhecimento em strings, a eoncatenagdo de ftrings @ancenl em outras petguntas
d.e
de
cada objetiuo. Faga um teste! Por exenpk, uoc6 pode aer uma linha como
int b = 2;
System.out.print.ln(*\r + b + 3);
qae exibiri
z5
System.out.println(b + 3) ;
entdo, o resultado serti 5.
Acr6scimo e decr6scimo
A linguagemJava possui dois operadores que aumentario ou diminuirio uma vari6vel em exatamente uma unidade. Esses
operadores sAo compostos por dois sinais de adi96o (++) ou dois sinais de subtraglo ( -):
I ++ acr6scimo (ptefixo e sufixo)
I - - decr6scimo(prefixoesufixo)
O operador 6 inseddo antes (prefixo) ou depois (sufixo) de uma variivelpan alterar o valor. O fato de o operador vir antes
ou depois do operando pode alterar o resultado de uma expressdo. Examine o c6digo abaixo:
1. class MathTest i
2. static int PIaYers = 0;
3. public static void main (String [] args) {
4. System.out.println("players online: " + players++);
5. System.out.println("The value of players is " + players);
6. System.out.println("The value of players is now " + ++players);
7. )
8. )
Observe que na quarta linha do progtam ,o operador de incremento esta depois d^v^i6vel players. Isso significa que
estamos usando o operador p6s-fixado, o que far6 com que a variivel players seia aumentada em umavnidade, mat
sonente dEois que nu aabrfor uvdo na expresdo. Quando executarmos esse Programa, ele exibir6 o seguinte:
?java MathTest
players online: 0
The value of players is 1
The value of players is now 2
Observe que quando avai6vel6 exibida na tela, primeiro informa que o valor 6 igual a 0. J6 que usamos o operador de
incrementop/r-fxado,oacr6scimondoocouer6.at6omomento ap6savai6velplayers serusadanainstrugiodesaida.
Entendeu? A paniculapris de p6s-fixado significa depois. Allnha seguinte, a de nri.mero 5, n6o aumenta o valor de play-
ers ; apenas o exibe na tela, portanto, o valor rec6m-aumentado a ser exibido ser6 1. A linha 6 aphca o operador pre-fxado
a players, o que significa que o acr6scimo ocortetS. antesque o valor da van6velseiavsado (pMsigrtrfrcz antet). Portantq a
saida ser6igaal a2.
Espere por perguntas que combinem os operadores de incremento e diminuigio com outros operadores, como no
exemplo abaixo:
irlLx=2;
int Y = 3t
if ((Y -= x++) | (x < ++Y) ) {
System.out.println(<x = < + x + < y = < + y);
)
JAVA 5 17]
Oc6digoanteriorexibirix = 3 y =4
Voc6 pode ler o c6digo assim: "Se 3 for'rgoaIa2 OU menor do que 4..."
finalintx=5;
int y - x++,.
epmdt$ni o erm
Operador condicional
Ooperadorcondicional 6umoperadortemirio(temtr€soperandos)usadoparaavaliarexpress6esbooleanas demodo
semelhante iinstrugio if, exceto por,emvezde executar um bloco de c6digo se o resultado do teste for true, atdbuir
um valor i vari6vel. Em outras palavras, o objetivo do operador condicional 6 decidir qual dos dois valores atribuir a uma
variivel. Ele 6 constnrfdo com os simbolos ? (ponto de interrogagio) e : (dois pontos). Os pardnteses sio opcionais. Sua
estrutura 6 a seguinte:
"Configura numOf Pets igual a 3. A seguir, atdbui uma String avati|vel starus. Se numOf Pets for menor do que
4, atibur6"Pet limit not exceeded"; do contr4rio, atibwrd"too many pets".
O operador condicional comega com uma operagdo booleana, seguida de dois valores possiveis paraavai|veld,esquerda
do opetador (=). O primeito valot (que fica i esquetda dos dois pontos) set6 atribuido se o teste condicional @ooleano)
tiver um resultado true e o segundo valor seri atribuido se o resultado do teste for f al-so. Voc6 tamb6m pode aninhar
operadotes condicionais em uma insrugio:
class AssignmentOps {
public static void main(String [] args) {
int sizeOfYard = 10;
int numofPetss = 3;
String status = (numOfPets<4) ?,,Pet count OK,,
: (sizeOfYard > 8)? ,,pet limit on the edqe,,
: "too many pets",.
172 Copfiulo 4: Operodores
System.out.printl-n("Pet status is " + status);
Nio espere muitas perguntas que usem operadores condicionais, mas lembre-se de que, is vezes, os operadores
condicionais sio confundidos com as instrugSes assertivas, portanto, certifique-se de poder diferenci6los. O Capinrlo 5
abordari as assertivas com detalhes.
Operadores L6gicos
Os objetivos para o exame especificam seis operadores "l6grcos" (&, | , ^, !, && e | | ). Alguns documentos oficiais da Sun
usam outra terminologia para esses operadores, mas,parz.os nossos prop6sitos, os "operadores l6gicos" sio os seis
listados acima e nos objetivos para o exame.
Tendo dito tudo isso sobre operadores bitwise, o principal a se lembrar 6 isto:
uI4>D lUYrUAf I
public static void main(String [] args) {
l
)
6. if ((isrrsmall(6)) ll (isrrsmall(9))) t
7. System.out.println("Rsgult is true");
8. ]
e. )
10.
l-1. public static boolean isltSmall(int i) {
L2. if (i < s) t
13 . System. out .println ("i < 5" ) ,.
onde parece que estawts teutando usar am operador bit a bit E nos bits que representam os inteiros 5 e 6, mas o cfidigo lteln Tresmo
seni compilado.
I &Endo-abreviado
I I OU nio-abteviado
Esses operadores s6o usados em expressdes l6gicas, assim como os operadores && e | ; por6m, j6 que ndo sdo os|
operadores de abreviagio, aualiardo os dois ladw da exprusdo, semprclBles serio ineficientes. Por exemplo, mesmo se o primeiro
operando (ado esquerdo) de uma expressio & for f al se, o segundo tamb6m seri avahado - ainda que agora tenha n
tonado impossiuel o resultado serErue/E o operador I ser6 ineficiente na mesma medida; se o primeiro operando for true,
ele a;nda dati prosseguimento e avahatS" o segundo operando, mumo quando souber q*e a expressdo seri Erue.
No exame, voc€ veri muitas perguntas usando tanto operadores l6gicos de abrciagdo quanto os que nio usam a abreviag6o.
Voc€ ter6 que saber exatamente quais opetandos sefao avaliados e quais ndo serlo, jique o resultado variar|se o segundo
opetando da expressio for ou n6o avaliado:
1nt z = 5;
if(++z r 5 (ll ++z > 6) z++i // z = 7 depois deste c6digo
contra:
int z = 5;
if (++z > 5 | ++z > 6) z++; // z -- 8 depois deste c6digo
OperadoresL6gicos ^ e!
Os dois ultimos operadores l6gicos no exame s6o
I ^ OU exclusivo (XOR)
I !inversiobooleana
O operador ^ (OU exclusivo) avalia somente valores booleanos. O operador ^ relaciona-se com os operadores de nio-
abreviagio que acabamos de revisar, no sentido de que sempre ava)ia ambot os operandos, o do lado direito e o do lado
esquerdo, em uma expressio. Pata uma expressio OU exclusivo ( ) set verdadeira, EXATAMENTE um operando precisa
ser Lrue - por exemplq
system.out.println("xor " + ( (2<3) ^ (4>3) ) );
produz asuda; xor false
A expressio actma avaJia como f al se porque TANTO o primeiro operando (2 < 3) quanto o segundo (4 > 3) avdtam
como crue.
O operador ! (inversio booleana) retorna o oposto do valor atual de um booleano:
if ( l (? == 5) ) { Sysfem.out.println("not equal") ; }
pode ser lido como "se nio for verdade que 7 == 5", e a instrugio produz esta saida:
not egual
Eis um ouuo exemplo usando booleanos:
boolean t = true;
boolean f = false;
System.out.prinLln("! " + (t & !f) + " " + f);
produz asuda:
! true false
No exemplo anterior, repare que o teste & teve sucesso (exibindo true), e que o valot da variavel booleana f n6o se
modificou, de modo que ela exibiu f alse.
Se voc6 estudou este capinrlo atentamente, deve tet obtido uma compreensio s6lida sobre os operadoresJava, e dever6
saber o que significa igualdade, quando seu conhecimento sobre o operador == for avaliado. Recapitr:lemos os Pontos
JAVA 5 I75
importantes do que voc€ aprendeu neste capitulo.
Os operadores l6gicos (&& e I l) s6 podem ser usados para avaliar duas express6es booleanas. A difetenga entre && e
& 6 que o operador && n6o se preocupari em testar o operando direito, caso o esquerdo for avaliado como f aI se, pois o
resultado da expressio && nunca pode ser true. A diferenga entre | | e | 6 que o operador | | n6o testar6 o operando
direito se o esquerdo for avaliado como true, porque o resultado i|setkrcconhecido como nesse momento. true
O operador -- pode ser usado p^r comp^rar valores de tipos primitivos, mas tamb6m pode ser empregado para
determinar se duas variiveis de refer6ncia referenciam o mesmo objeto.
Ooperadorinstanceof 6usadoparadeterminarseoobjetosendoreferidoporumavari6velderefer€nciapassano
teste E-UM para um tipo especificado.
Ooperador* 6sobrecarregadopanteahzartatefasdeconcatenaglodeStrings,epodeconcatenartamb6mStrings
com tipos primitivos, mas curdado - essa operagio pode ser complicada.
O operador condicional (tamb6m conhecido como "operador temirio') tem uma sintaxe incomum, com tres operandos -
nio a confunda com uma instrugio assert complexa.
Os operadores **s - - sereo usados em todo o exarne, e voc6 deve prcstzraatengdo a se eles s6o prefixados ou posfixados
ivaridvel que esti sendo atuaJizada.
Prepare-se para muitas perguntas no exame envolvendo os t6picos deste capihrlo. Mesmo em perguntas que testarem seu
conhecimento referente a outro obfetivo, o c6digo freqiientemente estar6 usando operadores, atribuig6es, passagem de
objetos e tipos primitivos, e assim por diante.
,/ Exercfcios r6pidos
Aqui estlo alguns pontos-chave de cada segio deste capitulo.
Q Quando compata car cteres, a linguagemJava usa o valot Unicode do caractet como o valor num6rico.
fl Operadores de igualdade
E Quatro tipos de itens podem ser testados: nirmeros, caracteres, booleanos, vari6veis de referdncia.
E Hi dois operadores de igualdade: == s l=.
Q Ao comparar vai|veis de refer€ncia, == retotna true somente se ambas as refer€ncias apontatemparao mesmo
objeto.
E Para intedaces, um obieto passa no teste instanceof se alguma de suas superclasses implementar a interface do
lado direito do operador instanceof .
D Os operadores l6gicos trabalham com duas expressSes (exceto ! ) que devem resultar em valores booleanos.
fl Os operadores && e & retornario Erue somente se os dois operandos forem uerdadeiros.
E Os operadores | | e I retornario true se um ou os dois operandos forem uerdadeims.
Q Os operadores && e | | sio conhecidos como operadores de abreviagio.
D O operador && ndo avahard o operando direito se o esquerdo for f a 1 se.
E O operador | | ndo avahat6ooperando direito se o esquerdo for true.
fl Os operadores & e I sempre avallamos dois operandos.
Q O operador ^ (chamado de "XOR l6gico') retorna t rue se exatamente um operando for verdadeiro.
E O operador I (chamado de operador de "inversio'), retorna o valor contr6rio do operando booleano que o precede.
Teste individual
l. Dado:
class uexy {
-,,L1
I ^ ^!-+i ^
"roi-d main
- (Srring [] args) {
Integer i = 42;
String s = (i<40) ?"1ife": (i>50) ?"universe" t"everything";
System. out.prinLln (s) ;
i
)
Qual 6 o resultado?
A. null
B. life
C. universe
D. everything
E. Acompilagio falha.
E E langada uma excegio no tempo de execugio.
2. Dado:
1. class Example {
2. public static void main(StringlJ args) {
3. Short s = 15;
JAVA 5 I77
4. Boolean b;
5. // insira o c6digo aqui
o. l
7. \
Qual opgio, inserida indepentemente na linha 5, ir6 compilar? (I\zlarque todas as corretas)
A.b = (Number instanceof s) ;
B. b = (s instanceof Short);
C. b = s. instanceof (Short) ;
D. b = (s instanceof Number);
E. b = s. instanceof (Object) ;
E b = (s instanceof String);
3. Dado:
1. cl-ass Comp2 i
2. public st.atic void main(Stringtl args) t
3. fl-oat f1 = 2.3f ;
4. floar n il f2 = {{.42.0f1 , {t.tt, 2.3tll , {2.6f., 2.tf}} ;
s. float tl t: = {z.tt} ;
6. Long x = 42Li
7. // insira o c6digo aqui
8. System.out.println("true");
ol )
10. i
E os cinco seguintes fragmentos de c6digo:
F1. if (fr == 121
EZ. :tlC.
r!\!r <^r^I r.l\
== LZLZJLLJ)
F3. if (x == f2 iol tol )
F4 . if (f1 == f2 lr,rl )
Fs. if (f3 == f2 L2) )
O que 6 verdadeiro?
4. Dado:
crass lorK t
public static void main(stringlJ args) t
if(args.length == 1 I args[1J.equals("test")) t
System. out.println ( "test case" ) ;
) else {
System.out.pri-ntln("production " + args [0J ) ;
)
)
178 Copftulo 4: Operodores
E a chamada de linha de comando:
java Fork 1ive2
Qual 6 o tesultado?
A- test case
B. production
C. tesE case live2
D. Acompilaglofalha.
E 6 hngada uma excegio no tempo de execugio.
5. Dado:
class Foozit {
public static void main(String[] args)
fnt.eger x = 0;
Integer y = 0;
for(Short z = 0; z < 5i z++)
if( (++x > 2) I | (++y > 2) )
x++ r.
System.out.println(x + s \ + y) ;
)
Qual 6 o resultado?
A-51
8,5 2
c.s3
D.81
882
883
G.102
rL10 3
6. Dado:
class Titanic {
public static void main(StringlJ args) {
Boolean b1 = true;
boolean b2 = false;
boolean b3 = true;
if ((br- & b2) | (bz e b3) & b3)
System. out .print (..alpha ., ) ,-
System.out.print ("beta *) ;
)
Qual 6 o resultado?
,{.. bet,a
B. alpha
C. alpha beta
JAVA 5 I79
D. Acompilagdofalha.
E Nio 6 produzida nenhuma saida.
7. Dado:
class Feline {
public static void main(StringlJ args) {
Long x = 42L;
Long Y = 44Li
System.out.prlnt(\\ \\ + 7 + 2 +.. ..),'
System.out.print(fooO + x + 5 + ,' .,);
System.out.println(x + y + fooO);
]
static String foo O { return "foo"; }
)
Qual 6 o resultado?
A" 9 foo47 86foo
8.9 foo47 4244foo
C. 9 foo425 86foo
D.9 foo425 4244foo
E 72 foo47 86foo
n 72 foo47 4244foo
G. 72 foo425 86foo
I+ 72 foo425 4244foo
I. Acompilagdofalha.
8. Coloque os fragmentos no c6digo para produzar a saida 33. Obseryagio: voc6 deve
usar cada fragmento exatamente uma vez.
class Incr i
public static void main(StringlJ args) {
Integer x = 7;
i-ntY=2;
)
FRAGMENTOS:
Y v Y v
Y x x
*= *=
I80 Copitulo 4: Operodores
9. Dado:
1. class Maybe {
2. public static void main(Stringtl args) {
3. boolean b1 = t.rue;
4. boolean b2 = false;
5. system.out.print(!fatse ^ fatse) ;
6. system.out.print(* $ + (!b1 & 1bz = true)));
7. system.out.println(' " + (b2 ^ b1)) ;
8. )
q]
'. )
O que 6 verdadeiro?
,d true.
A linha 5 produz
B. A linha 5 produz false.
C. A linha 6 produz true.
D. A linha 6 produz false.
E A linha 7 ptodtz true.
E AlinhaTproduzfalse.
10. Dado:
class Sixties {
pubtic static void main(StringtJ args) {
int x = 5; int y = 7;
System.out.print(( (y * 2) Z x)) ;
System.out.print(" " + (y ? x) );
i
)
Qual 6 o resultado?
A-11
B.L2
c.21,
D.2 2
E.41
F.42
G. Acompilagdofilha.
H. E langada uma excegao em tempo de execugio.
Respostas
1. D est6 correta. Este 6 um ternirio aninhado dentro de um ternario com um pouco de unboxing funto. Ambas as
express5es tern6rias slo falsas.
A estd incorreta porque os operandos est6o invertidos. C e E usam sintaxe instanceof incorreta. F estl errada
porque Short nio est6 na mesma 6rvore de heranga que String. (Obietivo 7.6)
5. vezes em que o teste i f 6 execuadq tanto x como y sio incementadas uma vez (s6
E esti correta. Nas duas primeiras se
alcangax++ natercekaitetagno).Apartirdatercaraiteragdodoloop,y nuncamais6usadqporcausadooperadorde
abrevia$o
6. E est6 cotteta. No segrrndo teste i f , a expressio mais i esquerda 6 uma aribuigio, e nio uma comparagio. Depois que
b1 foi definido como f al-se. os demais testes sdo todos f al-se.
A B, C, D e F estio incorretas com base no exposto acima . (Objetivo 7.6 )
7. G est6 correta. A concatenagio roda da esqu erdz pata z dtreita e, se algum dos operandos for uma S t r i ng, os
opetandos s6o concatenados. Se ambos forem nrimeros, eles sdo adicionados um ao outro. O unboxing funciona em
coni unto com a concatenagdo.
8.
class Incr {
Sim, sabemos que isso 6 complicadq mas voc€ poder6 encontrar algo parecido no exame real. (Obietivo 7.6)
10. F est6 correta. O opendoroh (resto, tamb6m conhecido como m6dulo) retorna o resto de uma operagio de divis6o.
Obierivos pqrq q
certificqe6o
I Usor InstruE6es if e switch
( Exercicios r6pidos
As instrug6es i f
e swi tch sio tipos de controles condicionais/de decisio.que permitirio aseu pro gramaagt de
ma.reira em uma "bifurcaglo do caminho", dependendo do resultado de um teste l6gico. A linguagemJava
iif..enre
fornece tr|s estruturas de loop difeientes - f or, whi Ie e do - portanto,
-As
voc6 poderi executar o mesmo c6digo
repetidamente ar6 que o res"hrao ae Agu-a condigio seja true. exceg6es the proporcionario,uma maneira simples e
limpa de organizarts c6digos e de lidar com ot proble*as que poss-am surgir no tempo de execugio. Para concluir, o
*"i*ir*o"d" asserrivas, aJicionado a linguagem na versXo 1 .4, lhe fornecer6 um meio de executar verificag6es de depura$o
-o
em condig6es que vod queira expor durante desenvolvimento, quando nio quiser ou precisar gerar a sobrecarga no temPo
de execugXo associada i manipulagio de exceg6es.
Com essas ferramentas, vocA poder6 desenvolver um programa robuso, capaz de manipular qualquer.situaglo l6gica com
sofisticaglo. Espere virias pergunras no exame que incluam o controle de fltrxo como pane de seu c6digo' at6 mesmo
aquelas que nio estiverem avaliando especificamente seu conhecimento sobre esse asstrnto.
As instrug6es i f e swi tch geralmente sio conhecida s como inshwpdes d.e decisd.o. Quando voc6 usar instrug6es de decisio
em seu programa, estar6 solicitando a ele que avalie uma expresslo especifica a fim de determinar que curso de a$o tomar.
Examinaremos primeiro a instrugio i f .
Ramificagio if-else
O formato bisico de uma instrugio if 6o seguinte:
if (expressdoBooleana) {
System.out.println( "conte\ido da instruqdo if" ) ;
if (x>3) {
System.out.println("x is greater than 3");
) else {
System.out.println("x is not gfreater than 3");
]
O bloco e1 se 6 opcio nal, portanto, vocA tamb6m poderia usar o seguinte:
if (x>3) {
]
z L- a.
a=y+X;
Oc6digoanterioratribuir|ovalor2ay seotesteforbemsucedido(isto6,sex forrealmentemaiorque3),masas
outras duas linhas tamb6m serio executadas independente disso. At6 mesmo as chaves serio opcionais se voc6 s6 tiver uma
instrugio a executar dentro do corpo do bloco condicional. O c6digo do exemplo abaixo 6 vilido (embora nio seja
recomendado por raz6es de legibilidade):
] else {
if (price < 400) {
getApproval ();
]
a'l co f
dontBuyProduct ( ) ;
J
)
Issonostrazaooutroconstrutorif-else,oif,e1se if,else.Oc6digoanteriorpoderia(edeveria)serreescrito
como:
if (price < 300) {
l.urrrDrnArra+
vsjrrvvseu\/, / \ .
) else {
dontBuyProduct ();
]
Existem algumas regras para o uso de eI se e de el s e i f :
I Voc6podeterumounenhumelse paraumdadoif,eeledevevirdepoisdequaisquerinstrug6eselse if.
r Vocdpodeterdemuitosounenhumelse if paraumdadoif,eelesdevemvirantesdoelse (opcional).
I Depois que um else tem sucesso, nenhum dos demais else i f ou else ser6 testado.
O segqnte glemplo mostra um c6digo horrivelmente formatado para o mundo real. Como vocA provavelmente j6
adivinhou,_6bastante prov6vel que encontre ese tipo de formatagio no exame. De qualque r f.orma,o codigo dernonstra o
uso de mriltiplos e lse i f :
int x = 1;
if(x==3){}
el-se if (x < 4) {System.out.println("<4"); }
else if (x < 2) {System.out.println("<2"); }
else { System.out.println("e1se") ; }
186 Copitulo 5: Controle de fluxo, exceE6es e qssertivos
(R.epareque,mesmoqueosegundoelse sejaverdadeiro,aexecugionuncachegaaele.)
Intencionalmente neo usamos o recuo nesse trecho de c6digo, portanto, ele nXo fornece pistas sobre a que instrugio i f a
cliusula else perrence. VocA conseguiu descobrir? As normas da linguagemJava determinam que uma cl6usula else
pertencerl ) initrugXo i f mais pr6ima a qual ela possivelmente pertenga (em outras palavras, i instrugio i f anterior
mais pr6xima que nio tenha uma cl6usula Llse). No caso do eximplo anterior, a cl6usula else pertencei segudn
instruglo i f da listagem. Com o recuo apropriado, a instrugio teria e$e formato:
if lavam Aana/\\
Seguindo nossas conveng6es de codificaglo que faz uso de chaves, ela ficaria ainda mais f6cil de ser lida:
if (exam.doneO ) {
if (exam.getscoreO < 0.61) {
System. out.prj-ntln ( "Try again. ");
No entanto, nio comece a ficar esperangoso pensando que os c6digos das perguntas do exame e$areo todos
apropriadamente recuados. Alguns candidatos t€m at6 uma frase de efeito para a maneira como as perguntas sio
apresentadas: tudo que puder ser feito de maneira mais confusa, assim seri.
Esteja preparado para perguntas que al6m de nio recuarem os c6digos apropriadamente, o fario intencionalmente de
maneira confusa: preste bastante atengio em distragSes como a do exemplo a seguir:
if (exam.done O )
queodbiri
anterior assim: "Se tanto (x > 3) quanto (y < 2) forem t rr-re ou se o resultado de dostuf f ( )
VocO pode ler o c6digo
tor true, entio 'true" seri exibido. Portanto, basicamente, se apenas d.oStuf ( ) for true, ainda obteremos true.
!or6ln,sedoStuff ( ) forfalso,(x>3)e(y<2)terloquesertrue paraquetruesejaexibido".Oc6digoanterior
ficariundamais complexo se voc6 nio inserir um conjunto de par6ntese, .orrro lr.rrro,
"t"i*o,
int y = 5'
int x = 2;
if ((x > 3) && (y . 2) I aostutro ) {
System. out.println ( "true,, ) ;
]
Agora ele exibir6... Nada! Porque o c6digo anterior (com um conjunto de par6nteses a menos) far6 a avaliagio como se
estivesse dizendo, "Se (x > 3) for true, e (y < 2) ou o resultado de oostuf f ( ) tamb6m o for, true ser6 exibido.
Portanto, se (x > 3) nlo for true, nio haveri por que verificar o resto da expressio". Por causa do operador && de
abreviagio, a expressio ser6 avaliada como se houvesse par€nreses enfeixando ( lv.z I dostuf f ( )). Em outras
palavras, 6 avaliada como uma rinica expressio antes do Er& e como uma 6nica expressio depois do Ec&.
Lembre-se de que o rinico argumento v6lido para um teste if 6 um valor booleano. Em algumas linguagens, O ==
false,e1== t.rue.MasnioemJava! Oseguintec6digomostrainstrug6esif quepodemparecerv6lidas,masnio
sio, seguidas de substitutos v6lidos.
int- irrraTnf - 1.
'i nl- f: l qoTnf = O.
if (truelnt) // inv6lido
if (truelnt == true) // inv5aido
if (1) // inv6lido
if (falseInt == fal-se) // inv6Tido
if (truelnt == 1) // v6lido
if (falselnt == 0) // v6Lido
oBSERVAQ6ESpeneOE)(AME
Um ero clmtlm qtle os programadoru cometea (e que pode ser dficil de identfimr) i atribair ama uari,iael booleana quando a intenpdo seria
teshl-la. Cuidado com aldigot como o seguinte:
1., pae o aidigo rcni nnpikdo e executado adeqaadamente, mdr qae o teste if falhar,i porque boo 6 f also.
2, pue o aidigo ndo senl nmpilado porque uoci est,l asando uma atibuigdo (: ), t, ueTde um teste de igualdade (: : ).
3. pae o aldigo senl conpilado e executado adzquadamente, e o teste if seni bem sandidn porque boo foi confgurado com Lrue (em
ueTde estar sendo aualiado se d uerdadeiro) n0 argunentl da insrap1o if!
E inilrtl, mas rctr?ta. Dado que o resultado de qualquer atibaQdo i igual ao ualor da aai,iuel incluido @rir essa
Bem, a oppdo 3 estti correta.
atibuigdo, a expressdo (boo = Lr:ue) turA como resaltado Erue. Portantz, 0 teste iffoi ben ncedido. Mas a ilnica uariduel que pode
ser atribaida (en ueqde aaaliada com relagdo a algo) d um ualorbooleano; todas as outrar atibuipdes resultardo erzt algum ualor ndo
booleano de modo qae ndo serdo udlidas, rcmo nas linhas a seguir:
Instrug6es svvitch
lJma maneira de simular o uso de virias instrug6es if 6 com a instrugXo switch. Observe o c6digo do bloco else-
if e veja como pode ser confuso ter testes if aninhados, mesmo com apenas alguns niveis:
int x = 3;
if (x == 1) {
System.out.println( "x equals 1" ) ;
]
else if(x == 2) {
System. out.println ( "x equals 2" ) ;
)
else if 1x == 3) {
System.out.println( "x equals 3" ) ;
)
el-se {
system.out.println("No idea what x is");
)
Agora vejamos a mesma funcionalidade representada na estrutura de uma instrugio swi tch:
int x = 3;
switch (x) {
case 1:
System. out.println ( "x is equal to 1," \;
break;
case 2:
System. out . println ( "x is equal to 2" ) ;
break;
case 3:
Q\rc|-
rJ 6m r vuu
p uelr nrrF nrinr'ln
. y! fIIurrr /\
"x is equal to 3");
break;
default:
System. out.println ( "Still no idea what x is" ) ;
ObservagXo: arazXo pelaqual essa instrugio switch emula os i f s aninhados listados anteriormente 6 devido )s
instrug6es break que foram colocadas dentro do switch. Em geral, as instrug6es break sio opcionais e, como veremos
daqui a algumas piginas, a inclusio ou excluslo delas causa grandes mudangas na forma como a instrugio swi tch seri
er<ecutada
switch (express6o) {
case constantel: bloco de c6digo
case constante2: bloco de c6digo
default: bloco de c6diqo
i
A expressio de um switch deve avaliar um char, byte, short, int ou, a panir do Java 5, um enum. Isso significa
que, se voce nio estiver usando um enurg s6 vari6veis e valores que puderem ser promovidos automaticamente (em
a um tipo int
outras palavras, implicitamente convertidos) serio aceitos. VocA nio conseguiri compilar se usar algum tipo
diferente, incluindo os tipos num6ricos 1ong, f loat e double.
O rinico argumento que uma instrugXo case poder6 avaliar seri aquele que apresentar o mesmo tipo que a instruSo
JAVA 5 I89
swi tch pode u.ar, com uma restrigio adicional - e re/euante: o argumento de case tem que wr uma constante tlc tenpo de conpikgdo!
Ele precisa ser resolvido no tempo de compilagio, portanto, isso quEr dizer q,r. vo.6 ipode usar uma variivi f inai
constante com um valor literal. Nio 6 o suficiente ser f ina1, ela deve ser uma constante no tempo de compila$o. Por
e><emplo:
f i-a] ihf . - 1.
final int b;
intx=0;
switch (x) {
case a: // ok
case b: / / erro de compilagdo
Al6mdisso,ainstrugdoswiLgh sdpodeuerifcaraigualdade.Oquesignificaqueosoutrosoperadoresrelacionaiscomomaior
qae sio.considerados nio utiliz6veis em uma instruEio case. A seguir temos o exemplo de uma expressS.o vilida que usa
uma chamada de m6todo na instrugio swi t.ch. Observe que para esse c6digo ser v6fido, o m6todo que esti sendo
chamado na referdncia ao objeto deve rerornar um valor compitivel com umiipo int.
String s = "xyz";
switch (s.lengthO ) {
case 1:
System.out.println( "length is one,') ;
break;
case 2:
System. out.println ( "length is two" ) ;
break;
case 3:
Syst.em. out.println ( "length is three" ) ;
break;
default:
System.out.println( "no match" ) ;
l
Oura regra que voc6 poderia nio esperar envolve a pergunta: "O que aconteceria se uma variivel menor do que um tipo
int fosseusadanainstrugloswitch?"Examineoexemplodeinstrugioswitch aseguir:
bYte g = 2'
switch(g) {
case 23:
case 128:
)
Esse c6digo nXo seri compilado. Embora o argumento da instruglo swi tch seja v6lido - um tipo bpe 6 convertido
implicitamente em um tipo int. - o segundo argumento de case (128) 6 muito grande para um tipo byte e o
compilador sabe disso! Se vod tentar compilar o exemplo anterior ver6 um erro:
Tamb6m nlo 6 vilido ter mais de uma instrugio case usando o rnesmo valor. Por exemplo, o bloco de c6digo a seguir
nio ser6 compilado porque usa duas instrug6es case com o mesmo valor igual a 80:
int temp = 90;
quri talr lr- amnl I
case B0 : System.out.println("80") ;
case 80 : System.out.print]n("80"); / / nd.o compila!
190 Copftulo 5: Controle de fluxo, exceq6es e ossertivos
case 90: System.out.println("90") ;
default: System.out.println("default") ;
A tt't
-c varoo se aprovenar cos recursos do boxing em uma expressao swi tch. O seguinte exemplo 6 vAlido:
switch(new Inteqer(4) ) {
case 4: System.out.println("boxing is OK");
]
oBSERVAQ6ESpeneOE)(AME
Procure alguma uiolagdo nas regras dos argumentos de swiLch, case. Por exenp/0, uocd pode enclntrar exempks que nio serian ttd/idos
como os tr* trecbos abaixo:
switch (x) {
case 0 {
)
switch (x) {
o: { }
1: { }
No exemplo, a inshag1o case usa uma cbaue e omite os dois pontos. O segundo exempk omite a pakwa-chaae case.
Em outras palavras, ap6sse encontrar uma correspond6ncia para uma constante case, a JVM executar6 o bloco de
c6digo associado e tamb6m TODOS os blocos de c6digo subseqiientes (fora uma instrugio break) ! O seguinte
exemplo usa um enum em uma instrugio case.
anrrm ('nlar IraA dra6n ].r'lrral
class SwitchEnum {
public static void main(String [] args) {
Color c = Col-or.gfreen;
switch(c) {
case red: System.out.print ("red ") ;
case gfreen: System.out.print("green ") ;
case blue: System.out.print ("b1ue ") ;
default: .qvstem-otrt nri nf ln( "done"),'
]
Neste exemplo, case green: teve uma correspondencia, entio aJVM executou esse bloco de c6digo e todos os
blocos subseqiientes paru produztr a saida:
green blue done
Novamente, quando o programa encontrar apalavra<have break durante a execugAo de uma instrugAo swj-tch, o
processamentopassar6imediatamentedoblocoswitch paraainstrugioposterioraele.Seapalavra-chaveforomitida,o
programa simplesmente continuar6 a executar os outros blocos case at6 que uma palavra break seja encontrada na
JAVA 5 191
]
Syst.em. out.println ( "out of the switch" ) ;
)
Ainstrugloswitch exibir6"x is an even number"ounloexibir|nada,issodependerAdonrimeroestarentre
um e dez e ser par ou impar. Por exemplo, se x for igual a 4, a execugio comegar6 na instrugio case 4, mas, e1n seguida,
percorrer6 as instrug6es 6, 8 e 10, onde exibir6 o resultado e ser6 interrompida. A prop6sito, a palavra break da instrugio
case 1 0 nio 6 necess6ria; o final da instrugio swi tch j6 ter6 sido atingido.
Observagio: pelo fato de a passagem completa ser pouco intuitiva, a Sun recomenda que voc6 adicione um coment6rio,
como: // pas sagem compl eta, quando usar essa l6gica em seus Programas.
A instrugio case default
Ese,usando oc6dtgoanterior,voc6quisesseexibir"x is an odd
number"quandonenhumadasinstrug6escase
(os switch ou como a riltima
nrimeros pares) fosse satisfat6ria? VocA nlo poderia inserir o resultado depois da instrugio
instrugiocase dainstruEioswitch,porquenessasduassituag6esoresultadoexibidoseriasempre"x is an odd
number". Para obter esse comportamento, use a palavra-chave default. (A prop6sito, se voc€ estiver se perguntando
por que h6 uma palavra-chave def ault ainda que nlo seja usado um modificador para o controle de acesso padrio,veri
agora que ela 6 empregada com uma finalidade completamente diferente) A rinica alteragXo que precisaremo sfazpr ser|
adicionar a instrugio case default
ao c6digo anterior:
int x = someNumberBetweenoneAndTen;
switch (x) {
case 2:
case 4:
case 6:
case B:
case 10: {
System.out.println("x is an even number");
break;
)
default: System.out.println("x is an odd number");
)
OBSERVAQoESPARAOH(AME
A instrag1o case def auLE pode ndo uir nofnal da inshagdo switch. Procure-a em locait e$ranhos como aemos abaixo:
inL x = 2:
switch (x) t
ea<a arrf
2, r vJrLerrrtvuu.v!frruril\
Qrrcfam nr.i6f l-/\rarr\. z
It
default
;
E se a alteramtos de modo qae a ilnica comrpond1ncia sela a inshagdo can defuult:
int x = 7;
switch (x) {
n:qa ?' , (rrefom arrf
sJ-Lsrrrivuu.PrrrrLrLL\nrihfln/\r/\. L t,
JAVA5 I93
default : System. out.printl-n ( "defaulL" );
na<a ?. Qrrcl- am vse r nri nf 'l n / $?" I
4aAe+
.
^11t- tsr
default
Exercfcio 5- 1
Al . t. ..f.
L/OleTrvo poro o centttcogoo
Loops e lteradores (Obietlvo 2.2 do exame)
2.2 Escreueraidigo qrc implenente todas asforwas de loopt e iteradorcs, induindo o uso defor, do loopforEinorado (for+ach), do, while,
labels, break e nntinue; e explicar os ualores *tiliqadot pelas uaiiutit de cortador do loop darante e @6s a exuugdo desse.
OsloopsdalinguagemJavav6memtr6svers6es:while,doefor(e,apanirdoJava5,oloopfor temduas
variantes). Todas as tr& permitem que voc€ repita a execugio de um bloco de c6digo at6 que determinada condigio seja
uerdadeira ott durante uma quantidade especifica de iterag6es. Voc€ deve estar familiarizado com os loops de outras
linguagens, portanto, mesmo se for iniciante emJava, esses loops nio serio dificeis de aprender.
++X;
]
Nesse caso, como em todos os loops, a expressio (teste) ter6 que resultar em umvalor booleano. O corpo do loop
while rdser6executadoseaexpressfo(tam66mchamadade"condigio") resultaremumvalortrue. lJmavezque
entrarmos no loop, seu conterido ser6 repetido at6 que a condigio nio possa mais ser_atendida e seja avaliada como f a1se.
No exemplo anteiior, o fluxo do programa entrari ,ro corpo do loop p-orque x 6 igual a 2. No entanto, x serl aumentado
194 Copitulo 5: Controle de {luxo, exceg6es e ossertivos
no loop, de modo que quando a condiglo for verificada noyamente seri avaliada como f alse e a execugeo do
loop seri finalizada.
Qualquer variivel usada na expressio de um loop while deve ser declarada antes da expressio ser avalia&. Em outras
nio pode escrwer
palavras, voc6
O ponto chave a lembrar sobre o loop whi 1e 6 que ele pode nem mesmo ser exectrtado. Se a expressio do teste for
false naprimeiravezqueoloopwhile forverificado,ocolpodoloopser6ignoradoeoprogramacomegareaser
executado na primeira instrugio depois dele. Examine o exemplo a seguir:
i-nt x = B;
whife (x > 8) {
System. out.println ( "in the 1oop" ) ;
x=10;
)
System.out..println( "past the 1oop" ) ;
Usando loops do
O loop do 6 semelhante ao loop whi 1 e, exceto pelo fato de que a expressao nlo 6 avaliada at6. que o c6digo do loop do
tenha sido executado. Ponanto, 6 garantido que o c6digo dentro de um loop do ser6 executado pelo menos uma vez. O
c6digo abaixo mostra um loop do em ageor
do{
System. out. println ( "rnside loop" ) ;
] while(false);
AinstrugioSystem.out.println( )seriexibidaumavez,aindaqueaexprusdos/aaualiadacomofalse.Lembre-se
de que o loop do serrpre execvt^o c6digo de seu conterido pelo menos umaaal. Nio esquega de observar o uso do ponto e
virgula no final da expressio while.
oBSERVAQ6ESpeneOE)(AME
Como nos tettes if , procure loops whil-e (e testes while de loops do -whi 1e) clm ilma expressdo que ndo resalte em um
booleano. Examine os exenplos abaixo de exprutduwhile uilidas e ndo-udlidar
intx=1;
while (x) { } / / Nao compila; x nio 6 booleano
while (x = 5) t ] / / Ni,o compila; resolve como 5 (resultado da atribuiqSo)
while (x == 5) { } // // rr.<l
.i
vaLLwt A^ F^df
ue>Le ^ /{a
uL i nrra l da^o
rvqqrsqse
r Declara$oeinicializa$odevariiveis
I A expressio booleana (teste condicional)
I Aexpressiodeiteragio
Cada uma das tr6s partes da declaragio do loop f or 6 separada por um ponto e virgula. Os dois exemplos a seguir
demonstram o loop f or. O primeiro mostra as partes de um loop f or em forma de pseudoc6digo e o segundo exibe a
sintaxe tipica do loop:
for (/*Inicializaqdo*/ ; / *Condiq5o*/ ; /*lteraedo*/ {
/* Corpo do loop*/
]
for (int i = 0; i<10; i++) {
q\rql-am nrinl-lnt"i iq " + i).
^rrt
]
/ / avnraccAoq
for (;i<10;) {
i++;
/ / faz algum outro trabalho
]
O exemplo abaixo demonstra um loop for com diversas variaveis. Umavirgula separa as variiveis e elas precisam ser do
mesmo tipo. Lembre-se de que as vari6veis declaradas na instruglo f or slo todas locais do loop, e nio po&m ser usadas
fora desse escopo.
PREPARAQAOPARAOE)HME
O ucopo das uaidueis terd unafungdo abrangente n0 exama Vocd ter,i que saber que ama uaidael declarada no loop f or ndo podeni ser
usadafora dele. Pordn, ama uariduel apenas inicialiTada na inthwgdo f or
(rzat dularada anteriormente) pode ser usadafora do loop. Por
exempk, o cddigo abaixo d uilido,
int x = 3;
for (x = 1_2; x < 20, x++l { }
int b = 3;
for (int a = I; b != 1; System.out.println("iterate") ) {
b=b-a;
)
PREI'ARAqAOPARAOE)(AME
Maitat perguntas do nouo exame (5) apruentam 'A nnpikgZofalhari" e 'Una excegdo oconeri ilo tenpl de execapho" c0m0 pzssiaeis
respostar. Isso o tomanl na* difcil porque uocd ndo podeni simplesmente analisar o comportamento do aldrgo. Pineiro uocd terd que se
certifcar se o aidigo ndo uti uiolando alguma regmfundamenta/ que leaani a //m elro d0 corQilador, en segaida teri qaepmcurarpossiueis
excegdes, e fi dEois que tiuer satisfeito uses doit requititos podenl se aprofundar na hgica e fto flilxr do aidigo da pergunta.
int [] a = {1,2,3,4};
for(int x = 0; x < a.length; x++) / / Ioop for b5sico
System. out.print (a Ix] ) ;
for(int n : a) / / J-oop for aprimorado
198 Copftulo 5: Controle de fluxo, exceg6es e ossertivos
System. out.print (n) ;
L234L234
Mais formalmente, vamos descrever o for aprimorado da seguinte forma:
fnrldanl araaVa . avnraq<Anl
Usando as definig6es acima, vejamos algumas declarag6es vfidas e inv6lidas de for aprimorados:
r-nt x;
long x2;
Long [] ta = {4L, 5L, 6L};
]ong Jl 1a = {7L, BL, 9L};
int [][] twoDee = {{1,2,3}, {4,5,6}, {7,8,9}};
String [] sNums - {"one", "two", "three"};
enimal [] animals - {new DosO, new CatO};
/ / Aar]: r: nAac I f nr
' v6lidas
fnrllnnn rr . Ia \ . / / faz loop atrav6s de um array de longs
um
Farllann ln T.a\ .
// fazendo autoboxing dos objetos Long
// para dentro de longs
for(int[]n:twoDee)t // faz um loop atrav6s do array de arrays
for(inL n2 : twoDee[2]) i // faz um loop atrav6s do 3e. sub-array
for(Strings: sNums) ; // faz um loop atrav6s do array de Strings
for(Objecto:sNums); // define uma refer€ncia Object para
// cada String
for(Animal a : animal-s) i // deflne uma refer6ncia Animal para
// cada elemento
/ / declarae6es "for" INVALIDAS
for(x2 : la) ; / / x2 j6 foi declarada
for(int x2 : twoDee) ; /,/ impossivel colocar um array dentro de um int
fnrlinf v? . la\ // impossivel colocar um longr dentro de um int.
for(Dogd: animals) ; / / vocd poderia receber um gato!
O loop for aprimorado assume que, nio havendo uma saida inesperada do loop, voc6 sempre desejari que o loop seja
feito atrav6s de todos os elementos do array. As discuss6es seguintes sobre break e continue aplicam-se tanto ao loop for
b6sico quanto ao aprimorado.
. _A
instruglo brea.k fari com que o programa encerre a execuglo do loop atual e inicie o processamento na linha de
c6digo posterior ao bloco.
A ingtrugio continue far6 com que s omente a iteragioatual do loop s elaencerradaeque a pr6xima iteragio do
mesmo loop seja iniciada se a condiglo deste for atendida. Quando usar uma instrugio coniinuJem um loop ior, vocA
teri que considerar seus efeitos na iteragio do loop. Examine o c6digo a seguir, que ser6 explicado logo depoil.
for (int i = 0; i < 10; i++) {
System. out.println ( "Inside loop" ) ;
-nnrrnrta.
]
A pergunta 6: Esse 6 um loop infinito? A reposta 6 nio. Quando a instrugio continue for atingida, a expressio de
itera$o ainda ser6 executada! Ela ser6 executada exatamente como se a itera$o anral terminasse "de maneira naturd".
Portanto, no exemplo anteri or, ainda aumentanio seu valor antes da condigio (i < 10) ser verifica& novamente. Geralmente, a
instrugio continue 6 usada dentro de um teste i f como vemos abaixo:
for (int i = 0; i < 10; i++) {
System.out.printfn ( "fnside 1oop" ) ;
if (foo.doStuff O == 5) {
continue;
)
/ / mais c6digo do 1oop, que ndo ser6 executado quando o t.este if acima
/ / for verdadeiro
break;
]
// pr6xi-ma linha do c6digo
No exemplo anterior, a instrugXo break nio foi rotulada. A seguir temos o exemplo de uma instrugio continue nio
ronrlada:
while (!EOF) {
/ / 16 vm canpo de um arquivo
if f Fh6ra r^7=c : nr^hl 6m\ I
Nesse exemplo, os campos de um arquivo esteo sendo lidos um de cada vez. Quando um erro for encontrado, o
programa ffr.."{ p"r" o ."*po r.g.tittt. do. arquivo e usari a instrugXo continue
para voltar ao loop (t.."1o
estiver no ?inal do arquivo) . .o.tti-ttrr"r a leituri dos outros campos. Se o comando break fosse usado,.o c6digo
encerraria a leitura do arquivo quando um erro fosse encontrado e passaria para a pr6xima linha de c6digo. A
instrugio conti-nue 6 ima maneira de dizer: "Essa iteragio espeLifica do loop precisa ser encerrada, mas nXo o
loop inteiro. Apenas nio quero que a execugio do resto do c6digo dessa iteragXo seja terminada' portanto,
processe a expressio da iteraglo i, em seguida, reinicie no teste nXo se preocupando com o que est6 abaixo da
instrugio continue".
Instrug6es rotuladas
Embora muitas instrug5es emJava possam ser rotuladas, 6 mais comum usar r6tulos com instrug5es loop tais como f or
e whi 1e, em conjunto com instrug6es break e continue. Uma instruEio de r6tulo deve ser colocada logo antes da
instrugio sendo rotulada, e consiste de um identificador vllido que termina com dois pontos 0.
Voc6 precisa entender a diferenga entre instrug6es break e continue rotuladas e nio-rotuladas. As rotuladas serio
,r...ss6rias somente nas situag6es em que voc6 tiver um loop aninhado e precisar indicar qual quer encerrar ou a panir de
qual deseja continuar a pr6xima iteragio. Uma instrugio break sair6 do loop rotulado e nio do loop atual, se a palavra-
chave break for combinada com um r6tulo. IJm exemplo do formato de um r6tulo se encontra no c6digo abaixo:
foo:
for (int x = 3; x < 20; x++) {
while(y > 7) {
Y-- i
O r6tulo precisa estar de acordo com as regras de nomes de variiveis vilidos, e deve estar em conformidade com a
convengXo de nomeagloJava. A sintaxe para o uso de um nome como r6tulo junto com uma instrugio break consiste na
palavra-chave break seguida do nome do r6tulo e de um ponto e virgula. Abaixo podemos ver um exemplo mais
completo do uso de uma instrugio break rotulada:
boolean i-sTrue = true;
outer:
for(int 1=6; i<5; i++) {
while (isTrue) {
System. out .println ( "Hel1o" ) ;
break outer;
j / / fim do loop for interno
Swst-em-out
eJsLerrr.vuu.y-rrrurrl\ nri nfln(\'Orrt-er
vsevr
"l
+vvy.nnn t'\: // n5o seri exibido
j/ fin do loop for externo
/
System. out.println ( "Good-Bye" ) ;
A execugio &sse c6digo produzir6
Hel1o
Good-bye
Nesse exemplo a palavra Hello ser6 exibida uma vez. Em seguida, a instruglo break rotulada ser6 executada e o
fluxo sair6 do loop rotulado com outer. Entio, a pr6xima linha de c6digo exibiri cood-bye. Vejamos o que
acontecera se a instrugio continue for usada em vez de break. O c6digo do exemplo a seguir 6 similar ao anterior,
exceto pela substituigio de break por continue:
outer:
for (int 1=6; i<5; i++; t
for (int j=0; j<5; j++) {
System. out.println ( "He11o" ) ;
continue outer;
JAVA 5 20]
j / fim do loop for interno
/
System. out.println (..outer,, ) ; // Nunca 6 exibido
]
System. out..println (..Good-Bye,, ) ;
A execugio desse c6digo produzir|:
Hello
Hel1o
HeIfo
He11o
Helfo
cood-Bye
Nesse exemplo, a palavra Hel1o ser6 exibida cinco vezes. Depois que a instrugio continue for executada, o
fluxo continuare com a pr6xima iteragio do loop identificado pelo r6tulo. Para concluir, quando a condigio do
loop externo fior avaliada como fal-se, o loop ser6 encerrado e a palavra Good-Bye ser6-exibida.
Exercfcio 5-2
As iutrugdes continue e break rotuladas deuem ficar dentro do loop que tiaer o mesmo rotulo; cato contririo, o aldigo ndo seni
combilado.
At . .ctc
\JoleTrvo poro o centttcocoo
Manipulando exces6es (Obietivos 2.4 e 2.5 do exame)
2.4 Escreuer aidigos quefagan uso @ropiado de excegdes e de clduvlat de nanipulapdo de exngdu (try, nhb,fnalfi) e declarar mdtodos
sabscrilos oa nio, os qmis /ancem exrcSdes.
2.5 Rcconbecer o efeito de ama exnpdo lanpada em um ponto etpufrn dofragwento de an cddigo. E bom ressahar que a excegdo pode ser de
tenpo de exuugdo, uerifcada oil um etro.
Um velho axioma relacionado ao desenvolvimento de softwares diz que 80 por cento do trabalho sio usados em 20 por
cento do temp_ o. Os 80 por cento se referem ao esforgo necessirio para identificar e manipular erros. Em muitas linguagens,
escrever o c6digo-de programas que procure e lide com erros 6 mon6tono e transforma o c6digo-fonte do aplicativo em um
emaranhado conftrso. Ainda assim, a detecgio e manipulagio de erros podem ser os ingredientes mais importantes de
qualquer aplicativo robusto. A linguagemJava fornece aos desenvolvedores um mecanismo sofisticado para manipulagio de
erros que produz c6digos de manipulagio eficientes e organizados: a manipulagdo de excegdes.
A manipulagio de exceg6es permite que os desenvolvedores detectem erros facilmente sem escreverum c6digo especid para
testar valores retornados. Melhorainda, nos permiJe manter um c6digo de manipulagio de exceg6es nitidamente separado
do c6digo que gerariaexcegio. A16m disso, permite que o mesmo c6&go de manipulagio de exceg6es lide com as diferentes
exceg6es possiveis.
O exame tem tr€s objetivos relativos ao tratamento de exce96es. Abordaremos os dois primeiros nesta segXo e, na pr6xima
segio, abordaremos os aspectos do tratamento de exceg6es que foram introduzidos no exameJava 5.
202 Copitulo 5: Controle de fluxo, exceg6es e ossertivos
A manipulagio de exceg6es funciona pela ransferd ncia da execugio d. yT programa para um manipulador de.
exceg5ei
-o apropriado quando uma excegio ocorrer. Por exemplo, se voc6 chamar um m6todo-que abra um ar.quivo,
*"t nio puier ser aberto, a execugXo desse m6todo seri encerrada e o c6digo que foi escrito para lidar
"rqrrirro
.orn .ss"iitnagio seri processado. Portanto, precisamos de uma maneira para informar ) JVM que c6digo
executar quando determinada excegio ocotrei. Para f.azer isso, usamos as palavras-chaye_ try- . ge.t"l. A palavra
try 6,tsid" pat" indicar um bloco de c6digo no qual possam ocorrer exceg6es. Esse bloco de c6digo 6 chamado
de regido protegida (que na verdade significa: "Aqui enlrari um c6digo arriscado"). IJma ou mais cliusulas catch
assoJi"rio uma excegio especifica (ou classe di exceg6es - veremos mais sobre isso posteriormente) a um bloco
de c6digo que a manipularZ. Abaixo podemos ver o formato em pseudoc6digo:
1. try {
2. // F-ssa 6 a primeira linha da "regido protegida"
3. / / q)e 6 control-ada pela palavra-chave try.
4. // Insira um c6digo agui que possa causar algum tipo de exceqao.
5. // Podemos ter muit.as linhas de c6digo aqui ou apenas uma.
6. ]
'7 aalrh lMrrE'i r<l- E'v.ahf
rrves.l i {
\rrJr ^h\
8. // Inslra um c6digo aqui que manipule essa exceq6o.
9. / / Essa 6 a linha seguinte do manipulador de exceeao.
10. / / F,ssa 6 a riltima linha do manipulador de exceqao'
1-1. ]
1) c:l-ctr aM\rqa.^ndEynonfi
\.rJ vvvv^.gg nn\ {
A execu$o ini ciari naIinha2. Se o programa for processado at6 a linha 5 sem nenhuma excegio lanqada, a execugio seri
transferida para a linha 15 e continuar6 dai em diante. No entanto, se em algum momento entre a linha 2 e 5 (o bloco try)
uma excegao do tipo MyFirstException for lanQada, a execugXo ser6 imediatamente transferida para a linha 7. Em seguida, f
linhas 8 a 10 serio processadas para que todo o bloco catch seja executado e depois o processamento passar6 para a linha
15 e dari prosseguimento.
Observe que se uma excegao ocorresse, digamos, na linha 3 do bloco try, as outras linhas desse bloco (4 e 5) nunca seriam
executadas. Uma vez que o controle do flrxo salar para o bloco catch, ele nXo retornar6 para concluir o restante do bloco
try. No entanto, isso dexatamenre o que queremos. Imagine se seu c6digo fosse parecido &*
ttt. pt.ndoc6digo:
try {
.anl- rrraAr-r i \roNaRedg
I ei aArmr i \/nePreenchaTabela
)
catch (NdoPodeCapturarArquivoNaRede ) {
rrseArmrirrnT.ocaf
)
O pseudoc6digo anterior demonstra como geralmente as excegSes sio usadas. O c6digo que depende de uma operaEXo
arriscada (como o preenchimento de umi tabela com dados de arquivo depende da captura do arquivo na rede) foi
JAVA 5 203
agruPado em um bloco try de uma maneira que se, digamos, a primeira operagio falhar, vocA nio dari
prosseguimento na,tentativa de executar outro c6digo que com cenezatamb6m falhar|. No exemplo do
pseudoc6digo, voc6 nio conseguir6 ler o arquivo se nio puderprimeiro capturiJo narede.
Um dos beneficios de us.1r a manipulagio de exceE6es 6 que o c6digo de manipulagio de alguma excegio especifica
que Poss, ocorrer !a regilo controlada precisa
ser escrito somente vmavez. Voltando
"o
rroiso c6digo anterior, pode
haver tr6s locais diferentes-no bloco Lry
capazes de gerar uma exceglo MyFirstException, mas o.rJ. qr.r q.t. .1"
ocorra seri manipulada pelo mesmo bloco catch
(da linha Z). Discutiremos ourros-beneficios da manipulaglo de
exceg6es peno do fim deste capitulo.
Usando finally
Os blocos t.ry e catch fornecem um 6timo mecanismo de captura e manipulagi,o de exceg6es, mas ainda ficamos com
o problema de como nos organizar depois. J6 que a execugio 6 transferida pari fora do bloco try
assim que uma excegio 6
langada, nio podemos inserir nosso c6digo de limpeza no final desse blocoi esperar que seja executado se uma excegio
ocorrer. lJma id6ia quase tio inadequada quanto essa seria inserir o c6digo de limpezi nos blocos catch.
Os manipuladores de excegio representam um local inapropriado para a limpeza depois da execuglo do c6digo do bloco
try porque cada manipulador precisari de sua pr6pria c6pia do c6digo de limpeza. Se, por exemplo, voc6 alocasse um
socket de rede ou abrisse um arquivo em um algum local & regiXo protegida, cada manipulador & excegXo teria que fechar o
arquivo ou liberar o socket. Isso tornaria f6cil esquecer a inclusio da limpeza e levaria a um c6digo redundante. Para resolver
esse problema, a linguagemJava oferece o bloco f ina11y.
4: catch(MyFirstException) {
q. // Danha:mli tAAi^^ para manipular este erro.
^
7: catch(MySecondException) {
B: // Ponha aqui o c6digo para manipular este erro.
q. 1
10: finally {
11 : // Ponha aqui o c6digo para liberar qualquer recurso que
!2: / / |'enhamos a]ocado na c15.usu1a trv.
1?. 1
L4:
1-5: / / l.,tais c6digo aqui
"a primeira linha do bloco try, a linha 2. Se nio houver exceg6es langadas no bloco try, a
Como antes,.a execuglo 6 iniciada
execugio ser6transferida para a linha 11, aprimeira linha do bloco f inal1y. Por outro lado, se uma excegio
MySecondException for langada enquanto o c6digo do bloco try estiver sendo executado, o processamento ser6 transferido
para a primeira linha do manipulador dessa excegio, a linha 8 da cldusula catch. Depois que o c6digo inteiro da cliusula
cqtc|,r for executado, o programa passari para a linha 11, a primeira linha da cl6usula f inal1y. Repita comigo: a
cl6usula f ina11y rcmpre seni exuutada. Ok, teremos de refinir isso um pouco, mas, por agora, comect a m emorizar aidl;ia
dequefinally sempreseriexecutada.seaexcegioforlangada,a&iiukfinally seriexecutada.Seaexcegionaofor
langada, a clausala f inal1y tamb6m ser6 executada. Posteriormente examinaremos alguns cen6rios nos quais f ina11y
pode nio ser executada ou concluida.
kmbrese de que as cl6usulas f ina11y nlo sio obrigat6rias. Se voc6 nio quiser escrwer uma, seu c6digo ser6 compilado e
executado da mesma maneira. Na verdade, se vocA nio tiver recursos a liberar depois que seu bloco try
for concluido,
provavelmente nio precisari& umacl6usula f inally. A16m disso, ji que o compilador nXo exige nem mesmo cl6usulas
catch, em algumas situag5es voc6 se deparard com c6digos com um bloco try
imediatamente seguido porum bloco
f inal ly. Um c6digo dese tipo 6 6til quando a excegio 6 retornada para o metodo chamador, como explicaremos na
pr6xima seglo. O uso de um bloco f inalIy
permitiri que o c6digo de limpeza seja executado at6 mesmo quando
nXo houver uma cl6usula catch.
204 Copitulo 5: Conlrole de fluxo, exceg6es e ossertivos
O c6digo vilido aseguir demonstra um bloco try com f inally, por6m, sem catch:
trY t
/ / faz aTgo
) finally {
// faz a limPeza
]
O c6digo v6lido a seguir demonstra os blocos try, catch e f inally:
try {
/ faz al-go
/
) catch (SomeException ex) t
// trata aexceqao
) finally {
// faz a limneza
)
O c6digo inudlido asegir demonstra um bloco try, sem catch ou f ina11y:
LrY {
/ / faz algo
]
/ 5 preciso um catch ou finally aqui
/
System.out.println("out of try block") ;
O c6dtgo inu,itidna seguir demonstra um bloco catch inserido erroneamente:
trY {
/ / faz a1-go
)
Nda i cliasula try sem uma cldusula catch oa f inaLly. Uma cldusula Lry indiuidaal resaltari
considerado udlida asar uma
em um etro do conpilador. puaQuer cliusula catch deue uir inediatamente @ds o bloco try. pualquer cl,lusula f inall-y deae uir
inediatanente apis a riltina cliuwla catch (ou deue seguir inedntamente o bkco Lry se ndo boauer an catch/. E unlido omitir a
cldusula catch ow a cllaula f inall-v, mas ndo as daas.
oBSERVAQ6ESpeneOE)(AME
V'oci ndo pode inseir nenham ctidigo entre os blocos try e catch (oa try e f inal-l-y). O cddigo a seguir nio seri
conpilado:
trY {
/ / faz al-go
]
System.out.print("be1ow the try") ; // Tnv6lidot
catch(Exception ex) { }
lr
rtde ser representada em ordem inversa (embora tamb6m possa ser visualizada na ordem correta). Como voc6
"-;il"
pode ver, o riltimo m6todo chamado est6 no inicio da pilha, enquanto o primeiro m6todo que fez uma chamada est6 no
final. O primeiro m6todo do rastreamento de pilha serla o que voc6 estivesse executando atualmente. Se nos movAssemos
para baixo na pilha, passariamos do m6todo atual para o m6todo chamado anteriormenre. A Figura 5-1. ilustra uma
maneira de representar como a pilha de chamadas funciona emJava.
Agora examinaremos o que acontece )s exceg6es transferidas. Imagine um pr6dio, digamos, de cinco andares tendo em cada
andar uma varanda ou sacada. Agora imagine que em cada varanda, uma pessoa est6 vestindo uma luva de baseball. As
exceg6es sio como bolas passadas de uma pessoa a outra, comegando do riltimo andar. Primeiro a excegio 6 langada do
inicio da pilha (em outras palavras, pela pessoa do riltimo andar) e se nio for capturada pela mesma pessoa que a langou (a
pessoa do riltimo andar), elacirS.paraom6todo anterior da pilha de chamadas, que seri a pessoa qui estivei um andar
abaixo. Se nio for capturada ai, pela pessoa do andar de baixo, a exce gdo/bola carhnovamente para o m6todo anterior a esse
(a pessoa do pr6ximo andar de baixo) e assim por diante at6 que seja capturada ou alcance o final da pilha de chamadas. hso
6 conhecido coma prnpdga$o de excegdo.
Se a exceglo alcangar o final da pilha de chamadas, seri como chegar ao fim de uma longa descida; a bola arrebentar6 assim
como seu programa. lJma exceEio que nio for capturadafaricom que seu aplicativo pare de ser executado. A descriglo (se
houver uma disponivel) da excegio seri exibida e a pilha de chamadas "eliminada". hso o ajudari a depurar seu aplicativo
ao lhe informar que excegio foi langada, de que m6todo e qual era o formato da pilha no momento.
OBSERVAQ6ESpeneoE)(AME
Vocd pode langar ama excegio para outrot mitodos da pilba. Mas, e quando cbegar ao ruitodo main ( ) no fnal? Tanbim podeni langar a
excegdofora duse mitodo. Isso resltani em uma interrupgdo da ndq*ina uirtual Jaua [1./M, taua Virtaal Machine) e o rastreamento da
pilba seni exibido na vida. O aidtgo a segair /anga ama excepio,
class TestEx {
public static void main (String [] args) t
doStuff ();
]
206 Copftulo 5: Controle de fluxo, exceg6es e ossertivos
)
qrc exibinl o rartreaneflto da Pilha,
Sjava TestEx
Exception in thread \\main" java. lang.AriLhmeticException:
by zero
at TestEx. doMoreStuff (TestEx. java : 10)
at TestEx.doStuf f (TestEx. java : 7 )
at TestEx.main (TestEx. java : 3 )
Exercfcio 5-3
I Em reverse, verifique se a string tem um comprimento igual a0 usando o m6todo String . length ( ) . Se o
comprimento for igual a 0, ele langar6 uma nova excegXo.
I Agora incluiremos o c6digo para inverter a ordem da string. J6 que ess e nlo 6 o t6pico principal deste capitulo,
forneceremos o c6digo de inversio, mas sinta-se lvontade parate$6lo como quiser.
String reverseStr = "";
for ( int i=s. length ( ) -1; i>=0; --i ) {
reverseStr += s. charAt (i) ;
)
return reverseStr,'
! Agora, no m6todo main ( ) tentaremos chamar esse m6todo e manipular qualquer excegio em potencial. Al6m disso,
incluiremos uma instruglo f inal 1y que nos informar6 que a execugio foi concluida.
Definindo excec6es J
Temos discutido as exceg5es como um conceito. Sabemos que elas sio langadas quando um problema de algum tipo ocorre
e que efeito terio sobre o flrxo de seu programa. Nesta seEio desenvolveremos os conceitos um pouco mais e usaremos as
exceg6es em um c6digoJava frrncional. Anteriormente dissemos que a exceglo 6 uma ocorr6ncia que altera o fluxo normal
do programa. Mas, ji que estamos falando deJava, tudo que nlo for um tipo primitivo deve ser... Um objeto. As exceg6es
nSosio,bem,vmaexcepioaessaregra.Todaexcegio6ainstAnciadeumaclassequepossuiaclasseException emsua
hierarquia de heranga. Em outras palavras, as exceg6es sio sempre alguma subclasse de j ava . lang . Exception.
Quando uma excegXo 6langada, o objeto de um subtipo Exception especifico 6 instanciado e inserido no manipulador
de exceg6es como um argumento para a cliusula catch. Uma cllusula catch real tem este formato:
try {
/ / a1 ortm e6di qo acrui
)
catch (ArraylndexoutofBoundsException e) {
e . printStackTrace ();
)
JAVA 5 207
Nesse exemplo, e 6 a instAncia de uma classe charnada resumidamente de ArrayrndexoutofBoundsException.
Como ocorreria com qualquer outro objao, vod pode chamar seus metodos.
Hierarquia de exces6es
Todas as classes de exceE6es sio subtiFos da clase Exception. Essa classe 6 derivada da classe Throwable (que 6
derivada da classe obj ect). A figura 5-2 mostra a hierarquia das classes de exceg6es.
Como voc6 pode ver, hiduassubclasses que derivam de Throwable: Exception e Error. As classes que derivam
de Error rePresentam situag6es incomuns que nio sio causadas por errot tro prog.ama e indicam coisas que nio
ocorreriam normalmente durante sua execuglo, como a JVM Ticar ..- tra mem6ria. Geralmente, os
"rp"gJ manipul6-los. Mesmo se seu c6digo
aplicativosrrio conseguem se recuperar de-um erro, ponanto, nio precisarnos
nio os manipular (e geralmente eles nlo o fazem), ele ainda seri compilado sem probl.-.t. Embora
freqiientemente considerados como condig6es excepcionais, o, .rror^t..nicamente nlo sio exceg6es porque nio
derivam da classe Exception.
No Ambito geral, uma excegio representa algo que ocorre nio como o resultado de um erro de programagio, mas, em vez
disso, porque algum recurso nio-isti disponivel ou por alguma outra condigio requerida para .".ltgao i"rreta nio esrar
"
Presente. Por exemplo, se seu aplicativo tivesse que ie com.tnica. com outro aplicativo ou computador que nio estiver
respondendo,.essa 6 uma excegio que nio:er6 causada por urn erro. A Figura S-Z tamb6m mostra um iubtipo de Excep-
tion chamado RuntimeException. Essas exceg6ei sio um caso esp.iial potqne, ls vezes, indicam realm.rrt.
"rror-
no Programa. Elas tamb6m podem representar condig5es excepcionais r-aras e dificeis de manipular. As exceg6es de tempo
de execugio serio discutidas mais detalhadamente neste capitufo.
A linguagemJava fornece muitas classes de exceg6es, a maioria delas tendo nomes bem descritivos. Hl duas maneiras de
obter informag6es sobre uma excegio. A primeira 6 sobre o tipo_da propril exceglo. A outra 6 sobre as informag6es que voc6
pode obter do objeto de.exceglo. A classe Throwable (no topo da 6rvoie de heranga de exceg6es) fornece aos seus
descendentes alguns m6todos que slo riteis em manipuladores de exceg6es. Um deles 6 piintstacktrace ( ) .
Como j6 era espelado, se voc6 chamar o m6todo printstackTrace ( ) de um objeto de excegio, conforme fizemos
no exemplo anterior, ser6 exibido o rastreamento de pilha do local onde a excegXo ocorizu
Vimos que uma pilha de chamadas 6 criada em ordem inversa com o rlltimo m6todo chamado inserido no inicio. Voc6 veri
que o m6todo printstackTrace ( ) exibir6 o m6todo inserido mais recentemente primeiro, e dar6 prosseguimento,
exibindo o nome de cada m6todo ao percorrer a pilha de chamadas (isso 6 ch arnado de dr:ronknento fupiiba) piri. do
inido. "
oBSERVAQ6ESpeneOE)(AME
No exam4 nio seni necessdrio conhecer nenham dot ndtodos contidot nas c/asvs Throwabl e , inc/uindo Except i on e Error.
Senl esperado que uocd saiba qae ot tipos Exception, Error, RuntimeException e Throwabl e podem ser langados
cLm 0 trr7 da palatra-chaue throw e que podem ur c@turados (enbora raramente sela c@turado algo que ndo s/a un snbtipo Excep-
tion).
e . printStackTrace ( );
)
AOTRABALHO
Resista i tentagdo de esreaer somente um rzanipa/ador que captilre todas as excepdes encontradas como o descrito abaixo:
trv {
/ / o c6digo
)
catch (Exception e) {
e . printstackTrace ();
Esse aidtgo uai c@turar todas at excegdu geradas. E claro que nenbum manipu/ador de excegdo pode nanipular indiuidualmente de maneira
@mpiada cada exnpdo e uma pngmnagdo feita dessa maneira prejadicani o objetiuo do pnyta Ot manipuladoru de excepdo que ca?tararem
naitos enos de uma sri ueVpmuauelmenn reda{rdo a confabilidad.e de rea pmgrama Porque d possiuel que c@turem uma excegdo que ndo saibam
como tratar.
Correspond6ncia de exceg6es
Sevoc6 tiver uma hierarquia de exceg6es composta de uma superclasse e virios subtipos, e estiver interessado em manipular
um dos subtipos de maneira especial, manipulando todos os outros juntos, ter6 que escrever somente duas cl6usulas catch.
Quando uma excegio for langada, Java tentar6 encontrar (procurando nas cl6usulas catch disponiveis, de cima para
baixo) uma cliusula catch para o tipo da exceglo. Se nlo encontrar, ir6 procurar um manipulador para um supertipo da
excegio.Senzoencontrarumacliusulacatch quecorrespon&aosupertipodaexcegio,entAo,aexcegioser6propagada
para baixo na pilha de chamadas. Esse processo 6 chamado de coresponddncia de excegdes.
Examinemosumexemplo:
1: import java.io.*;
2: public class ReadData {
3: public static void main(String arqs[] ) {
4: try {
5: RandornAccessFile raf =
6: new RandomAccessFile ( "myfile. txt", "a"; t
10: catch(FileNotFoundException e) {
11 : System. err. println ( ',Fi1e not f ound,, ) ;
t2: System.err.println(e.getMessageO);
13: e.printStackTraceO;
t4: )
15: catch(fOException e) {
1-6: System.err.println("fO Error,');
!7 : Syst.em. err.println (e. toString ( ) ) ;
18 : e. printstackTrace O ,.
1q. l
20: )
21 : j
Esse programacurto_tenta abrir um arquivo eler alguns dados nele. A abenura e leitura de arquivos podem gerar muitas
exceg6es, a maioria delas sendo algum tipo deroException. Suponha que nesse program; estiv3ssemos'inreressados
^Caso
em sabersomente se a excegao hngada foi rileNotFoundnxceition. contr6rL, nio nos importar6saber qual
foi exatamente o problema.
FileNotFoundException 6 uma subclasse de roException. Porranto, poderiamos manipuli-la na cl6usula
catch. cuja finalidade 6 capturar todos ossubtipos de roExcep_tion, mas ter?amos que tesrar Jexcegio p"ra
determinarse 6 r'ltemotFbundException. Emvezdisso, codificamos um maniputdorde exceg6es eqpecialpara
Fi leNotFoundException e um manipulador separado para todos os outros subtipos de toException.
Seessec6digogerarumaexcegioFilelJotFoundException,elaserimanipuladapelacliusulacatch quecomega
nalinha 10.Se geraroutra excegeo roException-talvezEoFException, que 6 uma subclasse de loException-
elaser6manipuladapelacl6uzulacatch quecomeganalinha15.Seoutraexcegioforgerada,comoalgumtipode-excegio
de tempo de execugio, nenhuma das cl6usulas catch ser6 executa&, . .*..glo ,. ri'propagadap".""b"i*o n" pilha de
chamadas. "
try {
/ / faz operag6es de E/S arriscadas
) catch (IOException e) t
/ / traLa loExceptions qerais
) catch (Fil-eNotFoundException ex) {
/ / Lrata apenas FileNotFoundException
)
Sepensarmos nas pessoas com luvas de baseball (da segio "Propagando Exceg6es Nio-Capturadas'), suponha que as luvas
-
mais abrangentes sejam as mais largas e, portanto, possam caprurar muitos tipos diferent.i de bol"s.'Uma luva
roException 6 grande e flexivel o bastante para capturar qualquer tipo di roException. Assim, se a pessoa do
quinto andar (digamos, Fred) tiver uma grande luva lOException, nio poder6 evitar a caprura de uma bola
FileNotFoundException com ela. E se o sujeito (digamos,Jimmy) do segundo andarestiverusandoumaluva
Fi leNotFoundException, essa bola nunca chegari a ele, ji que sempre ser| aparada por Fred, no quinto
andar, que estar6 de guarda com sua luva grande o bastante para capturar todas asixceg6is roExcepCion.
Portanto, o que voc6 far| com exceE6es que sejam irmXs na hierarquia da classe? Se uma classe Exception nio
for o subtipo ou supeftipo da outra, enteo, a ordem na qual as cl6uiulas catch serio inseridas n1o imponar{.
2l 0 Copitulo 5: Controle de fluxo, exceg6es e ossertivos
priferir nio manipular a excegio e, em vez disso, apenas declarA-la, como se fosse rz m6todo que realmente tivesse langado a
ixcegio. Se vocA declarar a excegio que seu m6todo capturari de outro m6todo e nlo fornecer um bloco try/catch para
ele, entlo, o m6todo propagariaexcegio devoltapara o m6todo que o chamou e elasericaptwradaai.oucontinuarS'aser
transferida atrav6s do flrxo, para ser manipulada por um m6todo mais abaixo na pilha.
Qualquer m6todo que pude r kngarwaexcegio (a menos que ela seja uma subclasse de RuntimeExcepLion) deue
otransferindo'e deixando a
declar-ila. Isso inclui os m6todos que nio estiverem langando-a diretamente, mas que estiverem
excegXo passar para o pr6ximo m6todo da pilha. Quando voc6 "passar" uma excegio, ser6 como se a tivesse langado. As
subclasses de runtimeexception nXoistXo incluidas ai, portanto, o compilador nio verificari se voc6 as declarou.
Por6m todas as exceg6es que nio pertencerem a RuntimeException serXo consideradas "verificadas", porque o
compilador far6 uma checagem parater certez.ade que voc6 sabe que "algo inadequado pode acontecer aqui".
Lembre-se do seguinte:
Todo mdtodo deae ou tratar todat as excepdu ueificadag fomecendl ama cl,iusula catch, oa entdo listar cada exagdo uerifcada
que ndo tiuer recebido tratamento c0m0 tlma exegdo langada.
Essa regra 6 conhecida como o requisito "tratar ou declarar'deJava (is vezes chamado tamb6m de "captvrar oudeclarar').
void doStuff O i
doMore ( ) ;
)
void doMoreO {
throw new foException ( ) ;
]
Primeiro, o mdtodo doMore ( ) langa uma excepdo uerifcada, mas ndo a dulara! Ponim, suponha qae o mdtodo doMore ( )
Novamente, algumas exceg6es estio dispensadas dessa regra. Um objeto do tipo RuntimeException pode ser
langldo m6todo sem ser especificado como parte da interface priblica do metodo (e um manipulador nlo
{e Walquer
precisari estar presente). E mesmo se um m6todo declarar realmente uma excegio RuntimeException, o
m6todo que o chamar nio ser6 obrigado a manipul6-la ou declar6-la. As exceg6es RuntimeException, Error e
todos os seus subtipos sio exceg6es ndo uerifcadas, e as excegdes ndo ueifcadas ndo precisam nr especifcadas ou nanipaladas.
Aqui estl um exemplo:
import java.io.*;
class Test {
JAVA 5 2I I
public int myMethodl ( ) throws EoFException {
return myMethod2 O ;
)
public int myMethod2 ( ) throws EOFException {
// Ponha aqui algum c6digo para fazer o lanqamento da exceqdo
return 1;
]
)
As exceg6es de tempo de execugio sio conhecidas como excegdu ndo uerifcadas. Todas as outras exceg6es, ou seia, todas
aquelas que nio sio derivadas de j ava. 1ang. RuntimeException, sio excegdu ueifcadas.A exceglo verificadaterS,
que ser capturada em algum local de seu c6digo. Se voc6 chamar um m6todo que lance uma excegio verificada, mas nio
capturar elsa e*cegio em algum local, seu c6digo nio seri compilado. E por isso que elas sio chamadas de exceg6es
veri{icadas; o compilador verifica para se cenificar se elas foram declaradas ou manipuladas. Virios m6todos das bibliotecas
Java 2 Standard Edition langam exceg6es verificadas, portanto, voc6 geralmente estari escrevendo manipuladores para rratar
de exceg6es geradas por m6todos que nlo escreveu.
Voc6 tamb6m pode langar uma exceglo, que j6 exista na API Java ou que tiver criado. Para criar sua pr6pria
excegio, simplesmente crie uma subclasse de Exception (ou uma subclasse a partir das subclasses de Excep-
tion) da maneira a seguir:
class MyException extends Exception { }
E sevocA langar a excegeo, o compiladorse certificar6 de que adeclare damaneira a seguir:
class TestEx {
void doStuff O {
)
O c6digo anteriorpreocupari o compilador:
TestEx.java:6: unreported exception MyException; must be caught or
declared to be thrown
l- hrar^r n6r^r M\rFv-anf i nn I \ .
oBSERVAQ6ESpeneOE)(AME
puando o objeto de um subtipo /a Exception for langado, ele teni que ser manipulado oa declarado. Esses objetos sio chamados de
excetl as que sio rubtipor /e RuntimeExceptiort, consideradas exupdes nio
excegdes uerifcadas e incluem todas as excegdes,
uerifcadat Estla preparado para identifcar mitodos que ndo sigan a regra da ruanipulagdo ou declaragdo, coml em
catch(MyException me) {
throw me,'
Vocd terd que uber que esse cfidigo ndo serd nmpilado. Se tentar corzpild-lo, obteni
RtparequesomeMethod( ) nioconseguenemtratarnemdeclararaexcepioquepodeserlangadopordoStuff O.
Voc6 teri que saber a Eror e exceg6es verificadas e nio verificadas. Objetos do tip o Error
diferenga entre um objeto
nXo sXo objetos Exception, embora representem condig6es excepcionais. Tanto Exception quanto Error
compaftilham uma superclasse em comum, Throwable, portanto, os dois objetos podem ser langados com o uso da
palavra-chave throw. Quando um objeto Etror, ou uma subclasse de Error , 67angado, nio 6 verificado. Nio 6
preciso capturar obietos ou subtipos de nrror. VocA tamb6m pode langar um objeto Error por sua pr6pria conta (embora
talvez nunca queira fazer isso) e capturar um objeto desse tipo, mas, provavelmente, nio irl fazA-lo. O que, por exemplo,
voc6 faria se recebesse um objeto ouLofMemoryError? Nio poder6 informar ao coletor de lixo que inicie a execugio;
pode apostar que a JVM lutou desesperadamente para se safar (e consumiu toda a mem6ria que p6de) no
momento em que voc6 recebeu o erro. Em outras palavras, nio espere que a essa altura a JVM diga: "Executar o
coletor de lixo? Oh, muito obrigado por me solicitar isso. Nunca teria me ocorrido. Certo, o farei
imediatamente...". Ou melhor, o que faria se surgisse um virtualMachineError? Seu programa ji estaria
danificado no momento em que voc6 capturasse o erro. Portanto, nXo hi realmente por que capturar uma dessas
gracinhas. Apenas lembre-se de que voc6 pode faz|-lot O c6digo abaixo seri compilado adequadamente:
class TestEx {
publLc static void main (String [] args) t
}r:AMaFhnrl 1 \
)
static void badMethodO { / / Ndo 6 necess6ri-o declarar um erro
doStuff ()
)
static void doStuffO { // Ndo 6 necess5rio declarar um erro
try {
throw new Error ( );
)
catch (Error me) {
throw me; / / Capturamos, mas depois relanqamos
]
)
Se f6ssemos langar uma excegio verificada em vez de run erro, enteo, o m6todo doStuf f (
) teria que declarar a excegio.
Mas lembre: Ji que o objeto nrror
nio 6 um subtipo de Exception, nio ter6 que ser declarado. Voc6 est6livre para
declari-lo se quiser, mas o compilador simplesmente neo se impoftar6, de uma maneira ou de outra, quando ou como o
erro w6,7angado, ou ainda por quem.
JAVA 5 2I3
AO TRABALHO
Jd que a linguagen Jauapwsui excegdes uerifcadat, narnalmente diq+e qae elaforga ot dercnuoluedores a manipular erros. Sim, a linguagem
Jaua
nosforga a esmuer manipaladores para cada excegdo que possa oeornr dilrante a operapilo nomtal, mas 6 nossa responnbilidadcJaTer qot *
de excegdo realmente executem algo ilril. Conhecemos gerentet de rofware que n6o amditaran qaindo uiran am pigramador ^
f#f*"t
try {
callBadl"Iethod ( );
] catch (Exception ex) { }
Notou aQofaltando? Ndo onita a excepdo capturando-a sem manipuldJa realmente. Voc6 nem newo podeni informar qae a excegdo
lclrretl, Plrque nunca aerd o rastreamento da pi/ha.
try {
]
Noc6digoanterior,6evidentequeom&ododoSLuff ( ) podelangarumaexcegioverificada-nessecasoumaexcegio
IoException-portanto,ocompiladordir6:"Certo,6formid6velquevoc6tenhaumbloco Lry/caich ai,masnio
6o suficiente. Se voc6 quiser relangar a excegio loB<ception que capturou, teri que declariJa!".
Exercfcio 5-4
NXo faga com que main ( ) declare o m6todo, porque se main ( ) passar a excegXo, quem mais exar|lLpara
captur6Ja?
I Mesmo com a manip ulagilo de exceg6es sendo tXo iti7, ainda ficar| a cargo do desenvolvedor fazer uso
apropriado dela. A *"nipnl"gio de exceg6es tornarif6cil a organizagio de seu c6digo e a detecaio de
probi"-"r, mas os manipuladores de excigXo terio que ser escritos. VocA veri que.mesmo as situag6es mais
iomple"as-podem ser manipuladas e que poder6 torn"r seu c6digo reutiliz6vel, legivel e de ficil manutengio.
O tratamenro de exceg6es 6 outra 6rea que a equipe de criagio do exame decidiu expandir para o exame SCJP 5 . Esta seglo
discute os.aspectos dasexceg6es que foram adicionadas para e$a nova v€rsio. A intengXo do Objetivo 2.6 6 certificar que voc6
est6 familiarizado com alguns dol erros e exceg6es mars comuns que rra encontrar como programadorJava.
OBSERVAQ6TSpeneOF)(AME
As questdes desta sepio prouauelmente ser6o algo do tipo :'Eh aqui algun cddigo que acabou defaTer buteira, qaal excegdo ser,l langada?"
Ao longo de exame, as questdes apretenturAt algun aldigo e lhe pedird.o para deterrztinar se o aidigo uai rodar, ou se serd lanpada una excegdo.
Uma ueTque essas que$des sdo tdo comuns, entender saas caasas ,!fundamentalpara 0 sea sacesso.
Este 6 outro dos objetivos que estarlo por todo o exame ('uma excegio 6 langada em tempo de execugio" lhe diz alguma
coisa?), entXo cenifique.se de dedicarbastante atengio aestasegio.
exceg6es e erros:
I Exceg6es da JVM As exceg6es ou erros que sXo ou exclusivos ou mais logicamente langados pela JVM.
r Excegdes Program6ticas As exceg6es langadas explicitamente pelo aplicativo e ,/ ou pelos programadores da API.
Mas 6 claro que o compilador perceber6 o problema com esse pequeno programa, certo? Errado - voc6 vai ter de
se virar sozinho. O c6digo compilari sem problemas, mas aJVM langarS, uma NullPointerExcept.ion
quando tentar chamar o m6todo length ( ) .
Anteriormente neste capitulo, n6s discutimos a pilha de chamadas. Como voc6 deve se lembrar, usarnos a convengio de qye
main ( ) estaria no final da pilha, e de que, )-medida que main ( ) chamar outro m6todo, e este chamar um outro m6todo,
e assim por diante, a pilha ciesc. p"t" citna. E claro que a pilha residre na mem6ria, e mesmo que o seu SO lhe dA um
grgabFi de RAM p"r" o t.r, pro gt^*a,ainda 6 uma qu"nti" fittit". E possivel que a pilha fiqui tXo grande que o SO acabe
ficando sem espago par^ armazen6Ja. Quando isso acontece, voc6 recebe (suspense...) um
JAVA 5 2I5
stackoverf lowError. A maneira mais comum de isso acontecer 6 criando-se um m6todo recursivo. lJm
m6todo recursivo 6.aqrrele que.chama a si mesmo no corpo. Embora isso possa parecer esquisito, 6 rlma t6cnica
bastante comum e util para coisas como busca e classificagio de algoritmoi. D6 uma olhadi neste c6digo:
void go0 { / / recursividade causando problemas
900;
)
Como pode voc6 ver, se vocd algum dia cometer o erro de chamar o m6todo go ( ) , o seu proqrama cairi em um buraco
negro; gro ( ) chamando go ( ) chamando go ( ) at6 que, nio importa quanta mem6ria voc6 tlnha, voc6 receber6 um
Stackoverf lowError. Novamente, apenas a JVM sabe quando esse momento ocorreri, ea JVM ser6 a fonte
desse erro.
E claro que, como discutimos anteriormente, voc6tamb6m pode criar as suaspr6prias exceg6es especiais, personalizadas, e
lang6-las sempre que quiser. Essas exceg6es personalizadas tamb6m recaem n"."t.gori" dr "e*ceE6is langaias
Programaticarnente'.
ArraylndexOutOBoundsException
,A. l r ,.t.
(Jbletivo poro o centttcogoo
Voc6 sabe que nio devefazer suposiE6es, mas nio poderievitilas quando estiver escrevendo um c6digo. VocO as
coloca em comentirios:
if (x>2&&y) {
/ / faz al-go
] else if (x .2 ll Y) {
/ / faz al-go
'l o1co f
// xdeveser2
/ / faz ortrra coisa
]
VocA escreve instrug6es print com elas:
while (true) {
if G>21 t
break;
JAVA 5 217
System.out.print("ff we got here something went horribly
wrong");
]
Adicionadas ) linguagem Java n? verseo 1.4, as assertivas permitireo que voc6 tesre suas suposig6es duranre
o
desenvolvrmento, sem o desgaste (tanto de seu tempo quanto de sobrecarga no programa) de escriver manipuladores para
e.xceg6es.quesestpaenanvlcorrerdo,umavezqueoprog?amativersaidoda'faseiedlsettrolrri-.rrtoefortoialmente'
distribuido.
A p1{r-do exame 31G035 (versig 1.4 do exame dgProgramadorJava Certificado pela Sun), e continuando com o exame
at ull 31G055 fava5), ser6 esperado que v.oc6 conhega Js aspectoi bisicos de .o-o (emJava) furrcioo"rrr,-
incluindo como ativi-las, usl-lxe naus6-las. ", ^r.nivas
]
J6 que voc6 esti tio. certo de sua suposigio, nio guer perder tempo (ou trazer um impacto ao desempenho do programa)
escrevendoumc6digodemanipulagiodeexceg6es.Enotempodeexecugio,nSodisejarestesif/Lrse insirid6spoique
se rvalnmte chegar i.condigio el sFr_isso significari que sua l6gica anterior (o que quer que estivesse sendo e*.c.rt"do^*tes
desse m6todo ser chamado) tem falhas.
As assertivas permitem que voc6 teste suas suposig6es durante o desenvolvimento, por6m, seu c6digo - efetivamente -
des@arece quando o programa 6 distribuido, nio deixando nenhum c6digo de depuragio ou que causl sobrecarga a ser
identificado e removido. Reescreveremos methodA ( ) para validar se-o argomento nio foi negativo:
private void methodA(int num) {
assert (num>=O) ; / / lanqa um AssertionError
// se este teste n6o for verdadeiro
rrc6I\Trrm /nrrn , + xr;
]
nio s6 permitem que seu c6digo permanega mais limpo e menor, mas, como elas ficam inativas, a
As assertivas
menos que seram especilicamente "postas em agio" (ativadas), o c6digo ser6 executado como se tivesse sido
escnto assrm:
private void methoda(int num) {
useNum(num + x), // testamos isto;
/ / zaara d5laemos que est6 tudo bem aqui
]
As assertivas funcionam de maneira bem simples, Voc6 sempre assumiri qu e algo 6. uerdadeiro. Se realmente for, nio haveri
Problemas. O c6digo continuar6 a ser exeiutado. Mas, se sua assertirrlr r. irortr", errada (false), eniio, seri
langado um erro AssertionError
(que vocA nunca, jamais deve manipular!) imediatamente,'de modo que
voc6 possa corrigir a falha na l6gica que levou ao problema.
Existem duas vers6es das assertivas: simples e muito simples, como podemos ver abaixo:
Muito simples
private void doStuff ( ) {
assert (y > x) ;
/ / mais c6digo assumindo-se que y seja maior do que x
218 Copitulo 5: Controle de fluxo, exceE5es e ossertivos
]
Simples
private void doStuff ( ) {
assert (y > x): tty ig o + Y \r s x ig " +:t;
/,/ mais c6digo assumindo-se que y seja maior do gue x
)
A diferenga entre elas 6 que a versXo simples adiciona uma segunda exPressao, seParada da primeira (a expressio
booleana) por dois pontor, q,r. algumas informag5es a mais ao ra$rearnento da pilha. As duas vers6es
".r.rienta
la.rg"mrr*assertionError imediatamenti, mas averslo simples lheforneceri.umpouco mais de aiudana
depuraglo, enquanto a verslo muito simples apenas informar6 que sua suposigio 6 fdsa.
AOTRABAI}IO
Norwalmente, as assertiaas sdo atiuadas quando an @licatiuo uttl sendo testado e depurado, porin, sd.o duatiuadas quando ele i distribuido.
Elas ainda estardo no cridigo, enbora s/an ignoradas pek JI/M, portanto, se uocl tiuer am aplicatiuo distibuido qae cLnece a a?resentar um
cornportamento tnadequado, senpre poderui optar por atiuar as assertiuas no cartpo para testes adicionais.
void noReturno {}
int aReturno { return 1; )
void go0 {
intx=1;
boolean b =
accarl- th\ .
assert true,'
^^^^rr /.. -- 1\ . x;
:ccarl- lv == 1 \
. aReturnO;
-^^^e!
oD-erL\^
/-.
--
--
1\
f/
.
. new ValidAssert O ;
assert (x) ;
assert 0;
ac<arl- lv == 1 'l
. . / / nenhrrma del as retorna um val-or
assert(x == 1) : noReturn { ) ;
assert(x == 1) : ValidAssert va;
JAVA 5 2'I9
oBSERVAe6rspaneoEl<eME
Se uoc6 se dtparar cam a palawa "expressio" em uma pergunta sobre asertiuas e ela n6o especifcar n esti se refeindo i pineira express1o (a
exprusio booleana) ou i rcgunda (o ualor a ser exihido n0 rastreamentl da pilhQ, entdo, ir$re prenna quiuti se ,tj'triuao i prineira
exprusio, o teste boo/eano. Por exemp/0, se /he pergmtanzos o rcguinte,
Preuma apa/awa 'expressdo'como nndo apimeira expressdo de uma instrugdo assert, atsim a du/aragdo dapergunta ettani
comta. Se
a declaragdo estiaesse se refeindo i segunda exprestdo, no entanto, ndo estaria coreta,jd que esa exprexdo pode to rloo
rcsultado quaQuer
ua/or e ndo apenas ambooleano.
Ativando assertiyas
Sevoc6quiserusarassertivas,teri.queconsiderarprimeiro comocompilarcomelasemseuc6digoecomoser|aexecupdocom
ativadas. As duas situag6es.requerem aversio 1.4 ou iuperior e isso nos conduiao primeiro problema:
essas asseftivas
como o c6digo seri compilado com asserdvas.
ldentificador x Palavra-Chave
Antes da versio L.4, vocd poderia muito bem ter escrito um c6digo como esse:
VocA pode usar "assert" como uma palavra-chave ou como um identificador, mas nXo como ambos.
AOTRABALHO
SeporalgummotiuoaociestiuerusandoumconpikdorJaua/.4,eettiuerutantloassert comoumapa/aara-chaue(enoutraspa/atras,
estiuer realmente tenlando nnfrrnar algo en seu aidigo), entdo, teni que atiuar explicitaaente o recofihecimento de assertiuas no ienpo de
rorpi/agio, como descrito abaixo:
Tobelo 5-3 Usondo Jovo 5 poro Compilor C6digo que use Assert como ldenti{icodor ou como Polovro-Chove
javac -source 1.3 TestAsserts. java O c6digo compila com avisos. A compilagio falha.
Ji que as asseftivas slo desativad x por padfro, usaros switches de desativag5" q"+ parccer desnecess6rio. De fato, o
*o dor switches, da maneira que mostr-amos no exemplo anterior, lhe fornecer6 simplesmente o comPortam€nto ,
padrlo (em ouras palavras, vod obteri o mesmo rgsultado independente do uso dos switches & desativagio). Por6m,
-cle
vocp tamb6m pode ativar e desativar as assertivas seletivamente, modo que- elas figuem ati.vadas para.algumas
classes e/ou p"aot.r e desativadas para outros, enquanto um programa especifico estiver sendo executado.
Voc6 pode combinar switches para, digamos, desativar assertivas em somente uma classe, por6m, mantendo-as
ativadas para todas as outras classes, como descrito abaixot
java -ea -da : com. geeksanonymous' Foo
A linha de comando anterior informa ) JVM para ativar assertivas no Ambito geral, por6m, desativando-as na
classe com. geeksanonymous . Foo. Voc€ pode ter a mesma seletividade para um pacote como vemos a seguir:
I ^--^ t- - ^. ..
lava -ea -od:com.geeksanonymous.
JAVA 5 221
A linha de comando anterior informa i JVM para
ativar asserrivas no imbito geral, por6m desativando-as no
P-acote coru.geeksanonlmous e en todos os yus^ pode nio estar familiarizado com o termo ubpacote, ji que
tubpac.oteslVoc6
ele nio era muito usado antes da exist6ncia das assertivas, O nbpacote pode ser qualquer pacote de um subdiretorio
O" mencionado. Por exemplo, observe a 6wore de diret6rio abaixo,
:::*
apalrcan i nr
.)rmous
I
_Foo
_twelvest.eps
_StepOne
_StepTvo
Essa irvore lista tr6s diret6rios.
geeksanonymous
twelvesteps
e tr6s c]asses:
com. geeksanonymous . Foo
com. geeksanonlzmous . twelvesteps. Stepone
com. geeksanonlzmous . twel-vesteps . StepT\^ro
lava -ea
java -enableassertions Ativa assertivas
java -da
j ava -disableassertions Desativa assenivas (o comportamento padrlo da versio 1.5)
lava -ea:com. too. Ativa assertivas no pacote com.foo e em todos os seut subpacotes
java -ea -dsa Ativa assenivas no Ambito geral, por6m desativando,as nas classes do sistema
lava -ea -da:com.too Ativa assertivas no Ambito geral, por6m desativando-as no pacote comrfoo e em
todot os sets subpacotes
assert (x > 0) ;
/ / faz coisas com x
]
Umm6todopublic podeserchamadoapartirdeumc6digoquevoc6niotenhacontrole(ouquejamaistenhavisto).
J6queosm6todospuniic fazempartedeiuainterfaceexpostaloambienteexterno,6precisogarantirquenenhuma
?ertrigio seja imposta pelo pr6prio m6todo. Por6m, como.nio 9e pgde as-segurar que-as assertivas sejam
" "rgumentos(normal-.ote .sao deiativadas em um aplicativo distribuido), a imposigio nio ocorrer6 se elas nio
,.dmlrrr. e*I*tadas
forem ativadas. Voc6 nXo ir6 querer um c6digo de acesso priblico que s6 funcio ne condicionalmente, dependendo das
assertivas estarem ou nio ativadas.
Se voc6 tiver que validar argumentos de m6todos publ ic, poder6 usar_exceg6-es para langar, digamos, uma
I 1 I ega lArgumentExi ept i on se os valores passados ao m6todo nio forem v6lidos.
A rinica diferenga importante entre o o<emplo anterior eo fomecido antes dele 6 o modificador de acesso. Portango, impgnha
restrig6es aa{gumeniosprivat e,n x o}oa^6todospubl ic. E claro q.te yod pode compilarum c6digo de assertivas com
"^ irnaaZ"napropnadzdea{gumentospublic,mas,noorame(enavidareal)6precisosaberqueniadewfaz&lo.
Nio use asseltiyas para validar argumentos de linha de comando
Na verdade, esse 6 apenas um caso especial da regra: "Nio use asseftivas para validar argumentos de um m6todo
publ ic'1 5" ,r, prbgr* a preitsar i" de linha de comando, voc6 poderi ,tt"t o tttecattismo de exceg6es
para forgar sua utilizaglo. "tgu*rttios
Nio use assertiv.ilr, mesnro em m6todos Public, para procurar instrug6es c.rse que sabe
gue nunca ocorrereo
Isso pode incluir blocos de c6digo que provavelmente nunca serio alcangados, como o bloco def ault de uma instrugio
switch que poderia ser a descrita abaixo:
swit.ch (x) {
case 2: Y = 3;
case 3: Y = ]-7;
case 4| y = 27;
defautt: assert false; /,/ N5o deveriamos nunca chegar at6 aquil
]
Se voc6 presumir que um bloco de c6digo especifico nio ser6 alcangado, como no exemplo anterior, no qual assume que x
temqueserigualiZ,lou4;poder6usiraisert falseparafazercomqueumAssert.ionError sejalangado
imediatamenie se em algum momento isso chegar a acontecer. Portanto, no exemplo de swi tch, nio estamos executando
um teste booleano - ji iseguramos que nunca chegaremos 16, de modo que simplesmente atingiresse ponto seri uma
falha autom6tica em sua assertiva/suposigio.
JAVA 5 223
Nio use express6es assettivas que possam causar efeitos colaterais!
O c6digo a seguir seria muito inadequado:
public void doStuff ( ) {
assert (modiflrlhings( )) ;
// segue adiante
J
)
A regra 6: Uma exprufio atserfiua deue deixar o programa no metno estado em que estaua antes da exprusdolPense nisso. Nio h6
garaffia de que as express6es assertivas sejamsempre executadas, ponanto, voc6 nio ir6 querer que seu c6digo se compone
dilerentemente caso as assertivas sejam ativadas. As asseftivas nio devem causar nenhum efeito colateral. Se elas forem
ativadas, a rinica alteragio na maneira como seu programa ser6 executado 6 que um AssertionError pode ser lanEado
se uma das assertivas (ou npmgde) se mostrar falsa.
AOTRABALHO
Usar assertiuas capaTu de causar efeitot colaterais pode leuar a a/guns dos bugs mais enlouquecedoru e dficeis de encontrar ! puando um
analista de controle de qualidade esquentado utd ubrau/andoporque 0 sea cddigo ndofunciona, a uelha devupa de "bom, elefunciona na
MINHA nAauina" ndo uai adiantar.
VocA tamb6m aprendeu que a instrugio switch 6 usada para substituir virias instrug6es i f -else. A instrugeo
swi tch pode avaliar tipos primitivos inteiros que possam ser conveftidos implicitamente em um tipo int
(esses tipos
slo byte, short, int e char), oupode avaliar enums.
No tempo de execugio, a JVM tentar6 encontrar uma coincid6ncia entre o argumento da instrugio swi tch e o
argumento de uma instrugio case correspondente. Se a coincid6ncia for eniontrada, a execugio comegar6 com
a.instrugio case correspondente e continuarA apaftir daiat6 que uma instrugio break surja ou que ocorra o
final da instru$o swiLch. Se nio houver correspond€ncia, a instrusio case default ser6 executad4 caso haja uma.
VocA conheceu as tr€s estruturas de loop disponiveis na linguagem Java. Essas estruturas slo os loops f or
(incluindo o for bisico e o for aprimorado que foi introduzido emJava 5), while e do. No Ambito geral, o
loop for 6 usado quando sabemos quantas vezes ser6 preciso percorrer o loop. O loop whi 1e 6 usado quando
nio sabernos quantas vezes precisaremos percorrer o loop, enquanto do 6 empregado quando temos que
-
Percorrer o loop pelo menos uma vez. Nos loops f or e whi1e, a expressio terl que ser true para entrl$ no
bloco e ser6 verificada a cada iteragio do loop. O loop do nio verifica a condigio antes de percorrer o loop uma
vez. O principal beneficio do loop f or 6 o recurso de iniciahzar uma ou mais vari6veis e aumentar ou diminuir
seus valores na definigio do loop.
As instrug6es break e continue podem ser rotuladas ou nio-rotuladas. Quando nio 6 rotulada, a instrugio
break forga o programa a interromper o processamenro da estnrtura mais interna de loop e prossegue na linha de
c6digo posterior ao loop. O uso de um comando continue nlo-rotulado [ar|,com que o programa interrompa a
execugio da iteragio atual do loop mais interno e prossiga com a pr6xima iteragio. Quando uma instruglo break
ou continue for rotulada, ela seri executada da mesma maneira, com uma exceglo. A instrugio nio ser6 aplicada
ao loop mais interno, emvez disso, ser6 aplicada ao loop com o r6tulo. A instrugio break geralmente 6 mais usada
junto com a instrugio switch.
Quando houver uma correspond6ncia entre a expressio switch e o valor de case, o c6digo posterior a case
seri executado. Para interromper
a execugio do c6digo, seri preciso introd:uzir a instrugio break.
Voc6 viu como a linguagem Java fornece um mecanismo sofisticado de manipulagio de exceg6es. A manipulagio
224 Copitulo 5: Conlrole de fluxo, exceE6es e ossertivos
de exceg5es permite que vocd isole seu c6digo de corregio de erros em blocos separados, de modo que o c6digo
principal nXo fique confuso por causa dele. Outro recurso interessante permite que voc6 manipule erros
iemelh"ntes .o* ,r* rtnico bloco de manipulagio de erros, sem a duplicaglo do c6digo. Al6m disso, a
manipulagio de erros pode ser transferida para m6todos mais embaixo na pilha de chamadas.
Voc6 aprendeu que a palavra-chave try da linguagem Java 6 usada para especificar uma regiio protegida - um bloco
de c6digo ,ro q,r"l os iroblemas podem r.r d.tect"dos. Um manipulador de exceg6es 6 o c6digo executado 9_uando
ocorre uma excegio. b manipulador 6 definido com o uso da palavra-chave catch da linguagemJava. Todas as
cl{usulas catch devem seguir imediatamente o bloco try relaironado. A linguagem Java tamb6m fornece a
palavra-chave f inal1y. Ela 6 usada para definir um bloco de c6digo que sempre ser6 executado, imediatamentg ap6s
uma cl6usula catch ser concluida on logo depois do bloco try associado, caso nenhuma excegXo seja langada (ou
se houver um bloco try, mas nio um bloco catch). Use blocos f inally para liberar recursos do sistema e
executar qualquer limpezarequerida pelo c6digo do bloco try. O bloco f inal Iy nlo 6 obrigat6rio, mas, se
houver,umteiAquevirap6sobloco.atch(Seniohouverumblococatch,oblocofinally deverivir
imediatamente depois dobloco try). Ele sempre serl chamado, exceto em casos especiais, quando o c6digo de try
oucatch emitirum System.exit( ).
O objeto de exceglo 6 uma instAncia da classe Exception ou de uma de suas subclasses. A cl6usula catch usa,
como parAmetro, uma instAncia de objeto de um tipo derivado da classe Exception. A linguagem Java exige que
todo m6todo capture a exceglo verificada que pode vir a langar ou enteo declare que langar6 a excegio. A declaragio
da excegio f.azfarte da interface priblica do m6todo. Na declaragio de uma exceglo que poder6 serlangada, apalavra-
chave throw Z usada em uma definigio do m6todo, junto com uma lista de todas as exceg6es verificadas que
poderio ser langadas.
As exceg6es de tempo de execugio sio do tipo RuntimeException (ou de uma de suas subclasses). Essas exceg6es
sio um caso especial porque nio precisam ser manipuladas ou declaradas e, portanto, sio conhecidas como exceg6es
nXo verificadas. Os erlos ilo do tipo j ava . 1ang. Error ou de suas subclasses e, como as exceg6es de tempo de
execugio, nio precisam ser manipulados ou declarados. As exceg6es verificadas incluem qualquer tipo de exceglo que
nio seja do tipo RuntimeException ou Error. Se seu c6digo nlo manipular uma excegio verificada ou declarar
que ela serilangada, ndo serA compilado. Por6m, quanto )s exceg6es nio veificadas ou objetos do tipo Error, nio
importa para o compilador se voc6 os declarou ou manipulou, se fez algo com eles ou criou alguma combinagXo de
declaragio e manipulagio. Em outras palavras, voc6 pode declar6los e manipuliJos, mas o compilador nlo se
imponar6 se fez uma ou outra coisa. No entanto, nio 6 boa priticamanipular um erro, ji que raramente vocO
poderi {azer algo para se recuperar dele.
As exceg6es podem ser geradas pela JVM ou pelo programador.
As assenivas, adicionadas i linguagemna versio 1.4, slo uma nova ferramenta ritil de depuragio. Voc6 aprendeu como
pode us6Jas em testes, ativando-as, por6m, mantendo-as desadvadas quando o aplicativo for distribuido. Se voc6 tiver
um c6digo Java mais antigo, o qual use a palavra assert como identificador, nio poderi usar assertivas e teri que
recompilar esse c6digo usando o flag padrio -source 1.3. Lembre-se de que a panir deJava 5, as assertivas sio
compiladas como palavras-chave por padrio, mas devem ser habilitadas explicitamente em tempo de execugio.
Voc€ aprendeu que as instrug6es assert sempre incluem uma expressXo booleana e que, se a expressXo for true, o
c6digo prosseguir6 com a execugio, mas se ela for f a1se, um AssertionError ser6 langado. Se voc6 usar a
instruglo assert de duas express6es, a segunda expressio serl avaliada, convenida para uma representagio em
String e inserida no rastreamento da pilha para fornecer mais algumas informag6es de depuragio. Para
concluir, voc6 viu por que as assertivas nio devem ser usadas para impor o uso de argumentos aos m6todos
priblicos, e por que as express6es assert nio devem apresentar efeitos colaterais!
E As instrug6es switch podem avaliar somente os tipos de dados byte, short, int e char. VocA nio pode
escreven
long s = 30;
switch(s) { }
E O argumento de case deve ser umavariivel literal ou f ina1, ou uma expressio constante, incluindo um enurn" Voc6
nio pode ter uma instrugio case que inclua uma variivel que nio seja final ou um intervalo de valores.
E Se acondigio de uma instrugio switch coincidir com o valor de uma instrugio case, todo o c6digo da instrugio
swi tch que estiver ap6s a instrugio cas e coincidente, ser6 executado at6 que uma instrugio break ou o final da
instrugio switch seja alcangado. Em outras palavras, a instrugio case coincidente ser6 apenas o ponto de entrada
para o bloco case, por6m, a menos que haja uma instrugio break, a instrugio case coincidente nio ser6 o rinico
c6digo do bloco case a ser execurado.
fl Se uma variivel for incrementada ou avaliada dentro de um loop f or bisico, ter6 que ser declarada antes do loop ou
dentro da declaragXo do loop f or.
E Uma variivel declara& (e nio apenas inicializada) dentro da declaragio do loop f or blsico nio poder6 ser acessada fora
do loop (em outras palavras, o c6digo abaixo do loop for nio poder6 us ar avariivel).
B Voc0 pode inicializar mais de uma variivel na primeira parte da declaragio do loop for b6sico; cada inicializaSo de
variivel tem que ser separada por uma virgula.
D Uma instruglo f or aprimorada (uma novidade doJava 5) tem duas panes, a declaragio ea expressio. E usada apenas
parasefazerloop atrav6s de arrays ou conjuntos.
D Com umfor aprimorado, a expressio 6 o array ou conjunto atrav6s do qual voc6 dese jafazer oloop.
E Com um f or aprimorado, a declaraglo 6 avari|vel do bloco, cujo tipo 6 compativel com os elementos do
affay ov conjunto, e essa variivel cont6rn o valor do elemento para aiteraglo em questio.
tr Voc6 nXo pode usar um nfmero (antiga estrutura de linguagens do estilo C) ou outro item que nXo resulte em um
valor booleano como a condiglo de uma instrugio i f ou estrutura de loop. Nio pode, por exemplo, escrever:
if (x) , a menos que x seja uma vari6vel bool-eana.
tr O loop do-while entrarino corpo do loop pelo menos umave4 mesmo se a condigio do teste nio for
atendida.
E As exceg6es verificadas incluem todos os subtipos de Exception, excluindo as classes que estendem
RuntimeException.
B As exceg6es verificadas esio sujeitas I regra de manipulagio ou declaragio; qudquer m6todo que puder langar uma
excegio verificada (incluindo os m6todos que chamem outros m6todos c p^zes de realizar essa tarefa) deve
226 Copftulo 5: Controle de fluxo, exceE5es e ossertivos
O As exceg6es nio capturadas serXo propagadas para baixo na pilha de chamadas , a partir do m6todo em que a
excegio foi langada e terminando no primeiro m6todo que tiver um bloco catch correspondente a esse tipo
de excegio ou com o encerramento da JVM (que ocorreri se a excegio chegar a main ( ) e esse m6todo
passar a exceglo declarando-a).
tr Voc6 pode criar suas pr6prias exceg6es, geralmente estendendo Exception ou um de seus subtipos. Ela seri
considerada uma excegio verificada e o compilador fiorgarS. a aplicagio da regra de manipulagio ou declaragio a
essa excegio.
E Todos os blocos catch devem ser ordenados do mais especifico ao mais geral. Se voc6 tiver uma cliusula catch
tanto para lOException quanto para Exception, ter6 que inserir o bloco catch de TOException
primeiro em seu c6digo. Do contr6rio, a excegio roException seria capturada pelo bloco catch (nx-
ception e), porque um argumento catch pode capturar a excegio especificada ou qualquer um de seus
subtipos! O compilador o impedir6 de definir cl6usulas catch que nunca poderio ser alcangadas.
fl Algumas exceg6es slo criadas pelos programadores, outras pela JVM.
E As assertivas geralmente slo ativadas durante o teste, mas desativadas durante a distribuigio.
D Voc6 pode ativar ou desativar assertivas por classe, usando a sintaxe a seguir:
fl Use assertivas * mesmo em m6todos public- para garantir que um bloco de c6digo especifico nunca seja
alcangado. VocA pode usar assert false; para um c6digo que nunca deve ser alcangado de modo que um
erro de assertiva seja langado imediatamente se a instrugio assert for executada.
Teste individual
l. Dado o seguinte c6digo:
JAVAS 227
public class OrtegorumFunction {
public int computeDiscontinuous(int x) {
inf r - 1.
T+=X;
if ((* > 4) && (x < 10)) {
r+=2*xi
) else (x <= 4) {
r+=3xX;
] al qa f
r+=4*x;
)
r += 5 * v.
roi. rrrn r.
)
public static void main(String [] args) {
OrtegorumFunction o = new OrtegforumFunction( ) ;
System.out.println( "OF(L1) is : .. + o.computeDiscontinuous (11) ) ;
)
]
Qual6 o resultado?
A. oF(11) is: 45
B. oF(11_) is: 56
c oF(11-) is: 89
D. oF(11) is: LL1"
E. Acompilagofalha.
ir
E
- E Iangada uma excegio no rempo de execugio.
1. class Two {
2. public static void main(Stri-ng[] arqs) {
3. assert false) ; 1
A\
3. Dado:
import java. io. *;
c]ass Master {
String doFileStuff ( ) throws FileNotFoundException { return "a"; }
)
class Slave extends Master {
public static void main(string[] arqs) {
String s = nul1;
try { s = new SlaveO.doFileStuffO ;
] catch ( Exception x) {
s = "b"; ]
System. out . println (s ) ;
]
/ / insira o c6digo aqui
]
QualopgXo,inseridaindependentementeem // insira o c6digo aqui,iricompilareproduzirasaidab?
(Marque todas as corretas)
4. Dado:
alaqc Tnhrrl- {
Strrng s = \r-";
try {
doMath(args [0] ) ;
s += "t "; // Iinha 6
]
finally { System.out.println(s += "f "); }
)
public static void doMath(String a) i
int y = 1 / Integler.parselnt(a);
))
E as chamadas de linha de comando:
i ^.-- T-^,.r
rrrPuL
_J4Va
i^--- fT6-..! vn
J qvq rrPuL
5. Dado:
1. cl-ass Crivitch {
2. public static void main(String [] args) {
3. int x = 0;
4. // insira o c6digo aqui
5. do { } while (x++ < y; t
6. System.out.println(x);
t1
8. )
,{"inty=x;
B.inty=10;
CintY=It;
D.inty=12;
E. int Y = 13;
E Nenhuma das anteriores permitiri que a compilagio tenha sucesso.
6. Dado:
class Pl-ane {
staticStrings=N-/'
public static voj-d main(String[] args) {
new P]ane O . s1 (1 ;
System. out . println ( s);
]
void s1 O {
try { s2O; )
catch (ExcePtion e) { s += "c"; }
)
void s2 ( ) throws Exception {
s3O; s += \\2";
s3O; s += "2b";
)
void s3 ( ) throws Exception {
throw new ExceptionO;
)
Qual6 o resultado?
A"-
230 Copitulo 5: Controle de fluxo, exceg6es e ossertivos
B. -c
C -c2
D. -2c
E. -c22b
E -2c2b
G -2c2bc
FL Acompila$ofalha-
7. Dado:
try { int x = Integer.parsefnt("two"); }
Qual opgio poderia ser usada para se criar um bloco catch apropriado? (&Iarque todas as corretas)
A ClassCastException
B tllegralstateException
C NumberFormatExcepLion
D. t 1 legalArgumentException
E. Excepti-onInInitiali zerError
F. ArraylndexOutOf BoundsException
8. Dado:
1. class Ping extends Utils {
2. public static void main(String [] argrs) {
9. Dado:
class Swi11 {
JAVA 5 23I
public static void main(String[] args) {
String s = "-",'
switch(Timezone.CST) {
case EST: s += \e,';
case CST: s += t c,, i
case MST: S += \m".'
default: s += rtl'rt
case PST: s += "p,,;
]
System. out . println ( s);
)
enum TimeZone {EST, CST, MST, PST }
Qual6 o renrltado?
.4"-c
B. -x
C -cm
D. -cmp
E. -cmXp
E Acompila$ofalha.
a 3r t -
G E langada uma excegeo no tempo de execugio.
10. Dado:
class Circus {
public static void main(String[] args) {
intx=9;
intY=6'
for(int z = 0; z < 6; z++, y--) {
if (x > 2) x--i
label:
if(x>5) {
System.out.print(x + " ").
--x;
continue label-;
)
Y--.
Qual6 o resultado?
A"8
B.87
c876
D. Acompila$ofalha.
E. E langada uma exce$o no tempo de exeor$o.
232 Copitulo 5: Conlrole de fluxo, exceE6es e ossertivos
D li apropriado usar asseftivas para gerar alertas quando vod alcang um c6digo que nio deveria ser alcanEado.
12. Dado:
1. class Loopy {
2. public static void main(String[] args) {
3. int[] x = {7,6,5,4,3,2,L);
4. // insira o c6digo aqui
5. System.out.print(y + " ");
7. ]
at
Qual opgXo, inserida independentemente na linha 4, compila? (Marque todas as corretas)
A for(int y : x) {
B for(x : int y) t
C int y = 0; for(y : x) {
D. for(int y=0, z=0; z<x.length; z++l { y = xlzli
E. for(int, y=9, int z=0; zcx.length,' z++) { y = xLzJ;
F inL y = 6r for(int z=0; z<x.length; z++) { y = x[z];
| 3. Dado:
1. class Ring {
2. f inaL stat.ic int x2 = '7 ;
3. final static Integer x4 = 8;
4. public static void main(StringlJ args) {
5. Integer xl- = 5;
6. SLring s = "ao,'
7. if (x1 < 9) s += ttSrt
8. switch(x1) t
9. case 5: s += \'c",'
1-0. case x2: s *= t'd";
LI- case x4: s += "e";
LZ. j
L3. SysLem.out.println(s);
14 ]
1s. )
Qual6 o resultado?
,{. abc
B. abcde
C A compilagio falha devido apenas a um erro na linha 7.
D. A compilagio falha devido apenas a um erro na linha 8.
14. Dado:
class Hnu {
static String s = \-" i
public static void main(String[] args) {
try {
throw Exception( ) ;
ne\^/
) catch (Exception e) {
try {
try { throw new Exception0;
] catch (Exception ex) { s += "ic "; }
throw nehr Exception0; )
catch (Exception x) { s +- *mc \r }
fina11y { s += "mf "; }
) fina11y { s += "of "; }
system. out.println (s ) ;
Qual6 o renrltado?
,{. -ic of
B. -mf of
C -mc mf
D -ic mf of
E. -ic mc mf of
n -ic mc of mf
G Acompila$ofalha"
15. Dado:
class Mineral { }
class Gem extends Mineral { }
class Miner {
staticintx=7;
static String s = nul-l-;
public static void getWeight(Mineral rn) {
intY=0/x;
System.out.print(s + " ");
)
public static void main(String[] args) {
Mineral [ ] ma = {new Mineral O , new GemO };
for(object o : ma)
getweight( (Mineral) o) ;
)
)
E achamadadelinha de cornando:
java Miner.java
Qual6 o resukado?
234 Copilulo 5: Controle de fluxo, exceE6es e ossertivos
A. nu1l
B. null null
C. E langada uma ClassCastException.
D. E langada uma NullPointerException.
E. E langada uma NoClassDefFoundEror.
F. ArichmeticException.
E langada uma
G. 6 langada uma rllegalArgumentException.
H. E langada uma ArraylndexOutO f Bounds Exc ep t i on.
6. Quais das seguintes opg6es normalmente seo langadas pelo desenvolvedor da API ou do
|
aplicativo, em vez de serem langadas pelaJVM? (Marque todas :$ corretirs)
A. ClassCastException
B. rllegalstateException
C. NurilcerFormatExcept ion
D. r1 I egalArgumentException
E. ExceptionlnlnitializerError
Respostas
1 Eest6correta.Ainstrugio it |invllda.Oif-else-else devesermodificadoparaif-else if-else,oque
resultariaem OF ( 11 ) 6: 111.
A, B, C, D e F estlo incorretas com base no exposto acima. (Objetivo 2.1)
2. B e F estio coretas. A classe One compilari (e emitir6 um aviso) usando o flag 1 - 3 , e a dasse Two compilar6 usando o flag
L.4.
A, C, D e E estlo incorretas com base no exposto acima. (Objetivo 2.3)
3. A, D, E e F esteo corretas. E vilido que um m6todo subscritor lance as mesmas exceg6es, exceg6es mais restritas, ou
nenhuma exce$o. E 6 v6,lido que esse m6todo lance quaisquer exceg6es de tempo de execu$o.
B est6 incorreta porque o m6todo subscritor est6 tentando langar uma excegio mais ampla.
C est6 incorreta. Este m6todo nio subscreve , portanto, a suda 6 A. (Objetivo 2.a)
4. A, F e H estio corretas. lJma vez que ambas as chamadas langm o<ceg6es, a linha 6 nunca 6 atingida. Uma vez que ambas as
exceg6esocorreramdentrodeumbloco try, o bloco fi-na11y sempre ser6exmrtado. Aprimeiracharnadalangauma
ArraylndexOutOfBoundsException,easegundalangaumaarithmeticException porcausadatentativa
dedividirporzero.
B, C, D, E e G e$eo incorretas com base no exposto acima. (Objetivo2.5)
9. E est6 correta. E v6lido usar enums em um switch, e , nesse caso, aplica-se a l6gica de passagem completa normal dos
swi tch; ou seja uma vez encontrada uma correspond0ncia, significa que o swi tch foi iniciado, e que todos os
JAVA 5 235
demais blocos rcdario caso nio seja encontrada nenhuma instrugio break. Observagio: d.efault nio
precisa ser o riltimo.
A est6 incorreta. E aceit6vel usar assertivas para testar os argumentos de m6todos private.
B esrl incorraa Embora os erros de assertivas possam ser capturados, a Sun recomenda que vod nio o faa. (Objetivo 2.3)
12' A,D eF estiocorretas.A 6umexemplodoloop for aprimorado. DeFsioexemplosdoloop for bisico.
B esti incorreta porque os selrs operandos estXo trocados. C esti incorreta porque o for aprimorado deve declarar o seu
primeiro operando. E usa sintaxe incorreta para declarar duas variiveis em uma instru$o f or. (Objetivo 2.2)
tl. F esti correta. Uma instrugio switch exige qge as suas express6es de caso sejam consrantes, e variiveis wrapper
(mesmo as que forem final static) nio sio consideradas como constantes. O resto do c6digo esti correto.
Obierlvos pqrq q
certificoe6o
Usor Siring, StringBuilder e
StringBuffer
Exercicios 16pidos
Teste individuol
li,r'
238 Copitulo 6: Strings, E,/S, FormotoEdo e Porsing
Este capitulo enfocari os virios t6picos relacionados ) API que foram adicionados na versXo Java 5 do exlge: O J2SE 1em
com uma enorme API, e bo" p"ne do r..t trabalho como programado rJavateriaver com o uso dessa API. A equipe do
exame decidiu se concentrar nas APIs de E/S, formatagio e paning. Cada um desses t6picos poderia preencher um livro
inteiro. Felizmente, voc6 nXo precisar6 se tornar um guru completo de E/S ou de regex para sair-se bem no exame. A
intengio da equipe do exame foi incluir apenas os aspectos b6sicos dessas tecnologias e, neste capitulo, iremos ab ordar nais
do que voc6 precisa para atender aos objetivos referentes a Strings, E/S, formataglo e parsing do exame.
Tudo que voc6 precisava saber sobre Strings no exame 1.4, continua tendo de saber para o exame SCJP 5... Al6m disso, a
Sun incluiu a classe StringBailfurna API, para fornecer recursos de Stringp mais ripidos e nlosincronizados. A classe
StringBuilder possui exatamente os mesmos m6todos que a antiga StringBuffer, mas StringBuilder 6 mais ripida porque os
seus m6todos nio sio sincronizados. Ambas as classes lhe fornecem objetos semelhantes a Strings capazes de compensar
por alguns dos pontos fracos da classe String (por exemplo a imutabilidade).
A Classe String
Esta segXo abordar6 a classe String, eo principal conceito a se entender 6 que, uma vez criado um objeto String, ele nunca
poderi ser modificado - entio o que acontece quando um objeto String parece estar se modificando? Vamos &scobrir.
s = "abcdef";
Como talvez vocA jA soubesse, a classe String possui virios construtores, portanto, podemos usar um atalho mais eficiente:
E j6 que voc6 usari strings o tempo todo, poderi at6 mesmo escrever o seguinte:
String s = "abcdef";
H6 algumas diferengas sutis entre essas opg6es, que discutiremos posteriormente, mas o que elas t6m em comum 6 que
todas criam um novo objeto String, com valor igual a "abcdef ", e o atribuem a uma variivel de refer6ncia r. Agora,
digamos que voc6 quisesse uma segunda referAncia ao objeto String para a qual s apontasse:
String x = "Java";
x.concat(" nulesI");
System.out.println(lx = " + x) ; // A saida ser5. x = .Java.
Aprimeiralinha6 simples: criaumnovo objeto Stringcom ovalor "Java" e apontax paraele. O queocorredepois? O
VM cria um segundo objeto String com o valor "Java Rules ! ", mas sem algo que o referencie!!! O segundo objeto
String perdido instantaneamente; ningu6m jamais poderi alcang6Jo. A variivel de referOncia x continuar6 referenciando o
6
objeto String original de valor "Java". A Figura G2 most raacriagio deum objeto String sem a atribuigio a uma
refe€ncia
String x = "Java";
x.concat(" Rules!");
System. out . printl
Agora adicionemos:
x. toUpperCase O ;
System.out.println(tx = " + x) i // a saida ainda 6: x = Java
(finhamos realmente acabado de criar um novo objeto String com o valor 'JAVA", mas ele foi perdido ,e x ainda relerencia a
String'Java" original inalterada). Que tal se adicionarmos:
x.replace('a', 'X');
System.out.println("x = " + x) ; // a saida ainda 6: x ='Java
VocA pode dizer o que aconteceu? O VM criou mais um objeto String, com o valor "JXvX", (substituindo as letras apor
x), mas novamente essanova String{oiperdida, deixando xreferenciando o objeto String original inalterado e inutduelde
240 Copftulo 6: Strings, E/S, FormotoEdo e Porsing
Passol: String
Varidvel de
refer6ncia String
Passo3: s = a,concat.
Vari6vel de
Yariivel de
refer€ncla String
Passo l: Slring
Strinl__\
Varidvel de
referGncia Str
r------r
q-Y
tl
Yariivel de
refer3ncia String
Repare que neo 6 criada nenhuma
variivel de referencia Para acessar a
string'Java Rulest".
Abordaremos mais detalhes desses objetos a seguir, mas nio se engane: em termos d€ beneficios para seu objetivo, o que i6
discutimos6 de longe aparre mais imponante dacompreenslo de como osobjetos Stringfuncionam emJava.
Terminaremos esta segio apresentando um exemplo com o tipode pergunta maldosa sobre objetos String quevocO pode
esperar no exame. Nio se apresse e udlizr um papel para pensar (dica: tente manter um controle de quantos objetos e
variiveis de refer6ncia existem e quais se referem aqu€).
SLring s1 = "spring ";
String s2 = s1 + "sunmer ";
st.concat("fal1 ");
s2.concat (s1) ;
s1 += "wi"nter " ;
System.out.println(sl- + * " + s2);
Qual seri o resultado? E quantos objetos String e vari6veis de refer6ncia foram criados antes da instruEio println?
Resposta:.O resuhado desse fragmento de c6digo 6 "spqg_winter spring summer". H6 duas variiveis de refer0ncia, s1 e
sz.^No toral foram criados oito objetos String comoisti descrito a seguir: "sprhg",."Surnmer" (p.t{{o), tptin8
summer", "fall" (perdido), "springiall" (perdido), "springsummerspring" (perdido), "winter" (perdido)' "springwinter"
(nesse ponto 'spring" foi perdido). 56 dois dos oito objetos String nio foram perdidos nesse Processo.
Variivel de
referGncia String
Passo2: x = x. concat
Vari{vel de
refer€ncia String
",Java Rul-es !
String x = "Exit";
system.out'print]-n(x.equa1sIgrnoreCase(..EXrT,,));//retorna
System.out.println( x.equalslgnoreCase("tixe") ) ; // retorna "false"
public int length$ Esse m6todo ret ornara a extensio da String usada para chamar o m6todo. Por exemplo,
String x = "01,234567";
Svstem.orrt.nrinfln( x Iencth() l: // reLorna "S"
vJ v evrLr. vg u t yr +r.e+
un ndtodo), chamado length. Vocdpode encontrarperguntas n0 exame que tentett asaro mdtodo
Os arrals tdm um atribato (e n6o
length ( ) en tlm atEt ou o atributo length em um objeto Sting. Os dois casos causardo envs do compikdor, Por exentpk,
Strj-ng x = "test";
System.out.println( x.length l; / / erro de compilaqSo
ou
public String replace(char old, char new) Esse m6todo retornari um objeto String cujo valor seri o da String
usada para chamar o m6todo, aatalizado de modo que qualquer ocorr€ncia do tipo char do primeiro argumento
seja sobrescrita pelo do segundo. Por exemplo,
244 Capitulo 6: Slrings, E/S, FormotoEdo e Porsing
String x = "oxoxoxox";
system.out.println( x.replace('x', 'x') ); / / a saida 6 "oXoXoXoX"
public String substring(int begin)
iublic String"substring(Int begfi, int end) O m6todo substring ( ) 6 usado para retornar umapane(ou.
zubstring) dJobjeto Strilg empiegado na clramada do m6todo. O primeiro argumento representa o local onde a substring
.o*.9" (L*itri.io no r"ti. S..clamadas6tiverum argumento, isubstringraornadainiluir6os caracteres.mfq*"1h
at6 o fini d. String original. Se a chamada tiver dois argumentos, a substring retornada terminar6 com o caractere localizxlo
na en6sima posigi6 dabtring original, em que n 6 repr-esentado pelo segundo argumento. In felizmente, o argumento final
nlo teri iniiio tro zero, pon-"ntol se o segwdo argumento for 7, o rihimo caractere da String retornada seri a posi$o 7 da
String original, que 6 o indice 6. Examinemos alguns exemplos:
String x = "0123456789"; / como num passe de m6gina, o valor de cada char
/
// 6 o mesmo que o seu indicel
System.out.prinLln ( x.substring (5) ) ; // asaida 6 "56789"
System.out.println( x.substring(5, B) ) ; // asaida6"567'
O primeiro exemplo 6 f6cil: comeEa no indice 5 e retorna o restante da String. . O segundo exemplo deve ser lido da forma a
seguir: comega no indice 5 e retorna os caracteres at6 (e incluindo) a oitava posigio (indice 7).
public String tolnwerCaseQ Esse m6todo retorna um objeto String cujo valor 6 a String usada para chamar o
m&odo, por6.-m, com os caracteres que estiverem em letras mairisculas agora convertidos para minusculas. Por exemplo,
String x = tr6 New Moon";
System.out.println( x.t.olowerCase( ) ) ; / / a saida 6 "a new moon"
public String toStringQ Esse m6todo retorna o valor da String usada para chamar o m6todo. Qu6? Por que
precisariamosdeumm6todoqueparece niofaz-ernada?TodososobjetosemJavadevemterumm6todotoString( ),
normalmente retornando uma String que de alguma maneira significativa descrwe o objeto em q-uestio. No caso de um
objeto String, o que seria mais significativo que seu valor? Para que isso fique mais claro, aqui estS um exemplo:
String x = "big surprise";
System.out.println( x. toStrinS ( ) ) ; / / a saida 6 - tente descobrir!
public String toUpperCaseS Esse m6todo retornaum objeto Stringcujovalor6 aStringusadapara chamar o
m6todo, por6m, com os caracteres que estiverem em letras minfsculas agoraconverddos paramairisculas. Por exemplo,
String x = "A New Moon";
System.out.println( x. toUpperCase O ) ; / / a saida 6 "A NEW MooN"
AOTRABALHO
Un enprego conun dot lbjetls S tingBufer e S tringBuilder d na E / S de arqaiuos quando fluxos grandet de entrada e com alteragdo
cufistafite estdo sendo manipuladot pelo programa. Nesset casot, grandes blocos de earacteres sdo manip*lados como ulidades, e os
objetls StingBrfer d a maneira ideal de manipular um bloco de dadoq passd-lo adiante e, em segaida, reatiliqar 0 nermo etpa(o na
memdria para maniprlar o pniximo bloco de dados.
StringBufier x StringBuilder
A classe StringBuilder foi adicionada emJava 5. Ela tem exatamente a mesma API que a classe StringBuffer, exceto pelo
fato de que StringBuilder nio 6 segura em relagio aos threads. Em outras palavras, os seus m6todos nio sio
sincronilados. (Filaremos mais sobre a seguranga de threads no Capitulo 9.) A Sun recomenda que voc6 use
JAVA 5 245
StringBuilder semPre que possivel, porque essa classe roda mais rapidamente (e talvez pule mais alto. tamb6m).
Asstm, tirando a sincrolizagio, tudo. que dissermos sobre os m6todos de StringBuildei6 verdadeiro iamb6m
Para os m6todos de StringBuffer, e vici-ve-rsa. O exame poder.i usar essas classJs na criagio de aplicativos com
threads seguros, e n6s veremos como isso funciona no Capitulo 9.
public StringBuilder delete(int start, int end) Este m6todo retorna um objeto StringBuilder e atualiza o
ialor do objeL StringBuilder'que chamou o m6iodo. Nos dois casos, uma substring 6 removida do objeto ori,ginal.
O indice incial da su6string a ser removida 6 definido pelo primeiro argumento (que comega pelo zero), e o indice
final da substring a ser rem"ovida 6 definido pelo segundo argumento (mas este comega pelo um)! Estude o seguinte
exemplo com cuidado:
StringBuilder sb = new StringiBuilder ("0L23456789" ) ;
System. out.println(sb.delete (4, 6) ) ; // asaida6"0\236789"
public StringBuilder insert(int offset, String s) Esse m6todo retorna um objeto StringBuilder e atualiza o valor
do objeto StringBuilder que chamou o m6todo. Nos dois casos, o objeto String passado para o segundo argumento
ser6 inserido no StringBuilder original comegando pelo local de deslocamento representado pelo primeiro_
argumento (o deslocamento tem inicio no zero). Novamente, outros tipos de dados podem ser passados pelo
segundo argumento (booleano, char, double, f 1oat, int, long e outros), mas o argumento String
provavelmente ser6 o que voc6 mais ver6:
Strlngeuilder sb = new StringBuilder ("0L234567 " ) ;
sb. insert (4, "---" ) ;
System.out.println( sb ) ; // a saida 6 "01,23---4567"
public synchronized StringBuffer reverse$ Esse m6todo retorna um objeto StringBuffer e atualiza o valor do
objeto StringBuffer que chamou o m6todo. Nos dois casos, os caracteres do.objeto StringBuffer sio invertidos, com
o primeiro caractere se tornando o riltimo, o segundo se tornando o penriltimo e assim por diante:
StringBuffer sb = new StringBuffer("A man a plan a canal Panama");
sb.reverse{);
System. ouL . pri-nt1n ( sb) ; / / a saida 6 "amanaP lanac a nalp a nam A"
public String toStringQ Esse m6todo retorna o valor do objeto StringBuffer que chamou o m6todo como
um objeto String:
StringBuffer sb = new StringBuffer("test string");
System.out.println( sb.tostring() l; / / a saida 6 "test string"
Isso 6 rudo com relagio aos objetos StringBuffer e StringBuilder. Se houve algo que voc6 conseguiu captar nesta
segio 6 que dferennnente dos objetot String, os objetos StringBffir e StingBuilderpodem ser alterados.
/ . Descubra o qae a chamada do mdtodo da exhvma esquerda rctomani (cbamaremos ase aa/or dc x).
2. Use x como o objeto que chanari partir da uqaerda). Se hoauer somente dois ndtodos encadlados, o rualtado da
o segando ndtodo (a
segttnda cbamada de mitodo ser,i o re.ruhado da express1o.
3. Se houuer am terceiro mdtldo, o res/tado da seganda chamada de mdtodo seni asado para chamar o terceim mitodo, culo reuhado senl o
resultado da expressio, Por exeuplo,
String x = "abc";
String y = x.concat("def"),toUpperCaseO.replace('C','x'l; //m6todo concatenado
system.out.println("y= " +y); // o resultado 6 "ABXDEF"
Exaninemos 0 qt/e nczrrerl. O ualorliteral "def "1ki concatenado a "abc", niando um objeto Shinginarnedidio terzporiio (qre bgo
seriperdido),comoualor "abcdef ". Omitodo toUpperCase( ) criouumnouoobjetoStringtenponirio(qotlososeniperdido)
comoualor 'ABCDEF'1 Omitodoreplace( ) criozamobjetoStringfnalconoaalor"ABxDEF"erelferencioay aele.
I F{:. A
{PI diz que a classe File 6 "uma representagio abstrata de nomes de caminho de arquivos e diret6rios". A
classe File nlo 6 usada para ler ou escrever dados, propriamente; 6 usada para trabalhar em um nivel mais alto, criar arquivos
vazios, procurar por arquivos, apagar arquivos, criar diretorios e trabalhar com caminhos.
r FileReader Esta classe 6 usada para ler arquivos de caracteres. Os seus m6todos read ( ) sXo de nivel relativamente
baixo, permitindo que voc6 leia caracteres isolados, todo o stream de caracteres ou um nrlmero fixo de caracteres. Os
FileReaders normalmente slo mcapuladw (wrapped) por objetos de nivel mais alto, como BufferedReaders, os quais
melhoram o desempenho e fornecem meios mais convenientes de se trabalhar com os dados.
r BufferedReader Esta classe 6 usada para tornar classes Reader de nivel mais baixo, como FileReader, mais eficientes e
ficeis de rfar. Comparados com FileReaders, BufferedReaders l6em pedagos relativamente grandes de dados retirados do
arquiv-o de uma s6 vez, e mantAm esses dados em um buffer. Quando voc0 pede o caracter ou linha seguinte, ele 6 retirado
do buffer, o que minimiza o nirmero de vezes que as demoradas operaE6es de leitura de arquivos serlo realizadas. Al6m
disso, BufferedReader fornece m6todos mais convenientes, como readline ( ) , que lhe permite obter a pr6xima linha
de caracteres de um arquivo.
r FileVriter Esta classe 6 usada para escrever em arquivos de caracteres. Os seus m6todos write
( ) lhe permitem
escrever caraderes ou Strings em um arquivo. Os File\Triters geralmente sio encapsulados por objetos \Triter di nivel mais
alto, tais como Buffered$Triten ou Print'\0riters, que fornecem melhor desempenho e m6todos de alto-nivel mais flelveis
para escrever dados.
r BufferedVriter Esta classe 6 us adaparatomar classes de baixo-nivel, como FileIflriters, mais eficiernes e ficeis de usar.
Comparados com Filetilflriters, Buffered\0(riters escrevem pedagos relativamente grandes de dados no arquivo de uma s6 vez,
minimizando o nimero de vezes que as demoradas operag6es de leitura de arquivos serio realizadas. Al6m disso, a classe
BufferedVriter fornece um rn6todo newline ( ) que facilita a criagio autom6tica de separadores de linhas especificos i
plataforma.
I PrintVriter Esta classe foi melhorada significativamente emJava 5. Devido aos novos m6todos e construtores (por
exemplo corstruir um PrintVriter com um File ou String), voc6 poderi perceber que poder6 usar Print\(/riter em lugares
onde, anteriormente, precisava que um \Triter fosse encapsrlado com um FilerilTriter e /ou um BufferedlVriter. Novos
m6todoscomo format ( ),printf O eappendO tornamosPrint$(ritersbastanteflexiveisepoderosos.
OBSERVAQ6ESpenaOH(AME
As elases de streamfio usadas para /er e etcreuer b1tes, e os Rcadert e lVriters sdo utados para ler e esmuer caratteres. (Jma ueqqae todos os
aipins de E/
S de arquiuot do exane se relacionam a caracterer, caso uoci uqfa nones de c/asses API contendo a palaura "Shvam", por
exefirPll DataOutputStream, entdo a questio prouauelmente se refere d nialiqagio, ou a algo qae ndo tem a aer clm o objeto de E/ S
propianente dito.
// classes de java.io
nlaqc lalri farl I
]
]
Se voc6 compilar e rodar esse programa, quando observar o conterido do diret6rio atual, voc6 nio descobriri
;br.il;;;;i;"""h"*" i"di."ia.3. chamado f ilewritel . txt. Quando cria uma nova instAncia da
classe File, uoci ndo estti criando um arqaiao"*'"r'q"i"o
propn)nede, e$ri ciando @enas um nome de _arquiuo. A.panir.do momento em que
voc6 tem um lbjetlFile,existem diversai m'aneiras de se criar um arquivo propriamente dito. Vejamos o que podemos
fazer com o objeto File que acabamos de criar:
imnar| irrra in *.
JsYs.rv. ,
class Writerl- {
publj-c static void main(String [] args) {
Ery { / / aviso: possiveis exceg6es
boolean newFlle = false;
File fi-le = new File / / 6 anan:q rrm ntr'iefn v syerrqs srr vvJ v ev
("fileWrite1.txt" );
System. out.println ( f i1e. exists ( ) ) i / / procura por um arquivo real
newFile = fiIe. creaLeNewPile ( ) ; / / Lalvez crie um arquivo!
System. out . println (newFile ) ; / / iA aviqr'a?
i
Isso produz a saida
false
E.rue
t n:"* t.*b6m um arquivo vazio no seu diret6rio atual. Se voc6 rodar o c6digo nouamenle,receberi a seguinte saida
I Primeira Execugio A primeira chamada a exists ( ) retornou f alse, que era o que esper6vamos... lembre-se de
quenew FileO nlocriaumarquivoemdisco! Om6todocreaLeNewFileO,essesim,criouumarquivoe
retornou true, indicando que o novo arquivo fora criado, e que antes dele nio havia nenhum. Finalmente, n6s chamamos
existsO novamente,edestavezeleretornoutnre,indicandoqueagoraexisteoarquivoemdisco.
I SegundaExecugeo Aprimeirachamadaaexists O retornatrue porquen6scriamosoarquivodurantea
primeira execugio. Depois, achamadaacreateNewFile ( ) retorna false, umavezqtrc o m6todo nio criou um
arquivo desta vez. E, 6 claro, a riltima chamada a exi sts ( ) retorna true.
Aconteceram algumas outras coisas novas nesse c6digo. Primeiramente, repare que tivemos de colocar o nosso c6digo de
criaEio de arquivos em um bloco trylcatch. Seriassim para quase todos os c6digos de E/S de arquivos que voc6
escrever. E/S 6 uma daquelas coisas inerentemente arriscadas. Estamos mantendo a simplicidade por enquanto, e
ignorando as exceg6es, mas ainda precisamos seguir a regra de tratar-oudeclarar, uma vez que a maioria dos m6todos de
E/S declaram exceg6es verificadas. Falaremos mais sobre exceg6es de E/S posteriormente. N6s usamos dguns dos
m6todos de File nesse c6digo:
I boolean exists ( ) Estem6todo retorna true se conseguirencontraro arquivo.
I bootean creat€lilevrFile ( ) Este m6todo cria um novo arquivo caso ele ainda nio exista.
oBSERVAQ6ESpeneOE)(AME
I-znbre-se de qw os criadores d.o exame estardo vmprc tentando co/ocar unagrandt q*antidade de cidigo en espaprPequenor, defonna que,
no exemplo anterior, en aeqdettas trds linbas de c6digo,
)
o que produz a saida:
1-2 howdv
folks
Eis o que acaboude acontecer:
c Criou um arquivo vazio em disco (e voc6 pode provar que isso aconteceu).
2.Escrevemost2caracteresnoarquivocomom6todowriteO,erealizamosumf}ushO eumcloseO.
3. Criamos um novo objeto FileReader, que tamb6m abriu o arquivo em disco para leitura.
4. O m6todo readO leuoarquivointeiro, umcaracterdecada vez,eo colocouem char[ ] in.
5. Exibimos o nfmero de caraaeres cujotamanho ('size") foi lido, e fizemos um loop atrav6s do alray rn CIdbindo cada
caracter que tenhamos lido, e depois fechamos o arquivo.
250 Copitulo 6: Sfrings, E/S, Formotogdo e Porsing
1. Quando esr6vamos escrevendo dados no arquivo, inserimos manualmente os separadores de linha (neste caso \n) em
nossos dados.
2. Quando est{vamos lendo de volta os dados, os colocamos emum array decaracteres. Por se tratar de um array, tivemos
de declarar o sen tamanho antecipadamente, de modo que teriamos problemas caso nio o ti#ssemos.feito_grande o
suficiente! Poderiamos ter lido oi d"dos .t* caracter de cada vez, procurando pelo fim do arquivo ap6s cada read ( ) ,
mas isso 6 bem inadequado tamb6m.
Devido a essas limitag6es, normalmente n6s sempre usaremos classes E/S de nivel mais alto, como BufferedWriter ou
BufferedReader, em combinafro com FilelVriter ou FileReader.
SLring delete ( )
String, String exists ( )
isDirect,ory ( )
r_st, l-le ( )
1i-st o
mkdir ( )
renameTo ( )
Writer nrini/\
Y!:frg \ / ,
nri-r1n/\
v! f rref rr \ /
write ( )
1. Sabemos que queremos' em ultima instincia, trabalhar com um objeto File. Entio, quaisquer que sejam as outras classes
que usarmos, uma delas precisa ter um constnrtor que use um objeto do tipo File.
2. Encontre um m6todo que, pelo nome, parega ser a forma mais poderosa eflclde reahzar atarefa.Observando a Tabela
Buffered\Triter tem um m6todo newline ( ) . Isso soa um pouco melhor do que ter de colocar
6-1, podemos ver que
manualmente um separador depois de cada linha, mas, se olharmos mais adiante, veremos que Print$riter tem um
m6todo chamado println ( ) . Essa aparenta ser a abordagem mais ficil de todas, entio eicolheremos essa.
3. Quando observamos os construtores de Print\7riter, vemos que podemos construir um objeto Print\Triter se tivermos
um objeto do tipo File, entio, tudo o que precisamos fazer para criar um objeto Print\Y/riter 6 o seguinte:
Eis uma maneirapossivel de resolver o problema: primeiramente, n6s sabemos que iremos criarum objeto File em uma
das pontas da cadeia, e que queremos um objeto Printtlflriter na ourra ponta. Podemos ver na Tabela GL que um
Print\(/ritertamb6mpodesercriadousando-seumobjeto\friter.Embora'Writernio seilaumachssepresintenatabela,
podemos v_ er que diversas outras classes estendem S7riter, a qual 6 igualmente adequada par" os nosos prop6sitos; e
qualquer classe que estenda Writer 6 uma candidata. Olhando mais adiante, podemos ver que File\Triter tem os dois
atributos pelos quais estamos procurando:
2. Estende\7riter.
Dadas essas informag6es, podemos escrever o seguinte c6digo (lembre.se: este 6 um exemplo deJava 1.4):
A esta dtura, dever6 ser relativamente ficil produzir o c6digo para ler mais facilmente a partir do arquivo, enviando as
informag6es para a mem6ria. Novamente, olhando na tabela, vemos um m6todo chamado readline ( ) que aparenta
ser uma forma bem melhor de ler dados. Passando por um processo semelhante, chegamos ao seguinte c6digo:
File file =
Sempre cria um objeto File, e em seguida faz uma das duas seguintes coisas:
Assim que tiver um diret6rio, vocd pode colocar arquivos nele e trabalhar com esses arquivos:
rile myFile = new File(rnyDir, "myFile.LxL");
myFile. createNewFile ( ) ;
Essec6digo est6 criando um novo arquivo em um subdiret6rio. Umavez que voc6 fornece o subdiret6rio ao
construro;, dai em diante basta referii-se ao arquivo pela sua vari6vel de referAncia. Neste caso, eis uma forma
myFile:
como voce poderia escrever dados no arquivo
PrintWriter pw = new PrintWriter(myFile);
JAVA 5 253
pw.println ("new stuf ,,
f );
pw. flushO ;
pw.closeO;
VocApodeapontarumobjetoFile paraumarquivooudiret6rioexistenre.Porexemplo,imaginequej6tenhamosum
subdiret6rio chamado existingDir, no qud reside um arquivo existingDirrile . txl, o qual cont6m algumas
linhas de texto. Quando voc6 roda o seguinte c6digo,
de1Filel- . createNewFile ( ) ;
File de1Fi1e2 = new File(
delDir, "de1Fi1e2. txt") ; / / adiciona um arquivo ao diret6rio
de1Fi1e2 . createNewrile ( ) ;
Aal Fi I a1 Aal afa / \ / / aE:aga um arquivo
System.out.println( "delDir is "
+ delDir.deleteO); / / lcenta apagar
/ / o diret6rLo
File newName = new File (
delDir, "newName.txt" ); / / um novo objeto
delFi1e2 . renameTo (newName ) ; // renomeia o arquivo
File newDir = new File("newDir"); // renomeia o diret6rio
defDir. renameTo (newDir) ;
Isso gera a saida:
delDir is false
e nos deixa com um diret6rio chamado newDir que cont6m um arquivo chamado newName . txt. Eis algumas regras
que podemos deduzir desse resultado:
I delete ( ) Nio 6 possivel apagar um diret6rio se ele nio estiver vazio, que 6 o motivo pelo qual a chamada
delDir. delete ( ) falhou.
I renarneTo ( ) VocA precisa dar ao objeto File existente um novo objeto File vilido com o novo nome desejado. (Se
newName fosse nu1 1, teriamos recebido uma Nu I 1 Po int erExc ept i on.)
I renaneTo ( ) E permitido renomear um diret6rio mesmo se ele neo e siler vazio.
H6 muito mais a aprender sobre o uso do pacote java.io, mas, no que se refere ao exame, s6 temos mais uma coisa para
discutir, que 6 aformadeprocurarporum arquivo. Panindo doprincipio quetemos umdiret6rio chamado
searchThis no qual queremos fazer a busca, o seguinte c6digo usa o m6todo File . list ( ) paracrtar vmarray
String de arquivos e diret6rios, nos quais usamos o loop f or aprimor ado paraiterar e exibir:
String[] files = new String[1-00];
File search = new File("searchThis");
files=search.listo; //criaalista
for(String fn: files) // iLera atrav6s dela
System.out.println( "found " + fn) ;
No nosso sistema, obtivemos a seguinte saida:
found dirl
found dir2
found dir3
found file]. txt.
found fi1e2 . txt
Os seus resultados quase cenamente serlo diferentes!
Nesta segio, n6s vimos o bisico sobre o que esd disponivel no pacote java.io.l|foram escritos livros inteiros sobre esse
pacote, de modo que, obviamente, estamos cobrindo apenas uma pequena (mas freqiientemente usada) pane da API. Por
outro lado, se voc6 entendeu tudo o que abordamos nesta segio, estarl bem preparado para lidar com quaisquer perguntas
referentes a java.io no exame (exceto no que se refere d senaltza$o, que serA abordadana seg6o seguintQ.
Imagine que voc6 queira salvar o estado de um ou mais objetos. Se Java nlo tivesse a serializagio (como nio tinha,
naprimeira versio), voc6 teria de usar uma das classes E/S para escrever o estado das variiveis de instAncias de
todos. os objetos.que quisesse salvar. A pior parte seria tentar reconstruir novos objetos que fossem praticamente
idAnticos aos objetos que voc€ estava tentando salvar. VocA precisaria ter o seu pr6prio protocolo pira a maneira
pela qual escreveria e restauraria o estado de cada obleto, caso contririo poderia aiabafdefinindoiari6veis com
os valores errados. Por exemplo, imagine que voc6 tenha armazenado um objeto que tenha vari6veis de instAncias
para altura e Peso. No momento em que silvar o estado do objeto, voc6 poderia .screvet a altura e o peso como
dois ints em um arquivo, mas a ordem em que voc6 os escrevesse seria crucial. Seria muito f6cil recriar o
objeto, mas trocar os valores de altura e de peso - usando a altura salva como o valor do peso para o novo objeto e vicevena-
A serializaglo lhe permite simplesmente dizer "Salve este objeto e todas as suas variiveis de instAncias". Na
verdade, 6 um pouco mais interessante do que isso, porque vocd pode adicionar'...a nio ser que eu tenha
marcado explicitamente uma vari6vel como translent, o que significa que nio 6 para incluir o valor da
vari6vel transiente como parte do estado serializado do objeto".
)
Vamos dar uma olhada nos pontos principais deste exemplo:
1. N6s declaramos que a classe Cat implementa a interf.ace Serializable. Serializable 6 uma interface marcadtra; ela
nlo tem nenhum m6todo para implementar. (Nas pr6ximas segSes, falaremos de virias regras sobre quando
voc6 precisa declarar as classes como Serializable.)
2. Criamos um novo objeto Cat, o qual, como sabemos, 6 serializ6vel.
3. Serializamos o objeto Cat chamando o m6todo writeobj ecL ( ) . Foi preciso alguma preparagio antes que
pud6ssemos de fato serializar nosso Cat. Primeiramente, tivemos de colocar todo o nosso c6digo relativo a E/S
dentro de um bloco trylcatch. Depois, tivemos de criar um FileOutputStream no qual escreveremos o objeto.
Em seguida, encapsulamos o FileOutputStream em um ObjectOutputStream, que 6 a classe que possui o m6todo
migico de serializagio de que precisamos. lembre-se de que a chamada de writeobj ect ( realba duas tarefas: )
256 Copitulo 6: Slrings, E/S, Formoioq6o e Porsing
Esse 6um exemplo simplificad o da serializagno na prhtica. Ao longo das pr6ximas p6ginas, veremos algumas das quest6es
mais complexas associadas com aserializagio.
Gr6ficos de Objetos
O que significa realmente salvar um objeto? Se as varilveis de instAncias forem todas tipos primitivos, 6 bem simples.
Mas, e seas vari6veis de instAncias forem elas mesmas refer6ncias a oQetos? O que 6 que acaba sendo salvo? Claramente,
nXo faria sentido emJava salvar o valor real de uma varilvel de refer6ncia, porque o valor de uma refer6ncia emJava s6
tem significado dentro do conrexto de uma rinica instlncia de umJVM. Em outras palavras, se voc6 tentasse restaurar o
objeto em outra instincia daJVM, mesmo que rodando no mesmo computador em que o objeto foi
originalmente serializado, a refer6ncia seria inritil.
Mas, e quanto ao objeto para o qual a referAncia aponta? Observe esta classe:
class Dog {
private Collar LheCollar;
nrirzafe inr doqSize;
public Dog(Co1lar co1lar, int size) t
thecollar = col-Iar;
doqSize = size;
)
public Coll-ar getcoll-ar() { return theCollar; }
t
nl:qq f-n]l:r f
Agora crie um Dog... Primeiramente, voc6 cria um Collar (*coleira") para o Dog:
Coffar c = new Collar(3) ;
Felizmente, o mecanismo de serializagilo Java cuida de tudo isso. Quando voc6 serializa um objeto, a seralizaglo
Java salva todo o "grifico do objeto". Isso significa uma c6pia detalhada de tudo de que o objeto salvo precisa para
ser restaurado. Por exemplo, se voc€ serializar um objeto Dog, o Collar seri serializado automaticamente. E se a
classe Collar contiver uma referencia a um outro objeto, esse outro objeto tamb6m seri serializado, e assim por
diante. E o rinico.objeto que voc6 precisa de-preocupar em salvar e testaurar 6 o Dog. Os outros objetos lggueridos
para se reconstruir completamente o Dog slo salvos (e restaurados) automaticamente, por meio da serializagio.
Mas lembrese de que vod precisa decidir ativamente se vai criar objetos qtre se6o antertaceserializiveis,
Seridizable. Se quisermos ulvar objetos Dog por er<emplo, rcremos de modificar a classe Dog da seguinte forma
)
]
Por6m, quando executarmos esse c6digo, receberemos uma exceEio de tempo de execuEio parecida com esta
java. io.NotSerializableException: Co1lar
O que foi que esquecemos? A classe Collar TAMBEM deve ser Serializable. Se modificarmos a classe Collar ea
tornarmos serializ6vel, enteo neo haverh problemas:
class Collar implements Serializable {
// mesma coisa
)
]
class Dog implements Serializable {
private Coll-ar thecollar;
258 Copitulo 6: Strings, E/S, FormotoE6o e Porsing
t
class Collar implements Serializable {
private int coflarSize;
public Co11ar(int. size) { collarSize = slze; }
nrrl-']
yuv+re in inf
rrre aat-(-nllareiual\
Yvuvvrrs!er-v\/
It rafrrrn
!eusrrr an1l:reiza. l
OU
A pr6pria classe Collar poderia referir-se a outros objetos nlo-serializ6veis e, sem conhecer a estrutura interna
2.
de Collar, voc6 nlo ter6 como fazer todos esses reparos (panindo do principio que voc6 sequer iria querer
TENTAR esse caminho).
OU
3. Se criar uma subclasse nio for uma opgXo por outros motivos relacionados ao seu projeto.
Agora n6s temos um Dog serializivel, com um Collar nlo-seializivel, mas o Dog marcou o Collar como tran-
sient; asuda6
before: collar size is 3
Exception in thread *main" java. lang.NullPointerException
E agora, o que n6s faremos?
trY {
is.defaultaeadObject () ; // s
theCollar = new Coll-ar(is.readlntO ); // 6
]
Vamos dar uma olhada no c6digo anterior.
No noso cenirio, n6s concordamos que, por qudquer que seja o motivo no mundo real, nio podemos serializar um objeto
Collar, mas queremos serializar um Dog. Para isso, iremos implementar writeObj ect ( ) e readObj ect ( ) . Ao
implementar esses dois metodos, voc€ esri dizendo ao compilador: "se alguem chamar writeobj ect ( ) ou
readobj ect ( ) em rela$o a um objao Dog use ese c6digo como parte da leitura e da escrita".
260 Copitulo 6: Strings, E/S, Formotog6o e Porsing
1. Como a maioria dos m6todos relativos a E/S, writeobj ect ( ) pode langar exceg6es. Voc6 as pode declarar
ou tratar, mas recomendamos que as trate.
2.QuandovocdchamadefaultWriteobjectO apartirdewriteobjectO,est6dizendoAjVMpararealizar
o processo normal de seri"liz4is no obieto em queitio. Ao implementar writeOb j ecE ( ) voc6 normalmente
'
rra pedir o processo normal de senahzaglo, e tambtm realbar alguma escrita e leitura personalizadas.
3. Neste caso, decidimos escrever mais um int (o tamanho de Collar) no stream que est6 criando o Dog
serializado. Voc6 pode escrever esses dados extras antes e /ou depois Qye chamar
def aultWriteobj ect ( ) . MAS... Quando frzer aleitura deles, vocA teri de ler os dados extras na mesma
ordem em que os escreveu.
4. Novamente, decidimos tratar as exceg6es, emvez de declari-las.
5. Quando chegar a hora de deserializar, defaultReadobj ect ( ) cuidar| da deserializagio normal que ocorre
se voc6 nXo implementar um m6todo readobj ect ( ) .
6. Finalmente, criamos um novo objeto Collar paru o Dog usando o tamanho que serializamos manualmente.
ffivemos de chamar readlnt (l
atpolt de te.mos cha=mado def aultRea-aoni ect ( ) , ou os dados streamed
sairiam de sincronia!)
Lembre-se de que o morivo mais comum para se implementar writeobj ect ( ) e readobj ect ( ) ocorre
quando voc6 tJm de salvar uma pafte do estado de um objeto manualmente. Se preferir, voc6 pode escrever e ler
TOOOS os seus dados voc6 mesmo, mas isso 6 bem raro. Assim, quando quiser fazer apenas parte da serializaglo/
deserializagio manualmente, voc6 DEVE chamar os m6todos def aultReadobj ect ( ) e
defaultWriteobject O para fazer o resto.
O que suscita uma outra pergunta - por que nio fazer todat as classes em Java serializiveis? Por que a classe Object
nio 6 serializ6vel? Existem algumas coisas em Java que simplesmente nXo podem ser serializadas, porque sio
especificas do tempo de execuEXo. Coisas como streams, threads, o pr6prio tempo de execugio, etc., e at6 mesmo
algumas classes GUI (que se conectam ao SO subjacente) nio podem ser serializadas. O que 6 ou nio 6 serializivel
em Java NAO cai no exame, mas voc6 precisari saber disso para serializar objetos complexos.
Isso nos traz a outra que$eo importante a respeito da serializagio... O que acontece se uma superclasse nio for marcada
como Serial i zable, mas a subclasse for? Ser6 que a subclasse ainda poder6 ser serializada, mesmo que a sua superclasse nXo
implemente S eriahnble? Imagine o seguinte:
class Animal { }
class Dog extends Animal implements Serializable {
5. O construtor finaliza.
JAVA 5 26I
Mas esrat coisas NAO acontecem quando um objeto i deniali7atlo.
Quando uma instAncia de uma classe serializivel 6
deserializada, o construtor n-o roda, e as vari6veis di instlncias NAO recebem os seus valores iniciais! pense
nisso - se o construtor fosse chamado, e / ou as variiveis de instAncias recebessem os valores contidos nas suas
decla.raE6e-s, o objeto que voc6 esti tentado restaurar voltaria ao seu estado original, emvezde voltar refletindo as
modificag6es que ocorreram ao estado.eT
4gur" momento depois da sua cria[io. Por exemplo, imagine que voc6
tenha uma classe que declare uma variivel deinstAncia e atribua a ela o valor int 3, e inclua n* mEtodo qr're
modifique o valor da variivel de instAncia para 10:
class Foo implements Serializable {
1nt num = 3;
void changeNumfl { num = 10; J
Obviamente, voc6 serializar uma instAncia de Foo tlepoh que o m6todo changeNum ( ) rodar, o valor da
se
variivel num deveri ser 10. Quando a instAncia de Foo foi des-serializada,voc| quer que avari|velnum ainda
seja 10! Otviamente, voc6 nio quer que ainicializagio (neste caso, a atribuigio do valor 3 i vari6vel num)
alontega_. Pense nas atribuig6es de construtores e de variiveis de instAncias junras, como parre de um s6 processo
de inicializagio de um objeto (e, na verdade, elas DE FATO se tornam um s6 m6todo diinicializacio em
bytecode). A questXo 6 que, quando um objeto 6 deserializado, n6s NAO queremos que a inicializigio normal
acontega. Nio queremos que os construtores rodem, e nio queremos que os valores explicitamente declarados
sejam atribuidos. Queremos apenas que os valores sejam salvos como parte do estado serializado do objeto a ser
reatribuido.
E claro que, se voc6 tiver vari6veis marcadas como transient, elas nio serio restauradas aos seus estados
originais (a nio ser que voc6 implemente defaultReadobj ect ( ) ); em vez disso, elas receberio o valor
padrio par^ o tipo de dados em questeo. Em outras palavras, mesmo se voc6 disser
class Bar implements Serializable {
transientintx=42;
)
quando a instAncia de Bar for deserializda, avari|vel x sera definida como um valor de 0. As refer€ncias a objetos
marcadas como transient. serio sempre resetadas como nu11, independentemente de se elas foram
inicializadas no momento da declaragio na classe.
EntXo,6 isso o que acontece quando o objeto 6 deserializado, e a classe do objeto serializado estende object
diretamente, ou tem APENAS classes serializiveis na sua irvore de heranga. Fica um pouco mais complexo quando a classe
serializivel tem uma ou mais superclasses nio-seializiveis. Voltando ao nosso exemplo da classe Animal nio-serializ6vel
com uma subclasse Dog seriaJizAvel:
class Animal {
nrrhl i c St-eL ri +Afvnq p6111g;
v
Pelo fato de AnimalNAO serse ialtzbvel,qualquere$ado mantido naclasse Animal, mesmo que avari6velde estado seja
herdada pelo Dog, nio seri restaurado com o Dog quando este {or deserializado! O motivo 6 que a parte (nio-serializada)
Animal deDogir6 serreinicializadaexatarrrcnte como sevoc6 estivese criando um novo Dog (emvezde deserializando
um). Isso significa que todas as coisas que acontecem com um objeto durante a construgio irio acontecer - mas
apenas is panes Animal do Dog. Em outras palavras, as variiveis de instAncias da classe de Dog serio serializadas
e deserializadas corretamente, mas as vari6veis herdadas da superclasse Animal, ni.o-serializ6vel, voltario com os
seus valores-padrio/ iniciais atribuidos, emvez de com os valores que tinham no momento da serializaEio.
Dada uma classe serializivel, rnas com uma superclasse NAO serializivel, quaisquer variiveis de instincias que a
primeira HERDAR da superclasse sereo resetadas aos valores que receberam durante a construgeo original do
objeto. Isso ocorre porque o constnrtor da classe nio-serializivel IRA rodar!
Na verdade, todo construtor ACIMA do construtor da primeira classe nio-serializixeltamb6m rodar6, de uma
forma ou de outra, porque, depois que o primeiro construtor for chamado, ele obviamente chama o seu super
construtor, e assim por diante na Lrvore de heranga.
Para o exame, voc6 dsver6 ser capaz de reconhecer quais vari6veis serlo restauradas com os valores apropriados, e quais nio
serio, quando um objeto for deserializado, entio, certifiqtrese de e$udar o seguinte c6digo de o<emplo e a sua saida:
import java.io.*;
class SuperNotserial {
public static void main(String [] args) {
262 Copilvlo 6: Slrings, E/S, FormotoE6o e Porsing
try {
os.writeobject (dr ;
os. close O ;
ois.closeO;
) catch (Exception e) { e.printStackTraceO; }
)
)
class Dog extends Animal implements Serializable
(l- ri rn n:ma .
Dog(int w, String n) i
weight = w; / / l:erdado
name = ni / / ndo herdado
)
)
nl aqc Anim:] I / / ndo serializ6ve-
int weight = 42;
]
que produz esta saida:
before: Fido 35
afLer: Fido 42
O ponto principal aqui 6 que, pelo fato de Animal nio ser serializ6vel, o seu construtor rodou e resetou a variivel
weight de Dog, herdada de Animal, quando Dog foi deserializado.
AOTRABALHO
Por mais que s/aflcil ucreuer aidigo de rcrialiqagdo, poden ocotrer problemas referentes is uersdes das clasxs, no mando real, Se uoed sahar
un objxo Dog usando uma uersdo da clare, mas tentar dueialiqti-/o usando uma aertio dferente, mais noua, o procero poderdfalhar.
Consalte a API Jaua para nais detalhet sobre questdet e solugdes rgferentes a uercb-et de clasw.
I j ava . ut i I . Dat,e A maior pane dos m6todos desta classe foram depreciados, mas voc6 pode us6-la como uma
ponteentreasclassesCalendar eDate Format.UmainstAnciadeDate representaumadataehoramut6veis,
at6 a resoluglo de milisegundos.
I java.util.Calendar Estaclasseforneceumagrandevariedadedem6todosquelhe $ltdama
converter e manipular datas e horas. Por exemplo, se quiser adicionar um m6s a determinada data, ou descobrir
em que dia da semana vai cair 1o de janeiro de 3000, os m6todos da classe Calendar estio ai para isso.
I j ava. text . DateFormat Esta classe 6 usada paraf.ormatar datas nio apenas fornecendo virios estilos
como "01/01 /70" ov"January l, 1970", mas tamb6m paraformatar datas para diversos locais em todo o mundo.
I java. text.NumberFormat Esta classe 6 usada para f.ormatar nrimeros e moedas para diversos
loacis em todo o mundo.
I java.util.Locale Esta classe 6 usada em conjunto com DateFormat e NrunberFornrat para
formatar datas, nri.meros e moedas para locais especificos. Com a ajuda da classe Locaf e vocd poderi converter uma
data como "10/08/2@5" para "Segunda-feira, 8 de Outubro de2@5" instantaneamente. Se quiser manipular datas sem
produzir output formatado, vod poderi usar a classe Locale diretamente com a classe Calendar.
uso relacionados a datas e n/rmeros, al6m de solug6es usando-se essas classes. A Tabela 6-2 com certeza suscitari
dfvidas especificas sobre determinadas classes, e iremos mergulhar nos detalhes de cada classe em seguida.
Depois de ler as explicag6es detalhadas sobre as classes, voc6 dever6 perceber que a Tabela 6-2 oferece um bom
resumo.
A Classe Date
A classe Date tem um passado nebuloso. O projeto da sua API nXo fazia um bom trabalho ao lidar com situag6es de
^est jdo
internacionalizagio e de localizagio. No seu atual, a maioria dos seus m6todos foram depreciados e, pari a maioria
das situag6es, vocA usari a classe Calendar em vez da classe Date. A classe Date est6 no exame por v6rios motivos: voc6
poder6 encontr6-la em c6digos antigos; ela 6 bem ficil de usar, caso tudo o que voc6 queira seja uma forma ripida de se
obter a data e a hora atuais; 6 ritil quando voc6 quer uma hora universal que nio seja afetada por fusos horirios e,
finalmente, voc6 a usar6 como uma ponte temporiria para formatar um objeto Calendar usando a classe DateFormat.
Como mencionamos rapidamente acima, uma instAncia da classe Date representa uma s6 data e uma s6 hora.
Internamente, data e hora silo armazenadas como um tipo long primitivo. Especificamente, o long
nimero de milisegundos (voc6 sabe, sio 1000 deles por segundo), entre a data sendo representada ^rmazenao
e 10. de janeiro
det970.
J6 parou para pensar em como os nrimeros sXo grandes? Vamos usar a classe Date para descobrir quanto tempo
demorou para passar um trilhio de milisegundos, comegando em Lo. de janeiro de 1970:
'imnnrl- i:rra rrl- i l *.
a1:ec m6ern=f66 {
public static void main(String[] args) {
Date d1 = new Date(1-000000000000L); // um trilhSol
System.out.println("1st date " + d1.tostrinS() ) ;
JAVA 5 265
class Test.Dates {
public static void main(String[] arqs) {
Date d1 = new Date(1000000000000L) ; / / um trilhdo!
System.out.println("1st date ,, + d1 .tostrinSO );
dl.setTLne(dl.getTime() + 350000O); /| 3600000 milisegundoE / hora
Sygtem.out.printLn($new time .' + dl.toString() ) ;
$epare que tanto setTime ) quanto . getrime ) usam a 6til escala dos milisegundos... Se vocA quiser manipular
( (
datas usando a classe Date, essa 6 a sua rinica opgio. Embora isso nio seja muito aborrecimento, imagine a diversio
que seria se voc6 precisasse adicionar, digamos, um ano a determinada data. N6s voltaremos ) classe Date mais
adiante, mas, por agora, arinica coisa que voc6 precisa saber 6 que, se quiser criar uma instAncia de Date para
representar "agora", voc6 usa o construtor sem argumentos de Date:
Date now = new Dateo;
(Pela nossa estimativa, se voc6 chamar now. getrime (), ir6 receber um nrlrmero entre um trilhio e dois trilh6es.)
A Classe Calendar
Acabamos de ver que manipular datas usando a classe Date 6 complicado. A classe Calendar foi elaborada Dara tornar
a manipulagio de datas maii f6cil! (Bem, pelo menos mais f6cil que Date.) Embora a classe Calendar tenha^milh6es de
campoi e m6todos, depois que'ttocA pegai o jeito de algumas delis as outias tendem a funcionar de forma semelhante.
Quando t_entar usar a classe Calendar pela primeira vez, poderi perceber que ela 6 uma classe abstrata. Nio 6
possivel dizer
Calendar c = new Calendaro; // inv6l-ido, Calendar 6 abstrata
Para poder criar uma instAncia de cal-endar, voc6 precisa usar um dos m6todos estAticos sobrecarregados
dafTncfanno I \.
Certo, agora que n6s temos uma instAncia de Calendar, vamos voltar ao nosso exemplo anterior e descobrir em
que dia da semana caiu o nosso trilion6simo milisegundo, e depois vamos adicionar um mAs a essa data:
imnnrl- iarra rrf i l *-
class Dates2 {
public static void main(String[] args) {
Date d1 = new Date(1000000000000L);
(rr<t-am
eJJuelr.vuu.!,rIIILIII\ ln/$1^t I-L i-ts^
uqLC r\ T
+ UI
A1 .LvJL!IttV\r
F^ef rira/\ \.
^rrf ^-;hf r,
Calendar c = Calendar.getlnstanceO ;
266 Copitulo 6: Sirings, E/S, FormotoE6o e Porsing
e.setTine(d1); ll #L
2. Usamos o campo strNDAY de Calendar para determinar se, para a nossaJvM, suNDAY ("domingo") 6 _
considerado cbmo o primeiro dia da semana (em alguns locais, MoNDAY -"segunda-f.eira"- 6 considerada o
primeiro dia da semana). A classe Calendar fornece campos semelhantes para dias da semana, meses, o dia do
m6s, o dia do ano e assim por diante.
3. IJsamos o campo DAY-OF-WEEK para descobrir o dia da semana em que caiu o trilion6simo milisegundo.
4. At6 aqui, usamos m6todos serter e getter que lhe devem ser de f6cil entendimento. Iremos agora usar o m6todo
add ( ) de Calendar. Esse m6todo bastanie poderoso lhe permite adicionar ou subtrair unidades de tempo
apropriadas para qualquer campo de Calendar que voc6 especificar. Por exemplo:
c.add(Calendar.HOUR, -4) ; // subtrai 4 horas do valor de
c.add(Calendar.YEAR, 2) ; // adicj-ona 2 anos ao valor de
c . add (Calendar. DAY_oF_WEEK, -2); // subtrai dois dias do
// valor de c
5. Convena o valor de c de volta em uma instAncia de Date.
O outro m6todo de Calendarquevoc6 devericonhecerparao exame6 ro11( ). O m6todo ro11( ) agecomo o
m6todo add ( ) , exceto pelo fa^to de que, quando uma pafte de um Date 6 incrementada ou diminuida, panes
maiores do Date em queltio nlo serlb inirementadas bu diminuidas. O qu6? Por exemplo:
// asqrrma mrec 6 8 de outubro de 2001
c.rol](Calendar.MONTH, 9); // repare no ano da saida
Date d4 = c.getTimeO;
System.out.print]n("new date " + d4.tostringO );
A saida seri algo como
new date Fri .Tu1 0B 19:46:40 MDT 2001,
Repare que o ano nio mudou, embora tenhamos adicionado 9 meses a uma data de outubro. De forma
semelhante, chamar ro11 ( ) com HOUR nio modifica a data, nem o m6s e nem o ano.
Para o exame, voc6 nio teri de memorizar os campos da classe Calendar. Se precisar deles para ajud6Jo a re-
sponder uma pergunta, eles serio fornecidos na pr6pria pergunta.
A Classe DateFormat
Tendo aprendido como criar e manipular daras, vamos descobrir como format6-las. Para estarmos todos
sincroniiados, eis um exemplo de como uma data pode ser formatada de diferentes maneiras:
import java.text.*;
import java.util. ";
JAVA 5 267
cl-ass Dates3 {
public static void main(String[] args) {
for(DateFormat df : dfa)
q\/qf am nrrl- nri
vJvuelrtvuL.v!fllLrrr\u! nl- l n ldf f nm:f /Al \ \ .
\sr/ /,
Sep B, 2001
9/B/0L
Sep 8, 2001
Septemlcer 8, 2001
Saturday, September 8, 200L
Examinando esse c6digo, percebemos algumas coisas logo de cara. Primeiramente, parece que DateFormat 6
mais uma classe abstrata, enteo nio podemos usar new p^ra criar instAncias de DateFormat. Neste caso,
usamos dois m6todos de fLbica, qetlnstance ( ) e getDatefnstance ( ) . Repare que
getDatelnstance ( ) est6 sobrecarregado; quando e$udarmos os locais, veremos a o:urra versio de
getDatelnstance ( ) que voc6 precisar6 conhecer para o exame.
Em seguida, usamos campos estiticos da classe DateFormat para personalizar as nossas virias instlncias de
DateFormat. Cada um desses campos e$6ticos representa um estilo de formataglo. Neste caso, parece que a verseo
sem argumentos de getDatelnstance ( ) nos d6 o mesmo estilo que a verseo MEDIUM do m6todo, mas essa
nio 6 uma regra geral. (Mais sobre isso quando discutirmos os locais.) Finalmente, usamos o m6todo f ormat ( )
para criar Strings representando as vers6es devidamente formatadas daData com que estamos trabalhando.
O riltimo m6todo com o qualvoc6 deve se familiarizar6parse O. O m6todo parse ( ) usauma String
formatada no estilo da instAncia de DateFormat sendo usada, e converte a String em um objeto Date. Como voc6
pode imaginar, essa 6 uma operagio arriscada, porque o m6todo parse ( ) poderia facilmente receber uma String
mal formada. Por causa disso, parse ( ) pode langar uma ParseException. O seguinte c6digo cria uma
instAncia de Date, usa DateFormat. f ormat ( ) para convertd-la em uma String e depois usa
DateFormat . parse ( ) para transformi-la de volta em Date:
Date d1 = new Date(1000000000000L);
System.out.printl-n("d1 = " + d1.toStringO);
DateFormat df = DateFormat.qetDatelnstance(
DateFormat. SHORT) ;
String s = df.format(d1);
System. out.print.ln ( s ) ;
trv {
Date d2 = df.parse(s);
System.out.printfn("parsed = " + d2.toString( )) ;
AO TRABALHO
A API para DateFormat.parse( explica que, porpadrio, o mdtodo parse ( ) d ben to/erante ao faqerparsing de datat. Pela nosa
expeilncia, parseQ ndo i tdo tolerante a retpeito daforraatagdo de Strings que insere com Jilcestl em datas; cuidado ao usar esse nitodo!
A Classe Locale
Anteriormente, n6s dissemos que uma das raz6a principais para a exist6ncia deste obj eilo era paratestar a sua capacidade
de realizar algumas tarefas bisicas de internacionalizagio. A sua espera acabou: a classe Locale 6 a sua passagem para a
dominagio do mundo. Tanto a classe DateFormat quanto a NumberFormat (sobre a qual falaremos em segurda) podem
usar uma instincia de Locale para personalizar uma saida formatada para que ela se adapte a determinado local. Voc6 poderia
perguntar, comoJava define um local? A API diz que um local 6 "uma regiio geogrifica, politica ou cultural especifica". Os
dois corutrutores de Locale quevocA precisari conhecerparao exame sio
Locafe (String lingua)
Locale (String lingua, String pais)
O argumento lingua representa um C6digo de Linguagem ISO 639, de modo que se voc6 quiser formatar as suas
datas ou ndmeros em Walloon (ingoa usada no sul da B6lgica), por exemplo, voc6 usaria "wa" como a sua string
para alingta. Existem mais de 500 c6digos ISO, incluindo um para Klingon ("tlh"), embora Java ainda nXo
oferega suporte ao local Klingon, infelizmente. N6s pensamos em dizer que voc6 teria de memorizar todos esses
c6digos para o exame... Mas nlo queriamos causar nenhum ataque cardiaco. Entio fique tranqiiilo, voc6 nio teri
de memorizar nenhum C6digo de Linguagem ISO, nem c6digos de paises ISO (dos quais existem cerca de 240)
Para o exame.
Vamos voltar ao modo de usar esses c6digos. Se voc6 quiser representar o italiano bisico no seu aplicativo, tudo
de que precisa 6 o c6digo dessa lingua. Se, por outro lado, quiser representar o italiano usado na Suiga, voc6
indicaria esse pais (sim, o c6digo de pais para a Suiga 6 "CH"), mas que a lingua 6 o italiano:
Locale locPT = new Locale("it"); // Italiano
Locale locBR = new Loca]e("it", "CH"); / / Suisa
IJsar esses dois locais em uma data poderia nos dar uma saida como estai
sabato 1 ottobre 2005
sabato, 1. ottobre 2005
Agora, vamos juntar tudo isso em um c6digo que criar6 um objeto Calendar, definir6 a sua data, e depois o
converter6 em um Date. Depois disso, pegaremos o objeto Date e o exibiremos usando diversos locais do mundo:
Calendar c = Calendar.getlnstance (l ,.
DateFormat . FULL ) ;
System.out.print.ln("US fu11 .' + dfUSfull.format(d2) );
DateFormat.FULL, l-ocPT) ;
Svsl-om orrl- nrinl- 'l n1.'p^rfrraal '. + rlfp.n f^.lm^l-//lrl\v-t )
I t
DateFormat.FULL, l-ocBR) ;
Japan 2010?12?1,4?
Opa! A nossa m6quina nio est6 configurada para dar suporte a locais da india ou do Japio, mas o obietivo do
exemplo era mostrar com um mesmo objeto Date pode ser formatado para funcionar par^ v6rios locais.
def Brazil
loc Brasi-1
def Danish
loc dansk
D>I danese
Dado que o local da nossaJVM (o padrio, para n6s) 6 us @stados Unidos), o padrio pan o Brasil 6 "Brazil",
e o padrio para a lingua dinamarquesa 6 "oanish". No Brasil, 6. claro, o pais se chama "Brasil " e, na
Dinamarca, a lingua 3 chamada de "dansk". Finalmente, s6 por diverslo, descobrimos que, na Itilia, alingua
dinamarquesa 6 chamada de "danese".
A Classe NumberFormat
Terminaremos este objetivo falando sobre a classe NumberFormat. Assim como a classe DateFormat,
NumberFormat 6 abstrata, de modo que normalmente voc6 usar6 alguma versio ou de getlnstance ( ) ou de
getcurrencyf ns tance ( ) para criar um objeto NumberFormat. Nio 6 surpresa que essa classe seja usada para
formatar nrimeros ou valores monetArios:
fLoat f1 = L23.4567f:
Locale locFR = new Locale('fr"); / / Er^rra
for(NumberFormat nf : nfa)
qlrqlam arrf nrintlnlnf fnmal /f1 ) ).
L23 .457
t23 ,45'7
>J_ZJ .40
rz5 ,40 !
Nio se preocupe se, como no nosso caso, o seu sistema nio estiver configurado para exibir os simbolos do franco,
da libra esterlina, da rupia, do yen, do baht ou do dracma. Nlo ser6 esperado que voc6 conhega os simbolos
usados para moedas: se voc6 precisar de um, ele seri especificado na questAo. Voc6 poder6 encontrar m6todos
diferentesdeformat noexame.Eisumpequenoc6digoqueusagetMaximr:rnFractionDigits(),
setMaximurnFractionDigits ( ),parse ( ) e setParseTntegerhly( ) :
float f1 = L23.45678f;
NumberFormat nf = NunberFormat.getlnstance( ) ;
System.out.print(nf .getMaximumFractionDigtits ( ) + " ") ;
System.out..print(nf .format(f1) + " ";;
nf . setMaximrunFract ionDigits (5 ) ;
3 I23.457 L23.45678
t234.567
t234
Repare que, neste caso, o nfmero inicial de digitos fracion6rios para o NumberFormat padrio 6 de tr€s, e que o
m6todo format O arredonda o valor de f 1, emvez de simplesmente descaftar as casas decimais excedentes.
Depois de modificar os digitos fracionirios de nf , o valor inteiro de f 16 exibido. Em seguida, repare que o
m6todo parse ( ) deve rodar em um bloco try/caLch e que o m6todo setParserntegeronly ( ) usa um
valor booleano e, neste caso, f.az as chamadas subseqiientes a parse ( ) retornarem apenas a parte inteira das
Strings formatadas como nrimeros de ponto flutuante.
ji
Como vimos, v6rias das classes abordadas neste objetivo sXo abstract. Al6m disso, para todas essas classes, a
frrncionalidade principal de cada instAncia 6 estabelecida no momento da cria$o. A Tabela 63 resume os construtores ou
m6todos usados para criar instAncias de todas as classes que discutimos nesta segio.
regularesparacorresponddncia(linitadosa:.(ponto),x(asteisco),+(nais),?,\/,\1,\r,[],0).Oasode+,*e?serilimitadoa
qaantifcadoresgananciosos, e o operadorpar4nteses serd audo @enas coml am mecanismo de agruparuento, e ndopara c@tararconteildo
dtrante a determinagdo da correspond1ncia. Para streams, escreuer cddigo usando as classes Foraatter e Scanner e os mdtados
PrintViter.format/prinf. Reconhecer e usarpardmetros defornatapio (linitados a: ohy' o/oc,
%d, W ohs)
en Stingt deformatos.
272 Copitulo 6: Sirings, E/S, Formoioqdo e Porsing
Comegaremos com mais um aviso: esta pequena segio nio vai lhe transformar de iniciante em regex em guru de
regex. Nesta segio, abordaremos tr0s id6ias bisicas:
I Encontrar coisas VocA tem montes de texto onde precisa procurar algo.Talvez esteja fazendo uma
selegio de tela, talvez esteja lendo de um arquivo. De qualquer modo, voc6 precisa de maneiras ficeis para
encontrar agulhas textuais em um palheiro tixtual. IJsaremos as classes java.regex.Pattern, java.regex.Matcher e
java.util.Scanner para nos ajudar a encontrar coisas.
I Tokenizar coisas VocA tem um arquivo delimitado do qual deseja extrair alguns dados riteis. VocA quer
transformar um pedago de texto que se parece com "1500.00,343.77,t23.4" em algumas vari6veis float individuais.
N6s iremos lhe mostrar os fundamentos do uso do m6todo String. split ( ) e da classe java.util.Scanner para
tokenizar os seus dados.
r Formatar coisas VocA precisa criar um relat6rio e transformar uma variivel float com um valor de
32500.000f em uma String com um valor de "$32,500.00". N6s lhe apresentaremos a classe java.util.Formatter
e os m6todos printf ( ) e format ( ).
Um Tutorial de Busca
Esteja voc€ procurando por coisas ou tokenizando coisas, muitos dos conceitos sio os mesmos, enteo comecemos
pelo bisico. Nio importa linguagem que voc6 esteja usando, mais cedo ou mais tarde provavelmente iri se
deparar com a necessidade de realizar buscas em grandes quantidades de dados textuais, procurando por coisas
especificas.
As express6es regulares (abreviadas como regex) sio um tipo de linguagem dentro da linguagem, elaboradas para
ajudar os programadores nessas tarefas de buscas. Toda linguagem que fornece fung6es regex usa um ou mais
mltnres regex. Os motores regex f.azem buscas atrav6s de dados textuais usando instrug6es que sio programadas em
expressdu.IJma expressio regex funciona como um pequeno programa ou script. Quando voc6 chama um motor
regex, voc6 passa a ele os dados textuais que quer processar (em Java, ser6 normalmente uma String ou um stream),
e passa tamb6m a expressio que deseja usar para procurar nos dados.
E apropriado pensar em regex como uma linguagem, e nos referiremos a ela dessa forma ao longo desta segio.
A linguagem regex 6 usada para criar express6es e, i medida que formos avangando nesta segio, sempre que
falarmos sobre express6es ou sobre a sintaxe das express6es, estaremos falando sobre a sintaxe da "linguagem"
regex. Ah, e mais um aviso: sabemos que os leitores especialistas em regex sio capazes de criar express6es
melhores do que as que iremos apresentar. Tenha em mente que, no geral, estaremos criando essas express6es
usando apenas uma parte do conjunto total de instrug6es regex, muito obrigado.
Buscas Simples
Para o nosso primeiro exemplo, gostariamos de buscar na seguinte Stringfonte
abaaaba
por todas as ocorrAncias (ov con'eEondincia) da expressdo
ab
Em todas as explicag6es, assumiremos que as nossas fontes de dados usam indices que comegam no zero, de modo
que, se aplicarmos um indice )s nossa string fonte, obteremos
fonte: abaaaba
indices : 0i-23456
Podemos ver que temos duas ocorr6ncias da expressio ab: uma comegando na posigXo O e outra comegando na
posigio 4. Se envi6ssemos esses dados-fonte e essa expressio para um motor regex, ele responderia nos dizendo
que encontrou correspond€ncias nas posig6es 0 e 4:
imnarf iarr: rrt. i l . regex. x;
cl-ass Regexsmall {
public static void main(String [] argrs) {
Pattern p = Pattern.compile( "ab") ; / / a expressdo
Matcher m = p.matcher("abaaaba"); / / a fonLe
boolean b = false;
while (b = m. find( ) ) {
System.out.print(m.startO + " ");
]
)
JAVA 5 273
]
Isso produz:
04
Nio iremos explicar esse c6digo imediatamentg. Daqui a algumas p6ginas, iremos lhe mosrar muitos outros c6digos reger,
mas, primeiramente, queremos passar alguma sintaxe regex. Depois que voc6 entender um pouco mais sobre regex, os c6digos
de e<emplo fario muito mais sentido. Eis um exemplo mais complicado de uma fonte e uma e4pressio:
fonte: abababa
l_n(I]-ces i urz345b
express5.o: aba
Quantas ocorrencias teremos neste caso? Bem, claramentehi uma ocorr6ncia comegando na posigXo O, e outra
comegando na posiEio 4. Mas e quanto )quela que comega na posigio 2? Em geral, no mundo regex, a string aba
que comega na posigio 2 nio serh considerada uma ocorrdncia v6lida. A primeira regra geral de busca regex 6
Emgera/, uma basca regex roda da uquerdapara a direita e, dEoh que am caracter dafonte tenba sido usado em ama ocorr€ncia, e/e ndo
pode ser reatiliqado.
Assim, no nosso exemplo anterior, a primeira correspondAncia usou as posig6es 0, I e 2 para bater com a
expressXo (outro termo comum para isso 6 que os tr6s primeiros caracteres da fonte foram consumidor). Pelo
fato de o caracter da posigio 2 ter sido consumido na primeira correspond€ncia, ele nio p6de ser usado
novamente. Entio o motor seguiu em frente, e nio achou outra ocorrAncia de aba at6 chegar i posigio 4.
Essa 6 a maneira tipica como um motor de correspond6ncia regex funciona. Entretanto, daqui a algumas
p6ginas, veremos uma excegio ) primeira regra que escrevemos acima.
Entio, achamos correspond6ncias para stringsexatas, mas o que fariamos se quis6ssemos encontrar algo um
pouco mais dinimico? Por exemplo, e se quis6ssemos encontrar todas as ocorr6ncias de nrimeros hexadecimais,
ou nrimeros de telefone. ou CEPs?
\d
Se modific6ssemos o programa anterior para aplicar a expressio \d i seguinte string fonte
fonte': aI2c3e455f
indice: 0123456189
regex nos diria que achou digitos nas posig6es !,2, 4, 6,7 e 8. (Se quiser tentar isso em casa, voc6 teri de "escapar"
o argumento "\d" do m6todo compile, transformando-o em "\ \d", mas falaremos mais sobre isso logo
adiante.)
Regex fornece um rico conjunto de metacaracteres que vocA pode encontrar descritos na documentagio API para
.|ava.util.regex.Pattern. Nio os discutiremos todos aqui, mas descreveremos aqueles de que voc6 precisari para o exame:
\d Umdigito
\s Um caracterde espago em branco
\w (Jm caracterde palavra (letras, digitos ou "-" (underscore))
VocA pode especificar tamb6m conjuntos de caracteres a serem procurados, usando colchetes; e intervalos de caracteres a
serem procurados, usado colchetes e um hifen:
fal-rcl Procrrra :ncnas nor a's . l-r's ou c'S
[a-f] procura apenas pelos caracteres a, b, c, d. e ou f
Al6m disso, voc6 po* procurar em diversos intervalos de uma s6 vez. A seguinte expresslo busca por ocorrOncias das letras
a- f ou A- F, mas NAO procura por uma combinagSo fa:
274 Copltulo 6: Strings, E/S, FormoioE6o e Porsing
AO TRABALHO
Aldn das fungdet descritas para 0 examq uocd pode tanbdm aplicar os seguintes atribatos a conjuntos e interualos dentro de cobhetes: '^"
para negar os caracteres especifcados, colchetes aninhados para criar ama anido de corgiuntos e "&.&" para especifcar a internpdo de
conjantos. Embora esrr,s clnstratlres ndo caiam flo exane, e/es sdo bastante ilteis, e bons exemplos deles poden ser encontrados na API para
a c/asse jaua. ati /. regex.Pattern.
A outra questlo que isso suscita 6 que, quando estamos buscando por algo cuja extensio seja vari6vel, obter apenas uma
posigio inicial como valor de retorno tem pouco valor. EntXo, al6m de retornar posig6es iniciais, uma outra
informagio que um motor regex pode retornar 6 a correspond6ncia inteira, ou o grupt, que encontrar.
Modificaremos a forma como falamos sobre o que regex retorna, especificando cada retorno na sua pr6pria linha,
lembrando que agora, para cada retorno, receberemos de volta a posigio inicial E depois o grupo:
fonte:. "1, a72 234b"
padrdo: \d+
VocA pode ler essa expressio como: "Encontre um ou mais digitos seguidos". Essa expressi,o produz a
seguinte saida regex
01
J IZ
6 234
VocA pode ler isso como "na posigio 0 hi um numero inteiro com o valor de 1; depois, na posigao 3, hi um
nrimero inteiro com um valor de 12, e depois, na posigio 6, h6 um nrimero inteiro com um valor de 234".Yoltando
agora ao nosso problema com hexadecimal, a riltima coisa que precisamos saber 6 como especificar o uso de um
quantificador para apenas uma parte de uma expresseo. Neste caso, precisamos ter exatamente uma ocorrAncia de
0x ou 0X, mas podemos ter de uma a muitas ocorr6ncias dos "digitos" hexa que se seguem. A seguinte expresseo
adiciona par6nteses para limitar o quantificador '+ " a apenas digitos hexa:
0 [xx] ( t0-9a-fA-Fl )+
Os parOnteses e " + " ampliam a expressio anterior ao dizer, na priltica "Depois que acharmos o nosso 0x ou 0X,
voc6 poder6 encontrarde uma a muitas ocorr6ncias de digitos hexa". Repare que colocamos o quantificador "+"
no final da expresslo. E 6til pensar nos quantificadores como estando sempre quantificando a parte da expressio
que os Preceoe.
[ ^abc ]
Entio, armados com o operador ^ e o quantificador * (nenhum ou mais), podemos criar o seguinte:
projl([^,])*
Se aplicarmos essa expressio apenas ao pedago do arquivo de texto que listamos acima, o regex retorna
lll nr^r le.ha.l ndf
25 projl
A principal parte dessa expressio 6 a que diz"me retorne zero ou mais caracteres que nio sejam urna virgula." O
riltimo exemplo de quantificador que iremos ver 6 o ? (um ou nenhum). D,igamos.que.a nossa tarefa agora se1.a .
procurar, em um arquivo de texto, por qualquer coisa que possa ser um nimero de telefone local, com sete digitos.
Iremos dizer, arbitrariamente, que, se encontrarmos ou sete digitos em seqiiAncia ou tres digitos seguidos de um
hifen (ou um espago) seguido de outros quatro digitos, entio temos um candidato. Eis alguns exemplos de
nrimeros de telefone "vilidos":
r234567
),23 456'7
123-4567
A chave para se criar essa expressio 6 perceber que precisamos de "uma ou nenhuma ocorr6ncia ou um espago ou
um hifen" no meio dos nossos digitos:
\d\d\d( [-\s] 1 ?\d\d\d\d
O Ponto Pr6-definido
Al6m dos metacaracteres \s, \d e \w que ji vimos, voc6 tamb6m precisar6 entender o metacaracter "."
(ponto). Quando vir esse caracter em uma expressio regex, ele significa "qualquer caracter serve". Por
exemplo, a seguinte fonte e o seguinte padrio
fonte: "ac abc a c"
padrdo: a.c
produzirio a saida
3 abc
7 ac
O "." foi capaz de encontrar tanto o "b" guanto o " " nos dados-fonte.
Quantificadores Gananciosos
Quando voc6 usa os quantificadores '!, + e ?, 6 possivel ajust6Jos mais detalhadamente para produzir um
comportamento que 6 conhecido como "ganancioso", "relutante" ou "possessivo". Embora voc6 precise entender
apenas o quantificador ganancioso para o exame, iremos apresentar tamb6m o quantificador relutante para servir de
base para comparagio. Primeiramente a sintaxe:
terminem com xx". Antes de lhe dizermos o que acontece, queremos que voc6 pelo menos considere que existem
dois resultados plausiveis... ser6 que voc6 consegue dizer quais sio eles? Lembre-se de que dissemos anteriormente
que, em geral, os motores regex atuam da esquerda para a direita e que eles consomem os caracteres ) medida que
os usam. Assim, trabalhando da esquerda para a direita, poderiamos prcver que o motor buscaria os quatro
primeiros caracteres (0 - 3), encontraria xx comegando na posigio 2, e teria ai a sua primeira correspond6ncia.
Entio, seguiria em frente e encontraria o segundo xx comegando na posigio 6. Isso nos levaria a um resultado
como este:
0 yyxx
4 xyxx
lJm outro argumento plausivel 6 que, uma vez que pedimos um conjunto de caracteres que termine com xx,
poderiamos receber um resultado como este:
0 yyxxxyxx
A maneira como pensamos nisso 6 considerando o adjetivo ganancioso. Par.a Qye. a segunda resposta esteja correta, o
motor regex teria que olhar (gananciosamente) em todo o conjunto-fonte de dados para poder determinar que havia
um xx no final. Entlo, na realidade, o segundo resultado 6 o correto, porque, no exemplo original, n6s usamos o
quantificador ganancioso 's. O resultado que encontra dois conjuntos diferentes pode ser gerado usando-se o
quantificador relutante *?. Novamente:
fonte: l lxxxyxx
padrdo: . *xx
aqui se est6 usando o quantificador ganancioso 'r-, com o resultado
0 llzxxxyxx
Se modificarmos o padrio para
fonte: l44xxxyxx
padrSo: . *?xx
agora estaremos usando o quantificador *?, e receberemos o seguinte:
0 yyxx
4 xyxx
O quantificador ganancioso de fato 16 todo o conjunto-fonte dos dados, e depois volta (procuradadireitaparaa
esquerda) at6 achar a corresponddncia mais i direita. Nesse momento, ele inclui tudo o que existir nos dados-fonte
at6 (e incluindo) os dados que fazem pane da correspond6ncia mais ) direita.
AO TRABALHO
Exixem maitos outms aspectos referentes a quantifcadores regex do qlrc 0s qtle discutimos aqut, rzasj,i abordamos mais do qae o rufciente
para o exame. A Sun ten diuersos tutoriais que lbe ajudardo a aprender mais sobre os quantificadoru e a tomd-/o o guru em quantficadores
no sea ambiente de trabalbo.
AO TRABALHO
A linguagen Jaua defne diuersas seqii1ncias de uc@q inclaindo
\b = backspace
\t = tab
E oilras, que uocd poderi encontrar na Etpecifcagdo da Linguagen Jaua. Fora uma euentual apaipdo dc um \n dentro de una String uoci
ndo precisard v preocupar com seqi.i4ncias de ucape Jaaa no exame.
Neste ponto, ji aprendemos o suficiente sobre a linguagem regex para comegar a us6-la em nossos programasJava.
Comegaremos e$udando o uso de express6es regex para encontrar coisas, e depois passaremos para um t6pico
intimamente relacionado, que 6 o de tokenizar coisas.
while(b = m.findO) {
System.out.printl-n(m.startO + " " + m.groupO);
]
Esse programa usa o primeiro argumento de linha de comando (args t 0 J ) para representar a expresslo regex que
voc6 deseja usar, e usa o segundo argumento (arqs [ 1 J ) para representar os dados-fonte em que voc6 deseja
procurar. Eis uma execugeo de teste:
% java Regex "\d\w" "ab4 56_'7ab"
Isso produz a saida
Pattern is \d\w
456
278 CoplIulo 6: Slrings, E/S, FormotoE6o e Porsing
(Lembre-se de se voc6 quisesse ter essa expressio representada em uma String, use \ \d\ \w) . Pelo fato de que.
ireqiientemente ter6 car"cte.es especiais ou espago, .m bmnco como parte dos setrs argumentos, provavelmente 6 uma boa
id6ia que voc6 se habitue a sempri colocar seus argu-entos entre aspas. Vamos dar uma olhada no c6digo com-mais
detallres. Primeiramente, perceba que nio estamos usando new para cri ar umPattern: se voc6 verificar a API, nio
encontrar6 quaisquer conitrutoreJlistados. Voc6 usarl o m6todo est6tico sobrecarregado.compile ( ) (que usaString
e>pressio;) para criar uma instAncia de Paftern. Para o exame, tudo o que voc6 precisari saber para criar um Matcher 6
usar o m6todo Pattern . matcher ( ) (que usa String sourceData)'
Om6todomaisimportantedesteprograma6tinaO.Esse6om6todoquedefatoiniciaomotorregexerealizaa
busca. O m6todo f inO ( ) retorna true caso ache uma correspondAncia, e memoriza a posigio inicial dessa
correspondAncia. Se f ind O retornar true, voc6 pode chamar o m6todo start ( ) para obter a posigXo
inicial da correspond6 ncia, e pode chamar o mbtodo group ( ) para obter a string que representa o pedago
propriamente dito dos dados que foi encontrado como correspondOncia.
AO TRABALHO
(Jm motiuo clmum para se asar regex i para realiqar operagdes de busca e substitaipdo. Embora as operagdu de nbstitaipdo ndo caiam no
exame, uoc€ deueni nber que a classe Matcherfomece diuersos ndtodos qae realiqan operagdu de busca e de substituipio. Consulte os mitodos
appendReplacement ( ), appendTail ( ) e replaceAll O na API d.e Matcberpara nais detalbes.
AclasseMatcherlhepermiteprocuraremzubconjuntosdosseusdados.fonteusandoseumconceitochamado regdes.Naida
real, as regi6espodemmelhorarsubsancialmente odesempenho, masvod n1oprecisadsabernadasobreelasparao exame.
Buscando com a Classe Scanner Embora a classe java.util.Scanner sirva principalmente para tokenizar dados (sobre o
que falaremos em seguida), ela pode tamb6m ser usada para encontrar coisas, assim como as classes Pattern e Matcher.
Embora Scanner nio fornega informagSes de localvaglo nem recursos de busca e substituigio, vocA pode us6-la para aplicar
express6es regex a dados-fonte para the dizer quantas instAncias de uma expressio existem em determinado conjunto de
dados. O seguinte programa usa o primeiro argu.mento de linha de comando como uma expressio regex, e depois pede
por input usando System . in. Ele exibe uma mensagem sempre que uma correspond6ncia| encontrada:
imnnrl- iarra rrf il *.
class ScanIn {
public static void main(String[] args) t
q\/<|-am nrrl-
rJousrrL.vuu.vrfare\ nrinl- f \\innl1f
frlvue. . t\\.
/,
Lrv {
Scanner s = new Scanner(System.in) ;
ql-ri hd t-^Lah .
do{
token = s.findlnl,ine(args[0] );
System. out.println ( "f ound " + token) ,'
) while (token t= null);
) catch (Exception e) { System.out.println("scan exc"); }
]
Achamadaeoinput
java ScanIn "\d\d"
.i nnrrts.
f rrPuu. 1l^t^"aqf456
produzem o seguinte:
found 33
found 45
found nul1
Tokenizagio
A tokenizagio 6 o processo de se pegar grandes pedagos de dados-fontes, dividi-los em pedagos pequenos e
armazenar esses pedagos pequenos em variiveis. Provavelmente, a situagao mais comum de tokenizagio 6 a
leitura de um arquivo delimitado para se ter o contefdo do arquivo movido para dentro de lugares iteis, tais como
JAVA 5 279
arrays ort conjuntos. Estudaremos as duas classes da A?I que fornecem recursos de tokenizagio: String
2bjetgs'
(usando o m€todo split ( )) e Scanner, que possui muitos m6rodbs tteis para a tokenizagio.
Tokens e Delimitadores
Quando-falamos em tokenizagio, estamos falando de dados que, no inicio, sio composros de duas coisas: tokens e
delimitadores. Os tokens sio os pedagos propriamente ditos dos^daios, e os deiimitadore^s sio as express6es q ve rfiaram
os tokens uns dos outros.. Quando. muitas peisoas pensam em delimitaiores, elas pensam em caractires ir"l"ior,
Jo*o
dtCT, 9" ba'as invertidas, ou talvez em 6nico espago em branco. Na-v-erdade, co^mo dro*"t i*pli.ii;d;;; fiA d;;r,
os delimitador,es godeq ser qualquer coisa que seria capaz de qualificar como uma expressi6 ,.g.*."V"*oi prg"i
um contunto de dados-lonte e realizar tokenizagio nele, usando diversos delimitadorei:
fonte: "ab, cd5b, 6x, 24,,
Se dissermos que o nosso delimitador 6 uma virgula, enrao os nossos quatro tokens serio
ab
cd5b
6x
z4
Se usarmos a mesma fonte, mas declararmos nosso delimitador como sendo \d. obteremos tr6s tokens:
ab. cd
]a
x,z
Em geral, quando tokenizamos dados-fonte, os delimitadores sio descartados, e tudo o que nos resta sAo os
tokens. Assim, no segundo exemplo, definimos os digitos como delimitadores, de forma-qu e 5, 6 e 4 nio
aparecem nos tokens finais.
class SplitTest {
public static void main(String[] args) {
String[] tokens = argst0l.split(args[]-l );
System.out.println( "count " + tokens. length) ;
for(String s : tokens)
System.out.println(s>/ + s + "<"),'
]
Tudo acontece de uma s6 vez quando o m6todo split ( ) 6 chamado. A string-fonte 6 dividida em pedagos, que
sio carregados no array de Strings chamado tokens. Todo o c6digo depois disso s6 estSli para verificar o que a
operaglo de divisio gerou. A seguinte chamada
t java SplitTest "ab5 ccc 45 @" "\d"
produz
count 4
>ab<
>ccc<
>@<
(ObservagXo: lembre-se de que, para representar "\' em uma string, voc6 poderi ter de usar a seqii6ncia de escape
"\ \". Por causa disso, e dependendodo seu SO, o seu segundo argumento poder6 ter de ser "\ \ d" ou at6 mesmo
"\\\\d".)
N6s colocamos os tokens dentro de caracteres
foram usados como delimitadores, e que os digitos contiguos criaram um token vazio.
280 Copitulo 6: Strings, E/S, FormotoE6o e Porsing
1ogo ,ro inicio do arquivo, voc6 gistaria de poder fin alivar o processo de tokenizaElo logo que obtiver seu nimero'
"p"r...r
A dasse Scannerfomece uma ricaAPlpara redizar justamente isso'
oBSERVAQ6ESpeneoE)(AME
Pelofan /e System. out.printJ.nO rcrumdo com lantafeqiilncia no examq uoc|podenl uerexenplos de rcqiidncias de escape
nisimdas en qawtdes de praticamente qualquer t6pico, inclaindo regex. Itmbre-u fu que, n precisar criar uma String qae contenba aspas
dtpks (') ou uma bara inuertida (,), teni de adicionar un caracter de ur@e pimeiro:
Isso exibe
En uociprecisarpmwrarpnrpontos (.) nls seus dados-fonte? Se sinp/esmente co/ocar o ponto na exprvssdo regex, aod obteri o
comportuhentu "quolqar ioroitrr". E se uoc6 tentar\.,-entdo? Agora o compiladnr Jaua acba que uocl estd tentando criar ana teqiidncia de
A sintaxe correta d
etcape qae ndo existe.
String s = "ab.cde.fg";
String[ ] tokens = s.split("\\.");
r AtokenizaEio|reahzadadentrodeumloop,paraquevocOpossafinalizaroprocessoaqualquermomento.
r Os tokens podem ser convertidos automaticamente para os seus tipos primitivos apropriados.
Vejamos um programa que demonstra diversos m6todos e fung6es de Scanner. O delimitadorpadrlo de Scanner 6 o espago
em branco, que 6b que este programausa. O programa cria dois objetos Scanner: s1, sobre o qual6 feita umaiteragio com
o m6todo mais gen6rico next ( ) , o que retoina todos os tokens na forma de String, enquanto que s2 6 analisado com
v6rios dos m6todos especialidos nextxxx ( ) (onde xxx 6 um tipo primitivo):
import java. uti1. Scanner;
class ScanNext {
public static void main(String [] args) {
boolean b2, b;
int i;
String s, hits
Scanner s1 = new Scanner(args[0] );
Scanner s2 = new Scanner(args[0] );
while(b = sL.hasNextO) {
s = sl.next0; hits += \s"-
i
while(b = s2.hasNextO) {
if (s2.hasNextlntO) {
i = s2.nextfntO; hits += !\i";
) else if (s2.hasNextBooleanO) {
b2 = s2.nextBooleanO; hits += *b";
1 else {
s2 .next ( ) ; hits += \\s2" ;
)
JAVA 5 28I
)
System.out.println("hits " + hits) ;
456 + ]-23
Vejamos o que acabou de acontecer. Dentro das aspas duplas hi uma string de formatagio, depois um +, e depois
uma segunda string de formatagio. Repare que misturamos literais com as strings de formatagXo. Vamos agora
mergulhar um pouco mais fundo e observar a construgio das strings de {ormatagio:
* larg_index$] [flags] [width] [.precision] conversion char
Os valores dentro de [ ] sio opcionais. Em outras palavras, os rlnicos elementos obrigat6rios de uma string de
formatagio sio o 7o e um caracter de conversio. No exemplo acima, os rinicos valores opcionais que usamos foram para
indexagiodeargumentos.O2grepresentaosegundoargumento,eo 1$ representaoprimeiroargumento(reparequenio
tem problema em trocar a ordem dos argumentos). O d depois dos argumentos 6 um caracter de conversio (mais ou
menos o tipo do argumento). Eis um resumo dos elementos das strings de formatagXo que voc€ precisari conhecer
Para o exame:
arg-index Um nrimero inteiro seguido diretamente por um $, isso indica qual argumento dever6 ser exibido
nessa posigio.
flags Embora existam muitos flags, para o exame voc6 teri de conhecer:
282 Copitulo 6: Strings, E/S, Formotoqdo e Porsing
precision Para o exame, voc6 s6 precisar6 disto ao formatar um nimero de ponto flutuante e, no caso desses
,r,t*..or, precision indica o ndmero de digitos a serem exibidos depois do ponto decimal'
conversion O tipo do argumento que voc6 est6 formatando. Os que voc6 precisa conhecer:
I b boolean
I c char
f d integer
r f floating point
I s string
Vejamos algumas dessas strings de formataglo na pr6tica:
int i1 = -L23;
>false + -123<
Q.,l6s adicionamos os literais ) e
( para ajudar a demonstrar como funcionam as larguras minimas, os
preenchimentos com zeros e o alinhamento). Finalmente, 6 importante lembrar que, se voc6 definir tipos
diferentes para o tipo especificado no seu caracter de conversio e para o seu argumento, receber6 uma excegio de
tempo de execugio:
System.out. format ( "%d", L2.31 ;
A classe StringBuilder foi adicionada em Java 5. Ela tem exatamente os mesmos m6todos que a antiga classe
StringBuffer, exceto pelo fato de os m6todos de StringBuilder nlo serem seguros em relagio aos threads. Por esse
motivo, os m6todos de StringBuilder tendem a rodar mais ripido do que os de StringBuffer, portanto, escolha
StringBuilder sempre que os threads nio forem uma preocupagio. Tanto os objetos StringBuffer quanto os
StringBuilder podem ter os seus valores modificados virias vezes, sem que se precise criar novos objetos. Se voc6
estiver manipulando muitas strings, esses objetos serio mais eficientes do que objetos String imutlveis, que sXo mais
ou menos "usados uma vez, mantidos na mem6ria para sempre". Lembre-se de que esses m6todos senptt modificam o
valor do objeto chamador, mesmo sem nenhuma atribuiglo explicita.
JAVA 5 283
E/S de arquivos Lembre-se de que os objetos do tipo File podem representar arquivos ou diret6rios, mas, at6
que voc6 chamg createNewFile ( ) ou mkDir ( ) , ;inda n{o tericriado nada ,ro i.., disco rigido. As classes do
Pacote java.io foram elaboradas para serem encadeadas. Raramente voce utilizar| um FileReadei ou File\Triter
sem os "encapsular' em um objeto BufferedReader ou Buffered\7rirer, o que the d6 acesso a m6todos mais
poderosos, de nivel mais alto. Em Java 5, a classe Print\X/riter foi aprimorada com m6todos append. ( ) f or-
,
mat ( ) e printf ( ) mais avangados, e quando voc0 os usa em combinagio com os novos construtores, os quais
lhe-permitem criar PrintrVriters diretamente do nome de uma String ou de um objeto File, 6 possivel qrr" .rro.6 rrr"
Buffer\(riters com bem menos freqiiAncia.
Serializagio A serializagio lhe permite salvar, distribuir e restaurar tudo o gue vocd precisa saber sobre um
objeto ativo. E quando o seu ob.ieto aponta para outros objetos, eles sio salvoi tamb6m. As classes
java.io.ObjectOutputStream e java.io.ObjectlnputStream sio usadas para serializar e deserializar objetos.
Normalmente voc6 os encapsulari em instlncias de FileOutputstream e FilelnputStream, respectivamente.
O principal m6todo que voc6 chama paraserializar um objeto 6 writeobj ect ( ) e,par^deserializar o objeto, use
readMethod ( ) . Para serializar um objeto, ele precisa implementar a intertace Serializable. Marque as vari6veis de
instlncias com transient caso voc6 nio queira que o estado delas entre no processo de serializagio. Voc6 pode
ampliar oprocesso de serializagloparaasuaclasse implementandowriteobject O e readobject O. $ ofrzcr,
uma chamada a def aultReadObj ect O e a d.efaultWriteobj ect O inserida ir| curdar das tarefas normais
de serializagio, e voc6 poderi ampliar essas chamadas com leituras e escritas manuais no stream.
Se uma superclasse implementar Serializable, entao todas as suas subclasses tamb6m o fazem. Se uma superclasse
nio implementar Serializable, entXo, quando um objeto da subclasse for deserializado, o construtor unserializable
da superclasse 6 executado
- tenha cuidado! Finalmente, lembre-se de que a serializagio diz respeito ls
instAncias, de modo que as variiveis estiticas nio sio serializadas.
Datas, Ntmeros e Moeda Lembre-se de que o objetivo da Sun 6 um pouco enganador, e que voc6 terA de
entender os fundamentos de cinco classes relacionadas: java.util.Date, iava.util.Calendar, java.util.Locale,
java.text.DateFormat e java.text.NumberFormat. Um Date 6 o nrimero de milisegundos desde 1o. de janeiro de
1970, armazenado em um long. A maioria dos m6todos de Date for depreciado, entio use a classe Calendar para
as suas tarefas de manipulagio de datas. Lembre-se de que, para criar instAncias de Calendar, DateFormat e
NumberFormat, vod precisa usar m6todos esr6ticos de fibica, como getlnstance ( ) . A classe Locale 6 usada com
DateFormat e NumberFormat para gerar uma drie de estilos de saida que sio especificos a uma lingua e / ou um pais.
Parsing, Tokenizagio e Formatagio Para encontrar panes especificas de dados em grandes fontes, Java fornece
diversos mecanismos que usam os conceitos de express6es regulares (regex). As express6es regex podem ser
usadas com as classes Pattern e Matcher do pacote java.util.regex, e tamb6m com java.util.Scanner e com o m6todo
String. split ( ) . Ao criar padr6es regex, voc6 pode usar caracteres literais para a combinagio ou pode usar
metacaracteres, os quais lhe permitirio achar corresponddncias para conceitos como "encontre digitos" ou
"encontre espagos em branco". regex fornece quantificadores que the permitem emitir comandos como "encontre
uma ou mais destas coisas em seqii6ncia". Voc6 nio precisar6 entender os m6todos de Matcher que facilitem a
substituigio de strings nos seus dados.
Tokenizar 6 dividir dados em pedagos delimitados. Os delimitadores normalmente sio simples virgulas, mas
podem ser tao complexos quanto qualquer outro padrio regex. A classe java.util.Scanner fornece capacidades
completas de tokenizaglo usando-se regex, e permite que voc6 tokenize em um loop, para que possa interromper o
processo a qualquer momento. String. split ( ) permite o uso de padr6es regex completos para tokenizagio,
mas esse processo 6 feito em um passo, de modo que grandes fontes de arquivos podem levar um longo tempo
para serem processadas.
A formatagio de dados para saida pode ser feita usando-se a classe Formatter, ou mais comumente usando-se os
novosm6todosdePrintStream, formatO eprintf O. Lembre-sedeque formatO eprintf Ose
componam de forma similar. Para usar esses m6todos, voc6 cria uma string de formatagio que 6 associada com
todos os dados que voc6 deseja {ormatar. VocA precisari entender o subconjunto de conveng6es de strings de
formatagio que abordamos no capitulo, e teri de lembrar que,se a sua string de formatagio especificar um caracter
de conversXo que nio corresponder aos seus dados, ser6 langada uma excegio.
Exercicios rdpidos
Aqui estio alguns dos pontos principais dos objetivos para certificagio deste capitulo.
E Se voc€ redirecionar a referAncia a uma String para uma nova String, o objeto String anterior pode ser perdido.
El Os m6todos String usam indices iniciados em zero, exceto para o segundo argumento de substring ( ) .
fl Quando uma String literal for encontrada pela VM, ela seri adicionada
ao pool.
fl As Strings tpm um m6todo chamado length ( ) e os arrays tem um atributo chamado lengLh.
tr A API de StringBuffer 6 a mesma que a nova API de StringBuilder, exceto pelo fato de que os m6todos de
StringBuilder nXo s5o sincronizados Para seguranga de threads.
D Os m6todos de StringBuilder deverio rodar mais ripido do que os de StringBuffer.
E Todos os seguintes itens aplicam-se a StringBuffer e a StringBuilder:
E Os StringBuffers sio alteriveis - eles podem ser alterados sem a criaglo de um novo objeto.
El Os m6todos StringBuffer atuam sobre o objeto chamador, mas os objetos podem ser alterados sem uma
atribuigio explicita na instrugXo.
tr O m6todo equals ( ) de StringBuffer nio 6 sobrescrito; ele nlo compara valores.
E Lembre-se de que m6todos encadeados sio avaliados da esquerda para a direita.
E M6todos String que voc6 deve memorizar: charAt O , concat O, equalslgnoreCase O length O,
replace ( ) , substring ( ) , tolowerCase ( ) , toString ( ) , toUpperCase ( ) e trim ( ') .
D MdtodosdeStringbufferquevoc€devememorizar:appendO, deleteO,insertO, reverseO e
toString ().
E PrintVriters podem ser usados para encapsular outros \ilflriters mas, a partir de Java 5 eles podem ser criados
diretamente apartir de Files ou Strings.
O OsPrintrVritersdeJava5t6mnovos m6todos appendO, format ( ) eprintf O.
E As classes precisam implementar a interface Serializable para que os seus objetos possam ser serializados.
tr O m6todo ObjectOutputstream.writeObjecL ( ) serializa objetos, e o m6todo
Obj ectlnputstream. readObj ect ( ) os deserializa.
E Se voc6 marcar uma vari6vel de instAncia com transient. ela nio seri serializada. embora todo o resto do
estado do objeto seja.
E VocA pode ampliar o processo automitico de serializagio de uma classe implementando os m6todos
writeObjectO ereadObjectO.Seofizer,aschamadasinseridasparadefaultWriteObjectO e
defaultReadObject ( ),respectivamente, cuidarlodapartedaserializa$oqueacontecenormalmente.
E Se uma superclasse implementar Serializable, entio as suas subclasses tamb6m a implementam automaticarnente.
0 Se uma superclasse nio implementar Serializable, entio, quando um objeto da subclasse for deseri alizado, o
constnrtor da superclasse sera executado.
JAVA 5 285
E DatalnpudtreameDauOutputStream,naverdade,nlocaemnoenamgapaardoqueatiescritonosobjetivos&Stm.
f,l regex 6 uma sublinguagem existente em Java e em outras linguagens (como Perl).
Q regex lhe permite criar padr6es de busca usando caracteres literais ou metacaracteres. Os metacaracteres lhe
permitem procurar por dados ligeiramente mais abstratos, como "digitos" ou "espago em branco".
E Estude os metacaracteres \d, \s, \we. (ponto).
fl regex fornece quantificadores que lhe permitem especificar conceitos como: "Procure por um ou mais digitos
em seqii€ncia".
E Lembre-se de que os metacaracteres e Strings nio trabalham bem juntos, a nio ser que voc6 se lembre de f.azer
o devido escape deles. Por exemplo, String s = "\\d";
D As classes Pattern e Matcher t6m as capacidades regex mais poderosas em Java.
D VocAdeverientendero m6todo compile O dePatterne os m6todosmatcher( ),patternO, findO,
start ( ) e group( ) de Matcher.
J Y oc| nda precisar6 entender os m6todos de substituigio de Matcher.
tr Voc6 pode usar java.util.S canner patafazcr buscas regex simples, mas o objetivo original dessa classe 6a tokenizagio.
0 A tokenizagio pode ser feita com a classe Scanner ou com String. split ( ).
tr Os delimitadores sio caracteres rinicos, como virgulas, ou entAo complexas express6es regex.
286 Copftulo 6: Strings, E/S, Formotogdo e Porsing
O A lhe permite tokenizar dados de dentro de um loop, o qual lhe permite interromper a
classe Scanner
operagio sempre que quiser.
E A classe Scanner lhe permite tokenizar Strings, $reams ou arquivos.
I O m6todo String. split ( ) tokeniza toda a fonte de dados de uma s6 vez, de modo que grandes
quantidades de dados podem levar um longo tempo para serem processadas.
D Existem dois m6todos novos em Java para formataglo de dados. Esses m6todos sio f ormat ( ) e print f O .
Eles se encontram na classe PrintStream, da qual o out de System. out 6 uma instlncia.
O A formataglo de dados com print.f ( ) (ou f ormat ( )) 6 realizada usando-se stings deformatagdo que sio
associadas com argumentos primitivos ou strings.
O O m6todo f ormat ( ) lhe permite misturar literais com as suas strings de formatagXo.
O Os valores para strings de formataglo que voc€ deve conhecer sio:
O Flags: -, +, 0, "," e (
E Convers6es: b, c, d, f es
E Se o seu caracter de conversSo nd,o bater com o tipo do seu argumento, ser6 langada uma excegio.
Teste Individual
L Dado:
import java.util. regex. * ;
class Regex2 {
public static void main(String[] args) {
Pattern p = Pattern.compile (args [0] ) ;
Matcher m - p.matcher (args []-l ) ;
boolean b = false;
while(b = m.findO) {
System.out.prinL (m.startO + m.group( ) ) ;
E a linha de comando:
java Regex2 "\d*" ab34ef
Qual 6 o resultado?
4.234
B. 334
c.2334
D.01-23456
E. 01-234456
F. 12334567
G. A compilaglo falha.
2. Dado:
import java.io.*;
nlaqq Pl ar;or I
PlayerO { System.out.print("p") ; l
)
JAVA s 287
class CardPlayer extends player implements Serializable {
CardPlayerO { System.out.print.(..c,,) ; }
public static void main(Stringtl args) {
CardPlayer c1 = new CardplayerO;
trY I
FileOutputstream f os = new Fileoutputstream(..p1ay.txt,') ;
Objectoutputstream os = new Objectoutputstream(fos) ;
os.writeobject (c1) ;
os. close O ;
FilelnputStream fis = new FilelnputStream(..play.txt,,) ;
i
]
Qual6 o resultado?
A.pc
B. pcc
c.pcp
D. pcpc
E. A compilagio.
r4r r { - t
F.
- E langada uma excegio no tempo de execugio.
4. Dado:
c_Lass 'l't(u I
String s = il-/,'
Integer x = 343;
long L343 = 343L;
if (x. equals (L343 ) ) s += '\ . e1 " ;
if (x.eguals(343)) s += ".e2 ";
288 Copitulo 6: Strings, E/S, Formotog6o e Porsing
Quais das seguinres opg6es serXo incluidas na String de saida s? (A4arque todas as corretas)
A. . e]-
B. .e2
C. =s
D.fly
E. Nenhuma das anteriores.
F. A compilagio falha.
n 3r I n | .
G. E langada uma excegio no tempo de execuglo.
5. Dado:
f. import java.text.*;
2. class Dateone {
3. public stacic void main(string[] args) i
4. Date d = new Dare(11-23631685981L) ;
5. DateFormat df = new DateFormat ( ) t
6. System. out.println (df . format (d) ) ;
7. ]
8. ]
E dado que 112363I68598IL 6 o nirmero de milisegundos entre L". de janeiro de 7970 e algum momento em9 de
agosto de 2005, qual 6 o resultado? (Observagio: a hora do dia na opgio A poderi variar.)
A.8/9/05 5:54PM
B. 1123631685981L
n 4r I I r r
C. E langada uma excegio no tempo de execugio.
D. A compilagio falha devido a um s6 erro no c6digo
E. A compilagio falha devido a diversos erros no c6digo.
6. Dado:
import java.io.*;
class Keyboard { }
public class Computer implements Serializable {
private Keyboard k = new KeyboardO;
public static void main(String[] args) {
LvrrrPuLs! a^n6rrf6rt\.
vurrrPuus!\/,
^^6^"F^-
a cl-nraTf la\ .
void storelt(Computer c) {
trY {
ObjectOutputstream os = new Objectoutputstream(
new FileOutputstream( "nyFi1e" ) ) ;
os . writeObj ect ( c);
JAVA 5 289
os.closeO;
System. out.prj_ntLn (..done,, ) ;
) catch (Exception x) {System.out.println("exc"),. }
]
Qual 6 o resultado? (Marque todas as corretas)
A. exc
B. done
C. A compilagio falha.
D. Exatamente um obieto 6 serializado.
E. Exatamente dois objetos sio serializados.
)
Fragmentos:
FileDescriptor,' Di ranf nnr.
t) (Exception x) ( "dir3" 1 ;
E. Uma mesma instAncia de NumberFormat pode ser usada para se criar objetos Number a panir de Strings e
para criar nimeros formatados a partir de nrimeros.
290 Copitulo 6: Strings, E/S, FormotoEdo e Porsing
| 0. Quais das afirmativas sobre as tr6s classes de java.lang, String, StringBuilder e StringBuffer sdo
verdadeiras? (Marque todas as corretzr)
A Todas as tr6s classes t6m um m6todo length () .
E. De acordo com a API, StringBuffer seri mais r6pida do que StringBuilder na maioria das implementag6es.
F. O valor de uma instAncia de qualquer um desses tr6s tipos pode ser modificado atrav6s de virios m6todos da
API.
]
Fragmentos:
io. *; new DateFormat ( Locale. LONG
12. Dado:
'imnnrf i:.': in *.
class Directories {
static String [] dirs = 1"dirl", "dir2"];
public static void main(String [] args) {
for (String d : dirs) {
iAVA s 291
// insira o c6digo L aqui
File fi-f e = new File(path, args [0] ) ;
// insira o c6digo 2 aqui
)
e que a chamada
java Directories fi1e2.txt
6 emitida a partir de um diret6rio que tem dois subdiret6rios, "dir1" e "dir2", e que "dir1" rem um arquivo
"fi1e1 .tit"e'dir2"temumaiquivo"file2.tlt",easaida6"false true'iquaisconjuntosdefragmentos
de c6digo devem ser inseridos? (N4arqG todas as corretas)
A String path = d;
System.out.print(fi1e.exists() + " ") ;
B. String path = d;
System.out.print(file.isFileO +\ ") ;
13. Dado:
n'l ace Dnl i <h I
sb.delete(3,6) ;
sb.insert(3, "az");
if(sb.lengthO > 6) x = sb.indexof("b") ;
sb.delete( (x-3), (x-2) | ;
System. out . println ( sb) ;
])
Qual6 o resultado?
A. .faza
B. .fzba
C. . . azba
D. . fazba
E. . . fezba
F. A compilaglo falha.
n Ar I i t n
G. E langada uma excegao no tempo de execugio.
14. Dado:
L. import java.uLil.*;
2. cfass Brain {
3. public static void main(String[] args) {
Qual opg5o, inserida independentemente na linha 4, compila e produz a saida "I23 82"? (Marque todas as corretas)
292 Copilvlo 6: Strings, E/S, Formotogdo e Porsing
Respostas
Eesi correta. O \d estA procurando por digitos. O * 6 um quantificador que procura por zero ou mais ocorrAncias do
padrio que o precede. Por termos. especificado 'r, .o m6todo group ( ) retorna Strings vazias at6 que digitos
consecutivos sejam encontrados, de forma que o rinico momento em que group ( ) retorna um valor 6 quando
retorna 34, quando o matcher encontra digitos comegando na posigio 2. O m6todo start ( ) retorna a posigio inicial
da correspond6ncia anterior porque, novamente, n6s especificamos a busca por zero ou mais ocorr6ncias.
import java.io.Pil-e;
class Maker {
public static void main(String[] args) {
try {
Fil-e dir = new File("dir3") ;
dir.mkdirO;
File file = new File(dir, "fi1e3");
file.createNewFile ( ) ;
) catch (Exception x) t )
294 Copilulo 6: Strings, E/S, FormotoE6o e Porsing
Observag6es: as instrug6es new File nio criam arquivos ou diret6rios, apenas objetos. VocO precisa dos
m6todosmkdir O e createNewFile ( ) parade fato criar o diret6rio e o arquivo no disco. (Objetivo 3.2)
8. B, C, D e E estio corretas.
A est6 incorreta, DateFormat . parse ( ) 6 usado para convener uma String em um Date. (Objetivo 3.4)
9. A, C, F e G estio corretas. O caracter de conversio 8b (booleano) retorna true para qualquer argumento
nio-nul1 ou nio-booleano.
B esti incorreta, o caracter de conversio 8c (caracter) espera um caracter, e nio uma String. D esti incorreta, o
caracter de converslo I f (ponto flutuante) nio promove automaticamente um tipo integer. E est6 incorreta, o
caracter de converslo o/od (integral) nio 6. capaz de usar um nrimero de ponto flutuante. (Observagio: Os m6todos
f ormat ( ) e prinLf ( ) se componam de forma id€ntica.) (Objetivo 3.5)
l0.AeBestlocorretas.
C esti incorreta porque String nio tem um m6todo "append". D est6 incorreta porque somente objetos String
podem ser manipulados usando-se operador sobrecarregado " + ". E esti ao contririo, StringBuilder normalmente
6 mais rApida por ndo ser segura em relagSo a threads. F esr6 incorreta porque objetos String sio imut6veis. Uma
referOncia String pode ser alterada para referir-se a um objeto String diferente, mas os pr6prios objetos sio
imut6veis. (Objetivo 3. 1)
11.
class DateTVo {
public static voj-d main(Strinq[] args) {
Date d = new Date(1119280000000L);
Dat.eFormat df = DateFormat.qetDatelnstance(
DateFormat. LONG, Locale. GERMANY) ;
ObservagSes: Lembre-se de que voc6 deve construir objetos DateFormat usando m6todos esteticos. Lembre-se
tamb6m de que voc6 deve esp ecrticar umLocale paraum objeto naterormat no momento do instanciamento. O
m6todo getrnstance ( ) nio usa um Locale. (Objetivo 3.a)
12. A e B estio corretas. Pelo fato de voc6 e$ar chamando o programa a partir do diret6rio em cujos subdiret6rios diretos a
buscadeveriserfeita,niosecomegaocaminhocomumcaracterFile.separator.Om6todoexistsO verifica
aexist6nciadearquivosoudiret6rios;om6todoisFileO verificaapenasarquivos. IJmavezqueestamos
procurando por um arquivo, ambos os m6todos funcionam.
14.CeDestlocorretas.Oespagoembranco6odelimitadorpadrio,eoloopwhileavangaatrav6sdaString
usando nexLlnt ( ) ou next ( ).
A e B estio incorretasporqueo loop while nilovaial6mdo primeironio-int. E eF estSoincorretas. O loop
do farium loop infinito uma vez encontrado o primeiro nio-int, porque hasNext ( ) nio avanga atrav6s dos
dados. (Objetivos 3.5)
15. C e F estio corretas. C esti correta porque vari6veis static e transient nio sio serializadas quando
um objeto o 6. F 6 uma instrugio vilida.
base no exposto acima. G este incorreta porque voc6 nio sobrescreve o m6todo
A, B, D e E estio incorretas com
def aultReadobj ect O , mas o chama apaftir do m6todo sobrescrito readObj ect O , junto com quaisquer
operag6es de leitura personalizadas de que a sua classe necessite. (Objetivo 3.3)
Gen6ricos e
a-.,
LOnf unros
Obierivos poro q
certificog6o
r Projetos Usondo Coniuntos
r Sobrescrever equols( ) e hoshCode( ),
Distinguir enlre ::
e equols|
I UsorVers6es Gen6ricos de Coniuntos
Incluindo Set, List e Mop
I Usor Por6metros de Tipos, Escrever
M6todos Gen6ricos
I Usor iovo.util poro Clossificor e Fozer
Buscos
t/ Exercicios 16oidos
deixando de fora a maior parte das quest6es mais complicadas. A cobernra dos coqjryrtgs njstg_exame se expandiu & duas
formas, em relaSo ao exarne anterior', o uso de gen6riios em conjuntos , e a capacidaAe de classificar e vasculhar conjwrtos.
Vod 6 um objeto. Acosnrmese a isso. Vod tem um e$ado, um comportamento e um trabalho (ou pelo menos suas chances
de conseguir um aumentario depois que passar no exame). Se excluirmos os tipos primitivgs, rudo_eqJava 6 um objeto. Nio
s6 ,rm oSjeto, rns um Objeto .orn 'O' mairisculo. Cada exce$o, cada wento, cada arny 6 derivado dg pacgte
java.lang.bbject. No exame, vocd nlo precisar6 saber cada m6todo de Objea , mas tufti qlre conhecer os listados na Tabela 7-1.
M6todo Descrigio
boolean equals (object obj ) Decide se dois objetos sio significativamente equivalentes.
void fina]-ize( ) Chamado pelo coletor de lixo quando este percebe que o objeto
n1o pode ser referenciado.
final- void notify( ) Notifica um thread que estiver agtardando o bloqueio desse
objeto.
final void notifyAll ( ) Notifica todot os threads que estiverem aguardando o bloqueio
desse obieto.
final void wait ( ) Faz com que o thread atual aguarde at6 que outro thread chame
notify ounotlfyAll nesse obieto.
O metodo toString( )Sobrescrwa toString ( ) qtrando quiser que simples mortais consigam obter um resultado
iffeligivel ,elacionio'aos objetos de zua class". U* .^odigo po& chamar tostring ( ) ernryu objeto quando precisar de
detalhes riteis sobre ele. Por exemplo, quando vod passar a refer€ncia a um objeto para o m6todo
System. out . println ( ) , o m6todo toString ( ) dese objao seri chamado e retornat6 o que vemos exibido aqui:
public class HardToRead {
public static void main (String [] args) {
% java HardToRead
HardToRead@a47e0
A saida anterior 6 a que voc6 obter6 quando nio sobre*rever o m6todo toString ( ) da classe Objea. Ela forneceri o
nome da classe (pelo-menos zira ten rlanlncia) seguido do simbolo @ e da representagio hexadecimal nXo assinalada do
c6digo de hashing do objeto.
JAVA s 297
Talvez o fato de ter visto ese resultado o motive a sobrescrever o m6todo toString ( em suas classes, por
exemplo;
public class BobTest {
pubfic static void main (String[] args) t
Bob f = new Bob("GoBobGo", 19);
System. out.print.ln ( f ) ;
class Bob {
int shoeSize;
cfrin^ ni^L^Tr
--*-,*,*me,'
Bob(String nickName, int shoeSize) {
this. shoeSize = shoeSize;
this.nickName = nickName;
)
public String toString O {
return ("I am a Bob. but you can call me " + nickName +
I java BobTest
f am a Bob, but you can caff me GoBobGo. My shoe size is l-9
Algumas pessoas se referem afetivamente a toString ( ) como "o m6todo da revelagio total", porque suas
implementag6es mais comuns simplesmente revelam o estado do objeto (em outras palavras, os valores atuais das
vari6veis de instAncia imponantes).
Entio,isso6tudoqueprecisamossabersobretoString( ).Agoraabordaremosequals( )ehashCode( ).
Sobrescrevendo equals( )
Voc6 conheceu o m6todo equals ( ) em capitulos anteriores, ao examinarmos as classes wrapper. Discutimos
como a comparaglo de duas referancias a objetos com o operador : : retornar^ Lrue se elas apontarem para o
mesmo objeto (porque : : avalia apenas os bits da vari6vel que podem ser id6nticos ou nio). VocA viu que a classe
String e as classes wrapper sobrescrevem o m6todo equals ( ) fterdado da classe Object), de modo a podermos
comparar dois objetos diferentes (do mesmo tipo) para saber se seus conteildos slo significativamente equivalentes. Se
duas instincias diferentes de Integer armazeflarem o valor int 5, elas poderio ser consideradas iguais. O fato do
valor 5 existir em dois objetos separados nio importa.
class Moof {
private int moofval-ue;
Mnnf f irf rr:l l {
moofValue = val;
)
== this.moofValue)) {
return crue;
) efse {
return fafse;
]
Analisaremos os detalhes desse c6digo. No m6todo main ( ) de EqualTest, criamos duas instincias de Moof,
passando o mesmo valor (e) para seus constnrtores. Agora examinemos a classe Moof paraver o que ela f.az com o
argumento desse construtor - ela atribui o valor avariLvel de instAncia moofValue. Suponhamos que voc6 definisse
q,ri dois objetos Moof serio iguais se suas vari6veis moofvalue forem idAnticas. Ent-io, voc6 estiri sobrescrevendo o
m6todo equals ( ) ao comparar as duas variiveis moofvalue. E simples assim. Por6m, analisemos o que ocorre
no m6todo equats ( ) :
JAVA 5 299
1. public boolean equals(Object o) {
2. if ( (o instanceof Moof) && ( ( (Moof)o).getMoofValueo
== this.moofValue) ) {
3. return truei
4. ) else {
5. return false;
6. )
7. j
Em primeiro lugar, voc6 drue observar todas as regras da sobrescrigio; e na linha L estamos realmente declarando uma
sobrescrigio v6lida do m6todo equals ( ) que herdamos de Object.
E na linha 2 que ocorre toda a agio. Logicamente, temos que fazer duas coisas para tornar uma comparageo de
igualdade v6lida:
Pnmeiro, assegurar que o objeto testado sela do tipo comto!Ele 6 inserido polimorficamente como do tipo Object, portanto, voc6
precisa que ele passe por um teste instanceof . Ter dois objetos de tipos de classe diferentes sendo considerados
iguais geralmerfie nal 6 uma boa id6ia, mas 6 uma questio relacionada a projeto, sobre a qual nio discutiremos aqui.
Al6m disso, voc| ainda teria que execurar um teste insLanceof simplesmente para se assegurar de que poder6
converter o argumento do objeto para o tipo correto, de modo a poder acesar seas rudtodos ou vari6veis e faqer realmente a
comparagio. Lembre-se de que se o objeto nio passar no teste instanceof, entio, voc6 veri uma excegio de tempo
de execugio ClassCastException. Por exemplo:
A conversio (Moof ) o falhari se a vari6vel a nXo referenciar algo que SEJA-UM objeto Moof.
Em segundo lugar, conrparar os atibutos releuantes (nesse caso, apenas moofValue). 56 os desenvolvedores podem decidir o
que torna duas instAncias iguais (por raz6es de desempenho, ser6 melhor verificar a menor quantidade possivel de
atributos).
Aprop6siro,casovocAtenhaestranhadoasintaxede ((Moof)o) .getMoofValue( )comoumtodo,estamos
simplesmente convertendo variAvel de refer6ncia de objeto, o, simultaneamente ) tentativa de chamarmos um
a
m6todo que esti na classe Moof, mas nlo em Object. Tenha em mente que, sen a conversio, voc6 nio conseguir6
compilar porque o compilador veria o objeto referenciado por o simplesmente como um tipo Object. E j6 que a
classe Object nio possui um m6todo moofvalue ( ) , o compilador iria berrar (termo t6cnico). Por6m, como
dissemos anteriormente, mesmo com a conversio o c6digo falhari no tempo de execugio se o objeto referenciado por o
nio for algo que possa ser convertido em um objeto Moof. Portanto, jamais se esquega de usar o teste instanceof
primeiro. Ai estA outrarazio paravalorizar o operador de abreviagio && - se o teste instanceof falhar, nunca
chegaremos ao c6digo que executa a conversio, de modo que sempre estaremos seguros no tempo de execugio
escrevendo o seguinte:
== t.his, MoofValue) ) {
recurn Erue;
) else {
return false;
]
Entio, isso encerra eguals ( ) ...
Calma... Nlo tio r6pido. Se voc6 examinar a classe Object na documentagio da APIJava, veri o que chamamos de um
conhato especlficado no m6todo equa 1 (
) . Um nnran Java 6 um conjunto de regras qrc dnrm rer *eurdas, ou melhor,
s
dann ser segridas se wd qtiserfomecer una intplenmh1do "mmta" coruo as ouhas ?essnar esfurao etp€randa, Ou para colocar de outra forrna, se
vocA nlo seguir o contrirto, pode conseguir que a compila$o ea execudo sejam processadas, mas seu c6digo (ou o de outra
300 Copftulo 7: Gen6ricos e Coniuntos
E cuidado tambdm com ot tipos de argumento. O ndtodo abaixo d ama nbrecarga e nio ama sobrucrig1o do mdtodo equals ( ).'
Certifque-u de estar ben faniliaiqado com ar regras da sobrescrigdo para qtle posw identifcar se um nitodo de Objut utti sendo sobrescrito,
sobrecamgado ou inaalidamente redalarado em t/ma c/asn. O mitodo equaLs ( )
da clare Boo a/tera o argumento de Objutpara Boo,
se tornando, portanto, um mdtodo sobruarregado, e ndo senl cbamado a menlt qile 0 setl nidigo, o qua/ conbece ese mdtodo nouo e diferente
qtle Plr acanl tambdn se cbama equa1 s ( ) , sda o chamador.
O contrato de equals( )
Extraido diretamente da documentagloJava, o contrato de equals ( ) diz:
f E reflexiztotPara qualquer valor de referAncia de x, x. equals ( ) deve retornar true.
a E sinitrico: Para qualquer valor de referAncia de x e y, x. equals (y) deve retornar true se, e somerue se,
y. equals (x) retornar true.
I E transitizso:Para qualquer valor de referAncia de x, y e z, se x. equal-s (y) retornar true e y. equals (z )
tamb6m retornar true, enteo, x. equals (z) deve retornar true.
) E consistenteiP^ra qualquer valor de referAncia de x e y, mriltiplas chamadas de x. equals (y) retornario
consistentemente true ou consistentemente f alse, contanto que nenhuma informaqio usada nas
comparag6es do objeto de eguals tenha sido alterada.
I Paraqualquervalorderefer6nciadex queniosejanull,x.equals(nu11) deveretornarfalse.
E voc6 ainda nem chegou perto de estar seguro. Nlo examinamos o m6todo hashCode ( ) , mas eguals ( ) e
hashCode ( ) estio vinculados por um contrato de associagio que especifica qtue se dois olensforen condderados iguais
peb ndtodo equal s ( ) , entdo, Precisardtt ter uakres de hasbing iddntint Poftanto, para estar realmente seguro, voc6 deve
adotar a regrapriticaque diz para se submuerequals ( ) , deue-se sobresmuerhashCode( ) tanbin. Agorapodemos
passar para hashCode ( ) e ver como esse m6todo esti associado a equals ( ) .
Sobrescreyendo hashCode( )
Os c6digos de hashing normalmente sio usados para melhorar o desempenho de grandes conjunros de dados. O valor
de hashing de um objeto 6 usado por algumas classes de conjuntos (examinaremos os conjuntos posteriormente neste
capitulo). Embora voc6 possa consider6-lo como um tipo de nimero identificador do objeto, elJnlo 6
necessariamente exclusivo. Conjuntos como HashMap e HashSet usam o c6digo de hashing de um objeto para
determinar onde ele deve ser armarynado no conjunto, i o c6digo 6 empregado novamente como auxflio na localizagio
do objeto dentro do conjunto. No exame voc| nio rcrA que conhece. muitos detalhes sobre como as classes do conjunto
que usam hashing sio implementadas, mas precisari saber quais conjuntos as empregam (por todos usarem hasb no
nome voc6 precisa ser realmente astuto nesse ponto). Tamb6m teri que reconhecer uma implementagio @npriada ou
comta de hashCode (
) . Isso nlo significa udlida e nem mesmo efciente. E perfeitamente vilido ter um m6todo de
c6drgo de hashing absolutamente ineficiente em sua classe, contanto que ele nio viole o contrato especificado na
documentagio da classe Object (examinaremos esse contrato em breve). Portanto, no exame, se lhe for solicitado que
selecione o uso apropriado ou correto do c6digo de hashing, nlo confunda apropriado com a,ilido ov efciente.
Imagine um conjunto de baldes alinhados no chio. Algu6m passa para voc6 um pedago de papel com um nome nele.
Voc6pegaonome ecalculaapartirdeleum c6digocujo resultado6umvalorinteiro, usandoaconvengio Abigua|a
1, B igual a 2, e assim por diante, e somando os valores num6ricos de todas as letras do nome. (Jm nome espedfn semprc
resultani do mumo aidigo; paraver um exemplo, consulte aFigaraT-1,.
Nio introduziremos nada aleatoriamente, simplesmente temos um algoritmo que sempre seri executado da mesma
maneira, dada uma entrada especifica, portanto, a saida serl sempre idAntica para duas entradas tamb6m id6nticas. At6
aqui tudo bem? A maneira como voc6 usa esse c6digo (e passaremos a cham6-lo de aidigo de hashin! ir6 determinar em
que balde o pedago & papel deve ser inserido (suponhamos que cada balde represente um nri.mero diferente de c6digo que
possa ser obtido). Agora imagine que chegue ,1gtr6-, mostre a voc6 um nome e diga: "Por favor, recupere o pedago de papel
JAVA 5 3OI
que coincida com esse nome". VocA olhari para o nome que esti sendo mostrado e executar6 o mesmo algoritmo de
geragio do c6digo de hashing. Esse c6digo lhe informar6 em que balde deve olhar para encontrar o nome.
No entanto, voc6 deve ter notado uma pequena falha em nosso sistema. Dois nonu diferentespodem resltar no ruesmo ualor.
Por exemplo, os nomes Amy e tuay t6m as mesmas letras, portanto, o c6digo de hashing ser6 id6ntico para os dois.
Isso 6 aceitivel, mas significa que quando algu6m lhe pedir (o vendedor de balde$ o pedago de papel no qual se
encontra o nome Amy, voc6 teri que procurar no balde de destino lendo cada nome at6 encontrar Amy emvez de May.
O c6digo s6 lhe informar6 em qtre bolth prwrrar,mas nlo como localizar o nome trma vez que tenha chegado a esse balde.
Conjunto
Baldes com os
C6digos de Hashing
l-Dl T_] f xl l=_l t4tl
T*\l Llr]
'Bob" "Fred" ::i';i:
Figuro 7-l lJm exernp/o de codigo de hoshing simplificodo
Porranto, para obter efici6ncia, seu objetivo ser6 distribuir os pap6is da maneira mais regular possivel por todos os
baldes. O ideal seria que voc6 pudesse ter apenas um nome por balde para que quando algu6m solicitasse um papel
fosse possivel simplesmenre calcular o c6digo de hashing e apanhar esse papel individualmente no balde especifico
(sem que seja preciso ir abrindo todos os pap6is desse balde at6 localizar o que esta sendo procurado). Um gerador
de c6digo de hashing menos eficiente (por6m, ainda funcional) retornaria o ///esmt c6digo (digamos, 42) independente
do nome, de modo que todos os pap6is seriam inseridos em um mesmo balde, com os outros Permanecendo vazios.
O vendedor teria que ir at6 esse balde e olhar cada um dos nomes at6 que o correto fosse encontrado. E se
funcionasse realmente assim, ele tamb6m poderia nunca usar os c6digos de hashing, e emvez disso ir at6 o balde
grande, escolher como comegar e olhar cada papel at6 encontrar o desejado.
O exemplo de distribuigio por baldes 6 semelhante I maneira como os c6digos de hashing sio usados em coniuntos.
Quando voc6 inserir um objeto em um conjunto que use c6digos de hashing, o conjunto usari o c6digo do obieto para
decidir em que dep6sito/slot ele deve ser inserido. Em seguida, quando voc€ quiserpraclrraresse objeto (ou, em uma
tabela de hashing, recuperar o valor associado a esse objeto), ter6 que fornecer ao coniunto uma referdncia a qual ele
vi comparar com os objetos qae utiuer annarynandt. Contanto que o objeto (armazenado no conjunto, como o papel no balde)
que voc0 estiver tenrando encontrar tenha o nurzto aidigo de hashirgdo objeto que estiver usando na pesquisa (o nome
mostrado ) pessoa que esrava trabalhando com os balde$, ele ser6 encontrado. Mas... E esse 6 um grande Por6m'
imagine o que aconteceria se, voltando ao nosso exemplo dos nomes, voc6 mostrasse ao vendedor de baldes um nome
e ele calculasse o c6digo baseado somente em metade das letras emvez de usar todas. Ele nunca encontraria o nome
porque nXo procuraria no balde correto!
Agora voc6 consegue perceber por que se dois objetos sio considerados iguais, seus c6digos de hashing tamb6m
devem ser iguais? Do contr6rio, voc6 nunca poderia encontrar o objeto j6 que o m6todo padrio de c6digo de hashing
da classe Object virtualmente sempre 6 usado com um nrimero exclusivo para cada objeto, uumo qaando o mitodo
equals O d sobrescrito de uma maneira erz que dois oa nafu o@etos sdo considerados igaais. Nio impona quanto sio iguais os objetos
se seus c6digos de hashing nio refletem isso. Portanto, repetiremos: se dnis objetosforcm igaait, reur c6digos de basbing
tambim terdo que ser.
lmplementando hashCode( )
Como ser6 que um algoritmo real de c6&go de hashing se parece? Algumas pessoas obt6m seu grau de PhD em
algoritmos de hashing, portanto, do ponto de vista da ci6ncia da computagio, isso esti al6m do escopo do exame. A
parte relevante aqui 6 a questio de seguir o contrato. E para seguir o contrato, Pense no que fez no m6todo equals ( ) . Vzd
cv//patoa anibutos. Porque essa compara$o quse sempre envolve valores de vari6veis de instAncia (embra-se de quando
examinamos dois objetos Moof e que os considerariamos iguais se os valores int das vari6veis moofvalue fossem os
302 Copitulo 7; Gen6ricos e Con junios
mesmos?). Sua implementaglo de hashCode ( ) deve usar as mesmas variiveis de instAncia. Aqui est6 um exemplo:
class HasHash {
yuvf i-f
^'.1-li^ fe -.
return false;
]
)
public int hashCodeO {return (x * 17);}
)
Jiqu9 o m6todo equals ( ) considerar6 dois objetos iguais se eles tiverem o mesmo valor x, temos que nos
certificar de que os objetos de mesmo valor x retornem c6digos de hashing iddnticos.
Normalmente, voce ver6 m6todos hashCode ( ) que usario alguma combinagio de ^ (XOR) exclusivo envolvendo
asvari6veis de instAncia, junto com, digamos, sua multiplicageo por um nrimero primo. Independente do caso, embora
o_objetivo seja obter uma distribuigio abrangente e aleat6riados objetos nos dep6sitos, o contrato (e o fato de um
objeto poder ou neo ser encontrado) s6 requer que dois objetos iguais tenham c6digos de hashing id6nticos. Nio seri
esperado no exame que voc6 avalie a eficiAncia de um m6todo hashCod.e ( ) , mas 6 preciso conseguir reconhecer
quais funcionario ou nio (funcionar significando "fazer comque o objeto seja encontrado no conjunto").
Agora que sabemos que dois objetos iguais devem ter c6digos de hashing iddnticos, o inverso tamb6m 6 verdadeiro?
Dois objetos com c6digos de hashing idAnticos t6m que ser considerados iguais? Pense nisso - voc6 poder6 ter virios
objetos no mesmo dep6sito porque seus c6digos de hashing sio id6nticos, mas a menls que eles tambdn passen no teste de
equals ( ) , nlo serio considerados coincidentes em uma pesquisa no conjunto. Isso 6 exatamente o que voc6
conseguiria com nosso m6todo ineficiente que fornece a todos os objetos o mesmo c6digo de hashing. E v6lido e
correto, apenas muito lento.
Ponanto, para que um objeto seja localizado, tanto o objeto pesquisado qtranto o existenre no conjunto devem ter valores de
hashingid6nticos rretornar true parao m6todo equals ( ) . Demodo quen5oMoutramaneiraanio sersobrescreveros
dois m6todos para estar absolatammte mto dz que seas o$etus poderdn ser asados en n@unfos que eruprcguern hasting.
O contrato de hashCode( )
Agora direto da fabulosa documentagXo da API Java referente i classe Object, apresentamos para voct. (rutar de
tambores) o contrato de hashCode ( ) :
r Sempre que for chamado no mesmo objeto mais de vmavez durante a execueeo de um aplicativo Java, o m6todo
hashCode (
) ter5, que retornar consistentemente o mesmo inteiro, contanto que nenhuma informagio usada
nas comparag6es de equals (
) envolvendo o obleto tenha sido aherada. Esse inteiro ter6 que permanecer
constante de uma execugio a outra do mesmo aplicativo.
r Se dois objetos forem iguais de acordo com o m6todo equals (obj ect ) , entio, a chamada do m6todo
hashCode ( ) nos dos dois objetos deve produzir como resultado o mesmo inteiro.
JAVA 5 303
r NXo 6 obrigat6rio que quando dois objetos forem diferentes de acordo com o m6todo
equals (java.lang.object), a chamada ao m6todo hashCode ( ) nesses objetos produza resultados
inteiros distintos. No entanto, o programador deve ficar aJertapara o fato de que produzir resultados inteiros
distintos para objetos diferentes pode melhorar o desempenho das tabelas de hashing.
E o significado disso serl...
x.hashCode( ) ==
x.equals(y) == true
rr hach(-nAa / \
I
Sem requisitos
de hashCode ( )
Portanto, examinemos o que maispode causar uma falha no m6todo hashCode ( ) . O que aconteceria se voc6
incluisse uma vari6vel transiente em seu m6todo hashCode ( ) ? Embora seja v6lido (o compilador nio reclamari),
sob algumas circunstAncias o objeto que voc0 inserir em um conjunto nio seri encontrado. Como voc6 sabe, a
serializagio salva o objeto de maneira que ele possa ser reativado posteriormente pela sua desserializaElo, voltando a
ser um objeto totalmente v61ido. Mashhpeigo,lVillRobinnn - lembre+e de que uaidueis hansientet ndo sdo saluar qwando un objeto i
niakqado. IJm mau cen6rio poderia ser o seguinte:
x = xVal;
y = yval_;
)
public int hashCodeo {
rofrrrn fv ^ rr\ / / E v6lido, por6m, ndo correto
/ / usar uma vari6vel transi-ente
]
public boolean equals(object o) {
SaveMe test = (SaveMe)o;
if (test.y == y && test.x == x) t // Valido, mas ndo correto
1611r7n rrrr6.
i else {
return false;
Aqui est6 o que poderia ser feito em um c6digo como o do exemplo anterior:
I Fornecimento de algum estado para o objeto (atribuigXo de valores a suas variiveis de instAncia).
I Insergio do objeto em um HashMap, sendo o objeto a chave.
I Salvar o objeto em um arquivo usando a serializagio sem alterar nada em seu estado.
I Recuperar o objeto no arquivo por meio da desserializagio.
I Uso do objeto deserializado (reativado na mem6ria) para extraiJo de HashMap.
Opa. O objeto do coniunto e o supostamente mesmo objeto reativado nio slo mais id6nticos. A vari6vel transiente do
objeto retornarS. comum valor padrio emvez do valor que tinha no momento em que foi salva (ou inserida em
304 Copitulo 7: Gen6ricos e Coniuntos
HashMap). Portanto, com o uso do c6digo SaveMe anterior,pe o valor de x for igual a 9 quando_a in-stincia for
inserida no objeto HashMap, j6 que , ser-6 usado no cilculo flp c6digo de hashing, quando seu valor for alterado esse
c6digo tamb6m ser6. E quando essa mesma instAncia de Savp$Ae for reativada na desserializagd,o, x, = = 0:
rndepintlenn dc sea ualor no iomento em qtle 0 objetofoi seriafiqatto. Por{ahto, o novo cilculo do c6digo de hashing resultar6 em
um c6digo diferente e o m6todo ( ) tamb6m falhhii j6 que x ser6 usado como um dos indicadores da
igualdade dos objetos. "q,tais
]
ConclusXo: vari6veis transiente podem realmente atrlphlhar suas implementaq6es de igualdade e de c6digos de
hashing. Mantenha a variivel nio transiente ou, se el4 rtuerqve ser marcada como transiente, nio a use na
determinagio de igualdade ou de c6digos de hashing de uni objeto.
Voc6 consegue imaginar escrever aplicativos orientados a bbjetos sem usar estruturas de dados como as tabelas de
hashing ou listas encadeadas? O que voc6 faria quando prgcisasse ter uma lista classificada com, digamos, todos os
membros de seu fi-clube dos Simpsons? E claro que podeda faz6-lo por sua conta; a Amazon.com deve ter milhares de
livros sobre algoritmos que vocA poderia comprar. Mas cofn o tipo de prazos aos quais os programadores estao
submetidos atualmente, chega a ser incoerente demais parf que possa ser considerado.
A estruturade conjuntos da linguagemJava, que tomou fofma com o lanEamento daJDk1.2 e se expandiu na versio 1.4
e novamente em Java 5, fornece listas, conjuntos, mapas e filas que satisfario a maioria de suas necessidades em
<<interhce>> <<interfuce>>
Set Queue
<<interhce>>
SortedSet
<<interface>>
SortedMap
implementa
r Colleaion (C' mairisculo), que, na verdade, 6 aintertacejava.util.Collection da qual Set, List e Queue sio
derivadas (est6 certo, deriuadar, e nio implementadas. Nio h6 implementag6es diretas de Collection.)
I Collections (C' maiusculo e com 's' no final), que, na verdade, 6. a clastejava.util.Collections, a qual armazena
virios m6todos utilit6rios static para serem usados com os collections.
oBSERVAQ6ES pene O EXAME
E -
ruuhof,lcil nnfandir "Collections" cum "Co//ection" tome cuidado. I--embre-se de que Collections d ma classe, con mitodos utilitdrios
utdtims, enquantr Collection d una interface com as declaragdes dos mitodos comans i maioria dos conjuntos inclusiae add( ), re-
move ( ), contains ( ), size ( ) r iterator( ).
Os conjuntos v6m em quatros vers6es b6sicas:
Listas Listas de itens (classes que implementam List).
Mapas Itens com uma identificagio exclusiva (classes que implementam Map).
Uma classe de implemena$o pode ser nioclasificada e nioordenad4 ordenadae nioclassficada ou or&nada e dassificada
Mas uma implementa$o nunca pode ser classficada e nioordenad4 porqu€ a classifica$o 6 um tipo especifico de
ordenamento, comovocivedem breve. Por exemplo, F{ashset 6umconiunto nloordenado e nioclassificado, enquanto
LinkedHashser 6 um conjunto orrdenado (rnas nioclassificadQ que maff6m a ordem na qrul os objaos foram inseridos.
306 Cooitulo 7: Gen6ricos e Coniuntos
fimmffi[il'ffi[il
Lisc O itineririo do vendedor (duplicatas sio permitidas)
E'-.spr{l
HashMap: Os produtos do vendedor (Chaves geradas a partir das lDs dos produtos)
A Interface List
No conjunto List o indice tem relevAncia. A rinica coisa encontrada em List que conjuntos diferentes nio tAm sio
virios m6todos relacionados ao indice. Entre esses m6todos principais esteo, por exemplo, get (int index) ,
ind.exOf ( ) , add ( int ind,ex, Obj ect obj ) , e outros. Todas as tr& implementag6es de List sio or&nadas atrav6s
da posiSo do indice - uma posiglo que wd deterrnnailrconfigurando um objeto em um indice especifico ou adicionandoo
:en especificar a posigio, quando o objeto 6 inserido no final. As tr6s implementag6es de Lis serio descritas na pr6xima se$o.
Arraylist Considere esse conjunto como um array que pode crescer. Ele proporciona iterapdo e acesso aleat,rio com
rqideT,Declaraglo 6bvia: 6 um conjunto ordenado (por indices), mas nAo 6 classificado. VocO pode vAJo a partir da
verslo 1..4, e atualmente ele implementa a nova interface RandomAccess - uma intedace marcadora (o que significa
que nio possui m6todo$ que informa' "Essa lista di suporte ao acesso aleat6rio r6pido (geralmente de forma
ininterrupta)". Prefira essa lista a Linkedlist quando precisar de iteragio r5rpida e n6o pretender executar muitas
inserg6es e exclus6es.
Vector E,r'trn re-anescente dos prim6rdios daJava; Vector e Hashtable sio dois coniuntos originais, os outros
foram adicionados nas vers6es I.2 e I.4 dalava2.Umconjunto Vector 6 basicamente igud, a LrrayList, mas os
m6todos Vector sio sincronizados para a seguranga dos threads. Normalmente 6 preferivel usar Arraylist em vez de
Vector, ji que os m6todos sincroniiados .ansam um impacto no desempenho que pode ser desnecessirio. E se vocA
realnmte precisar de seguranga para os threads, h6 m6todos utilitirios na classe Collections que podem ipdar. Vector 6
a 6nica classe al6m de Arraylist que implementa RandomAccess.
Linkedlist Linkedlist 6 ordenado pela posigio no indice, como Arraylist, exceto pelos elementos serem
duplamente encadeados entre si. Esse encadeamento fornece novos m6todos (a16m dos obtidos na interf_ace List)_ para
a insergio e remogio do inicio ou final, o que o torna uma opglo adequada ) implementagio de uma pilha ou fila.
Lembre-se que um conjunto Linkedlist pode ser mais lento na iteraglo do que Arraylist, mas ser6uma boa opgXo
quando voc3 precisar de inserE6es e exclus6es ripidas. No Java 5, a classe Linkedlist foi aprimorada para implementar
atntertacejava.util.Queue.Assim,elaagoraoferecesuporteosm6todosdefilascomuns:peek( ),po11( )eoffer( ).
A Interface Set
O conjunto Set d6 relevAncia i exclusividade - ele nio permite duplicatas. O m6todo equals ( ) determinari se
dois objetos sio id6nticos (situagio na qual s6 um poder6 ficar no conjunto). As tr6s implementag6es de Set serio
descritas nas se96es seguintes.
HashSet Hashset 6 um conjunto Set nio-classificado e nlo-ordenado. Ele usa o c6digo de hashing do objeto que esti
sendo inserido; portanto, quanto mais eficiente for sua implementagio de hashCode ) melhor seri o.desempenho (
obtido no acesso. lJse essa classe quando quiser um conjunto sem duplicatas e nio precisar de ordem na iteragio.
LinkedHashSet LinkedHashSet 6 uma versio ordenada de HashSet que mant6m uma lista com encadeameflto
duplo para todos os elementos. IJse essa classe em vez de HashSet quando a ordem da iteragio {or imponante.
Ni iteiagio em HashSet a ordem 6 imprevisivel, enquanto LinkedHashSet permitir6 que voc6 itere pelos
elementos na ordem em que foram inseridos.
Treeset TreeSet 6 um dos dois conjuntos classificados (o outro 6 TreeMap). Ele usa uma estrutura de irvore vermelha e
preta voc6 sabe disso), e garante que os elementos fiquem em seqiiAncia ascendente, de acordo com sua orden natural.
(e
Qp.i"naL"*t , vod pode criar TreeSet com um construtor que the permita fomecer ao conjunto suas pn;prA rqras e qrul deve ser
a onleu w*rat (emvez de &pender da orrdem definida pela clase dos elementos), usandose um Comparable ou Comparator.
A Interface Map
Para Map os identificadores exclusivos 6 que sio relevantes. lJma chaue exclusiva (o identificador) ,6 napeada para um
uakrespecifico, em que 6 claro que tanto i cboue quanto o uakrsio objetos. E provivel que voc6 esteja bem familiarizado
.o- oi coniuntos Map, ji que muitas linguagens dio suporte a estnrturas de dados que usam pares thauef uabr ou nomef
uakr. As.implementag6es de M1n permitirio que voc6 faga coisas como procurar um valor com base na chave, solicitar
um con;unro apenas com os valoris ou somente com as chaves. Como Sets, Maps depende do m6todo equals ) (
para determinar se duas chaves sio as mesmas ou se slo diferentes.
HashMap HashMap fornece um conjunto Map nio-classificado e nio-ordenado. Quando voc6 precisar de um
conjunto Map e nio estiver preocupado com a ordem (na iteraEio), enteo, FlashMap seri sua melhor opgio; os outros
308 Copitulo 7: Gen6ricos e Coniuntos
mapas adicionam um pouco mais de sobrecarga. O lugar do Map onde as chaves irlo parar 6 baseado no c6digo de
hashing da chave, portanto, assim como HashSet, quanto mais eficiente a sua implementageo de hashCode ), (
melhor o desempenho de acesso voc6 ter6. HashMap permite uma chave e diversos valores nulos no conjunto.
Hashtable Como Vector, Hashtable existe desde os prim6rdios daJava. 56 por diversio, nio esquega de
observar a inconsist6ncia na nomeagio: HashMap versus Hashtable. Onde esti o "t" mairlsculo? Bem, nio esperarnos
que esse detalhe entre na pronrincia. De qualquer forma, assim como Vector 6 uma contrapartida sincronizada do
conjunto mais sofisticado e avangado Arraylist; Harhtable d a contr@artida incroniqada de Ha:bM@. Lembre-se de que nio se
pode sincronizar uma classe, portanto, quando dizemos que Vector e Hashtable sio sincronizados, queremos dizer
apenls que os mitodot chave da classe sio sincronizados. Outy difercnga, no entanto,6 que enquanto HashMap
permite que vocO tenha tanto valores quanto uma chave nla, Hasbtabb nio perwitini a existincia de algun componente na/0.
LinkedHashMap Como sua contrapartida Set, LinkedHashSet, o conjunto LinkedHashMap mant6m a ordem de
insergio (ou, opcionalmente, a ordem de acesso). Embora seja um pouco mais lento do que HashMap para adiironar e
remover elementos, pode-se esperar uma iteragio mais r6pida com LinkedHashMap.
TreeMap Agora voc6 j6 deve ter adivinhado que TreeMap 6 um conjunto Map clcxstfcado. E ji sabe que isso
significa "classificado pela elementos". Como TreeSet, TreeMap permitir| que voc6 introduza suas
ordem natural dos
p.pi^ regras de comparaglo (por meio de um Comparable ou Comparator) no momento da criagio do TreeMap,
para especificar como os elementos devem ser comparados entre si quando forem ordenados.
A Interface Queue
A fungio de Queue 6. armazenar uma lista de "coisas afazor", ou itens a serem processados de alguma forma. Embora
outras ordens sejam possiveis, as filas normalmente sio consideradas como do tipo FIFO (em que o primeiro item a
entrar.6 o primeiro a sair). As filas oferecem suporte a todos os m6todos-padrio de Collection, e tamb6m adicionam
m6todos para acrescentam e subtrair elementos e revisar elementos da fila.
PriorityQueue Esta classe 6 uma novidade de Java 5. Uma vez qlre a classe Unkedlist f.oi aprimorada, para
implementar a interface Qugue, as filas bisicas podem ser manipul-adas com uma Linkedlist. O prop6sito de uma
PriorityQueue 6 criar uma fila com ordenamento "prioridade de entrada-prioridade de saida", em vez do sistema
FIFO. Os elementos de PriorityQueue sio ordenados ou naturalmente (em cujo caso os elementos que forem os
primeiros na ordem serio acessados primeiro) ou de acordo com um Comparator. Em qualquer urrrdos casos, a
ordenagXo dos elementos representa a prioridade relativa deles.
explicita qaando iro impnrta, putantq se lhe solicitarem que selecione ama inteface, esco/ha uma inteface ea ueqde uma classe que a
inplemente. O inuerso tambdm i uerdadtiro - se lhe solicitarem para selecionar uma clase de implementagio, ndo esco/ba un tipo de interface.
A Tabela 7-2 resume 11 das 13 classes concretas relativas a conjuntos que voc6 precisari conhecer para o exame. (Os
Arrays e os Conjuntos v6m logo a seguir!)
Certifque-se de aprender a interpretar a Tabela 7-2 de maneira pnltica. I\o exame, podem lbe solicitar qae selecione um conjanto com base em
am requisito especifn, no qua/ essa nuessidade sela expressa c0///0 am cendrio. Por exemplo, qae conjunto uocd usaria se precisasse manter e
faTgr puquisas em utna lista de pegas, identifcadas por seu nltmero seqilencial afanamirico exclusiuo, sendo Part o tipo da pEa? Voci
alteraria stla retpltta se muddssemot o requisito de modo que tarztbim fosse precin exibir as peps em ordem, por rcu nilmero de sdrie? Na
primeirapergunta, uocd tem a classe Part, mas apuquisa dos objetot senl baseada em ilm fltirltero seqtiencia/, portanto, precisard de urt
conjunto M@. A cbaue serd o nrimero seqiiencial nafonna de um objeto Stringe o ualor serd a instdncia de Part. A opEdo padrdo deue ser
HashM@, o conjanto Mqp de acesso na* nipido. Porim, qaando acrercentarmls o reqaisito de incluir o ordenanento das pegas por nilmero
rcqiiencia/, precisarenos de un TruMap -
que manhim a ordem natural das chauet J,l que a chaue 6 uma String, a ordem nataral seni uma
classtfcagdo alfabitica padrdo. Se o requisito tiuuse sido raslrear qaalfoi a illtina pepa acerada, prouauelmente iiamos precisar de um
LinkedHashMap. Masli que o LinkedHashM4 perdeia a ordem natural (sabstitaindo-a pela ordem do illtino item acessado), se
precisarntos /istar as pegas por nilmero de sirie, leremos que classficar exp/icitamente o conjunto, asando um ndtodo uti/iniio.
ea um arEl. (Jnrfungdes do pacotelauauti/pma esmuer nid,igo qae manipub un arrEt clasifcando-0, realiqando nelc uma burca bindria oa
conuertendo o arE eru uma lista. (Jsar at intufacesjaua.util.Comparator elaua.kng.Conparablz para inflaenciar a classifcag1o dt l$as e arrqys.
Ahm diso, reconhecer o efeito da "ordrnapdo natural" das classes atr@perprinitiuas e dejaua.kng.Stringsobre a classficagdo.
J6 demos uma olhada te6rica nas principais interfaces e classes da Estrutura dos Conjuntos, e vamos ver agora como
elas funcionam na pr6tica.
Fundamentos de Arraylist
A classe java.util.Arraylist 6 uma das mais freqiientemente usadas de todas as classes da Estrutura dos Conjuntos. EIa
6 como um array anabolizado. Algumas das vantagens que Arraylist tem em relagio aos arrays sio:
I E capaz de crescer dinamicamente.
Esse tipo de declaragio segue o principio da programaEio orientada a objetos de "programar para uma interface", e faz
uso de gen6ricos. Falaremos muito mais sobre os gen6ricos mais adiante neste capitulo, mas, por agora, basta saber
que, aparrirdoJava 5, asintaxe (String> 6amaneiracorreta de se declararo tipo de uma colegio. (Antes deJava5
nao hivia nenhuma maneira de especificar o tipo de uma coleglo e, quando abordarmos os gen6ricos, falaremos sobre
as implicag6es de se misturar coniuntos Java 5 (digitados) e pr6-Java 5 (nio-digitados.)
n"l-'-l rl6ctArr^\rT.i
ysv4+v i a al ac< <f {
test.add(s+s);
System. out.println (test. size ( ) ) ;
System. out.println (test. contains (42l, | ;
System. out . println ( test . contains ( "hihi " ) ) ;
rda5e
true
2
H6 uma s6rie de coisas acontecendo nesse pequeno programa. Repare que, quando declaramos o Arraylist, nio demos a
ele um tamanho. Em segurda pudemos pedir que o Arraylist nos informasse o seu tamanho, pudemos pergu.ntar se ele
continha determinados objetos, removemos um objeto que estava presente nele, e depois verificamos novamente o
tamanho.
Classificando Coleg6es
Vamos comegar com algo simples, por exemplo, classificar um Arraylist de Strings alfabeticamente. Acha que isso
deve ser ficil demais? Cino, esperaremos enquanto voc6 vai procurar o m6todo sdrt ( ) de Arrayl-ist... Entendeu?
Araylist nio lhe fornece nenhuma maneiride classificar o ieu conterido, mas 6 claro que a classe
iava.util.Collections fornece um:
import java.util.*,'
class Testsortl {
public static void maj-n(Stringll args) {
ArrayList<String> stuff = newArrayliEt<String>()r // #1-
System.out.println("unsorted .. + stuff) ;
C+e;F-
p!rrrrv .i Fl
fLrLrs, ^.
String genre;
Strj-ng leadActor;
DVDInfo(String t, String g, String a) {
title = t; etenre = g; leadAct.or = a;
)
public String toString ( ) {
return title + " " + gfenre + " + leadActor + \\\n"
l
/ / ftaff^Te 6 caflar --rl
p^rao AirayList, ele chamou tostring ) ( para cada uma das instAncias.)
A Interface Comparable
A interface Comparable 6 usada pelos m6todos Cof lections. sort O e java.utils.Arrays. sort o
para classificar Lists
e arrays de objetos, respectivamente..Para implementar Comparable, a classe precisa
implementar apenas um m6todo, compareTo ( ) . Eis uma chamada de compareTo ( ) :
int x = thisObject.compareTo (anotherObject) ;
^"1-1 i^
yuvrrv inf
f rlu nnmn:r6rlr^tf)\iT)Tnfn
vvrrwu! v d\ {
return title.coqrareTo(d.getTitle () ) ; // +2
])
Na linha 1, n6s declaramos que DVDInfo implementa Comparable de uma forma tal que objetos DVDInfo
a classe
podem ser comparados ourros objetos
a DVDInfo. Na linha 2, impllmentamos compareTo ( ) ao.compararmos os
titulos dos dois objetos DVDInfo. IJmaurzque sabemos que os tirulos sio Strings, e que String imo_lementa Compi-
rable, essa 6 uma maneira f6cil de classificar oi nossos objetos DVDlnfo: por titulo. Antes da introdugio dos gen6ricos,
em Java 5, teria sido necess6rio implementar Comparable de uma forma parecida com esta:
class DVDInfo implements Comparable {
/ / c6di oo i nexi stcnte
public int compareTo(Object o) { / / ttsa rrm Oh-iect em vez de
// um tipo especifico
JAVA 5 3I3
DVDInfo d = (DVDInfo)o;
return tit1e. compareTo (d. gretTitle ( ));
]]
vilido, mas vocA.pode ver que nio s6 6 complicado como tamb6m arriscado, porque vocA precisa fazer
Isso ainda 6
uma conversio, e precisa verificar se a conversio nio vai falhar antes de tenti-la.
a|-rinn don16.
(t-rinn 1a:dAafnr.
return title;
)
// // vuLrvo
^111r^a
dafF^'^
vsuLgrD g
^ ^^!!^-.^
DgLLct-
import java.utiJ-.*;
class Genresort implements Comparator<DVDlnfo> {
public int compare(DVDInfo one, DVDfnfo two) t
return one. getcenre ( ) .compareTo (two. getcenre ( ) ) ;
iava.lang.Comparable java.util.Comparator
56 pode ser criada uma seqii6ncia de classificagio. Podem sercriadas muitas seqiiAncias & classificaglo.
Finalmente, lembre-se de que os m6todos sort ( ) tanto para a classe Collections quanto para a classe Arrays sio
e_st6ticos, e que eles alteram os objetos que esteo chssificando, emvez de retornar um objeio classificado de iorma
diferente.
I Se o conjunto/array em que voc6 deseja-procurar tiver sido classificado na ordem natural, a busca deve ser feita
nessa mesma ordem. (Isso 6 feito ao NAO se enviar um Comparator como argumento para o m6todo
3l6 Copiiulo 7: Gen6ricos e coniunlos
binarySearch ( ) .)
I Se o conjunt o/array em que voc€ deseja procurar tiver sido classificado com um Comparator, a busca deue ser feita
usando-se o mesmo Comparator, que 6 passado como o segundo argumento ao.m6todo binarySearch ( ) '
Lembre-se de que Comparators nio podem ser usados ao se buscar em arrays de tipos primitivos.
Vejamos um exemplo de c6digo que p6e em pritica o m6todo binarysearch () :
import java.util.*;
class SearchObjArray {
public static void main(String [] args) {
String [] sa = {"one"
Arrays.sort(sa) , ,, Ot
for(String s : sa)
System.out.print(s + " ");
q1r<fam nrrf nrinj- lnl\r\nnno ='\
+Arrays.binarySearch(sa,"one")); // #2
+ Arrays.binarySearch(sa,"one".rs)) ; / / #5
It
static cl-ass ReSortComparator
implementsComparator<String> { // #6
public int compare(String a, String b) {
returnb.compareTo(a); // #7
)
]
)
Linha 3 Cria uma instAncia de Comparator. Na linha seguinte, n6s re-classificamos o array usando o Comparator
Linha 4 Tentafazor uma busca no array, N6s nio passamos ao m6todo binarySearch ( ) o Comparator que
usamos para classificar o arr^y, e, por isso, recebemos uma resposta incorreta (indefinida).
Linha 5 Nova busca, passando o Comparator a binarySearctr ( ) . Desta vez obtemos a resposta correta,2.
Linha 6 Definimos o Comparator; 6 permitido que esta seja uma classe interna.
JAVA 5 3I7
LinhaT Ao trocar o uso dos argumentos na chamada a compareTo ( ), obtemos uma classificagio invertida.
String[] sa = {"one"
List slist = Arrays.aslist(sa); / / cria um List
System.out.println("size " + s],ist.sizeO ) ;
idx2 three
one five three srx
s1 [1] five
Repare que, quando exibimos o estado final do array e do objeto List, cada um foi atualizado com as modificag6es
feitas no outro. Esse tipo de comportamento nio seria excelente p.ua uma questeo do exame?
Agora vamos dar uma olhada no m6todo toArray ( ) . Nio hA nada de muito espetacular acontecendo com o m6todo
toArray ( ) ; ele tem dois tipos: um que retorna um novo array Object, e um que usa o array que voc6 envia para ele
como o xray de destino:
List<fnteger> iL = new Arraylist<Integer> ( ) ;
Usando Lists
Lembre-se de que os objetos List sio usados normalmente para manter as coisas em ordem, de alguma forma. Voc6
pode usar um Linkedlist para criar uma fila no estilo primeiro-a-entrar-primeiro-a-sair. Voc6 pode usar um Arraylist
paru manter registro dos locais que visitou, e em qual ordem. Repare que, em ambos os exemplos, 6 perfeitamente
nzoAvel pressupor que possam ocorrer duplicatas. Al6m disso, os Lists lhe permitem modificar manualmente a
ordenagio dos elementos, ao fornecer a capacidade de adicionar ou retirar elementos usando-se os seus indices. Antes
deJava 5, e do loop f or aprimorado, a maneira mais comum de se examinar um List "elemento por elemento" era
usando-se um Iterator. Voc6 ainda encontrarilterators sendo usados em c6digosJava que encontrar, e 6 possivel que
encontre alguns deles no exame. Um Iterator 6 um objeto associado com um conjunto especifico. Ele lhe permite fazer
um loop atrav6s do conjunto, um passo de cadavez. Os dois m6todos Iterator que vod precisa conhecer para o exame sio:
318 Cooitulo 7: Gen6ricos e Coniuntos
I boolean haelilext ( ) Retorna true se houver pelo menos mais um elemento no conjunto em que esta
sendo feito o loop. Chamar hasNext ( ) NAO move o foco para o pr6ximo elemento do conjunto.
I object next ( ) Este m6todo retorna o pr6ximo objeto do conjunto, E move o foco para o elemento que vem
depois daquele que acabou de ser retornado.
Vejamos um pequeno c6digo que usa um List e um lterator:
imnnrt- i:rra rri-il *.
cfass Dogr {
yuvrfv ia efrinn n:ma.
^"1-'1
Dog(String n) { name = n; }
]
class rtTest {
public static void main(String[] args) {
Dog d2 = (Dog)o;
System.out.println("oa " + d2.name) ;
]
]
)
Isso produz
aiko
clover
magnolia
size 3
geLl clover
A1KO U
oa aiko
oa clover
Primeiramente, n6s wamos a sintaxe dos gen6ricos para criar o Iterator (um Iterator do tipo Dog). Por causa disso,
quando usamos o m6todo next O , nlo precisamos converter o Object retornado por next O em um Dog.
Poderiamos ter declarado o Iterator desta forma:
Iterator i3 = d.i-t.eratorO; / / cria um iterator
Mas, assim, n6s teriamos de ter convertido o valor retornado:
Dog d2 = (DoS) i3.next ( ) ;
JAVA 5 319
O restantedo c6digodemonstraousodosm6todos size O, get O, indexof ( ) e toArray( ). Nloh6nadade
novo em nenhum desses m6todos. Daqui a algumas piginas, a Tabela 7-5listaritodos os m6todos de List, Set e Map
-
com os quais voc6 dever6 estar familiarizado para o exame. Como um riltimo aviso, lembre-se de que List 6 uma
interface!
Usando Sets
Lembre-se de que os Sets slo usados quando voc6 nio quer ter nenhuma duplicata no seu conjunto. Se tentar adicionar
)
um elemento a um Set que j6 exista nele, o elemento duplicado nio ser6 adicionado, e o m6todo add ( retornari
false. Lembre-se, HashSets tendem a ser bastante ripidos porque, como vimos anteriormente, eles usam c6digos de
hashing.
Voc6 pode tamb6m criar um TreeSet, que 6 um Set cujos elementos sio classificados. E preciio rer caurela ao se usar
um TreeSet (6 explicaremos o porqu6):
imnnrl- i:rra rrf il *.
class SetTest {
public static void main(String[] argrs) {
boolean[] la = new boolean[5.t ;
// insira c6d.igo aqui
bat01 = s.add("a");
ba[1] = s.add(new Integer(421);
ba[2] = s.add("b");
h:f?l = c aAdlse/\.
ba[4] = s.add(new ObjectO );
for(int x=0; x<ba.length; x++)
System.out.print(ba[x] + " ");
System. out.println ( " \n" ) ;
fnrt0h'ioat n . <\
Usando Maps
Lembre-se de que, quando voc6 usa uma classe ftIash) que implementa Map, quaisquer classes que usar como. parte
das chaves pari o questio deverio sobrescrever os m6todos hashCode O e equals O . @em, voc6s6
^apaem
precisa sobrescrev&los se tiver interesse em obter informag6es do Map. Mas falando s6rio, 6 vilido usar uma classe
que nlo sobrescreva equals ( ) e hashCode ( ) como chaves em um Map; seu c6digo iri compilar e rodar, voc6 s6
nio conseguir6 obter informaglo nenhuma.) Eis algum c6digo demonstrando o uso de um HashMap:
imnarr iarra rrfil *.
cl-ass Dog {
public Dog(String n) { name = n; }
public String name;
public boolean equals(Object o) {
if ( (o instanceof Dog) aa
( (DoS)o).name == name) ) {
reEurn true;
) else 1
return false;
i
)
public int hashcode ( ) (return name.lengTthO ; l
)
class Cat { }
al acc ManrFact I
System.out.println(m.get("k1") ) ; / / #1,
String k2 = "k2";
System. out.printLn (m. get (k2) ) ; / / #2
Pets p = Pets.CAT,.
System.out.println(m.get (pl ) ; / / #3
System,out.println(m.get (dI) ) ; / / #a
System.out.println(m.get(new Cat O ) ) ; / / #5
System. out.println (m. size (l ) ; / / #6
]
o que produz algo como isto:
Dog@1c
DOG
JAVA 5 32I
CAT key
Dog key
nul-l-
5
Vamos estudar a saida. O primeiro valor obtido foi um obieto Dog (o seu valor poderi ser diferente.) O sezundo valor
obtido foi um valor enurn-(DOG). O terceiro valor obtido foi umJStrine: reDara oue a chave 6 um vilor erium. Teste
r6pido: qual 6 a implicagio'do fado de rermos conseguido usar enum .orio ,rrn. chave?
A implicagio disso 6 que enums sobrescrevem equals O e hashCode ( ). E, sevoc6 consultara classe
java.lang.Enum na API, ver6 que, de fato, esses m6todos foram sobrescritos.
A quana saida 6 uma String. O ponto mais imponante sobre essa saida 6 que a chave usada para obter a String 6
composta de um objeto Dog. A quinta saida 6 nu 1 1 . O ponto imponante aqui 6 que o m6todo Se t ( ) nio conseguiu
encontrar o objeto Cat que fora inserido anteriormente. (A riltima linha da saida confirma que, de fato, exisrem cinco
pares de chaves,/ valores no Map.) Por que nio conseguimos achar a String com chave Cat? Por que foi possivel usar
uma instAncia de Dog como chave, enquanto que usar uma instAncia de Cat como chave nio teve sucesso?
Eficl.rer que Dog substituiu equals ()e hashCode (), enquanto que Cat nio ofez.
Vamos dar uma olhada r6pida nos c6digos de hashing. IJsamos uma f6rmula de c6digo incrivelmente simplificada na
classe Dog - o c6digo de um objeto Dog 6 do tamanho do nome da instAncia. Assim, neste exemplo, o c6digo = 4.
Vamos comparar os dois seguintes m6todos hashCode ( ) :
public int hashCodeO {reLurn name.length0; } // +1,
Hora de mais um teste r6pido: os dois hashcodes acima sio v6lidos? Ser6 que eles terio sucesso em obter objetos a
panir de um Map? Qual deles ser6 o mais r6pido?
As respostas para as duas primeiras perguntas sio Sim e Sim. Nenhum desses c6digos de hashing ser6 muito eficiente
(na verdade, eles seriam ambos incrivelmente ineficientes), mas ambos sio v6lidos, e ambos funcionario. A resposta )
riltima pergunta 6 que o primeiro c6digo seri um pouco mais ripido do que o segundo. Em geral, quanto mais
singulares os c6digos criados por uma f6rmula, mais r6pida ser6 o obtengio de dados. A primeira f6rmula acimairi
gerar um c6digo diferente para a extensio de cada nome (por exemplo, o nome Roberto ir| gerar um c6digo, e o
nome Pedro i-r.6gerar um c6digo diferente). A segunda f6rmula iri sempre produzir o mesmo resultado, 4, e,por
isso, serl mais lenta do que a primeira.
O nosso ultimo t6pico relacionado a Map 6 sobre o que acontece quando um objeto usado como chave tem os seus
valores modificados. Se adicionarmos duas linhas de c6digo ao MapTest . main ( ) anterior,
d1.name = "magnofia"
q1/<|-6m nrirt- lnlm nat. ld'l\\.
vJ e LvfrL I
^rr|-
vsv . yr 4rf e+
DOG
CAT key
Dog key
nul1
5
nu11
O Dog que havia sido encontrado anteriormente nlo pode mais ser encontrado. Pelo fato de a variivel Dog . name ser
usada para criar o c6digo de hashing, modificar o nome causa a modi{icaglo do c6digo. Como um rtltimo teste
relacionado aos c6digos, determine a saida das seguintes linhas de c6digo, caso elas sejam adicionadas ao final de
MapTest.main () :
d1.name = "magnolia";
System.out.println(m.get(d1 )); // #L
d1.name = "clover";
System.out.println(m.get(new Dog("clover") ) ); / / #2
= "arttrur" ;
dl- . name
System.out.printfn(m.get(new Dog("c1over")) ); / / #3
322 Cooiiulo 7: Gen6ricos e Coniunlos
Lembre,se de que o c6digo de hashing 6 igual ao tamanho da variivel name. Ao se deparar com um problema desse
tipo, pode ser ritil pensar nas duas etapas da obtengio:
1.. Usar o m6todo hashcode ( ) para achar agaveta correta
2. Usar o m6todo equals O paraachar o objeto dentro dagaveta
NaprimeirachamadaagetO,oc6digo68(magrnolia) edeveriaser6(clover),demodoqueaobtengiofalhano
passoLen6sobtemosnull.NasegundachamadaagetO,osc6digossioambos5,entioopassoltemsucesso.
Tendo achado a gaveta correta (a gaveta "tamanho de name : 6"), o m6todo equals ( ) 6 chamado e, uma vez que o
m6todo equals O de Dog compara nomes, equals O tem sucesso, e a saida 6 oog key. Na terceira chamada a
set O, ot.rr.doc6digo temsucesso, mas otestede equals O falhaporque arthur NAO 6 igual a clover.
Daqui a algumas paginas, a Tabela 7-5 resumir6 os m6todos & Map com os quais vocA deveri estar familiarizado para o
exame.
class PQ {
static class PQsort
implements Comparatorclnteger> { / / ordem inversa
public int compare(Integer one, fnteger two) {
1356789
sj-ze 7
peek 9
size 7
poll 9
size 6
B'1 6531-null
Vejamos isso em mais detalhes. O primeiro loop f or itera atrav6s do anay ia, e usa o m6todo of fer ( ) para
adicionar elementos ao PriorityQueue chamado ps1. O segundo loop for itera atrav6s de pq1 usando o m6todo
poll ( ) , o qual retorna a entr^da com maior prioridade em pq1 E remove essa entrada da fila. Repare que os
elementos sio retornados na ordem da prioridade (neste caso, a ordem natural). Em seguida, criamos um Comparator
- neste caso, um Comparator que ordena os elementos na ordem contriria i natural. lJsamos esse Comparator p^r^
criar um segundo PriorityQueue,pe2, e o carregamos com o mesmo array qtre haviamos usado antes. Finalmente,
verificamos o tamanho depq2 antes e depois das chamadas apeekO e poll O.Isso confirmaquepeeko
retorna o elemento com a prioridade mais alta na fila sem o remover, e po11 ( ) retoma o elemento com a prioridade
mais alta E o remove da fila- Finalmente. revtl,samos os elementos restantes da fila.
static int binarySearch (Object[ ],k"y) Procuram em urn array classificado por um dado valor,
static int binarysearch (primiLive [ ] , key) retornam um indice ou ponto de insergio.
static boolean equals (Object[ ], Objectt I ) Comparam dois arrap para determinar se os seus
static boolean equals (primitive[ ], primitive[ ] ) conteridos sio iguais.
public staticvoid sort (Object[ ] ) Classificam os elementos de um arrav por ordem natural.
public static void sort (primitive [ ] )
static int binarySearch (List, key) Procuram em um List "classificado" por um valor,
static int binarysearch (List, key, Comparator) retornam um indice ou ponto de inserglo.
static void Eort (List) Classificam um List ou pela ordem natural ou por um
static void sort (List, Comparator) Comparator.
No caso dessas quatro interfaces, ji abordamos os m6todos mais complexos que voc6 poder| encontrar no exame. A
Tabela 7-5 apresenta um resumo dos m6todos de List, Set e Map que voc6 tamb6m precisa conhecer.
remove ( index)
Removem um elemento atrav6.s de um indice,
remove ( obj ect ) X
remove (key) do valor do elemento ou de uma chave.
Para o exame, os m6todos de PriorityQueue que vocA precisa entender sio of f er O (que 6 semelhante a add O ),
peekO (que obt6mo elementono iniciodafila, masnio o apaga) epo11( ) (que obt6m oprimeiro elementoe o
remove da fila).
for(String s : sa)
System.out.print(pq3.poll O + " ") ;
Isn pndu4
> f< >FF< >f < >ff<
Se uoc6 se /embrarque os espaEot sdo cobcados antes dos caracteres e qae at lehas naitiscalu sdo colocadas antes das minilsculr, utani bempara o
exane,
6.4 Desenuoluer aidigo qae use @mpriadanente os parhmehts de tipo en declaragdes de clasnsf intufacu, uaridueis dz insti.ncias, argamentos de
nitodnse tips fu ntomol e esoa,vr mdtodas gmtfrns oa mdtodos qac usem tipos rtringas, e entender as sene/banpar e d{ewryat mhv essas daar abordagns.
Os arrays em Java sempre foram de tipo especifico - um array declarado como do tipo String (string t J ) nio 6
capaz de aceitar Integers (ou ints), Dogs, ou qualquer outra coisa que nio sejam Strings. Mas lembre-se de que, antes
de Java 5, nlo havia nenhuma sintaxe para declarar um conjunto com esse mesmo comportamento. Para criar um
Arraylist de Strings, voc6 usava:
Arraylist mylist = new Arraylist ( );
ou o equivalente polim6rfico:
r!f i Du
-f mvT i cf
ILLJIrDL -- nar.r
Irgw Arra\rT..i
n!!qt!f <1- l\ /l ,.
ru
Nio havia nenhuma sintaxe que lhe permitisse especificar que mylist usaria Strings e somente Strings. E, nio
havendo nenhuma maneira de especificar um tipo para o ArrayList, o compilador neo podia forg6Jo a colocar apenas
coisas do tipo especificado na lista. A partir de Java 5, podemos usar os gen6ricos e, embora eles nlo sirvam apenas
para criar coniuntos de tipo especifico, 6 s6 para isso que a maioria dos desenvolvedores usa os gen6ricos. Assim,
embora os gen6ricos nio sirvam apenas para conjuntos, considere que os conjuntos 6 a principal razio e motivagio
para os gen6ricos terem sido adicionados ) linguagem.
E essa nio foi uma decisio f6cil, nem foi uma adigio inteiramente bem-vinda. Isso porque, junto com capaci&de de se
usar tipos especificos, os gen6ricos v6m com uma consider6vel bagagem - a maior pane vod nunca ver6 nem ter6 de se
preocupar com ela, mas existem algumas quest6es que surgem de forma str4rreen&ntemente r6pida Abordaremos aquelas
mais prov6veis de aparecer no seu pr6prio c6digo, que sio tamMm as questSes que vocA precisar6 conhecer para o exame.
O principal desafio para a Sun, ao adrcionar os gen6ricos ) linguagem (e o principal motivo pelo qual demoraram
tento), foi como lidar com c6digos antigos escritos sem os gen6ricos. Os engenheiros Java da Sun obviamente neo
queriam estragar todos os c6digos Java existentes, enteo, tiveram de encontrar uma maneira de as classes Java com tipo
especifico (gen6ricas) e as sem tipo especifico (nXo-gen6ricas/pr6-Java 5) conseguirem funcionar juntas. A solugXo
encontrada nlo foi a mais amig6vel, mas ela lhe permite usar c5digo antigo, nio-gen6rico, ao mesmo tempo usando
c6digo gen6rico que trabalha juntamente com c6digo nio-gen6rico. Mas perceba que dissemos "trabalha", e nio que
"trabalha BEM".
Embora vocA possa integrar c6digo gen6rico Java 5 com c6digo antigo, nio-gen6rico, as conseqiiAncias podem ser
desastrosas e, infelizmente, a maioria dos desastres ocorrem em tempo de execugio, e nio de compilagio. Felizmente,
no entanto, a maioria dos compiladores geram avisos que lhe informam quando voc6 esti usando conjuntos nio-
seguros (significando nio-gen6ricos).
O exame Java 5 aborda conjuntos tanto no estilo pr6-Java 5 (nio-gen6rico) quanto no estilo Java 5, e vocA veri quest6es
que esperam que voc6 entenda os complexos problemas que podem surgir quando mistura c6digo nio-gen6rico com
gen6rico. E, como alguns dos outros t6picos deste livro, seria possivel escrever um livro inteiro se f6ssemos abordar
326 Copitulo 7: Gen6ricos e Coniuntos
todos os detalhes sobre os gen6ricos, mas o exame (e este livro) aborda mais do que a maioria dos desenvolvedores
precisar| usar na prinica.
Um conjunto nio-gen6rico 6 capaz_de armazonar qualquer tipo de objeto! Um conjunto nio-gen6rico armazena
alegremente qualquer coisa que NAO seja um tipo primitivo.
Isso significava que era responsabilidade total do programador ser... Cuidadoso. Nlo ter nenhuma maneira de garantir
o tipo do conjunto nio era muito amistoso para o programador em um linguagem tio rlgtda com relagXo aos tipos.
Estamos tio acostumados com o compilador nos impedindo de, por exemplo, atribuir um int
a uma refer6ncia
booleana ou uma String a uma refer6ncia Dogl rn?s' com os coniuntos, a hist6ria era "pode entrar! A porta esti
sempre abena! Todos os objetos sio bem-vindos aqui a qualquer hora!"
E, uma vez que um conjunto podia armazcnar qualquer coisa, os m6todos que retiram objetos do conjunto s6 podiam
ter uma esp6cie de tipo de retorno - java.lang.Object. Isso significava que, para retirarmos uma String da nossa lista
que-devia-armazcnar-silStnngs, era preciso uma conversio:
String s = (String) myl,ist.get (0) ;
E uma vez que nio era possivel garantir que o que estava saindo era realmente uma String (uma vez que era possivel
colocar qualquer coisa na lista), a conversio podia falhar em tempo de execugio.
Assim, os gen6ricos cuidam dos dois extremos (inserir e retirar informag6es) ao forgar o uso de um tipo especifico nos
seus conjuntos. Vamos atualizar a lista String:
Perfeito. E, e"ata-ente isso o que queriamos. Ao usar a sintaxe dos gen6ricos - o que significa colocar o tipo entre
sinais de maior e menor ( String , estamos dizendo ao compilador que esse coniunto s6 poder6 armazenar ob.ietos
)
String. O tipo declarado dentro dos sinais 6 conhecido como "tipo parametrizado", "parAmetro de tipo" ou, 6 claro, o
nosso bom e velho "tipo". Neste capitulo, iremos nos referir a ele usando os dois novos termos tamb6m.
Entio, agora que garantimos o tipo do que seri INSERIDO, voc6 pode tamb6m garantir o tipo do que ser6
RETIRADO, e isso significa que voc6 pode se livrar da conversio quando receber algo do conjunto. Em vez de:
String s = (String)mylist.get(0); // pr6-gen6rj-cos, quando ndo
/ / era garantido que receberi.amos uma String
agora podemos usar simplesmente
O compilador j6 sabe que mylist cont6m apenas coisas que podem ser atribuidas a uma refer6ncia String, entXo,
nio 6 mais necessirio usar uma converslo. At6 aqui, tudo parece bem simples. E, com o novo loop for, 6 claro que
voc6 pode fazer iterag6es atrav6s da lista de Strings:
for (String s : myl,ist) {
int x = s.lengtho;
/ / n6,o 6 preciso converter antes de chamar um m6todo string! o
/ / compilador j6 sabia que \rs" era uma String vindo de Mylist
]
E, 6 claro, vocA pode declarar um parAmetro de tipo para um argumento de m6todo, que, enteo, transforma o
argumento em uma refer€ncia de tipo especifico.
JAVA 5 327
void t.akel,istOfStrings (List<String> strings) {
strings. add ('.foo', ) ; / / adiedo de uma String sem problemas
)
O m6todo acima NAO compilaria se o modificissemos para:
void takelistOfStrings (List<String> strinqs) {
strings.add(new Integer(42)l; // NAO! ! strings s6 pode receber Stringrs
]
Obviamente, tipos de retorno tamb6m podem ser declarados com tipo especifico:
public Set<Dog> getDoglist ( ) {
Set<Dogr> dogs = new HashSet<Dog> ( ) ;
/ /
mais c6digo para inserir dogs
return dogs;
)
O compilador o impedir6 de retornar qualquer coisa que nio seja compativel com um Set(Dog) (embora essa
questlo de o que 6 e o que nio 6 compativel ficari bem interessante logo a seguir). IJma vez que o compilador garanta
que apenas um DogSet de tipo especifico ser6 retornado, os objetos que chamarem o m6todo nio precisario de uma
conversio para retirar Dogs do Set:
Dog d = getDoglist0.get(0); // fr sABrDo que receberemos um Dog
(A conversio neste exemplo aplica-se ao que vem do m6todo seL ( ) de Set; n6s nio estamos conveftendo o que 6
retornado do m6todo getDoglist ( ) , que 6 um Set)
E quanto ao beneficio de um conjunto completamente heterogeneo? Em outras palavras, e se voc6 gostasse do fato de
que, antes dos gen6ricos, era possivel criar um Arraylist que armazenasse qualquer tipo de objeto?
List mylist = new arraylist O ; / / esLilo antigo, n5o-gen6rico
6 quase id€ntico a
Lj-st<Object> myl,ist = new
Arraylist<Object> O; / / armazea QUALQUER tipo de objeto
Declarar um List com um parAmetro de tipo < Object > cria um conjunto que funciona quase da mesma forma que os
conjuntos pr6-Java 5, nio-gen6ricos - 6 possivel colocar QUATQUER tipo de Object no conjunto. VocA veri mais
adiante que os conjuntos nio-gen6ricos e os conjuntos de tipo < Object > nio sXo completamente similares, mas, na
maior parte do tempo, as diferengas nio imponam.
Ah, se isso fosse o fim da hist6ria... Mas ain& existem algumas quest6es complicadas referentes a argumentos de
rn6todos, polimorfismo e a integragio entre c6digo gen6rico e niogen6rico, de modo que estamos apenas nos
aquecendo aqru.
328 Copitulo 7; Gen6ricos e Coniunlos
se torna
List<Integer> mylist = new Arraylist<lnteger> ( ) ;
para isto:
public List<String> changestrings(Arraylist<String> s) i ]
Moleza. E se houver c6digo que usava a verseo nio-gen6rica e realizavauma conversao para obter coisas, isso nio vai
e$ragar o c6digo de ningu6m:
Thf^d6t
frrLc:jer fi --
/Tnranar\
\rrrLsvs!/ list.get(0li // a conversSo ndo 6 mais necess5ria,
/ / mas deix6-1a aqui ndo causar6 problemas
mylisr.add(4);
myl,ist.add(6);
Adder adder = new eddero;
int total = adder.addall(myl,ist);
// passado para um argumento sem tipo
System. out.println (tota1 ) ;
class Adder {
int addA]1(List list) {
/ / m6todo com um argumento List n5o-gen6rico,
/ / mas assume (sem garantia nenhuma) gue serSo Int.egfers
Iterator it = 1ist. iterator ( ) ;
int total = 0;
JAVA 5 329
while (it.hasNextO ) {
int i = ((Integer) it.next ( )) . intValue( ) ;
total += i;
)
return total;
Sim, fu-nciona sem problemas. E possivel misturar c6digo gen6rico correto com c6digos anrigos, nio-gen6ricos, e todos
ficam felizes.
No exemplo anterior, o m6todo antigo addA11 ( ) presumiu (confiou? torceu?) que a lista passada estava de fato
restringida a Integers, mesmo que, quando o c6digo foi escrito, nio houvesse nenhuma gararfiia. Era responsabilidade
do programador ser cuidadoso.
Umavez que o m6todo addAll ( ) nio estava fazendo nada, exceto obter o Integer (usando uma conversio) de uma
lista e acessar o seu valor, nio houve problemas. Nesse exemplo, nio houve nenhum risco para o c6digo do chamador,
mas o m€todo antigo poderia ter falhado caso a lista que foi passada contivesse qualquer coisa que nio fosse um
Integer (o que teria causado uma ClassCastException).
Mas, imagine agora que voc6 chame um m6todo antigo que nio apenas leia um valor, mas adicione algo ao Arraylistl
Ser6 que vai funcionar?
import java.util.*;
nrrl-r'l i a nl:c< rn6ciR^dT.6dA^1r
s\4\4seYsvj I
L
Ceftamente, esse c6digo funciona. Ele compila e executa. O m6todo insert ( ) coloca um Integer na lista que fora
originalmente declarada como ( Integer ) , portanto, nlo h6 nenhum problema.
Mas... E se modificarmos o m6todo insert ( ) desta forma:
void insert(List list) {
1 i cf :rt^ /rat.r
\rrsw cfrih^/\/t/
oulfrrv \ a- \ \ . |// / nAa rrma al-rinnffry n:
rfs lic+-:
I I I Pvv
/ / <anAa n:cc:da
que isso vai funcionar? Sim, infelizmente funciona! Isso compila e executa. Nenhuma exceglo de tempo de
Ser6,
execugio. Ainda assim, algu6m acabou de colocar uma String em um Arraylist que deveria ser exclusivo do tipo
(Integer). Como isso 6 possivel?
Lembre-se de que o c6digo antigo permitia que se colocasse qualquer coisa (exceto tipos primitivos) em um conjunto.
E, para dar suporte aos c6digos antigos, Java 5 permite que os c6digos novos, com tipos especificos, usem c6digos
antigos (a ultima coisa que a Sun queria era pedir que milh6es de desenvolvedores Java modificassem todos os seus
c6digos existentes).
330 Copitulo 7: Gen6ricos e Coniuntos
Assim, o compilador Java5 6 forgado a permitir que voc6 compile oseu c6digo novo mesmo que ele chame um
m6todo de ,tma classe antiga que usa rr- sem tipo especifico, e faga deus-sabe-o-qu6 com ele.
"rgorn"nto
Entretanro, s6 porque o compiladorJava 5 permite que esse c6digo compile, nio quer {ize1 que ele fique FELZ com
isso. Na verdade, oiompilador iri thi advertir de qG est6 assumindo um grande, {ande risco ao enviar o seu
excelente Arraylist ( Integer ) para um m6todo perigoso que pode inserir Floats, Strings ou at6 mesmo Dogs na sua
lrsta,
Quando voc6 chamou o m6todo addall ( ) em um exempl_o anterior, ele nio inseriu nada nalista
(simplesmente
adiciorrou os valores dentro do conjunto), de forma que nio houve risco, para o chamador, de que a sua lista fosse
modificada de alguma forma horrivel. O c6digo compilou e executou sem problemas. Mas, na segunda versXo, com o
m6todo antigo insert ( ) que adiciona uma String, o compilador gerou um aviso:
j avac TestBadlegacy. java
NoLe: TestBadlegacy.java uses unchecked or unsafe operations.
Note: Recompile with -Xfint:unchecked for details.
lrmbre-se de que os auisos do runpiladlrNAo sdo consifuradot un erm dr compikgdo. O compilador gerou um arquivo de classe
perfeitamente v6lido a partir & compilagio, mas foi gentil o suficiente para lhe dizer o _equivalente a: ."Eu esPero
ieriamente que voc6 saiba o que esta fazendo,porque este c6digo antigo NAO tem nenhum respeito (e nem
conhecimento) do seu tipo especifico ( lnteger ) , e poderi fazer o que quiser com o seu precioso
Arraylist(Integer)".
OBSERVAQ6ESpeneOE)(AME
Certifqa*se de saber a dfervnga entre "a compila4dofalha" e "conpila rem enos", e enhe 'bonpila sem auisos" e "compila com auisot". Na maioia
das quutdes do exame, sd d preciso uber w compi/a ou w a conpikgdo falha - auisos do conpzlador nio fardo diferenga para a naior parte do exama
Porin, quando uoc| estiaer usando gendricot e misturando aldigo com e sem tipos especlfcos, ot auisos passam afaryr difmnga.
De volta ao nosso exemplo com o c6digo antigo que fazuma inserglo, tenha em mente que, para AMBAS as vers6es
do m6todo insert ( ) (uma que adiciona umlnteger e outra que adiciona uma String), o compilador emitir6 avisos.
O compilador NAO sabe se o m6todo insert ( ) esti adicionando a coisa cena (Integer) ou a errada (String). A razlo
pela qual o compilador produz um aviso 6 porque o m6todo esti ADICIONANDO algo ao conjunto! Em outras
palavras, o compilador sabe que h6 uma chance de que o m6todo possa adicionar a coisa enada a um conjunto que o
chamador pensa ser de tipo especifico.
OBSERVAQ6ESpRneOE)(AME
Para os propdsitot do exame, a ndo vr que a que$do inc/aa uma resposta que mencione auisos, mtia, mesmo qae wc6 niba que a compi/agdo os
pmdu{ri, ainda asim se trata dz una compilagdo com sacesso!A nnpila.{Ao com auins NUI'JCA d considerada como unafalba de nnpihEdo.
Mais urua aeq- se uir um cddigo que uoc| sabe qae iri compi/ar com auisos, I\{AO escolha "a corrpilag1ofalha" como a retposta. A quutdo d a
seguinte: am aidigo que nmpilt com auins ainda d una compikgdo cun st'lcesso. Se a pagunta d.o exame quivr testar o rea conhecinento dc se o
nldigo pnda{ni am ayiso (oa o que mc€ pode faryr con o nidigo para EIJMII,{AR os auisos), a peryunta (ou a rcspwtQ induinl explcitamente a
palura "auisos".
At6 aqui, ji vimos como o compilador irS,gerar avisos caso perceba que h6 uma chance de que o seu conjunto de tipo
especifico seja prejudicado por c6digos antigos, que nio usam tipo especifico. Mas, uma das perguntas que os
delenvolvedores sempt. fazem 6.: "Ok, certo, o c6digo compila, mas, por que ele E)GCUTA? Por que o c6digo que
insere a coisa errada na minha lista funciona no tempo de execuglo?" Em ouras palavras, por que a JVM permite que
o c6digo antigo insira uma String no seu Arraylist < Integer > , sem nenhum problema? Nenhuma excegXo, nada. .
Apenas uma discreta violagio total da seguranga do tipo que voc6 poderia nio descobrir at6 o pior momento possivel.
H6 uma grande verdade que voc6 precisa saber para entender porque o c6digo roda sem problemas - aJVM nio tem
id6ia de que o seu Arraylist devia armazenar apenas Integers. A informagio sobre os tipos nio existe em tempo de
execugio! Todo o seu c6digo gen6rico serve apenas para o compilador. Por meio de um processo chamado de
"apagamento de tipos", o compilador realizatodas as suas verificag6es no seu c6digo gen6rico e depois retira as
informag6es de dpos do bytecode da classe. Em tempo de execugio, TODOS os c6digos referentes a conjuntos - tanto
os antigos quanto os novos do Java 5 que voc6 escreve com gen6ricos - t6m exatamente a mesma apar6ncia, que 6 a da
versio pr6gen6ricos dos conjuntos. Nada das suas informag6es de tipos existe em tempo de execugio. Em outras
palavras, que vocA tenha ESCRITO
List<Integer> mylist = new Arraylist<Integer> ( );
JAVA 5 33I
Depois que o trabalho do compilador termina, aJVM vA o que ele sempre viu antes deJava 5 e dos gen6ricos:
Lj-st mylisL = new Arraylist O;
O compilador at6 mesmo insere as convers6es para voc6 - aquelas que voc6 tinha de fazer para retirar coisas de um
conjunto prdava 5.
Pense nos gen6ricos como uma proteglo estritamente de tempo de compilaglo. O compilador usa informag6es de
tipos, gen6ricos (o < tipo)entre sinais de maior e menor) para ceftificar-se de que o seu c6digo nio colocar6 as coisas
erradas em um conjunto, e de que voc6 nio atribuir6 o que receber de um conjunto ao tipo de refer6ncia errado. Mas
NADA dessa protegio existe em tempo de execugio.
Isso 6 um pouco diferente dos arrays, que lhe fornecem protegeo TANTO em tempo de compilagio quanto em
tempo de execuglo. Por que eles fizeram os gen6ricos assim? Por que nio existe informagio de tipo em tempo de
execuglo? Para dar supofte a c6digos antigos. Em tempo de execufXo, os conjuntos slo similares ios conjuntos de
antigamente- O que voc6 ganha ao usar os gen6ricos 6 uma protegio de tempo de compilagio o qual garante que voc6
nio colocari a coisa errada em uma colegio com tipo definido, e tamb6m elimina a necessidade de uma conversio ao
se retirar algo, uma vez que o compilador ji sabe que, de uma lista Integer, s6 pode sair um Integer.
O fato 6 que voc6 nio PRECISA de protegio em tempo de execugio... At6 que comece a misturar c6digo gen6rico e
nio-gen6rico, como fizemos no exemplo anterior. Ai entlo voc6 pode ter desastres acontecendo em tempo de
execugio. O 6nico conselho que podemos dar 6 prestar muita atenglo nestes avisos do compilador:
javac TestBadlegacy. java
Note: Test.Badlegacy.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
Esse aviso do compilador nio 6 muito descritivo, mas a segunda observagio sugere que voc6 recompile com -
xlint : unchecked. Se o fizer, voc6 receber6 algo como isto:
javac -X1j-nt :unchecked TestBadlegacy. java
TestBadlegacy. java: 17 : warning: [unchecked] unchecked cafl- to
add(E) as a member of the raw tl4)e java.util.l,ist
list. add (new String (" 42" \ ) ;
1 warning
Quando voc6 compila com o flag -Xlint : unchecked, o compilador lhe mostra exatamente guais m6todos
poderio fazer algo perigoso. Neste exemplo, uma vez que o argumento da lista nio foi declarado com um tipo, o
compilador o trata como se fosse um c6digo antigo e assume que nio h6 risco a respeito do que o m6todo colocar6 na
lista.
No exame, voc6 precisar6 ser capaz de reconhecer quando est6 compilando c6digo que ir6 produzir avisos, mas, ainda
assim, compilar. E qualquer c6digo que compile (mesmo com avisos) ir6 executar! Nenhuma violaqXo de tipo ser6
detectada em tempo de execugio pelaJW[, at6 que essas violag6es bag;uncem o seu c6digo de alguma outra forma. Em
outras palavras, o ato de adicionar uma String a uma lista ( Integer )
nlo vai falhar em tempo de execugio at6 que
voc6 tente tratar essa String-que-voc6-pensa-ser-um-Integer como um Integer.
Por exemplo, imagine que voc6 queira que o seu c6digo retire algo do seu (supostamente seguro)
Arraylist (Integer), no qual um c6digo antigo inseriu uma String. Ele compila (com avisos). E executa... Ou pelo
menos o c6digo que faz essa insergio de uma String executa. Mas quando voc6 retira a String-que-nXo-deveria-estar-16
da lista, e tenta atribui-la a uma refer6ncia Integer ou chamar um m6todo Integer, ter6 problemas.
Tenha em mente, enteo, que o problema de se colocar a coisa errada em um conjunto (gen6rico) de trpo especifico nio
aparece no momento em que voc6 usa add ( ) no conjunto. Ele s6 aparece depois, quando voc6 tenta usar algo da lista
e esse elemento nio bate com o que voc6 esperava. Antigamente (no tempo pr6-lava 5), vocA sempre assumia que
poderia receber a coisa errada de um conjunto (uma vez que nenhum conjunto era de tipo especifico), entao voce
tomava precaug6es defensivas no seu c6digo. O problema de se misturar c6digo gen6rico com nio-gen6rico 6 que voc€
nio estari esperando esses problemas, pois imagjnari que este protegido por um falso sentimento de seguranga por ter
escrito c6digo com tipos especificos. Basta se lembrar que, assim que vocA repassa o seu conjunto de tipo especifico
para nm c6digo antigo, que nio usa tipos especificos, a protegio j6fioi para o espago.
Novamente, preste muita atengio nos avisos do compilador, e esteja preparado para ver quest6es como essas
aParecendo no exame.
332 Copftulo 7: Gen6ricos e Coniuntos
Polimorfismo e os Gen6ricos
Os conjuntos gen6ricos lhe dio os mesmos beneficios da seguranga de tipos que voc6 sempre teve com os arrays, mas
existem algumas diferengas cruciais que podem lhe pegar se voce nXo estiver preparado. A maioria delas tem a ver
com o polimorfismo.
Voc6 ji viu que o polimorfismo se aplica ao tipo "base" do conjunto:
List<fnteqer> mylist = new Arraylist<Integer> ( ) ;
Em outras palavras, podemos atribuir um Arraylist a uma refer6ncia List, porque List 6 um supeftipo de Arraylist.
Nada especial ai - essa atribuigio polim6rfica funciona da maneira como sempre funcionou em Java,
independentemente dos tipos gen6ricos.
Masequantoaisto?
cl-ass Parent { }
class Child extends Parent { }
List<Parent> mylist = new Arrayf,ist<Chi1d> ( ) ;
Lis eAraylistslo otipo-base eJBumon6 o tipo gen6rico. Assirq umArrayl-istpode seratribuido aumLisq masumconiuntode
(JButon ) nio pode ser atribuido a uma referBncia de < Objea > , mesmo queJButton seja um zubtipo de Object.
A pane que parece errada para a maioria dos desenvolvedores 6 que NAO 6 assim que a coisa funciona com arrays,
JAVA 5 333
onde 6 permitido que voc6 faEa isto,
import java.util.*;
nlacc Daranf I l
Po1 que as regras para definigio de tipos em arrays sio diferentes das regras para definigio de tipos nos gen6ricos?
Falaremos sobre isso em um minuto. Por agora, apenas memorize que o polimorfismo nio funiiona da mesma forma
para gen6ricos como funciona para affays.
M6todos Gen6ricos
Se voc6 ainda nio estava familiarizado com os gen6ricos, poder6 e$ar se sentindo pouco ) vontade com as implicag6es
da questlo nio-h6-atribuigio-polim6rfica-para-tipos-gen6ricos que apresentamos acima. Mas como 6 que poderia estar
se sentido ) vontade? Um dos grandes beneficios do polimorfismo 6 que voc6 pode declarar, digamos, um argumento
de m6todo de determinado dpo e, em tempo de execugio, poder fazer esse argumento referir-se a qualquer subtipo -
incluindo aqueles que voc6 nem sabia que existiam quando escreveu o m6todo com o argumento do supertipo.
Por exemplo, imagine um exemplo cllssico (simplificado) de polimorfismo, com uma classe representando um
veterin6rio (AnimalDoctor) que possui um m6todo checkupQ. E neste momento, voce tem tr6s subtipos de Animal -
Dog, Cat e Bird - cada um implementando o m6todo abstrato checkupQ de Animal:
abstract class Animal {
public abstract void checkupO,'
)
)
class Cat extends Animal {
public void checkupO { // implementa c6digo especifico de Cat
System. out.println ( "Cat checkup" ) ;
]
]
class Bird extends Animal {
public void checkupO { // implementa c6digo especifico de Bird
System. out . println ( "Bird checkup" ) ;
])
Esquecendo os conjuntos,/arrays por um momento, apenas imagine o que a classe AnimalDoctor precisa para poder
ter um c6digo que tome qualquer tipo de Animal e chame o m6todo checkup ( ) de Animal. Tentar sobrecarregar a
classe AnimalDoctor com m6todos checkup ( ) para cada tipo poss(vel de animal seria absurdo, e obviamente nio-
extensivel. VocA teria de modificar a classe AnimalDoctor a cada vez que algu6m adicionasse um novo subtipo de
Animal.
Assim, na classe AnimalDoctor, vocd provavelmente teria um m6todo polim6rfico:
public void checkAnimal (Animal a) t
334 Copftulo 7: Gen6ricos e Coniunlos
E, 6 claro, queremos que AnimalDoctor tamb6m tenha c6digo que possa tomar affays de Dogs, Cats ou Birds, para
quando o veterinirio vier a uma exposigio de cies, gatos ou pissaros, resPectivamente.
Novamente, nio queremos m6todos sobrecarregados com a$ays paracada subtipo potencial de Animal, entXo
usaremos polimorfismo na classe AnimalDoctor:
public voj-d checkAnimals (Animal[] animals) {
for(Animal a : animals) {
a ahan'Lrrn
*'-------*Y'l / i
j
Eis o exemplo inteiro, com o teste do polimorfismo do array que usa qualquer tipo de array de animais (Dos [ ],
car [ ], Bird[ ]).
import j ava. utj-1 . *;
abstract class Animal {
public abstract voj-d checkupO;
]
class Dog extends Animal {
public void checkupO { // implementa c6digo especifico de Dog
System. out . println ( "Dog checkup" ) ;
)
]
class Bird extends Animal i
public void checkupO { // implementa c6digo especifico de Bird
System. out.println ( "Bird checkup" ) ;
)
)
public class AnimalDoctor {
/ / o m6Lodo usa um array de qualquer subtipo de animal
public void checkanimals (Animal [] anj-mals) {
for(Animal a : animals) {
a.checkupO;
]
]
public static void main(String[] args) t
// faz o tesLe
Dog[] dogs - {new DoSO , new DogO };
Cat[] cats = {newCatO, newCatO, newcat0};
Bird[] birds - {new Bird( ) };
)
Isso, 6 claro, funciona a contento (n6s sabemo-s, n6s sabemos, isso nio 6 nenhuma novidade). Mas eis o motivo por que
resolvemos repassar isso - esta abordagem NAO funciona da mesma forma com conjuntoi de tipos especificos^!
Em outras palavras, um m6todo que use, digamos um Arraylist<Animal> NAO ser6 capazde aceitar um conjunto
de qualquer subtipo de Animal! Isso significa que Arraylist ( Dog )
nio pode ser passado para um m6todo com um
argumenb de Araylist<Animal), mesmo que, como n6s sabemos, isso firncione bem com arrays simples.
Obviamente, essa diferenga entre arrays e Arraylist 6 condizente com as regras de atribuigio de polimorfismo que ji
vimos - o fato de que voc6 nio pode atribuir um objeto do tipo Arraylist (JBunon ) a um List i Object > . Mas 6
aqui que voc6 comega a sentir a complicagio trazida pela disdngio entre arrays com tipos especificos e conjuntos com
trpos especrtrcos.
N6s sabemos que nio vai funcionar corretamente, mas vamos tentar modificar o c6digo de AnimalDoctor para usar
I,
generrcos emvez oe arrays:
public class AnimalDoctorGeneric {
// modifica o argumento de Animal! I para Arraylist<Ani-rna1>
public void checkAnimals (ArraylistcAnimal> animals) {
for(Animal a : animals) {
a.checkupO;
]
]
public static void main(St.ring[] arqs) {
/ / cri,a Arraylist.s em vez de arrays para Dog, Cat, Bird
ListcDog> dog,s = new Arraylist<Dog> ( ) ,'
dogs.add(new DogO );
dogs. add (new Dog ( ) r ;
ListcCat> cats = new Arraylist<Cat> ( ) ;
cats.add(new CatO );
cats.add(new CatO );
List<Bird> birds = new Arraylist<eird> ( ) ,
birds. add (new Bird ( ) ) ;
/ / este c6digo 6 o mesmo que o da versdo com Array
Ani-malDoctorGeneric doc = new AnimafDoctorceneric ( ) ;
)
Entio, o que acontece?
j avac AnimalDoctorGeneric . j ava
AnimalDoctorGeneric. java : 51 : checkAnimals ( java. util.
Arraylist<animal>) in animalDoctorceneric cannot be applied to
( java. util . List<Dog>)
3 errors
O compilador nos interrompe com erros, e nXo avisos. Voc€ simplesmente NAO PODE atribuir os Arraylists
individuaisdossubtiposdeAnimal(<Dog>, (Cat) ou <Bird>)aumArraylistdosupenipo (Animal),que6
o tipo declarado do argumento.
Essa 6 uma das quest6es mais complexas para programadores Java que esteo tio familiarizados com o uso de
polimorfismo comarrays,ondeomesmo cenArio (enimalt J podesereferiraDog[ ],Cat[ ] ouBirdI f )
funciona da maneira como voce esperaria. Assim, n6s temos duas quest6es na verdade:
1.. Por que isso nXo funciona?
2. Como faz6-lo funcionar?
Voc€ nos odiaria, e a todos os engenheiros da Sun, se lhe diss6ssemos que nlohicomo faz&lo funcionar - ou seja, que
voc6 teria de aceitar as coisas como slo e teria de escrever c6digos horrivelmente inflexiveis que tentam antecipar e
codificar m6todos sobrecarregados para cada ( tipo ) especifico. Felizmente, existe uma forma de faz&lo funlionar.
Mas, primeiramente, por que nio funciona, se funciona para os arrays? Por que nio 6 possivel passar um
Arraylist ( Dog ) a um m6todo com um argumento de Arraylist ( Animal > ?
N6s chegaremos li, mas primeiramente vamos dar um passo atr6s por um minuto e considerar este cenirio, que 6
perfeitamente v6lido:
Animalf l animalq = nai^r Animal f ?l
animals.add(new CatO ) ; / / OK
animals.add(new DoSO ) i / / OK
Assim, esta parte funciona tanto com arrays quanto com conjuntos gen6ricos - podemos adicionar uma instlncia de
um subtipo em um $ray o! conjunto declarado com um supertipo. Vocd pode idicionar Dogs e Cats avmarray
Animal (animal [ 1) ou a um conjunto Animal (Arraylist ( Animal >).
E, com arrays, isso se aplica ao que acontece dentro de um m6todo:
public void addAnimal(Animal[] animals) {
animals [0] = new Dog ( ) ; / / sem problema, qualquer Animal funciona
,/ / em animal [ ]
Entio, se isso for verdadeiro, e voc6 puder colocar Dogs em um Arraylist ( Animal > , enteo por que voc6 nio pode
usar o mesmo tipo de cenirio de m6todos? Por que nlo 6 possivel fazer isto?
public void (Arraylist<Animal> animals) {
addAnimal
animal-s.add(new DoSO ) ; / / permitido em alguns casos...
)
JAVA 5 337
Na verdade, voc6 PODE fazer isso sob ceftas condig6es. O c6digo acima IRA compilar com sucesso SE o que voc6
passar ao m6todo for tamb6m um Arraylist < Animal > . Essa 6 a parte onde isso difere dos arrays porque, na versXo
dos arrays, voc6 PODIA passar um Dos [ ] ao m6todo que usa um Ani-ma1 [ ] .
A TINICA coisa que vocA pode passar a um argumento de m6todo de Arraylist ( Animal ) 6 um
Arraylist < Animal ) ! (Assumindo que voc6 nio esteja tentando passar um subtipo de Arraylist, uma vez que,
lembre-se, o tipo "base" pode ser polim6rfico.)
]
public void addAnimal(Animal[] animals) {
anj-malslO] = new DogO; // ok, qualquer subtipo de Animal funciona
)
Nenhum problema aqui. N6s passamos um Dog I J para o m6todo e adicionamos um Dog ao array (o que foi
permitido porque o parimetro do m6todo era do tipo Animal [ ] , o qual pode armazenar qualquer subtipo de
Animal). Mas e se modificdssemos o c6digo chamador para
public void foo ( ) t
Cat.[] cats = {new CatO, new CatO};
addAnimal(cats); // sem problema, envia o Cat[ ] para o m6todo
)
O compilador pensa que 6 perfeitamente vilido adicionar um Dog a um array Animal [ ] , uma vez que um Dog
pode ser atribuido a uma referAncia de Animal. O problema 6 que, se voce passasse um array de um subtipo de _ .
Animal (Cat, Dog ou Bir$, o compilador nio saberia. O compilador nio percebe que, em algum lugar do heap, hi um
arraydo tipo caat l, e nioanimal [ ], e voc6 est6prestes itenta. adicionarum Doga ele. Para o compilador, voc6
p,rssou vm do tipo Animal, enteo ele nio tem como perceber o problema.
^rray
ESSE 6 o cen6rio que estamos tentando impedir, independentemente de se 6 um array ou um Arraylist. A diferenga 6
que o compilador permite que isso funcione com arrays, mas nio com coniuntos gen6ricos.
A razlo pela qual o compilador nio lhe permitir6 passar um Arraylist ( Dog para um m6todo que use um )
ArrayliJtcAnimal> 6 que, dentro do m6todo, o parAmetro 6 do tipo Arraylist(Animal>, e isso significa que voc6
poderia colocar qualqueriipo de Animal dentro dele. Nio haveria como o compilador the impedir de colocar um
-Dog
em um List que fo.a originalrnente declarado como Cat ( ),
mas que esti agora sendo referenciado a partir do
parAmetro <Animal).
Ainda temos duas perguntas... como se contorna essa problema e por que, afilal, o compilador permite que voc6
assuma esse risco para arrays mas neo para ArrayLists (ou qualquer outro conjunto gen6rico)?
A, razio pela qual voc6 consegue compilar isso com arrays 6. que existe uma excegio de tempo de execugio
(ArrayStbreEiception) que lhe impedirl de colocar o tipo errado de objeto em um array. Se vocA enviar um array Dog
para o m6todo que usa um array Animal, e adicionar apenas Dogs (incluindo subtipos de Dog, 6 clarQ ao array ago1^
iendo referenciado por Animal, nioh|problemas. Mas se voc6 tentar adicionar um Cat ao objeto que nio verdade 6
tm array Dog, receber6 a excegio.
Mas NAO hi uma excegio equivalente para gen6ricos, por-causa do apagamento dos tipos! Em outras palavras, em
tempo de execugXo aJVM SABE o tipo dos mas NAO sabe o tipo de um conjunto. Todas as informag6es de
^rr^ys,de forma que, no momento em que ela chega )JVM, simplesmente nlo
tipoi gen6ricos sio removidas dtrante i compilaSo,
338 Copiruf o7: Gen6ricos e Coniuntos
Desde que a:6rttca coisa que voc6 passe a addAnimals (List<Animal>) seja um Arraylist(Animal), o
compilador ficaleliz - sabendo que qualquer subtipo de Animal que voc6 adicionar seri vilido (voc6 sempre pode
adicionar um Dog a um conjunto Animal, etc e tal). Mas se voc6 tentar chamar addAnimal ( ) com um argumento de
qualquer OUTRO tipo Arraylist, o compilador o impedir6, uma vez que, em tempo de execugio, aJVM nio teria
nenhuma forma de impedir que voc6 adicionasse um Dog ao que foi criado com um conjunto Cat.
Por exemplo, este c6digo que modifica o tipo gen6rico para ( Dog ), mas sem modificar o m6todo addAnimal (),
NAO ir6 compilar:
public void addanimal (ListcAnimal> animal-s) {
animals.add(new DoSO ) ; / / ainda oK como sempre
)
public static void main(Strinq[] args) {
List<Dog> animal-s = new Arraylist<Dog> ( ) ;
anj-mals.add(new Dog ( ) ) ;
animals.add(new DoS( ) ) ;
AnimalDoctorGeneric doc = new AnimalDoctorGeneric ( ) ;
doc. addAnimal (animals ) ; / / 6 AQUI que surge o problema!
)
O compilador diz algo como:
j avac AnimalDoctorGeneric . j ava
AnimalDoctorGeneric . j ava : 4 9 : addAnimal- ( j ava . ut i 1 . Li s t<Animal> )
1 error
Repare que essa mensagem 6 praticamente a mesma que vocd receberia ao tentar chamar qualquer m6todo com o
argumento errado. Esti dizendo que voc6 simplesmente nio pode chamar addAnimat (List<Animal>) usando
algo cuja referAncia tenha sido declarada como List (Dog>. (E o tipo da refer6ncia, e nio o pr6prio tipo do objeto
que importa, mas lembre-se: o tipo gen6rico de um objeto 6 SEMPRE o mesmo que o tipo gen6rico declarado na
refer6ncia. List(Dog) po& se referir A?ENAS a conjuntos que sejam subtipos de List, mas que tenham sido
instanciados como o tipo gen6rico < Dog > )
Maisumavez, lembre*e de queumavezdentro do mdtodo addAnimals ( ) , nrdo o queimporta6 otipo doparAmaro -
neste caso, List < Animal > . (N6t o modificamos de Arraylist para Lis para manter o nosso polimorfismo de tipo "base"
mais claro.)
JAVA 5 339
De volta I questio principal - como contornamos isso? Se o problema esti relacionado apenas ao perigo de se
adicionar a coisa errada ao conjunto, e quanto ao m6todo checkup ( ) que usou o conjunto passado como de
somente-leitura? Em outras palavras, e quanto aos m6todos que chamam m6todos de Animal para cada coisa do
coniunto, o que iri funcionar independentemente de qual esp6cie de subtipo de Arraylist 6 passada?
Eisso6umadica! Om6todo add O 6que6oproblema,entio oqueprecisamos6deumaformade dizerao
compilador'ei, estou usando o conjunto-passad6 apenas parachamir m6todos para os elementos - e prometo NAO
adicionar nada ao conjunto". E de fato EXISTE um mecanismo paradizer ao compilador que voc6 pode usar qualquer
subtipo gen6rico do tipo do argumento declarado, porque nlo iricolocar nada no conjunto. E esse mecanismo 6 o
coringa < ?>.
A assinatura do m6todo se modificaria de
public void addAnimal (ListcAnimal> animals)
Para
public void addAnimal(List<? extends Animal> animals)
Ao usar < ? extends Animal>, estamos dizendo: "Eu posso receber um conjunto que seja um subtipo de List e
com o tipo definido de < Animal ) ou qualquer coisa que estenda Animal. Ah sim, e PROMETO que nio vou
ADICIONAR nadaao coniunto". @xistem mais alguns detdhes, mas chegaremos li.)
Assim, 6 claro que o m6todo addAnimal ( ) acima nXo vai compilar nem mesmo com a notagio do coringa, porque
esse m6todo ADICIONA algo.
public void (List<? extends Animal> animals) {
addAnimal
animal-s.add(new DosO) ; // NAol Nao se pode adicionar se
sarmos <? extends Animal>
)
VocA receberi um erro bastante estranho que poderi se parecer com isto:
j avac Ani-malDoctorGeneric . j ava
AnimalDoctorGeneric. java: 38 : cannot f ind symbol
symbol : method add(DoS)
location: interface java.util.List<capture of ? extends Animal>
animals. add (new Dog ( ) ) ;
l- error
que basicamente diz: "voc6 nio pode adicionar um Dog aqui". Se modificarmos o m6todo de forrna que ele nio
adicione nada, passarl a funcionar.
Mas eqpere - ainda tem mais. @ a prop6sito, tudo o que abordamos nesta sedo sobre ggn6ricos provavelmente ser6 te*ado
no exame, com ex@o do "apagamento de tipos", sobre o qual nlo 6 necessdrio que vod saiba quaisquer detalhes)
Primeiramente, <? extends Animal> significa que vocd pode usar qualquer subtipo de Animal; entretanto, esse
subtipo pode ser OU uma subclasse de uma classe (abstrata ou concreta) OU um tipo que implemente a interface que
vem depois da peJavra extends. Em outras palavras, a palavra-chave extends no contexto de um coringa
representa tanto as subclasses quanto as implementag6es de interfaces. Nio h6 uma sintaxe <? implements
SerializabLe>. Se voc6 quiser declarar um m6todo que use qualquer coisa que seja de um tipo que implemente
Serializable, voc6 ainda usaria extends desta forma:
void foo(List<? extends Serializable> list) // forma esquisita, mas correta
// de usar "extends"
Parece estranho porque vocA nunca usaria isso em uma declaraglo de classe, porque Serializable 6 uma interface, nio
uma classe. Mas a sintaxe 6 essa, entio memorize-a!
Mais uma vez - s6 existe llMA palavra-chave coringa que representa tanto implementag6es de interfaces qlranto
subclasses. E essa palavra-chave 6 extends. Por6m, quando a vir, pense em "E-LIM", no sentido de dgo que passa no
teste de instanceof .
Entretanto, hi outro cenirio ern que voc6 pode usar um coringa E aindaadicionar ao conjunto, mas de uma forma
segura - a palavra-chave super.
Imagine, por exemplo, que voc6 tenha declarado o m6todo desta forma:
public void addAnimal(List<? super animals) { Dog>
animals.add(new DoSO) ; ll em alguns casos 6 correto adicionar com super
]
340 Copftulo Z: Gen6ricos e Coniuntos
Assim, o coringa lhe fornece atribuig6es polim6rficas, mas com certas restrig6es que voc0 nio tem no caso dos arrays.
Pergunta r.lpida: estes dois sio iddnticos?
public void foo(List<?> list) { }
public void foo(List<Object> list) { }
Se EXISTE uma diferenga (e aindanio estamos dizendo que existe), qual 6?
Sim,EXISTEumagrandediferenga.List<?>,que6ocoringa<?>semaspalavras-chaveextends ousuper,
significa simplesmente "qualquer tipo". Assim, isso significa que qualquer tipo de List pode ser atribuido ao
argtrmento. Poderia ser um List de ( Dog ) , ( Integer ) , (JButton ) , ( Socket ) , qualquer coisa. E usar o coringa
sozinho, sem a palavra-chave super (r.g*d" de um tipo), significa que voc6 nio pode ADICIONAR nada i lista
referida como List < ? >.
List<object.> 6 completamente diferente de List<?>. List<object> significa que o mdrodo SOMENTE
pode usarum List<obj ect>. Nio um List.<Dog>, nem um List<Cat>. Significa, no entanto, que voc6 pode
adicionar. i lista, uma vez que o compilador ji se certificou que voc6 est6 passando apenas um List < Object > v6lido
para o m6todo.
class Bar {
void dolnsert(List<?> list) {
list.add(new DogO );
)
]
Se nio, onde est6 o problema?
O problemaestano m6todo list.add( ) dentro de dornsert ( ). O coringa<?> permite queumalistade
QUALQUER tipo seja passada ao m6todo, mas o m6todo add ( ) nlo 6 v6lido, pelas raz5es que exploramos
anteriormente (que voc6 podia colocar o tipo errado de coisas no conjunto). Assim, desta vez, a classe Test\Tildcards
JAVA 5 34]
nio. causa problemas, mas a classe Bar nio compilar6, porque elarealizaum add ( ) em um m6todo que usar um
coringa (sem super). E se modificarmos o m6todo dotnsert ( ) para isto:
public class TestWildcards {
public static void main(String[] args) {
List<Integer> mylist = new Arraylist<fnteger> ( ) ;
]
)
cfass Bar {
void dolnsert (List<Object> list) {
list.add(new DogO );
]
]
E agora,vai funcionar? Se nlo, por quA?
Destavez,aclasseBar,comom6tododornsertO,compilasemsobressaltos.Oproblema6queoc6digo
Test\il/ildcards est6 tentando passar um List ( Integer ) para um m6todo capaz de usar APENAS um List ( Object > .
E narla mus pode substituir < Obiect > .
A prop6sito, List< ? extends ob j ect.> e List< ?> slo absolutamente id6nticas! Ambas as instrug6es dizem:
"Eu posso me referir a qualquer tipo de objeto". Mas, como voc6 pode ver, nenhuma delas 6 o mesmo que
List < Object ) . Uma forma de se lembrar disso 6 qlue, se voc6 vir a notagio com coringa (um ponto de interrogagio
?), isso significa "muitas possibilidades". Se voc6 NAO vir o ponto de interrogagio, entio significa que deve ser usado
o ( tipo ) especificado, e absolutamente NADA ALEM DELE. List ( Dog ) significa List ( Dog ) , e nio
List ( Beagle ), List ( Poodle ) nem qualquer outro.subtipo de Dog. Mas List < ? extends Dog ) poderia significar
List(Beagle), List(Poodle) e assim pordiante. E claro que List<?> poderia ser... Qualquer coisa.
Tenha em mente que os coringas s6 podem ser usados para declarag6es de referAncias (incluindo argumentos,
variiveis, tipos de ietornos e assim por diante). Nio podem ser usados como o parAmetro de tipo quando voc6 cria um
novo conjunto com tipo especifico. Pense nisso: enquanto uma refer6ncia pode ser abstrata e polim6rfica, o pr6prio
objeto criado deve ser de um tipo especifico. VocA precisa definir o tipo quando cria o objeto usando new.
Como uma pequena revisio antes de seguirmos adiante com os gen6ricos, observe as seguintes instrug6es e descubra
quais irio compilar:
1) List<?> list = new Arraylist<Dog>O;
2) List<? extends Animal> alist = new Arraylist<Dog>O;
3) List<?> foo = new Arraylist<? extends Animal>O;
4) List<? extends Dog> clist = new Arraylist<Tnteger> ( ) ;
5) List<? super Dog> blist = new Arraylist<Animal> ( ),'
6) List<? super Animaf> dlist = new Arraylist<Dog>O;
As respostas corretas (as instrug6es que compilario) sio t,2 e 5.
Declarag6es Gen6ricas
At6 agora, falamos sobre como criar conjuntos com tipos especificos, e sobre como declarar vari6veis de referAncia
qne incLr"* argumentos e tipos de retorno usando a sintaxJgen6rica. Mas eis aqui algumas quest6es: como 6 que
vamos saber se 6 permitido / requerido que n6s especifiquemos um tipo para essas classes de conjuntos? E a
especificagio de tipos gen6ricos funcionJcom outias classes da API? E, finalmente, 6 possivel declararmos as nossas
proprias il.sses co*o iipos gen6ricos? Em outras palavras, podemos criar uma classe (ue requeira que algu6m passe
um tipo quando adeclararem e instanciarem?
Primeiro, a resposta que vocA obviamente ji conhece: a API lhe diri quando um tipo parametrizado for esperado. Por
exemplo, esta 6. a declaragio API para a interface java.util.List:
public interface List<E>
O <E> 6 um marcador parao tipo quevoc6 passar6. A interface List estise comportando como um "modelo" (mais
ou menos como os modelos do C+ +) e, ao escrever seu c6digo, voc6 o modifica de um List gen|rico puaum
List < Dog ) ou List ( Integer ) , e assim por diante.
6 apenas uma convengio. Qualquer identificadorJava vilido funcionaria aqui, mas E significa
O E, a prop6sito,
"Elemento",e6usadoquandoomodelo6umconjunto.Aoutraconvengioprincipal 6T(significa"tipo"),usado
para, bem, para as coisas que NAO forem conjuntos.
Agora que voc6 ji viu a declaragio dainterface para List, como imagina que seja o m6todo add () ?
boolean add(E o)
Em outras palavras, o que quer que E seja quando voc6 declarar aList, i itso o que wc|podni adicionar a ela. Assim, imagine
este c6digo:
List<Animal> list
= new ArraylistcAnimal> ( ) ;
OEnaAPldeListderepentedeixadeserumabstrato (seutipoaqui> epassaaserumListdeAnimals.Esedum
List de Animals, enteo o m6todo add ( ) de List obviamente deve se comportar desta forma:
boolean add(Animal a)
Quando consultar uma classe ou interface gentrica na API, escolha um parAmetro de tipo (Dog, JButton ou mesmo
Object) e faga uma operaglo de busca e substituigXo mental para cada instAncia de E (ou qudquer identificador que
esteja sendo usado como marcador para o parAmetro do tipo).
)
nrrhlin Ol-!iadt-
vvJ ev u aal-Ponl-al
yeur\srf uq! /\
\ /
It
Agora imagine que voc6 quisesse criar uma subdasse de Rental que servisse apenas para o aluguel de carros. VocA
POOena comegar com algo deste ttpo:
import java.util.*;
public class CarRental extends Rental {
JAVA 5 343
public CarRental(int maxNum, List<Car> rentalpool) {
super (maxNum, rentalpool ) ;
]
public Car gletRental ( ) {
return (Car) super.getRental O;
)
public void returnRent.al(Car c) {
qtlnFr ral-rrrnPanf:1 qf /a\ .
\el ,
)
public void returnRental (Object o) {
if (o instanceof Car) {
qrlner ral-rrrnPant-:1 lnI .
] alca I
import java.util.*;
public class RentalGeneric<T> { // "'t" significa o parAmetro
// do tipo
private List<T> rentalPool- t // Use o tipo da classe como
// o tipo de List
private int maxNum;
public RentalGeneric (
int maxl\trum, l,ist<T> rentalPool) { // o construtor usa um
/ / List do tipo da classe
this.maxNum = maxNum;
)
public T getRental0 { // estamos alugando urn T
// bloqueia aL6 que haja algo disponivel
return rentalPool. get (0) ;
)
public void returnRental (T returnedThing) { // e o locador
// retorna um T
rentalPool . add ( returnedfhing) ;
344 Copitulo 7: Gen6ricos e Conluntos
]
]
Recebemos um erro:
kathy* javacl,. 5 RentalGeneric. java
RentalGeneric. java:38: cannot find symbol
strmbof : method add(Cat)
location: interface j ava. util . List<Car>
carl,ist. add(new Cat ( "Fluf fy" ) ) ;
1 error
Agora temos uma classe Rental que pode ter o tipo definido para qualquer coisa que o programador escolha, e o
compilador forgarS. o uso desse tipo. Em outras palavras, funciona da mesma maneira como as classes de Coniuntos.
Vejamos outroJ exemplos de sintaxe gen6rica qui voc6 poderia encontrar na API ou em c6digo-fonte. Eis uma outra
classe simples que usa o tipo parametr:uado da classe de diversas maneiras:
public class Testcenerics<T> { // aama o tino da elasse
rF anTncf an-o - // como um tipo de vari6vel de instAncia
rF
r ftJ I srl.drrqaeLL-t
:nArr:rrAfTs- // como um tipo de array
T nat_rFl\
YeLr \,
I / J aama rrh l-e4tsv
ind .la
ev rol-drno
return anfnstance;
Obviamente, esse 6 um uso absurdo dos gen6ricos e, na verdade, voce raramente veri gen6ricos fora de conjuntos. Mas
voce precisa entender os di{erentes tipos de sintaxe gen6rica que poderi encontrar, de modo que continuaremos com
esses exemplos at6 que os tenhamos abordado todos.
JAVA 5 345
Voc6 pode usar mais de um tipo parametrizado em uma 6nica definigio de classe:
urdb> rr^^
1;uurre
^,'Lll^ ^r^^^ u>eTwO<T, X> {
T one;
X two;
UseTwo(T one, X two) {
thiq nna = ^na.
rLl ^ r-,^
LITI-.LWU LWU;
-
]
T getT0 { return one; }
getxo { return two; }
!_voc6 podg ular uma forma de notagio com coringa em uma definigio de classe, para especificar um intervalo
(chamado de "limites") para o ripo que poderi ser usado para o parimetro do tipo:
public class AnimalHolder<T extends Animal> { / / use "T" em vez
/ / .16 \\?"
T animal;
public st.atic void main(SLring[] args) {
AnimalHolder<Dog> dogHolder = new Animal-Holder<Dog> ( ) ; // oK
AnimalHofder<Integer> x = new AnimalHolder<Tnteger> ( ) . // NAol
)
se voce chamar o m6todo com um lnteger, o T ser6 substiruido por Integer (nio no bltecode, lembre-se
E, 6 claro, -
estamos descrevendo como ele aparenta se compott"r, e nlo como de fato acontece).
A coisa mais estranha a respeiro dos m6todos gen6ricos 6 que voc6 precisa declarar a vari6vel do tipo ANTES do tipo
de retorno do m6todo:
public <T> void makeArraylist (T t)
O < T > antes de void simplesmente define o que T 6 antes que voc6 o,use como um tiPo no argumento. VocA DEVE
declarar o tipo dessa forro", a ser que ele seja especificado para a classe. Em CreateAnArraylist, a classe nio 6
nio
gentrica,portanto, nio h6 nenhum marcador de parAmetro de tipo que Possamos usar.
VocA tem a opgio tamb6m de colocar limites sobre o lipo qu9 declarar;por exemplo, se q-uiser restringlr o m6todo
makeArrayllst ( ) a apenas Number ou os selrs subiipos (Integer, Float e assim por diante), vocd usaria
public <T extends Number> void makeArraylist(T t)
tipo como T, iw6 priciw t6-/a dutarado 0a c0m0 o k'po de pardnetro da classe oa no mitodo, antes do tipr de retuml. A linha abaixo podetl
Parecer coteta,
Mar a ilnicafonaa de ela ser uilida seia se defato hosuerse lma classe chamadaT, em c{o caso o argumentofunciona como qualqtter oatra
du/amg6o de h'po para ama aaritiael. E qzanto aot argumeltos dl constnttores? Tanbdn eles podem ser dlclarados com am tipo genirico, mas
aifca ainda mais utranbo, uma ue<qile os construtores ndo t4n nenhum tipo de retotwo:
Sim, irofunciona. O X qae i o nome do constnttor ndo tem nlagdo nenhama con a dularag1o de tipo <X>, qile' pzr sila ue7, ndo tem
re/ag6o nenhuma com o identifcador do argumento do consh'ntoy que tambim 6, claru, X, O conpi/ador convguefaryrpasing disso e hata
cada um dot asos de X defonza independente. Asin, ndo ocom nenbum conf/ito entre 0t fllmes das clares, dos narcadores dotpardmetms
de n'pos e dos identifcadores de uari,lueit
tJm dos enganos mais cumafis qte ospmgramadores conetem ao criarvm classes ou mitodos geniricos i asar am 4?t na intaxe do coringa
em aeqde uma uariduel de h'po<T>, 1E), e assin por diante. Este cddigo pode parecer con'eto, mat ndo i:
public class NumberHolder<? extends Number> { }
Enbora o ponto d.e innrrogagdo funcione ao se declarar ama referincia para uma uaitluel, ete NAO funciona para dularapdes de c/ases e
Exercicios ripidos
Aqui estio alguns dos pontos principais do Capitulo 7.
E Use : : para determinar se duas vari6veis de refer6ncia apontam para o mesmo objeto.
O Use ( ) para determinar se dois objetos sio significativamente equivalentes.
equals
E Se voc6 nio sobrescrever equals ( ) , seus objetos nio serlo chaves riteis para tabelas/mapas de hashing.
El Se voc6 nio sobrescrever equals ( ) , dois objetos diferentes nio serio considerados iguais.
O Classes String e wrapper sobrescrevem equals ( ) e se tornam chaves adequadas paratabelx/mapas de hashing.
tr Quando sobrescrever equals ( ) , use o operador instanceof para se certificar de que est6 avaliando uma classe
apropriada.
D Quando ser5, nub: se x nio for nu11, x. equals (nu1l) ser6 falso.
D Sex.equals(y) forverdadeiro,x.hashCode( ) = = y.hashCode( ) deveser true
E Se voc6 sobrescrever equals ( ) , sobrescreva hashCode ( ) '
E As classes HashMap, HashSet, Hashtable, LinkedHashMap e LinkedFlashSet usam hashing.
E Uma sobrescriglo vilida de hashCode ( ) ter6 que se ater ao contrato.
E Uma sobrescriglo eficiente de hashCode ( ) distribuir6 chaves de forma igualit6ria em v6rios dep6sitos.
D Para reiterar: se dois objetos forem iguais, seus c6digos de hashing tamb6m devem ser.
B E vilido que um m6todo hashCode ( ) retorne o mesmo valor para todas as instAncias (embora na pritica
seia muito ineficiente).
E Aspectos do contrato de hashCodeQ que foram realgados:
O Se x. equals (y) for f a1se, x.hashCode ( ) -= y.hashCode ( ) podedser true ou false, mas
false indtcar| uma tend6ncia a gerar mais eficiAncia.
D As vari6veis transiente nio sio apropriadas para equals ( ) e hashCode ( ).
E Conjuntos de itens: Podem ou nio ser ordenados e/ou classificados e a @etigdo ndo dpermitid4
E Mapas de itens com chaves: Podem ou nlo ser ordenados e/ou classificados e a rqeilgdo de chaau ndo i pemitida.
tr Uq Arraylist < Animal > pode aceitar refer6ncias do dpo Dog, Cat ou qualquer outro subtipo de Animal
(subclasse ou, se Animal for uma interface, implementigio).
tr A.o usq conjuntos gen6ricos, nXo 6 necess6ria uma conversio para se obter elementos (de tipo declarado) a panir
do conjunto. Com conjuntos nio-gen6ricos,6 preciso converrer:
List<St.ring> glist = new Arraylist<Strj_ng> ( ) ;
D As atribuig6es polim6rficas aplicam-se somente ao tipo-base, e nio ao parAmetro de tipo gen6rico. Voc6 pode usar
fl A regra.de atribuigio polim6rfica se aplica sempre que uma atribuigio puder ser feita. Os seguintes nia sio
permitidos:
void foo(List<Animal> al,ist) { } // ndo pode usar um List<Dog>
List<Animal> baro t ] // ndo pode retornar um List<Dog>
Q A sintaxe dos coringas permite que um m6todo gen6rico aceite subtipos (ou supenipos) do tipo declarado do
argumento do m6todo:
void addD(List<Dog> d) {} // s6 pode usar <Dog>
void addD(List<? extends Dog>) {} // pode usar <Dogl> ou <Beagle>
O A palavra<have coringa 6 usada para significar ou "estende" ou "implementa". Assim, em <? exLends Dog>,
Dog pode ser uma classe ou uma interface.
QAoseusarumcoringa, List<? extends Dog>,oconjuntopodeseracessado,masniomodificado.
Q Ao se usar um coringa, List<?>, qualquer tipo gen6rico pode ser atribuido i refer6ncia, mas aPenas Para acesso,
e nXo para modificag6es.
QList<Object>refere-seapenasaumList<Object>,enquantoqueList<?>ouList<? extends
obj ect> podem armazanar qudquer tipo de objeto, mas apenas para acesso.
fl As conveng6es de declaraEio para gen6ricos usam T para o tipo e E para o elemento:
public interface List<E> / / DecJ-araglo de API para List
boolean add(E o) // Dec]-araqdo de List.addo
tr O identificador de tipo dos gen6ricos pode ser usado em declarag6es de classes, m6todos e variiveis:
class Foo<t> { } // vma classe
T anrnstance; / / vma variiivel de instdncia
Foo(T aRef) {} // o arqtmento de um construtor
void bar(T aRef ) {} / / o argttmento de um m6t.odo
T bazo {} // vm tiPo de retorno
O compilador fornecerS,o tipo propriamente dito.
B VocA pode usar mais de um tipo parametrizado em uma declaragio:
public class UseTwo<T, X> i i
tr VocA pode declarar um m6todo gen6rico usando um tipo nio definido na classe:
Teste individual
l. Dado:
import java.util.*;
class Test {
public static void main(String[] args) {
Quais opg6es, inseridas em / / insira o c6digo aqui, irio compilar? (Marque todas as corretas)
A. listcstring,> x = new Linkedlist<String> O ;
B.TreeSet<String> x = new Treeset<String>O ;
C.HashSet<String> x = new Hashset.<String> O ;
D. Queue<Stringr> x = new Priorityeueue<Strinq> ( ) ;
E.errayl,ist<String> x = new Araylist<String> ( ) ;
F.f,inkedf,ist<String> x = new Lj,nkedlist<String>O ;
2. Dado:
public static void main(String[] args) {
// INS]RA A DECLARAqAO AQUI
for (int i = 0; j- <= 10; i++; {
List<Integer> row = new Arraylist.<Integer> ();
Quais instrug6es poderiam ser inseridas em / / TNSIRA A DECLARACAO AQUI para permitir que esse c6digo
compile e rode? (Marque todas as corretas)
A. List<List<Integfer>> table = new List<List<Integer>> ( ) ;
B. t,ist<f,ist<Integer>> table = new Arraylist<List<Integer>> ( ) ,.
l. Quais das declarag6es abaixo s6o verdadeiras com relagao comparagdo de duas instincias i
da.mesma claslq, dado que os m6todos equals (
) e halhcode ) foram apropriadamente (
sobrescritos? (Marque todas as corret:N)
A.Seom6todoequals( ) retornartrue,ooperador::decomparagiodehashCode( ) poderetornar
true.
B.Seom6todoequals( ) retornarfalse,ooperador- = decomparaglodehashCode( ) poderetornar
E.rue.
C. Se o operador :: de comparagXo de hashCode ( ) retornar true, o m6todo equals ( ) deve retornar
true.
D. Se o operador = : de comparaSo de ( ) retornar true, o m6todo equals ( ) pode retornar true.
frashCode
E. Se o operador !: de comparagio de hashCode ( ) retornar true, o m6todo equals ( ) pode retornar
true.
4. Dado:
import java.util.*;
class Flubber {
public sEatic void main(String[) args) {
List<String> x - new Arraylist<String>O;
352 Copftulo 7: Gen6ricos e Coniunlos
))
E a saida:
xx
Xx
x
Qual c6digo, inserido em / / insira o c6digo aqu j., produziri a suda acima? $4arque todas as corretas)
E, Comparator c = Collections.reverseorderO,'
Collections. sort (x, c) ;
5. Dado:
10. public static void main(String[] args) {
11. Queue<String> q = new Linkedlist<String> O ;
6. Dado:
public static void before ( ) {
while (it.hasNextO )
Svstem 6lll- nrinj- lif navl-
.rfvr:u l\
\ /
+ \\ $.|.
I I I
C. O m6todo bef ore ( ) exibir6 tr6s ndmeros, mas a ordem nio pode ser determinada.
D. O m6todo before ( ) nio compilari.
E. O m6todo before ( )langari uma excegio no tempo de execugio.
7. Dado:
.i n*^rts
flrLlrur i ar,-
L Jqvq. F .i 1 . * .
,,uLr!
,
class MapEQ {
public static void main(String[] args) {
Map<ToDos, Strj_ng> m = new HashMap<ToDos, String>O;
ToDos t1 = new ToDos("Monday,,);
ToDos t2 = new ToDos ( "Monday,, ) ;
ToDos t3 = new ToDos ( "Tuesday" ) ;
m.put (t1, "dolaundry" ) ;
m.put (t2, "payBi11s" ) ;
m nrrl- /f? rr^la^nAff i^,,\.
qr/ql-am nrrj- nrinl-lnlm cizot\1.
]
class ToDos{
String day;
ToDos(String d) { day = 6' 1
public boolean equals(Object o) {
return ( (ToDos)o).day == this.day;
)
// public int hashCodeo { return 9; }
8. Dado:
12. public class AccountManager {
13. private Map accountTotals = new HashMap0;
14. private int retirementFund;
15.
354 Copftulo 7: Gen|ricos e Coniuntos
25. )
26. j
Esta classe precisa ser atudizada para usar os tipos gen6ricos apropriados, sem modificag6es no comportamento (nem
para melhor nem para pior). Quais destes passos poderiam ser realizados? @Iarque tr6s)
A. Substituir a linha 13 por
private Map<String, int> accountTotals = new HastrMap<String, int> O ;
B. Substituir a linha 13 por
private Map<String, Integer> accountTotals = new HashMap<Strinq, Integer>O;
C. Substituir a linha 13 por
private Map<String<Integer>> accountTotals = new Hash.N{ap<String<Integer>> ( ) t
if (total == null)
total = 0;
return total;
E. Substituir as linhas 17-20 por
9. Dado um array String devidamente preparado, contendo cinco elementos, qual faixa de
resultados poderia ser produzida por uma chamada correta de Arrays.binarySearchQ?
A.0a4
B.0a5
C. -La4
D. -1a5
E. -5a4
F. -5a5
G. -6a4
H. -6a5
JAVA 5 355
10. Dado:
interface Hungry<E> { void munch(E x); }
interface Carnivore<E extends Animal> extends Hungry<E> {}
interface Herbivore<E extends Plant> extends Hungry<E> {}
abstract class Plant { }
class Grass extends Plant { }
abstract class Aninal { }
class Sheep extends Animal implements Herbivore<Sheep> {
public void munch(Sheep x) {}
)
Quais das seguintes modificag6es (feitas separadamente) permitiriam que esse c6digo compilasse? (Marque todas as
corretas)
A. Modificar a interface Carnivore para
int.erface Carnivore<E extends Plant> extends Hungry<E> {}
I l. Que classe de conjunto permitir6 que voc6 aumente ou diminua o tamanho e fornecer6
acesso indexado a seus elementos, nao tendo, por6m, m6todos sincronizados? (Marque
todas as corretas)
A. java.util . Hashset
B. j ava. util . LinkedHashset
C. java. util . List
D. java.util .Anaylist
E. java.util.vect,or
F. java. util . Prioritl4ueue
12. Dado:
i-mport java.util.*;
public class Group ext.ends Hashset<Person> {
356 Copitulo 7: Gen6ricos e Coniuntos
)
nrrhl
y$ry4+!
in hnnlaan :AAfohiont- nt t
]
nla<q Parcnn {
A.Adding Hans
B.addingr Lotte
C. Adding ,fane
D. total: 3
E. total: 5
13. Dado:
'imnnrf i:rr: rrri'1 *.
class AlgaeDiesel {
public static void main(String[] args) {
String[] sa = {"foo", "bar", "baz" };
/ / lnsira as chamadas de m6todos aqui
]
]
Quais m6todos de j ava. util
. Arrays e./ou j ava. util- . Collections voce poderia usar para converter as
em um List e depois procurar no List pelo indice do elemento cujo vaTor 6 "f oo"? (Marque de um a tr& m6todos)
A. sort ()
B.asl,ist ( )
C. tor-ist ( )
D. search ()
E. sortr,ist o
JAVA 5 357
F. contains ( )
G. binarySearch ()
t
Collection<E> longwords = new Arraylist<E> ( ) ;
for (E word : coll)
if (word.lengthO > 6) longWords.add(word);
return lonqWords,.
)
]
Quais declarag6es poderiam ser inseridas em /,/ INSIRA A DECLARACAO aQUr de forma que o programa
compile e rode? (Ir4arque todas as corretas)
A.public static <E extends CharSequence> Collection<? extends CharSequence>
get.Longwords (Collection<E> co11 )
2L. \
qual ser6 o resulmdo?
A. A compilaglo falha
B. one two three four
C. four three two one
D. four one three two
E. one two three four one
F. one four three two one
G. I1 hngada uma excegio no tempo de execuglo.
H. A ordem de exibiEio nio 6 garantida.
output - process(input) ;
Quais pares de declarag6es poderiam ser colocados em / / INSTRA As DECLARACOUS aQur para permitir a
compilagio do c6digo? (Marque todas as corretas)
A.Arraylistclnteger> input = nu1l ;
Arraylist<Integer> output = nul1;
B,ArrayList<Integfer> input = nu1l;
List<Integer> output = nu1l;
C. Arraylist.<Integfer> input = null;
As respostas A, C e E estio incorretas. C est6 incorreta porque o m6todo hashCode ( )6 muito flelvel
em seus valores de retorno e, geralmente, dois objetos diferentes podem retornar o mesmo valor de hashing.
AeEnegamocontratodehashCode( )e equals ( ). (Objetivo 6.2)
4. E esth correta. O ordenamento natural produziria uma saida na seqii6ncia inversa da saida listada. O m6todo
Collections . reverseorder ( ) usa um Comparator, e nio um Comparable, para reclassificar o conjunto.
A, B, C e D estio incorretas com base no exposro acima. (Objetivo 6.5)
5. B esti correta. Hi
um aviso do compilador na linha 19 devido a uma atribuiglo nlo verificada, mas, fora isso, tudo
compila e executa sem erros. Embora tenha sido declarada originalmente como Queue<SLring>, em
showAll O ela 6 passada como um Queue sem tipo especifico - nada no compilador ou naJVM nos impede de
adicionar um Integer depois disso. O m6todo add ( ) coloca itens no final da fila, enquanto que remove ( ) os
redra do inicio da lista, de forma que os itens sio exibidos na ordem em que foram colocados.
6. E est6 correta. Nio 6 possivel colocar Strings e ints no mesmo TreeSet. Sem os gen6ricos, o compilador nio tem
como saber qual tipo 6 apropriado para o TreeSet em questeo, entio ele permite que tudo compile. No tempo de
execugio, o TreeSet tentarS. classificar os elementos ) medida que eles sio adicionados, e, quando tentar comparar
um Integer com uma String, langar6 uma ClassCastException. Observe que, embora o m6todo bef ore ( ) nio use
gen6ricos, ele usa autoboxing. Tome cuidado com c6digo que use recursos novos e antigos misturados.
10. B est6 correta. O problema com o c6digo original 6 que Sheep tenta implementar Herbivore<Sheep> e
Herbivore declara que o seu parametro de tipo E pode ser qualquer tipo que estenda Plant. Uma vez que um Sheep
nio 6 um Plant, Herbivore<Sheep> nio faz sentido - o tipo Sheep est6 fora da faixa permitida do parimetro E
de Herbivore. Apenas solug6es que ou alterem a definigio de um Sheep ou alterem a definigio de Herbivore
poderlo conser[ar isso. Assim, A, E e F estio eliminadas. B funciona: modificar a definiqio de um Herbivore para
permitir que possa devorar Sheep resolve o problema. C nio funciona porque um Herbivore<Plant> precisa
ter um m6todo munch ( Plant ) , e nXo munch (Grass ) . D, finalmente, nio funciona porque, em D, fizemos
'Wolf
Sheep estener Plant, e a classe falha porque o seu m6todo munch ( Sheep ) nio atende mais ao
^gora
contrato de Carnivore. (Objetivo 6.4)
11. D estl coffeta. Todas as classes de conjunto permitirlo que voc6 aumente ou diminua o tamanho de seu coniunto.
O conjunto Arraylist fornece um indice para seus elementos. As classes de conjunto mais recentes tendem a
nio ter m6todos sincronizados. O conjunto Vector 6 uma implementagio mais antiga da funcionalidade de
Aruayl,ist e possui m6todos sincronizados; 6 mais lento que Arrayl,ist.
As respostas A, B, C, E e F estlo incorretas com base na l6gica que esti descrita acima. Observag6es: C, List 6
uma interface e F, PriorityQueue nlo fornece acesso por indice. (Objetivo 6.2)
12. ( ) de Group
F e*6correta. O problema aqui reside no m6todo add
- ele deveria ser add ( Person ) , uma vez que a
Hashset<Person>. Assim, isso nlo compila. Teste ripido: o que aconteceria se voc6 consertasse
classe estende
essec6digo,modificandoadd(object) paraadd(Person)?Tenteexeantaroc6digoparaverseoresultadobate
com o que voce esPerava.
360 Cooitulo 7: Gen6ricos e Coniunios
As respostas A, B, E, F, G e H estio incorretas com base nal6gica que este descrita acima. Observe que, embora
voc6 nio seja mais obrigado a usar um Iterator emJava, pode faz6Jo se quiser. (Objetivo 6.5)
16. B, E e F estio corretas.
O tipo de retorno do processo 6 declarado definitivamente como um List, e nio um Arraylist, de modo que A
eD estio erradas. C est6 errada porque o tipo de retorno resulta em um List<rnteger>, que nio pode ser
atribuido a uma variivel do tipo l,istcNumber>. E claro que todas essas provavelmente causariam uma
NullPointerException, uma vez que as varilveis ainda sio nulas - mas a questio s6 nos pediu parafazer o
c6digo compilar.
Classes internas
Obiefivos porq q
certificoq6o
I Closses inlernos
a/ Exercicios rdpidos
As classes internas permitirio que voc6 defina uma classe dentro de outra. Elas fornecerlo um tipo de escopo para
suas classes j6 que voc6 poderifazer com que uma classe seja membro de outra. Da mesma forma que as classes Possuem
variiveis e m6todos-m.*b.o, tamb6m poiem rer classes-rnembro. Elas v6m em virias vers6es,iependendo d. como
e onde voc6 definir a classe interna, incluindo um tipo especial de classe interna conhecido como 'classe aninhada de
nivel superior" (uma classe interna marcada com static), que tecnicamente nio 6 uma classe interna.Jique uma
classe estitica aninhada nio deixa de ser uma classe definida dentro do escopo de outra classe, tamb6m a abordaremos
neste capitulo sobre classes internas.
Diferente do que ocorre nos outros capitulos deste livro, os objetivosparaaceftificagio sobre classes internas nio t6m
nrimeros oficiais no exame, jiquef.azemparte de outros objetivos abordados em locais diferentes. Portanto, neste capitulo,
os cabegalhos dos objetivos p ara a ceftifLcagio representario os quatro tdpicos sobre classes internas discutidos nele, em vez
de quatro o$etiuosoficiais do exame.
I Classes internas
I Classes internas locais de m6todos
Classes internas
VocA 6 um programador que usa o modelo OO, portanto, sabe que para obter reutilizagio e flexibilidade/extensibilidade
precisa que suas classes sejam especializadas. Em outras palavras, a classe deve ter um c6digo somente para as operag6es que
um objeto desse tipo especifico precise executar; qualque r ltdm comp.ortamenJo deve ser pane de uma classe diferente mais
adequada para essatarefa.As vezes, no entanto, nos vemos projetando uma classe na qual descobrimos ser preciso um
comportamento que pertence a uma classe separada especializada, mas que tamb6m ter6 que estar intimamente associado )
classe que estivermos projetando.
Os manipuladores de eventos talvez sejam o melhor exemplo disso (e, na verdade, uma das principais raz5es por que as
classes internas foram adicionadas i linguagem). Se voc6 tiver a classe de uma interface grifica de wuirio que execute alguma
tarefa como, digamos, um cliente de batepapo; pode querer que os m6todos especificos desse cliente (aceitar entradas, ler
novas mensagens no servidor, retornar entradas do usulrio para o servidor e assim por diante) estejam na classe. Mas,
como esses m6todos serio chamados? O usuirio clicari um botio? Ou digitara algum texto no campo de entradas? Ou
ainda um thread separado que execute a tarefa de E/S de captura de mensagens no servidor ter6 as mensagens que serdo
eibidas na interface? Ponanto, voc6 ter6 m6todos especificos do cliente de bate-papo, mas tamb6m precisari de m6todos
para manipular os "eventos" (pressionamento de bot6es, digitaglo no teclado, E/S disponivel e outros), os quais
controlario as chamadas aos m6todos desse cliente. O cenArio ideal - da perspectiva do modelo OO - 6 manter os m6todos
do cliente na classe ChatClient e inserir o aidigo de maripulagio de event os emrma chsse separada para essa manipulagXo.
At6 agora nio vimos nada incomum; afinal, 6 assim que se sup6e que sejam projetadas as classes do modelo OO. Como
eEecia/istas. Por6m, o problema no cenirio do cliente de bate-papo 6 que o c6digo de manipulagio de eventos estA
intimamente associado ao c6digo especifico desse cliente! Pense bem: quando o usu6rio pressionar um botio Enviar
JAVA 5 363
(indicando que q-uer que a mensagem que digitou sej a enviada para o servidor do bate-papo) , o c6digo do cliente de bate-
papo que enviar6 amensagem ter6 que ler em um campo de texto especifco.Em outras palavias, se o isuirio clicar no botio
A, o programa ter6 que extrair o texto do objeto- TextF ieldB, de ama inttdncia espedfca fu ChatClienr Nlo em algu m otlho
c1ynp9.de texto de um objeto dzferente,mas especificamente no campo de texto que determinada instAncia da cilse
ChatClient referencia. Ponanto, o c6digo de manipulagio de eventos precisar6 de acesso aos membros do objeto ChatClienr,
para que seja rltil como o c6digo "auxiliar" de uma instAncia especifica de ChatClient.
E se ChatClient for derivada de uma classe e o c6digo de manipulagio de eventos estender algu ma outraclasse? Voc6 nio
Pode fazer.com que uma_classe seja derivada de v6rias classes, portanto, inserir todos os c6dig-os (o c6digo especifico do
cliente de bate-papo e o de-manipulagio de eventos) na mesmi classe nlo funcionar6 nesse cio. Entio,6 qui voc6
p^oderiafazerseria se beneficiar da insergio de seu codigo de eventos em uma classe separada (melhor pr6tica no modelo
OO, encapsulapglto e o recurso de estender uma classe diferente da estendida por ChatClient), mas,linda assim,
concedendo a ele f6cil acesso aos membros da classe ChatClient.(para que o c6digo de manipulagio possa, por exemplo,
atualizar xvari6veis de instAncia privadas de ChatClie nt).Y oc€potter; conseg,rii isso fazenio .o-
qrlr or rttembros de'
ChatClient pudessem ser acessados pela classe de manipulagio ao torn6Jos, por exemplo, priblicos.'Contudo, essa
tamb6m nlo 6 uma boa solugio.
Voc6 i6 sabe para onde estamos indo - um dos beneficios principais da classe interna 6 o "relacionamento especial" que a
instdncia de uma classe intemacompanilha com uaa instincia da classe ex.tema. Esse "relacionamento especial" concede ao c6digo
da classe interna acesso aos membros da classe que a estiver encapsulando (externa), como se a claise intemafryrseparte da
extema.Naverdade, 6 exatamente isso que significa: a classe interna dumapane da classe externa. Nio s6 uma "parte', mas
um nembm individual da classe externa. Sim, uma instAncia da classe interna teri acesso a todos os membros da ilasse
externa, mgsTo aque/es marcados comopriuados- relaxe e lembre-se de que o objetivo era esse. Queremos que essa instAncia
especifica da classe interna tenha um relacionamento intimo com a instAncia da classe externa, por6m, mantendo todo o
resto separado. E, al6m disso, se voc6 escreveu a classe externa, enteo tamb6m criou a interna! Ponanto, nio est6 violando o
encapsulamento;voce o prljetlzz dessa forma.
I Estiticas
I Locais de m6todo
I An6nimas
No resto desta seEio, no entanto) usaremos apenas otermo classe internaedescartaremos a palavra clmam quando
-
passarmos para um.dos outros tr6s tipos da lista anterior, voc6 saber6. Defina a classe interna dentro das chaves da classe
externa como descnto a segurr:
alacc Mrrflrrt-ar I
class Mylnner { }
Sjavac Myouter.java
terminar6 com /oziarquivos de classe:
MfOuter.dass
MlOuter$Mykrner.class
A classe interna continua sendo uma classe separada, portanto, um arquivo de classe 6 gerado. Entretanto, voc6 nio poder6
acessar o arquivo da classe interna da maneira usual. Nio poder6, por exemplo, escrever:
*java MyOuter$MyInner
esperando executar o m6todo main ( ) da classe interna, porque uma classe inte rna comam ndo possui declarag6es estiticas
de nenhum ipo. A iinica maneira de uocd conseguir acessar a classe interna seni por meio de una instdncia afiua da c/are externalEm
outras Palavras, s6 no tempo de execugio quando ji houver uma instAncia da classe externa a qual associar a instAncia da
classe interna. VocA veri tudo isso em breve. Primeiro, aperfeigoaremos um pouco as classes:
nlacc MrrArrtar I
private int x = 7;
Instanciando uma classe interna a partir do c6digo da classe externa Geralmente, 6 a classe externa que cria instincias
da classe interna, ji que 6 ela que costlrma usar a instAncia interna como objeto arxiliar para seu uso pessoal. Vamos alterar a
classe M@ter para que irstancie Mylnner:
nlaec Mrzf)rrt.ar {
private int x = 7;
public voj_d makefnnerO {
a l a << Mr;Tnnar I
Vod podever no exemplo anterior que o c6digo de MyOutertrataMylnner exatamente como se fosse qualquer outraclasse
que pudesse ser acessada - ele a instancia usando o nome da classe (new Myrnner )) e, em seguida, chama um (
m6todonavari6veldereferdncia(in.seeouter( )).Contudo,ainicarazloporqueessasintaxefunciona|queo
c6digo do m6todo de instAncia da classe externa est6 criando a instAncia. Em outras pal avras,ja existe tma inst1ncia da classe
erterna- a instdncia qae estd execatando o mdtodomakelnner ( ) . Ponanto, como voc6 instanciari um objeto Mylnner de
algum local fora da classe MyOuter? Isso 6 ao menos possivel? @em, j6 que teremos o trabalho de criar um novo subtitulo
para esse assunto, como voc6 verA a seguir, o grande mist6rio nio ser6 resolvido aqui.)
Criando um obieto de classe interna fora do c6digo da instincia da classe externa Uau! Esse 6 um grande
subtitulo, mas realmente explica o que tentaremos fazer. quisermos criar uma instAncia da classe interna, 6 preciso ter
Se
uma instAncia da classe externa. Voc6 j6 sabe disso, mas pense nas implicag6es... Significa que, sem uma referbnciaauma
instAncia da classe externa, nio poderi instanciar a classe interna a partir de um m6todo static da classe externa
(porque, nio esquega, no c6digo static ndo hd a referdncia Lhis) ou de qualquer outro c6digo de alguma classe
diferente. As instAncias de classes internas sempre recebem uma refer6ncia implicita ) classe externa. O compilador se
encarrega disso, portanto, vocA nunca ver|nada,s6 o resultado final - o recurso que tem a classe interna de acessar
membros da classe externa. O c6digo para criar uma instAncia de qualquer local fora do c6digo nio-static da classe
externa 6 simples, mas voc6 deve memorizar isso para o exame!
public static void main (String[] argrs) i
Marnrrf
lrJvsuv! 6r MrrArrf
rlJvuLst ar f\, \ ,.
O c6digo anterior 6o mesmo, independente de o m6todo main ( ) estar dentro da classe MyOuter ou de algoma ouha
classe (supondo-se que a outra classe tenha acesso a MyOuter, e ji que essa tem acesso padrXo, isso significa que o c6digo
JAVA 5 365
deve estar em uma classe do mesmo pacote de MyOuter).
Caso goste de c6digos curtos, poder6 faz6-lo desta forma:
public static void main(String[1 args) 1
MyOuter. Myfnner
e para instanciar, vocA precisa usar uma referAncia i classe externa,
I A refer6ncia thi s
6 a maneira de um objeto passar uma refer6ncia dele pr6prio para algum outro c6digo, como
argumento de um m6todo:
public void myMethodO {
class MyOuter {
Private int x = 7;
public void makelnner ( ) {
Myfnner in = new MyInner0;
in.seeOuterO;
]
class Mylnner {
publj-c void seeOuterO {
System.out.println("Outer x is " + x) ;
System.out.println("Inner class ref is " + this);
System.out.println("outer cfass ref is " + Myouter-this);
]
)
public scatic void main (String[] argrs) {
MyOuter . MyInner inner = new MyOuter O . new MyInner O ;
inner. seeOuter ( ) ;
asaidaseri:
Outer x is 7
Inner class ref is Myouter$MyInner@113708
Outer class ref is MyOuter@33f1d7
Poftanto, as regras para uma classe interna que aponte para si pr6pria ou para a instancia externa sAo as seguintes:
I P ara re{erenciar a instAn cia da pr6pria classe interna , de dcnhv do c6digo dessa classe, use thi s .
I Para apontar para a refer6ncia " thi s ex'terna" (instAncia da classe externa) de dentro do c6digo da classe interna, use
NomeDaClasseExterna. this (exemplo, MyOuter . this).
Modificadores de membros aplicados a classes internas A classe interna comum 6 um membro da classe
externa, exatamente como os m6todos e variiveis de instAncia, portanto, os modificadores a seguir podem ser aplicados a
umaclasse interna:
I final
I abstract
I public
I private
I protected
I static - a excepio d qae sLatic a ttma uma classe aninhada de niuel supeior, em ueqde uma classe intema.
I strictfp
cl-ass Myouter2 {
a'lacc MrrOrrfar? I
mi. seeout.er O ;
) / / fecha o m6todo doStuff ( ) da classe externa
I // fecha a classe externa
Pense bem. As variiveis locais do m6todo residem na pilha e s6 existem conforme a duraglo do m6todo. VocA ji sabe que o
escopo de uma variivel local 6 limitado ao m6todo em que foi declarada. Quando o m6todo 6 fin alizado, o quadro da pilha
6 eliminado e a vari6vel vira hist6ria. Contudo, mesmo depois que o m6todo 6 concluido, o objeto da classe interna criado
denrro dele ainda pode estar ativo no heap se, por exemplo, uma referAncia_a ele tiver sido passada para algum outro c6digo
e, em seguida, arriazrnada em uma vari6vel de instAncia. J6 que.as vari6veis locais nio t6m_ garantia de continuarem ativas
por tanto tempo quanto o objeto da classe interna local de m6todo, esse objeto_nio pode usi-las. A menor qae as umiiueis
locais vlan maridas cono f inal.'lO c6digo a seguir tenta acessar uma varilvel iocal de dentro de uma classe interna local de
metoclo:
class MyOuter2 {
hl-t r. r.f.
\,roleTtvo poro o centttcocoo
Classes internas an6nimas
At6 agora examinamos a definigio de uma classe dentro de outra classe encapsuladora (uma classe interna comum) e dentro
de um m6todo (uma classe interna local de m6todo). Para concluir, examinaremos a sintaxe mais incomum que voc€ veri
emJava: classes internas declaradas sem qualquer nome (dai a palavr a an6nina).E se isso nio fo. estrarrho o bastante, vocA
poderi at6 mesmo definir essas classes nio s6 dentro de um m6todo, mas no argumento de um m6todo. Primeiro,
clrscutiremos a versio (na verdade, at6 essa versio subdivide-se em duas outras) simples (como se existisse algo do tipo
classe interna an 6nima imples)e, em seguida, a classe interna an6nima decl arada no argomento.
Talvez sua tarefa mais importante aqui seja aprender a ndo se confundir quando se d.eparar com essa intaxe. O exame est6 repleto de
c6digos com classes internas an6nimas. 56 para ter uma id6ia, voc6 poderi v6-los em perguntas sobre threads,
wrappeobre, sobrescrigio, coleta de lixo, etc.
cl-ass Food {
I Food tem uma variivel de instAncia, declarada com o tipo Popcorn. Isso 6 tudo quanto i Food. Essa classe nattem
m6todos.
E aqui esta o ponto importante a captari
A variivel de referAncia Popcorn ndo aponta para uma instAncia de Popcorn, mas para a instdncia de ana subclasse
an6nina (ndo noneada) de Popcorn.
6. j;
Linha2 A linha 2 comega como uma declaragio de vari6vel de instAncia do tipo Popcorn. Mas, em vez de ter este
formato:
Popcorn p = new Popcorn (\ ; / / repare no ponto-e-virgula ao final
-
h6 uma chave no final da linha2, onde normalmente estaria um ponto-e-virgula
Popcornp = new Popcorn(\ { // _uma chave emvez do ponto-e-virgula
Voc6 pode ler a linha 2 como:
"Declare uma variivel de referAncia, p, do tipo Popcorn. Em seguida, declare uma nova classe que nio tem
nome, mas 6, uma sbclasse de Popcorn. E agora temos a chave que abre a definigio da classe..."
Linha 3 Em seguida, a linha 3 6, na verdade, a primeira instrugio dentro da definigio da nova classe. E o que ela
faz? Sobrescreveu o m6todo pop ( ) da superclasse Popcorn. Aqui este o ponto crucial da criagio de uma classe
interna an6nima: sobresmuer am ou mais mtitodos da saperclasse (ou implementar m6todos de uma interface, mas
guardaremos isso para mais tarde).
Linha 4 Alinha46aprimeira (enesse casoailnica) instruglodom6todopop( ) novo. Nadaespecialaqui.
Linha 5 A linha 5 cont6machave defechamento do m6todopop( ). Nadaespecial aquitamb6m.
Linha 6 E aqui que vocA ter6 que prestar atengeo: a linha 6 inclui uma chauefechando a defnipdo da classe andnina (6 a
chave que acompanha a da linha 2), por6m, aindah| mais! Essa linha tamb6m tem 0 plnto- e-uirgula qaefnali7a a inshztgdo
iniciada na linha 2, instruglo em que tudo comegou - a que declara e inicializa a vari6vel de referAncia Popcorn.
Portanto, terminaremos com uma referAncia de Popcorn a uma instAncia rec6m-criada da novissima rubclasrc
an6nima (sem nome) instantAnea de Popcorn.
?
zt Dnnnnrn
rvvuvlr] n
P - iar^r
rrefv Dnnnnrnf
rvyevlrr\/ \ {
-
2 ^,,1-1
Puvrfe ^ -.^;
.i
vvr d pop ( ) i
4. SysLem.out.println("anonymous popcorn") ;
O polimorfismo entra em cena quando classes intemas an6nimas estlo envolvidas. kmbrese & q*, como no exemplo
antarior de Popcorn, estamos usando o tipo da vari6vel de referAncia de uma superdasse para referenciar um objao da
zubclasse. Quais sio as implicag6es? Vod s6 poder6 chamar os m6todos da refer6ncia de uma classe interna an6nima que
forem definidos no tipo davaiilelde referAncia! Iso nlo 6 diferente de qualquer outra referAncia polim6r{ic4 por exemplo:
370 Copitulo B: Clqsses internos
]
c]ass test {
public static void main (String[] args) {
Animalh=newHorseo;
h.eatO; / / V61ido, a classe Animal tem r.m m6todo eato
h.buckO; // Inv6lido! A classe Animal- nao tem buck()
]
]
Portanto, no exame, voc6 ter6 que ser capaz de identificar uma
classe interna an6nima que, em vez de sobrescrever
um m6todo da superclasse, defina seu pr6prio m6todo novo. A definiglo do m6todo nlo 6 o problema, no entanto;
o que impona realmente 6 como vocA chamari esse novo m6todo. O tipo da variivel de refer6ncia (a superclasse)
nio terA nenhuma informagdo sobre esse mltodo (definido na subclasse an6nima), e o compilador reclamarA se
voc6 tentar chamar qualquer m6todo na referAncia de uma classe interna an6nima que nXo esteja na definiglo de
classes da superclasse.
]
cLass Food {
^,,1-1
Puvffu ^ ,,^r,{ sizzle ( )
.i
vvrs t
System. out.println ( "anonymous sizzling popcorn" );
]
public void pop ( ) {
System. out.println ( "anonlmous popcorn" ) ;
]
];
]
]
A compilaglo do c6digo anterior nos dara,
Anan i:rr: . 1q ' .^nh^f racnl rrav crmlln
uJ f L'!vr l
que 6 a maneira de o compilador dizer: "NXo consigo encontrar o m6todo sizzle ( ) na classe Popcorn",
seguido de: "Consiga uma pista".
JAVA 5 371
Classes internas an6nimas simples, versio dois
A rlnica diferenga entre as vers6es um e dois 6 que a primeira cria uma subclasse an6nima do tipo de classe
especificado, enquanto a verslo dois cria um implerueitador an6nimo do tipo de interface especificado. Nos exemplos
anteriores, definimos uma nova subclasse an6nima do tipo popcorn como vemos abaixo:
Popcorn P = new PopcornO {
Mas, se Popcorn fosse um tipo de intefaa emvez de um tipo de classe, entAo a nova classe an6nima seria um
inp le n e n tador da i n terface em v ez de uma s u b t las s e da c las s e, Examine o exemplo abaixo :
interface Cookable {
public void cook();
)
class Food {
Cookable c = new Cookableo {
public void cookO {
System. out.println ( "anon)rmous cookable implementer" ) ;
]
];
]
O c6digo anterior, como o exemplo de Popcorn, tamb6m cria a instAncia de uma classe interna an6nima, mas, dessa vez,
a nova classe instantanea 6 um implementador da interface Cookable. E 6 bom ressaltar que essa ser6 a rinicavezqlre
voc6 ver6 a sintaxe,
new Cookable ( )
como: "Declara uma varilvel de referAncia do tipo Cookable que, obviamente, apontarl para um objeto da classe que
implementarainterfacecookable.Mas,ahsim,aindanio temotumaclassequeimplementeCookable,portanto,
cflaremos uma agora mesmo. Nio precisamos de um nome para a classe, mas ela seri uma classe que implementar6
Cookable, e essa chave iniciar6 a definigio da classe implementadora".
Mais uma coisa a memorizar sobre implementadores an6nimos de interface: eles podem implewentar sowefite uma inte(ace.
Simplesmente, nlo h6 um rnecanismo que defina que sua classe interna an6nima ir6 implementar virias interfaces. Na
verdade, uma classe interna an6nima nio pode nem estender uma classe e implementar uma interface ao mesmo tempo. A
classe interna precisa da definiglo de se ir6 ser a subclasse de uma classe nomeada - e de maneira alguma ir6 implementar
diretamente qualquer interface - az se implementari uma rinica interface. Por "diretamente", queremos dizer usando a
palavra-chave implements como parte da declaragio da classe. Se a classe interna an6nima for uma subclasse do tipo de
uma classe, ela se tornari automaticamente um implementador de qualquer interface criada pela superclasse.
oBSERVAQ6ESpeneOE)(AME
l,{60 se deixe enganar por qaalquer tentatiua de instanciagdo de intefan que ndo s/a uma clase intema an6nima. A linha a tegair ndo 6
u,llida,
gostariamos de nos responsabilizar completamente pela confusio. Por6m, ficaremos felizes em compartilhar.
Certo, se voc€ chegou a essa sentenga presumiremos que voc6 compreendeu a segio anterior e adicionaremos
apenas uma nova alteragio. Imagine oien6rio a seguir. Voc€ est6 digitando, tentando criar a classe perfeita, e
.i.r.n. o c6digo que chama um m6todo em um objeto ear e usa um objeto do tipo Foo (uma interface).
cfass MyWonderfulClass {
void go0 {
Barb=newearo;
b.doStuff(AckweDon'tHaveAFool) i / / Nao tente compilar isso em casa
]
in|-ovf:aa Fna I
void foof O ;
]
class Bar {
void doStuff(Foo f) { }
Sem problemas, exceto por voc6 nlo ter-o objeto de uma classe que.implemente Foo. Contudo, tamb6m nio.pode
instanciar um, porque nem mesml tem umaclasse que implenenteFoo, o que dizer da instAncia dela. Assim, primeiro voc0
precisa de uma classe que implemente Foo e, em seguida, precisar6 de uma instAncia dessa classe que ser6 passada para o
m6tododoStuff ( )daclasseBar.SendoumprogramadorJavaastuto,voc6simplesmentedefiniriumaclasseinterna
an6nima, dentro do argumenlo. Exatamente, logo onde voc6 menos esperaria encontrar uma classe. E aqui est6 o formato de
seu c6digo:
1. class MyWonderfulClass {
2. void goO {
3. Barb=newBarO;
A
b.doStuff(new FooO {
5. n,,1-r1 ia r,^.i^ +^^f o {
6 q\tqfpm arrt. nrinfln / \f^^f\r/ \ .
7. j // final-izaom6todofoof
8, j) ; / / finaliza as instruq6es def, arg' e end da classe interna
9. j // finalizago(l
L0. j // final-iza a classe
11.
12. interface Foo {
13. void foof ( ) ;
14. ]
15. class Bar {
L6. void doStuff(Foo f) { }
1,7. \
Toda a agio comega na linha 4. Estamos chamando doStuf f(
) em um objeto Bar, mas o m6todo usa uma instAncia
que E-Um Foo, em que Foo 6 uma interface. Ponanto, temos que criar tanto um a clxse de implementagdo quanto uma
instdnciadessaclasse, tudo bem aqui no argumento de doStuf f(
) . EntXo,6 o que faremos. Escreveremos
new FooO {
para iniciar a nova definigio da classe an6nima que implementar6 aintertace Foo. Foo s6 tem um m6todo a implementar,
f oof ( ) , portanto, nas linhas 5, 6 e 7 implementamos esse m6todo. Em seguida, na linha 8 - calma! - aparece mais uma
sintaxe estranha. A primeira chave fecha a nova definiglo da classe an6nima. Mas, nio esquega que isso tudo
ocorreu como parte do argumento de um m6todo, de modo que o par6ntese de fechamento ')' finaliza a chamada
do m6todo, e ainda temos que encerrar a instruQio que comeqou na linha 4; assim, finalizaremos com um ponto-e-
virgula. Esiude essa sinta*ei YocE ueri classes internai an6nimas no exame e teri que ser muito cuidadoso com a
JAVA 5 373
maneira como sao fechadas. Se elas forem locais de argumento, terminario assim,
));
mas se forem classes an6nimas simples, entao, sereo finalizadas assim:
j;
De qualquer forma, a sintaxe nio 6, a que voc6 usar6 em praricamenre qualquer outra parre da linguagem
Java,
Poftanto, seja cuidadoso. IJma pergunta de alguma pane do exame pode envolver claises internas an6nimas
constituindo o c6digo.
As ,r.zes, ouvimos falar de classes est6ticas aninhadas como classes aninhadas de nivel superior ou classes internas
e$dticas, mas elas nio sio de maneira alguma classes internas, pela definigio padrio de uma classe interna.
Enquanto uma classe interna (independente da versio) se beneficia do relacioianento especial com a classe externa (ou,
emvez disso, poderiamos dizer qve as iilstdncias das duas classes compartilham um rilacionamento), uma classe
estitica aninhada nio tem esse privil6gio. EIa simplesmente 6 uma cLsse nio-interna (tamb6m conhecida como
"de nivel superior") cujo escopo se encontra dentio de outra classe. Ponanto, quando'se trata de classes estiticas,
na verdade, a resolugio do nome-espago conta mais do que um relacionamento implicito entre as duas classes.
IJma classe aninhada estatica 6 simplesmente aqaela que d um merybro utdtico da classe encapsulatlora, como vemos abaixo:
class BigOuter {
static class Nested { }
A classe propriamente dita nio 6 realmente "est6tica"l nio existem classes est6ticas. O modificador static,
nesse caso, informa que a classe aninhada 6. um membro utitico da classe extema.Isso significa que ela pode ser acessada,
como qualquer outro membro estAtico, sem ter tma instdncia da c/asse extema.
]
class Broom {
static class 82 {void goB2( ) { System.out.println(..hi 2,,\; } }
public static void main(String[ ] args) {
Bigouter.Nest n = new Bigouter.Nest( ); // an,bos nomes de cl_asses
n.go( );
82b2= new82( ); // acessa a classe interna
b2.goB2( );
O que produz
hi
r]i2
374 Copitulo B: Closses inlernos
A seguir examinamos as classes internas locais de m6todo - classes definidas dentro de um m6todo. Vimos que o c6digo
de uma classe interna local de m6todo parece vinualmente igual ao de qualquer definig1o de classe, exceto por nlo.ser
possivel aplicar um modificador de acesso da maneira que sio usados em uma classe interna comum. VocA tamb6m
aprendeu por que as classes internas locais de m6todo nio podem usar variiveis locais que nio seiam finais declaradas
dentro do mesmo m6todo - a instAncia da classe interna pode ter uma sobrevida depois que sair do quadro da pilha,
portanto, a variivel local po& desaparecer, enquanto o objeto da classe interna ainda estar6 ativo. Mostramos que, Para usar
i classe interna, voc6 precisa irstanii6-1a e que a instanciagio deve vir depois da declaragio da classe no m6todo.
Tamb6m examinamos o tipo de classe interna mais estranho de todos' a classe interna an6nima. Voc6 aprendeu que elas
v6m em duas formas: simples e local de argumento. As classes internas an6nimas, digamos, normais, sio criadas como
parte da atribuigio de umi vari6vel, enquanto as classes internas locais de argumento, na verdade, sio declaradas, definidas e
automaticamente instanciadas dentro do argumento de um m6todo! Abordamos a maneira como as classes internas
an6nimas podem ser uma subclasse do tipole classe nomeado ou um implementador da interface nomeada. Para concluir,
examinambs como o polimorfismo 6 aplicado a classes internas an6nimas' voc6 s6 pode chamar na nova instAncia os
m6todos definidos com o tipo de interface ou classe nomeada. Em outras palavras, mesmo se a classe interna an6nima
definir seu novo m6todo, nenhum c6digo externo a ela poder6 chamar esse m6todo.
Como se j6 nio estiv6ssemos nos divertido o suficiente para um dia, passamos para as classes internas est6ticas, que, na
verdade, nio sio classes internas. Conhecidas como classes aninhadas est6ticas, uma classe aninhada marcada com o
modificador s tat i c 6 bem semelhante a qualquer outra classe nio interna, exceto pelo fat o de que pan acess6-la, o
c6digo deve ter acesso tanto ) classe aninhada quanto ) classe encapsuladora. Vimos que como a classe 6 estitica, nenhuma
instAncia da classe encapsuladora 6 necessiria e, portanto, a classe aninhada est6tica nlo compartilha um relacionamento
especial com nenhumi instAncia da classe encapsuladora. kmbre-se de que as classes internas est6ticas nio sio capazes de
acessar m6todos ou vari6veis de instincias.
Exercicios ripidos
Aqui estXo alguns dos pontos principais deste capitulo.
Classes internas
E Uma classe interna "comu m" 6, declaradadentro das chaves de outra classe, mas fora de qualquer m6todo ou outro
bloco de c6digo.
E A classe interna 6 um membro individual da classe encapsuladora
(externa), portanto, pode ser marcada com um
modificador de acesso, assim como com o modificador abstracL ou f inal (mas 6 claro que nunca com ab-
stract e f inal ao mesmo tempo - lembre-se de que abstract significari que ela deve ter subclasses,
enquanto final quer dizer que ela nXo pode ter subclasses).
E A instAncia da classe interna companilhari um relacionamento especial com uma instAncia da classe encapsuladora.
Esse relacionamento concederi ) classe interna acesso a todos os membros da classe externa, incluindo os
marcados com private.
fl Para instanciar uma classe interna, voc6 precisa ter uma refer6ncia i instAncia da classe externa.
E A partir do c6digo da classe encapsuladora, vocA pode instanciar a classe interna usando somente o nome dela,
como vemos abaixo,
Myfnner mi = new MyTnner ( ) ;
JAVA 5 375
E A partir de um c6digo externo aos m6todos de instAncia da classe encapsuladorq vod pode instanciar a classe
interna usando somente os nomes das classes interna e extema e uma refer€ncia i classe extern4 como
no c6digo abaixo:
Myouter mo = new MyOutero;
Myouter.Myfnner inner = mo.new MylnnerO;
D A partir de um c6digo dentro da classe interna, a palavra-chave this pode armazenar uma refer6ncia i
instAncia da classe interna- Para apontar para a refer|ncia this .*t.rrr" (em outras palavras, a instAncia da
classe externa a qual essa instincii interna esti associada) anteceda a palavra-charr. i5i" com o nome da
classe externa como na linha abaixo:
MrzOrri- ar thi c.
D A classe interna an6nima pode estender uma subclasse azr implementar uma interface. Diferente das classes nio.
an6nimas (internas ou nio), uma classe interna an6nima nio pode fazer as duas coisas. Em outras palavras, nio pode
e$ender uma classe e implementar uma interface, nem implemlntar mais de uma interface.
E Uma interna de argumento local 6 declarada, definida e automaticamente instanciada como pane de uma chamada
classe
de m6todo. O importante a lembrar 6 que a classe estar6 sendo definida dentro do argumento de um m6todo, portanto,
a sintaxe finalizariadefinigio da classe com uma chave, seguida de um par6ntese de feihamento para encerrar alhamada
do m6todo, que ainda ser6 seguido por um ponto-e-virgula, o qual fechari a instruEio: ] ) ;
tr J6 que a classe aninhada 6 estdtica, nio compartilha nenhum relacionamento especial com uma instAncia da classe externa.
Naverdade, voc6 nio precisa de uma instAncia da classe extgrnapara instanciarumaclasse aninhadaest6tica.
E Instanciar uma classe aninhada estitica requer o uso tanto do nome da classe enerna quanto o da aninhada, como
vemos abaixo:
D Uma classe aninhada estitica nlo pode acessar membros nioest6ticos da classe extern4 ji que nio tem uma refer6ncia implicita
a nenhuma instAncia externa (em outras palavras, a instAncia da classe aninhada nio usa uma referAncia thi s orterna) .
Teste individual
As perguntas a seguir o ajudario a avaliar sua compreensio do material dinAmico e transcendente apresentado
neste capitulo. Leia todas as opg6es com cuidado. Selecione todas as resposras corretas para cada pergunta. Nlo se
apresse. Relaxe.
]
que instruglo, se inserida em uma classe diferente de MyOuter ou Mylnner, criar6 uma instAncia da classe aninhada?
2. Quais das declarag6es abaixo s6o verdadeiras com relagao i classe aninhada estetica? (Marque
todas as corretas)
A Voc6 precisa ter uma referdncia ) instAncia da classe encapsuladora para instanci6-la.
3. Dado:
public interface Runnable { void run( ); }
O que cria a instAncia de uma classe interna an6nima? Qr4arque todas as corretas)
A.Runnabler=newRunnable( ) { };
B.Runnable r = new Runnable(public void run( ) { });
C.Runnable r = new Runnabfe{public void run( ) { }};
D. Runnable r = new Runnable ( ) {public void run{ } };
E. System.out.println(new Runnable( ) {public void run( ) { }});
F. System. out.println (new Runnable (public void run ( ) { } ) ) ;
4. class Test {
5. publj_c static void main (String [] args) t
6. Foo f = new FooO;
7 . / / Trq; r: n n,idi ^n =qui
8. ]
9.]
que instruglo, inserida na linha 7, criari uma instAncia de Bar? (l\4arque todas as corretas)
6. Quais das declarag6es abaixo s6o verdadeiras com relagao a uma classe interna local de
m6todo? (Marque todas :N correhs)
A Ela deve ser marcada com f i-nal.
B. Elapode ser marcada com abstract.
C Elapode ser marcada compublic.
D. Ela pode ser marcada com stat.ic.
E. Ela pode acessar membros privados da classe encapsuladora.
7. O que 6 verdade com relagao ) classe interna an6nima? (Marque todas as correhs)
,4" Ela pode estender somente uma classe e implementar apenas uma interface.
B. Ela pode estender somente uma classe e implementar v6rias interfaces.
C Ela pode estender somente uma classe ou implementar apenas uma interface.
]
nrrhl ic <j- :l- ic rrnid main /qt- rina f l :ra<) {
C. foobarhi
D. barhi
E. hi
10.)
qual ser6, o resultado?
A. Uma excegio ocorreri no tempo de execugio.
B. true
L. ralse
D. A compilagio falhari por causa de um erro na linha 3.
3. class Horse {
4. public String name;
5. public Horse(String s) {
5. name = s,.
t. )
8. ]
9. Object obj = new Horse ( "Zippo,') ;
10. System.out.println(obj.name) ;
1.r. )
12. j
qual ser6 o resultado?
A. Uma exceglo de tempo de execugio ocorrer6 na linha 10.
B. zipppo
C. A compilagdo falharipor causa de um erro na linha 3.
D. A compilagio falhari por causa de um erro na linha 9.
A repo*a A esti incorreta porque classes aninhadas est6ticas nio precisam (e nio podem usar) de uma referAncia )
instAncia da classe encapsulidoia. C esti errada porque as classes aninhadas est6ticas podem declarar e definir membros
nio-estlticos. E estl iniorreta porque... Simplelmente est6. Nlo h6 uma regra que diga que uma classe interna ou
aninhadatenha que estender algo.
3. E estA correta. Ela define a instAncia de uma classe interna an6nima, o que tamb6m significa que ao mesmo tempo cria
uma instAncia dessa nova classe an6nima. A classe an6nima 6 um implementador da interface Rur:nable, portanto,
deve sobrescrever o m6todo run () de Runnable.
A resposta A est6 incorreta porque nlo sobrescreve o m6todo run ( ), portanto, viola as regras da
implementagio de interfaces. B, C e D usam a sintaxe incorreta.
4. B e C. A resposta Best6 correta porque as classes internas an6nimas nio slo diferentes de nenhuma outra
classequando se trata de polimoifismo. Isso significa que vocA sempre poder6 declarar uma vari6vel de
refer€niia do tipo da superclasse e ter essa vari|vel referenciando a instincia de um tipo da subclasse, que,
nesse caso, 6 uma subclasse an6nima de Bar. Ji que Bar 6 uma subclasse de Boo, tudo funciona. C usa a sintaxe
correta para a criaglo de uma instAncia de Boo.
A resposta A esti incorreta porque passa um tipo int para o constnrtor de Boo, e nio hi um construtor
coincidente na Boo. D est6 errada porque viola as regras do polimorfismo; voc6 nio pode referenciar
classe
um tipo da superclasse usando uma variivel de refer6ncia declarada com o tipo da subclasse. NXo 6 garantido
que a superclasse tenha tudo que a subclasse possui. E usa a sintaxe incorreta.
f,. B est6 correta porque usa a sintaxe certa - emprega os dois nomes (das classes externa e interna) na declaraEio
da refertncia, utilizando, em se gwda, uma referbncia ) classe ext erna para chamar new na classe interna.
As repostas A, C, D e E usam a sintaxe incorreta. A esti incorreu porque nio usa uma refer6ncia ) classe externa, e
tamb6m porque inclui os dois nomes na instrugio new. C est|ercadaporque n5o usa o nome da classe externa na
declaraglo da variivel de referAncia e porque a sintaxe de new nio esti correta. D est6 incorreta porque nio usa o nome
da classe externa na declaragio da variivel de refer6ncia. E est6 errada porque a sintaxe de new est6 incorreta.
6. BeE.ArepostaBesticorretaporqueumaclasseinternalocaldem6todopodeserabstract,emboraissosignifique
a necessidade da criagio de uma subclasse da classe interna se a classe abstract for usada (ponanto,6 improv6vel
que uma classe interna local de m6todo abstractseja ritil). E est6 correta porque uma classe interna local de m6todo
funciona como qualquer outra classe interna - tem um relacionamento especial com uma instincia da classe externa, de
modo que pode acessar todos os membros dessa classe.
A resposta A est6 incorreta porque uma classe interna local de m6todo nio precisa ser declarada como f inal (embora
seja viiido faz€-lo). C e D esteo erradas porque uma classe interna local de m6todo nio pode ser public
(embre-se de que voc6 nio pode marcar nenhuma variivel local com public) ou static.
7. C esth correta porque a sintaxe de uma classe interna an6nima s6 permite um tipo nomeado depois de.new, e
tipo tem que ser apenas uma interface (caso no qual a classe an6nima implementari essa interface) ou
esse
vma inica classe (situag5o em que a classe an6nima estender6 essa classe).
As respostas A, B, D e E estXo todas incorretas porque nio seguem as regras da sintaxe descritas na resposta
JAVA 5 381
C.
8. C esti correta pgrgue primeiro a instAncia de Foo 6 criada, o que significa que o consrnrtor de Foo foi
executado e exibir6 foo. Aseguir, o m6todomakeBar( I 6 chamldo, o que criaumainstAnciade Bar,
significando que o constnrtor de Bar foi executado e exibir6 barl e, para concluir,6. criadauma instAncia (de
um subtipo an6nimo de Bar) partir da qual o m6todo go0 6 chamJdo. Repare que a linha (new Bar ( ) {
] ) . so ( ) ; cria uma pequena^ classe interna an6nima, um subtipo de Bar.
As respostas A, B, D, E e F estXo incorretas com base na l6gica do programa que esd descrita acima.
9. G. Esse c6digo seria vilido se a linha 7 terminasse com um ponto-e-virgula. Lembre-se de que a linha 3 6 uma
instrugio que nio termina at6 a linha 7 e, como instrugio, precisaria de um ponto-e-virgulicomo fechamento!
As respostas $ B, C, D, E e F estio incorretas com base nal6gica do programa descrita acima. Se o ponto-e-
virgula fosse adicionado i linha 7, entio a resposta B estaria correta - o programa exibiria true, o retbrno do
m6todo equals ( ) sobrescrito pela subclasle an6nima de obj ect.
10. B. O c6digo da classe FlorseTest 6 perfeitamente v6lido. A linha 9 cria uma instAncia da classe interna local de
m6todo Horse, usando uma variivel de refer6ncia declarada com o tipo Object. A linha 10 converte o objeto
Horse na vari|vel de refer6ncia Fforse, o que permitir6 que a linha 11 seja compilada. Se a linha 10 fosse
removida, o c6digo de HorseTest nio seria compilado, porque a classe Object nio tem uma vari|vel name.
As repostas A, C, D, E e F estio incorretas com base na l6gica do programa que est6 descrita acima.
11. E. Esse c6digo 6 semelhante ao da pergunta L0, exceto pela instrugio de converslo ter sido removida. Se voc6
usar uma vari6vel de refer€ncia do tipo obj ect, poderi acessar somente os membros definidos na classe
Obj ect.
As repostas A, B, C e D estio incorretas com base na l6gica do programa que esd descrita acima.
12. A. Voc0 pode definir uma classe interna como abstract, o que significa que s6 poderl instanciar subclasses
concretas dessa classe. O objeto referenciado pela vari6vel t 6 a instAncia de uma subclasse concreta de
AbstractTest, e a classe an6nima sobrescreve o m6todo getNum( ) para que retorne 22. Avariiryel
referenciada por f 6 a instAncia de uma subclasse an6nima de Bar, e essa subclasse tamb6m sobrescreve o
m6todo getNum ( ) (para que retorne57). Lembre-se de que para criar uma instAncia de Bar, precisaremos de
uma instAncia da classe externa AbstractTest, a fim de associ6-1a I nova instincia da classe interna Bar.
AbstractTest nio pode ser instanciada porque 6 abstract, portanto, criamos uma subclasse an6nima (nio-
abstract) e, em seguida, usamos essa instAncia associando-a ) nova instAncia da subclasse de Bar.
As repostas B, C, D, E e F estio incorretas com base na l6gica do programa que esd descrita acima.
382 Copitulo 8: Clqsses internos
Threads
Obietivos poro q
certificog6o
I Inicior Threods
Imagine um aplicativo para corretores do mercado financeiro com virios comportamentos_complexos iniciados pelo
usu6-"rio. Uma das aplicag6es seria"fazer o download das ultimas opg6es deprego das ag6es", a outra, "verificar avisos de
pregos"; e uma terciira operagio, mais dem orada, seria"artalisar dados hist6ricos da emp resaY{Z" .
Em um ambiente de tempo de execugio de segmentaglo inica, essas.ag6es serio executadas uma ap6s a outra. A.pr6xima
agio :d poder6o.orr., q.ra.rdo a anteiior tiveriido concluida. Se a anilise de um hist6rico levar meia hora e o usu6rio
silecionat a e*ecugio d^o download seguido da pesquisa, o aviso de, digamos, compra ou venda de ag6es como resultado,
podevirtarde demais.
Acabamos de imaginar o tipo de aplicativo que precisa de virios threads. O ideal seria que o download ocorresse em
segundo plano (isto 6, em outro thread). Delsa forma, outros processos poderiam ocorrer ao mesmo temPo para que' por
e*implo,.rm arriso pudesse ser comunicado instantaneamente. Todo o tempo, o usuirio estaria interagindo com.outras
panei do aplicativo. A an6lise tamb6m poderia ocorrer em um thread separado, para que o usu6rio pudesse trabalhar em
outros lociis do aplicativo enquanto os resultados estivessem sendo calculados'
Mas, o que exatamente i um thread? EmJava, "thread" significa duas coisas diferentes:
I umthreaddeexecuglo.
Uma instAncia de Thread 6 apenas... IJm objeto. Como qualquer outro objeto emJava, ele tem vari6veis e m6todos, reside e
6 eliminado no heap. Mas um thread de exuapdo6 um processo individual (um processo "simples") que possui sua pr6pria
pilha de chamadas. EmJava, hi an tbrcadporpilba de cbamadas - ou, considerando inversamente, anapilha de chanadaspor
tbrcad.Mesmo se voc6 nio criar nenhum thread novo em seu programa, os threads estario li sendo executados em
segundo plano.
(
O m6todo main ) , que di inicio a todo o processarnento, 6 um thread chamado (surpreendentemente) de thread
principal. Se voc6 examinasse a pilha de chamadas principal (e 6 possivel, sempre que capturar um rastreamento de pilha de
algo que ocor ra dEois do m6todo principal ser iniciado, mas nlo dentro de outro thread), veria que main ) 6 o primeiro (
m6todo da pilha - o m6todo na parte inferior dela. Por6m, logo que voc6 criar w
nouothread, uma nova pilha se
materializar|eos m6todos chamados a partir duythreadserio executados em uma pilha de chamadas separada da pilha de
(
main ) . A execugio dessa segunda pilha de chamadas 6 considerada simultAnea a do thread principal, mas
aperfeigoaremos essa noglo ao percorrermos este capitulo.
VocA pode achar confuso estarmos falando de c6digos sendo executados simultaneamenle - como se estivessem emparelhadu
-, jh que voc6 sabe que hi somente uma CPU na maioria das miquinas que processam Java. Do que se trata entio?
A JVM, que obt6m sua parcela da CPU independente do mecanismo de agendamento que o sistema operacional
usar, funciona como um mini-sistema operacional e agenda seus pr6prios threads, nlo imponando o sistema
operacional subjacente. Em alguns JVMs, os threads java sio convertidos em threads nativos do sistema
operacional, mas nio discutiremos isso arqui; os threads nativos nio estario no exame. Tamb6m nlo ser6 avaliada
a compreensio de como os threads se comportam em ambientes de JVMs diferentes. Na verdade, o conceito mais
importante a entender em todo este capirulo 6: Quando se trata de threads, h6 poucas garantias.
Poftanto,seja muito cuidadoso com a interpretagdo de algum comportamento com o qual voc6 se deparar em /./ma
m6quina, como "a maneira do thread funcionar". Seri esperado no exame que voc6 saiba o que 6 ou nio um
comporramento garantido, para que seja possivel projetar um programa de maneira que funcione
independentemente da JVM subjacente. Issofaqpafte do conceito pincipal da linguagem Jaua.
AO TRABALHO
Nio comela o erro de proletar reil pragrama baseado em ama implementagio especifca da JL/M. Camo uocd aprenderd posteionnente, JW|IS
diferentespoden execatar tbreads de naneiras profundamente distintas. Por exempl0, um JIlM pade attryrar que todot as threads tenbam
ttltt ue<caxl uma durapio ben distibuida, alocada para cada axt, nllm radi{o pefeito. Mas em outros JL/Ms, um tbread pode coille{ar a ser
executada e, em seguida, sitzp/esrnente raubar a ftna, nunca dando ueTpara que os outros possam ter taa thance. Se uoc6 teslar sea aplicatiuo
na JVM de "alocagdo adeqaada de tempo", e ndo soaber o que d ou ndo garantido em Jaua, entdo, poderdfcar assustado qaando executd-/o em
an JWII com um mecanismo diferenle de agendamento de threads.
As perguntas do exame sobre threads estio entre as mais dificeis. Na verdade, para a maioria das pessoas elas sla
JAVA 5 385
realmente mais dificeis, e com qrxttro objaivos sobre threads voc6 terd que responder udriarpergontassobre eles. Se ainda
I
nio estiver familiawado com os threa&, provavelmente ter6 que passar algum tempo fazendoieGs. Al6m disso, ai vai um
aviso final de isen$o: Este t@ituk ndt i ama lentatiua fu lhe mstnmcomoprEehruru Elicatun con uirios tbrcatls fuJonna atleqaatla e segara bemos
@rcsentar@enat o hisim sobv esse a<finso hhito neste capitublVo& estS aqui para aprender os frrndamentos do uso de threads, e
tamb6m o que precisa para acertar as perguntas do exame sobre threads. Antes de conseguir escrever um c6digo adequado
com v6rios tlrreads, no entanto, tera realmente que estudar mais sobre as complexidadesi sutilezas desse tipo de c6dilo.
(Observagio: O.t6pico de threads daemon nio cai no exame. Todos os threads discutidos neste capitulo sio
threads "do usu6rio". Voc0 e o sistema operacional podem criar um segundo tipo de thread, chamado de thread
daemon. A diferenga entre esses dois tipos (do usuiiio e daemon) 6 que a JVM16 finaliza um aplicativo quando
todos os threads do usuirio tiverem finalizado - a JVM nio se importa em deixar os threads daemon fi.nalizarem,
de forma que, uma vezfrnalizados todos os threads do usu6rio, aJVtrrt ir|fechar, independentemente do estado de
quaisquer threads daemon. Mais uma vez, esse t6pico ndo cai no exame.)
Criando um thread
Um tlrread emJava comega como uma insAncia de java-lang.Thread Vod encontra.ri m6todos na classe Thread para gerenciar
os threads, o que inclui zua cia$o,inicio e pausa- No exame, vod ter6 que conhecer, pelo menos, os m6todos a sryin
start ( )
yield( )
st-eep ( )
run( )
Toda a aglo comega no m6todo run ( ) . Considere o c6digo que voce quer executar em um thread diferente,
como "o trabalho a ser feito". Melhor dizendo, vocA tem alguma tarefa que precisa ser executada, digamos, o
download dos pregos de ag6es, em segundo plano, enquanto outras coisas estiverem acontecendo noprograma;
portanto o que pretende realmente 6 que o trabalho seja executado em seu pr6prio thread. Entio, quando a tarefu
executada for o trabolho citado, o executor (quem execut ari realmente o c6digo) ser6, o thread. E o trabalbo sempre comepa
em um mdtodo run ( ) . como esti descrito abaixo:
Definindo um thread
Para definir um thread, voc6 precisa de um local para inserir seu m6todo run ( ) e, como acabamos de discutir, 6
possivel fazer isso estendendo a classe Thread ou implementando a interface Runnable. Examinaremos as duas
situag6es nesta segXo.
Estendendo java.lang.Thread
A maneira mais simples de definir que um c6digo deve ser executado em um thread separado 6:
O formato 6 este:
386 Copftulo 9: Threods
]
A limitagio dessa abordagem (al6m de ser uma opgio fraca para o projeto na maioria dos casos) 6 que se voc6 estender
Thread, nio poderd utender nada mais. E nlo se trata de esse comportamento herdado da classe Thread ser exclusivamente
necess6rio, porque para usar um thread voc6 teri que instanci6-lo de uma maneira ou de outra.
Lembre-se de que voc6 pode sobrecarregar o m6todo rurr ( ) em sua subclasse de Thread:
]
public void run(Strj-nq s) {
Qa,cf6m hrinflh/\\cts'.i-^ i- r"n i. " + S);
^,1f
].
]
Masesteja a)ertaparaisso:omitodarun(String s) MbrecarregadoserdignoradopelaclasseTbreadamenosqueuoc6ochane.A
classe Tbread espera um milodo run ( ) um argumentos, e executari esse mdtodo para uoci ert una pi/lta de chamadas sQarada dEois que
otbreadtiuerseiniciad.o.Comumm6todorun(string s),aclasseThreadniochamar6om6todoparavocA,e,mesmo
que voc6 chame o m6todo diretamente, a execugao nio ocorrer6 em um novo thread com uma pilha de chamadas s eparada.
Acontecer6 na mesma pilha que a do c6digo de onde voc6 fez a chamada, como acontece com qualquer outra chamada a
m6todo normal.
I mplementando java.lang.Runnable
A implement aElo dalntertace Runnable lhe proporcionari uma maneira de estender a classe que quiser, al6m de definir o
comportamento que serA executado por um thread separado. O formato 6 esse:
]
)
Independente de que mecanismo voc6 escolher, ji tem um c6digo que pode ser processado por um thread de execugio.
Portanto, examinaremo s agoraa inttancia(alde sua classe habilitada para threads e, em seguida, veremos como fazer a coisa
fancionarrealmente.
Instanciando um thread
Nio se esquega de que todo thread de execuglo comega como uma instAncia & classe Thread. Independente de seu m6todo
run (
) estar em uma subclasse de Thread ou em uma classe de implementagio de Runnable, voc6 ainda precisar6 de um
objeto Thread parafazer t:udo funcionar.
Se voc6 estendesse a classe Thread, a instanciagio seria muito simples (veremos mais alguns construtores sobrecarregados
daquiapouco):
MyThread t = new UyThreadQ ;
Se voc6 implementar Runnable, a instanciagio serl um pouco menos simples. Para ter um c6digo executado por um thread,
uocdaindaprecinrideanainttdnciade-I'hread.Contudo,emvezdeinserirothreadeatarefu(oc6digodom6todorun( ))em
uma classe, voc6 teri que dividi-los em duas classes: a classe Thread para o aldigc espedfn do thread, e sua classe de
implementagio de Runnable para o c6digo da tarefa que seri executada pelo thread. (Uma outra forma comum de se
considerarisso6pensandoqueThread6o"trabalhador",eRunnable6o"trabalho"aserfeito.)
Primeiro, instancie sua classe Runnable:
MvRrrnnatr'lF r = no\^r MrzPrrnn:hlol\.
A seguir, crie uma instAncia de java.lang.Thread (algo tem que executar sua tarefa...) e passe para ela a tarefa!
JAVA 5 387
Thread t = new Thread (r) ; / / passe seu Runnable a Thread
Se voc0 criar um thread usando o constnrtor sem argumentos, ele ch,amarS,seu pr6prio m6todo run ( quando
)
for hora. de comegar a-trabalhar. E, exatamente essa i'intengXo qualdg .rt.nd.rrlo, ih..rJ, qr"rdo lr'o16 ,ro1.
-",
Runnable, teri que informar ao novo thread qye eppre_gue seu'm6todo run ( ) em vez do que .ie ti.,r... A classe
Runnable que voc€ passari para o construtor de ThriaJ6 chamada de destino on classe Rannabi de de$ino.
VocA s6 pode passar uma instAncia de Runnable para os virios objetos Thread, de modo que a mesma instAncia se
torne o destino de miltiplos threads, como vemos a seguir:
public cl-ass TestThreads {
public static void main (String [] args) {
MyRunnable r = new MyRunnableO;
Thread foo = new Thread(r);
Thread bar = new Thread(r);
Thread bat = new Thread(r);
Fornecer o mesmo destino para vlrios threads significa que mriltiplos threads de execugio estario executando a
mesma tarefa (e que a mesma tarefa seri feita diversas veies).
A pnipria classe Tbread inplementa Rtnnable (afna/, ela tern am adtodo run ( ) qae estiuamos sobrescreuendo). I:sa signfica que uocd
poderia passar am Thread a 0ulr0 clnstrutzr de Tbread:
Al6m do constnrtor sem argumentos e do que usa uma instAncia de Runnable (o destino, a instAncia que cont6m o trabalho
a ser executado), hi outros construtores sobrecarregados na classe Thread. Os construtores relevantes para n6s seo:
I Thread( )
I Thread(Runnable target)
I Thread(Runnable target, String name)
I Thread(String name)
VocA ter6 que conhecer todos eles no exame! Posteriormente, discutiremos alguns dos outros construtores da lista anterior.
Entio, voc6 j6 criou uma instAncia de Thread e sabe qual m6todo run ( ) chamar. Mas ainda ndo hti nada anntecendo.I\esse
momento, tudo o que temos 6 um objetoJava simples do tipo Thread. Ainda nio d un tbread de exuupio.Para obter um
thread real - uma nova pilha de chamadas - ainda teremos qre iniciaro thread.
Quando um thread tiver sido instanciado, por6m, nio iniciado (em outras palavras, o m6todo ) nio foi start (
chamado na instAncia de Thread), diz-se que ele est6 no estado novo. Nesse est6gio, o thread ainda nio 6 conside rado atiuo.
Depoisqueom6todo start ( )6chamado,othread6considerado comoatiuo(emboraom6todorun( )possaainda
nio ter comegado a rodar). Um thread 6 considerado como desativado (nio mais ativo) depois que o m6todo run ( ) finaLza-
O m6todo i sAl ive ( ) 6 a melhor maneira de determinar se um thread foi iniciado, mas nio concluiu seu m6todo
mn ( ) . (Observagio: o m6todo getstate ( ) 6 bastante ritil para a depuragio, mas voc6 nio precisar6 conhec6Jo para
oexame.l
Iniciando um thread
Voc6 criou um objeto Thread e ele sabe seu destino (a instAncia de Runnable que foi passada ou ele pr6prio se voc6
estendeu a classe Thread). Agora 6 hora de fazer toda essa est6ria de thread funcionar - iniciar uma nova pilha de chamadas.
E tio simples que quase nao merece um subtitulo pr6prio:
t. start O ;
Antes de start ( ) ser chamado em uma instAncia de Thread, diz-se que o thread (quando usarmos o t minrisculo,
estaremos nos referindo ao tbread de exuacio, e nio a classe Thread) este no estado novo. como foi mencionado. O
estado novo significa que voc6 tem um objeto Thread, mas ainda nio tem um thread rea/.Portanto, o que aconteceri
depois que chamar start ( )? O que interessa:
I Um novo thread de execucio ser6 iniciado (com uma nova pilha de chamadas).
388 Copitulo 9: Threoos
r Quando o thread puder ser executado, o m6todo run ( ) de seu destino ser6 processado'
Certifique-se de memorizar o seguinte: a classe iniciada 6 Thread e nio Runnable. Chame start ( ) em uma
instAncia de Thread ( ) e nXo de Runnable.
nouo thread chamard. Portanto, se uoft se deparar com aidigo que cbame o mdtodo rwn
un (
) em uma c/asse Rannable (oa mesmo em ama
instincia tle Thread), isso i pefeitanente udlida. Mas ndo stgntfca que o m,itodo run (
) serd executado em uru thread sQarado! Chamar
um milatlo run ( ) drx)ninn tignfrco aPendr qile uoci estd cbamando am mitodo independente do thread qae estti sendo execatado, e ele
entrard na pi/ha de chamadas ataal, em ueqde no inicio de ma noua pilba. O cddtgo a seguir ndo inicia um nouo thread de exuupdo:
]
]
public class TestThreads {
public static void main (String [] args) {
]
A execugio do c6digo anterior exibiri exatamente o esperado:
% java TestThreads
Runnable running
Runnabfe running
Runnable runningr
Runnable running
Runnable running
Se nXo era isso que voc6 esperava, volte e releia todo esse objetivo.
Entlo, o que aconteceri se iniciarmos v6rios threads? Veremos um exemplo simples em breve, mas primeiro, precisamos
saber como exibir o thread que esti sendo executado. Podemos usar o m6todo getName ) da classe Thread e fazer com (
que cada objeto Runnable exiba o nome do thread que executar seu m6todo run ) . O exemplo a seguir instancia um (
thread, d6 a ele um nome e, em seguida, esse nome 6 exibido a partir do m6todo run ) : (
class NameRunnable implements Runnabfe {
public void runO {
qr/ct- 6m nrrf nri nf I n / \\\T:m6prrnn:l'r'l o rrrrni nn" I .
]
)
public class NameThread {
JAVA 5 389
nrthl ic ql-^l- id \z^id main (strind
\ruLfrrv Il q!vr/
arfta\ Ir
LJ
NameRunnable nr = new NameRunnable (, ;
Run by Fred
Para obter o nome de um thread chame - quem adivinharia - getName ( ) na instAncia do thread. Mas, a instAncia
Runnable de destino nem mesmo tem uma referAncia ) instAncia de Thread, de modo que primeiro chamamos o m6todo
stat ic Thread. currentThread ( ) , que retorna uma referencia ao thread que estiver sendo executado e, em
seguida, chamamos getName ( ) na refer6ncii retornada.
Mesmo se voc6 nio nomear explicitamente um thread, ele ter6 um nome. Examinemos o c6digo anterior, comentando a
instrugio que configura o nome do thread:
public class NameThread {
public static void main (String [] args) {
]
Agora a execugio do c6digo anterior nos dari:
% java NameThread
NameRunnable runninq
Run by Thread-O
Ej6queestamosobtendoonomedothreadatualusandoom6todostatic Thread.currentThread( ),
podemos at6 obter o nome do thread que est6 executando nosso c6digo principal,
public class NameThreadTwo {
public static void main (String [] args) {
Svsfem.oilf
vJULLrr!rvsury! nrinfln("thro^d iS "
+ Thread. currentThread( ) . getName ( )) ;
]
)
que seri
% java NameThreadTwo
thread is main
Certo, othreadprincipal j6temum nome -main () (novamente, quem adivinhou?). AFigurag-1 mostra oprocesso de
inicializaeio de um thread.
)
public class ManyNames {
nrrlrl in c|.at'ir rrnirl m:in /€j- rino
\ v e! r44Y Il aros)
/ Cr:-a um Runnable
/
NameRunnable nr = new NameRunnable ();
|,hr^a ar^r|.l\.
l) comega main0
pub) ic static void main{SL:ing I I args) i
r1
/ / execuca *_ryI_-i
Pilha A
/ / al attm aAAl.d--"
f--* *-.*--*
//em maino
2) mainQ chama methodl()
methodl(r;
I executa
ii ''--
,r
-. __-i**''-
i methodl j
i-..-'.."'-*J
j
/ / mais c6digro rtain i
j
Pilha A
void nethodl{} {
Runnah)l-e r : new MyRunnabLeO;
i-----l
Thread t - new Thread{r);
t.sLartO; --.--__, {
I 1 r**h"Ji I
-l
)
I I faz mais alguma coisa
I-a{:
B
Il;r
pilha Pilha A
(thread t) (main thread)
Z java ManyNames
Rrrn fr\/ F-re.l Y r_S 1
JAVA 5 39I
Run by Fred, x is 2
Run by Fred, x is 3
Run by Lucy, x is 1
Run by Lucy, x i_s 2
Run by Lucy, x is 3
Run by Ricky, x is 1
Run by Ricky, x is 2
Run by Ricky, x is 3
Bem, pelo menos 6 isso o que foi exibido quando executamos o c6digo - desta vez, na nossa miquina. Mas o
comportamento que voc6 viu acima nio 6 garantido. Isso 6 tio crucial que voc€ teri que fazer uma pausa agora, respirar
firndo e repetir comigo: "O comportamento nio 6 garantido". Vocd prlcisa saber, para usar fufliramente como
programadorJava assim como no exame, que nio h6 nada na especi{icagloJava que informe que os threads comegario a ser
executados na ordem em que foram iniciados (em outras palavras, a ordem na qual start ( ) foi chamado em cada
thread). E nlohA garantias de que uma vez que um thread comece a ser executado, continue at6 sua conclusio. Ou que um
loop ser6 concluido antes que outro thread comece. Nio, meu caro. Nada 6 garantido no c6digo anterior, exceto isro:
Cada tbread seni iniciado e exuutado ati a eonclusdo.
Dentro de cada thread, as coisas acontecem em uma ordem previsivel. Mas as ag5es de diferentes threads podem se misnrar
deformas imprevisiveis. Se vocA executar o programa diversas vezes, ou em diversas miquinas, poderi ver saidas diferentes.
Mesmo se nlo vir, voc6 precisa entender que o comportamento que est6 vendo nio 6 garantido-As vezes, uma pequena
modificagio na maneira como o programa 6 executado fari uma diferenga emergir. Apenas por diversio, aumentamos a
quantidade de iterag6es no c6digo do loop para que cada m6todo run ( ) o execute 400 vezes em vez de 3, e
eventualmente comegamos a ver alguma oscila$o:
public void runo {
for (int x = L; x <= 400; x++) t
System.out .println ( "Run by "
+ Thread. currentThread ( ) . getName ( )
A execuglo do c6digo anterior, com cadathreadprocessando o m6todo run de szuloop 400 vezes, comegou bem, mas
depois se tornou nio linear. Aqui esd apenas um trecho da saida de linha de comando da execuEio desse c6digo. Paratornar
maisfacildistinguircadathread coloquei emit6lico asaidaqueincluiFred, eemnegrito adeLucy, deixando adeRicky
inakerada:
RunbyLucy,xis33T
RunbyRicky,xis3l0
RunbyLury,xis338
RunbyRicky,xis3ll
RunbyLury,xis339
RunbyRidry,xis312
RunbyLuqy,xis340
RunbyRicky,xis313
RunbyLucy,xis34l
RunbyRidry,xis314
Runbylucy, xis342
RunbyRidry,xis3l5
Run by Fred, x is 346
Run by Lucy, x is 343
Run by Fred, x is 347
392 Cooitulo 9: Threoos
Quando um thread conclui seu m6todo run ( ) , deixa de ser um tread de execugio. A pilha desse tread se dissolve e ele 6
considerado inatiuo.floentanto,nlo6inativoeeliminado,apenasinatiuo..Pinda|urr'objetoThread,s6nio6.um/readde
exuapdo.Ponarfio, se houver uma referOncia i instAncia de Thread, entio, mesmo quando essa instAncia nio for mais um
tread de execugio, voc6 ainda poderi chamar m6todos nela, como em qualquer outro objeto Java. O que nio po derifazer,
entretanto,6 chamar start ( ) novamente.
Una ueqqae o tread se tomar inatiuo, jamais podenl ser reiniciado!
At6 agora, vimos tr6s estados dos tread: nouo, executduel e inatiuo. Examinaremos outros estados antes de terminarmos
este capitulo.
O agendador de threads
O agendador de treads 4. a pane da JVM (embora a maioria das JVMs converca os treads Java diretamente em
treads do sistema operacional subjacente) que decide qual tread deve ser executado em algum momento
especifico, al6m de tirarteads do estado execut6vel. Presumindo a existAncia de somente uma m6quina
processadora, apenas um tread pode ser executado por yez. Somente uma pilha pode ser processada de cada vez. E 6.
o agendador de treads que decide qaaltread - de todos os qualificados - ser6 realmente processado. Qvando dizemos
qaalifcado, na verdade, queremos dizer no e$ado exautiael.
Qualquer tread no estado execut'iuel pode ser selecionado pelo agendador como o rinico a ser ?rlcesradz. Se um tread
nio estiver no estado executAvel, enteo, neo poderi ser selecionado como o que ser6 imediatamente executado. E,
portanto, fica evidente aprecariedade de garantias aqui:
A ordem na qua/ ot lreadt exuuhiueit sdo s/eaonadas nio i garantida.
Embora o comportamento deflksela comum, ele nio 6 garantido. Comportamento de fila significa que quando um
tread tiver concluido sua execugio, passari para o fim da fila do pool executlvel e aguardar6 at6 que finalmente chegue
a ser o primeiro, quando poderA ser selecionado novamente. Na verdade, chamamos isso de pool executavel, em vez de
fk executivel, para ajudar a reforgar o fato de que os trea& nio ficam todos alinhados numa ordem cena.
Apesar de nio controlarrnot o agendador de treads (nXo podemos, por exemplo, informar que um tread especifico
seri executado), )s vezes, 6 possivel influenciilo. Os m6todos a seguir nos fornecerlo algumas ferramentas para
inflaenciar o agendador. Somente nio confunda influ6ncia com controle.
J6 vimos tr6s estados - nouo, executduele atiuo -, mas espere! Ainda h6 mais! A tarefado agendador 6 colocar e tirar os
treads do esrado de execagdo. Embora ele possa passar um tread do estado de execugio novamente para o executAvel,
outros fatores podem fazer com que um tread saia do estado de execugio, por6m, tem vo\tar para o estado
executavel. Um deles 6 quando seu m6todo run ( ) 6 concluido, situagio em que o tread passa do estado de
execugio diretamente para o inativo. A seguir, examinaremos algumas das outras maneiras pelas quais um tread
pode sair do estado de execugio e para onde ele ir6.
I Execut6vel Esse 6 o estado em que um tread se encontra quando est6 qualificado para ser executado, mas o
agendador nlo o selecionou como o tread a ser processado. O tread entra pela primeira vez no e$ado executivel quando
o m6todo start (
) 6 chamado, mas tamb6mpode retornar ao estado executivel depois de serprocessado ou ao
retornar de um estado bloqueado, de espera ou de suspensio. Quando o tread est6 no estado execut6vel, 6 considerado
atiut
I ExecuFo E o que interessa. O "grande momento". Onde acontece a aglo. Esse 6 o estado em que o tread se encontra
quando o agendador o seleciona (no pool executivel) como o processo a ser executado imediatamente. IJm tread pode
sair de um estado de execugio por v6rios motivos, inclusive pelo "agendador ter decidido assim". Examinaremos as
outras raz6es em breve. Observe que n aFigtrag-2,h6 virias maneiras de se chegar ao estado executivel, mas s6 umo de
entrar no estado de execugio: o agendador selecionar um tread no pool executivel.
t Espera/bloqueio,/suspensio Este 6 o estado de um thread quando est6 qualificado para executar. Ceno, entio temos
tr6s estados em um; mas todos possuem algo em comum: o tread ainda es6 ativo, por6m, nio esti qualificado para
execngio. Em outras palavras, nio 6. exeuniwfmas pode rctomaraum estado execut6vel posteriormente, se um evento
especifico ocorrer. Um tread pode ficar bkquead,t esperando por um recurso (como a E/S, ou o bloqueio de um objeto),
caso em que o evento que o retornar6 ao esado executivel ser6 a disponibilidarle do recuno - por exemplo, quando forem
recebidos dados atrav6s do fluxo de entrada que o c6digo do tread estiver lendo, ou se o bloqueio do objeto ficar
disponivel. Um tread pode lrcar itlsPewr porque seu c6digo de execu$o o infomou paraficar inativo por algum tempo,
sinra$o em que ocorreri o retomo ao estado execut6vel devido ao periodo de suspensXo ter expirado. Ou o tread pode
estar na erpcr4por W src6digo de exe cuglo a prouocou, caso em que o evento que o retorna rL para o estado
394 Copitulo 9: Threods
execut6vel ser6 outro tread enviando uma notificagio de que nio 6 mais preciso aguardar. O ponto imponante
6 que um tread nio inforrua ao outro que deve ficar bloqueado. Com alguns m6todos, pode pdrece,'que estea
dizendo a outro threid para bloqueai, mas nlo estio. Se voc6 tiver uma refer€ncia t a outro thread, pode
escrever algo como:
t.sleep( ); ou t.yield( )
I Suspensio
I Espera
Suspensio
O m6todo sleep ( ) 6 um mdtodo static da classe Thread. use-o em seu c6drgo para "desacelerar umtread
forgandoo entrar no modo de suspensio antes de retornar ao e$ado executivel (no qual ainda ter6 que aguardar para ser
a
o ffead executado). Quando um tread 6 suspenso, vai para algum local e nio retornaao estado execut6vel at6 que seja
despenado.
Entio, por que voc6 iria querer um tread por achar que o treadex|percorrendo seu c6digo muito
suspenso? Bem,
rapidamente. Ou precisar forgar seus treads dar opomrnidades a outros, j6 que uma execuglo adequadamente agendada
a
nilo 6 garantidanas especificag6esJava. Ou suponhamos um read executado em um loop, fazendo o download dos pregos
mais recentes das ag6es e analisando-os. O download dos pregos um ap6s o outro se mostraria uma perda de tempo, j6 que
a maioria seria semelhante, e o que 6 mais imponante - seria um consumo precioso de largura de banda. A maneira mais
simples de resolver isso 6 fazer com que um tread entre em pausa (suspensio) por cinco minutos depois de cada download.
Faga isso chamando o m6todo est6tico Thread. sl-eep ( ), fornecendo um periodo em milissegundos, como vemos
abaixo:
try {
Thread.sleep(5*60*1000); // Suspenso por 5 minutos
i catch (InterruptedException ex) { }
JAVA 5 395
Observe que.o m6todo sleep ( )pode lanear uma excegio verificada InterruptedException (cuja possibilidade
de ocorrer n6s geralmente temos conhecimento, j6 que outro tread tem que faier ainterrupgio explicit"mente),
Portanto' voc6 ser6 forgado a reconhecdJa manipulando ou declarando-a. Normalmente, ipln"r &."ps.tlamoi
cada chamada de suspenslo em um bloco tryliatch,
como no c6digo anterior.
Vamos alterar o c6digo de Fred, Lucy e Ricky usando a suspenslo para tentdrforgar os treads a se alternarem, em vez
de.permitir que um deles seja o dominante durante um periodo de timpo. Onde vocA acha que o m6todo sreep (
) deveria entrar?
class NameRunnable implements Runnable {
public void run0 {
for (int x = 1; x < 4i x++) {
System.out.println ( "Run by "
+ Thread.currentThread( ) . getName ( ));
trv {
Thread. sleep ( 1000 ) ;
) catch (InterruptedException ex) { }
/ / Cria um Runnable
NameRunnable nr = new NameRunnableO;
cl-arf/1.
^no
l-r^rn q|- :rl- I l .
l-hrao qi-arl-/\.
t java ManyNames
Run by Fred
Run by Lucy
Run by Fred
Run by Lucy
Run by Ricky
Run by Fred
Run by Lucy
Pr rn h\/ P i
^L\/
395 Copitulo 9: Threods
Apenas lembre-se de que o componamento da saida anterior tamb6m nlo 6 garantido. VocA nio teri como se
..rtifi."r de quanto tempo um tread serl executado antes de entrar em suspensio, portanto, nlo poder6 saber com
certezase s6 um dos tr6i treads estari no estado executAvel quando o tread em execugeo entrar em suspensio. Em
outras palavras, se houver dois treads ativos no pool execut6vel, voc6 nio ter6 como saber com certeza se o que
nXo foi usado por riltimo ser6 o selecionado para execugio. Ainda asim, usar sLeep ( ) i a melhor maneira de tentarfaryr
clm que todos osireads tenbam a chance de serent executados!Ou, pelo menos, de garantir que um tread nlo entre em
execugio, e assim permanega atd sua conclusio. Quando vm tre^d encontrar uma chamada de suspensio, teri que
ficar suspenso pelo menos durante o periodo especificado em milissegundos (a menos que seja interrompido antes de
sua hora de deipertar, caso em que langari imediatamente a exceElo InterruptedException).
NXo se esquega de que s l eep ( )6 um m6todo estitico, portanto, nio se engane achando que um tread pode colocar
outronoeltadodeiuspensio.Voc€podeinseriroc6drgodesleep( )emqualquerlocal,j|quet0d0oc6digoser6
executado po r alguntread. Quando o c6digo que estiver sendo executado (o que significa o c6digo do tread que estiver
sendo executado atualmente) chegar a uma chamada de s l eep (
) , colocar6 o tread atual em suspensio.
Exercfcio 9-1
1. Crie uma classe e estenda Thread. Como alternativa, vocA pode implementar a interface Runnable.
2. Sobrescreva o m6todo run ( ) de Thread. E ai que entrari o c6digo que exibir6 os nrimeros.
3. Crie um loop for que seja executado 100 vezes. IJse a operagio de resto para verificar a exist6ncia de algum
nrimero que seja o resto da divisio por 10.
4. Use o m6todo static Thread. sleep ( ) para f.azer uma pausa. lJm mimero do tipo long representar6
os milissegundos.
AO TRABALHO
Nio tonfe en pioidadu quando projetar reu @licatiuo com u,irios tltreads. Jd qae o conrPortamentl das pioridadu para udrios tbreads nio i
garantido, ase-ar coml ama maneira de me/horara efcidncia de seuprograma, mas certfique-se de qae ele ndo dQenda desse comportamento
para qae /anrion( nrftlameflle.
O que tamb6m ndo 6. garantido 6 o comportamento quando os treads do pool t6m prioridade igual, ou o tread
sendo executado tem a mesma prioridade dos treads do pool. Se todas as prioridades forem iguais, a
implementagXo do agendador que a JVM usar poder6 fazer simplesmente o que quiser. Isso significa que um
agendador pode executar uma das ag6es a seguir (entre outras coisas):
JAVA 5 397
r Selecionar a execugio de um tread mantendo-o assim at6 que seja bloqueado ou conclua seu m6todo run ( );
T dividir o tempo dos treads do pool para dar a todos uma opoftunidade igual de execugio.
Configurando a prioridade de um tread O tread receberi uma prioridade padrio que ser6 igual a do tread de
execugio que o criou. Por exemplo, no c6digo
public class TestThreads {
pubfic static void main (String [] args) {
MyThread t = newMyThreado;
O tread referenciado por t teri a mesma prioridade do tread main (), ji que esse esti executando o c6digo que cria a
insAnciadeMyThread
VocAtamb6mpodeconfiguraraprioridadedeumtreaddiretamentechamandoom6todosetpriority( )emuma
instAncia de Thread. como vemos abaixo:
t.start O ;
As prioridades sio configuradas com o uso de um inteiro positivo, geralmente entre 1 e 10, e a JVM nunca alterar6
a prioridade de um tread. No entanto, valores de 1 a 10 nio sio garantidos. Alguns JVMs podem nio reconhecer
dez valores distintos. Um JVM desses poderi a redtzir os valores de 1 a 10 para valores de I a 5, por exemplo; assim,
se voc6 tiver, digamos, dez treads cada um com uma prioridade diferente e o aplicativo atual estiver sendo
executado em um JVM que aloque um intervalo com somente cinco prioridades, entlo, dois ou mais treads podem
ser mapeados para uma prioridade.
Embora apioridadepadrio t/a 5, a classe Thread possui trAs constantes (variiveis static f inal), as quais definem
o intervalo das prioridades dos treads:
Thread.MIN_PRIORITY (1)
Thread.NORM_PRIORITY ( 5)
Thread. MAX_PRIORITY ( 110 )
O mdtodo yield( ) Mas o que o m6todo static Thread. yield ( ) tem a ver com tudo isso? Nio muito, na
pr6tica. O que yield ( ) fuuefazer |retornar fim de permitir que
o tread sendo executado para o estado executivel, a
outrostreadscomanermaprioridadetenhamsuaoportunidadedeserprocessados.Portanto,afinalidade6usaryield( )
parapromoverum agendamento sofisticado de opornrnidades entre treads de prioridades iguais. Na verdade, o m6todo
yield ( ) nlo garantefazer o que deveria, e mesmo se realmentefrzer com que um tread saia do estado de execugio
retornando para o estado execut6vel, ndo hd gmantia deque o tread que ceder seu espago seja selecionado novamente entre
todos os outros! De modo que, embora yieldQ possa - e geralmente o faz - fazer comque o tread sendo executado ceda
seu espago para outro tread execut6vel com a mesma prioridade, nlo h6 garantias.
Um yield ( ) nunca faz um thread entrar no estado espera/bloqueio/suspensio. O miximo que pode acontecer 6
yield ( ) fazerumthread passar de executado para executivel, mas, novarnente, ele pode tamb6m nio ter efeito nenhum.
O m6todo join( )
Om6todonio-static join( )daclasseThreadpermitequeumtread"sejaadicionadoaofinaldeoutrotread".Se
voc6 dver um tread B que nio puder executa r atarefa dele at6 que o tread A tenha conclui do a sua, entio, ser6 melhor
"adicionar" o tread B ao A. Isso significa que o tread B nio se tornar6 execut6vel at6 que A tenha sido concluido (entrado no
estado inativo).
Threadt=newThread0;
t.start O ;
t.joinO;
O c6digo anterior pega o tread que esti sendo executado (se ele estivesse no m6todo main ( ) , entio, seria o tread
principal) e o adiciona ao final do tread referenciado por t. Isso impede que o thread atual se torne execut6vel antes que o
threadreferenciado por t fique inativo. Emoutraspalavras, o c6digo t. join( )significa'me anexe (othreadatual)
ao final de t, de forma que t precise finalizar antes que eu (o thread atual) possa executar novamente." Voc6 tamb6m
pode chamar uma das vers6es sobrecarregadas do m6todo j oin ( ) que usa a duragio do tempo de espera, de modo
que voc6 diga: "Espere at6 que o thread r seja concluido, mas se ele demorar mais de 5.000 milissegundos, interrompa
a espera e se torne executivel assim mesmo". A Figura 9-3 mostra o efeito do m6todo j oin ( ) .
398 Copftulo 9: Threods
At6 agora, examinamos tr6s maneiras pelas quais um thread sendo executado pode sair do estado de execugio:
I Uma chamada a sleep ( )
Garante f.azer comque o thread atual interrompa a execugio, ao menos durante o periodo especificado para a
suspenslo (embora possa ser interompido antes do temPo especificado)'
I Uma chamada a yield ( )
Nio garante muito, embora normalmente faga com que o thread sendo executado retorne ao estado executevel'
a fim de que outro thread com a mesma prioridade possa ter uma chance.
Garante f.azer com que o thread atual pare de ser executado at6 que o thread ao qual foi adicionado (em outras
palavras, o thread no qual wait ( ) foi chamado) seja concluido. Se o thread no qual for adicionado estiver
inativo, no entanto, o thread atual nio ter{ que retornar ao estado executevel.
Al6m desses tr6s, tamb6m temos os cen6rios a seguir, nos quais um thread pode sair do estado de execuglo:
I Se o m6todo ( ) do thread for concluido (6bvio).
run
I Com uma chamada a wait ( ) em um obieto (nio chamamos wait ( ) em um tbread, como veremos em
breve).
I Quando um thread nio consegui r o bkq*eio do objeto cujo c6digo do m6todo estiver tentando executar.
I O agendador do thread pode decidir passar o thread atual do estado executado paru execut|vel, para permitir
que outro thread tenha a chance de rodar. Nio 6 preciso nenhum motivo - o agendador do thread pode fazer
essas trocas da maneira que desejar.
Principais eventos no
Saida
c6digo do thread
A is running
n
A l-
!r !--.-'*i--
urlrrlrv
{D rurllrug
^
a ic rrrnninn
a ic nrnnina Thread b = new Thread(aRunnable);
A ic rrrnnina b. start Ot
A ic rilnhihd
P ic rrrnrina r'/Os Threads v6m e voltam Pilha A esti
R ic nrnnind
A ic nrnninn sendo
executaca
R
A
ic
ie
vrrnninn
rrrnninn
f-*--t r*-_:l ;l
A ic rrrnhinn
ti t1
!E i-
+r r*,--i--
s4rf rrg aosturQ ] a"ottero
I i"l
I
il
R ic rrlnhi-d i
A ic rrrnrinn il
n i< -,rrnina
A estii
LI Pilha B esti
A ic nrnhiaft Pilha
//A-iilnfa-sc ao finaf
R ic nrnninc senoo
rt
//de B
R ic rirnnind executaoa
R ic rrrnninn
""';lo;u
R ic firnhind
R ic rrrnnina Pilha B
R ie rr:nnina
R ic rrrnninn ldood'e4l
R ic rrrnni //Thread B finaliza !!
A ic rrrnai //Thread A inicia novamencer i___,1
A ic n:nnina
A ie rrrnnira
A ic nrnninc Pilha A dostuf0
I
A
ie
ic
rrrnnina
.1,hnin^
i i
'a ---,Ji
Pilha Aunida
Pilha B
Nesse exemplo, temos uma classe chamada Account que representa uma conta de banco. Para que o c6digo nio
fique extenso, essa conta comegari com um saldo igual a 50 e s6 poder6 ser usada para retiradas. A retirada ser6
aceita mesmo se nio houver bastante dinheiro na conta para cobri-la. A conta simplesmente rcrL o saldo reduzido
da quantidade que voc6 quiser retirar:
-^^ l^^^,,-! r
^l
ufa-D 6LLUUIrL I
]
Agora 6 que vai ficar divenido. Imagine um casal, Fred e Lucy, os dois com acesso ) conta e querendo fazer
retiradas. Mas eles nio querem exceder o saldo, portanto, antes de fazerem uma retirada, ele ou ela primeiro
verifica o saldo, a fim de ter certeza de que hi o bastante como cobenura. Al6m disso, as retiradas slo sempre
limitadas a uma quantia igual a 10, de modo que deve haver pelo menos esse valor no saldo da conta para que uma
retirada seja feita. Parece simples. Mas 6 um processo de duas etapas:
1. Verificar o saldo:
2. Se houver o suficiente na conta (nesse exemplo, pelo menos um valor igual a L0),fazer a retirada.
O que aconteceri se algo separar a etapa t da 2? Por exemplo, imagine o que aconteceria se Lucy verificasse o
saldo e visse que h6 apenas o valor exato na conta, 10. Mas antes de elafaTer a retirada, Fred wifcasse o saldo e tambtim vire
que h,l o bastante para a retirada. J6 que Lucy verificou o saldo, mas ainda nio f.ez sua retirada, Fred est6 vendo "dados
inv6lidos". Ele est6 vendo o saldo da conta antes de Lucy debitar realmente a conta, mas a essa altura o d6bito 6
ceno de ocorrer. Agora, tanto Lucy quanto Fred acreditam que h6 o bastante paraf.azer suas retiradas. Poftanto,
imagine agora que Lucy tenha {eito saa retirada e j5, nio tenha o bastante na conta para a retirada de Fred, mas ele
acha que tem, )i que quando verificou, tinha! J6 veremos como o c6digo real da operagio no banco se pareceri,
com Fred e Lucy representados por dois threads, cada um atuando no mesmo objeto Runnable e com esse objeto
contendo uma refer6ncia a somente uma instincia da conta - poftanto, hi dois threads e uma conta.
A l6gica do c6digo de nosso exemplo ser6 a seguinte:
I quando sair da suspensio, concluirl a retirada e exibiri que ela foi feita;
I se nlo houver o basranre, exibir6 uma declaragio mostrando quem 6 vocA e o fato de que nio hi dinheiro
suficiente.
Porranto, o que esramos realmente tentando descobrir 6 se o seguinte 6 possivel: um s6cio verificar a conta e ver se
hi o bastante, mas antes da retirada real ser feita, o outro s6cio verificar a conta e tambdmver que hi o suficiente.
Quando o saldo da conta chegar a L0, se os dois s6cios o verificarem antes de fazer a retirada, ambos pensario que
esti tudo certo e a conta ficar6 com menos 10!
Aqui est6 o c6digo:
public class AccountDanger implements Runnabl-e {
private Account acct = new Account ( ) ;
public static void main (String [] argrs) {
AccountDanger r = new AccountDanger O ;
Thread one = new Thread(r);
Thread two = new fhread(r);
one. setName ( "Fred" ) ,'
two . setName ( "Lucy" ) ;
one.start();
two. start O t
)
public void runO t
for (int x = 0; x < 5; x++) {
makeWithdrawal (10) ;
if (acct.getBal-anceO < 0) {
System.out.println( "account is overdrawn! ");
)
1
Entio o que aconteceu? E possivel que Lucy rcnha verificado o saldo, o thread tenha entrado em suspensao, Fred verificou o
saldo,othreaddeLurydespeftoueconcluiu silaretirad^e,emseguida,Fredconcltiuasua,eelesacabaramportirarmaisdo
quepodiam? Veja a saida (numerada):
* i arra --**------rnger
A--^rrnt.n:
Na linha 5, Lucy concluiu sua retirada e, em seguida, antes de Fred concluir a sua, Lucy verifica novamente a
conta na linha 6. E isso continua assim at6 chegarmos i linha 8, onde Fred verifica o saldo e vA que 6 igual a 20. Na
linha 9, Lucy conclui uma retirada (para qv^l ji tinha verificado o saldo anteriormente) e isso levou o saldo a um
^ novamente e viu que o saldo era 1.0, poftanto ela sabe que pode fazer
valor igual a 10. Na linha 10, Lucy verificou
uma retirada. Mas nio sabe que Fred tambdn jti aeifcou o saldo na linha 8, dusaforma, ele acha que d segurofaqer a renradalNa
linha 11, Fred conclui a retir^d^ para a qual verificou o saldo na linha 8. Isso levou o saldo a zero, mas Lucy ainda
tem uma retirada pendente que aprovou na linha 10! Voc€ sabe o que acontecere.
Nas linhas !2 e 13, Fred verficou o saldo e viu que nlo havia o bastante na conta. Connrdo, na linh a I4,Lua7 concluiu sua
retirada e BOOM! A conta agora esi estourada em 10 - algt que athamw qae seria euitada por meio de uma r,wficagdo anterior a uma ntirada
A Figura 94 mostra a linha de tempo do que pode ocorrer quando dois threads acessam simuhaneamente o mesmo objeto.
Tempo
Temos que garantir que as duas aapas da retbada - wrfiatr o saldo e jtya rcr.trada - nunca fiquem separadas. Precisamos que
elas sempre sejam executadas como urna opera$o, mesmo quando o thread entrar em suqpensio entre as etapx I e2l
Chamamos isso de "opera$o at6mica" (embora aqui a fisica esteja um porrco desatualizada, neste caso "at6mico" sigpfica
"indivisivel") porque a operaSo, independente da quantidade de declara6es efetivas (ou insrug6es bytecode zubjacentes),
serS concluida antesdo codigo de qudquer outro tlrread qtre attre sobre os mesmos dados.
Vocd ndo podz garantir que um tinico thread perrzanepa yndo execatado darante toda a operagdo atdmica. Entretanto, pode garantir
que mesmo se o thread que estiver processando a opera$o at6mica entrar e sair do estado de execu$o, nenham oahn tbnad smda
execatada prsa ahtm sobrc os mesmos dados. Em outras palavras, se o thread de Lury entrar em zuspensio depois de verificar o saldo,
podemos i-pdit que Fred verifique o sddo anta de o thread de Lucy despenar e concluir sua retirada
lembrese de proteger as variiveis de maneira normal usando um modificador de controle de acesso. E o codigo do moodo
que voc6 precisa proteger, para qtre so um thread posa exe antA-lo por vez. Faga isso com a palavrachave slmchroni z ed .
Podemos resolver todos os problemas de Fred e Lucy adicionando uma palavra ao c6digo. Marcaremos o m6todo
makeWithdrawal ( ) com slmchronized, como vemos abaixo:
private synchronized void makeWithdrawal(int amt) {
if (acct.getBalanceO >= amt) {
System.out.println(Thread. currentThread( ) .getName ( ) +
) catch(InterruptedException ex) { }
acct.wj-thdraw(amt);
System. out.println (Thread. currentThread ( ) . getName ( ) +
]
Agoragarantimosquequandoumthread(LucyouFred)comegaroprocessoderetirada(chamandornakevvithdrawal( )),
o outro thread nlo poderl acessar esse m6todo at6 que o primeiro conclua o processo saindo do m6todo. A nova saida
exibir6 o beneficio da sincronizagio de makewithdrawal ): (
I java AccountDanger
Frcd ic ooino 1-^ ldithdraw
Fred completes the withdrawal
Trrcw is ooinc to withdraw
Lucy completes the withdrawal
Fred is going to withdraw
Fred completes the withdrawal
Lucy is going to withdraw
Lucy compl-etes the withdrawal
Fred is going to wiLhdraw
Fred completes the withdrawal
Not enougfh in account for Lucy to withdraw 0
Observe que agora os threads, Lucy e Fred, sempre verificam o saldo da conta e concluem a retirada antes de o
outro thread poder verificar o saldo.
SincronizasAo e bloqueios
Como a sincronizagio funciona? Com bloqueios. Todo objeto em Java possui um bloqueio interno que s6 surge
quando o objeto tem um c6digo de m6todo sincronizado. Quando entrJmos em um m6todo sincronilado nio--
est6tico, automaticamente adquirimos o bloqueio associado com a instAncia atual da classe cujo c6digo esramos
erecutando (a instAncia this). A operaEio de adquirir um bloqueio para um objeto tamb6m e conheiida como
obten$o do bloqueio, ou como bloquear o.objeto, on_ bloque ar no obj*o,ou sincronizar no objeto. Poderemos usar tamMm
o termo monitor para nos referirmos ao objao cujo bloqueio estamos adquirindo. Tecnicamente, o bloqueio e o monitor slo
duas coisas diferentes, mas a maioria das pessoas fala deles como se fossem a me$na cois4 e faremos o mesmo.
J6 que s6 h6 um bloqueio por objeto, se um thread usar o bloqueio, nenhum outro poder6 acessar o c6digo
sincronizado at6 que o bloqueio seja liberado. Isso significa que nenhum outro thread pode entrar no c6digo de
sincronizagXo (o que significa que nio pode entrar em nenhum m6todo sincronizado desse objeto) at6 que o
bloqueio tenha sido liberado. Normdmente, a liberagio de um bloqueio significa que o thread que o estA
mantendo (em outras palavrx, o thread que est6 anulmente no m6todo sincronizado) sairi do m6todo sincronizado. Nesse
momento, o bloqueio 6liberado at6 que algum outro thread entre em um m6todo sincronizado nesse objao.
VocA precisa lembrar dos seguintes pontos-chave sobre bloqueio e sincronizagio:
I 56 os ndtodos podem ser slmchronized, as variiveis, nio.
I Cada objeto possui apenas anbloqueio.
I Nen todot ot mdtodos de ama classe deuem ser sincroniqados.IJma classe pode ter tanto m6todos sincronizados quanto
nio-slmchroni zed.
I Se dois threads estiverem prestes a executar um m6todo slmchronized em uma classe, e ambos os threads
estiverem usando a mesma instAncia & classe para chamar o
m6todo. somente um thread poder6 executar o m6todo de
cadavez.O outro teri de esperar at6 qu. o pri-.iro termine a sua chamada. Em outras piavras, quando um thread usar
o bloqueio de um objeto, nenhum outro thread poderi acessar quaQaerdos m6todos sincronizados dessa classe
(referentes a esse objeto).
I Othreadpodeasarmaisdearzbloqaeio.Porexemplo,othreadpodeacessarumm6todoslmchronized,obtendo
assim um bloqueio e, em seguida, chamar imediatamente outro m6todo slmchronized em um objeto
diferente, usando are bloqueio tamb6m. Com o desenrolar da pilha, os bloqueios serio liberados novamente.
Al6m disso, se um thread adquirir um bloqueio e depois tentar chamar um m6todo sincronizado nesse mesmo
objeto, nio haveri problemas. A JVM saberd que esse thread ji possui o bloqueio desse objeto, portanto, ele
poder6 chamar outros m6todos synchronized no mesmo objeto, usando o bloqueio que j6 possui.
li que a sincronizagio prejudica a concorr€ncia, 6 melhor nlo sincronizar nenhum outro c6digo al6m dos
necess6rios para proteger seus dados. Portanto, se o escopo de um m6todo for maior do que deveria, voc6 poder6
reduzir o escopo da parte sincronizada para algo menor do que um m6todo completo - para apen s um bloqueio.
Chamamos isso, por mais estranho que parega, de "bloco sincronizado", e seu formato 6 o seguinte:
nlacc q1m^rF6cf I
Psvrrv (
slmchronized(this) {
System, out . println ( " slmchronized" ) ;
]
404 Cooitulo 9: Threods
Quando o thread esti processando um c6digo a panir de um bloco slmchronized, inclusive o c6digo de
qualquer m6todo desse bloco, diz-se que esse c6digo esta sendo executado em art clntexto sincroniTado. A pergunta que
pode surgir 6.: sincroniqado com base em qud? O:u, sincroniqado com base no bkqueio dr qual objeto?
Quando voc6 sincronizar umm6todo, o objeto usado para chamilo ser6 aquele cujo bloqueio tiver que ser obtido.
Mas, quando sincronizar um bloco de c6digo, voc6 teri que especificar qual bloqueio de objeto ir6 usar; para tanto
voc6 poder6, por exemplo., empregar alguniobjeto.de terceiroipara bloquear essi trecho de codigo.,kso lhe
proporcronari o r.c.rr* de teimais de um bloqueio para a sincionizagio de c6digos dentro de um rinico obieto.
Ou voc6 pode sincronizar na instAncia atual (ttris), como no c6digo acima. (Jma vez que 6 a mesma instAncia em
que os m6todos slmchronized bloqueiam, isso significa que voc6 pode sempre substituir um m6todo slm-
chronized por um nio-slmchr onized, que contenha um bloco slmchronized. Em outras palavras, isto:
public synchronized void dostuff O {
System. out.println ( "slmchronized" ) ;
]
6 equivalente a isto:
public void doStuff ( ) {
slmchronized (this ) {
System. out . println (" slmchronized" ) ;
]
Ambos esses m6todos t6m exatamente o mesmo efeito, na prhtica. Os bltecodes compilados poderlo nio ser
exatamente os mesmos para os dois m6todos, mas poderiam ser - e quaisquer diferengas existentes nlo sio
importantes. A primeira forma 6 mais curta e mais familiar para a maioria das pessoas, mas a segunda pode ser
mais flexivel.
E quarrto aos metodos static? Eles podem ser slmchronized? Os m6todos static podem ser synchronized.
56 haveri uma copia dos dados static que vod tentar proteger, portanto, seri preciso apenas um bloqueio por classe para
a sincronizaSo de m6todos estiticos - um bloqueio para tda a classe. Existe um bloqgeio assim; toda classe carregada em
Java possui uma insrAncia correspondente de,iava.lang.Class esa classe. E essa instincia de java.lang.Class cujo
bloqueio ser6 usado para proteger m6todos static da classe (se eles forem slmchronized). Nlo hi nada especial que
sejapreciso fazer parasincronizar um m6todo static:
public static slmchronized void getcount ( ) {
return count;
)
Novamente, isso poderia ser substituido por c6digo que use um bloco slmchronized. Se o m6todo for definido
em uma classe chamada MyClass, o c6digo equivalente 6 o seguinte:
;^ rf-f;^.int-
>LdUfL Irru noft-nrrnf l\ J
^'lh]
PulrIL VEuevurrL\/ \
t"artt count;
,
)
Espere, que hist6ria 6 essa de MyClass.class? Isso se chama literal de classe. Trata-se de um recurso especial da
linguagem Java que diz ao compilador (que por sua vez diz ) JVM): 'encontre para mim a instAncia de Class que
represente a classe chamada MyClass." Voc6 tamb6m pode fazer isso com o seguinte c6digo:
public static void classMethodO {
Class c1 = Class.forName("MvClass") ;
slmchronized (cl) {
/ / faz alqo
]
)
Entretanto, essa verseo 6 mais longa, mais complexa e, o mais importante de tudo, nlo cai no exame SCJP. Mas 6
f6cil e ripido usar um literal de classe - basta escrever o nome da classe e adicionar . class ao final. Nio 6
preciso usar aspas. Agora voc6 tem uma expressio para o objeto Class que precisa sincronizar.
JAVA 5 405
Exercfcio 9-2
Poderiamos executar a sincronizagio em um objeto String, mas as strings nio podem ser alteradas depois que sio
criadas, Portanto, nio poderiamos passar para a pr6xima letra sem gerar um novo objeto String. A saida final
deveriter 100 As, 100Bs e 100 Cs, tudo na mesma linha.
1. Crie a classe e estenda Thread.
2. Sobrescreva o m6todo run ( ) de Thread. E ai que entrarS,o bloco de c6digo slmchronized..
3. Para que nossos tr6s threads companilhem o mesmo objeto, teremos que criar um constnrtor que aceite um
objeto StringBuffer no argumento.
4. O bloco de c6digo slmchronized obter6 um bloqueio do objeto StringBuffer na etapa 3.
5. Dentro do bloco, exiba o objeto StringBuffer 100 vezes e, em seguida, passe para a letra seguinte. VocA pode
consultar o Capitulo 5 para verificar os m6todos de StringBuffer que ajudario aqui.
6. Para concluir, no m6todo main ( ) , crie somente um objeto StringBuffer que use a letra A e, em seguida, gere
tr6s instAncias de nossa classe e inicie todas elas.
Ao se considerar o impedimento, 6 importante prestar atengio a quais objetos estio sendo usados para o bloqueio.
r Threads qtre chamam m6todos que nio sejam static
slmchronized. da mesma classe so bloquearto uns aos outros
se forem chamados usandose a mesma insdncia. Isso ocorre porque cada um deles bloqueia na instAncia this, e, se
forem chamados usandose duas irstAncias diferentes, eles receberXo dois bloqueios, qlre neo interferem um com o outro.
I Threads que chamam m6todos static slmchroni zed da mesma classe sempre bloqueario uns aos outros
- todos eles bloqueiam na mesma instAncia de Class.
I Um m6todo st,atic slmchronized e um que nio seja static slmchronized nunca bloqueario um
ao outro, jamais. O m6todo static bloqueia em uma instincia de Class, enquanto que o m6todo nio-
static bloqueia na instincia this - essas ag6es nXo interferem umas com as outras de forma nenhuma.
lPara blocos slmchronized, voc6 precisa observar exatamente qual obieto foi usado para o blogueio. (O que
slmchronized?) Threads que sincronizem no mesmo objeto
est6 dentro dos par6nteses, depois da palavra
bloqueario umas )s outras. Threads que sincronizem em objetos diferentes nio o fard.o.
A Tabela 9-1 lista os m6todos relacionados a threads e se o thread abre mio de seus bloqueios como resultado da chamada.
acess6-los. Sincronizando o m6todo, voc6 garante que quaisquer threads que tentem executar esse mdtodo usando
a mesma instAncia serio impedidos de ter.m simultAneo. Mas um ihread que esteja trabalhando com uma
"cesso
instAncia diferente nio serlifetado, porque esti adquirindo um bloqueio na outra instAncia. E isso o que
queremos - que os threads trabalhanio .bm or mesrnos dados tenham de atuar um de cadavez, mas threads
trabalhando iom dados diferentes possam simplesmente ignorar uns aos outros e executar semPre que quiserem;
nio faz diferenga.
Para dados modific6veis, em um campo static, voc6 normalmente usa um m6todo est6tico para acess6-los. E
novam ente, sincron)zando o m6todo, voc6 garante que quaisquer dois threads que tentem acessar os dados serio
impedidos de ter acesso simultAneo, porque-ambos os threadsterlo de adquirir bloqueios no objeto Class para a classe em
que o m6todo static est6 definido. Novamente, 6 isso o que queremos.
Entretanto-esevoc6tiverumm6todonio-st.atic queacessaumcampostatic?Ouumm6todostatic.que
acessaumcamponio-static (usandoumainstAncia)?Nessescasos,ascoisascomegamafrcarcomplicadasbemrhpido,
e h6uma boa chance de elas nio funcionarem da maneira que voc6 deseja. Se voc6 tem um m6todo static acessando
um campo nio-static, e sincronizar o m6todo, voc€ adquire um bloqueio no objeto Class. Mas e se houver um outro
m6todo.que tamb6m acesse nio-static, desta vez usando um m6todo nio.static? Ele provavelmente
9:ampg
srlcromzanainstAnciaatual(this).Lembre-sedequeumm6todostatic slmchronizedeumquenioseja
stat.ic slmchronizedniobloquearioumaooutro-elespodemrodaraomesmotempo.Deformasemelhante,
sevoc6acessarumcampostatic.rsandoumm6todonio-est6tico,doisthreadspodemchit-rrr.m6todousando
duas instAncias diferentis de this. O que significa que nXo bloqueario um ao outro, porque estario usando bloqueios
diferentes. O que significa que dois threads estio acessando simultaneamente o mesmo campo sLatic - exatamente o
tipo de coisa que estamos tentando impedir.
Fica muito confuso tentar imaginar todas as coisas estranhas que podem acontecer aqui. Para manter a simplicidade:
para tornar uma classe segura no que diz respeito a threads, os m6todos que acessam campos modificiveis precisam
ser slmchroni-zed.
O acetso a campos utdticos deue nrfeito apartir dc mdtodw stat.ic slmchroni zed. O acesso a campos ndo-esL6ticos
deue rerfeito apartir de ndtodos que ndo s/an sLatic slmchronized. Por exemplo:
public class Thing {
nrirra|-a cl-aFi^ inf <i:l-iaFia]A.
this.nonstaticField = nonstaticField;
JAVA 5 407
E se voc6 precisar acessar tanto campos static quanto nlo-static em um m6todo? Bem, existem maneiras
de se fazer isso, mas esti.al6m do que voc6 precisa para o exame. Vocd viver6 uma vida mais longa e feliz se
sinplesnente ndofryr isn. S6rio mesmo. N6s mentiriamos para voc6?
import java.util.*;
public class Namelist {
private List names = Collections.slmchronizedlist(
nar.r T.i nlra^r.i cf r \ ) ;
)
public String removeFirst ( ) {
if (names.sizeO > 0)
return (String) names.remove (0) ;
else
return nuI1;
O m6todo Collections. synchronizedlist ( ) retorna um List cujos m6todos estao todos sincronizados e
"seguros", de acordo com a documentagXo (como um Vector mas, uma vez que estamos no s6culo XXI, nXo iremos
-
usar um Vector aqui). A questio 6, a classe Namelist pode ser usada de forma segura a partir de mriltiplos threads? E
tentador pensar que sim; uma vez que os dados em names e$ao em um conjunto sincronizado, a classe Namelist tamb6m
6 "segura". Entretanto, nio 6 o caso - o m6todo removeFirst ( ) pode, is vezes, langar uma
NoSuchElementException. Qual6 o problema? Ser6 que ele nio verifica corretamente o size ( ) dos nomes antes d€
remover algo, para ceftificar-se de que existe alguma coisa neles? Como ese c6digo poderia falhar? Vamos tentar usar
Namelist destaf.orma
public static void main(StringlJ args; 1
t2.startO ;
408 Copitulo 9: Threoos
O que. poderia acontecer aqui seria.que um dos threads removeria um name e o exibiria, e depois o outro thread
tenrarra remover,r- nam.l obteriJnull. Se pensarmos apenas nas chamadas a names. size ( ) e
names - get (0 ) , elas ocorrem nesta ordem:
Thread t1 executa names . size ( ), que retorna 1.
Thread t1 executanames . remove (0 ) , que retornaozlzmandias.
Threadt2 executanames. size ( ),queretorna 0.
Ozlzmandias
nu11
Entretanto, se executarmos o programa novamente, poderi acontecer algo diferente:
names.add(name);
]
public synchronized String removeFirst ( )
if (names.sizeO > 0)
return (String) names.remove(0) ;
else
raf rrrn nrrl1 .
Agoratodoom6todoremoveFirstO estisincronizado,edepoisqueumthreadoiniciarechamarnames.sizeO,o
outro thread nio poder6 mais interromper e roubar o ultimo name. O outro thread simplesmente teri de esperar at6 que o
primeiro finalize a sua operagXo com o m6todo removeFirst ( ) .
A moral aqui 6 que, s6porqueest6descritacomo "seguraem rela$oatlveads",nioquer dizerqueuma classe 6 sempre segura.
Se m6todos individuais estiverem sincronizados, isso pode nio ser o suficiente - pode seruma solugXo melhorcolocar a
sincronizaqio em um nivel mais alto (ou seja, colociJa no bloco ou m6todo que chama os outros m6todos). Depois que voc6
faz isso, a sincronizagio original (neste caso, aquela dentro do objeto retornado por collections . synctrronizedlist ( ) )
podeni se tornar redundante.
lmpasse em threads
O que talvez possa ocorrer de mais assustador a um programaJava 6 o impasse. O impasse ocorre quando dois threads
ficam impedidos de obter um bloqueio, cada um esperando pelo bloqueio do outro. Nenhum deles poderl ser executado
at6 que abram mXo do bloqueio, portanto, aguardario eternamente. Isso poder6 acontecer, por exemplo, quando o thread A
chegar a um c6digo slmchroni zed, conseguir o bloqueio B e, em seguida, entrar em oaho m6todo (ainda dentro do
c6digo slmchroni zed. parao qual possui o bloqueio) que tamb6m for slmchroni zed. Por6m, o thread A nlo
poder4 obter o bloqueio par^ entr^r nesse c6digo slmchroni zed - o bloqueio C - porque outro thread, D, ji
est6 com ele. Sendo assim, o thread A ir|, para o pool "de espera do bloqueio C", na esperanga de que o thread D
JAVA 5 4O9
seja breve e o libere (concluindo o m6todo slmchronized). Mas o thread A ter6 que esperar realmente muito
depois que o thread l-) obteve o bloqueio C,.ele entrou em um m6todb slmchronized que usa o
l:mpo'.Pgrqle
bloqueio^ B. E.:l?to que o thread D nio conseguiu o bloqueio B, uma vez que o thread ,{
16 .rt"lr" com ele.'E esse
thread nio vai liber6lo at6 que o thread D libere o bloqueio C.
Contudo,othreadDnioliberariobloqueioCantesdeobterobloqueioBedarprosseguimento.Eassim
permanecerio. O exemplo a seguir demonstra o impasse:
1. public cl-ass OeadlockRisk {
2. private static class Resource {
3. public int value;
4. )
5. private Resource resourceA = new Resource ();
18. resourceA.value = a;
19. resourceB.value = b;
20. )
21. )
))t
23. \
Suponhamos que read ( ) tenha sido iniciado por um thread e write ( ) por outro. JA que temos dois threads
diferentes que podem ler e gravar independentemente, exise o risco de impasse na linha 8 ou 15. O thread de leitura possui
o recurso A, o de gravagio possui o recurso B e os dois ficario paralisados eternamente aguardando o outro desistir.
Um c6digo como esse quase nunca resulta em impasse porque a CPU tem que passar do thread de leitu ra para o de gravagXo
em um ponto especifico e as chances de o impasse ocorrer sio muito pequenas. O aplicativo pode funcionar bem 99,9 por
cento do tempo.
Esse exemplo simples 6 f6cil de corrigir; apenas troque a ordem do bloqueio do thread de leitura ou de gravaEio nas linhas
16 e 17 (ou nas linhas 8 e 9). Situag6es mais complexas de impasse podem levar muito tempo para serem identificadas.
Independente de serem pequenas as chances de seu c6digo entrar em um impasse, a conclusio 6 t se yoc€ entrar em un impasse,
fcaniparalivdo. H6 abordagens de projeto que podem ajudar a evitar impasses, incluindo estrat6gias de sempre obter
bloqueios em uma ordem predeterminada. Deixaremos a seu cargo esse estudo que est6 al6m do escopo deste livro. Se voc€
aprender tudo que abordamos neste capitulo, no entanto, ainda saber6 mais sobre threads do que a maioria dos
programadoresJava.
este riltimo thread teri que verificar continuamente se hi alguma correspondOncia aprocessar. Usando o
mecanismo de espera (l'"ir) . notificaglo (notify), ele poderia procurar a correspond6ncia, e se nio encontrasse
nenhuma dizerr
;Ora,'nlo vou perder-meu tempo proiurando-correspond6nciai a cada dois segundos. Vou ficar
por aqui, e quando o distribuidbr de correspond6niia colocaralgo nacaixa de correio, farei com que ele me avise'
Assim, .n posso voltar ao estado execut ivel e f.azer meu trabalho". Em outras palavras, os m6todos wai t ( ) e
notify ( ) permitem que um thread fique em uma "sala de espera" at6 que algom outro thread o avise
(notifique) de que hi uma r^z1o para voltar ) atividade.
Um ponto a lembrar (e memorizar para o exame) sobre waitlnotify 6 esse:
Os ndtodos waiL ( ), noti f y ( ) e noti fyA11 ( ) deuen ser chamados de dentn dr um contexto sincmniTado! O thread nio
pode chamar an mdtodo aait or,t notifi de am objeto a menls que obtenba o bloqueio duse objeto.
Agora apresentaremos um exemplo de dois threads que dependem um do outro para dar prosseguimento a suas tarefas, e
mosrraremos como usarwaiL ( ) e notify ( \ pirafazercom que interajamieguramente e no momento apropriado'
Considere uma m6quina controlada por computador que cone pedagos de tecido em formatos diferentes, e um aplicativo
que permita que os usuS.rios especifiquem o formato do cone. A verslo atual do aplicativo possui somente um thread, o
q"at pri-.iro solicita ao usuirio instrug6es e, em seguida, direciona o hardware para cortar no formato desejado, repetindo
ociclo&pois.
public void run ( ) {
while (true) {
'
Esse projeto nlo 6 6timo porque o usuirio nio poder|fazer nada enquanto a miquina estiver ocupada e houver outros
formatos a definir. Precisamos melhorar a situa$o.
Uma solugio simples 6 separar os processos em dois threads diferentes, um deles interagindo com o usuirio e outro
gerenciando o hardware. O thread do usu6rio enviar6 as instrug5es para o thread do hardware e, em seguida ,voltarh a
interagir com o usuirio imediatamente. O thread do hardware recebe as instrug6es do thread do usuirio e comega a instruir
a miquina imediatamente. Os dois threads usam um objeto em comum para se comunicarem, o qual cont6m o projeto
atual que est6 sendo processado.
l
Oproblema agora|.fazer comque o threaddo hardware processe as etapas &miquinalogo que estiverem disponiveis.
AlSm disso, o lhread do usuirionio deve alter6Jas at6 que todas tenharn sido enviidas paia o hardware. A solugio 6 usar
wait ( ) enotify ( ), al6mdesincronizaralgunstiechosde c6digo.
Lembre-sedequeosm6todoswait( ) enotify( ) slom6todosdeinstAnciadeObiect.Damesmamaneiraque
todo objeto poisui um bloqueio, pode haver uma lista um sinal (uma notificagio) desse objeio. Um
de threads aguardando
thread pode entrar nessa lista com a execugio do m6todo wait ( ) do objeto de desdno. A partir desse momento, ele nio
executarl nenhuma outra instrugio at6 que o m6todo noti fy ( ) do obieto de destino seia chamado. Se muitos threads
e$iverem aguardando no mesmo objeto, somente um seri selecionado (sem uma ordem definida) para prosseguir com sua
execugio. Se nio houver threads esperando, entao, nenhuma agio especifica seri tomada. Examinemos um c6digo real que
mo$ra um objeto aguardando que outro o notifique (preste atenglo ji que 6 um pouco complexo):
JAVA 5 411
1. class ThreadA {
2. public static void main(String [] args) {
3. ThreadB b = new ThreadBo;
4. b.start0;
5.
6 . slmchronized (b) i
'7. try {
zo. l
27. j
Esse programa condm dois obfetos com threads. ThreadA cont6m o rhread principal e ThreadB possui um thread oue
calcula a soma de todos os ntmeros de 0 a 99. Logo que a linha 4 chamar o m6todo start ( ) , ihreadA passar6 p'ara a
pf"ft"Jd* de c6digo de sua pr6pria classe, o qie si-gnifica.que pode chegar ) linha 12 antes que ThreadB concluaieu
carcuro. r-ara rmpecur rsso, usamos o metodo wat-t ( ) na lrnha y.
Observe na linha 6 que o c6digo 6 sincronizado com o objeto b; isso porque, para chamarwait ( ) no objero, ThreadA
precisa.do.bloque-iodeb.Paraqueumthreadchamewait( )ounbtity[ ),.1.t.-queseroproprietiriodo
bloqueio desse objeto,. Quando o thread estiver aguardando, liberar6 temporariamente o bloqueio para outros threads
usarem, masprecisar6dele novamenteparadarpiossegurmento aexecugao. E comum enconirarmbsnm c6digo como o
segumte:
Esse c6digo notificari qualquer outro que esteja aguardando o obieto this. O bloqueio pode ser obtido bem no
inicio do c6digo, por eiemplo, no m6todo chamador. E bom ress;ltar que se o threid qui chamar wai t ( ) nio
tiver o bloqueio, uma excegXo rllegalMonitorstateException seri langada. Eisa exceglo nio 6 verificada,
412 Copftulo 9: Threods
porranro, voc[ nlo precisa captari-la explicitament". E i*po.tante semPre deixar claro se um thread possui o
bloqueio de um ob.iito em um bloco de c6digo especifico.
Observe nas linhas 7-10 que hi um bloco trylcatctr encapsulando o m6todo wait ( ) . Um thread em esPera
p;jgr.; i"tlri"mpid" di -.rrrr" maneiraqnl. n- thread em suspenslo, portanto, voca ter6 que manipular a
exceglo:
trY{
wai_t O ;
) catch(InterruptedException e) {
/ / Faqa alga sobre isso
)
No exemplo do tecido, esses m6todos serio usados parafazer.com que o hardware esPere.que.o formato fique
disponivel e o thread do usu6rio emita uma notificagio depois que is_etapas forem gravadas. As etaPas. da
*6q"itr" podem incluir etapas globais, como mover o tecido requerido para.a 6rea de cone e v6rias subetapas,
como a diregio e o comprimenio de um corte. A titulo de exemplo, elas poderiam ser:
int fabricRoll;
int cuttingSpeed;
Point startingPoint,'
tloat t I oarecE.lons;
rrvsu L
etc. .
E imponarrte que o thread do usuirio nlo altere as etapas da m6quina enquanto o thread do hardware as estiver
,rsando, portanio, essa leitura e gravagS,o devem ser sincronizadas.
O c6digo resultante ter6 esse formato:
public void runO {
while(true) {
/ / ObL6m um formato do usu6rio
slmchronized(this) {
// Calcula as novas etapas da m6guina para o formato
notifyO ;
]
i
class Machine extends fhread {
operator operator; // assuma que isso seja iniciali-zado
public void runO {
while(true) {
slmchronized ( operator) {
xtY {
operator.wait ( ) ;
] catch(InterruptedException ie) {}
/ / Errvia as etapas da m6quina para o trardware
)
]
O thread da miquina, uma vez iniciado, entrar6 imediatamente no estado de espera, e aguardari pacientemente at6 que o
operador envie iprimeira notificaESo. Nesse momento, ser6 o thread do operador que teri o bloqueig dessg o_bj91o,
pbrtanto, o threJd do hard* are frcariparalisado por algum tempo. 56 depois que o thread do operador sair do bloco
iincronizado 6que o thread do hardware poder6 realmente iniciar oprocessamento das etapas da m6quina.
JAVA 5 413
Enquanto um formato estiver sendo processado pelo hardware, o usu6rio poder6 interagir com o sistema e
especificar outro_formato para ser cortalo. Quanio o usu6rio tiver terminado o formato-e for hora de con6-lo, o
thread do operador rcntarl entrar no bloco s]ncronizado, podendo ser impedido at6 que a miquina .orr.l.r"-", o"p",
anteriores. Quando o thread da m6q]rina tiver terminado, iepetir6 o loop, entrando ,rorr"m.rrt. no est"do d. .rp.ri -
(e, ponanto,.liberando o bloqueio). 56 entio o thread do operador podei6 entrar no bloco sincronizado
esubstituir as
etapas da miquina pelas novas.
Ter dois threads 6 definitivamente uma melhoria sobre ter somente um, embora nessa implementagao ainda haja
uma possibilidade de fa7.ey.9 ujuirio esperar. Uma melhoria adicional seria rer muitos forrn"to, em uma fila, '
reduzindo assim a possibilidade de ser necessirio solicitar ao usuirio que aguarde o hardware.
Tamb6m
!6 yma. segunda versXo de wait ( ) que aceita alguns milissegundos como tempo miximo de espera. Se
o thread nio for interrompido,_continuarA sua eiecuglo nor-malment. tJ*p.. que for notificado ou o que 6,.*po
--r -
de espera especificado expirar. Essa continuagXo comum consiste em sair do eriado de espera, ,rr", p"rl d"i
prosseguimento i execugio serl necess6rio obter o bloqueio do objeto:
slmchronized(a) { // O thread obt6m um bloquei-o em .a,
a.wait(2000); // O thread libera o bloqueio e espera por notify,
/ I mas soment.e por dois seg,undos no miiximo, depois retorna para Runnable
// O Lhread readquire o bloqueio
/ / ItIais inst.ruc6es acrui
j
7.
8. publ-ic void runO {
crmnhrnni zaAlr\ t
1-0 . j-rrr I
11 Qrr<fpm
eJ v eurrL. nrrl- nrini- ln/.'T^7^if
\ vvqr Lf ina
rrv fnr nalnrrl:f Lf inn
vrr. r r
x\
/ ,
L2. n rrr:ifl\.
414 Copitulo 9: Threods
l-3. ) catch (InterruptedException e) {i
1,4. ]
l-5. System.out.println("Total is: " + c.total);
I7'
18. public static void mai-n(String [] args) {
t9 . Cal-cul-ator calculator = new Calculator ( ) ;
20. new Reader(calculator) .startO ;
2L. new Reader(calculator) .startO ;
22. new Reader (calculator) . start ( ) ;
23. calculator.startO;
24. )
25. j
26.
27. class Calculat.or ext.ends Thread {
28. int total;
29,
30. public void run0 {
31 . slmchronized (this ) {
32. for(int i=0;i<100;i++) {
33. total += i;
34. ]
35. notifyAll O;
36. )
3'7. )
38. )
Esse programainida tr6s threads, todos esperando para receber o cilculo concluido (linhas 18-2a), e depois inicia a
calcuiadJra e a sua tarefa. Observe qn. r. o m6todo run ( ) da linha 30 usasse notify ( ) em vez de notifyAll (
Isso poderia acontecer, uma vez que nXo podemos garantir em que ordem as diferentes partes do.thread irio executar.
InfeLmente, quando os Readers rodam, eles comelam a esperar imediatamente. Nlo faznmnadaparaver. se o evento pelo
qualestioespeiandoj6aconteceu.Assim,seoCalculatorjitiverchamadonotifyAll O,nioirAcham|-lonovamente-
e os Readers na espera ficario esperando para sempre. Isso provavelmente nXo 6 o que o programador queria que
acontecesse. Quasl sempre, quandovoc6 queresperarporalgo, precisatamb6msercapazdevenficar se o wento j6ocorreu.
Geralmente, a melhor maneira de resolver isso 6 colocar algum tipo de loop que verifique em algum tipo de express6es
condicionais, e espere somente se o evento ainda nio tiver acontecido. Eis uma versio modificada, mais segura, do exemplo
anterior damiquina cortadora de tecidos:
class Operator extends Thread {
Machine machine;// assume que isso seja inicializado
public void runO {
while (true) {
Shape shape = getshapeFromUserO;
Machinefnstructions -iob =
JAVA 5 415
calculateNewlnstructionsFor ( shape ) ;
machine. add,fob ( j ob) ;
O operador continuar6o loop para sempre, obtendo mais formatos dos usuirios, calorlando novas instn46es para esses
formatos enviando-os para a miquina. Mas agon al6grca para no t i fy ( ) foi movida para dentro do m6todo add,Job ( )
e
dadasseMachine:
cl-ass Machine extends Thread {
List<Machinelnstructions> i obs =
new Arrayl,ist<Machinefnstructions> ( ) ;
crmnhrnnizod /'inhc\ I
/ / aqnara
/ / veyvre al- 6 mra no l o menos um job esteja disponivel
whil-e ( jobs. isEmpty( ) ) {
try {
inl-'c 'uai t 1\
] catch (InterruptedException ie) { }
)
A m6quina mant6m uma lista dos trabalhos agendados. Sempre que um operador adiciona um novo trabalho i lista, ele
chamaom6todoadd.rob O ef.azaadtgio.E'nquantoisso,om6iodorunO continuaoloop,procurandoportrabalhos
na lista. Se nio houver nenhum, ele comega a esperar. Se for notificado, iri parar de esperar e irl verificar novamente a
condigio do loop: a lista ainda est6 vazia? Na pi6tica, essa verificagio dupla provavelmente nio 6 necessiria, uma vez que o
rtnico momento em que um noti fy ( ) 6 enviado 6 quando um novo trabalho acabou de ser adicionado i lista.
Entretanto, 6 uma bo; id6ia exigir que o thread verifique novamente a condigio i sHrpty ( ) sempre que for reativado,
porque 6 possivel que um thread tenha acidentalmente enviado um noti fy ( ) incorretamente.
Existe tamb6m uma situaglo possivel, chamada de reativagio espontenea, que pode existir em algumas situag6es - um thread
podeserreativadomesmoquenenhumc6di.gotenhachamadonotifyO ounotifyAllO.@elomenosnenhum
i6Ag" de que voc€ tenha conhecimento. Als vezes aJW poderi chamar notify ( ) po1 raz6es que s6 ele sabe,_ou
programar ilgumas outras chamadas de classes por raz6es desconhecidas) O que isso significa 6 que, quando o seu thread 6
reativado depois de um wai t O , voc6 nlo sabe com ceneza por que motivo ele foi reativado. Ao colocar o m6todo wai t o
em um loop whi 1 e e veriiicar novamente a condigio que representa o evento pelo qual estivamos esperando, nos
cenificamosdeque,qualquerquesejaomotivo,voltaremosawaitO se(esomentese) oeventoaindaniotiveracontecido.
Na classe Machine, o que e$avamos esperando era que a lista de trabalhos nio estivesse vazia. Se estiver vazia, esperamos; se
nlo estiver, nio esperamos.
modific6veis, e sio armazenados em um campo que 6 acessado por dois threads diferentes. Precisamos
sincronizar para podermos acessar esses dadoi mbdificiveis de iorma segura. Felizmente, os mesmos blocos
sincronizador qrr. ro, permitem esperar (wait ( )) e notificar (notify"( )) tamb6m fornecem a seguranga de
thread requeridl para os nossos outros acessos a dados modificiveis. Na verdade, essa 6 a razio principal pe_la _
qual a sinironizagilo precisa usar wait ( ) e notify O - quase sempre, voc6 precisa companilhar alguns dados
modificiveis entre v6rios threads ao mesmo tempo, e isso significa que voc6 precisa da sincronizagio. Repare que
o bloco de sincronizaEio em addJob ( ) 6 grande o suficiente para incluir tamb6m a chamada a
jobs. add(job) que modifica dados compartilhados. E o bloco sincronizado em run ( ) 6 grande o suficiente
-
paraincluirtodooloopwhile-queincluiachamadaajobs.isEmptyO,queacessadadoscompartilhados.
Amoraldahist6ria6que,quandousawaitO enotifyO ounotifyAll{),quasesemprevoc6deveterum
loop while junto com wait ( ) para verificar uma condigio e forgar a continuagXo da espera at6 que a condigio
seja atendida. E vod deve tamb6m usar o requerimento de sincroniza$o para as chamadas await O e notify O , para
proteger tarnb6m quaisquer outros dados que estiver compartilhando entre tfreads. Se vir c6digo que falhe em fazer isso,
normalmente hi algo de errado com o c6digo mesmo se vod tiver dificuldacles em ver qual 6 exatamente o problema"
-
OBSERVAQ6BS pene O EXAME
O:ndtodoswaiL( ),notify( )enotifyAll( ) sdonitodotnmentedejaua.lang.Objut,endodejaua.lang.Tltreadou
jaua.lang.Rannable. Certfique-se de saber que mritodos sdo defnidu em Tbread, quais sdo en Objut e os de Runnable (sonente ran( ),
plftantqesseificil).DosrzitodosprincipaisdeThread,ceftifique-sedesaberquaissdosLaLic -s1eep( )eyield( )- e
) pode ser usado para fazer uma pausa em um thread, e vimos que quando um objeto entra em suspensio,
mant6m todos os bloqueios que obteve antes de ficar suspenso.
Examinamos os cinco estados dos threads: novo, execut6vel, de execugio, bloqueado/em espera/suspenso e inativo. Voc6
aprendeu que quando um thread est6 inativo, nunca poderi ser restaurado mesmo se ainda lor um objeto vilido no heap.
Vimos que s6 h6 uma maneira pela qual um thread pode passar para a execugio, que 6 a partir do e$ado execut6vel. No
entanto, uma vez em execugXo, o thread pode se tornar inativo, entrar em suspensio, esperar que outro thread seja
concluido, ser impedido de obter o bloqueio de um objeto, esperar por uma nbtificagio ou retornar ao estado exicut6vel.
VocA viu como dois threads atuando sobre os mesmos dados podem causar problemas s6rios (embra-se da conta banc6ria
de Lury e Fred?). Vimos que, para permitir que um thread execute um m6todo, impedindo, por6m, que outros threads
Processem o m6todo do mesmo objeto, usamos apalavra-chave slmchronized. Para coordenar iatividade entre
threadsdiferentes,useosm6todoswait ( ),notify( ) enotifyAll ( ).
Exercicios ripidos
Aqui estio algunsdos pontos principais de cada objetivo para a certificagio deste Capinrlo. Tire uma c6pia e durma com eles
embaixo de seutravesseiro para completar a absorgio.
D QuandoumobjaoThreadforcriado,eleniosetomarawntlmaddemug'wxiq:eseum6todostart( )sejacharrudo.
tr Quando um objeto Thread existe, mas nio foi iniciado, est6 no estado nouo e nXo 6 considendo atiuo.
D Para uma m6quina tipica, de apenas um processador, s6 um thread pode ser executado por vez, embora muitos possam
estar no estado execut6vel.
tr Nio hi garantia de que a ordem na qual os threads foram iniciados determinarl a ordem na qual serio executados.
tr Nio h6 garantia de que os threads terio a chance de ser executados de maneira justa. Isso 6 responsabilidade do
agendador, como determinado pela implementagio especifica da miquina virnral. Se voc0 quiser garantir que seus
threads terio sua execugio alternada, independente daJVM subjacente, deve usar o m6todo sleep ). Isso (
impedir6 que up thread domine.o processo sendo executado enquanto o outro estiver aguardando. (No
entanto, na maioria dos casos, yield ( ) funciona bem o suficiente para encorajar os seus threads a
trabalharem bem juntos.)
E Umthreadsendoexecutadopodeentraremumestadobloqueado/deesperaporumachamadaawait( ),s1eep( )
oujoin( ).
D Um thread sendo executado pode entrar em um estado bloqueado/de espera, porque nio p6de obter o bloqueio de
umtrecho de c6digo sincronizado.
E Quando o m6todo wait ou sleep for concluido, ou o bloqueio de um objeto se tornar disponivel, o thread s6 poder6
entrar novamente no e$ado executivel. Ele ir6 diretamente da espera para a execuglo (bem, tudo por raz6es pr6ticas).
E Um thread em suspenslo ficari inativo por pelo menos o tempo especificado no argumento do m6todo s leep ( ) (a
menos que seja interrompido), mas nio h6 garantias de quando o thread rec6mdesperto retornar6 realmente ) execugio.
D O m6todo sleep ( ) 6 um m6todo staEic que suspende o thread que estiver sendo executado. Um thread nio
pode informar a outro que deve ficar suspenso.
fl O m6todo setpriority ( ) 6 usado em objetos Thread para dar aos threads um n(vel de prioridade entre 1 Saixo)
e 10 (alto), embora prioridades nio sejam garantidas e nem todos osJVMs usem um intervalo de prioridades de 1 a
as
10 - alguns niveis podem ser tratados como efetivamente iguais.
E Se nio for configurada explicitamente, a prioridade de um thread seri a mesma do thread que o criou.
O O m6todo yield ( ) pode fazer com que um thread em execuglo se.ja interrompido se houver threads execut6veis com a
mesmaprioridade. Nio h6garantias de que isso ocorreri e de que quando o threadfor interrompido umthreaddiferente
ser6selecionado paraexeorSo. Umthreadpode serinterrompido e reentrarimediatamente no esado deexean$o.
tr O mais pr6ximo que teremos de uma garantia serA que, em qualquer momento em que um thread estiver sendo
executado, ele geralmente nio ter6 uma prioridade menor do que a de algum outro thread do estado executivel. Se um
thread de prioridade menor estiver sendo executado quando um thread de prioridade alta entrar no estado
executrvel, a JVM geralmente interromperA o thread de prioridade menor e comegar6 a executar o de
prioridade alta.
B Quando um thread chamar o m6todo j oin ( ) de outro thread, aquele que estiver sendo executado esperar6 at6
que o thread ao qual foi adicionado seja concluido. Considere o m6todo j oin ( ) como se dissesse: "Ei thread,
quero ser acrescentado ao seu final. Deixe-me saber quando voc6 tiver encerrado sua execugio para que eu possa
entrar no estado execut6vel.
E Para sincronizar um bloco de c6digo (melhor dizendo, um escopo menor do que o m6todo inteiro), voc6 ter6
que especificar um argumento que seja o objeto em cujo bloqueio quiser basear a sincronizaglo.
E Embora s6 um thread possa acessar o c6digo sincronizado de uma instAncia especifica, virios threads podem acessar o
mesmo c6digo nio sincronizado do objeto.
E Quando um objeto entra em suspensio, seus bloqueios estario indisponiveis para outros threads.
E Osm6todosstatic podemserslmchronized comousodobloqueiodainstAnciadejava.lang.Classque
representar essa classe.
E O m6todo noti fy ( ) ndo pode especificar qual thread em espera deveri ser notificado.
E Om6todonotifyAll ( ) funcionadamesmamaneiraquenotify( ),s6queenviaosinalparatodosos
threads que estiverem aguardando no objeto.
Teste individual
Asperguntas a seguir o ajudarXo a avaliar sua compreensXo sobre o material apresentado nese capinrlo. Se inicialmente achar
dificil, nio se culpe. Seja otimista. Algumas destas quest6es sio longas e intrincadas, espere ver quest6es longas e intrincadas
no exametamb6m!
l. Dado:
public class Messager implements Runnable {
public static void main(St.ring11 args) {
message(2);
)
prj.vate slmchronized vold message(int n) {
System.out.print(name + \-" + n + " ");
)
JAVA 5 419
this.name = name;
Qtreremosnoscenficardequeasaidasejaou)O(YYouYY)O!masnuncaXYXYnemqualqueroutracombinaSo. Quaisdas
seguintadefinig6esdem&odospoderiamseradicionadas lclasselenenparase obteressa-garanrid (Marquetodas asco-rretas)
A public void runo { writel;; i
B. public synchronized void runO { writeO; }
C public static slmchronized void runO { wriLeO; }
D. public void run0 { stmchronized(this) { writeO; } }
E. public void runO { stmchronized(Letters.class) { writeO; } i
E public void runO { slmchronized(System.out) { writeo; } }
G public void runO { stmchronized(System.out.class) { writeO; } }
4. Dado:
2. class MyThread extends thread {
3. public static voj-d main(String [] args) {
4. MyThread t = new MyThread|;
5. t.srarto;
6. System.out.print("one. ");
't . t. start O ;
8. System.out.prj-nt("two. ");
9. )
10. public void runo {
11. System.out.print("Thread ");
72. )
l-3. )
Qual6 o resultado desse c6digo?
A Acompilagofalha.
B. Ocorre uma exce$o no tempo de execu$o.
C Thread one. Thread two.
D. A saida nio pode ser determinada.
8.
9. public voi-d run O {
10. for(int i=0;i<3;++i) {
11. System.out.print(i + "..");
1.2. )
1? l
14. )
4. printAll (args) ;
JAVA 5 421
s. )
8. for(int !=Q;i<1j-nes.length;i++){
9. System.out.printl-n(1ines Ii] ) ;
10. Thread.currentThreadO.sleep(1000);
11. ]
L2. ]
1? I
o m6todo stat.ic Thread. currentfhread ( ) retornar| uma referencia ao objeto Thread que estiver
sendo executado no momento. Qual seri o resultado desse c5digo?
A. Seri exibida cada String das linhas do array, com uma pausa de 1 segundo.
B. Ser6 exibida cada String das knhas do array, sem pausa entre elas porque esse m6todo nio 6 executado em um objeto
Elt
r nread.
C. Seri exibida cada String das /inbat do array, sem garantias de que haveri uma pausa porque
currentThread ( ) pode nio recuperar esse thread.
D. Esse c6digo nio ser6 compilado.
7. Suponhamos que voce tivesse uma classe com duas varieveis private: a e b. Quais dos
pares a seguir Podem impedir problemas de acesso simultAneo nessa classe (selecione todos
que forem aplic6veis)?
'4" public int read(int a, int b) {return a+b}
public void set(int a, int b) {this.a=a;this.b=b}
B. public synchronized int read(int a, int b) {return a+b}
public slmchronized void set(int a, int b) {this.a=a;this.b=b}
C public int read(int a, int b) {synchronized(a) {return a+b}}
public void set(int a, int b) {slmchronized(a) {this.a=a;this.b=b}}
D. public int read(int a, int b) {s}mchronized(a) {return a+b} }
public void set(int a, int b) {slmchronized(b) {this.a=a;this.b=bi}
E. public synchronized(this) int read(int a, int b) {return a+b}
public slmchronized(this) void set (int a, int b) {this .a=a; this.b=b}
H public int read(int a, int b) {slmchronized(this) {return a+b} }
public void set(int a, int b) {synchronized(this) {this.a=aithis.b=b}}
8. Quais dos m6todos abaixo s6o da classe Object. (Marque todas as corretasx
,d notify( );
B.notifyAll ( );
C isfnterrupted( r;
D. slmchronized( );
E.
!. int-arrrrni-/
4rf ue!rqvu I
\'
I I
E wait(1ong msecs);
G sleep(long msecs);
FL yield( );
3. System.out.print("1 ");
4. slmchronized(args) {
5. System.out.print("2 ");
6. try {
'7. args.wait0;
B. )
9. catch(InterruptedException e) {}
10. ]
1l-. System. out.print. ( "3 " ) ;
L2. ]
13. i
qual seri o resultado se tentarmos compilar e executar esse programa?
E. Notempodeexecuglo,elelangar6umaexcegiolllegalMonitor StateExceptionquandotentarentrarno
estado de espera.
E Sua compilagio falhar6 porque ele tem que ser sincronizado no objeto this.
10. Suponhamos que o m6todo a seguir tenha sido apropriadamente sincronizado e chamado
por um thread A no objeto B:
wait (2000) ;
Depois que esse m6todo for chamado, quando o thread A se tornar6 candidato a conseguir outra chance de ser executado
PelaCPI-llr
A Depois que o thread A for notificado, ou ap6s dois segundos.
B. Depois que o bloqueio de B for liberado, ou ap6s dois segundos.
C Dois segundos ap6s o thread A ser notificado.
D. Dois segundos ap6s o bloqueio de B ser liberado.
Il. Quais das declarag6es abaixo sio verdadeiras? (Marque todas as corretas)
A O m6todo notify ( ) deve ser charnado em um contexto sincronizado.
B. Para chamar wai E ( ) , um objeto deve possuir o bloqueio do thread.
C O m6todo notify ( ) 6 definido na classe java.lang.Thread.
D. Quando um thread esdver aguardando como resultado de waitQ, liberari seus bloqueios.
E. O m6todo not.i fy ( ) faz com que um thread libere imediatamente seus bloqueios.
E Adiferengaentre notify ( )enotifyAll ( ) 6quenotifyA]1 ( )notificatodos osthreads queesteo
aguardando, independente do objeto em que estio esperando.
12. Dado o cen6rio: Esta classe dever6 permitir que os usu6rios escrevam uma s6rie de
mensagens, de forma que cada mensagem seja identificada com a hora e a data, d6m do nome
do thread que escreveu a mensagem:
public class Logger {
private StringBuilder contents = new StringBuilderO;
public void log(String messaqe) {
contents . append ( System. currentTimeMillis ( ) ) ;
contents.append(" : ") ;
JAVA 5 423
contents . append (Thread. currentThread ( ) . getName ());
Como podemos garantir que as instAncias dessa classe poderio ser usadas de forma segura por mriltiplos threa&?
A. Essa classe j6 6 segura.
B. Substituir StringBuilder por StringBuffer tornar6 essa classe segura.
13. Dado:
public static slmchronized void main(String[] args) throws
InterruptedException {
Thread t = new Thread0;
t. start O ;
Syslem. out.print ( "X" ) ;
t.wait(l-0000);
System. out.print ( "Y" ) ;
,I
A Exibexefinaliza.
B. Exibex enuncafinaliza.
C ExibexY efinalizaquaseimediatamente.
D. Exibe xY comum atraso de 10 segundos entre X e Y.
ItyThread ( ) {
)
public void run(String s) {
System. out.println ( " baz" );
i
);
t.start O ;
)
qual ser6 o resultado?
A. foo
B. MyThread foo
C Mythread bar
D. foo bar
E. foo bar baz
E bar foo
G Acompila$oQallariL
H E langada uma excegio no tempo de execugio.
15. Dado
public class ThreadDemo {
slmchronized void aO { act.Busy0; i
static slmchronized void bO { actBusy0; }
) catch (fnterruptedException e) t)
]
public static void main(String[] args) {
finaf ThreadDemo x = new fhreadDemoO;
final- ThreadDemo y = new ThreadDemoo;
Runnable runnable = new Runnable0 {
public void runo {
j-nt option = (int) (Math.random1 * 4l;
switch (option) {
case 0: x.ao,' break;
case 1: x.b0; break;
case 2: y.ao; break;
case 3: y.bO; break,'
)
j;
Thread threadl = new Thread(runnabl-e);
Thread thread2 = new Thread(runnable);
threadl. start O ;
thread2. start O ;
JAVA 5 425
Quais dos seguintes pares de chamadas a m6todos nunca poderiam ser executadas ao mesmo tempo? (l4arque todas as
corretas)
A.x.a0 em threadl, and x.ao em thread2
B. x.ao em threadl , and x.b0 em thread2
C. x.ao em thread.l , and y.ao em thread2
D. x. a O em threadl , and y. b O em thread2
E. x.bo em threadl , and x.ao em thread2
F. x.bo em threadl-, and x.bo em thread2
G.x.bo em Lhreadl, and y.ao em thread2
H.x.bO em Lhread.l , and y.bo em t.hread2
1,4. t. start ( ) ;
l-5 . g. start O ;
16. ]
17. )
1. class Foo {
2. int x = 5,'
3. public void doStuff ( ) {
4. if (x<10) {
5. // nada a fazer
6. try {
7. wait.O;
8. ] catch(InterruptedException ex) { }
9. ) else {
10. System.out.println("x is " + x++);
11. if (x >= 1-0 ) t
12. notifyQ;
1? ]
]-4. )
1s. ]
16. )
qual seri o resultado?
A. O c6digo nXo seri compilado por causa de um erro na linha 12 da classe Foo.
426 Copitulo 9: Threods
B. O c6digo nXo seri compilado por causa de um erro na linha 7 da classe Foo.
C. O c6digo nlo seri compilado por causa de um erro na linha 4 da classe Test'
D. O c6digo nio ser6 compilado por causa de algum outro erro na classe Test.
)
);
hardy = new rhread0 {
public void run0 i
q\rcfam
vJpeurrr.vuu.Pif.rL4nrrl- nrint-ln l"Tl/) .
trY {
laurel.wait ( ) ;
] catch (Exception e) t
System. out . println ( "8" ) ;
)
q\rcl_am
vtruelri.vuL.vr nrin|In INF"') :
^rrt-
]
);
laurel. start O ;
hardy. start O ;
Quais letras acabarlo aparecendo em algum lugar na saida? (Marque todas as corretas)
,4. a
B.e
Cc
D.p
E.e
Ep
G A resposta nio pode ser determinada de forma segura.
H Oc6digonSocompila.
JAVA 5 427
4. B esti correta. Quando se tenta usar o m6todo start ( ) pela segunda vez em um mesmo objeto Thread, o
m6todo lang*i uma IllegalThreadStateException. @mbora esse componamenro esteja
especificado na API, alguns JVMs nio langam uma excegio consistentemente neise caso.) Mesmo se o thread
tiver terminado de rodar, ainda 6 invilido chamar start ( ) novamente.
A est6 incorreta porque a compilagio teri sucesso. No geral, o compilador Java s6 verifica se existem erros de
sintaxe, emyez de erros na l6gica especifica de cada classe. C e D estio incorretas com base na l6gica exposta
acima. (Objetivo4.1)
J. D esti correta. O thread MyThread seri iniciado e executar6 um loop tr6s vezes (de 0 a 2).
A resposta A est6 incorreta porque a classe Thread implementa a interface Runnable; portanto, na linha 5,
Thread pode usar um objeto do tipo Thread como argumento no construtor. B e C estio erradas porque a
vari6vel i do loop for comega com um valor igual a 0 e termina com2. E esti incorreta por causa da l6gica do
programa que esti desffita acima. (obj +.1)
6. D esti correta, O m6todo sleep ( ) deve ser inserido em um bloco try,/catch ou o m6todo printAll (
7. B e F estio corretas. Se os m6todos forem marcados com slmchronized, os threads obterio o bloqueio do
objeto thisantes de prosseguir. 56 um thread estar6 configurando ou lendo em determinado momento, o
que assegura que read (
) sempre retorne a soma de um par v6lido.
A resposta A est6 incorreta porque nio foi sincronizada; portanto, ni,o h6 garantias de que os valores somados
pelo m6todo read ( ) pertengam ao mesmo par. C e D estio erradas; somente objetos podem ser usados na
sincronizagio. E falha; nio 6 possivel selecionar outros objetos (nem mesmo thi s) para executar a sincro ruzergio
quando um m6todo for declarado com slmchronized. (Objetivo 4.3)
& A, B e F estio corretas. Eles estio todos relacionados ) lista de threads em espera no objeto especificado.
bloco de c6digo sincronizado pelos argumentos. F est6 errada porque qualquer objeto pode ser usado na
sincronizaglo e, al6m disso, this e static nio combinam. (Objetivo 4.4)
10. A esti correta. Um dos dois eventos fari com que o thread se torne candidato a ser executado novamente'
A resposta B est6 incorreta porque um thread em espera nio retornar6 para o estado exectt6vel quando o bloqueio
for liberado, a menos que uma notificagio ocorra. C est6 errada porque o thread se tornar6 candidato
imediatamente ap6s a notificagio. D tamb6m est6 incorreta potqne Jm thread nio sair6 de um pool de espera s6
porque um bloqueio foi liberado.
l,l.ArespostaAest6corretaporqueom6todonotifyAll( ) (untoawait( ) enotify( ))devesemPre
ser chamado em um contexto sincronizado. D 6 uma instrugio correta.
A resposta B est6 incorreta porque para chamar wait ( ) , o thread deve possuir o bloqueio do objeto em que
waiC ( ) est6 sendo chamido,i nio o contr6rio. C esti erradaporque notify( ) 6 definido em
java.lang.object.Eest6erradaporquenotify( ) niofar6comqueumthreadlibereseusbloqueios.O
thread s6 poderi liberi-los saindo do c6Agb sincronizado. F est6 incorreta porque notifyAll ( ) notificar6
rodos os threads que estiverem aguardando um objeto bloqueado especifico e nio todos os threads que estiverem
aguardando em qaaQaer objeto. (Objetivo 4.4)
12. E estit, correta. Sincronizar os m6todos priblicos 6 suficiente paru tornar a classe segura, en6o F 6 falsa. Esta
classe nioestar6 segura a nio ser que algum tipo de sincronizaglo proteja os dados sendo modificados.
B nio est6 correta porque, embora um StringiBuf fer seja sincronizado internamente, podemos chamar
append ( ) diversas vezes, e nada impediria que duas chamadas simultAneas a log ( ) misturassem as suas
mensagens. C e D nio esteo corretas porque se um m6todo permanecer dessincronizado, ele poderi executar
enquanto o outro esti rodando, o que poderia resultar na leitura do conterido enquanto uma das mensagens ainda
est6 incompleta, ou em algo pior. (VocA nio vai querer chamar getstring ( ) para o StringBuf ter
enquanto ele est6 modificando o tamanho do seu array de caracteres interno.) (Objetivo 4.3)
13. G esticorrera. O c6digonio adquireumbloqueioem t antesde chamar t.waitO, entio elelangauma
Illega1Thread.StateException. O m6todo est6 sincronizado, mas nio em L, entlo a excegio ser6langada. Se
a espera fosse colocada dentro de um bloco slmchronized (t ) , entAo a resposta correta seriaD.
A, B, C, D, E e F estio incorretas com base na l6gica exposta acima. (Objetivo a.2)
14. A resposta B est6 correta. Na primeira linha de main estamos construindo a instAncia de uma classe interna
an6nima, estendendo MyThread. Poftanto, o construtor de MyThread ser6 executado e exibiri MyThread.
A pr6xima instruEeo de main chama start ( ) na nova instAncia do thread, o que far6 com que o m6todo
run ( ) sobrescrito (o m6todo run ( ) definido na classe interna an6nima) seja chamado.
As respostas A, C, D, E, F e G esteo todas incorretas por causa dal6gca do programa que estA descrita acima.
(Objetivo4.1)
15. A, F H. A est6 correta porque os m6todos chamados para a mesma instAncia bloqueiam uns aos outros. F e
e
H nio poderiam acontecer porque m6todos static synctrroni zed da mesma classe bloqueiam uns aos
outros, independentemente de qual instAncia foi usada para chamar os m6todos. (I.{1o 6 obrigat6rio que uma
instAncia chame m6todos stat.ic; apenas a classe est6 su.ieita a esse requerimento.)
C poderia acontecer porque os m6todos slmchronized chamados para diferentes instincias nio
bloqueiam uns aos outros. B, D, E e G poderiam acontecer, porque os m6todos de instAncias e os m6todos
static bloqueiam em diferentes objetos, e nio bloqueiam uns aos outros. (Objetivo 4.3)
16. A resposta E est6 correta porque o thread nio possui o bloqueio do objeto em que chama wai t( ) . Se o
m6todo fosse sincronizado, o c6digo seria executado sem langar uma excegio.
As respostas A, B, C e D estio incorretas porque o c6digo ser6 compilado sem erros. F esti errada porque a
excegXo ser6 langada antes que haja alguma saida. (Objetivo 4.4)
17 . A, C, D, E e F estlo corretas. Poderia parecer que 1aurel e hardy estio brigando para f.azer o outro
s leep O ou wait O mas nio 6 o caso. LJma vez que sleep O 6 um m6todo static, ele afeta o thread
-
atual, que 6 ]aurel (embora o m6todo seja chamado usando-se uma refer6ncia a hardy). Isso 6 enganador,
por6m, perfeitamente v6lido, e o Thread 1aure1 poderi entrar em suspensio sem exceg6es, exibindo A e C
(depois de um atraso de 1 segundo). Enquanto isso, hardy tenta chamar laurel .wait ( )
sincronizou em 1aure1, de modo que chamar laurel .wait ( ) causa imediatamente uma
- mas hardy nio
IllegalThreadstateException, e assim hardy exibe D, E e F. Embora a ordem da saida seja mais ou
menos indeterminada (nio temos como saber se A ser6 exibido antes de D, por exemplo), 6 garrntido que A, C,
D, E e F serio exibidos, em alguma ordem - enteo G est6 incorreta.
B, G e H estio incorretas com base no exposto acima. (Objetivo 4.4)
JAVA 5 429
Respostas dos exercicios
Exercicio 9- l: Criando um thread e colocando-o em suspensio
O c6digo final deve ficar parecido com este:
)
public static void main(String [] args) {
new TheCount ( ) .start ( ) ;
)
)
*
t0
.,
,tiir
Desenvolvimento
rt
Oblerfuos pqru o
certlflcog6o
T Usor Pocoles e lmports
I Deierminor o Comoortomento em
Tempo de ExecuE6o de Closses e
Linhos de Comondo
a/ Exercicios r6pidos
'ir,.,
,i
432 Cooftulo l0: Desenvolvimento
Voc6 deseia manter as suas classes organizadas. Voc6 precisa ter recursos poderosos pafa as suas classes enconffarem umas as
outras. Voc6 quer certificar-se de que, quando estivet procuando por determinada classe, encontari a qlue esti procurando, e
n6o outra que por acaso tenha o mesmo nome. Neste capinrlo, iremos explorar alguns dos recursos avangados dos
comandos java eiavac.Iremos rever o uso de pacotes emJava, e veremos como procurar por classes que residem em
pacotes.
/
7.5 Dado o nome completamente qualifcado de uma classe dbtribuida dentro e oufora dr an arquiao JAR, con$ruir a estrutura de
**riadapara essa classe. Dado am exempk de aidigo e um classpath, detenninar se o classpath permitirtl que o cddigo compile con
l:;::r::t
At6. agora neste livro, n6s provavelmente j5, falamos sobre chamat os comandos j avac e j ava um milhio de vezes;
agora iremos dar uma olhada mais aprofundada neles.
Compilando com -d
Por padrio, o compilador coloca um arquivo . class no mesmo diret6rio que o arquivo-fonte . j ava. Isso funciona
bem para pequenos projetos, mas, quando vocd estiver trabalhando em projetos maiores, ir6 querer manter seus arquivos
. j ava separados dos . class (isso aiuda no controle das vers6es, nos testes, no depuramento...). A opgio -d lhe
permitedizeraocompiladoremquediret6rioeledevericolocaro(s)arquivo(s).cl-assquegerar(d significadestino).
Digamos que voc6 tenha a seguinte estrutura de diret6rios:
myProj ect
I
| --cdllFFA
I I -- MyClass. java
I
| - - classes
I
t--
O sguinte comandqernitidonodiretoriomyProj ect,iticompilarMyClass . j ava ecolocaroarquivolvb€lass . cLass resultanre
nodiretorio classes. (Obsena$o:istoassumequeMlClassniotenhaumainstrugopadcage;filarernos sobrepacoteseminstantes.)
JAVA5 433
ftrrDT^'i 6^i
^/l
Suponha que n6s temos o seguinte arquivo . j ava na seguinte estrufura de diret6rios:
package com. wickedlysmart ;
myProj ect
| - - <arrraa
ll
I I --com
|- -wickedlysmart
| --MyClass.java
| - -ur4DDED
^1 -^^^^
|
ll
| | --com
I
|- -wickedlysmart
De forma um tanto surpreendente, o comando j avac pode, em alguns casos, lhe ajudar ao ciar os diret6rios de que ele
precisa! Suponha que temos o seguinte:
package com. wickedlysmart ;
myProj ect
I
I - -cnrrrna
| | --com
I
|- -wickedlysmart
I
l--uyclass.java
434 Cooitulo l0: Desenvolvimento
| --classes
Neste caso, o compilador criar6 dois diret6rios, chamados com e com/wickedlysmart, nessa ordem, para colocar o
arquivo MyClass . class resultante no dirct6io coneto do pacote (com/wickedlysmart,/), o qual o compilador
cria dentro do diret6rio.. . /classes existente.
A ultima coisa sobre - d que voc6 precisar6 saber para o exame6 que, se o diret6rio de destino que vocd especificar nio existit,
voc6 receber6 um erro de compilagdo. Se, no exemplo anterior, o diret6rio classes NAO existisse, o compilador diria algo como:
java:5: error while writing MyClass: classes/MyClass.class (No
Deixando os detalhes para depois, esse comando pode ser lido como "crie umapropriedade de sistema chamada myProp e
defina o seu valor como myValue. Em seguida, abra o arquivo chamado MyCIass . cl-ass e envie para ele dois
argumentos String cuios valores seiam x e 1".
Vamos dar uma olhada com mais detalhes nas propriedades de sistema e nos argumentos de linha de comando.
import java.util.*;
public class TestProps {
public static void main(StringlJ args) i
Properties P = System.getProperties O ;
p. setProperty ( "myProp" , "myVa]ue" ) ;
p. Iist (System.out) ;
]
Se esse arquivo for compilado e chamado desta forma:
java -DcmdProp=cmdval TestProps
Voc6 receber6 algo como isto:
os.name=Mac OS X
mYProP=myvalug
cmdProp=cmdVal
retic6ncias (. . .) representam diversos outros pares de nome = valor. (O nome e o valor sio, ds vezes, chamados de
""0.;;
chave e propriedade, respectivamente) Duas propriedades norne = valor foram adicionadas is propriedades do sistema:
myProp=myValue foi adicionada atavds do mEtodo setProperty, e cmdProp=cmdVal foi adicionada arraves
da opgio -D na linha de comando.
Ao usar a opgio - D, se o seu valor contiver espagos em branco, entlo todo o valor deve ser colocado entre aspas, desta
forma:
java -DcmdProp="cmdval take 2" TestProps
E caso voc6 nio tenha reparado, quando usa -D, o par nome = valor deve segak imediatamente,rrio sdo permitidos espagos.
O m6todo getProperty ( ) 6 usado para se obter uma fnica propriedade. Pode ser chamado com run s6 argumento
(uma String que represente o norne, ou chave), ou pode ser chamado com dois argumentos (uma String que represente o
nome, ou chave, e um valor String padrio para set usado como a propriedade caso esta ainda nao exista), Em ambos os
casos, getProperty ( ) retotna a propriedade como uma String.
)
compilado e depois chamado da seguinte forma
java CmdArgs x 1
a saida ser6
0 element = x
1 element = 1
Como todos os arrays, o indice de args comega no zero. Os argumentos na linha de comando seguem diretamente o nome
daclasse.Oprimeiroargumento6atribufdoaargs[0],osegundoargumento6atribuidoaargs[1],eassimpor
diante,
Hnalmente, existe alguma flexibilidade na declaragio do m6todo ma i n ( ) usado Eara se iniciar um aplicativoJava- A ordem dos
modificadoresdemainO podeseralteradaumpoucqoaffrydeStringsnnoprecisasechamarargs e,apartirdoJava5,ometodo
pode ser declarado usando-se a sinta:<e dos argumentos vati6veis Todas as seguintes declarag6es s6o vilidas para ma in ():
4. O ptimeiro lugar onde eles procuram 6 nos diret6rios que contem as classes que v6m com oJ2SE.
6. Classpaths significam "caminhos de busca de classes". Eles sdo listas de diret6rios nos quais podem ser encontradas
classes.
A maioria das quutdu do exame relacionadas a caminbos asani conuengdes do Unix. Se uocdfor usadio do l%indowq os seus diretrjrios
serdo declarados usando-se banas inaertidas (\) e o caracter rcparador serd o ponto-e-uirgala 0. M^, nluamente, uod NAO precisani ter
nenbum conhecimento esputJtin sobre the//s para o exa///e.
Uma situagio bastante comum ocorre quando j ava ou j avac reclama que nio consegue encontrar um arquivo de classe,
e mesmo assim vocd pode ver que o arquivo SE ENCONTP-{ no diret6rio ataal! Ao procurar pot arqwvos de classe, os
comandos j ava e j avac nio procuram no diret6rio atual por padrio. Voc6 precisa instrui-los aproctttar ar. A maneira
de drzet a j ava ou j avac para procurar no diret6rio atual 6 adicionando um ponto (.) ao classpath:
-classpath / com/ foo / acct : /com/foo : .
Esse classpath 6 id€ntico ao antettor, EXCETO pelo fato de que o ponto (.) ao final da declangd.o instrui j ava ou j avac
a procurar por arquivos de classe tamb6m no diret6rio atual. (Lembte-se de que estamos falando de arquivos de classes
-
quando voc6 est6 dizendo a j avac qual arquivo . j ava compilat, j avac procura no diret6rio atual por padrio.)
Tamb6m 6 imPortante lembrar que os classpaths determinam a busca da esquerdzpara a diteita. Portanto, em uma situagio
em que existam classes com nomes duplicados localizadas em diferentes diret6rios nos seguintes classpaths, diferentes
resultados irSo oconer:
nio6omesmoque
-classpath . : / foo : f com
Finalmente, o comando j ava lhe permite abreviar - cf as spath como - cp. A documentagdoJzvz 6 inconsistente sobre
se o comando j avac permite ou nio - cp. Na maioria das m6quinas ele permite, mas nao h6 garanias.
^ ^brevi^tnra
Pacotes e a Procura
Quando voc6 comega a colocar classes dentro de pacotes, e depois comega a usar classpaths para encontrar essas classes, as
coisas podem se complicar. Os criadores do exame sabiam disso, e tentaram criar um conjunto especialmente diab6lico de
quest6es relativas a pacotes / classpath especialmente para confundir voc6. Vamos comegar revisando os pacotes. No
seguinte c6digo:
package com.foo;
public class MyClass { public void hj- O { } i
JAVA 5 437
estamos dizendo que MyClass 6 um membro do pacote com. f oo. Isso significa que o nome totalmente qualificado
da classe agota6 com. f oo . MyClass. Depois que uma classe 6 colocada em rrm pa.ote
,^p^rtedo nome totalrnente
qualificado referente ao pacote se torna at6mica - ela nunca pode ser dividida. Vocd nio pode-dividi-la na linha de comandq
e tamb6m nio pode dividi-la em uma insrrugio import.
Agora que j6 demos uma revisada nos pacotes, vejamos como eles funcionam em coniunto com classpaths e linhas de
comando. Primekamente, comegaremos com a id6ia de que, quando voc€ est6 procutando por uma classe usando o seu
nome totalmente qualificado, esse nome se relaciona intimamente com runa estrutura de diret6rios especifica. Por exemplq
em relagdo ao seu diret6rio at:s^J., a classe cujo c6digo-fonte seja
package com.foo;
public class MyClass i public void hi O i ) )
precisa estar locdtzada aqui:
com/ f oo / MyClass . class
Para poder encontrar uma classe em um pacote, vocC precisa ter um diret6rio em seu classpath que tenha a entrada mais i
esquerda do pacote (a"raiz" do pacote) como um subdiret6rio. Esse 6 um conceito importante, entao velamos um outro
exemplo:
import com. wickedlysmart . Utils ;
class TestClass {
void doStuff O {
Utils u = new UtilsO; / / nome simples
u.doX("argt", "arg2" ) i
com.wickedlysmart.Date d =
new com.wickedlysmart.Date O ; // nome completo
d. getMonth ( "Oct" ; ,
)
Neste caso, estamos usando duas classes do pacote com. wickedlysmart. Apenas a titulo de explicagio, n6s
importamosonometotalmentequalificadoparaaclasseUtils,enioofizemosparaaclasseDate.Afnicadtfercnga6
que, por termos listado Ut i l- s em uma instrugio import, nio tivemos de digitar o seu nome totalmente qualificado
denffo da classe. Em ambos os casos, o pacote 6 com. wickedlysmart. Quando chegar a hora de compilar ou executar
TestCl-ass, o classpath ter6 de incluir um diret6rio com os seguintes attibutos:
I Um subdiret6rio chamado com (o chamaremos de diret6rio "ruz do pacote")
438 Cooftulo l0: Desenvolvimento
1. O caminho at6 o diret5do deve ser absoluto; em outras palavras, a partit da ruz (at2|lz do sistema de arquivos, e neo a
do pacote).
/ (raj_zl
|- -dire
|- -aire
| - -airc
-cp dirB:dirB/dirc
Neste exemplo, dirB e dirB/dirC sio caminhos relativos (eles nio comegam com uma barra /). Ambos esses
caminhos relativos s6 tem sentido quando o diret6rio atual 6 dirA. Teste ripido! Se o diret6rio atual for dirA, e voc6
estiver procurando por arquivos de classes, e usar o classpath descrito acima, em quais diret6rios ser6 feita a busca?
/ (raiz)
I
| --dirA
I
|- -dirB
| - -airc
ArquivosfAReaProcura
Depois que voce criou e testou o seu aplicativo, voc6 poder6 dese)ar "empacot6-lo" para facilitar a sua distribuigio e
instalagSo por outas pessoas. Um mecanismo queJava fornece para esse prop6sito 6 o arquivoJAR.JAR significaJava
Archive ('ArquivoJava'). Os arquivosJAR sio usados para comprimir dados (de forma semelhante a arquivos ZIP) e para
arquivar dados.
Digamos que voc6 tenha um aplicativo que use muitas classes diferentes,localtzadas em diversos pacotes diferentes. Eis
uma 6rvore de diret6rios parcial:
faql-
| --UseStuff.java
| --ws
| --mYAPP
|- -uti1s
I
|- -engl-ne
j
- -r.a.. class (pacote myApp. engine,' )
| --minmax.class
Voc€pode cnarumrinico arquivoJARquecontern todos os anquhos de dasses demyApp, emantdrnaestruturade diret6rios de
myApp. Umarcz criado essearquiroJAR, elepode sertransferidoparaoutros diret6rios e outros computadores, e todas as dasses no
alquvoJARpodedo seracessadasatrav6sdedasspathseusadaspor j ava e j avac.Tirdoissopodeacontecersemquevocd jamais
nio precise saber como criar arquivosJAR para o exame, r'amos passar para o diretotio
precise descompactar o arquivoJAR Embora voc€
ws, e em seguida cnat um arquivoJAR charnado My,Jar . j ar:
cd ws
jar -cf MyJar.jar myApp
OcomandoiarcriaumarquivoJARchamadoMyJar.ia4oqu;zliriconterodiret6riomyApp etodaairvorede
subdiret6rios e todos os arquivos de myApp. Voc6 poder6 examinar o conterido do arquivoJAR com o comando seguinte
(isso tamb6m rti.o ca no exame):
j ar -tf Myilar. j ar
que listari o contetido doJAR, mais ou menos desta forma:
META_INF/
META- INF/MANIFEST. MF
440 Copitulo I0: Desenvolvimento
mvApp/
myApp/ .lr5 score
myApp/uti1s/
myApp/ut i 1slDaLes . clas s
myAPp,/ut i1 s/ Convers ions . class
myApp/engine/
myApp/engine/rete . class
myApp/ engine /minmax .c 1as s
Certo, voltemos agora aos assuntos do exame. O processo de se encontrar um arquivoJAR atrav6s do classpath 6
semelhante ao de encontrar um arquivo de pacote em um classpath. A diferenga 6 que, quando voc€ especifica um caminho
para urn arquivo JAR, precisa incluir o nome do arquivo ao final do caminho. Digamos que voc€ queira compilar
UseStuff.javanodiret6riotest,eUseStuff.javapreciseteracessoaumaclassecontidaemmyApp.jar.
Para compilar UseStuf f . j ava, voc6 usaria
cd test
javac -classpath ws/myApp. jar Usestuff . java
Compare o uso do arquivoJAR ao uso de uma classe em um pacote. Se UseStuf f . j ava precisasse usar classes do
diret6rio myApp . utiIs, e a classe n6o estivesse em umJA\ vocd usaria
cd test
javac -classpath r./s Usestuf f . java
Lembre-se de que, ao usar run classpath, o ultimo diret6rio no caminho deve ser o super-diret6rio daruz do pacote. Q'{o
exemplo anterior, myApp 6 o dfuet6rio-raiz do pacote myApp . ut i 1 s.) Repare que myApp pode ser o dret6io raiz
para mais de um pacote (myApp. utils e myApp. engine), e os comandos j ava e j avac podem, dessa forma,
encontrat o que precisarem em diversos pacotes relacionados. Em ouffas palavras, se wg estiver no classpath, e ws for o
super-diret6rio de myApp, entao as classes presentes tanto em myApp . ut i l- s quanto em myApp . eng ine serao
encontradas.
Buando usa uma instragdo import, aocd estd dtclarando apeflas tffir pacote. pzando uu imporE j ava . ut i 1 . * ; aocd ettd
diqendo "use 0 ntne cartrpara todat as classes dnpacote j ava. uti1.'Voc6NAO estti obtendo as classes de java. util . j ar
nem 0rpacntes de java. util .regex! Esrcspacotes sdo totalnente indtpendentet entre $; a tinica coiv qae nrrpatilban i o mesmo
direnirio "raiq", mas ndo sdo o mesnl paclte. A tituk d.e infomagdq uoci n6o pode usar import, j ava . * I na esperanga de importar
niltiplos pacotet - implesnente lembre+e, uma inshvgdo inlprrt xd i capa<dz inportar un rinico pacote.
E possiuel criar aaridueis de ambiente queforne(am //m para classpaths hngu. O cksspath de alguns arquiuos JAk no J2SE
nome-cridigo
pode rcr bastante extenso, defonna qae i dun tipo ao se defnir aru clatrpath. Se uoei uir algo como
comum ilsar ilm nome-aidigo
JAVA_HOME oz $JAVA_HOME en ama questdo do exame, isn signifim @enas "aquelaparte do classpath absoluto atd os direhiios
q/'/e eitamos especifcando explicitamente". Voei pode assumir que a ,IAVA_HOME literal ten un signifcado, e esti
@ontando para o
classpathparcial que uocd estd uendo.
JAVA 5 44I
Observag6o: No Capinrlo 1, n6s abordamos a maior parte do que estd definido neste obietq mas deixamos as importag6es
est6ticas para este capinrlo.
lmportag6es Est6ticas
N6s vimos usando instug6es import ao longo de todo o livro. No fim das contas, o finico valor que as instrug6es
import t€m 6 que elas economizam dtgtagdo e podem tarr' r o seu c6digo mais f6cllde ler. EmJava 5, a instrugio
imporf foi aprimoradapan fotnecer capacidades ainda maiores de economia de digitagio... Emtora algumas pessoas
argumentem que isso prejudicou a legibilidade. Esse novo recurso 6 conhecido como importagio estitica. As importag5es
est6ticaspodemserusadasquandovoc6desejausarosmembrosstatic deumaclasse.ffo.6podeusaresserecursoem
classes da API e nas suas pr6prias.) Eis um exemplo do tipo "antes e depois":
l
i
Depois das importag6es est6ticas:
2747 483647
Vamos ver o que est6 acontecendo no c6digo que usa o recurso das importag6es est6ticas:
1. Embora o recurso seja normalmente chamado de 'lmportagio estitica", a sintaxe DE\IE ser import static
segu.ida pelo nome totalmente qualificado do membro stat i c que voc6 deseja importar, ou enteo um coringa. Neste
caso, estamos fazendo uma importagio estitica no obieto out da classe System.
2. Nestecaso,poderiamosquererusatdiversosmembrosstaticdaclassejava.lang.Integer.EstainstruEio
import stat ic usa o coringa para dtzer"eu quero fazer importagio est6tica de TODOS os membros stat i c
desta classe".
3. Agora finalmente estamos vendo o beneficio do recurso! Ndo tivemos de digitar System in System.out.prindn! Uau!
Em segundo lugar, nio tivemos de digitat o Int.eger em Integer. MAX_VALUE. Assim, nessa linha de c6digo,
pudemos usar um atilho para um m6todo static Epanuma constante.
4. FinaLmente, fazemos mais um atalho, desta vez p^r um m6todo da classe Integer.
N6s fomos um pouco sarc6sticos sobre esse recurso, mas nio somos os rinicos. Ainda nio estamos convencidos de que a
economia de muito pouca digitagd.o valha a pena diante da possibilidade de se tofnaf o c6digo um pouco mais dificil de ler.
Entretanto, esse recurso foi pedido por muitos desenvolvedores, de modo que acabou sendo adicionado i linguagem.
442 Cooitulo l0: Desenvolvimento
N6s comegamos explorando o comando j avac com mais profundidade. A opgio - d lhe permite colocar arquivos de
classes gerados pela compilagio em qualquer diret6rio que quiser. A op96o - d lhe permite especificat o destho dos arquivos
de classes rec6m-criados.
Em segrida, falamos sobre algumas das opg6es disponiveis atrav6s do iniciador de aplicativos j ava. Discutimos a otdem
dos argumentos que j ava plde usar, iniluindo [opq6esJ class largument.os] . N6s aprendemos como
consultar e afi^liz rptopriedades de sistema no c6digo e na linha de comando, usando a opgio -D.
O t6pico seguinte referiu-se ao tratamento dos argumentos de linha de comando. Os principais conceitos sio que esses
colocados em um arcay deStrings, e que o primeiro argumento vai para o elemento 0 do arr y, o segundo
".go-..rtoJrio
argumento vai para o elemento 1 e assim por diante.
Passamos para o importante t6pico referente a como j ava e j avac Procuram por outros arquivos de classes quando
precisam deler, .oho ambos bs comandos usam o mesmo algoritmo para encontrar essas classes. Existem locais de busca
"
pr6-definidos pela Sun, e outros locais de busca, chamados classpaths, que sio definidos pelo usu6rio. A sintaxe para
ilasspaths no Uni* 6 diferente da sintaxe para classpaths do Windows, e o exame tende a usat a sintaxe do Unix'
O t6pico sobre pacotes veio em seguida. Lembre-se de que, depois que vocd colocar uma classe em um pacote, o seu nome
se torna at6mico - em outras palavras, n6o pode ser dividido. Existe um relacionamento intimo entre o nome de pacote
totaknente qualificado de uma classe e a estrutura de diret6rios na qual a classe reside.
Os arquivosJAR foram discutidos em seguida. Os arquivosJAR sio usados para comprimir e arquivar dados. Eles podem
ser usados para arquivar estruturas arb6reas de diret6rios inteiras em um tinico arquivoJAR. Os arquivosJARpodem ser
vasculhados pot j ava e pot j avac.
N6s tetminamos o capitulo discutindo um recurso novo deJava 5, as importag6es est6ticas. Esse 6 um recurso aPenas
deconveni€ncia,quereduzanecessidadedesedigitarnomeslongospa:amernbtosstatic dasclassesquevoc6usar
em seus Pfogfamas.
Exercicios Raipidos
Eis aqui os pontos principais deste capinrlo.
El Em um classpath , uma vez encontrada uma classe, a busca 6 interrompida, de modo que a ordem dos locais de
busca 6 importante.
J Parafazer testes, voc6 pode colocar arquivosJAR em - . . / jre/l-ib/ ext,que fica em algum lugar dento da drvore
de diret6riosJava na sua mdquina.
Teste Individual
class Needy3 {
public static void main(Srringll args) {
xcom.Useful u = new xcom.UsefulO; // Iin}ra 2
C. Asafda66.
D. Acompilagtrofdha.
E. O c6digo compila se a linha 1 fot removida.
E O c6digo compila sealinha2formodificadapara
Useful u = new UsefulO;
I -- .*
| -- Pet.class
I
| -- 'hv
| -- oos.class
E o seguinte arquivo-fonte:
^1 ^-^ |
urdss ^"--^1 ^-^
rYryvrdsE 1
Robot r;
Dats
^.
Dog d;
)
Qual(is) instrugio(6es) deve(m) ser adiciona(s) para que o arquivo-fonte possa compilar? (1\4arque todas as corretas)
A. package org,.
B. j-mport or9.* ;
C. package or9.*;
D. package org.ex;
E. import org. ex. * ,.
E package org.ex.why;
G. package org. ex.why.Dog,.
3. Dado:
1,. // insira o c6digo aqui
2. class StatTest {
3. public static void main(String[] args) {
4. System.out.println(Integer.I4AX_VALUE) ;
5. l
-1
b. J
4. Dado:
import static java. lang. System. * ;
JAVA 5 445
class _ {
static public void main(String. . . _A_V_) {
Cf rin^ < N/.
vut^rr: Y --
g += _A_V_[xl;
out.println($);
)
)
E a linha de comando:
java_-A
Qual 6 o resultado?
A- -A
B. A.
C. -1.
D. -A.
E. _-A.
E Acompilagdofalha.
G. E langada uma excegio no tempo de execugio.
xcom
| --A.class
| --8. java
E estes dois arquivos:
package xcom;
publicclassA{ }
package xcom;
public class B extends A { }
Qual opglo permite que B . j ava compile? $4arque todas as corretas)
,{. Definir o diret6do atual como xcom e depois chamat
i arr: n Il 'i elra
import xcom,Stuff.*;
import j ava. 1ang. System. out ;
cl-ass User {
new Userll.goO;
i
Qual 6 o resultado?
a* 25
B. 30
c. 36
D. Acompilagdofalha.
E E langada uma exceg6o no tempo de execugio.
package xcom;
public class B extends A {public void doBO { System.out.println("B.doB"); } }
import xcom.B;
class TestXcom {
public static void main(Stringll args) {
g b = new BO; b.doBO; b.goO;
JAVA 5 447
l
Qual opgdq se inserida em / / insira o c6digo aqui, permitir6 que todos os tr€s arquivos compilem? @larque
todas as coretas)
9. Dado:
class TestProps {
public static void main(Stringtl args) {
String s = System.getProperty("aaa","bbb" )i
)
)
E a chamada de linha de comando:
java -Daaa=ccc TestProps
O que 6 sempre verdadeiro? (trIarque todas as correas)
.d O valot da propriedade aaa 6 aaa .
/foo/bar/baz
E esta linha de comando fot chamada a parat de / t oo
j avac - classpath / f oo / bar / baz /bLng : / f oo /bar MyClass, j ava
Qual versio seri usada por j avac?
A. /foo/MyClass.java
B. / too/barlMyC1ass. java
C. / foo /bar /baz /MycLass. java
D. / foo/bar /baz/bing/MyClass . j ava
E O resultado nlo 6 previsivel.
D. Para especificar o uso de um arquivo JAR na linha de comando, o camiflho e o nome do arquivo JAR /er,rrz ser incluidos.
E. Quando uma parte de uma 6rvore de diret6rios que inclui subdiret6rios com arquivos dentro 6 colocada em um arquivo
JAR, todos os arquivos sio salvos no JAR, mas a estrutura dos subdiret6rios 6 perdida.
import pkg.*;
c-Lass useKltr t
l^ ELduru -yoid main(String[] args)
vq!f,ru
-,,L1 ^r^r:^ {
String s = new Kit O .gluelt (args [1] , args [2J ) ;
System. out.println (s) ;
)
t--
| --useK].f'.cIass
I
com
l--Kr-t.uar.lar
Se oditet6rio atual for test, e o arquivo pkg/Kit . cl-ass estiver em Kit,far. j ar, qual linha de comando
produzirS,a saida bc? O4arque todas as corretas)
A. java UseKit b c
B. java UseKit a b c
C. java -cl-asspath com UseKit b c
D. java -classpath com:. UseKit b c
E java -classpat,h com/Kit,Jar. jar UseKit b c
F. java -classpaLh com/KitJar.jar UseKit a b c
G. java -classpath com/Kit,far.jar:. UseKit b c
FI. java -classpath com,/KitJar.jar:. UseKit a b c
A, C, D e G est6o incotretas com base no exposto acima. Al6m disso, C e G usam sintaxe incorreta. (Obietivo 7.1)
3. C e E usam sintaxe correta para importag6es estedcas. A linha 4 nlo est6 usando importag6es esteticas, de modo que o
c6digo tamb6m compilari sem nenhuma das importag6es.
6. D est6 corteta. Para importar membros estAticos, a instrugZo import deve comegar com: import static.
8. Best6 correta. O modificador de acesso publ ic 6 o 6nico que permite que c6digo de fora de um pacote acesse
m6todos em tun pacote - independentemente da heranga.
9. C est6 cotteta. O valor de aaa 6 definido na linha de comando. Se aaa nio tivesse nenhum valor ouando
get Property foi chamado, entio aaztena sido definido como bbb.
A, B, D, E e F est6o incorretas com base no exposto acima. (Obietivo 7.2)
10. D est6 cotret^. Um - clas spath incluido com uma chamada a j avac substitui o classpath do sistema. Quando
j avac esti usando um classpath, ele 16 o classpath da esquerda para a direita e usa a primeira corresponddncia que
encontrat.
A,C,EeGestioincorretaspeiosimplesfatodequeargsI J comegaporzero.B,DeFestaoincorretasporquejava
precisa de um classpath que especifique dois diret6rios, um para o arquivo da classe (o diret6rio . ) e um para o arquivo
JAR (o diret6rio com). Lembre-se de que para encontrar um arquivoJAR, o classpath deve incluir o nome do arquivo
JAR, nio apenas o seu diret6rio (Objetivo 7.5)
450 Copftulo l0: Desenvolvimento
i
,it!,i
Ap6ndice A
Sobre os stqulvos
dlsponlvels poro
donwlosd
.
.. t :":
ij:
"
452 Ap6ndice A
Os arquivos disponiveis para donwload, no site wwrv.altabooks.com.br, vdm com o MasterExam (todos os arquivos estZo
em ingl6s). O software 6 ficil de instalar em qualquer computadorWindows 98/NT/2000, e para que os recursos do
MasterExam possam ser acessados ele precisa ser instalado. Para registrar-se para um segundo MasterExam, basta clicar no
link Bonus Material da pigrna principal e seguir as instrug6es para acessar o registro online.
Requisitos do sistema
O software requer o \X/indows 98 ou superior, o Internet Explorer 5.0 ou superior e 20 MB de espago no disco rigdo pan a
instalagio completa.
MasterExam
O MasterExam the fornecer6 uma simulag6o do exame real. A quantidade e os tipos de perguntas al6m do tempo
permitido foram definidos para ser uma representagio precisa do ambiente do exarne. Voc€ ter6 a opgdo de fazer um exame
com o livto aberto, incluindo dicas, refer€ncias e respostas; um exame com o livro fechado; ou a simulaqio MasterExam
com tempo definido,
Quando voc6 iniciar o MasterExame, um rel6gio.ligrtal apatecer|no canto superiot esquerdo da sua tela. O rel6gio
contjnuat6,acontagem tegressivaat€zero a menos que voc6 selecione terminato exame antes que o tempo expire. Pata se
registar a fim de teceber outro MasterExam, simplesmente clique no link Bonus MateialdapAgjna principal e siga as
instrugdes para o rcg1svo on-l.ine graruiro.
Aiuda
Um atquivo de ajuda 6 fornecido por meio do botio Help que se encontra no canto inferior esquerdo da p6gina principal.
Os recutsos de ajuda individual tamb6m est6o disponfveis no MasterExam e no treinamento on-line da LearnKey.
Removendo instalag6es
O MasterExam ser6 instalado em sua unidade de disco rigrdo. A fim de obtet melhores resultados no que diz respeito i
remogio de programas, use as opg6es Iniciar I Programas I LearnKey I Desinstalar para remover o MasterExam.
Se quiser remover o Real Player, use o icone Adicionar/Remover Programas de seu painel de controle. Voc€ tamb6m pode
remover os pfogramas de treinamento da LearnKey nesse local.
Suporte t6cnico
Para enviar perguntas relacionadas aocontefdo t6cnico do livro elet6nico ou do MasterBxam, visite o site
www.osborne.com ou mande uma mensagem (em ingl€s) de correio eletr6nico para customer.sewice@macgraw-hill.com.
Clientes fora dos Estados Unidos, devem enviar a mensagem para international-cs@mcgraw-hill.com.