Você está na página 1de 480

Elogios ao Guia de estudos para programador e desenuoluedor em Jaua 2 certif cado pela S an@

"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

alunos que beneficiaram


se terem assistido
de a suas aulas" . i
,1

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

- Thomas Bende6 Presidente, Gold Hi// Sofnaare Desing, Inc'

"por habilidade em expressar claramente conceitos complexos aos que assistem


sua a seus treinamentos' todos os alunos
cons€guem se tornar especialistas no que Ben tem a ensinar".
- DauidNdgq Diretor Geral, Ndge Astociatet

"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

literdmente-grav"ra- ot.o.t..itos principais na minha cabega."


-Bhsshen P. Madan (Kansas, Estadot Uildos)

(
"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!"

-lon W. Knsting (Smatoga, Califomia, Estadot Unidos)

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

-Vad Fogel (Onlaia, Canadi.l


Ceftificagdo Sun@ para
Programador fAVA 5
Guia de Estudo
(tuame 310-055)

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.

Rua Viriva Claudio,29l - Jacaft


Rio de Janeiro - RJ. CEP: 20970-031
TeI: 21 3278-8069/ Fax: 21 3277-1253
ESeitrrRl*|E
wu{w.osborne.Eorn
ww.altabooks.com.br
e-mail: altabooks@altabooks.com.br
JAVA 5V

ParaaComtrnida&Java
Sum6rio
capirulo | - DEclAnag6es E coNTRoLE DE AcEsSo.................................... I

ldentificodores e Polovros-chove........... ......... 2

Encontrondo Outros Closses ..................'...... 2

Objetivo para a Certificagio............ ............3


ldentificadores e JavaBeans (Objetivos 1.3 e 1.4) ....--.-.-.. 3

ldentificadores Legais ................... 3

Objetivo para a Certificagio.............. ..........6


Declarar Classes (Objetivo l. I do Exame) .....-.'............... 6

a
Outros Modificodores de Closses (N6o-re{erentes o Acesso)
Exercicio l- | Criando uma Superclasse Abstrata e uma Subclasse Concreta .....' | 0

Objetivo paraaCertificag6o............ .......... ll


Declarar lnterfaces (Objetivos l. I e 1.2 do Exame) ............. .'........ I I

Objetivo para a Certifi cagio ............ t4


Declarar Membros de Classes (Objetivos 1.3 e 1.4) ............ ........... 14

Membros Protecl eDefoult ....... 19


Deiolhes de Protect ................. n
Detolhes de Deioult....
Vori6veis Locois e Modificodores de Acesso ..................... 23

Argumentos Finol ...........


M6todos Abs
M6todos Synchronized ..'.......... 27

M6iodos com Listos de Argumentos Vori6veis (vor-orgs) .......-...-.......--.. 27

Declorondo Primitivos e Iniervolos de Primitivos


Refer6ncio
DeclorondoVori6veis de ............. 30
Voridveis de Instdncios ...........' 30
Vori6veis Locois (Automotic/Stock/Method) ......... ........-.... 3l
Declorog6es de Arroys ..........'.. 33
JAVA 5 VII
Voridveis e M6todos Stotic.........'.. ................ 35

Declorondo Construtores, M6todos eVoridveis em um enum .......... ...... 37

CAPITULO 2' ORIENTA€AO A OBf ETOS...................................o.......................... 49


Objetivo para a certificagSo ............. .........50
Beneffcios do encapsulamento (Objetivo 5. I do exame) ................ 50

Objetivo para a Certificagio


Heranga, E-Um, Tem-Um (Obletivo 5.5 do Exame) .....52
Relacionamentos E-Uy e TEM-UM ............55

Objetivo para a Certifica9io.............. ........58


Polimorfismo (Obietivo 5.2 do Exame) .......58

Objetivo para a Certi{ica9io............ ..........60


Subscrevendo / Sobrecarregando (Obfetivos 1.5 e 5.4 do Exame) ................... 60

Chomondo o versOo do superclosse de um m6todo subscrito ............... 63


Exemplos de subscrilos de m6iodo v6lidos e ndo-v6lidos ................ ..... U

Sobrecorgos v6lidos ................ &


Chomqndo m6todos sobrecorregodos ............. ................ 65
Polimorfismo em m6todos sobrecorreqodo e subscrilo ....... &
Objetivo para a Certificagio ............ ,.............68
Conversio de Vari6veis de Refer6ncia (Objetivo 5.2 do Exame) ....68

Objetivo para a certificagio ............. .........7 |


lmplementando uma Interface (Obietivo 1.2 do exame) ................71

Objetivo para a certificag6o ............. 74


Tipos de retorno v5lidos (obfetivo 1.5 do exame) ........74

Tipos de retorno de m6todos sobrecorregodos............. ..... 74


A Subscrig6o e os Tipos de Retorno, e Retornos Covorionies ................. 75

Objetivo para a certificag6o ............. .........77


Construtores e instanciaEio (Objetivos I .6 e 5.4 do exame) .........77
Aspeclos bdsicos do construtor .................... 77
Codeiqdeconslrulores................. ..............77
Regros dos construtores .............. ................ 78
ldentifcando se um constru
Como voc6 pode ter o certezo de que um conslrutor podr6o ser6 criodo? ................ 79
O que oconlecer6 se o conslruiuor do superclosse tiver orgumentos?........... ..........80
vlll
Objetivo para a Certificagio
Vori6veis e m6todos stotic .......... ................. 85
...........
Acessondo vori6veis e m6todos stotic ................... 85

Objetivo para a Certificagio............................. ..........88


Acoplamento e Coesao (Objetivo 5. I do Exame) ........ 88

CAPiTuLo 3 - ATR|BU1C6ES.........r....r.....,..-... ......r.o.....o........................ f 0f


J

Pilha e Heap - Uma Revisio .... 102

Objetivo para a certificagio ............. ........ 103


Literais, Atribuig6es e Vari6veis (Objetivos I .3 e 7.6 do Exame) ... 103

Literois de ponto flutuonte .......1U

Literois
Volores literois poro strings......... ................ 05

Convers6o detipos primitivos .................... ]07

AtribuiE6es de vori6veis de refer6nciq .......... I l0

Usando umavari6vel ou elemento de array que nlo tenha sido

Vori6veis de instdncio de tipo primiiivo e de obieto .......... I 13


Voridveis de instdncio primitivos ................. 1.l3
Vori6veis de insi6ncio de refer6ncio o obietos ..........-....... I 13
Vori6veis de instdncio de orroy ................... I 14
Tipos primitivos e obielos locois (de pilho, outom6ticos) ...................... I l5

Refer6ncios de Obietos 1ocois.......... ........... I 16

Airibuindo umo vori6vel de refer6ncio o ouiro .................117


Objetivo para a Certificag6o............ ........ | | I
Passando varieveis para m6todos (Objetivo 7.3 do exame) .......... I l8

AlinguagemJavausaasemnnticadepassagemporvalor? ............ l19

Objetivo para a certificagio ...122


DedaraEio, construgao e inicializaEio de arrays (objetivo 1.3 do exame) ..... |-22

Declorondo um orroy de tipos primitivos .....122

Construindo orroys unidimensionois ...........123


Construindo orroys multidimensionqis .........124
JAVA 5 IX
lniciolizondo elementos em um loop ........... ...................126
Declorondo, construindo e inciolizondo em umo linho .......... .............126
Construindo e iniciolizondo um orrov on6nimo ...........127
AtribuiEoes v6lidos poro os elemenlos do orroy . .............128
Arroys de tipos primitivos............... ............ l2B
Arroys de referGncio o obietos ....................129
.|30
AtribuiE6es de vori6veis de refer6ncio de orroys unidimensionois .............. ...............
Atribuigoes de vori6veis de re{er6ncio de orroys multidimensionois ............ ..............
'130

Blocos de Iniciolizo96o ..............

Objetivo para a certificagio ............. t33


Usando classes wrapper (Objetivo 3. I do exame) 133

Osconstrutoreswrqpper .........133
Os m6todos volueOf0 ... ... ............. ]34
Usando os utilitidos de conversio das classes wrapper .............. | 34

.l35
porseXrx$ e volueOffl . .... .. ............

to/rxxStringfl (bose bindrio, hexodecimole octol) .............136

Boxing, ::, e equolsfl .......... 137


Onde Pode ser Usodo o Boxing .................. l3B
Objetivo para a Certifica96o............ ........ | 39
Sobrecarregando (Objetivos 1.5 e 5.4 do Exame) ...... 139
Sobrecorregondo do Moneiro Di{icil- Correspond6ncio de M6todos r39
Sobrecorgo com Boxing e Vor-orgs r40
Ampliondo Vori6veis de Refer6ncio 141
Sobrecorgo no CombinoE6o de AmplioE6o com Boxing 141
Sobrecorgo em CombinoE6o com Vor-orgs 142

Objetivo para a certificagio


Coleta de lixo (Objetivo 7.4 do exame) .... 143
Vis6o total do gerenciamento da mem6ria e da coleta de lixo ............... ............ 143

Quondo o coletorde lixo 6 execulodo? ............ ..............144


Como o coletor de lixo funciono? ..144
Escrevendo um c6digo que torne os objetos explicitamente qualificados

Anulondo umo refer6ncio ............... ...........144


Reotribuindo umo voridvel de referGncio ......145
lsolondo umo refer6ncio ............... .............146
ForEondo o coleto de lixo .......146
Fozendo umo limpezo ontes do coleto do lixo - o m6todo finolize( ) .. ... ....... l4B
Cuidodos relocionodos com finolizefl ......... . . .......... 148

Objetivo para a certificageo ..........


Operadores Java (Objetivo 7.6 do exame) .................. 162
Operodores deAtribuiE6o ......162
Operodores de AtribuigdoCompostos .........162
x
lguoldode de tipos pdmilivos ...........'..'..-..'164
lguoldode de vori6veis de referGncio ..."...... 165
lguoldode poro Enums r65
Operodorde comporog6o inslonceo{ .......... 166
Erro de CompiloE6o de instqnceof ................. ...............-167

O Operodor Resto (%) .'......... 168


Operodor de concotenoE6o de strings
Acr6scimo edecr6scimo ......... ]70
Ooerodor condicionol. ..........'171
Operodores L6gicos ...............172
Operodores Bitwise (N6o Coem no Exome!) ...................172
OperodoresL6gicosdeAbrevioE6o................ .....'........'172
Operodores l6gicos (que n6o s6o de obrevioE6o) ...........174
Operodores L6gicos ^ e !........... ..............174
Resumo para a certificagio

cApiTULo 5 - coNTRoLE DE FLUxo, ExcEg6es E AssERTlvAs...o............. 183


Objetivo para a ceftificagio ....... t84
Escrevendo o c6digo usando instruE6es if e switch
(Objetivo 2. I do exame) .......... 184

Express6es v6lidos poro instruE6es if ............ .................. 186

Breokeopossogemcompletoemblocosswitch......... .....190
defoult
A instruE6o cose .........192
Exercicio 5- | Criando

Objetivo para a certificagio ... 193


Loops e lteradores (Objetivo 2.2 do exame) .............. 193

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

Objetivo para a certificagio


Manipulando exce96es (objetivos 2.4 e 2.5 do exame) ................. 20 |

Manipulando uma hierarquia inteira de classes de exceg6es .........208


JAVA 5 XI

Objetivo para a Certifica9io.............. ......214


Erros e ExceE6es Comuns (Objetivo 2.6 do Exame) ...................214
De Onde V6m os ExceE6es .....214
JVM
Exceg6es LonEodos pelo .....................214
ExceE6es LonEodos Progromolicomente ......... .................215
Um Resumo dos ExceE6es e Erros poro o Exome .............215
Objetivo para a certificagio ...216
Ti'abalhando com o mecanismo de assertivas
(Objetivo 2.3 do exame) ..........216

Regros dos express6es de ossertivos ............... ................218

ldentificodorx Polovro-Chove ................ ....219


Usqndo o Versdo 5 de lovo e iovoc ............219
Compilondo um C6digo Alenio ds Assertivos 219

Aiivondo ossertivos no tempo de execuc6o ...220


Desotivondo ossertivos no tempo de execuEdo ................220
AtivoE6o e desotivoE6o seletivo ..................22|.

N6o use ossertivos ooro volidor orqumentos de um m6todo o0blico. ..................222


Use os ossertivos poro volidor orgumentos de um m6todo privodo. ......222
N6o use ossertivos poro volidor orgumenios de linho de comondo .......222
N6o use ossertivos, mesmo em m6iodos p0blicos, poro procuror instrug6es cose que sobe que nunco ocorre16o ..222
N6o use express6es ossedivos que possom cqusor efeitos coloteroisl ....223

CAPITULO 6 - STRINGS, E/S, FORMATACAO E PARS|NG.................................237


Objetivo para a ceftificagSo ............. .......238
String, StringBuilder e StringBuffer (Objetivo 3. I do exame) ......... 238

Strings s6o obietosinolter6veis ...................238


Fatos importantes relacionados aos objetos String e a mem6ria .......................24 |

Criondo novos slrings ............242


M6todos importon'les do closse String......... ..............242

StringBufferx StringBuilder ......244


Usondo StringBuffereStringBuilder .............245
StringBuilder
M6todos importantes das classes StringBuffer e ......245
Objetivo para a Certificagio.. 246
NavegaEio de Arquivos e E/S (Objetivo 3.2 do Exame) ...............246
Criondo Arquivos com o Closse File ............. .................247
Usondo FileWriter e FileReoder ..................249
Combinondo Closses de E/S ......................250
Trobolhondo com Arquivos e Direi6rios .......252

Objetivo para a Certifica9io.............. ......254


SerializagSo (Objetivo 3.3 do Exame) ........254
xil
ObiectlnputStreom
Trobolhondo com ObiectOutputStreom e ................255
Gr6ficos de Obietos ...............256
reodObieci
Usondo wrileObiect e ............... 258
Seriolizog6o
Como o HeronEo Afeto o .........260
................
A SeriolizoEoo n6o 6 poro Est6ticos ...............262
Objetivo para a Certificasio..............
Datas, Nrimeros e Moeda (Objetivo 3.4 do Exame) ...263
Trabalhando
Orquestrondo Closses Relocionodos o Dotos e Nimeros .... ...............263

A Closse Colendor .................265


A Closse DoleFormol .............266

A Closse NumberFormot ............... ............270


Objetivo para a Certificagio............ ........27 |
Parsing, Tokenizag6 e Formatagao (Objective 3.5 do Exame) .......271

Buscqs Usondo Melocorocreres ......................., ,,,,.........'273


Buscos Usondo Quqnti{icooores ................
O Ponto Pr6-definido .............275
Quonti{icodores Gononciosos.............. ......275
Colidem
Quondo Metocorocleres e Strings .....................276
Padr6es...
Locaf izando Dados atrav6s da Correspond6ncia de ....277

Tokens e Delimitodores ................ ..............279


Tokenizondo com String.splitfl ......... ......279
Tokenizondo com Sconner ..............280

cApiTuLo7-GENfRlcosEcoNfuNToso.........o...o.ooo......o.o...................oo........zgs
Objetivo para a certificagio ............. .......296
Subscrevendo hashCode( ) e equals( ) (objetivo 6.2 do exame) ...296

O que significor6 o n6o subscriEdo de equolsfl ... ....... . ...............297


lmplemenlondo um m6fodo equols( ) .. ...............298
O conlroto de equols( ) ................. ............300

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

Interfoces e closses chove do estruturo de coniuntos ........304

A Interfoce Se1.............. .........307

A Interfoce Queue........ ..........308


JAVA 5 XIII
Objetivo para a Ceftificag6 o .................. 309
Usando a Estrutura dos Conjuntos (Objetivo 6.5 do Exame) ....... 309

Clossificondo Coleg6es ....... .. . 3l O


A Interfoce Comporoble ................... 312
Clossificondo com Comporotor .............. ....3j3
ClossificondocomoClosseArroys........ .....315
Fozendo Buscos em Arroys e em Coniuntos .............. ......315
ConverJendo Arroys em Listos e de Voltq em Arroys ..........3j7

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

cAPiTULo 8 - ctAssEs 1NTERNAS...................................................................... 36 |


Objetivo para a certificagiio ............. .......362
Classes

lnslonciondo umo closse interno ................3U


Referenciando a instincia interna ou externa de dentro da classe interna ...........365
Objetivo para a certificagio ...366
Classes internas locais de m6todo .............366
O que um objeto interno local de m6todo pode ou n?rofazer ..................... 367
Objetivo Para a ceftificagao ............. ................ 368
Classes internas an6nimas ........369

Objetivo para a certificagio ...373


Classes est6ticas aninhadas ....... 323
xtv
CAPiTULO 9 - THREADS............o..o.........................................................................383
Objetivo para a certificagSo ............. .......384
Definindo, instanciando e iniciando threads
exame)
(Obletivo 4. I do .......... 384

Criando um thread ............... 385

Objetivo para a Certificagio............ ........393


Estados e Transig6es de Threads (Objetivo 4.2 do Exame) .......... 393

Criando

Objetivo para a certificagio ............. .398


Sincronizando o c6digo (Objetivo 4.3 do exame) ....... 398

O oue ocontecer6 se um threod n6o puder obter o bloqueio? """"'405


Ent6o, Quondo Eu Preciso Sincronizor? ..."' 405
Closses Seguros em ReloEdo o Threods """' 407

Objetivo para a certificagio .............


lnteragio entre os threads (Objetivo 4.4 do exame) "409
Usando notifyAll( ) quando houver a possibilidade de muitos threads estarem esperando ...'.4 |3

Usondo woit( ) em um Loop " " 414

Exercicio 9-l: Criondo um threod e coloconoo-o em suspensfio..........'... """""""'428


Exercicio 9-2: Sincronizondo um bloco de c6digo ..""""' 429

cApiTULO l0 - DESENVOLVIMENTO ........o.............o..o...............o..........oo............ 43 |

Objetivos para a Certificag5o............ ......432


Usando os comandos iavac e java (Obietivo 7.2 do Exame) ...-..." 432

Comoilondo com -o ..............432

Usondo os Propriedodes de Sistemo """""' 434


Lidondo com Argumentos de Linho de Comondo """""" 435

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

Usondo .../ye/lib/ext com Arquivos JAR........... .............440


Objetivo para a Certifi cagio .............. ..............441
Usando lmportaE6es Est6ticas (Objetivo 7.1 do Exame) ..............441

APENDICE A..o..o.......o............................................................................................... 45 |
Requisitos do sistema ...............452
lnstalando e executando o MasterExam ....452

Suporte t6cnico ......452


xvl
Sobre os Colaboradores
Sobre os Autores
exame SCJP paralaval. Sierra trabalhou como instrutora sAnior da Sun e' em
Kathy Sierra foi desenvolvedora-lider do
1997, fundou oJavaranch.com, a maiorcomunidade sobreJava nalnternet. Os seus livros recordistasdevendassobreJava
jireceberam v6rios prAmios da revista Sofrware Development Magazine, e ela 6 tamb6m membrofundador do programa
Java Champions da Sun.
Bert Bates tem sido desenvolvedor-lider de virios exames de certificagio da Sun, incluindo o SCJP paraJava 5. Ele tamb6m
6 moderador de um f6rum emJavaranch.com, e tem desenvolvido softwares por mais de 20 anos. Bert 6 co-autorde
diversos livros recordistas de vindas sobreJava, e 6 membrofundador do programaJava Champions da Sun.

Sobre a Equipe de Revisio T6cnica


(Ele tem mais paci6ncia
Johannes deJong tem sido o lider das nossas equipes de revislo t6cnica por muito, muito tempo.
do que qualquer pessoa qrre conhecemos.) Neste livro, ele liderou a maior equipe que j6 formamos. Nossos sinceros
t"goitttes volunt6rioi, que foram inteligentes, trabalhadores, pacientes e muito, muito detdhistas!
"gmd..i-entot "or
Rob Ross, Nicholas Cheung, Jane Griscti, Ilja Preuss, Vincent Brabant, Kudret Serin, Bill Seipel Jing Yr' GinuJacob
George, Radiy4 LuLrrr-MazaAnshu Mishia, Anandhi Navaneethakrishnan, Didier Varon, Mary McCartney, Harsha
Pherwani, Abhishek Misra e Suman Das.

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

Os Astros da Revisio T6cnica


Nio sabemos quem trabalhou mais, mas podemos contar as edig6es feitas por cada revisor (e o fizemos!) - entio, na ordem
de mais edig6es feitas, n6s orgulhosamente apresentamos os nossos superastros.

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.

O que esse livro n6o 6


Neste livro voc6 nio encontrar6 um guia para iniciantes no aprendizado de Java. Todas as suas piginas sio dedicadas
somente a ajud6-lo a passar nos exames. Se voc6 for iniciante emJava, sugerimos que demore algum ternpo aprendendo os
aspectos b6sicos e nXo passe para esse livro at6 que saiba como escrever, compilar e executar programas Java simples. No
entanto, nio pressupomos nenhum nivel de conhecimento anterior dos t6picos individuais abordados. Em outras
palavras, em todos os t6picos discutidos (direcionados exclusivamente pelos objetivos reais do exame), paftimos da
suposigio de que voc6 ainda nio os conhece. Portanto, o consideramos iniciante nos t6picos indivi duais, mas ndo na
linguagemJava.

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.

Introdugio ao material do livro


O exameparaProgramadorJavaCertificado pelaSun (SCJP, Sun CertifiedJavaProgrammer) 6consideradoumdos mais
dificeis (se nXo for a mais dificil) do segmento de inform6tica e podemos dizer a panir de nossa experiAncia que boa parte
dos candidatos fazem o teste sem o preparo necess6rio. E estamos falando de pessoas que ji conhecemJava muito bem e
que ji a usam em programagio h6 anos! Como programadores, ten&mos a aprender somente o que precisamos para
concluir nosso projeto atual, dados os prazos impraticiveis, geralmente associados. Mas esse exame tentarA avaliar seu
conhecimento totd da linguagemJava e nio apenasas partes com as quais voc6 se familiarizou em seu trabalho.

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.

Quem se importa com certificag6es?


Os empregadores se impoftam. Os recrutadores de executivos. Os programadores. O exame de programador da Strn tem
sido considerado a cenificaglo que mais se popularizou no universo da inform6tica e a quantidade de candidatos que o faz
continua a crescer a cada ano. Passar nesse exame provar6 tr& itens importantes para um empregador atual ou futuro: que
voc6 sabe das coisas; que sabe como estudar e se preparar para um teste desafiador; e, acima de tudo, que conhece a
linguagemJava. Se um empregador tiver que optar entre um candidato que passou no exame e outro que nlo tenha
passado, ele saberi que o programador cenificado nio precisar6 se demorar no aprendizado da linguagemJava.

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.

Programa de certificagio da Sun


Atualmente, h6 oito exames de cenificagio emJava. Os exames de Associado,ProgramadoreDesenuoluedoresteo associados com
aJava Standard Edition. Os exames de Componentet IYeb, Ca@onentes de Negocin, Smigos IYeb e Proletista Empresarial estl.o
associados com aJava Enterprise Edition . O exane de Aplicatiuot Mriueis est6 associado com aJava Micro Edition.

Os exames de Associado, Programador, Componentes'Web, Componentes de Neg6cios, Servigos \il7eb e Aplicativos


M6veis sio exclusivamente de mriltipla escolha e do tipo arrastar-e-soltar, e sXo feitos em um centro de testes, enquanto os
exames de Desenvolvedor e de Projetista envolvem o envio de um projeto.

O exame de associado (CX-3 l0-0 | 9)


Associado Java Certificado pela Sun (SCJA)

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 (CX-3 10.035)


ProgramadorJava Certificado pela Sun paraJava 5 (SCJP)

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 (CX-3l0-252A CX-3 | 0-027)


DesenvolvedorJava Cenificado pela Sun paraJava 5 (SCJD)

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

O exame de Desenvolvedor de Componentes de Neg6cios (CX-3 l0-090)


Desenvolvedor & Componentes de Neg6cios Certificado pela Sun na Pl ataformaJavaEE (SCBCD)
O exame de desenvolvedor de componentes de ne.g6cios foi elaborado para os candidatos que estejam usando a tecnologia
Java.EJB para criaraplicativos de camada de neg6cios. O exame se baseii na especificaglo f;n deirnida naJava Enterprise*
Edition flava EE). Para fazer este exame, 6 necessirio que o candidato seja um ProgramadorJava Certificado pela Sun.

O exame de Desenvolvedor de Servigos Web (CX-3 lO-220)


Desenvolvedor de Servigos \feb Certficado pela Sun na PlataformaJava EE (SCDIWS)
O exame de servigos web tem como alvo os candidatos que estejam criando aplicativos com tecnologiasJava EE eJava \7eb
Services Developer Pack. Para fazer este exame, 6 necessi.rio que o candidato seja um ProgramadorJaia Clrtificado pela Sun.

o exame de Projetista (cX-3 | 0-05 | , cx-3 | 0-300A, cx-3 | 0-06 | )


Projetista Empresarial Cenificadopara a Tecnolo 1gr_J2EE (SCEA)
Essa certificagXo se destina a projetistas empresariais e, ponanto, nio requer que o candidato passe no exame de
Programador. O exame de Projetista tem tr6s panes: uma prova de mriliipla escolha baseadaim conhecimentos, um
projeto de arquitetura e um teste de acompanhamento com quest6es dissertativas. VocA precisa passar na prova de multipla
escolha antes de se registrar e receber a tarefa do projeto.

O exame M6vel (CX-3 | 0-0 | l)


Desenvolvedor & Aplicativos M6veis Certi{icado pela Sun paraJava ME (SCMAD)
O exame de. dese1,volv9d91{e aplicativos m6veis 6 para candidatos que esejam criando aplicativos para telefones celulares
ou outros dispo_sitivos habilitados paraJava. O e_xame aborda a espeiificagio Java Technology for 'rt/ireless Indusry
[T\fl),
-
a API lil/ireless Messaging e as APh Mobile M edia.Parafaznr este exame, 6 necess6rio que o iandidato seja um SCJir.

Fazendo o exame de Programador


Em um mundo ideal, vocA seria avaliado-p-or seu conhecimento efetivo em um assunto e nio simplesmente pelas respostas
gu9. d9y a.varias perguntas de um e*ame. Mas a vida nXo 6 perfeita e nem 6 pritico avaliar o conhecimento de v6rias p.iro".
individualmenre.
Na maioria de seus exames de cenificaglo, a Sun avalia os candidatos usando um servigo de teste baseado em computador e
operado pela SyJvan Promet'ic. Esse servigo 6 bem popular na indfstria e usado por v6rios programas de cenificag?o de
outros fornecedores, incluindo o CNE da Novell e b MCSE da Microsoft. Gragas a grande luaitidade & filiais daSylvan
Prometric, os exames podem ser administrados em todo o mundo, geralmente na riesm" cidade do candidato.
Geralmente, os exames da Sylvan Prometric apresentam um funcionamento semelhante para todos os fornecedores. No
entanto, h6 um fato imponante a se conheceriobre os exames da Sun: eles usam o formaio tradicional de te*e da Sylvan
Prometric e nio o adotado recentemente. Isso d6 ao candidato uma vantagem, j6 que o formato tradicional permiteque as
repostas sejam revisadas e refeitas durante o teste.

oBSERVAQ6TS pene O E)GME

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,

Formato das perguntas


Os exames da Sun sobre Java apresentam as perguntas no formato de mriltipla escolha o v de arrxtar-e-soltar. Em vers6es
anteriores, quando lhe era apresentada uma que$io de mtltipla escolha, voc0 nXo sabia quantas respostas estavam corretas'
por6m, a cada versXo do exame, as respostas ie tornaram mais dificeis, de modo que, atualmente, a pergunta informa
quanras respostas t6m que ser selecion-adas. As perguntas do Teste Individual, encontrado no final de cada capitulo, t6m
quase o meimo formato, redagXo e nivel de dificuldade das perguntas do exame real, com duas exceg6es:

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 Um cenirio Uma pequena descrigXo da tarefa que voc6 deverireaJizar.

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

for @agada, nrificil drgitar noaanente a rerporta.

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.

Dicas para a hora do exame


H5,72 pergontas no exame 31G055 $ava 5). VocA ter6 que acertar pelo menos 43 delas para passar - acima de 59 por cento.
Essas informag6es estio zujeitas a alterag6es. Confirme sempre
O tempo para conclusio do exame ser6 de quase tr€s horas.
com a Sun emwww.suned.sun.com, antes deprestar o exame.
. VocA pode responder as perguntas em qualquer ordem e tamb6m pode volt ar paramarcol suas respostas depois que tiver
percoirido otlste. Nio hi penalidades para as respostas erradas, ponanto, 6 melhor marcar uma resposta do que deixar uma
Perguntaem branco,
Uma estrat6gia adequada ao fazer o exame 6 percorr€Jo uma vez e responder todas as perguntas que souber de imediato.
F.m seguida, voc6 poder6 voltar e responder as outras. Responder uma pergunta pode fazer com que se lembre como
responder a anterior.
Seja muito cuidadoso com os exemplos de c6digos. Primeiro, procure erros na sintaxe, conte as chaves, sinais de ponto e
virgula e par6nteses e ceftifique-se se h6 a mesma quantidade desses simbolos na abeftura e no fechamento. Procure erros na
colocagio de letras maiusculas e outros problemas de sintaxe antes de tentar descobrir qual a fungXo do c6digo.
Muitas das perguntas do exame dependerio de minricias da sintaxe. Voc6 precisar6 de um conhecimento consistente da
linguagemJava para que seja bem sucedido.

Dicas que podem ser aplicadas no estudo para o exame


Antes de tudo, reserve bastante tempo para o estudo. AJava 6 uma linguagem de programagio complexa e voc€ nio pode
esperar apreender tudo que precisa siber em uma revisio ripida feita em uma inica sessio de estudo. Trata-se de um campo
que vai sindo m.lhor corttpreendido com o tempo, atrarr6s do estrrdo de um assunto e posterior aplicagXo do
Conhecimento. Elabore uma programagio de estudo e atenha-se a ela, m as seja razoivel com a carga atribuida,
principalmente se estiver estudando ao mesmo tempo em que executa suas tarefas di6rias no trabalho.

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.

Chegando no local do exame


Como em qualquer teste, voc6 fic arS"tentado afaz.er uma revisio r6pida na noite anterior. Resista a essa tentagio. Voc6 jl deve
conhecer o material a essa altura e se estiver muito sonolento pela manhi, nio se lembrari o que esnrdou. Tenha uma boa
noite de sono.

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.

Revise suas respostas


Agora voc6 est6tranqiiilo! Respondeu a todas as perguntas e estA pronto par afazer smaverificaglo apurada. Faga outra
leitura (sim, mais uma) em todo o teste (embora talvez seja uma^boa id6ia nio revisar as quest6ls de arrastar-e-soltar!),
relendo rapidamente cadapergunta e sua resposta.
Repasse as perguntas cuidadosamentg-qais rlma vez para procurar "pegadinhas". Fique panicularmente arento para as que
incluirem a opgio "N5o 6cotttpil"t".Eseja alenapara pistas de riliirnahora. VocO j6 eiti bem familiarizado com quase
todas as perguntas a essa altura e pode encontrar algumas pistas que nio tinha visto antes.

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.

Fazendo novamente o teste


Se voc6 nio passar no exame, nio perca a esperanga. Tente aproveitar o que ganhou com a experiAncia e preParese Pararcntar
,ro1r"rn.rrr..'Considere.se um po.tco -"is informado. Voc€ conhece o fbrmato do teste um Pouco melhor e o relat6rio
mostrari que ireas vod precisa fortalecer.
Se fizer o teste mais uma vez sem demora, provavelmente voc€ se lembrari de virias das Perguntas que pode ter errado.
Isso o ajudari a concentrar seus estudos na area certa'

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:

I Decloror Closses e Interfoces


I Desenvolver Inlerfoces e Closses
Abstroct
I Usor Primitivos, Arroys, Enums e
ldentificodores Legois
I Usor M6todos Stotic, NomeoEdo
JovoBeons e Vor-Args
I Exercicios R6pidos

P&R Teste lndividuol


2 Copitulo 1 : DecloroE6es e Conirole de Acesso

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.

Encontrando Outras Classes


Como veremos mais adiante no livro, 6 uma boa id6ia manter a coesio das suas classes. Isso significa que cada classe deve tet
um coniunto bem definido de responsabilidades. Por exemplo, se fosse criar um progtam de simulagio de um zool6gco,
voc6 representaria javalis com uma classe, e visitantes do zool6gico com outra. Al6m disso, voc6 poderia ter uma classe
Tratadot de Animais, uma classe Vendedor de Pipoca e assim por diante. A questio 6 que voc€ nio deve ter uma classe que
tenha comportamentos deJavali e Vendedor de Pipoca ao mesmo tempo (falaremos mais sobre isso no Capitulo 3).

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
^

ldentificadores e favaBeans (Objetivos 1.3 e 1.4)


l.J Detenuoluer cddigo que dulare, inicialiqe e ase primitiuos, atraJs, enumr e objetos como uaridueis stat ic, de instdncias e locais. Ahn
disto, usar identifcadoret legais para nomes de uaridaeis.

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.

I Padr6es de NomeagdoJavaBeans Os requisitos de nomeagio da especificagioJavaBeans. Nio 6 preciso estudar a


especificagioJavaBeans pata o exarne, mas voc6 precisa saber algumas regras b6sicas de nomeagSoJ"rrrB.*, q.r.
abordaremos neste capitulo.

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)

abstract boolean break byte case catch

char class const ^^nl_


i nlra default do

double else extends final finally float


for :Jvuv if implements import instanceof
int interface long nati-ve package
hri rt^l-a protected public return short staEic
strictfp super switch synchronized this throw
throws trans]-enE Ery void voLatile while
asserE enum

Conveng6es de C6digo lava da Sun


Pelas estimativas da Sun, ao longo da vida de um c6digo padrdo,2\oh do esforgo ser6 despendido na criagio e no teste
ftil
originais 6e 66digo, e 80% do esforgo seri despendido na manutengio e nas melhorias subseqiientes do c6digo. Concordar
com um coniunto de padr6es e programiJo aiudaadiminuir o esforgo envolvido em testar, fazer amanutengio e
melhorar qualquer c6digo. A Sun criou um con,unto de padr6es de programagdopanJavaepublicou esses padr6es em um
documento inteligentemente chamado de "Convengdes de C6digoJ ava",o qualvoc6 pode encontrar em iava.sun.com.
Trata-se de um 6timo documento, curto e f6cil de ler, que recomendamos enfaticamente.

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:

Regras de Nomeagao de Propriedades favaBean


I Se a propriedade r'do fot booleana, o prefixo do m6todo getter deve ser get. Por exemplq getsize ( ) 6 um
nome getterJavaBeans v6lido para uma propriedade chamada "size." Tenha em mente que voc6 n6o precisa ter uma.
vari6vel chamada size (embora alguns IDEs v6o esperar que voc6 tenha). O nome da propriedade 6 inferido a partir dos
t getters e setters, e nZo-atrav6s de quaisquer vari6veis da sua classe. O que vocd ir6 retornat a partir de gets i ze ( )
fica a seu critdrio.

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:

Regras de Nomeagao de Listeners favaBean


I Os nomes de m6todos listeners usados para"reg|strar" um listener com ulna fonte de eventos devem usar o prefixo
add, segu.ido do tipo do listener. Por exemplo, addActionlistener ( ) 6 um nome v6fido para um m6todo que
uma fonte de eventos dever6 permitir a outros registrarem para eventos Act ion.

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

public void addMylistener (MyListener m)


public void removeMylistener (MyListener m)

Alguns exemplos de assinaturas de m6todosJavaBezn inuilidar


void setCustomerName (String s) t
/ / nrcai sa sFr nrrl-r1ic
t ylvvlve

public void modifyMyValue(int v) / / n6.o se pode usar 'modify'


public void addXlistener{MyListener m) I
/ / crra
I eLLv da l- inn d. l-iStenef

oB SERYAQoBS pene O EXAME

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

tzmente se um dado identifcador iri conpilar - os JauaBeaw serdo mendonados explidtamente.

Obietivo poro o Certificogdo

Declarar Classes (Objetivo l. I do Exame)


/.1 Desenuoluernidigo que dulare classes (incluindo claset absLracL e todas atformas de classu aninhadat), intefaces e enilm!, e

incluir o uso apropriado de dularagdes package e inport (incluindo irportagdu utriticas).


I
Ao escreve c6digo emJava, voc€ est6 escrevendo classes ou interfaces. Dentro dessas classes, como voc€ sabe, eistem
variiveis e m6todos (al6m de algumas outras coisas). O-- rSdq qq$o-vsc6 dgclara ag.qu?! 4g_q.q9!:.m(t9dgq 9 varj|y-etg cfsta.-
dramatic4lnente o qg4portamentadoseirc6digo. Pot exemplo, trlr!-lqeto.daJ:ublic pode set acessado a pattit do
c6dig:o que. es-tep Sgdandg em qualqu-er p4-r19 da s.ua,apliesa.g No entanto, l9-ve*-narcar esse m6todo coma pdlf4le-rg]g
&sapar*er?dg.pfo!_ggrAgh,res (94etoo ds glagpe qa qual f.oi-de.clarado). Para este objetivo, estudaremos as formas pelas
quais vocd pode declarar e modificar (ou nio) uma classe. Voc€ perceber6 que abordaremos os modificadores em um nivel
extremo de detalhe, e, embora saibamos que voc6 j6 es td famt\arizado com eles, comegaremos pelo b4sico. A maioria dos
programadoresJava pensa que sabe como todos os modificadores funcionam,m s,ao examinar cuidadosamente a questao,
descobre que nio sabem (ou pelo menos nio no nivel exigido pelo exame). Existem sutis disting6es em toda parte, entao
rer ceftezzabsoluta de que domina totalmente todos os assuntos dos objetivos desta segZo antes de fazet o
::;:....O"

Regras de Declarageo pa;ra Arquivos-Fonte


Antes de mergulhalrnos nas declatagSes de classes, fagamos uma breve revisdo das regras associadas com a declaragio de
classes, declarag6es import e declarag6es package em um arquivo-fonte:
JAVA 5 7
I 56 pode haver uma classe publ i c em cada arquivo de c6digo-fonte.
r Os comentirios podem aparecer no inicio ou no fim de qualquer linha no arquivo do c6digo-fonte;
eles sio
independentes de quaisquer regras de posicionamento diicutidas aqui.

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.

Declarag6es e Modificadores de Classes


Embora classes aninhadas (freqientemente chamadas de internas) caiam no exame,
deixaremos as declarag6es de classes
aninhadas para o Capitulo 8. Voc€ vai adorar esse capinrlo. Niq s6riq vai mesmo. O
c6digo seguinte 6 uma declaraqio de
classe simples:

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

a E:ttdpfZd6Xq,!.(em outras palavras, tornar-se uma subclasse da classe B).

I Acessarcertos m6todos e da classe B, dependendo do controle de acesso desses m6todos


vari6veis dentro .:_:,:::____,".;_r. e variiveis.

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 .

public cfass eeverage { }

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.

Outros Modificadores de Classes (Nio-referentes a Acesso)


Voc€podemodificarumadeclzraglodeclasseusandoaspalavras-chavefinal"ab.sEract,oustricF€.D.!sse;.
modiicadores exi*sfen-rm-adigio-a.qualqueffontrolede acesso existent€naslasse, entiovoc6 poderia, por eremplq declarar
U€Q(!.classecomopublic efina]*ao.mesrf,rotempo.Nlar:r.dqd.semprequevocepodemisturarmodificadoresndo-
{F.fgtgqtesaacesso.Voc€podeusarstrictfp emcombinagiocomfinal,porexemplo,masniodevenunca,iamais,
m tc rvmaclassecomof inal- eabstract aomesmotempo.Voc6ver6porquenasduaspr6ximassegSes.
strictfp funciona, entio nos concentfafemos apenas em modificar uma classe como
Voc6 nio precisard saber como
final- ouabstract.Paraoexame,voc6s6precisasaberquestrictfp 6umapalavra-chavegguepodeserusadapara
.nodifijarumaclasseouunm6tgdo*.m4snuocamavan|vel.Marcarumaclassecomostrictfp significaquequa-lquet
c6digo de m6todo na classe se conformar6 is regras do pa&io IEEET54pzrzpontos flutuantes. Sem esse modificador, os
JAVA 5 9
pontos flutuantes usados nos m6todos poderio comportar de forma variante conforme aplataforna.Se ndo declarat a
se
classecomostrictfp,aindaassimvoc6poder6obterumcomportamentostrictfp param6todosespecificos,
declarando o m6todo como strictfp. Se voc6 nio conhece o pa&io IEEE 754,agotanio6 o momento pam aprend6-lo.
Voc€ tem assuntos mais importantes para se preocupar.

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.

V?.i n1i.U]ique rr.rtls-gb:-q9g-4?s bibliotecas fuodamentaisJava s6o f ina1.


!og*9,1emplo, a classe String"nio pode ser
subclassificada. Imagine a confusio que ocoreria se vocd nio pudesse garantir fo.mi co-t um objeto String funcionaria
em qualquer sistema que executasse a sua aplicagdo! Se os programadores tivessem"
a liberdade de estender a clisse String (e
assim colocar as suas novas instancias da subclasse String onde esperam-se instAncias de java.lang.Strin a civiltzagfuo ti $,
comoaconhecemosenttaiaemcolapso.$ssim,usefinal paraseguranga,masapenasqo".rdotivercertezadequeasua
classe f inal de fato j6 disse tudo o que precisa ser dito nos seus m6todos. Marcaiuma.larr".orno f
significa, na inal-
EI?a-94 que a su,a classe nunca ser6 aprimorada, ou mesmo modificada para uso mais especifico, por outro programador.

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.

Vamos modificat o nosso exemplo Beverage colocando a palavra-chave f inal na declaragio:


nadLrd6
Fsv.leJv ^arf.
ve! e,

public final class Beveraqe {


nrrl-rl i n rrai A impor."n.rJ.noao
"-,* { }

Agora, se tentarmos compilar a subclasse Tea:

package exam. stuf f ,.

i mnnrl- .art Part , erage,.


class Tea extends Beverage { }
Recebetemos um erro como:

Can't final classes: cl_ass


subcl_ass
cert.Beverage class Tea e:itends Beveraqe{
1 error
Napr6tica,voc€quasenunczciars"wrnacJ.asse f inal.As classes f inal acabamcomumbeneficio fundamentalda
programagio OO - a extensibilidade. Assim, a n6o set que voc6 tenha uma s6ria preocupagio de seguranga, assuma
que
-'
algum dia algum outro programador precisar6 estender a sua classe. Se nio o fizir,o pt6*i-o p.op[amador
que for
obrigado a fazer a manutengio do seu c6digo ir6 lhe perseguir e <insira algo muito aisustadoiaqri>.

ClassesAbstract Umaclasseabg-trac-t lraqpgdeserinstanciadanunca.oseurinicoptop6s-ito,missionavida,raison


{'eqe i5lgoteodidetqllbglalsificada). @epare, no entanto, que vocd pode compilar e executaruma classe abstract,
desde que ni.o tente criar urnainst6nciq dela.) por que criar uma classeie voc€ nit pode criar objetos dela? porque
a classe
poderia ser simplesmente, bem, abstract. Por exemplo, imeging qu9 voqitgnh-a uma classe Car que tenha m6tpdo$
genericos comuns a todos os veiculos. Mas vocd n6o quer que]l-gq6- d. futo i.i. um objeto carge.r6ri.o,
abst.r.act.
t;ifro !d inici alzatia o seu estado? De que cor ele seria? Quantos assentos? Potancia do motor? bireg6o hidriulica ou nio?
ou, mais imPortante, de que forma ele se comportaria? Em outras palavras, como os m6todos seriam implementados?
O que voc6 precisa 6 que os progtamadores instanciem tipos reais de carros, como BMWBoxster e SubaruOutback.
Temos
apenas ,.sonha em
cefteza de que o dono de um Boxster lhe diria que o caffo dele 6. capaz de fazer coisas que o Subaru
fazer". Observe a seguinte classe abstract:

abstract class Car {


*_*-,e prlce;
nri rr:f a dnrrl.l
'l
0 Copftulo I : Decloroc6es e Controle de Acesso

privaLe String model,'


private String year;
public abstract voj-d goFast ( ) ;
public abstract void goupH]--Ll- (/;
public abstract void impressNei.ghbors O ;
/ / Co1 odrrc o resfo do c6digo importante e s6rio aqui
/ / vv+vYqv

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:

AnotherClass.java:7: class Car is an abstract


class. It can't be instantiated.
Car x = new CarO,'
1 error
Repare que os metodos matcados com abstract terminam componto-e-virgula, emvez de chaveg'
com uma declaragio de m6todo que te"rmine com ponto-e-virgula, emvezde chaves. Se o m6todo estiver
Pro.Clr_19-lyeptQes
.o-Uniliaiq9,-9 $io em uma interface -, entaq tanto o m6todo como a classe devem ser marcados como abstract.
Pode aparecer uma questao que lhe pergunte como consertar uma amostra de c6digo que inclui um m6todo que termina
com p;nto-e-virgula, mas sem um modificador abstract na classe ou m6todo. Nesse caso, voc€ poderia ou rn rcar o
m6todo e a classe como abstract, ou modificar o ponto- e-virgiapatao c6digo apropriado (um par de chaves, por
exemplo). Lembre-se, se transformar um m6todo de abstrac E parando-abstract, n5o se esquega de trocar o
ponto-e-virgula no final da d eclangdo do m6todo por um par de chaves!

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

Criando uma Superclasse Abstract e uma Subclasse Concreta


Osegu.inteexerciciotestarioseuconhecimentodeclassespublic,default,finaf eabstract.Crieuma
suoerclasse chamada Fruit e urna subclasse concreta chamada Apple. A superclasse deve pertencer a um pacote
abstracg
chamado food e a subclasse pode pertencer ao pacote def ault (significando que ela ndo ser6 colocada em
um pacote
expLicitamente). Torne a superclasse pubf ice d€ i subclasse acesso def ault.
1. Crie a superclasse da segrrinte maneuzl.
n:nlraa fnnd.

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

Declarar Interfaces (objetivos l.l e 1.2 do Exame)


1'l Desenuolaer aidigo qae declare clases (incluindo clasus abttract e todas asformas de c/asses aninhadat), intefans e enum!, e inclua o uso
4rEiado de dukmgdet package e inport (incluindo impo,tapdet utriticas).
1'2' Desenaolaer aidigo qae declare uma nttrfott Desenuoluer aidigo que inplenente ou estenda uma ou mais interfaces. Desenuoluer c;digo
qae dec/are uma classe abstract. Desenuoluer cddigo que ettenda nri ,l^n abttract

Declarando uma interface


Quando voc6 criar uma inte rfzce, estat6' definindo um contrato com o que a classe pode fazer, sem mencionar nada sobre
como a classe o fad.Umalnterface 6 um conffato. Voc6 poderia escrevei uma interiace Bounceable,
por exemplo, que
estabeleceria: "Essa 6 uma interf"ceboon.eable.
Qualquertipo de classe que @plementar .rru irt.riu.. precisa concordar em
e;19r;y_q-r-9p6$go do_sm6todosbounce (
) e setBounceFactor ) ". (
Se uma interface Bounceable (Saltitante) for definida, qualquer classe que quiser ser ttatada
como algo sal.ntante podet6
simplesmente implementar essa interface e fornecer oi6digo de seosiois m6todos.

As interfaces podem ser implementadas por qualquet clasEe,


de,.quglguq 6rvore de heranEa. Isso permiur6 que voc€ use
gbi!9,uadadg-.tsltediferentes e-fortegaaelas.umacaracteristicaemiomum.Pore*emplJ,'voc€podequererquetantoa
classe Ball quanto Tire tenham o mesmo comportamento, mas elas n6o compartilham nenhom^relacionamento
de heranga;
Ball.e stende Toy, enquanto Tite s6 estende
iava.lang.Object. Por6m, ao frrer iom que Ball e Tire implementem Bounceable,
voce estara dizendo que as duas classes podem ser tratadas como "coisas saltitante-s", o qr.. .-Jr.r" 6 traduzido por..coisas
quevoc€podeusarparachamarosm6todosbounce( ) esetBounceFor( )".AFigura1_1 ilustrao
relacionamento entre interfaces e classes.

interface Bounceable O que vocd


declara

void bounce( );
void setBounceFactor(int. bf) t

interface Bounceable Oqueo


compilador
v6.
frub].tc abrtract void bounce ( ) ;
Dubtlc rJrttract void setBounceFactor(int bf),.

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

s6o declarados. As regras s5o


/ apresentam muito pouca flexibilidade em como os m6todos e vari6veis definidos na interface
restritas:

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

i synchronized. (Falaremos mais sobre esses modificadores a seguir)


I Uma interface pode estender uma ou mais interfaces diferentes.
I f Uma interface nio pode estender nada que nio seja outra interface.
1 I Uma interface nio pode implementar outra intetface ou classe.
f Uma interface deve ser declarada om apalavn-chave interf ace.
c
\
I r Os tipos de interface podem ser usados polimorficamente (consulte o Capitulo 2paramais detalhes)'
A linha a seguir 6 uma declaragio de interface v6lida:

public abstract interface RoIlable { }


Digitat o modificador abstract 6 considerado redundante; as interfaces serio implicitamente abstract caso
voce
.ligite ou n6o abstract. 56 6 preciso saber que essas duas declarag6es sio vilidas e funcionalmente id6nticas:

public abstract interface Rol1ab1e { }


public interface Ro1lable { }
g*+."di. 4S_ed"r pub 1 i c ser6 obrigat6rio se voc€ quiser que a interface tenha acesso priblico em Yez de padrig.

Examinamos z declaragdoda interface, mas agora nos aprofundaremos nos mdtodos de uma interface:

Public interface aounceable {


public abstract void bounce ( ) ;
cublic abstract void setBounceFactor(int bf) ;

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:

public interface Bounceable {


void bounceO ; / / sem modificadores
void setBounceFactor (int bf) ; / / sem modificadores
]
Voc€precisalembrarquetodesosrn6todosdeinterfaces6opublic eabstract independentedoqueestivetoa
definigio daintetface.
procure m6todos de interface declarados com qualquercombinaglo que envolvapublic ou abstract, ou sem
modificadores. por exemplo, as cinco declarag6ls de m6todo a seguir, se declaradas dentro de uma interface, serio
vilidas e
id€nticas!

void bounce O ;
.,, public void bounce O ;
abstract void bounce O ;
: Fubf ic abstract void bounce O ,'

abstract public void bounce O ;


As declarag6es de m6todos de interface abaixo nio serio compiladas:

final voj-d bounceO; // f1-nal- e abstract jamais podem ser usados juntos' e

/ /abstract j6 est6 imPlicito


JAVA 5 13
i static void bounce ( ) t / / interfaces definem m6todos de instAncias
I

I private void bounce O ,. / / os m1todos de interface sio sempre public


{
I
I protected void bounce ( ) ; / / (iden)

Declarando constantes de interface


Voc6 pode inserir constantes em uma interface. Ao fazer isso, gq-r?8!I?g::.g.p-4a,s-ap clajises que implementarem a interface
tenham ace ! s !A qE "s.--!S?.cq_tls!.4ol9.

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

class Zap implements Foo {

public void goO {


EAK = ZI'

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

oB SERYAQoBS pene O EXAME

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:

public int x = 1; // varece nao-static e n50-fina1, mas n50 6,


ant x = 1; // parece defaul-t, ndo-final e ndo-static, mas ndo 6!
statii i-nt x = 1; // Neo mostra final ou public
final int x = 1; // Ndo mostra static ou public
6,,L] i^
1luuaru >L4Lru
^r-!l^ ant
l
x = 1; // Nao mostra final
yuuras
^,,Ltl^ larrdr
4t*^1 rrrt
r- x = 1,. / / Nao most.ra static
static final int x = 1 // Nd,o mostra public
public static final int x = 1; // o que voc6 recebe implicitamente
pualquer combinapio dos motlficadores necessriios (poriru in4licitos) d udlida, como tambdm o i o nlo artliqasio de modficadores! No
exame' espere encontrar perguntas as quais ndo podeni responder coretamenle, a ntenos qae saiba, por exempl0, qae
y.f a.u,,!!!,t!!,! dg-innface .f
final enanrapodenireceberumualordarlasseqaeaestiuerimp/emenlando(oadeqaa/qaeroarrarlasse).
14 Copitulo 1 : Declorogoes e Conirole de Acesso

Obietivo poro o CertificoEdo

Declarar Membros de Classes (Obietivos 1.3 e 1.4)


1 .i Desenuoluer tidigo qne dulare, inicialiTg e ase primitiuos, atrEt, enans e objetos coma uaridueis stat ic, de instdncias e locais' Aldn
disso, usaridentificadoru legaispara nomes de uaridueis.

l.4Desenuolueraidigoqaedeclaremdtotlosstatic enio-sLaLic e,seapropriado,ilsarnomesdemdtodosqaeobedtpanaospadrdes


tle nomeapdl JauaBi^. ZU, tlisso, d.esenuoluer aidigo que declare e use ama lista de argunentos de extensio uaiduel.

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!

Voc6 precisa entender duas quest6es difetentes telativas ao acesso:

I Se o c6digo de um m6todo em um classe pode acessarDm membro de outra classe


I Se uma subclasse pode berdarwm membro da sua superclasse

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

return "Wow baby";

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

/ / wma instAncia de zoo?


Zoo z = new ZooO;
System.out.pri.ntln("Zoo says. rr + z.coolMethodO );
// coolMeuhodO 6 public. entao Moo pode invocd-Io em
/ / uma refer6ncia a zoo
)

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

Figuro l-2 Comporogdo de herongo x operodor ponto pqro ocesso o membros.

Tr€s formas de acessar um m6todo:

(D)Invocando um m6todo declarado na mesma classe


(R) Invocando um m6todo usando uma referdncia da classe

(I) Invocando um m6todo herdado


Observe o seguinte arquivo-fonte:
package book;
import cert.*; // tmporta todas as classe do pacote certo
class Goo {
public static void main (String IJ args) {
Sludge o = new SludgeO;
o.testIt O ;
)

Agora observe o segundo arquivo:


narkanp acrl.

public class Sludge {


public void testrtO { System.out.println("s1udge"),' }
1
)

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.

public class Roo {


public String doRooThings O {
/ / imagine o c6digo divertido que entra aqui
rafrrrn \fr1n/.

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

Cloo c = new Cloo0;


System. out.println (c. doRooThings ( ) ) ; // Sem problema; o m6todo
// 6 public

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

Se tentatmos compilarUseARoo, receberemos um erro de compilagio parecido com este:


cannot find symbol
symbol : method doRooThings ( )
E como se o m6todo doRooThings ( ) nio existisse, e, no que diz respeito a qualquer c6digo fora da classe Roo, isso 6
verdade. Um membro private 6 invisivel para qualquet c6digo fora da pr6pria classe do membro.
E se uma subclasse tentasseherdar um membro private da sua supetclasse? Quando um membro 6 declarado
private, uma subclasse nio pode herdar dele. Pata o exame, voc6 precisa entender que uma subclasse nio pode ver, usar
e nem sequer pensar nos membros private da sua superclasse. Voc6 pode, no entanto, declarar um m€todo
cortespondenie na subclasse. Mas, nio importa asuaapai€.nci^,t Ao se irqta de um mdtodo substitutolE
simplesmente um m6todo que por acaso tem o mesmo nome que o m6todo private (de cuia existdncia voc6 nio deve
sequer saber) da superclasse. As regtas de substituigio ndo se aplicam, de forma que voc6 pode fazer esse m6todo "rec6m-
declarado-que-por-um-mero-acaso-6-o-mesmo" declarar novas exceg6es, ou modificar o tipo de retorno, ou qualquer otrtra
coisa que voc6 queira fazer com ele.
nanlrana rarf .

public class Roo {


private String doRooThings ( ) {
// Imagine o c6digo divertj-do que entra aqui, mas nenhuma
/ / orttra classe saber6 disso
return "fun" -

.l
O m6todo doRooThings ( ) agora est6 fora do alcance de todas as subclasses, at6 mesmo aquelas que esteiam no
mesmo pacote que a superclasse:

package cerL; / / Cloo e Roo estao no mesmo pacote


class Cloo extends Roo { / / fuao bem aj-nda, a superclasse Roo 6 prlblica
public void testClooO {
System. out.prj-ntl-n (doRooThings O ) ; / / Erro de compilaqdo !

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.

O efeito do controle de acesso privado

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

Trds formas de acessar um m6todo:

@)Invocando um m6todo declarado na mesma classe


(R) Invocando um m6todo usando uma referdncia da classe

(I) Invocando um m6todo herdado

Membros Protect e Default


Osniveisdeconuoledeacessoprotect edefault sioquaseid€nricos,mascomumadiferengafundamental.Um
membro de f aul t s6 pode ser acessado se a classe que o estiver acessando pertencer ao mesmo pacote, enquanto que um
membro protect pode ser acessado (atrav6s da heranga) por uma subclasse rnesmo se e subclasse estiuer em urn
pacote diferente.
Observe as duas classes seguintes:
nanl::ao
--- *--*JaEfon,.
narf i f i z

public class OtherClass {


20 Copftulo 1 : DecloroE6es e Controle de Acesso

woiri festTr () {L // O
/ /v faro dc nio haver modificador
LsLv

/ / indica acesso padrao


System. out . println ( "Othercl-ass" );

)
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

diferente, e tentar usar a vari6vel x (que a subclasse herda):


package other; / / Pacote diferente
imnnri- carfi fiaal-inn Drranf.

class Child extends Parent {


public void tesrlr ( ) {
System. out . printl-n ( "x i_s \ + x) ; Sem problema; Child
herda x

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

System. out . printl-n ( "x is " + x) i


// Sem prdblema; Child
/ / herda x
Parent P = new Parento; // Podemos acessar x usando
// a refer6ncia a p?
System. out.println ( "X in parent is " + p.x); // Erro de compilaqSol

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.

Se goFast$ for padr6o Se goFast$ for protegido

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.

Onde goFast 6 lnvocando goFast$ usando-se uma Refer- Invocando


Declarado na 6ncia A classe na qual goFastQ foi goFast$ usando.
mesma classe. declarada. se uma Refer6ncia
d classe na qual
goFast$ foi
declarada.

Figuro l-4 Efeitos do ocesso protect

Quando compilarmos o arquivo Child, recebetemos um effo parecido com este:


: Undefj-ned variable : x
Chi1d. j ava:4
System.out.println("Variable x is " + x) t
1 error
O compilador nos d6 o mesmo erro de quando um membro 6 declarado como private. A subclasse Child (em um
pacote diferente do da superclasse Parent) ndo 6 capaz de ver nem usar o membro padrio x da superclasse! Agora, e quanto
ao acesso padrio para duas classes do mesmo pacote?
package certif ication ;

public cl-ass Parent{


JAVA 5 23
int x = 9; // acesso padrao
)

E, na segunda classe, voc6 tem o segrinte:

package certif ication ;


class Child extends parent{
static public void main(StringlJ args) {
Child sc = new Chi_IdO;
sc. testIt O ,.

i
)

public void testrr O {


System.out.println('.Variable x is " + x) ; // Sem problemas
)

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.

Variiveis Locais e Modificadores de Acesso


Os modificadores de acesso podem ser aplicados a variiveis locais? NAO!
Nio existe nenhum caso em que um modificador de acesso possa ser aplicado aumavailvel local, entio, cuidado com
c6digo como o seguinte:
class Foo {
void doSruff O {
private int x = 7;
this.doMore(x);

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

Tqbelo I -2 Determinondo o Acesso o Membros de Closses

Visibilidade Pubtc Protect Default Private

A partir da mesma classe Sim Sim Sim Sim


A partir de qualquer classe do mesmo pacote Sim Sim Sim Nio
A partir de uma subclasse do mesmo pacote Sim Sim Sim N6o
A partir de uma subclasse de fora do mesmo pacote Sim Sim, atrauis Nio Nio
da heranga

A partir de qualquer classe que nio seja Sim Nio N6o Nio
uma subclasse e esteia fora do pacote

Modificadores Nio-Referentes a Acesso


J6 discutimos o acesso a membros, o qual diz respeito ao c6digo de uma classe pode invocar rxn m6todo (ou acessar uma
variivel de instdncia) aparar de outra classe. Isso ainda nio inclui uma s€rie de outros modificadores que vocd pode usar em
declarag6es de membtos. Dois deles j6 lhe sio fami-liares f
- inale abstract -,porque n6s os aplicamos a
24 Coollulo I : Decloroc6es e Conirole de Acesso

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:

public Record getRecord(int fileNumber, int recordNumber) { }

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 ;

A classe anterior produzird o seguinte erro se voc€ a tentar compiJar:


f11ega1Class. java: 1 : class Il1ega1C1ass must. be declared
abstract.
It does not define void doftO from cl_ass I11ega1C1ass.
public cLass I11ega1Class{
1 error
voc6 pode, no entanto, ter uma classe abstract sem nenhum m6todo abstract. O seguinte exemplo ir6
compilar sem problemas:
publi-c abstract cl_ass LegalClass {
void goodMethodO {
/ / insira um monte de c6digos reais de implementagdo aqui
)
1
J

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.

Os m6todos abstract devem set implementados por uma


subclassenio-abstract. Se a subclasse for abstrata, ela n6o 6
obrigada a implementar os m6todos abstract, mas tem a
pemisseo de implementat qualquer um ou todos os m6todos
abstract da superclasse. A classe AcmeRover 6 nio- enable4wd( \ // oPclonaL
goOffRoad( ) // requerido
abs t rac t, entao ela precisa implementar o mdtodo ab - turn (int, whichWay) //requerido
stract declarado na sua superclasse, SUV e precisa
implementar tamb6m turn ( ) , que nio foi implementado por
SL]V

Figuro t-5 Os efeilos do modificodor obsfrocl sobre subclosses concrefos e obsfrolos


Ptocure por classes concretas que nio fornegam implementag6es pata m6todos abstracL da superclasse. O seguinte
c6digo nio vai compilar:
public abstract class A {
abstract void foo ( ) ;
)

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:

abstract static void doStuff ( ) ;

E lhe daria um effo que a esta altura i6 deverdlhe parecet familiar:

MyClass.java:2: i1lega1 combi-nation of modifiers: abstract and


<f i
^l- ^
abstract static void doStuff O;

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.

M6todos com Listas de Argumentos Vari6veis (var-args)


Desde a versio 5.0,Java lhe permite criar m6todos c pzzes de usar um nfmero variivel de argumentos. Dependendo
de
onde voc€ pesquisar, poderd ver essa caPacidade ser chamada de "listas de argumentos de extJnsio v ariivel';,,,argumentos
vari6veis", "vat-args","vatatgs" ou o nosso favorito (saido do departamento de obscuridad e),"patdmetrocom nfmero
vari6vel de argumentos". Todos eles sio a mesma coisa, e usaremos o termo "vat-ztgs" daqui em diante.

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

// pardmexros: String e int


Falaremos mais sobre o uso de mftodos var-args nos pr6ximos capinrlos, por agora vamos revisar as regras de
declangtro
pamvar-args:

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

protected void Foo O { } este 6 um m6todo com um P6ssimo nome,

^^-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

void Foo2 O { } / / 6 um m6t.odo, ndo um consrrur.or


FooO { \ / / n5o 6 nem m6todo nem conscruuor
Foo2 (short s) ,. / / se parece com um m6todo abscracc
static Foo2(float f) { } // ndo pode ser static
final Foo2 (long x) { } / / ndo pode ser fj_naI
abstract Foo2 (char c) { I t t ndo pode ser abstract
Foo2(int.. x, int t) { } tt sintaxe var-arg lncorreEa

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.

Declarando Primitivos e Interralos de Primitivos


Vari6veis primitivas podem set declaradas como vari6veis de classe (stat ic), varidveis de instincias, parimetros de
m6todos ou vari6veis locais. Voc6 pode declarar um ou mais primitivos, do mesmo tipo primitivo, em uma mesma linha.
No Capitulo 3, discutiremos as diversas maneiras pelas quais eles podem ser inicializadosrmas, por agora, apresenraremos
apenas alguns exemplos de declaragSes de vari6veis primitivas:

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.

bitde sinal: 0 - positivo 1 = negativo

ryi I 00100r.1 bits de valores:

/ t__=\ byte: 7 bits representam 27 ou 128 valores


bit de sinal bit valores diferentes: de 0 a 127 ou de -128 a -1
fe
\ short: 1 5 bits podem representar 21
s
ou 327 68
short I 111110100000011 valores: de 0 at6 327 67 ou de -327 68 a -1,

Figuro 1-6 O bit de sinol de um byte


30 Copftulo 1 : Declorog6es e Conlrole de Acesso

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

souber as duas primeiras colunas desta tabela, estar4 em boaforrnzpzra o exame.

Tobelo l-3 Intervolos de Primitivos Num6ricos

Tipo Bits Bytes Intervalo Minimo Intervalo Miximo

b)'t' 21 -1
)15 a15 1
short t6

1nt 5Z
.r3r )3r 1

163 a63_L I
long oz+ L

float JZ n/d n/d


double oz+ n/d n/d

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

Declarando Vari6veis de Refer6ncia


Vari6veis de refet€ncia podem ser declaradas como variiveis s t at i c, vari6veis de instincias, parAmetros de m6todos ou
vari6veis locais. Voc6 pode declarar uma ou mais vari6veis de referCncia, do mesmo tipo, em uma mesma linha. No Capitulo
3, discutiremos as virias maneiras pelas quais elas podem setirnciahzadas, mas por agot^^presefltaremos apenas alguns
exemplos de declarag6es de vari6veis de refer€ncia:

Object o;
Dog myNewDogRe f erenceVariable ;

String sL, s2, s3; / / declara tr6s vari6veis Strinq

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 {

// d.efine campos (vari5veis de instAncias) para instdncias de employee


private String name;
private String titl-e,
private String manageri
/ / ouLros c6digos aqui, incluindo os metodos de acesso para campos privados
JAVA 5 3I
A classe Employee antetior diz que cada instAncia de employee saber6 qual 6 o seu pr6prio nome, titulo e gerente. Em
ouras palavras, cada instAncia pode ter os seus valores irnicos para esses ff6s campos. Se voc6 vir os termos "campo",
"vari6vel de instdncia", "propriedade" ou "atributo", eles significam praticamente a mesma coisa. (I.{a verdade, existem
disting6es sutis, mas ocasionalmente importantes enfte os termos, contudo, elas nio sio usadas no exame.)

Parao exame,voc6 ptecisa saber que as varidveis de inst6ncias


I Podem usarqualquer um dos quatro niueis de acerso (o que significa que eles podem ser marcados com qualquer um dos
tr€s nodficadoret de acesso)

I Podem sermarcadas como f inal


I Podem sermatcadzscomo transient
I Nio podem sermarcadas como absLract.
I N6opodem sermarcadas como sinchroni-zed
I Nio podem sermatcadas como strictfp
I Niopodem sermarcadas como native
I Nio podem set marcadas como stat. ic, porque isso as transformatia emvati|veis de classe.

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.

Vari6veis locais Varidveis (nioJocais) M€todos

final finaL tinaL


nrrhf i ^
yuvf+e nrrl.r'l'i
ysvrre a

protected hr^|-a-l-aA
Fr vevv ues

private nrirr.f-a

st.at. ict D LdLIU

transient
volatile abstract
synchronized
c|-ri al-fn

native

iguro l-7 ComporoEdo de modificodores pqro vori6veis x m6fodos

Variiveis Locais (Automatic/Stack/Method)


Varidveis locais sio aquelas declaradas dentro de um m€todo. Isso significa qu e avai|velnd.o 6 apenas inrciahzzda dentro do
m6todo, mas tamb6m declarada dentto dele. Assim como a vari6vel local iticjaasua vida denffo do m6todo, ela tamb6m 6
destruida quando o m6todo finaLzz. As vari6veis locais frcam sempre na pilha, e nio no heap (Falaremos mais sobre a pilha
e o heap no Capinrlo 3). Embora o valor da vanivel possa ser pass ado para, digamos, outro m6todo que enrao
valor em uma vari6Lvel de instincia, a vari6vel propriamente dita s6 vive dentro do escopo do m6todo. ^r^^"in o
Apenas nlo se esquega de que enquanto a variivel local est6 na pilha, se a vati6vel for uma referdncia a obietq o objeto
propriamente dito ainda ser6 criado no heap. Nio existe um objeto de pilha, apenas umavari6vel de pilha. Voc6
frlqiientemente ouvird programadores usarem a expressio "objeto local", o que eles realmente querem dizer 6 "variivel de
refer6ncia declarada localmente". Assim, se ouvir um programador usar essa expressio, vocd sabir6 que ele 6 simplesmente
preguigoso demais parausar o termo tdcnico mais preciso. Voc6 pode dizer a ele que n6s afirmamos is so a nio ser que ele
-
saiba onde nos moramos.

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
)

public void count O {


System.out.println("instance variable count is " + count);
)

public static void main(Stringtl args) {

new Testserver O . loglnO ;


new TestServer O .count (),.

i
i
O c6digo acimaproduz a seguinte saida:
loca1 variable count is 10

instance variable count is 9

Mas por que razdovoc6.iiaquerer fazer isso?


Normalmente, voc6 n6o vai. Mas uma das raz6es mais comuns € pan dzr a um parAmetro o mesmo nome que a vai6vel de
instAncia i qual o parimetro ser6 atribuido. O seguinte c6digo (incotreto) est6 tentando definir o valor de uma vari6vel de
instAncia usando um parAmetro:

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

size = size; // // ??? qual size 6 igual a qual size???


)

]
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 o exame, voc6 precisa saber ffes coisas:

I Como cizrwavai|vel de refer6ncia a um array (declarar)

I Como criar um objeto array (construir)


I Como preencher o array com elementos (inicializar)

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.

Derlaranclo um Arral de Pinitiuot

int I J key; // Colchetes antes do nome (recomendado)


int key I J ; / / colchetes depois do nome (v61ido, mas menos legivel)
Declarando am Aray de Refer1ncias a Obietos

Thread [ ] threads; / / Pccnmond:dn

Thread threads [ ]; // val-i-do, mas menos leglvel

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.

OBSERVAQ6BS pene O EXAME

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:

int [5] scores;


O cddigo acima ndo uai compilar. Itmbre-se, a JI./M ndo aloca etpapo ati que uoci defato in$ancie o objeto array Sd entdo d que o tamanbo

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.

classe classe final Foo a clasrc f j-nal- ndo

mdtodo cfasse Baz o nrltodo f inal nio


finrl rrnirl
vvru an/
Jv \
\/

classe Bat estende Ba

rinaffid so ( )

variivel classe Roo a uariduelf inal nio


fi"al i"t sir. = pode receber um valor
42; novo, depois de ter sido
criado o m6todo inicial (a
auibuigio inicial de um
,roi-ffi"rrgsize (

Figuro 1-8 Efeito de finol sobre vori6veis, m6fodos e closses


JAVA 5 35
Vari6veis Transient
Se marcar uma vari6vel de instdncia como transient, voc6 estar6 dizendo dJ\M para ignorar ess avaiilvelquando voce
tentat seria\zar o objeto que a contem. A serializagio 6 um dos recursos mais legais deJava; ela lhe permite salvar (o que As
vezes se chama de "flatten') um objeto escrevendo o seu estado (em outras palavras, o valor das suas vari6veis de
instincias) em um tipo especial de stream de E/S. Com a serializagio vocd pode salvar um objeto em um arquivo, ou at6
enviilo affav6s de uma conexio para ser "re-inflado" (deseridtzado) do outro lado, em outraJ\M. A serializagio foi
adicionada ao exame na vetsioJava 5, e falaremos dela com mais detalhes no Capitulo 6.

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

O que voc€ nlo pode marcar como s t at i c:


I Construtores (nio faz senado;os constfutores somente s6o usados para criarinstAncias)
I Classes (a nio ser que esteiam aninhadas)

I Interfaces

I Classes internas locais de m6todos (veremos isso no Capitrrlo 8)

I M6todos de classes internas e vari6veis de instincias


I Vari6veis locais

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:

enum CoffeeSize { erc, HUGE, oVERwHELMING };


Dai em diante, a rinica maneira de se obter um Co f f e e s i z e ser6 com um a declaragdo parecida com esta:
CoffeeSi-ze cs = CoffeeSize,BIG;
Nio 6 obrigatdrio que as constantes enums estejam escritas totalmente em mairisculas, mas, tomando emprestado da
convengio de c6digos da Sun que detetmina que as constantes tenham os seus nomes em mairisculas,6 uma boa id6ia
faz€Jo aqui.
36 Copftulo I : Decloroc6es e Controle de Acesso

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!

Declarando um enum fora de uma classe:


enum CoffeeSize { erc, HUGE, oVERWHELMTNG I / / n5o pode ser
/ / private nem protect

class Coffee {

CoffeeSize size;
l
J

public class CoffeeTestl {


public static void main(Stringtl args) {
Coffee drink = new Coffee ( ) ;
dri-nk. size = Cof feeSize.BIG; // enum fora da cl-asse

]
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

enum coffeesize {erc, uuce, oVERWHELMTNG }

CoffeeSize size;
I)

public class CoffeeTest2 {


public static void main(Stringtl args) {
Coffee2 drink = new Coffee2 O ;
drink. size = Coffee2 . CoffeeSize . BIG; ,z/ incluindo classes
/ / nome requerido
)
l
J

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

enum coffeesize { erc, HUGE, OVERWHELMTNG I; / / .- o ponto-e-virgula


| / e
< ^^^:
// ^-^-
opcrona_L aqu]-

public statj.c void main(StringtJ args) {


Coffee drink = new Coffee O ;
drink. si_ze = CoffeeSize.BIG;
)

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:

,// exemplo conceitual- de como voc6


/ / pode entender os enums

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 =

new CoffeeSize (.'OVERWHELMfNG,,, 2 ) ;


public CoffeeSize(String enumName, int index) {
// mais coisas aqui
I
)

public static void main(Stringtl args) {


System. out . println (CoffeeSize . BIG) ;
]
)
Repare como cada um dos valotes enumerados, BIG, HUGE e OVERWHELMING, 6 uma instAncia do tipo
Cof f eeSize. EIes sio representados como static e f inal-, o que no mundo Tava corresponde a uma constante.
Repare tamb6m que o valor de cada enum conhece o seu indice o.. poiigao... Em o.rtias palavras, a ordem na qual os
enumssdodeclaradosfazdiferengz.Voc€podepensarnosenums deCoffeeSj-ze iomofazendopatedieumarray
do tipo Cof f eeSi ze, e, como ver6 em um capitulo postedor, voc6 pode iterar atrav6s dos valor de um enum
invocando o m€todo val-ues ( ) em qualquer tipo de enum.
Q.,Tio se preocupe com isso neste capitulo.)

Declarando Construtores, M6todos e Variiveis em um enum


Pelo fato de um enum ser na verdade um tipo especial de classe, voc €. pode fazer mais do que apenas listar os valores das
constantes enumeradas. Voc€ pode adicionar consffutores, vari6veis de inst|ncias, m6todos e uma coisa bastante estranha
chzr:nada corpo de c/asse especfico da constante.Pan entender por que voc6 poderia precisar ter mais coisas no seu enum, pense
neste cen6rio: imagine que voc6 queira saber o tamanho exato, em ongas, que corresponde acadavmadaa aonrt"nta, f,.
CoffeeSize.Porexemplo,voc6querdeixarclaroqueBlG tem8ongas,HUGE teml0onqaseOVERWHELMING
tem inacredit6veis 16 ongas.

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

B]G (8), HUGE (10), OVERV'THELM]NG(16) ;


/ / os argumentos ap6s o valor do enum sdo "passados"
/ / como valores para o construtor

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

public static void main(StringIJ args) {


Coffee drinkl = new Coffee O ;
drinkl . slze = CoffeeSize.BIG;

Coffee drink2 = new Coffee O ;


drink2 . size = CoffeeSize.OVERWHELMING;

System. out println (drinkl- . size . getounces


. ( )) ; exibe 8

System. out.println (drink2. size. getOunces ( )); exibe 16

]
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) ,

OVERWHELMING ( 16 ) ttbloco de c6digo que defina


t,// ininie rrm

/ / o "corpo" para esta constante


public String getlidcode O { // substitua o m6todo
/ / definido em Coffeesize
return rrA";
)

); // .- o ponto-e-virgula 6 OBRIGAT6RIO quando h6 um corpo


CoffeeSize (int ounces) {
this.ounces = ounces;
)

private j-nt OUnCeS;

public int get.Ounces O {


reEurn ounces;
)
public String get.LidCode () { // este m6t.odo 6 subsriruido
/ pe!a consranre
/| / ^^1 OVERWHELMING
rafrrrh !rQrr.
/ / o va\or padrao que queremos retornar
/ / para as constantes CoffeeSize
)

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

Vamos rever brevemente o que vocd precisar6 saber para o exame.

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.

ldentificadores (Objetivo | .3)


E Os identificadores podem comegar com uma letra, um underscore, ou um caracter monet6rio.
E Depois do primeiro car^cter,os identificadores podem incluir tamb6m digitos.
E Os identificadores podem ter qudquer extensio.
D Os mEtodosJavaBeans devem ser nomeados usando-se camelCase e, dependendo do prop6sito do m6todo, devem
comegar com set ("define'), get ("obt6m'), i s("6'), add("adiciona") ou remove.

Regras de declaragSo (Objetivo l.l)


E Um arquivo de c6digo-fonte s6 pode ter uma classe priblica.
E Se o arquivo de c6digo-fonte tiver uma classe priblica, seu nome terA que coincidir com o dessa classe.
D O arquivo s6 pode ter uma instrugio de pacote,por€m,v6izs de importaqdo.
E A instrugeo de pacote (se houver) deve ficar na primeira linha (fora os comentarios) do arquivo de c6digo-fonte.
E A instruq6o de importaqio (se houver) deve vir depois do pacote e antes da declaragio de classe.

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 O arquivo pode ter mais de uma classe nio priblica.


JAVA 5 4I
E Os arquivos que nio tiverem classes pfblicas nio apresentario restrig6es de nomeagio.

Modificadores de acesso a classe (Objetivo l.l)


0 ga t€s modificadores de acesso: publ ic , protected e private.
E H6 quatro niveis de acesso: public, protected, def ault e private.
E As classes s6 podem ter acesso publ ic ou d.ef ault .

D A visibilidade das classes gira em torno de se o c6digo de uma classe pode:


E Criar uma instdncia de outra classe
E Estender (ou criar subclasses) outra classe
E Acessar m6todos e vari6veis de outra classe

Modificadores de classe (n6o referentes a acesso) (Objetivo 1.2)


E As classes tamb6m podem ser alteradas com f ina1, abstract ou strictfp.
E Uma classe nio pode ser f inal- e abstract.
E Uma classe f inal- n6o pode ter subclasses.
E Uma classe abstract nio pode serinstanciada.
E Uma classe com somente um m6todo abstract significa que a classe inteira deve ser abstract.
E Uma classe abstract pode ter m6todos abstracts ou ndo.
E Aprimeiraclasseconcretaaestenderumaclasseabstract ter6queimplementartodososm6todosabstracts.

lmplementagio de interfaces (Objetivo 1.2)


D Asinterfacessiocontratosquedefinemoqueaclassepod,er6.fazer,masndodtzemnadasobreamaneirapelaqualela
deverS,faz€-Io.

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

Modificadores de acesso a membros (Obietivos 1.3 e 1.4)


E Os m6todos e as vari6veis de inst6ncia (nio locais) sdo conhecidos como "membros".
fl Os membros podem usar todos os quatro niveis de acesso: public, protected, def aul-t, private.
E O acesso aos membros se d6 de duas formas:
D O c6digo de uma classe pode acessar um membto de outra classe
f,l Uma subclasse pode herdar um membro de sua superclasse.
E Se uma classe ndo puder ser acessada, seus membros tamb€m ndo poderio.
E A visibilidade da classe deve ser determinada antes da dos membros.
D Os membros pub 1 i c podem ser acessados por todas as outras classes, mesmo de pacotes diferentes.
D Se um membro da superclasse for publ i c, a subclasse o herdat6 - independente do pacote.
fl Os membros acessados sem o operador ponto (.) t6m que pertencer i mesma classe.
D tnis sempre referenciarS.o objeto que estiver sendo executado no momento.
fl tnis.aMethod( ) 6omesmoquesimplesmentechamaraMethod( ).
E Os membros private s6 podem ser acessados por um c6digo da mesma classe.
D Os membros private n6o ficam visiveis p^r^ as subclasses, portanto, nZo podem ser herdados.
E Os membros def ault e protect s6 diferem quando subclasses estio envolvidas.
B Os membros def ault s6 podem ser acessados por outras classes do mesmo pacote.
E Os membros protect podem ser acessados por outras classes do mesrno pacote, al6m de pot subclasses,
independente do pacote.

E protect = pacote + kids (kids significando subclasses).


E Por subclasses externas ao pacote, o membro protect s6 pode ser acessado affavEs da heranga: uma subclasse
externa ao pacote nio pode acessar um membro protect usando a refer6noa a uma instAncia da superclasse (em
outras palavras,ahetangzb o rinico mecanismo para uma subclasse externa ao pacote acessaf urn membro protect
de sua superclasse).

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.

Vari6veis locais (Objetivo 1.3)


D As declarag6es de varidveis locais (de m6todo, autom6ticas, de pilha) nio podem ter modificadores de acesso.

E f inal 6 o,inico modificador disponivelpzrzvzi|veis locais.


E As vari6veis locais nio recebem r-alores padriq portanto, devem ser inicializadas antes do uso.

Outros modificadores - membros (Objetivo 1.3)


E Os m6todos f inal nio podem ser sobrecarregados em uma subclasse.
E Os m6todos absgract foram declarados, com runa assinarura, um tipo de retorno e uma cl6usula throws opcional,
mas nio foram implementados.
E Os m6todos abs t rac t terminam com urn ponto-e-virguIa, e ndo chaves.
E H6 tr6s maneiras de identificar um m6todo n6o abstract :

E O m6todo ndo 6 marcado como abstract.


E O m6todo possui chaves.
E O mdtodo possui um c6digo entre as chaves.

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.

D Omodificadot strictfp s6 6apJicado aclasses em6todos.

M6todos com Argumentos Vari6veis (var-args) (Objetivo 1.4)


E A partir de Java 5,os m6todos podem declarar um p ardmetro que aceita de zero avdriosargumentos, 6 o chamado
m6todo var-arg.
O Um parimetrov^r-zrgedeclarado com a sintaxe tipo... nome; por exemplo:
doStuff (int... x) { }
E Um m6todo var-arg s6 pode ter um parim etro var'zlrg.
E Em m6todos com parimetos normais e um var-arg, o var-arg deve vir por ultimo.

Declarag5es de Vari6veis (Objetivo 1.3)


fl As vari6veis de instincia podem:
E Ter qualquet tipo de contole de acesso
E Seremmarcadas como finaL ou transl-ent
D Asvari6veisdeinstAncianiopodemserdeclaradascomabstract, sychronized, nativeoustrictfp.
D E valido declatar uma v ari|vellocalcom o mesmo nome de uma vari6vel de instincia; isso 6 chamado de
"sombreamento".
E As variiveis f inal apresentam as seguintes propriedades:
E Nao podem ser reinicializadas, uma vez que tiverem um valor atribujdo.
E As vari6veis de refer6ncia f inal- ndo podem referenciar um objeto diferente se j6 tiverem um objeto atribuido a
elas,

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.

Declarag6es de Arrays (Objetivo 1.3)


D Os arrays podem arm^zerrat tipos primitivos ou objetos, mas o attay propriamente dito 6 sempre um objeto.
O Quando voc€ declara um array, os colchetes podem ficar i esquerda ou i direita do nome davzridvel.
fl Nunca 6 vdlido inclut o tamanho do anay na declaragdo.
D Um zrfay de obietos pode armazenar qualquer objeto que passe no teste E-UM (ou instanceof) para o tipo declarado do
attay.Por exemplo, se Horse estender Admal,entd,o um objeto Horse pode ser colocado em um arav di Animal.

Vari6veis e m6todos static (Objetivo 1.4)


D Nio sio associados a nenhuma instincia especifica da classe.
E Nio6necessiriaaexistdnciadainstinciadeumaclassepataqueosmembrosstatic destasejamusados.
D 56 haveri um a c6pia da vaidvel ou classe s tat i c e todas as instdncias a compartilhario.
E Os m6todos static nio tdm acesso direto a membros nio-static

Enums (Objetivo 1.3)


E Um enum especifica uma lista de valores constantes que podem ser atribuidos a um determinado bpo.
D Um ertum ndo 6 uma String nem um int; o tipo constante de um enum 6 o tipo do pr6prio enum . por exemplo,
INVERNq PRIMAVER T, VERAO e OUTONO sio do tipo enum Estagio.
Q Um enum pode ser declarado fora ou dentro de uma classe, rnas ndoem um m6todo.
E Umenum declarzdoforadeuma classeadopodesermarcadocomstatic, f inal , absLract, pro-
tected ou private.
44 Copitulo I : Decloroc6es e Controle de Acesso

E Os enums podem conter construtores, m6todos, variiveis e corpos de classes constantes.


E As constantes enum podem enviar argumentos para o construtor enum, usando a sintaxe BIG(8), onde o l-iteral int
8 6 passado ao construtor enum.

E Os construtores enum podem ter argumentos e podem ser sobrecarregados.

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

l. Dado o seguinte c6digo


f. interface Base {
2. boolean m1 O ;
3. byte m2(short s);
4. )

Qual fragmento de c6digo ir6 compilar? (N4arque todas as corretas')


A. interface Base2 i-mplements Base { }
B. abstract cl-ass Class2 extends ease {
public boolean m1 O { return true,' } }
C. abstract cl-ass Cfass2 implements ease { }
D. abstract class Class2 j-mplements Base {
public boolean mlO { return (true) ; } }
E. cl-ass Class2 implements Base {
boolean mlO {return false; }
byte m2(short s) i return 42; ) )

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 ; }

esti correta? (Marque todas as corretas.)


3. Qual das seguintes afirmativas
A. "X estende Y" 6 Correto Se, e Somente se, X for uma classe e Y for uma
interface.
B. ..X estende Y" 6 correto se, e somente se, X for uma interface e Y for uma
^t ^a^^
5 45 JAVA
C. "X estende Y" 6. correto se x e Y forem ambos classes ou ambos interfaces.
D. "X estende Y" 6. correto para todas as combinaq6es d.e X e y sendo cl-asses e/
ou interfaces.

4. Quais das seguintes sio declarag6es v6lidas? (Marque todas as corretas.)


A. int gx;
B. int 123;
C. int _1,23;
D. int #dim;
F i nl- *naraanl- .

F. int *divide;
G. int central_sales_region_Summer_200S_gross_sa1es ;

5. Quais nomes de m6todos obedecem ao padreo favaBeans? (Marque


todas as corretas)
A. addSize
B. getcust
C. deleteRep
D. isColorado
E. putDimensions

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

5. / / insira c6digo aqui

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

D. A compilagio falha devido a um erro na linha 3

E. A compilag6o falha devido a um ero naltnha 4

F. A compilagio falha devido a um erro na linha 9

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.

Respostas do Teste Individual


1. C e D estio coffetas. C esti correta porque uma classe abstract nio precisa implementar nenhum dos m6todos
da sua interface.D esti correta porque o m6todo est6 implementado coretamente.
A est6 incoreta porque as interfaces nio implementam nada. B est6 incorreta porque as classes nio estendem interfaces.
E est6 incorreta porque os m6todos de interfaces sio implicitamente publ ic, entao os m6todos sendo
implementados precisam ser publ i c (Objetivo 1.1)
2. B est6 correta. As classes abstract nio precisam ter nenhum m6todo abstract.
A est6 incorreta porque os m6todos abstract devem ser marcados como tais. C est6 incoreta porque n5o 6
possivel ter um m6todo abstract sem que a classe seja abstract. D est6 incorreta Porque apalzvra-chave
abst.ract deve vir antes do nome da classe. (Obietivo 1.1)
JAVA 5 47
3. C estd correta.

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)

4. A, C eG slo identificadores v6lidos.


B est6 incorreta porque um identificador nio pode comegar com um digito. D, E e F estao incorretas porque os
identificadores devem comegar com $ ou uma letra. (Obietivo 1.3)
5. B e D usam os prefixos v6lidosget e is.
A, C e E estao incoffetas potque add, delete e put nio sio nomes de prefixosJavaBeans padr6es. (Obietivo 1.4)
6. Ae E usam sintaxe vat-atgv6Jrdz.
BeCusamsinaxevar-arginv6lida,eD6invilidoporqueovar-argdeveseroultimoargumentodom6todo(Obietivo1.4)
7. A B e E sdo declaragSes de arrays corretas; E 6 um array tridimensional.
C, D e F estao incoffetas, ndo 6 possivel incluir o tamanho do seu array em uma declaragdo a n7'o ser que voc€ tambdm
instancieoobjeto anay.E usaumasintaxedeinstanciamentoinv6lida. (Objetivo 1.3)
8. A estd correta; enums podem ter consffutores e vari6veis.
B, C, D, E e F estio incorretas; todas essas linhas usam sintaxe correta. (Objetivo 1.3)
9. D e F estio corretas. A linha 5 6 a rinica que nio vai compilar, porque os enums nio podem ser locais a um m6todo.

A B, C e E estio incoffetas com base na afirmaglo acima. (Obietivo 1.3)


48 Copitulo I : Decloroc6es e Controle de Acesso
OrientaEio a
objetos

Obierivos pqrq q
certificog6o
I Decloror Interfoces

I Decloror, Iniciolizor e Usor Membros


de Closses

I Usoro Sobrecorgo eo SobrescriE6o


I Desenvolver Consirulores

I Descrever o Encopsulomento, o
Acoplomenlo e o Coes6o

I Usoro Polimorfismo
I Relocionor Modificodores e HeronEo

I Usor Conslrutores de Superclosses e


Conlrutores Sobreco rregodos

I Usor ReloE6et 6-UU e TEM-UM

l/ Exercfcios r6pidos

P&R Teste individuol


50 Copitulo 2: Orientogdo o objetos

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.

I Para os m6todos, use a conveng1o de nomeagioJavaBeans de seLcsomeProperty> e


get<someProperty>.
JAVA 5 5I
A Figura2-1 ilustra o conceito do encapsulamento, forgando os chamadores do c6digo a usar m6todos em vez de
poderem acessar as variiveis diretamente.
Chamamos os m6todos de acesso de capturadores e confgaradores. embora algumas pessoas prefiram os termos mais
pomposos acusadorcs e modifcadorcs. (Pessoalmente, nio gostamos dapalavra modfiear.) Independente da maneira como
voc6 os chamar, eles serio os m6todos que as outras pessoas terio que usar para icessar suas varilveis de instincia. Slo de
apar6ncia simples, e 6 provivel que voc6 ji os tenha usado:

B b = new BO;
int x = b.getSize0; Qretsize ()

b.setsize(34); setSize ()

St.rinq s = b.getName0; getName ()

b.setName( "Fred') ; setName ()

Color c = b.getcolorO; getcolor ()

b. set.Color (b1ue) ; set.Color ()

A Classe A nio 6 capaz de acessar os dados de vari6veis de


instAncias da Classe B sem ser atrav6s de m6todos
capturadores e configuradores. Os dados sio marcados como
privados; apenas os m6todos acessadores sio p0blicos.

Figuro 2-l A noturezo do encopsulqmenfo

public class Box {


// protege a variS.vel de inst.Ancia; somente uma instAncia
/ / a parEir de Box pode acessar .' d
private int size;
// Fornece capturadores e configuradores priblicos
public int getsizeO {
recurn st-ze;
]
public void setsize(int newSize) {

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.

oBSERVAQ6ES pene O EXAME


Cuidado con cridigos que parepm abordar o cumpnftamentl de um mtitodo, ponim, com o pmblena real sendo afalta de encapsulamento.
Examine o exerQ/o a seguiry e uela se clltsegtle detcobir o qae eshi acontecendo:

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

// muitos c6digos de teste complexos aqui


)

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.

Obietivo poro o Certificog6o

Heranga, E-Um, Tem-Um (Obietivo 5.5 do Exame)

5,5 Desenuolaer aidigo qae inplenente relagdes "d-um" ef ou "tem-um".

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" ) ;
)

Produz esta saida:


they're not equal
t1's an Object
De onde saiu esse m6todo equals? A varilvel de referAncia t1 6 do tipo Test, e nio existe nenhum m6todo
equals na classe Test. Ou existe? O segundo teste if pergunta se E1 6 uma instAncia da classe Object, e pelo
fato de ela ser (falaremos mais sobre isso em breve), o teste i f tem sucesso.
JAVA 5 53

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

class PlayerPiece extends cameshape {


public void movepiece ( ) i
System. out.println ('.moving game piece,, ) ,.

/ / ma:-s c6digo
)

public class Testshapes {


public static void main (String[1 args; {
PlayerPiece shape = new playerpiece ( );
shape. displayShape ( ) ;

shape . movePiece ( ) ;

]
)

Tem como saida:

displaying shape
moving game piece

Repare que a classe


-p.layllspiece herda o m6todo display ( ) gen6rico da classe menos especializada
GameShape, e tamb6m adiciona o seu-pr6prio_m6todo, movePiece ( ) . A reutilizagio de c6digo atrav6s da
heranga.significa que.os m6todos com funcionalidade gen6rica (como display ( ) - que podeiia- se aplicar a
)
uma s6rie de tipos diferentes de formas em um jogg nio precisam ser reimplementadoi. Isio significa que todas
_
as subclasses.especializadas.de GameShape garantidamenie terlo as capaciiades da superclass."*"ir gen6rica.
Voc6.n6o vai querer que seja.necessirio reescrever o c6digo display (j em cada .rtn dor seus componenres
especializados de um jogo online, por exemplo.
Mas disso voce ji sabia. Voc€ ji passou pela dor de enconrrar c6digo duplicado ao f.azer uma modificaqeo em um
lugar e ter de rastrear todos os outros pontos em que exista o mesmo c6digo (ou um muito semelhante).
54 Copitulo 2: OrienfoE6o o obietos

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

class PlayerPiece extends GameShape {


public void movePieceO (
System.out.println ( "moving game piece" ) ;

)
// mais crldio6
vvs4Y

)
class TilePiece extends GameShape {
n"l.'l
yulfre in rzniA
vvfs na|-aAi:nanf
Yeu^sJqeslru\/
1\ I
L

System.out.println("getting adjacent tiles" ) ;

// 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

public class TestShapes {


public static void main (String[] args) {
PlayerPiece player = new PlayerPieceO;
TilePiece tile = new tilePiece ( ) ;
doghapes (player) ;
doshaDes (tile) t
)
public static void do9hapes(Gan€shaDe shape)
shape . displayShape ( ) ;

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

Relacionamentos E-UM e TEM-UM


No exame vocA teri que ser capaz de examinar o c6digo e determinar se ele demonstra um relacionamento E-UVI
ou TEM-UM. As regras sio simples, poftanto, essa deve ser uma das poucas 6reas em que, para responder is
perguntas corretamente, euxs€ nlo ser6 preciso raciocinio.

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.

Subaru 6 a subclasse de Vehicle.

CarherdadeVehicle
Subaruherdade Car
Subaru herda de Vehicle.

Subaru 6 derivado de Car.

Car 6 derivado de Vehicle.

Subaru 6 derivado de Vehicle.


Subaru 6 um subtipo de Car.
Subaru 6 um subtipo de Vehicle.
Voltando ao nosso relacionamento E-uM, as declaraE6es a seguir sio verdadeiras:
56 Copitulo 2: Orientogdo o obietos

"Car (Carro) estende Vehicle (Veiculo)" significa 'Carro E-(JM Veicuk".


"Subaru estende Carro' significa " Sabarv E-(JM Caro".
E tamb6m podemos dizer:
"Subaru E-UU Veiculo" porque a classe seri considerada "um tipo do" item que estiver acima dela em sua irvore
de heranga. Se a expressio (Foo instanceof ear) 6 true, enteo a classe Foo E-UM Bar, mesmo se Foo nio
estender diretamenie Bar, mas, emvez disso, estender alguma outra classe que seja uma subclasse de gar. A
Figura 2-2 ilustra a 6wore de heranga de Vehicle, Car e Subaru. A seta se rnove da subclasse para a superclasse. Em
outras palavras, a seta de urna classe aponta em direglo a classe de onde foi estendida.

Figuro 2-2 Arvore de herongo de Vehicle, Cor e Suboru

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)

A classe Horse tem um Halter, porque Horse declara


uma variivel de instincia do tipo Halter. Quando o
c6digo chama tie( ) em uma instincia de Horse, o
Horse em quest5o chama tie( ) na varidvel de inst6ncia
Halter do obleto Horse.

Figuro 2-3 Relocionomenfo TEM-UM entre Horse e Holter


JAVA 5 57

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

Obletivo poro o CertificoE6o

Polimorfismo (Objetivo 5.2 do Exame)


5.2 Dado am cendrio, desenuoluer aldigo qae demonsile o uso dopolimorfsno. Alin disso, deterrtinar quando a conuersdo senl necerdria e

reconhecer quando os erros sdo de nnpikgdo e quando sdo de i


tenpo de exuugdo n0 que re refere conuersdo de referdncias de objxo:.

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:

class PlayerPiece extends GameShape, Arrimatable t // Niot


// mais c6dica
]
IJma classe nio pode estendermais do que uma classe. Isso significa um parent por classe. lJma classe pode ter mriltiplos
ancestrais,no.itttatrto,,r-avezqueiclasseBpoderiaestenderaclasseA,aclasseCpoderiaestenderaclas_seBeassimpor
diante. Entio, qualquer classe poderia ter mriltiplas classes acima de si na 6rvore de heranga, mas isso nio 6 o mesmo que
dizer que uma classe estende diretamente duas classes.

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

public interface Animatable {


public void animate ( ) ;
)

E eis a classe PlayerPiece modificada para implementar a interface:


class PlayerPiece extends Gameshape implements Animatable
publi-c void movePiece ( ) {
System.ouL.println( "moving game piece" ) ;
)
public void animateo {
qlrcf 6m
rJeuerLrr nrrl. nrifif
vqu.y!rarufll l-
\
jfr-F.l*-
/\r--AIlrlL@LfIrV, ,,\;
)
/t /| ^^:^
Lltal> ^aa:-^
Lvufvv

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)

I Um PlayerPiece (umavez que 6 isso que realmente 6)


I Um Animatabl e (uma vez que Pl ayerP i ece implementa Animat.abl e)
As seguintes sio todas declarag6es legais. Observe com cuidado:
PlayerPiece player = new PlayerPiece ( ) ;
uDJecE.
^Li ^^+ o prayer;
^ -= *1 --.,

Gameshape shape - player;


Animatable mover - player;
56existeumobjetoaqui-umainstAnciadotipoPlayerPiece -mashiquatrotiposdiferentesdevari6veisde
referdncia, todasreferindo,se a um objeto na *&n6.i". teste rapido: quais das variiveis'de refer6ncia acima podem chamar o
m6todo displ-ay ( ) ? Dica: apenas duas das quatro declarag6es podem serusadas para chamar o m6todo display ( ) .
Lembre-se de que as chamadas a m6todos permitidas pelo compilador sio baseadas unicamente no tipo declarado da
referAncia, independentemente do tipo do obj eto.Eitlo,observando os quatro tipos de refer6ncias novamente - obj ect,
GameShape, PlayerPiece e Animatable - quais desses quatro tipos conhecem o m6todo display ( ) ?
VocA adivinhou - e PlayerPiece, como 6 de conhecimento do compilador, t6m um m6todo
as classes GameShape
display (), tipos de refer6ncias pode ser usado para chamar display ( ) . Lembre-se de que,
entio qualquer um desses
para o compilador, um PlayerPiece E-UM GameShape, enteo o compilador diz'estou vendo que o tipo
declarado6 elayereiece e,umavezque PlayerPiece e$endeGameshape,issosignificaque etayerpiece
herdou o m6todo display ( ) . Ponanto, PlayerPiece pode ser usado para chamar o m6todo display ( ) ."

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.

Obletivo poro o CertificoE6o

Sobrescrevendo/ Sobrecarregando (Obietivos 1.5 e 5.4 do


Exame)
/.5 Dado um exemplo de cddigo, detenninar se um mitodo estd sobrescreuendo ou sobrecarregando coretamente outro mitodo, e identifcar
ualoru de retorto udlidos (inclaindo retlrnlr couaiantes) para o mitodo ent questio.

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

Animal b = new Horseo; // Referlncia Animal, mas 6 um objeto Horse,


/ / aL6 aqui. tudo bem
// Falha no tsnpo de execug3,ol

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.

As regras para a sobrescrita de um m6todo sio as seguintes:

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 O niuel de acesso pode ser menos restitiao 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

private void eat ( ) t


System. out.println ( "Generic Animal Eating Generically" ) ;
)

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

/ / C6digo ritil de exibiqdo aqui

]
class Horse ext.ends Animal {
nrrl-r'lic rrnid
wvfu nr.infv^rrra6lf
yrfrrurvq!osr! /\
\/
/I

/ Aproweita-se do c6digo de Animal, depoj-s adici-ona mais c6dioo


/
super.printYourself O,. // Chama a supercfasse
/ / c6digo (Animal)
/,/ Depois volta e realiza
// outros serviqos de exibiqio
// especificos de Horse aqui

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

oBSERVAq6ES pane o EXAME


Se am mitodofor sobreterito, mar anr
ama refeftnciapolinilfica (do sapet'po)para apontarpara o objeto do subtipo com o m1todo
aocd
sobretcritor, o conpiladar arunini que
cbamando a uersdo do ndnio do srpen;po.-Se o aeoAo do supet;po dul)rar uma exnpdo
uocd eshi
uerifcada, mas o mdtoda do subn'po ndo of7.er, o conpilador ainda assim pensani qie uoc6 uni chamando
,nao qae declara ama"excegdo ni
(mais sobre isso no Capit*lo 5). V/anos un exemplo:

class Animal i
public void eat ( ) throws Exception {

/ / Ianea uma Exceqd.o

class Dog2 ext.ends Animal {


public void eatO { //sem Exceq6es }
public static void main(String [] args) t
Animala=newDog2O;
Dog2 d = new Dog2O;
d.eatO;// ok
a.eatO; ll erro de coogilagao -
I / Exceg6,o n6o relatada
)

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

Exemplos de sobrescritas de m6todo v6lidas e nao-vilidas


Examinemos a sobrescrita do m6todo eat ( ) de Animal:
public class Animal {
public void eat O { }
)

A Tabela 2-1 lista exemplos de sobrescrig6es nio-viLlidas Odo m6todo eat ( ) de Animal, dada a verslo anterior da
classe Animal.

Tobelo 2-1 Exemplos de sobrescriE6es ndo-vd/idos

C6digo de subscrigio invSlido Problema no c6digo

privatevoideat( ){l O modificador de acesso 6 mais restritivo

Declara uma excegio verificada nio declarada


public void eat ( ) throws lOException { }
pela versio da superclasse

IJrru sobrecarga vilida, e nio uma subscrigiq


public void eat ( string food) { }
poque a lista de a{gumentos foi aherada

Nio 6 uma subscriglo por causa do tipo de


publicStringeat( ){ } retorno, mas tamb6m nio 6 uma sobrecatga
porque nio h6 afteragio na lista de argumentos

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:

I Os m6todos sobrecarregados deuem alterar a lista de argumentos.


I Os m6todos sobrecarre gados poden alterar o tipo de retorno.
I Os m6todos sobrecarreg adospodem alterar o modificador de acesso.
I Os m6todos sobrecarregado pothm declarar exceg6es verificadas novas ou mais abrangentes.
s

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

public void changeSize(int size, String name) { }


n,,1.r1 .in ini
frrL urrqrtverr!= qize f I^al- naftern) I I
trruurI9 ^h:ndaqizotini- \rlru
public void changeSize(float pattern, String name)

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:

public class Foo {


nrrhl
vuvrrL i c rrni
vvru rl rlnqtrrf
u---e f / i nr rr
r, ctsri
evL-ng S) { }
public void moreThings(int x) { }
]
class Bar extends Foo {
nrrl.r'lin rznid r{nQl-rrff!! f\ frfu
inr y, float s) throws rOException { }
i
VocdpodefcartentadoaconsideraralOExcepLioncomooproblema,a0uerqueomdtodosobrevritodoStuff()ndodeclarou
um1 excegdo e ao saber que a excegdofoi uerifcadapelo compilador. Mas o mitodo doStuf f ( ) ndofoi defotma alguma substcrito! A
-
subclasse Bar o sobrepds, altemando a lista de argumentlr, portanto a excepdo lOExcept.i on i adequada.

Chamando m6todos sobrecarregados


Repare.que ha muito mais a ser dito sobre como o compilador sabe qual m6todo chamar, mas o restante ser6
abordado no^Capjtu1o.3, quando virmos o boxing e os var-args - ambos t6m impacto significativo sobre a
sobrecarga. (Voc6 ainda assim ter6 de prestar atengio na pafte apresentada aqui, no enianto.)

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

// Sobrecarrega o m6todo addThem para adi-cionar doubles em vez de ints


public double addThem(double x, double y) {
return x + y;
)

/ A partir de outra classe, chama o m6todo


/ addThemo
public c1ass TestAdder {
public stat.ic void main (String [] args) {
Adder a = new Adder0;

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

UseAnimals ua = new UseAnimals ( ) ;


Animal animalObj = new animal ( ) ;

Horse horseobj = new HorseO;


ua.doStuff (animalObj ) ;
ua.doStuff (horseObj ) ;
)
)

A saida seri a que voc6 espera:

in the Ani-mal version


in the Horse version
Mas, e se voce usar uma referOncia de Animal a um objeto Horse?
Aninal aninalRefToHorse = new Horse();
ua. doStuf f ( animalRefToHorse ) ;

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.

Polimorfismo em m6todos sobrecarregado e sobrescrito


Como o polimorfismo funciona com m6todos sobrecarregados? Pelo que acabamos de examinar,.nio parece que o
polimorfiimo seimponecom o fato de o m6todosersobrecarregado. Sevodpassarumarefer6nciaaAnimal, o m6todo
iobrecarregado q*^usatrrmobjao Animalser6chamado, mesmo que o objetorealmentepassadotenhasido Horse. Mesmo
queHorse"sejapassado parao m6todo como Animal, ele continuarisendouqobjao Hgrse apesarde o m6todo estar
apera"d" enit"d. Portanto, 6 verdade que o polimorfsmo nio dgtermina qual versio sobrecarregada seri chamada o
polimorfismo enrra em agdo qrr*do a decisio a tomar aborda qual veisio sobrescrita de um m6todo ser6 chamada.
'Por6-, )s vezes u- m6todo 6 sobr.."rregado e sobrescrita. Suponhamos que as classes Animal e Horse fossem
iguais is descritas abaixo:
public class animal {
public void eat ( ) {
System.out.println ( "Generic Animal Eating Generically" ),'
JAVA 5 67
)
public class Horse extends Animal {
public void eat0 {
System. out.println ( ..Horse eating hay .. ) ;
)

yslf
.ia rrniA
nrrh'l re vvfq a:|- tqt-rind c\ II
cqu \uL!frrY o/

System.out.println(..Horse eating \ + s);


)

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.

Iobelo 2-2 Chomodos o rn6fodos e sobrescrifos


C6digo de chamada de m6todo Resultado

Animala=newAnimal( ); a.eat( ); Generic Animal Eating Generically

Horseh=newHorse( ); h.eat( ) Horse eating hay

Hone eating hay O polimorfismo funciona - o tipo do objeto real fttrone), e


Animal ah = new Horse ( ) ; ah. eat ( ) nio o tipo da refedncia (Aninral), 6 usado para determinar que m6todo eat( )
he . eat ( "App1es " ) ; ser6 chamado.

Horse he = new Horse ( )


Hone eating Apples O m6todo eat(String s) sobrecarregado 6 chamado.

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.

Erro do compilador! O compilador conrinuou examinando somenre o tipo da


Animal ah2 = new Horse ( ) ; refer6nciae viu que Animal nio tem um m6todo ea( )qtre use uma srring. O
ah2 . eat ( " carrots " ) ; compilador nlo se preocupou com o fato de quetalvez o objeto real no tempo
de e:<ecugio seja um objeto Hone.

oBSERVAQ6ES pene O EXAME


Ndo se deixe enganar prr uril mitodo que s/a sobruamgado, e ndo robretcrito pnr uma subclatse. E perfeitanente udlido fa7,er o seg,tinte:

public class Foo {


void doStuff0 { }
]
class Bar extends Foo {
void doStuff (String s) { }

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

A Tabela 2-3 resume a diferenga entre m6todos sobrecarregados e sobrescritos.

Iobelo 2-3 Diferengo enlre m6fodos sobrecoregodos e sobrescrifos.

M€todo sobrecarregado M6todo sobrescrito

lista de argumentos Deve ser alterada Nio deve ser alterada


tipo de retorno Pode ser alterado Nio deve ser alterado

Exceg6es Podem ser alteradas Podem ser reduzidas ou eliminadas.


68 Copftulo 2: Orientog6o o obietos
Nio devem ser langadas exceg6es
verificadas novas ou mais abrangentes

Acesso Pode ser aherado Nio deve se tornar mais restritivo (pode
ser menos restritivo)

O tipo do objeto (em otttras palavras, o


Chamadas O tipo da refer6ncia determina
qtre verslo sobrecarregada ti1o da inrfincia real na memtiia)
(baseada nostipos de ser6 selecionado. Isso ocorrer6 a todo
argumentos deilarados) seri instante.
sel-ecionada. O m6todo real a ser
chamado ain&ter6uma
chama&virnral no tempo de
excecu$o, a coincidAncia de
argumentos ji teri sido definida,
s6 faltando a classe real onde o
m6todo reside.

Sobrescrito Sobrecarregado

Tree Tree

showleaves () setFeatures (String name)

Oak Oak

showleaves () setFeatures (String name, int leafSize)


setFeaLures (int leafSize)

Figuro 2-4 Metodos sobrescrifos e sobrecorregodos em relocionomenfos de closses

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.

Obietivo poro o Certificogdo

Conversio de Variiveis de Refer6ncia (Objetivo 5.2 do Exame)


5.2 Dado un centirio, d.esenuoluer aidigo que demonstre o uto do polimorfsno. Al6n disso, deterwinar quando a conuersdo senl necessdna e

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?

Quando tentarmos compilar esse c6digo, o compilador dir6 algo como:


cannot. find slzmbol
O compilador est6 dizendo: 'Ei, a classe Animal nio tem um m6todo playDead () ". Vamos modificar o bloco
de c6digo if:
if (animal instanceof Dos) {
oog d. = (Dog) anirnal; // conwertendo a variSvel de refer6ncia
d.playDeadO;
]
O novo e melhorado bloco de c6digo cont6m uma conversio, que neste caso 6 is vezes chamada de conuersdo
redutora,porque estamos convertendo para baixo na Lrvore de heranga, de uma classe mais geral para uma mais
especifica. Agora, o compilador frcarS, feliz. Antes de tentarmos chamar playDead, n6s convertemos a variivel
do animal para o tipo Dog. O que estamos dizendo ao compilador 6 "sabemos que ela na verdade se refere a um
objeto Dog, entio nio tem problema em criar uma nova vaiiivel de refer6ncia Dog pata apontar para esse objeto".
Neste caso, nos safamos porque, antes de sequer tentarmos a conversio, fazemos um testtinstJnceof para
termos certeza.
E i-pon"ttt. saber que o compilador ser6 forgado a confrar em n6s quando fazemos uma conversio redutora,
mesmo quando fazemos besteira:
class Animal i )
class Dog extends Animal { }
al aac T\aaToct I

public static void main(Stri-ng [] args) t


Animal animal = new Animal ( ) ;
Dog d = (Dog) animal; // corpila, nas falha depois

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:

Animal animal = new Animal ( ) ;

Dogd= (Dogr) animal;


9tring s = (String) aninal; // animal NTNCA poderia E6r urra String
70 Copitulo 2: Orientoglo o obietos

Nesse caso, voc6 receberi um erro parecido com este:


inconvertible tlpes
Ao contr6rio da conversio redutora, a conversio generalizadora (convefter para cima na irvore. de heranga, de um
tipo mais especifico para um mais geral) funciona-implicitamente (ou seja, voc6 nio precisa incluir n_o seg c{digo)
porque q.rando faz ima conversio ge neralizadora, votA esti implicitamente restringindo o nimero de m6todos
que ilode chamar, ao contririo da conversio redutora, o que implica que, mais tarde, voc6 poder6 desejar chamar
um m6todo mais espec{fco. Por exemplo:
^t ^^^
Ll45> n-i*-1
rurrrllal r )
I J

class Dog extends Animal { }

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.

oBSERVAQoES pene O EXAME


Os niadorcs do exame irdo lhe diryr que foran forgadot a eo/ocar toneladas de aldigos em pequeills espapos 'por causa do sistema do exane".
Embora isso t/a potencialmente uerdadeiro, eles TAMBEM gwtam de ser obvums. O aidigo ngainte:

Animala=newDogO;
Dogd= (Dog) a;
: rlnnnacrrrff
s.uvsvvvesr! /\
\ / ,

Pode rcr substituido por e$e, nuito nais jlcil de ler:

Ani-ma1 a = new DogO;


( (Dog) a) .doDogStuff () ;
Neste caso, o conpiladorprecisa de todos esses par€nteses, caso contniio pentari que eshi recebendo ama infuwgdo innmpleta.
JAVA 5 71

etivo poro o CertificoEdo

lmplementando uma Interface (Objetivo 1.2 do exame)


1.2 Desenuolaer cddigo qae declare uma interface...

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:

public class Ball inplenents Bounceable { // palavra-chave.imp]ements'


public void bounce O { }
public void setBounceFactor(int. bf) t ]
)

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

public void bounceO t


/ / a6di an hnrrnna acnaaif
vePevflfvv i an rla Ra:nhpr1 rr I amri
uqur

]
72 Copftvlo 2: OrientoEdo o objetos
public void setBounceFactor(int bf) {
/ / c6digo bounce especifico de BeachBall aqui para definir um fator de bounce

/ / se a classe Ball Liver definido quaisquer m6todos abstract, eles terao de


/ / ser implementados aqui tamb6m.
)

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 {

public void bounceO { } // rmplementa os m6todos de Bounceable


public void setBounceFactor(int bf) { }
JAVA 5 73

publ-ic void movelt O { } // Implementa os m6todos de Moveable

public void doSphericalThingO { } // Implementa os m6todos de Spherical


]
Se a classe Ball n5o conseguir implementar nenhum dos m6todos de Bounceable, Moveable ou Spherical, o
compilador se move{6_para cima e para baixo incontrolavelmente, um pouco envergonhado, at6^que ela o faga.
Isto 6, a menos que Ball.seja marcada.como. abstract. Nesse caso, ela poderia opiar por implementar qualquer
um, todos ou nenhum dos m6todos de qualquer das interfaces, deixandoassim o restante das implem.ttt"g6.ip"r"
uma subclasse concreta de Ball, como descriio abaixo:
abstract class Ball implements Bounceable {
public void bounce0 | ... j / / Define o comportamento de bounce
public void setBounceFactor(int bf ) { ... }
// N6,o implemente o resto,. deixe para Lrma subclasse
)
class SoccerBal-l- extends Ball {
// a classe SoccerBal-l precisa i-mplementar os m6todos da interface gue Ball nao
implemenLou
public void moveTt ( ) { ... }
public void doSphericalThingO { ... }
/ / SoccerBall pode decidir sobrescrever os m6todos de Bounceable
// implementados por Ball
public void bounce ( ) { ... }
I

interface Bounceable
void bounce( ); abstract Ball implements Bounceabl-e
void setBounceFacEor(int bf) ;

/*ndo serSo implementados


em Ball quaisquer m6todos
de Bounceable */
^
I
void beSpherical( ){}

class Tire implements Bounceable class BeachBall exEends Ball


public woid bounce( ) { ) public void bounce( ){ }
public void setBounceFactor (int bf) { } public woid setBounceFactor (int bf) { )

/*beSpherical n5o 6 abstract entao


BeachBall ndo 6 solicitado para
implementar isso */

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.

oBSERVAQ6ES pene O EXAME


Procure utiliqagdes ndo udlidas de exten$u e inplenentapdes. As linhas a seguir mostram exemplos de dulamgdu udlidas e ndo udlidat de
intet'aces e clastes:

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

int.erface Zoo extends Foo { } // Ndo! A interface ndo pode estender


/,/uma cf asse
interface Boo extends Fi { } // OK. A interface pode estender uma
// interface
class Toon extends Foo, Button { } // Ndo! A c-lasse ndo pode estender
/ /miTtiplas cl.asses
cl-ass Zoom implements Fi, Fee { } // OK. A cTasse pode implementar miTtipTas
/ /interfaces
interface Vroom extends fi, Fee { } // OK. A interface pode estender
/ /n67tip7as interf aces

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

Obietivo poro o Certificoc6o

Tipos de retorno v6lidos (Objetivo 1.5 do exame)


|.5 Dado am exemplo de nidigo, deterninar se *m ndtodo estd sobrescreuendo ou sobreean'egando comtamente oahv mitodo, e identifcar
ualoret de retorno adlidos (inc/aindo retomot couariantet) para o mdtodo,
Este objetivo abordari dois aspectos dos tipos de retorno: o que voc6 pode declararcomo um tipo de retorno e o que
pode realment e returnar como um valor. O que pode ou nio ser declarado 6 muito simples, mas tudo depender6 de
voc6 estar sobrescrevendo um m6todo herdado ou simplesmente declarando um novo m6todo (o que inclui os
m6todos sobrecarregados). Examinaremos rapidamente a diferenga entre as regras dos tipos de retorno para
m6todos sobrecarregados e sobrescritos, porque j6 abordamos isso neste capitulo. Entraremos um pouco em uma
6rea nova, no entanto, quando examinarmos os tipos de retorno polim6rficos e as regras para o que 6 ou nio
v 6lido re torn ar realmente.

Declarag6es de tipos de retorno


Esta seglo examinar6 o que voc6 pode declarar como um tipo de retorno, o que depender6 principalmente de
sobrescrever, sobrecarregar ou declarar um novo m6todo.

Tipos de retorno de m6todos sobrecarregados


Lembre-se de que a sobrecarga de m6todos nXo significa muito mais do que a reutilizagdo de nomes. O m6todo
sobrecarregado 6 completamente diferente de qualquer outro m6todo com o mesmo nome. Portanto, se um
m6todo for herdado, mas sobrecarregado em uma classe, voc6 nio estar6 sujeito is restrig6es da sobrescrigio, o que
significa que poderi declarar o tipo de retorno que quiser. O que voc6 niopodef.azer 6 alterar o tipo de retorno.
Para sobrecarregar um m6todo, lembre-se de que uoc€ precisa alterar a lista de atgamentos. O c6digo a seguir mostra um
m6todo sobrecarregado:
publj-c class Foo{
void go0 { }
)
public class Bar extends Foo {

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;

A Sobrescrigio e os Tipos de Retorno; e Retornos Covariantes


9y4o uma.subclasse quiser alterar a implementagio de um m6todo herdado (uma sobrescrigio), ter6 que
definir um m6todo qrre coincida exatanente com a verslo herdada. Ou, a partir do Java 5, voc6 tem a possi-bilidade
de modificar otipo de retorno no m6todo sobrescritor, desde que o novo tipo de i.totno seja um subiipo do tipo
de retorno declarado do m6todo sobrescrito (da superclasse).
Vejamos um retorno covariante em agXo:
public class Foo{
void so0 { }
)
public class Bar extends Foo {
String goO { // sobrescrlgdo v6.1i-da em ,Java 1.5
return nu11;
)
]
Com oJava 5, esse c6digo compilari sern problemas. Se voc6 tentasse compil6Jo usando um compilador 1.4 ou
com o flag source, desta forma:
javac -source 1.4 Beta.java
receberia um erro de compilagio parecido com este:
attempting t.o use incompatible return type
(Falaremos mais sobre os flags do compilador no Capitulo 10.)

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

implicitamente conveftido para o tipo de retorno declarado.


public int foo ( ) {
char c = 'c';
return c; / / char 6 compativel com int
)

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
)

public Object. getObjectO {

int[] nums = {I,2,3};


reLurn nums; // Retorna um array int, que ainda 6 um objeto
]

public interface chewable { }

public class Gum implements Chewable { }

public class TestChewable {

/ / M6Lodo com um tipo de retorno da interface


Chewable getChewable {

return new Gum(); // Retorna o implementador da interface


]
)

oBSERVAQ6ES pRne O EXAME


Procure mdtodos qae dtclarem cono tipo de retomo una clasn abs trac t ou anta interface, e rzemoriry que qaa/quer objeto qae passar
no teste E-UM (erz outras pa/awar, qu/e tiaer como ruultadn lrae no teste com o operador ins t.anceo f ) podeni rcr retomado desse

mdtodo - por exemplo:


public abstract class Animal { }
public class Bear extends animal { }
public class Test {
public Animal go ( ) {
return new Bear (\ ; / / OK, Bear $a!-um/' Animal

]
]
Esse aldigo ini compilar, o ualor de retorno i um subtipo.
JAVA 5 77

Obietivo poro o certifico€6o

Construtores e instanciagio (Objetivos 1.6 e 5.4 do exame)


1.6 Dado um conjanto de claset e saperc/asses, desenuo/uer constmtzrer para uma oa mais das c/asses. Dada uma dukragdo de c/asse,
deterwinar se serri criado am clnrtutzrpadrdo e, em caso afrrtatiuo, determinar o comportamento dcsse construtor. Dada uma listagem dt
c/asse aninhada ou ndo, escreuer aidigo para instanciar a c/asse.

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.

Apectos bisicos do construtor


Toda classe, incluindo as classet abstract, precisa ter um constnrtor. Memorize isso. Mas s6 porque uma classe
precisa ter um constnrtor, nio significa qlre a prugramadorterthaque digit6-lo. lJm construtor tem o formato a
segurr:

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

2. Horse ( ) calls super ()

l. main ( ) calls new Horse ()

Figuro 2-6 Construtores no pi/ho de chomodos

Regras dos construtores


A lista j.g"lf re^sume as que voc6 teri que conhecer para faze.r o exame (e para compreender o restante
" .regras
cesta segao). v oce preasara se lembrar-se delas, portanto, estude-as mars de uma vez.
r Os construtores podem usar qualquer modificador de acesso, inclusive private (um construtor private
significaque somente o c6digo que estiner dentro da pr6pria classe poderi inJtanciar um objeto desse tipo, ionanto, se
a classe do construtor private tor permitir que uma instincia dela seja usada, deve fornecer uma varilvel ou m6todo
static que conceda acesso a uma iistAncia ciiada dentro da classe).
I O nome do construtor deve coincidir com o da classe.
I Os construtores nio devem ter um tipo de retorno.
r E valido (mas inritil) ter um m6todo com o mesmo nome da classe, por6m, isso nio o tornar6 um construtor. Se
houver um tipo de retorno, seri um m6todo em vez de um construtbr. Na verdade, voc6 poderia ter um m6todo e um
construtor com o mesmo nome - o nome da classe - dentro da mesma classe, e isso nlo 6 um problema paraJava.
Cuidado para nlo achar que um m6todo 6 um constnrtor e vice-versa - pro*i. ,.*pre um tipb de retorno.
r Se voc6 nlo inserir um construtor no c6digo de sua classe, um constnrtor padrio seri gerado automaticamente
pelo compilador.
I O construtor padrio ser| sempreum construtor sem argumentos.
I Se voc6 quiser um construtor sem argumentos e tiver inserido algum(n$ outro(s) no c6digo de sua classe, o
compilador nio fornecer6 esse constirtor (ou qualquer outro). Ein outras palavias, se uori"tiaerinseido am
clnthatlr clrt aryt/rlettlr, nZo teni tlm sem argumentli a nenlJ que o insira por conta pnipia!
Todo construtor deve ter como sua primeira instruEXo a chamada a um construtor sobrecarregado (this ( ))
ou ao constnrtor da superclasse (super ( )), mas lembre-se de que essa chamada pode ser inserida pelo
compilador.
Se voc6 inserir um construtor (emvez de ficar esperando pelo construtor padrio gerado pelo compilador) e ndo
digitarachamadaasuper( )ouathis( ),icon?iladirinseini,automaticamente,irztachanadarsuper(') sen
argt/mentos, como a primeira instrugdo do constrvtor.

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

HorseO; // chamando o construt.or - inv6.lidot


]
]

ldentificando se um construtor padrio seri criado


O exemplo a seguir mostra uma classe Horse com dois construtores:
class Horse {
Horse O { }
Horse(String name) { }
)

O compilador inseriri um consrrutor padrio para a classe acima? Nio!


E para uma variagio da classe como a descrita abaixo?
class Horse {
Horse(String name) { }
)

Agora o compilador inseriri um construlor padrlo? Nio!


E para esta classe?

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,

I Ele ndo terd atgumentor.

I Ele incluir6 uma cbamada sem atgamenttt ao constrator da stperclatse (super ( ) ).


80 Copitulo 2: OrientoE6o o obietos

A Tabela 2-4 mostrao que o compilador gerari (ou nio) para sua classe.

Tobelo 24 Codigo do construto r gerodo pelo compilodor

C6digo do closse C6digo do construlor gerodo Pelo


(digitodo por voc6) com pilodor

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 que acontecer6 se o construtor da superclasse tiver argumentos?


Os construtores podem ter argumentos da mesma forma que os m6todos, e se voce tentar chamar um m6todo que
use, digamos, um tipo int, mas nio passar nadaPara ele, o compilador reclamari:
cfass Bar {
class UseBar {
public static void main (String [] arqs) t
Barb=newBarO;
b.takelnt () t / / Tenta chamar wn n6todo takelnto sem argJumentos

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

Anima] (String name) t ]


)

cl-ass Horse extends Animal {


Horse) { (

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 / \
\ /

focation: class Clothing


class TShirt extends Clothing { }

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

j // mas esse construtor ndo existel


Um. riltimo ponto relacionado. a toda essa po.lAmica sobre o construtor padrio (e que provavelmente 6 muito
obvro' mas. temos que mostre-lo ou nos sentiremos culpados por anos), 6 que ar constratores nunca sdo herdados. EIes
nlo sio m6todos. Nio podem ser sobrescritos (porque nio sio m6todos, e s6 os m6todos podem ser sobrescritos).
82 Copitulo 2: Orientog6o o obietos
Poftanro, o(s) tipo(s) de construtor(e$ que sua superclasse_tiver, de maneira alguma determinar6 o tipo de
consrnrtor iia.ao q,r. rro.6 prr*"t acreditam que o construtor padrio de alguma forma
coincidiri ** o "bte.i.'Algrn",
da supercLsse, trot que ter6 (lembre de que o conshtttorpadrd.o i sempre am
"o'rrrt*to,
constrator sem argunento) ou nos usados
"rru*entos
na chamadi ) super ( ) fornecida pelo compilador.
"rgrr*.ntot
Por6m, embora os constnrtores nio possam ser sobrescritos, voc6 j6 viu que eles podem ser sobrecarregados, e

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

3. Animal (Strinq s ) chama super ( ,r

2. Animal ( ) qhama this ( randoml-yChosenNameString)


l.main( ) chama new Animal( )

Figuro 2-7 - Construfores sobrecorregodos no pilho de chomodos


r Linha8 O construtor- sem argumentos chamar6 o constnrtor que o sobrec arrega e usa strings, da mesma
maneira que seria chamado se o c6digo-cliente estivesse executando o comando new para instinciar um
objeto, passando para ele uma string relacionada ao nome. A chamada sobrecarregada nsa a palavra-chave
tJris, empregando-a como se fosse o nome de um m6todo, this ( ) . Portanto, a linha 8 esi6 simplesmente
chamando o constrtrtor da linha 3, passando para ele uma string selecionada aleatoriament , emviz de um
nome escolhido pelo c6digo-cliente.
r Linha 11 Observe que o m6todo makeRandomName ( ) foi marcado com static! Isso porque voc6, ndo
pode chamar um m6todo de instAncia (em outras palavras, nio-static) ou acessar uma vari6vel ie instAncia,
at6 que o constnrtor da superclasse tenha sido exicuta do. E ji
que esse construtor seri chamado a partir do
construtor da linha 3, emvez de usar o da linha 7, alinha 8 s6 poderi empregar um m6todo static
para
gerar o nome. Se quis6ssemos que todos os animais sem nomes especificidos pelo chamador tivessem o
mesmo nome padrXo, digamos, 'Fred", enteo, a linha 8 poderia apresentar thls ( "Fred" ); em vez de
chamar um m6todo que retorne uma string com o nome escolhido aleatoriamente.
r Linha 12 A linha 12 nio tem nada a ver com construtores, mas j6 que estamos todos aqui para aprender... Ela
gera um nfmero aleat6rio entre O e 4.

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.

2. Criamos um array de String (anonimamente - nio atribuimos o array a nada).


3. Recuperamos a string no indice [x] (sendo x o nrimero aleat6rio gerado na linha 12) do array de String
rec6m-criado.
4. Atribuimos a string recuperada no array i variivel de instAncia declarada, nama Poderiamos rer tornado
a leitura mais f6cil se tiv6ssemos escrito apenas:
String [ ] namel.ist = { "F1uf fy", "Fido" , "Rover" , "Spike", ,.ciqi,'} ;

String name = namelist [x] ;


Mys o.ndefc-a a diuersdo?Inserir uma sintaxe incomum (principalmente par^ um c6digo que nio esteja totalmente
relacionado ao cerne da questio) f.az pane do espirito do exame. Nlb fique (ceno, fique assusrado, mas
entAo apenas diga para si mesmo: "Calma", e d€ prosseguimento). "rsustlado

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

Static (Objetivo 1.3 do Exame)


1.3 Desenaoluer nidigo que dulare, inicialiry e use tipos primitiuos, arraJs, entlmr e objetos como uaridueis eshiticas, tle instdncias
e locais.
Aldm disso, usar identifcadores utilidos para nomes de uaritiaeis.

Variiveis e m6todos stat:c


O modificador static
tem um impacto de forma profunda sobre.o comportamento de um m6todo ou variivel que o
trataremos como um conceito inteiramente separado dos outros modificadoies. Para compreender a manerra como um
membrostatic funciona,examinaremosp-rimeiro arazioparausarum. Imaginequeioc6tivesseumaclasseutilit6ria
com um m6todo que sempre fosse executido da mesma mineira; sua rinica"fungio seria retornar, digamos, um
nrimero aleat6rio. Independente de que instAncia da classe execure o m6todo - ile sempre se compoitari '
exatamente da mesma f-orma..Em ouiras palavras, o comporramento do m6todo nio depende do Jstado (',ralor., da
variivel deinsA.ncia) de um objeto. Portanto, por que, entio, voc6 precisa de um objeto, j6 que o m6todo nunca
ser6 especifico da instAncia? Por que nio apenls soii.it"t a pr6pria classe para ."...rt"r'o m6todo?

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.

O c6digo a seguir declara e usa uma vari6vel static de contador:


class Frog {

static int frogCount = 0; // Decl.ara e inicializa a vari6vel static


public Frog0 {
frogfcount += 1; / / Modifica o valor do const.rutor
)
public static void main (String [] args) {
new Frog'O;
new Frog( ) ;
new FrogO;
System.out.println("Frog count is now .. + frogCount);
]
)

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.

oBSERVAQ6ES pene O EXAME


[Jm dos enos maisfreqiientet cometidos porprogramadoru laua iniciantet d tenlar acessar una uarihuel de in$6ncia (o qae ignfrca una
aaiiaelndostatic) apartirdomitodomain( ) (quendotennenhamainfomag1osobrein$incias,prrtantz,ndopodeaeessara
aaiduel). O aidigo a rcgair i um exenpk de acesso inudlido de ama aaidael ndo sLaLic a partir dt um mitodo s tat i c.'

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

nta pnlpria classe.

Acessando yari6yeis e m6todos static


Jriquevoc€nioprecisaterumainstinciaparachamarumm&odostatic ouacessarumavai|velstatic,entio,
iomo chamar6 ou usar6 um membro st;tic? Qual 6 a sintaxe? Sabemos que para um m6todo de instAncia comum, voc6
usaria o operador ponto na refer6ncia a uma instAncia:
nl:ce Frnn I

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.

Vejamos um exemplo de m6todo static redefinido (lembre-se, nio-sobrescritos):


class Animal {
static void doStuff O {
System.out.print ( "a " ) ;

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

Executar esse c6digo produz a seguinte saida:

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
)

Figuro 2-8 Os efeifos de sfolic sobre m6lodos e voriiveis

Obietivo poro o CertificoE6o

Acoplamento e Coesio (Objetivo 5. I do Exame)


5./ Desenao/aeraldigo que inplemente enc@vt/ameato rigido, acoplanntofraco e alta coesio en c/assu, e desmueros benefciot.

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

public float getSalesRate(String region) {


salesRate = new ItoTaxes() .doColorado( ) ; / | oh nAo, de novo
/ / faz c61culos com base na reqiSo
return adjustedSalesRate ;

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

Resumo para a certificagio


N6s comegamos o capitulo discutindo a imponAncia do encapsulamento em um bom pro.ieto orientado a
objetos, e depois falamos sobre como o bom encapsulamento 6 implementado: com vari6veis de instAncias
privadas e com getters e setters priblicos.
Em seguida, abordamos a imponAncia da heranga, para que voc6 pudesse entender a sobrescrigio, a sobrecarga ,o
polimorfismo, a conversio de refer}ncia,os tipos de retorno e os constnrtores'

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

Encapsulamento, relacionamentos E-ut't e TEM-UM (Obietivo 5.1)


E O encapsulamento aluda a ocultar a implementagio por tris de uma interface (ou API)'
tr O c6digo encapsulado fornece dois recursos:
E As vari6veis de instAncia sXo mantidas protegidas (geralmente com o modificador private).
E Os m6todos capturadores e configuradores fornecem acesso a variiveis de insdncia.
E O relacionamento E-Uvt se refere ) heranga.
E O relacionamento n-UU 6 representado pela palavra-chave extends.
E "E-UM", "herda de" e "6 um subtipo de" sio todas express6es equivalentes.

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.

Heranga (Objetivo 5.5)


D A heranga 6 um mecanismo que permite que uma classe seja uma subclasse de outra, e, dessa forma, herdar
variiveis e m6todos da superclasse.
D A heranga 6 um conceiro fundamental, que est6 por tr6s do E-UM, do polimorfismo, da sobrescrigio, da
sobrecarga e da conversio.
fl Todas as classes (exceto obj ect) sio subclasses do tipo obj ect, e, portanto, herdam os m6todos de ob-
i:ats

Polimorfismo (Objetivo 5.2)


E Polimorfismo significa "muitas formas".
U Uma vari|vel de refer6ncia 6 sempre de um s6 tipo imutivel, mas ela pode referir-se a um objeto do subtipo.
E Um mesmo objeto pode ser referido por vari6veis de instAncias de muitos tipos diferentes - desde que elas
sejam do mesmo tipo ou de um supenipo do objeto.
E O tipo da variivel de refer6ncia (nio o tipo do objeto) determina quais m6todos poderlo ser chamados!

E As chamadas polim6rficas a m6todos se aplicam apenas a m6todos de instAncias sobrescritos.

Sobrescrig6o e sobrecarga (Objetivos 1.5 e 5'4)


E Os m6todos podem ser sobrescritos ou sobrecarregados; os construtores podem ser sobrecarregados, mas nio
sobrescritos.
D Os m6todos abstrac L deuerz ser sobrescritos pela primeira subclasse concreta (nio abstract).
O No que diz respeito ao m6todo sobrescritos, o m6todo novo:

E Deve ter a mesma lista de argumentos;


D Deve ter o mesmo tipo de retorno, exceto pelo fato de que, em Java 5, o tipo de retorno pode ser uma
subclasse - isso 6 conhecido como um retorno covariante.

tr Nio deve ter um modificador de acesso mais restritivo;


O Pode ter um modificador de acesso menos restritivo;
tr Nio pode langar exceg6es verificadas novas ou mais abrangentes;
tr Pode langar exceg6es verificadas mais restritivas ou menos abrangentes, ou qualquer excegio nio
verificada.
E Os m6todos f inal nio podem ser sobrescritos.

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.

Conversio de Vari6veis de Refer6ncia (Objetivo 5.2)


E Existem dois tipos de conversio de variiveis de refer6ncia: a conversio redurora e a ampliadora.
E Conversio redutora: se voc6 tiver uma vari|vel de referAncia que aponte para um objeto de um subtipo, poder6
atribui-la a uma vari6vel de refer6ncia do subtipo. Voc€ precisa f^ie, u iconversio explicita p"." iso, I o
resultado 6 que voc6 pode acessar os membros-do subtipb com essa nova vari6vel de referAncia.
0 Conversio ampliadora: voc6 pode atribuir uma vari6vel de referAncia a uma varibvel de referAncia de um
supenipo explicita.ou implicitamente. Essa 6 uma operagio inerentemenre segura porque a atribuigio
restringe as capacidades de acesso da nova variivel.

lmplementando uma Interface (Objetivo 1.2)


fl Quando voc6 implementauma interface, est6 cumprindo o seu contraro.
tr Voc6-implementa uma interface ao sobrescrever apropriada e concretamente todos os m6todos definidos pela
interface.
E Uma mesma classe pode implementar muitas interfaces.

Tipos de Retorno (Objetivo 1.5)


fl Os m6todos sobrecarregados podem modificar os tipos de retornol os m6todos sobrescritos nio podem, exceto
no caso de retornos covariantes.
E Os tipos de retorno de referAncias de objetos podem aceitar nul-L como valor de retorno
D Um array 4 um tipo de retorno vilido para declarar e para retornar como um valor.
E Para m6todos com tipos de retorno primitivos, pode ser retornado qualquer valor que possa ser converrido
implicitamente para o tipo de retorno.
tr Nada pode ser retornado a partir de um void, mas voc€ pode decidir nXo retornar. E permitido que voc6 use
simplesmente return,
em qualquer m6todo com um tipo de retorno void, para inierrornper um m6todo antes da
sua finalizagio. Mas nio 6 possivel retornar nada a panir de um m6todo com um tipo de retorno nio-void.

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.

Construtores e Instanciamento (Objetivos 1.6 e 5.4)


E Nio se pode criar um objeto sem que seja chamado um constnrror.

E Toda superclasse da 6rvore de heranga de um objeto chamari um construtor.


E Toda classe, mesmo as classes abstract, tem pelo menos um construtor.
D Os construtores devem ter o mesmo nome da classe.
E Os constnrtores nio t6m um tipo de retorno. Se houuer,entio, seri simplesmente um m6todo com o mesmo nome
da classe e nio um construtor,
E A execugio do construtor ocorrer6 da maneira a seguir:

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 Os construtores podem usar qualquer modificador de acesso (at6 mesmo private!).


E O compilador criar6 um co nfirutor padraose voc6 nio criar nenhum construtor em sua classe.
E O construt or padrdo 6 wconstrutor sem argumentos com uma chamada tamb6m sem argumentos a super ( ).

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.

D As interfaces nio t6m constnrtores.


B superclasse nlo tiver um construtor sem arg'umentos, vocA_teri que criar um construtor e inserir uma
Se sua
chamada a super ( ) com argumentos que coiniidam com os do construtor da superclasse'
D Os construtores nunca sio herdados, portanto, nXo podem ser sobrescritos.
tr Um constnrtor s6 pode ser chamado diretamente por outro constnrtor (usando uma chamada a super ( ) ou
rhis ( )).
E Quest6es relacionadas com chamadas a this ( ):

tr 56 podem aparecer como a primeira instrugio de um construtor.


O A lista de argumentos determina que construtor sobrecarregado ser6 chamado.
B Os construtores podem chamar outros construtores que podem chamar-ainda ourros eassim por diante;
mas, cedo ou iarde, 6 melhor que un deles chame super ( ) ou a pilha excederi o limite.

O Chamadas a this ( ) e super ( ) ndo poden ficar no mesmo construtor. Voc6 pode ter um ou outro' mas
nunca os dois.

Est6ticos (Objetivo 1.3)


D Use m6todos static para implementar comportamentos que nio sejam afetados pelo estado de quaisquer
instincias.
E Use variiveis static i instAncia - s6 existiri uma
paraarmazonar dados que sejam especificos ) classe, em vez de
static.
c6pia de uma vari6vel
E Todos os membros static pertencem i classe, e nio a uma instAncia.
tr Um m6todo static nio pode acessar uma vari6vel de instincia diretamente.
E Use o operador ponto para acessar membros esteticos, mas lembre-se de que usar uma,variivel de refer6ncia
o op.t"dor na verdade 6 um truque sint6tico, e o compilador substituiri a variivel de referAncia pelo
"om
nome da classe, por exemplo:
d.doStuff O ;
se torna:
Dog.doStuff ( ) ;
E M6todos static nlo podem ser sobrescritos, mas podem ser redefinidos.

Acoplamento e Coesio (Objetivo 5.1)


D O acoplamento refere-se ao nivel em que uma classe conhece ou usa membros de uma outra classe.
fl O acoplamento fraco 6 o estado desejivel para classes bem encapsuladas, que minimizam as referAncias umas is outras e
limitam a extensio do uso da API.
E O acoplamento forte 6 o estado indesejivel de se ter classes que desobedecem is regras do acoplamento fraco.

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

new Clidlets O . flipper ( ) ;


]
]
Qual6 o resultado?
A Flip a Clidlet
B. rlip a Clidder
C rfip a Clidder
Flip a Clidlet
D. rrip a Clidlet
F] in a a] iAA6r

E. A compilagio falha

3. Dado:
public abstract interface Frobnicate { public void twiddle(String s); }

Quais classes slo corretas? (lvlarque todx as corretas)

A. public abstract class Frob implements Frobnicate {


public abstract void twiddle(String s) t ]
]

B. public abstract class Frob implements Frobnicate { }

C. public class Frob extends Frobnicate {


public void twiddle(Integer i) { }

D. public class Frob implements Frobnicate {

public void twiddle(rnteger j-) { }

E. public class Frob implements Frobnicate {


public void twj-dd1e(String i) { }
public void twiddl-e(Integer s) { }
96 Copitulo 2: Orientogoo o obietos

4. Dado:
class Top {
public Top(String s) { System.out.print("8"); }

pubfic class Bottom2 extends Top {


public Bottom2 (String s) { System.out.print("D") ; }

public static void main(String [] args) {


new Bottom2 ( "C" ) ;
System.out.println( " ") ;

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

B. A classe refere-se a um pequeno nfmero de outros objetos.


C O objeto cont6m apenas um pequeno nrimero de vari6veis.

D. O objeto 6 referido atrav6s de uma variivel an6nima, e nio diretamente.


E. Avari6veldereferAncia6declaradaparaumtipodeinterface,enioumaclasse.Aintertacef.orneceumpequenonimero
de m6todos.

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"; }

3. Plant getTlpeO { return this; }


4. )
5. cl-ass Fl-ower extends Plant i
6. // insira o c6digo agui

8. class Tulip extends Flower { }

Quais instrug6es, inseridas na linha 6, irio compilar? (Marque todas as corretas)

,{. Flower getTlpe| { return this; }


B. String getTlpeO { return "this"; }
C.Plant getTypeO { return this; }
D. tulip getTlpe0 { return new Tulip0; }

9. Dado:
1. class Zing {
2. protected Hmpf h;

^1 ^^^ rr'^^- --.f anr{c 7i nn I }


+^ t ufa-D vvuvP YJ---^-

E nl:cc umnf I )

Quais opg6es slo verdadeiras? (Marque todas as corretas)

A. Woop 6-umFlmpf etem-umZing.


B. zingr 6-umWoop etem-umHmpf.
C. Hmpf tem-umWoop eWoop 6-umZingr.
D. Woop tem-umFlmpf eWoop 6-umZing.
98 Copiiulo 2: Orientog6o o obletos
E. zing tem-umFlmpf eZing 6-umWoop.

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

System. out.println (y) ;

])
Qual6 o resultado?
4.6
8.7
c.8
D.9
E. A compilagio falha.
F. SerS langada uma exceglo.

12. Quais afirmativas sao verdadeiras? (Marque todas as corretas)


A A coesio 6o principio da programagio OO mais intimamente associado com o ato de esconder os detalhes da
implementa$o.
B. A coesio 6 o principio da programagio OO mais intimamente associado com o ato de certificar-se de que as classes s6
conhecerlo outras classes atrav6s da" suas APIs.
C A coesXo 6 o principio daprogramaglo OO mais intimamente associado com o ato de certificar-se de que a classe foi
elaborada com um rinico e bem-focado prop6sito.

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)

A. Beagle b2 = (Beagle) dogl;


B. Beagle b3 = (Beagle) dog2;
C. Beagle b4 = dog2;
D. Nenhuma das instrug6es acima irl compilar.

14. Dado o seguinte c6digo,


l-. class X { void do1 O { } }
2. c]ass Y extends X { void do20 { } }
?

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)

2. E estir correta. M6todos f inal nio podem ser sobrescritos.


A, B, C e D estXo incorretas com base no exposto acima. (Objetivo 5.3)

3. B estl correta, uma classe abstract nio precisa implementar quaisquer m6todos de uma interface.

E esti correta, a classe implementa o m6todo da interface e, adicionalmente, sobrecarrega o m6todo


twiddle () .

A esti incorreta porque m6todos abstract nlo t6m corpo.


100 Copitulo 2: OrientoEdo o obietos
C estA incorreta porque as classes implementam interfaces, mas nio as estendem.

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.

A, B, C e D estio incorretas com base no exposto acima. (Objetivo 1.6)

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.

A, B, C e D estio incorretas com base na tese de doutorado acima. (Objetivo 5.1)

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.

B, C, D e E estio incorretas com base no exposto acima. (Objetivo 5.3)

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)

9. D est6 correta, Woop herda um Hmpf de zing.


A, B, C e E estlo incorretas com base no exposto acima. (Objetivo 5.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.

A, B, C, E e F estao incorretas com base no exposto acima. (Objetivo 1.5)

12. A resposta C est6correta.

A refere-se ao encapsulamento, B refere-se ao acoplamento e D refere-se ao polimorfismo. (Objetivo 5.1)

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.

C e D estio incorretas com base no exposto acima (Objetivo 5.2).

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.

A, B e D estio incorretas com base no exposto acima. (Objetivo 5.2)


AtribuiE6es

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

P&R Teste individuol


102 Copftulo 3: AtribuiE6es

Pilha e Heap - Uma Revisio


Para maioria das pessoas, entender os fundamentos sobre a pilha e o heap facilita bastante a comPreensio de t6picos
a
como passage* d.
a o polimorfismo, threads, exceg6es e coleta de lixo. Nesta segio, nos limitaremos a uma
"rg.r*.ntos,esseJt6picos virias vezes ao longo do livro.
visio geral, mas expan&remos
No gerd, as objetos) dos programas emJava residem em um dos dois seguintes lugares
virias partes (m6todos, variiveis e
da riem6ria, a pilha ou o heap. Por agora, nos preocuparemos apenas com tr6s tipos de coisas: varilveis de instAncias,
vari6veis locais e objetos:
I As vari6veis de instAncias e os objetos residem no heap.
r Asvarilveislocaisresidem napilha.
Vejamos um programa emJava, e como os seus diversos pedagos sio criados e mapeados na pilha e no heap:

l-. class Collar { l


2.
3. class Dog {
4. Co11ar c; // vari6vel de instAncia
5. String name; / / vari6vel- de instAncia
6.
7. public static void main(String [] arss) {

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

Figuro 3-l Visto gero/ do pilho e do heop


JAVA 5 IO3
I LinhaT-main ( ) 6colocadonapilha.
r Linha 9 - a variivel de referAncia d 6 criada na pilha, mas ainda nio existe um objeto Dog.
r Linha 10 - um novo objeto oog 6 criado, e6 atribuido i variivel de referAncia d.
I Linha 1 1 - uma c6pia & vari6vel de referAncia d 6 passada para o m6todo go () .

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.

Obietivo poro o certificog6o

Literais, Atribuig6es e Variiveis (Objetivos 1.3 e 7.6 do Exame)


| .3 Desenuo/uer aldigo que dukre, inicialiry e use primitiuos, affaJg enums e objetos romo aaiiaeis static, de in$1ncias e locais. Ahm disn,
asar identifeadores udlidos para nonet de uariiueis.

7,6 Evreaer aidigo qw @kque coffetamente ot operadores @mpiados, incluindo os de atribaigdo (initados a =, *=, -=)...

Valores literais de todos os tipos primitivos


Um literal primitivo 6 simplesmente a representagio do c6digo-fonte dos tipos de dados primitivos - em outras palavras,
um inteiro, umnrlmero de ponto flutuante, umbooleano oucaractere quevoc0 digite enquanto escreveumc6digo. A
seguir, temos exemplos de literais primitivos:
-b' // char literal
42 // inE literal
false // booTean literal
2546789.343 // double literal

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

A execu$o de HexTest produziria a saida abaixo:


x = 1 y = 21,4'1483647 z = -559035650
Nio se deixe enganar por alterag6es nas letras maiusculas de um digito hexadecimal ou do 'x' que o preceder6. 'Tanto
OXCAFE quanto 0xcafe siov6lidos.
Todos esses literais inteiros (octal, decimal e hexadecimal) sio definidos como int por padrXo, mas tamb6m podem ser
especificados como long com a inclusio de um sufixo L ou 1 depois do nrimero:
long jo = 110599L;
long so = 0xFFFFI; // Observe a letra '1' minriscula
Literais de ponto flutuante
Os nrimeros de ponto flutuante slo definidos com um nimero, um simbolo decimal e os outros n{meros que
representam afra$o.

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.

Valores literais para strings


Um literal de strng| arepresentagio do c6digo-fonte para o valor de um objeto String. Por exemplo, abaixo vemos um
exemplo com duas maneiras de representar um literal de string:
Strinq s = "BrII Jov";
System.out.println( "8i11" + ",Joy") ;

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.

Vodpode atribuirumavarilvel primitivausando umvalorliteral ou o resultado deumaexpressio. Examine o c6digo a


segur:
int x = 7; / / aurflqrvqv
/ /
arri1-rrlinin I ifar-1
ffLE!4f

int y = x + 2; // atribuiqdo com uma expressao (incluindo um valor literal)


inL z = x * y; // atribuiqao com uma expressao
O mais imponante a lembrar 6 que um inteiro literal (como 7) 6 sempre implicitamente um tipo int. Se voltarmos ao
Capitulol,vocAlembrar6queotipoint 6umvalorde32bits.Niohaveriproblemasevoceestiveratribuindoumvalor
a uma vari6vel int. ou long, mas, e se estiver arribuindo a uma variivel uyte? Afinal, um dep6sito do tamanho do
tipo fote nlo pode armazenar tantos bits quanto um dep6sito com o tamanho do tipo int. Aqui, as coisas comegam a
ficar estranhas. O c6digo a seguir 6 v6lido,

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:

byte b = 3; // Semproblemas, 3 cabe em um byt.e


byte c = B; / / Sem problemas, 8 cabe em um byte
byted=b+ct / / xeo deveria ter problemas, a soma dos dols bytes
/ / cabe em um tipo de byte

Aultimalinha nio seri compilada!Voc6 veri o erro aseguir:


JAVA5 IO7
TestBytes.java:5: possible loss of precision
found : int
ramli rad. lrrrt-a

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

Conversio de tipos primitivos


A nnuersdopermitirl que vocA transforme valor-es primitivos de um tipo em outro. Examinamos a converslo de tipos
primitivos anteriormente neste capinrlo, na seglo de atribuig6es, mas agora, a discutiremos com mais detalhes. A conversio
de objetos foi abordada no Capitulo 2.

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-^ \

public static void main(String [] argrs) {


int x = 395'7.229; // n5o 6 v61ido
)

]
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

public static void maj-n(String [] arqs) {


long 1 = 56L;
byte b = (byte)1;
System.out.println("The byte is " + b);

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

public static void main(String [] args) {


long 1 = 130L;
byte b = (byte)1;
System.out.println("The byte is " + b);

]
O c6digo ser6 compilado adequadamente, e quando o executarmos, obteremos o resultado a seguir:
O; --.-
tJovd l
ud>Lf119
^-^r --

The byte is -126


Voc€ nio vera um erro de tempo de execugio, mesmo quando o valor que estiver sendo compactado for grande demais para
o tipo. Os bits ) esquerda do 8 inferior simplesmente... desaparecerlo. Como vimos na seglo de atribuig6es, se o bit da
extrema esquerda do tipo byte, por acaso , agora,for t, ele nio far|mais parce do vatorl emvezdisso se tornari o bit de
sinal do novo tipo byte.

Exercicio 3- |

Convertendo tipos primitivos


Crie um tipo de nrimero f loat de qualquer valor e atribua-o a um tipo short usando a converseo.

1. Declare umavariivel f loat: f loat f = 234 .56F;


2.Atribuaotipo float aumtiposhort: short s = (short) f;
Atribuindo nirmeros de ponto flutuante Os nrimeros de ponto flutuante apresentam um compoftamento de
atribuigio um pouco diferente dos tipos inteiros. Primeiro, voc€ precisa saber que todo lberal depontoflutuante d
implicitanenteantipodouble @abit)endoantipofloat.Portanto,oliteral 2.3,porexemplo,6consideradoumtipo
double. Se voc6 tentar atribuir um double a um f loat, o compilador saberi que nio h6 espago suficiente no
cont6iner do tipo float de 32 bits paraarmaenar aprecisXo do tipo double de 64 bits, e ele lhe informarl isso. O
c6digo a seguir parece adequado, mas nio ser6 compilado:
float f = 32.3;
VocApode achar que 32 .3 deveria caber satisfatoriamente emumavari6vel com o tamanho de um tipo f 1oat, mas o
compilador nio permitir6 isso. Para atribuir um literal de ponto flwuante a uma variivel f 1oat, voc6 precisa converter o
valor ou acrescentar um f ao final do literal. As atribuic6es abaixo serlo compiladas:
floatf= (f1oat) 32.3;
fl_oar g -- 32.3f ;
float h = 32.3F:
JAVAs 109
Atribuindo um literal que seia muito grende para avariivel Tamb6m veremos um erro do compilador se renrarmos
atribuir um valor literal que ele saiba que E muito grande para caber em uma va/riryel.
byte a = 1,28; // byte s6 pode armazenar at6 o nirmero \27
O c6digo anterior renrltard nesse effo:
llact- R\rl- aq i:rr: f : h^6ri
.. q. possroJ_e
1-.1 l aa-
^ -Loss or
^f preclsaon
Found : int
required: byte
byte a = t28;
Podemos corrigi-lo com uma conversio:

bvtea= (bYte) 128;


Mas entio qual seri o resultado? Quando vocA compactar um tipo primitivo, aJava simplesmente descartar6 os bits de
ordem superior que nio se enquadrarem. Em outras palavras, ele perder6todos os bits ) esquerda dos que voce estiver
conveftenoo.

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;

System.out,println("a = " + a + "after change to b");

A saida desse programa serA:

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.

Atribuig6es de vari6veis de refer6ncia


VocO pode atributum objeto rec6m-criado aumavariivel de refer€ncia de objeto da maneira abaixo:

Button b = new Button0;


A linha anterior executa tr6s operag6es essenciais:
I Cria uma vari6vel de refer6ncia chamada b, do tipo Button.
I Criaumnovo obieto Button namem6ria.
r Atribui o objeto zutcon rec6mcriado ) vaiivelde referlnciab
Voc6 tamb6m pode atribuir o valor nul1 a uma vari6vel de refer€ncia de objeto, o que significa simplesmente que a
vari6vel nio referenciar6 nenhum obieto:

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:

public class Foo {


nrrlrlin
vglrfv
rzniA AnFnncfrrff
vveLBLL\/ /\ Ir

)
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

x++, / / n5o compilar6, x 6 uma wari6.ve1 de .instAncia,

]
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

de go ( ) anteriormente declaradas estio de volta ao escopo. Por exemplo:


class ScopeErrors {
pubfic static void main(Strj-ng [] args) {

ScopeErrors s = new ScopeErrorsOi


s.go();
)
rrniA
wvls an/\
Yv \ / IL

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

oBSERVAQ6ES pnne o E)GME


Tenba um caidado eEecial cum efflr de escEo de blocos de aidigo. Vocd podeni ai-los em swiLches, try- catctres, e em :.oops
for, do rwhife.

Usando uma vari6vel ou elemento de array que neo tenha sido


inicializado e atribuido
A linguagemJavanos fornece aop$o de inicializarumavari6veldeclarada oudeix6-lasem serinicializa<la. Quandotentarmos
usmalaiive[nloncialuadarpoderemos obterumcomportamento diferente dependendo dotrpo devariivel ou arraycom o
qual estivermos lidando (primitivos ou de objeto). O comportamjntg tamb6m depender6 d9 niyel (eryopo) no qual
estivermos declarando nossa variivel. Um a umhfunl de inrt4ncia6 declarada dentro da classe, por6m, fora de qualquer m6todo ou
con$ruror, en qtrxnotmauarititvl bca/6declaradadentro de um m6todo (ou na lista de argumentos do m6todo).
As vari6veis locais, )s vezes, sio chamadas de variiveis de pilha, tempor6rias, autom6ticas ou de m6todo, mas as regras
aplicadas a elas serio as mesmas, independente do nome dado. Embora possamos deixar umavari6vel local nXo inicializada,
o compilador reclamar6 se voc6 tentar usar uma vari6vel local antes de inicializ6la com um valor, como veremos em breve.
JAVA5 I13
Variiveis de instincia de tipo primitivo e de objeto
As umidueis de instdncia (tarnb|mchamadas de vari6veis membros) sio vari6veis definidas no nivel da classe. Isso significa que
a declaragio da variivel rrio 6feita dentro de um m6todo, construtor ou qualquer outro bloco incializador. As vari-6veis de
instAncia sio incializadas com um valor padrio sempre que uma nova instAniia 6 criada, embora possam receber um valor
explicito depois de os superconstrutorei do objeto ierem fin ahzado o seu trabalho. A Tabela 3-i lista os valores padrio para
os tipos primitivo e de objeto.

Vari6veis de instincia primitivas


No exemplo a seguir, ointeiro year 6 definido como um membro da classe, pois esti dentro das chaves iniciais dessa
classe e nio nas chaves de um m6todo:
public class BirthDate {
int year,' / / Yari6vel de instdncia
public staLic void main(String [] args) {
BirthDate bd = new BirthDate ( ) ;
bd. showYear O ;
)
public void showYearO {
System. out.println ( "The year is
]
)

Quando o programa for iniciado, atribuir6 o valor zero avari|vellear, o vaior padrXo para variiveis de instAncia primitivas
relacionadas a nfmeros.

Iobelo 3-l Vqlores podrdo de tipos primifivos e de refer6ncio

Tipo de variivel Valorpadrio

Vari6vel de refer6nciade obieto nu11 (nio faz refertncia anenhum objeto)


byte, short, int, long
float, double 0.0
boolean €-f
!4Abe ^^

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.

Vari6veis de instincia de refer6ncia a obietos


Quando comparadas com as vari6veis primitivas nio inicializadas,uvari|veis de referdncia de obieto nio inicializadas
representam uma hist6ria completamente diferente. Examinemos o c6digo abaixo:
public class Book {
private String title; / / vari6,ve1 de referGncia de instAncia
nrrtrl ic (t-rina nal-rFit- urs
l6/\ \ / II
Ysurf
return t.it1e;
1

public static void main(String [] args) {


Book b = new Booko;
System.out.println("The title is .. + b.getTitleO );
]
I I4 Copitulo 3: AtribuiE6es
Esse c6digo seri compilado adequadamente. Quando o executarmos, o resultado seri:
The title is nu1l
A variivel title nio foi explicitamente inicializada com a atribuigio de uma string, portanto, o valor da
variivel de instAncia ser6 nuII.
Lembre-se de que nu11 nio 6 o mesmo que uma stringvazia (""). IJm valor
nu1l significa que a variivel de referdncia nao foi atribuida a nenhum objeto da pilha. Sendo assim, a alteragio
abaixo no c6digo da classe Book apresentari problemast
public class Book {
private String title; / / vari6vel de refer6ncia de instAncia
public String getTitle ( { )

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
)

Quando tentarmos executar a classe Book, a JVM produzirS, o erro a seguir:


Exception in thread "main" java. lang.NullPointerException
at Book.main (Book. j avaz !2
Recebemos esse erro porque a variivel de referAncia nio esti apontando (referenciandg) para um objeto. Podemos
verificar se urn objeto foi irstanciado com o uso da palavrachave null, como o c6digo revisado abaixo demonstra:
public class Book {
private String title, / / vari6vel de refer6ncia de instAncia
public String getTitle( ) {
r6t-11rh t i t- l a '

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

Vari6veis de instincia de array


O array 6 um objeto; portanto, uma vari6vel de instAncia de array que for declarada, mas nio explicitamente
inicializada,teri'o valor nu11, exatamente como qualquer outra variilelde instAncia de referAncia a objeto.
Por6m, se o array forinicializado, o que acontecer6 aos elementos contidos nele? Todos os elementos do array
receberio seus valores padrio - os mesmos valores padrio que os elementos desse tipo recebem quando sio
variiveis de instAncia. Conclusio: Os elementos do analt receberio iemPre sempre nnpre uakret padrdo, independente de onde o
pnlpio aral for dularado oa in$anciado.

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.

Tipos primitiyos e obietos locais (de pilha, autom6ticos)


As vari6veis locais sio definidas dentro de um m6todo, o que tamb6m inclui os parAmetros desse m6todo.

OBSERVAQ6ES pene O EJGME


'Automdtico" i apenas niltrr tennl para "aariduel local". Ndo :igntfca qrc um ualor d atribuido automaticanente a uaritluel automdtica! O
oposto 6 qae d uerdadeiro; um ualor deue rcr atribuido a uma uai&uel automitica no cddigo; do contnlrio, o conpilador reclamani.

Tipos primitivos locais


No simulador de viagem no tempo a seguir, o inteiro year 6 definido como uma vari6vel autom6tica, porque esr6 dentro
das chaves de um m6todo.
public class TimeTravel {
public static void maj-n(String [] args) t
int year = 2050;
System.out.println("The year is .' + year),.

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

public c]ass Testlocal {


public static void main(String [] args) {
l-nt x/'
if (arqs [0] l= nu11l { //suponhamos que voc) soubesse que este resuitado seja
<amore Erue
x ='J; / / o compilador ndo poderd informar se esta instrugdo ser1. executada
)
inf
LLLv ar
t --
v'
^t
// o compilador ter5 problemas agui

O cddigo antenorprodu{nl o ero abaixo, qaando uoc€ tentar compi/6-/o:

Testl,ocal.java:8: variable x might not have been initialized


Por causa do problena do conpilador ndo poder infomar com cerieqa, em algamat situagdes uoci ter,i que inicialiTar saa uaiduelfora do bloco
condiriona/, cpenat para deixar o conpilador satisfeito, Voci sabe porque isso d importante seji uiu o adesiuo de pdra-cboqae: "puando o

compilador n1o eshi mtisfeito, ninguin ufli".

Refer6ncias de Objetos locais


Tamb6m as referdncias dos objetos se compoftam de maneira diferente quando declaradas dentro de um m6todo em vez de
como var-i6veis de instAncia. Nas refer6ncias a objetos em variiveis de instAncia, voc6 pode ter bons resultados, deixando a
refer6ncianio ffigializada, contanto que o c6digoverifique realrnente se elanio 6 nul1antes deus6-la. Lembre-se de que
para o compilador, nu11 /um valor. Voc6 nlo pode usar o operadorponto emuma referAncia nu1l, porque-ni9 hquer,i
um objeto im sua outra extremidade, mas o*i n|trAocianuLl ndo i o mesmo que una referdncia ndo inicialiqada. ReferAncias
declaradas localmente n5o poderio apresentar bons resultados quando um valor nullfor procurado antes do uso, a menos
quevoc6 inicialize explicitamente avariivel local com nul1. O compilador reclamarido c6digo a seguir:
'i mnor1- i arza rrl- -i 1. . Date;
public class TimeTravel- {
public static void maj-n(String [] args) {

Date date;
iF (Aaf a == nrrl I I

System.out.println( "date is nu11" ) ;

]
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:

Date date = nufl . / / canFi ^1,r^ avcficitamente a vari6vel de referancia 1oca1


// com nul-]"

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.

Atribuindo uma variivel de refer6ncia a outra


Com relagio as vari6veis primitivas, aatribuigig de gma variivel a outra significa que o conterido (padr6es de bits) de uma
vari6vel seri copiado em outra variivel. As vari6veis de refer6ncia de objeto-funcionam ex"t"*.nte-cla m.sma maneira. O
conterido de uma vari6vel de referAncia 6 um pa&lo de bits, portanto, se voc6 atribuir a vari6vel de referAncia a ) variivel de
refer6ncia b, o padrlo de bits de a seri copiado e a nova c6pia seri inserida em b. Se atribuirmos a instAncia existente de um
objeto auma novavariivel de referOncia, entio, duasvari6veis de refer6nciaarmazenarioo mesmo padrio de bits -um
padrlo de bits referenciando um objeto especifico da mem6ria. Examine o c6digo a seguir:
i **^*!
rlrryvr u IJ4vq.
---- -- -- f)i mon<.i nn
dwL .

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,
-

Srrsl-cm 6ttf nr.irf'lh/\r-


uJuuerLLtvuu.y!frlLrrr\ L^.i-L+
a.rrcr9lrL tr +: hoinlrt
, q.rrsfvrrL r
-- I

"after change to b" ) ;

]
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

Svstem orrf nri nl- l n 1"\/


\ J
qtri nn = \\ +' \/l
ru!+lry J I t'
-
'18
I Copftulo 3: AtribuiE6es
x = x + " Bean"i / Agora, o objeto foi alterado
/ com o uso da
/ /referlncia a x
System.out.println("y string = " + y);

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

Poftanto, quando vod escrever,


1. Strind s = *Fred";
2. String t = s, // Agora, t e s referenciam o mesmo objeto String
3. t.touppercase0; / / Chama um m6todo String que altera o objeto String
na verdade, neo ter6 alterado o objeto String original criado na linha 1. Quando a execugio da linha 2 for conclui&' tanto t
quanto s referenciarXo o mesmo objeto Stiing. Mas quando a linha 3 for executadao em vez de alterar o objeto referengia{9
t
por (que 6 o rinico objeto String at6 esse mo-.trto),.tm novo objeto String seri criado. E, em seguida, abandol{tg Ji.
que o n&o objeto String nio 6 atribuido a uma variivel String, esse objeto rec6m-criado (que armazena a string "FRED") 6
eiquecido. Portanto, embora dois objetos String tenham sido criados no c6digo anterior, somente um ser6 realmente
referenciado e tanto t quanto s o referenciario. O comportamento das strings 6 extremamente importante no exame, de
modo que o abordaremos com muito mais detalhes no Capitulo 6.

Obietivo poro o Certificog6o

Passando variiveis para m6todos (Obietivo 7.3 do exame)


7.3 Detenninar o efeito nbre as refer€ncias dc olxos e sobre os ualoru pimitiuos quando eles sdo passados a mdtodot que realilam atribuipdes
oa niltras operagdu de nodtftagdo nos parimetros.

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.

Passando variiveis de referGncia de objeto


Quando voc€ passar uma vari6vel de objeto para um m6todo, teri que se lembrar que estar6 passando a r{edncia ao objeto e
nio o pr6prio o@eto.I-embrese de que uma vari6vel de refer6ncia cont6m bits que representam (para o VM subjacente) uma
rn*rit" d. um objeto na mim6ria (no heap). O mais imponante que voc€ precisa lembrar 6 que nio estari
".essar
passando nem mesmo a variivel de refer6ncia real, mas, emvez disso, uma c6pia dos bits dessa vari|vel, P.ortanto'
qnando passar uma variivel de refer€ncia, estar6 passando wa alpia dos bits que representam como um objeto
eipecifico pode ser acessado. Em outras palavras, tanto o m6todo chamador quanto o chamado agora terio c6pias
id6nticas da refer6ncia e, portanto, referenciario exatamente o mesmo objeto (e nio uma c6pia) na mem6ria.

Nesse exemplo, usaremos a classe Dimension do pacote java.a:wt:


JAVA 5 I'I9
f . import java.awt. Dimension;
2. class ReferenceTest {
3. public static void main (String [] args) {
4. Di-mension d = new Dimension(5,10) ;
5, ReferenceTest. rt = new ReferenceTest ( ) ;
6. System.out.println("Before modifyO d.height = " + d.height);
7. rt.modify(d) ;
8. System.out.println("After modifyO d.height - " + d.height);
f. i
10. void modify(Dimension din) {
1-1. dim.height = dim.height + 1;
1,2. System.out.println("dim = " + dim.height) ;
l-3. )
14.j
Quando executarmos essa classe, poderemos ver que o m6todo modi fy ( ) realmenre conseguiu alterar o objeto
Dimension originat (e rinico) ciado nahrta4.
C:\ Java Pro j ec ts \Re f erence> j ava Ref erenceTes t
Raf^r6 mndi€rz/\ r{ haia}rf
srrlsrvrrL 1A
fv
\/ --

dim = 11

After modifyO d.height = 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.

A linguagem faya usa a semantica de passagem por valor?


Se alinguagemJavapassaobjetos usando avariivel de refer6ncia, isso significa queempregaaparsagempnrrcfefinciano que
da resryito a objetos? N5o exatamente, embora seja comum ouvirmos falar e vermos em livros que ela fazisso. Na
verdade, elapassanlpor aakr todas xvariiveis que forem executadas dentro do mesmo VM. Passar por valor significa passar
por valor da uai,luel. E isso quer di zer, pa$arpnr aipia da uaiiuel (eis apalavra "c6pia" novamente) !
Nio. faz diferenga se voce est6 passando vari6veis primitivas ou de refer6ncia, sempre estari passando uma c6pia dos bits da
vari6vel. Portanto, no que diz respeito a uma variivel primitiva, vocO estari passando uma c6pia dos bits qrr. i.pr.s.nt"m o
valor. Por exemplo, se vocd passar uma vari6vel int
de valor 3, estari passando um a adpia dosbitsque representam 3.
Assim, o m6todo chamado obteri sua propria c6pia do valor, para fazer com ela o que quiser.

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!

Passando vari6veis primitiyas


Examinemos o que acontece quando uma vari6vel primitiva 6 passada para um m6todo:

class ReferenceTest {
public static void maj-n (String [] args) {

int a = l-;
ReferenceTest rt = new ReferenceTest ( ) ;

System.out.println("Before modifyO a = " + a);


rF mnr{ i frz /\a);
r*..,.-*--f

System.out.printl-n("After modifyO a = " + a) ;


]
void modify(int number) {
number=number+1;
System.out.println("number * " + number);
r

Nesse programa simples, avariivel a


6 passada para um m6todo chamado modify ( ) , que a aumentari em
uma unidade. A saida resultante teri este formaro:
Refnremndifvll rllvgf !J \ , a=l
number = 2

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

public static void main (String [] args) {

Foo f = new FooO;


System.out.println("size - " + size);
changelt (size) ;

System.out.println("size after changeft 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 {

Bar myBar = new Bar ( ) ;


void changelt(Bar myBar) {

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);
]

public static void main (String [] arqs) {


Foo f = new t'ooo;
System.out.println("f .myBar.barNum is " + f .myBar.barNum) ;

changelt (f.myBar) ;

System.out.println("myBar.barNum after changelt is " + f .myBar.barNum) ;

O c6digo anterior exibir6 isto:


f.myBar.barNum is 28
myBar.barNum in changelt is 99
122 Copftulo 3: AtribuiE6es

myBar.barNum in changelt is now 420


f.myBar.barNum after changelt is 99
Como voc€ pode ver, a variLvel de sombreamento (o parAmetro local myBar de changel t ( ) ) ainda po der5. afetar a variivel &
instAncia myear, porque o parlmetro myBar receberl uma refer6ncia ao mesmo objeto Bar. Por6m, quando ) vari6vel local myBar
for atribuido um novo objeto Bar, que em seguida modificaremos alterando seu valor barNum, avariivel de instAncia myear origi-
nal de Foo permanecerl intocada.

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:

I Como criarumavariivel de nfunciade xray (declaraio)


r Como criar um ofrxo de array (consrugXo)
I Comoprymcheroarraycomelementos (inicializagXo)

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.

Declarando um array de tipos primitivos


int[] key; // Colchetes anLes do nome (recomendado)
int key []; /,/ Colchet.es depois do nome (v61ido, mas menos legivel)
Declarando um array que referencie objetos

Threadl] threads; // Recomendado


Thread threads []; // v6Lido, mas menos legivel
Quando declanr avanivelde refer6ncia de um affry, insira sempre os colchetes do array imediammente ap6s o tipo
declarado, em vez de depois do identificador (nome da variivel). Dessa forma, qualquer pessoa que ler o c6digo pod."6
perceber que, por exemplo, key 6 uma variivel de referAncia do objao de array int e nio um tipo primitivo int.

Tamb6m podemos declarar arrays multidimensionais, que, na verdade, sio arrays com outros arrays
armazenados. Isso pode ser feito da maneira a seguir:

Stringtl tl tl occupantName,' // recomendado


String[] ManagerName []; // feio, mas v61ido
JAVAs I23
O primeiro.exemplo 6um_array tridimensional (um aray com outros arrays tamMm alrrrra?.Enrerrdo arrays) e o segundo 6
um-array bidime-rsional. Observe que no segtndo exemplo, temos um colchete antes do nome davariivei eum delois. Isso 6
perfeitamente v6lido para o compilador, o que prova mais vnavez que fipaque,t t,t/ida nao signfu que 6 eio.

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

Construindo arrays unidimensionais


A maneira mais-simples de construir um array 6 usar a palavra-chave new seguida pelo tipo do array, com
colchetes. especi{icando quantos elementos desse tipo o array armazenarS.A seguiriemos um exemplo da
construgio de um array de tipo int:
int[] testscores; / / Declara o array de tipo int
testscores = new int[4]; //constr6i um array e o atribui a vari6vel testscores
O c6digo anterior insere um novo objeto na pilha - um objeto de array contendo quatro elementos - com cada
elemento contendo um tipo int de valor padrio igual a 0. Considere esse c6digo como se ele dissesse ao
comPjlaior: "Crie na pilha um objeto de array que armazenar6 quatro tipos inJ primitivos e atribua-o i vari|vel
de refer6ncia declarada anteriormente chamada Lestscore=. E ..tq.t".rt o fizer isso, aproveite paraconfigurar
cada elemento int com zero. Obrigado". (O compilador aprecia boas maneiras). A Figura 3-2 mostra como o
array testscores aparecer| na pilha, depois da construglo.

varidvel de
refer€ncia do
array int[ ]

FFT;T;I
0123
Valores

Indices

Figuro 3-2 - Um orroy unidimensiono/ no pilho


Voc6 tamb6m pode declarar e construir lma arc^y em uma instrugio como vemos abaixo:
int[] testscores = new int[4];
Essa instrugXo individual produz o mesmo resultado das duas instrug6es anteriores. os arrays de tipo de objeto
podem ser construidos da mesma maneira:
Thread[] threads = new Threadt5l;
O ponto chave a lembrar aqui 6 que - apesar da apar6ncia do c6digo - o constratorTbread ndo eshl sendo chanado. Nio
estamoscriandoumainstdnciadeThread,mas,emvezdisso,umrinico objetodearEThread.Depois&inclusXodas
instrug6es anteriores, aindanio haver6, realmente, objetos Thread!

oBSERVAQAO pene O EXAME


Contidere cuidadoumente qilantts objetos estardo napilha, dtpois que uma instrugdo ou bloco do aidigofor exuutado, No exame seri
esperado que uoci taiba, por exenpk, qae o aidigo anteriorpmduq@enas m objxo (o aral atribuido a uaiiuel de refer€ncia cbamada
124 Copitulo 3: AtribuiE6es
thread). O ilnico objeto referenciadopor threafu contim cinco uaridaeis de referinciaTbread, mas nenbum objetoTbreadfoi criado ou
atribaido a essas uaridueis de referincia.

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:

int[] carlist = new int[]; // Ndo serii compilado, precisa de um tamanho

Portanto, nlo o faga, e se voce ver isso no teste, nio hesite em marcar a resPosta "A compilagio falhar| '

oBSERVAQAO pene O EXAME


Voc€ pode uer as palauras conslrair, criar e instanciar usadas alternadamente. Todas elas signficam: 'Un objeto rcrd construido e inseido na

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.

Construindo arrays multidimensionais


fumbre,se de que os arrays multidimensionais sio simplesmente arrays com outros arrays. Portanto, um array
bidimensioni de tipo int, na verdade, seri um objeio com o tipo de array int (int I I ), em que cada elemento
desse array fari uma referAnci a a outro array int. A segunda dimensio arm azenerL ostipos primitivos int reais. O
c6digo a seguir declara e constr6i um array bidimensional de tipo int:

inttl[] ratings = new j-ntt3l tl;


Observe que apenas os primeiros colchetes possuem um tamanho. Isso 6 aceitivel em Java, i6 que a JVM precisa
saber somente o tamanho do obieto atribuido avariivel ratings.

objeto do array int[ ]

array 2-D int[ ][]


vari6vel de refer6ncia (do
array 2-D) de int[ ] [ ]

A figura demonstra o resultado do seguinte c6digo:


intt l[ ] rnyArray = new inti3lt 1;
rnyArraylO] = new intt2l;
myArray[0] [0] = 6;
myArray[0] t]-l = 7;
myArrayll] = new intt3l;
mYArraYlll I0l = 9;
rnyArray [1] l1l = 8;
mYArraY[1] [2] = 5;

A Figuro 3-3 mostro como um orroy int bidimensionol funciono no pilho.


JAVA 5 I25
Inicializando um array
lniciel i"x1' qn array significa inserir itens n ele. Os iterc (Srorque, sim, esse /um rermo t6cnico) do array sio seus elemenros,
osquaispoderioservaloresprimitivos(2,'x',fa1se eoutros)ouobjetoscitadospelasvariiveisderefer€niradoarray.
Se voc6 tiver um array de objetos (e nXo de tipos primitivos), na verdade , ele nilo armaTenar,ios objetos, exatamente como
nenhuma outra vari6vel que nio seja primitiva, nunca cont6m realmente o ofiea, mas, em vez disso, armazenavma r{er€ncia
a ele. Por6m, nos referimos a arrays como, por exemplo, "um array de cinco strinp", embora isso, na realidade, signifique,
"um array de crnco refer€nciat a objetos String". Portanto, a grande pergunta p"srJa ser s. essas refer6ncias estio riesm^o ou
nlo apontando (opa, issodJava, q-ueremos drzer refercnciando) pariobjetos Siring reais ou se sio simplesmente null.
Lembre-se de que uma referAncia ) qual nio tenha sido atribuido um objeto seri uma refer6ncia nuil. E se voc6 tentar
usar essa referOncia nu11, digamos, aplicando o operador ponto para chamar um m6todo com ela, receber6 a detestivel
exceglo Nu1 1 PointerExcept i on .

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:

Animal [] pets = new Animal[3];


Temos_um objeto de array na pilha, com tr6s refer6ncias nu11 do tipo Animal, mas ainda nio temos nenhum objeto
Animal. A pr6xima etapaser6 criar alguns objetos Animal e atribuir a eles posig6es de indice no array relerenciado por
peES:
pets[0] = new Animalo;
Pets [1] = new animal ( ) ;
Pets [2] = new Animal O ;
Esse c6digo insere tr6s novos objetos Animal napilha e os atribui atrAs posig6es (elementos) de indice do arraypets.

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.

int[] x = new int[5];


x[4] = 2; / / OX, o riltimo elemento est6 no indice 4
x[5] = 3; // Exceqd.o de tempo de execuqSo. Nao h5. nenhum elemento no indice 5!

int [] z = new int[2];


int Y = -3'
zlyl = 4; / / ExceqSo de tempo de execugSo. y 6 um nfmero negativo
F las poden ser dfrceis de loca/iqar em um kop complexo, mas ese seri o momentr mais prouiuel em que suryirdo problemas con os indiees
dos anals de perguntas do exame.

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

for (int x = 0; x < myDoqs.length; x++) {


myDogslx] = new DogO; // aErlbui um novo elemento Dog a posigSo de indice x
)

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

Declarando, construindo e incializando em uma linha


VocA pode usar dois atalhos de sintaxe especificos de arrays tant o para ainciahza$o (atribuir valores especificos aos
elementos de um array) quanto para a construgio (instanciar o proprio objeto de array) em uma rinica instru$o. O primeiro
ser6 usado para declarar, criar e inicializar, usando uma instrugeo como a seguinte:
f. int x = 9;
2. ing[] dots = {6,x,8};
A linha2 do c6digo anterior executa qlrdro operag6es:
I Declara uma vari6vel de refer6ncia ao array int chamada dots.
I Cria um array int de tamanho igual a tr6s (tr6s elementos).
I Atribui aos elementos os valores 6,9 e 8.
I Atribui o novo objeto de array ) vari6vel de refer6ncia dots.
O tamanho (extensio do array) 6 determinado pela quantidade de itens separados por virgulas entre as chaves. O c6digo 6
funcionalmente equivalente ao mais longo descrito a seguir:
int[] dots;
dots = new int[3];
intx=9;
dots[0] = 6;
dots[1] = x;
dots[2] = B;
Issotraz apergunta: "Por que algu6musaria aformamais longa?" Uma razXo vem )mente. VocA pode nio saber- no
momeruo em q.r. .rr", o ,ir"y --os ,ralores que serlo atribuidos aos elementos. 56 esse atalho de array vale o prego deste
livro (bem, isso combinado com amaravilhosa apresentagio).
Com refer6ncias a objetos em vez de tipos primitivos, ele funcionar6 da mesma maneira:
Dog PUPPY = new Dog("Frodo");
Dog[] myDogs = {PuPtry, new Dog("Clover"), new oog("Aiko")};
O c6digo anterior cria o array Dog, referenciado pela variivel myDogts, com um tamanho de tr6s elementos. Ele atribui o
objeto Dog criado anteriormente (atribuido ) vari6vel de referAncia puppy) ao primeiro elemento do array e tamb6m cria
dois novoJobjetos Dog ("clover" e "Aiko") atribuindo as duas instAncias rec6m-criadas aos dois riltimos elementos
&variivel de referAnciaDog, do arraymyDogs. AFigura 34 mostrao resultado.
Vodtamb6mpode usarasintaxe de atalho com arrays mukidimensionais, como nalinhaabaixo:
inttl [] scores = {{5,2,4,1}, {9,2}, t3,4}};
O c6digo anterior cria um total de quatro objetos na pilha- Primeiro, um array contendo arrays int 6 construido (o
objao {ue ser6 atribuido ) variivel de refer€ncia scores). O array scores tem um tamanho igual a tr€s, derivado da
q"."tid.d" de itens (separados por virgula) entre as chaves externas. Cada um dos tr& elementos doarray scores 6 uma
v,iriivel que faz refeiOncia a um-array in{ portanto, os tr6s arrays int foram constnldos e atribuidos aos ffes elementos
do affay scores.
JAVA 5 I27

vori6vel de
re{er6ncio do orroy oog [ ]

A figuro demonstro o resuhodo do c6digo seguinfe:

Dog PtrBtrY = new Dog("Frodo');


OoSt I myDegs * ipuppy, nsw Dsq('Clover,lr rsr. Oog{'Aiko"}};
Quofro obielos s6o criodos:
1 objeto Dog referenciodo por puppy e por myDogs ( 0 )

i orroyde Dog [ ] re{erenciodo pornyDogs

2 obieios Dog re{erenciodos pormyDoss [1 ]e myDoss [ 2 ]


Figuro 3-4 - Declorqndo, construindo
e iniciqlizondo um arroy de obletos
O tamanho de cada um dos tr6s arrays int 6 derivado da quantidade de itens dentro das chaves internas
corresPondentes. Por exemplo, o primeiro array tem um tamanho igual a quatro, o segundo array 6 igual a dois e o
terceiro tamb6m 6 igual a dois. At6 agora, temos quatro objetos: um array contendo arrays int (cadi elemenro 6 uma
referAncia a umar:rey int) e tr6s arrays int (cada elemento dos tr& arrays int 6 um valor int). Para concluir, os tr6s
arrays int foram inicializados com os valores int reais das chaves internas. Portanto, o primeiro array int cont6m
os valores 5, 2 ,4 e7 . O c6drso a seguir mostra os valores de alguns dos elementos desse ariay bidimensional:

scores t}l / / um array de quatro ints


scores 1Ll / / Lrm array de 2 ints
scores t2l / / um array de 2 ints
scoresl0l t1l // o valor int igual a 2
scores t2l l1l / / o va]-or int igual a 4
AFigura3-5 mostrao resultadodadeclaragio, consruglo einicializagXo deum arraybidimensionalemumainstruso.

Construindo e inicializando um array an6nimo


O sggundo atalho 6 cham ado de aalao ac an'a1 andnimo epode ser usado para construir e inicializar um array e, em seguida,
atribui o arrayaumavari6veldeclarada anteriormente, que fagarefer6nciaaoutro aftay:
i nf I l l-6cl- q-^ra<
- --- -i,'
testscores = new int [ ] {4 ,7 ,2} ;

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

objeto Cat objeto Cat

objeto do array Cat objeto do array Cat

variivel de refer6ncia (do


array 2-D) de Cat[ ][] variivel de referGncia (do array 2-.
D) de cat[ ][

A figura demonstra o resultado do seguinte c6digo:


cat[ ][ ] myCats = {tnewCat("Fluffy"}, newcat('zeus")},
{new Cat("Bilbo"), new Cat("Legolas"), new Cat("BerE") }}
56o criados oito obietos:
I obieio orroy 2-D Cat t I t l
2 obietos orroy de Cat [ ]

5 obietos cat

Figuro 3-5 - Um orroy bidimensiono/ no pilho

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

nar^r f\lrioal-f ?l Inrr'l'l


trrufrr
naur
rlvvv nl-rian|-
vvJvvL\r, /l row Oh'iccl- {)}:

/| // '^x^ : --<r
Ltsv s I r^,
varauq; o tamanho nao deve ser especificado

Atribuig6es vilidas para os elementos do array


O que podemos iruerir em um array especifico? Voc6 teri que saber no exame que os arrays s6 podem ter um tipo declarado
(int t J , Dog [ ] , string [ ] e outros), mas isso nlo significa necessariamente que somente objetos ou tipos
primitivos podem ser atribuidos aos elementos do array. E a variivel de referAncia do array? Que tipo de objeto de array
pode ser atribuido ivariivel de refer6ncia especifica de um array? No exame, voce ter, que saber a respostaparatodas essas
perguntas. E, por coincid6ncia, iremos abordar esses mesmos t6picos nas seg6es seguintes. Preste atengeo.

Arrays de tipos primitivos


Os arrays primitivos aceitam qualquer valor que possa ser atribuido implicitamente ao tipo de array declarado. Por exemplo,
vm arlay inL armazenar6 qualquer valor que seja permitido para uma vari6vel int
de 32 bits. Portanto, o c6digo a seguir
6v61ido:

int[] weightlist = new int[5];


JAVA5 I29
byte b = 4;
char c = 'c';
short s = 7;
weightlisttOl = b' // OK, byte 6 menor do que int
weightlisttll = c' // OK, char 6 menor do que int
weightlist[2] = si // OK, short 6 menor do que int

Arrays de refer6ncia a objetos


Se o tipo declaradopuaoarray forumaclasse, voc6poder6inserirnele objetos de qualquersubclasse do tipo declarado. Por
exemplo, se Subaru for uma subclasse de Car, voc6 poderi inserir tanto objetos Subaru quanto objetos Car no array, como
vemos no exemplo abaixo:

class Car { }
class Subaru extends Car { }
class Ferrari extends Car { }

Car [] myCars = {new Subaru0, new CarO, new Ferrario};


E bom lembrar que os elementos do array Car nXo sio nada mais do que varilveis de refer6ncia Car. Portanto, qualquer item
que possa ser atribuido a uma variivel de refer6ncia Car poderi ser concedido de maneira v6lida a um elemento do array 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

Zf i*pf"*.nt.a o m6todo sporty (esportivo) especificamente atrav6s de Ferrarj.


)

)
class RacingFlats extends AthleticShoe implements Sporty {
public void beSportyO {

U ) i*pf"*"nta o m6todo sporty atrav6s de Racingshoe (t6nis de corrida)


)

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

Atribuig6es de vari6veis de refer6ncia de a?rays unidimensionais


No exame, voc6 ter6 que reconhecer atribuig6es vilidas e invilidas de vari6veis de refer6ncia de arrays. Nio.
estarnos falando sobre vari6veis de refer6nciis dn array (em outras palavras, elementos do array), mas, em vez 4isso,
de refer6ncias ao objeto de array. Por exemplo, se vocA'declarar um array inL, avariivel de referAncia declarada
podeni ser reatribuida a qualquer array (de qualquer tamanho), mas ndo a um item que ndo seja um array inL,
inL
lnclusive valores Lembre-se de que todos os arrays sXo objetos, portanto, uma aaiduel de reueftncia de atral nio
int.
pode ser atribuida a um tipo primitivo int. O c6digo a seguir demonstra atribui$es vilidas e inv6lidas de arraln primitivos:
infIl <nlafc.

int[] dats = new int[4];


char[] letters = new char[5];
splats = dats; / / Ox, dats se refere a um array int
splats = letters; / / NAo ESTA coRRETo, letters se refere a um array char
E tentador presumir que j6 que uma variivel de tipo byte, short. ou char pode ser promovida e atribuida
explicitamente a um tipo int, um array de qualquer &sses tipos poderia ser atribuido alum array int. Voc€ nio po&.
fazer isso emJava, mas seria bem pr6prio deises elaboradores de exame maldosos e impiedosos (por6m, interessantes)
inserir perguntas ambiguas sobre atribuig6es de arrays no exame.
Os arrays que podem conter referdncias a objetos, e nio a tipos primitivos, nio slo tio restritivos. Da mesma forma que
voc6 pode inserir um objeto Honda em um array Car (porque Honda esten& a classe Car), pode atribuir um aray detipo
Hondaaumavariivel de refer€nciado array Carcomo descrito abaixo:
Car [ ] cars,.
Hondal] cuteCars = new Honda[S];
cars = cutecars; / / OK, poi-s Honda 6 um tipo de Car
Beerl] beers = new Beer [99];
cars = beers; // llAo nsrA conReTo. pois Beer nao 6 um tipo de Car
Apliqueotest.ti-l,tgUnnOparalhe ajudaradistinguiro que6vilidodo quenio 6. HondaII-MEMBROdo grupo Car,
portanto, um arrayHondapodeseratribuido aum array Car. A assertivaBeerE-MEMBRO do grupo Carnio est6correta;
Beer ndo estendea classe Car (para nio mencionar o fato de que nio tem sentido l6gico, a menos que voc6 j6 tenha bebido
bastante).

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

Atribuig6es de vari6veis de refer6ncia de arrays multidimensionais


Quando voc6 atribuir um array a uma vari6vel de refer€ncia de array declarada anteriormente, 0 affal teri que estar
na metma dimeudo da uaiduel de refeftncia a qual estiuer sendo atribuido. Por exemplo , um array bidimensional de arrays int
ndo pode ser atribuido a uma vari6vel de refer6ncia de um array inL comum, como vemos abaixo:

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:

int[] tl books = new inr[3] [];


int[] numbers = new intt6l;
int aNumber = 'l i
books[0] = aNumber; //NA.o 6 vdlroo, espera-se um array r-nt. em vez de um valor int
books[0] = nunbers, //vALrDo, numbers 6 um array int
A Figura 3-6 mostra um exemplo de atribuig6es v6lidas e invilidas para refer6ncias a um array.

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;

\lari{vel de refer€ncia ao Afiay


Cat[ ]
A YariAvel de ref€rencia ao anay
SOMENTE pode se referir a um
a.ray Cat l-D

i Cat obj6to
cat obj€to cat
aluffy

-n o .loato uh a.r.y Cat t-D


r a 8m pdo- .. t.f.stE . u

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

Figuro 3-6 AtribuigOes de oroys volidos e inv6lidos

Atribuig6es Inv6lidas de Refer6ncias de Arrays |


A mycats = myCats [0]; "*,r,
I

/ / Nd,o 6 possivel atribuir um array 1-D a uma I


refer6ncia a array 2-D I
B mycats = myCats [0] tOl ; | ----------*
v61.ido
// N5o 6 possivel atribuir um objeto ndo-array a I
uma refer6ncia a array 2-D
I
c mycats [1] = mycats [1] l2l; | ---"-"--'--">
/ / Nl,o 6 possivel atribuir um objeto ndo-array a I Inv6lido
uma refer€ncia a array 1-D
D myCats [0] [1] = morecats'
/ / N5o 6 possivel atribuir um objeto array a uma
refer6ncia n5o-array
// q€ats [0] [1] s6 pode se referir a um objeto Cat
132 Copitulo 3: AtribuiE6es
Como voc6 pode ver, blocos de inicializaglo 6 bem complexa. Eles nXo t6m nomes, nio usam-
a sintaxe dos
argumentos nada. Um bloco de inicializagdo esttitico ,6d^ oro ue7, quando a classe 6 carregada pela
. ,rio ,.iorrram
pr?meira vez. IJm bloco de inicializagio de instincia roda ti*pn qae ama noaa instdncia i criada.Lembra {..q}Tdo- ,
i"l"mos sobre a ordem em que o c6digo de cada construtor era executado? o c6digo de blocos de inicializaglo de
instincia roda logo depois da chamadia super ( ) em um construtor, ou seja, depois que todos os
superconstnrtores tenham rodado.
VocA pode ter muitos blocos de inicializagio em uma classe. E impottattte notar que' ao contr6rio de m6todos ou
apareceril em uma clarefaqd&rtofo. Quando chega a hora de os blocos
constnrtores , a ordem em qae 0s blocos de inicialiqagdo
de inicializa$o .*"..rt"r'"-, se uma classe iiver mais de um, eles roditao na ordem em que.aParecem no arquivo
da classe... Ern o,rtr", palavras, de cima para baixo. Com base nas regras que acabamos de discutir, voc6 consegue
determinar a saida do seguinte programa?
class rnit {
rnit(int x) { system.out'println("1-arg const"); }
InitO { System.out.println("no-arg const") ; }
static { System.out.println("1st static init"); }
{I Slzstem.orri-nri
efrullr!vuu.yt4.Ae+ nl- ln("1st insl-a.nce init"); }

{ System.out.println("2nd instance init"); }

Svst^* arrts nvj-r1-/""nd


staf ir: {t slpusrrrrvuu.y!rrru+rr\ 4rr Static init"); }

public statj-c void main(String [] args) {

new InitO;
new Init(7) t
]
]
Para descobrir a resposta, lembrese destas regras:

I Os blocos deiriciahzagiro rodam na ordem em que aParecem.

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

Com essas regras em mente, a seguinte sai da deverifazer sentido:

1st static init


2nd static init
1st instance init
2nd instance inic
nn-arff a6nql.

1st i-nstance init


2nd instance init
1-arg const
Como voc6 pode ver, os blocos de rnicia\izaglo de instAncias rodaram duas vezes. Esses tipos de blocos sio usados
como um lugar para se colocar c6digos que todos os constnrtores de uma classe devam compartilhar. Dessa
forma, o c6digo nio precisa ser duplicado em todos os construtores.
Finalmente, se voc0 cometer um erro no seu bloco de inicializagio estatico, a JVM pode langar um
Exc ept i onlnlnini ta1 i z at i onError. Veiamos um exemplo,
class hitError {
static int [] x = new i-nt[4];
static { xt4l = 5; } // indice de array inv6.1ido!
public static voj-d main(String [] args) { }
JAVA5 I33
J

que produz algo como:

Exception in thread *main" j ava. 1ang. Exceptionrnrnitial_izerError


Caused by: java. lang.ArraylndexOutOfBoundsException: 4
at InitError. <clinit> (Tnit.Error. iava: 3)

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

As classes wrapper da API Java seryem a dois prop6sitos principais:


r Fornecer um mecanismo para "empacotar" valores primitivos em um objeto de modo que possam ser
incluidos em atividades reservadas a obietos, como ier adicionados a coniuntos on retornadbs de um m6todo
que tenha como valor de retorno um objeto. Observagio: com a adigio do autoboxing (e unboxing) emJava 5,
que veremos- daqui a algumas p6ginas, muitas das operag6es de wrapping que os programadores costumavam
fazer mantalmente agora sio feitas de forma autom6tica.
I Fornecer um conjunto de fung6es utilitirias para tipos primitivos. A maioria dessas fung6es esti relacionada
com v6rias convers6es: de-tipos primitivosem.objetbs Siring e vice-versa, de tipos primitivos e objetos String
para bases (ou radicais) diferentes - como binirias, octais e hexadecimais, e viie-virsa.

Uma vis6o geral das classes wrapper


Hi uma classe wrapper para cada tipo primitivo em Java. Por exemplo, a classe v/rapper para o tipo int 6
Integer, para f loat 6 Float, e assim por diante. I-,embre-s de qae o noie do tipoprinitiuo iinpisnente o iome em minrisculat
do wrapper, excetl para cbar, que passa a w Cbaracter, e inL, qae passa a ser Integer. A Tabela 3-2 lista as classes wrapper da
APIJava.

Criando obietos wrapper


No exame voc6 ter6 que saber as tr6s abordagens mais comuns para a criaglo de objetos wrapper. Algumas
abordagens usam a representagio em String de um tipo primitivo como argum.nto. Ar qrre .tram Strings lanEario
exceg6es NumberFormatException se a String fornecida nio puder ser converrida no ripo primitivo
apropriado. Por exemplo, "dois" nio pode ser convertido em "2". Os objetos wrapper sio inaltir6veis. lJma vez
que receberem um valor, ele nio poderi ser alterado. Falaremos mais sobre a imutabilidade dos wrappers quando
estivermos discutindo o boxing, daqui a algumas p6ginas.

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\ ;

E roaL 12 new Float ( "3 .14f" ) ;


134 Copitulo 3: AtribuiE6es
Tobelo 3-2 C/osses wrapper e os orgurnenios de seus conslrulores

Tipo primitivo Classe wrapper Argumentos do construtor

Boolean Boolean booleano ou String


Byte Byte byte ou String
Char Character char
Double Double doubleString ou

Float Float float ou String


Int Int.eger int ou String
Long Long long ou String
Short Short short ou String
A classe Character fornece s6 um construtor, que usa o tipo char como argumento. Por exemplo,
Character c1 = new Character('c');
Os construtores da classe wrapper Boolean usam um valor booleano true ou f a1se, ou uma String que nlo
diferenciamaiusculasdeminisculascomovalortrue oufalse.AntesdeJava5,umobjetoBooleanniopodiaser
booleano - por exemplo,
usado como expressio em um te$e

Boolean b = new Boolean("fa1se") ;


i f /h\
// ndo compila com Java 1.4 ou anterior
ApartirdeJava5,umobjeto Boo:.earropodcserusadoemumtestebooleano,porqueocompiladorir6,f.aznr
automaticamente o unboxing do objeto para um boolean. Iremos nos concentrar nas fun96es de autoboxing deJava 5
na pr6xima seglo - entio fique alena!

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

Float f2 = Float.valueOf ("3. l-4f") ; // atribu:- 3.1-4 ao objeto Float f2

Usando os utilit6rios de converseo das classes wrapper


Com dissemos anteriormente, a segunda grande fungio de um wrapper 6 converter coisas. Os m6todos a seguir
sio os mais freqiientemente usados e mais proviveis de estar no exame.

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

short s = i2.shortValueo; / / vm outro m6todo xxxValue


/ /
/ ,
Aa
sv
Taraaar
4A4vvYe!

double d = i2.doubleVa1ueO; / / mais um m6todo xxxValue


/ / Aa 'rnranar

Float f2 = new Float(3.14f); / / cria objeto wrapper


um novo
short s = f2.shortvalue0t // converxe o valor de i2's em um
// primitivo short
System. out.println (s ) ; // o resultado 6 3 (truncado, nao
// arredondado)

Iobelo 3-3 M6todos wrapper comuns de conversdo

M6todo
s=static
n=excegeoNFE Boolean Byt€ Character Double Float Integer Iong Short

ByeVdue

doubleValue

FloatVdue

IntValue

IongVahre

ShortMue

ParseX:o<42

ParseX:o< 4z (com a base)

valueOf. s,n

valueOf s,n (com abase)

Tosfting

toStringi(primitivQ x
toString s (primitivo, base)

Resumindo, as assinaturas essengiais dos m6todos wrapper de conversio sio:


primitivexorValue$ -paraconverterumtilfrapperparaumprimitive
primitive parsdGo<(String) - para converter um String para um primitive
\(lrappervahrcOf(String) -paraconvefterumStringparaum\ilfrapper

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.

Alguns exemplos desses m6todos em agio:


136 Copitulo 3: Atribuiqoes
double d4 = Double.parseDouble ("3.14") ; / / converte um Strinq em um primitivo
System.out.println("d4 = " + d4); // o resul_tado 6 "d4 = 3.14"
Double d5 = Double.valueOf ("3. 14" ) ; / / cria um objeto Double
System.out.println(d5 instanceof Double ) ; // o resultado 6
Os exemplos abaixo envolvem o uso da base como argumento (nesse caso, biniria):
long L2 = Long.parselong("101010", 2); / / S:uringbin6ria para um primitivo
System.out.println("L2 = " + L2) ; // o resultado 6 "L2 = 42'
Long L3 = Long.vafueOf("101010", 2t; // Strrng bin6ria para objeto Longl
System.out.println("L3 value = " + L3); // o reswLtado 6 "L3 value = 42"

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,

String s = "hex - "+ Long.toString(254,1,6); // s = r\hex = fe"

toXxString( ) (base bin6ria, hexadecimal e octal)


As classes wrapper Integer e Long permitem que voc6 converta para outras bases nrimeros que estiverem na base
1.0. Esses m6todos de conversio, toXxxString ( ) , usam um tipo int ou long e retornam uma
representagio em String do nrimero convertido, por exemplo,
String s3 = Integer. toHexstring(254) ; / / converLe 254 para hexa
system.out.println("254 in hex - " + s3); // o resultado 6 "254 in hex = fe"
String s4 = Long.tooctalstring(254); // converLe 254 para octal
System.out.println("254 in octal = "+ s4); // o resul-tado 6 "254 in octal = 376"
Estudar a Tabela 3-3 6. a melhor maneira de se preparar para esta segio do teste. Se voc6 conseguir entender bem as
diferengasentre xxxvalue( ),parseXxx( ) evalueOf ( ),devesesairbemnessapartedoexame.

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

Agora, com o novo e aprimorado lava 5, voc6 pode usar

Integer y = new Integer(557) ; / / cria


Y++ i // abre, incrementa,
// fecha novamente
System.out.printl-n("y = " + i); // exlbe
Ambos os exemplos produzem a saida:

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

Vamos tentar o seguinte:


Integer Y = 567; / / cri-a um wrapper
T- |
rllLeljer ^-^e
^ -
y, / / atribui uma segunda vari5vel
/ / de refer6ncia AO wrapper

System. out.println (y==x) ; / / verifica se elas estao se


// referindo ao mesmo objeto
Y++ i // abre, usa, fecha novarnente
System.out.println(x + * " + y); // exibe os valores
System. out.println (y==x) ; // verifica se elas estao se
// refcri ndn : ntrietos diferentes
O que produz a saida:
Erue
567 568
false
Assim, nos bastidores, quando o compilador chegou i linha y++; ele teve de substitui-la por algo como isto:
int x2 = y.intValue0 ; / / abre
x2++; // usa
y = new Integer(x2); / / fecha novamente
Como suspeit6vamos, precisa haver uma chamada a new em algum lugar do c6digo.

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

diiendoqueil- ei2 sXoobjetosdiferentes,quando:: est6dizendoquei3 ei4 sioomesmoobjeto?Para. .


economizar mem6ria, duas instAncas dos seguintes objetos wrapper serio sempls : : quando os seus valores primitivos
foremo mesmo:
I Boolean
I Byte
r character de\u0000at6\u007f (7f 6I27 emdecimal)
I Short ernteger de-I28a&127

Onde Pode ser Usado o Boxing


Conforme discutimos anteriormente,6 bastantecomumusarv/rappers emcombinagio comconjuntos. Sempre que quiser
que o seu conjunto armazene objetos e primitivos, voc6 usar6 wrappers para tornar esses primitivos compativeis com os
cbnjunros. A regra geral 6 que boxinge unboxinqfuncionam em todos os lugares onde voc6 normalmente possausarum
primirivo ou um obJeto wrappect. L, segumte coogo demonstra algumas mineiras vilidas de se usar boxinf:
class UseBoxing {
public static void main(String [] args) {

UseBoxing u = new UseBoxingO ;


u.go(5);
]

boolean go(Integer i) { // encapsula o int que recebeu


Boolean ifSo = true; // encapsula o literal
Short s = 300; // encapsula o primitivo
if (ifso) t / / abrindo
System. out . println ( ++s ) ; / / abre, incrementa, encapsula novamente
i
return !ifSo; / / abre, reLorna o inverso

oBSERVAQoES pene O DC{ME


I-*mbre-se de qae as uaiiueis de refer€ncia wr@perpodem serrrwJ_l-,. Isso signfica que uoci precita tomar euidado com algum nidigo que
parega e$arrealiqando operagdu seguras conprinitiuos, nat queplssan lanprumaNullPointerException.'
class Boxing2 {
static Integer x;
JAVA5 I39
public static void main(String [] arqs) {
evves!! \^/ |

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

Obietivo poro o CertificoE6o

Sobrecarregando (Objetivos 1.5 e 5.4 do Exame)


1,5 Dado um exemplo de aidtgo, deterwinar se um mitodo eshi sobresmuendo oa sobncamgando comtanente ouho mitodo, e identifcar
aalores de retomo udlidot (incluindo retnrnls coaaiades) para o mitodo en questdo.
5.4 Dado un ceniio, dueruolueraidigo que dulan ef or ebame mdtodat sobrescritos ou sobrecamgados...

Sobrecarregando da Maneira Dificil - Correspond€ncia de M6todos


Embora ji tenhamos abordado algumas regras para a sobrecarga de m6todos no Capitulo 2, neste capitulo n6s
adicioaaremos alguns itens ) nossa caixa & ferramentasJava. Nesta segio, daremos uma olhada em ti6s fatores que podem
difi cultar um pouco a sobrecarga:

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

Que produz esta saida:


int int lonq double
140 Cop(tulo 3: Atribuig6es
Isso provavelmente nlo serl nenhuma surpresa; as chamadas que usam byte e os arguryentos shon sio
implicitamente ampliados para bater com a versio do m6todo go ( ) que usa um int. E claro que a chamada
.o* long usa a rierslo tong de go ( ) e, finalmente, a chamada que usa um f l-oat 6 convertida para bater
com o m6todo que usa um double.
Em qualquer caso, quando uma correspond6ncia exata nio puder se encontrada, a JVM usa o m6todo com o
menor argumento que seja mais amplo do que o parAmetro.
VocA pode verificar que, se houver apenas uma versio do m6todo go ( ) , e ele usar um double, essa versio se r|usaAapara
todas as quatro chamadas a go ( ) .

Sobrecarga com Boxing e Var-args


Vamos agora volar ao nosso exemplo anterior e adicion ar boxinga elel.

class AddBoxing {
static void gro(Integer x) { System.out.println("Integer"); }

static void go(1ong x) { System.out.println("1ong"); }

public static void main(String [] args) {

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... "); }

public static void main(String[] args) {


byte b = 5;
qo{b,b); // qual go0 ser5 chamado?

Como voc6 provavelmente adivinhou, a saida 6

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

public static void main(StrinS [] args) {


byte b = 5;
qo (b, b) ; // qoaT go$ ser6 chamado?
)

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.

Ampliando Vari6veis de Refer6ncia


Ji vimos que 6 vilido ampliar um primitivo. E possivel ampliar uma variivel de refer6ncia e, em caso positivo, o que isso
significaria? Voltemos o nosso raciocinio para a nossa atribuigio polim6rfica favorita:
Animal_ a = new DogO;
Mantendo esse mesmo raciocinio, uma chamada poderia ser:

cl-ass enimal {statj-c void eatO { } i


class Dog3 extends Animal {
public static void main(String[] args) i
Dog3d=newooq3o;
d.so(d); // Lsso 6v61ido?
)
void go(Animal a) { }

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.

Sobrecarga na Combinagio de Ampliagio com Boxing


Ji vimos as regras que se aplicam quando o compilador consegpe estabelecer uma correspond6ncia entre chama& e m6todo
realizando uma tinica convenio. Vejamos agora o que acontece quando 6 preciso fazer mais de uma conversio. Neste caso, o
compiladorter6 de ampliar e depois fazer autoboxing do parAmetro para que haja uma correspond6ncia:
142 Copitulo 3: AtribuiE6es
class WidenAndBox {
sLatic void go(Long x) { System.out.println("Long"); }
public static void main(String [] args) {
byte b = 5,'
go (b) ; / / preclsa ampliar e depois fazet boxing - inv6lido

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

Sobrecarga em Combinagio com Var-args


O que acontece setentarmos combinarvar-argp oucom a ampliagio ou com o boxingemum cenirio de buscapela
correspond6ncia de um m6todo? Vejamos:
class Vararg {
static void wide-vararq(1ong. . . x)
{ System.out.println("1ong. . . " ) ; }
static void box_vararg(Integer. . . x)
{ System.out.println( "fnteger. . . " ) ; }
public static void main(String [] args) t

wide-varars(5,5); // precisa ser ampliado e usa var-args


box_vararg(5,5) ; / / preclsa ser encapsul-ado com boxing e usa var-args
'143
JAVA 5

]
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:

r A ampliagio de primitivos usa o "menor" argumento possivel do m6todo.


I Usados individualmente, boxing e var-args sio compativeis com a sobrecarga.
r NAO 6 possivel ampliar de um tipo wrapper para outro. @-tnt frlha.;
r NAO 6 possivel ampliar e depois fazer boxing. (Jm int nlo pode se tornar um Long)
I E possivel fazer boxing e depois ampliar. (Um int pode se tornar um Object, via Integer.) E possivel combinar var-
args com ampliagio ou com boxing.

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!

Obietivo poro o certificoEdo

Coleta de lixo (Objetivo 7.4 do exame)


T.4Dadoumexemplodealdigo,reconheceropontoemqueumoletosetornaqualifcadoparaacoletadelixo,edeterminaroquedeoquendoi
pek $stema de colcta de lixo. Reeonhuer 0 cnnpnftamentr de Slsten.gc e dafnaliryg1o.
gmantido

Visio total do gerenciamento da mem6ria e da coleta de lixo


Esta 6a seglo pela qual voc6 estava esperando! Finalmente chegou a hora de nos aprofundarmos no interessante universo
do gerenciamento da mem6riae coleta de lixo.

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.

Vis6o geral do coletor de lixo em fava


Vamos examinar o que queremos dizer sobre coleta de lixo no universoJava. Aqui, a 30 mil p6s de altura, coleta de lixo 6 o
termo usado para descrever o gerenciamento automitico da mem6ria em Java. Sempre que o programa de um software for
executado (emJav4 C, C + + , Lisp, Ruby, e assim por diante), ele usar6 a mem6ria de v6rias maneiras diferentes. Nio
entraremos nos aspectos blsicos da ci€ncia da computaglo aqui, mas 6 normal a mem6ria ser usada para criar uma pilh4 um
heap, em pools constantes de maiusculas e minusculas da linguagemJava, e em 6reas de m6todos. Heap 6 aparte da
mem6ria onde residem os objetosJava, sendo o rtnico local da mem6ria que de alguma forma estari envolvido no
processo de colaade lixo.
Un heap i irzplesaente am he@. No exane rcni inportantu saber que uocd pode chaad-lo de be@, de heap de cokta de lixo, de
144 Copitulo 3: Atribuig6es

Johnson, pordrn ,s6 bi um beap.

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!

Quando o coletor de lixo 6 executado?


O coletor de lixo 6 controlado pelo VM. A JVM decide quando executi-lo. De dentro de seu programa Java voc6
pode solicitar )LJVM para executar o coletor de lixo, mas nio haveri garantia, em nenhuma circunstAncia, de que
ele o far|. Quando a decisio 6 s6 dele, normalmente a JVM executa o coletor de lixo ao perceber que a mem6ria
est6 ficando sem espago. A experiAncia mostra que quando um programalava f.az uma solicitagio de coleta de
lixo, a JVM geralmente a atende rapidamente, mas ado bd garuntias. Exatamente quando pensamos que poderemos
contar com ele, aJVM decide ignorar a solicitagio.

Como o coletor de lixo funciona?


VocA nio conseguir6 ter certeza. Pode ouvir que o coletor de lixo usa um algoritmo de marcaglo e eliminaglo, e
isso poderia ser verdade para alguma implementagio Java em particular, mas a especificaEio da linguagem nio
garante nenhuma implementaEio especifica. VocA pode ouvir que o coletor de lixo trs a tontagem de referdnciat;
novamente, talvez sim, talvez n6o. O conceito imponante a compreende r para o exame 6. quando un objeto re tlrna
realmente qaalifcado para a coleta de lixo. Para responder essa questeo integralmente temos que nos adiantar um pouco e
falar sobre threads consulte o Capitulo 9 para obter informag6es detalhadas sobre eles. Resumidamente, todo
-
programa Java possui de um a v6.rios threads. Cada thread tem sua pr6pria pilha de execugio. Normalmente, voc6
(o programador) fari com que pelo menos um thread seja executado em um programaJava, o que tiver o m6todo
main ( ) no final da pilha. No entanto, como aprenderemos em detalhes no Capitulo 9, hl muitas raz6es
realmente importantes para iniciar threads adicionais a paftir de seu primeiro thread. Al6m de ter sua pr6pria
pilha de execugio, cada thread possui seu pr6prio ciclo de vida. Por enquanto, tudo que precisamos saber 6 que os
threads podem estar ativos ou nio. Com essas informag6es auxiliares jf podemos dizlr cbm bastante clareza que
um objeto utui qualficado para a coleta de lixo qaando nenhum tbread atiuo pode acessd-/0. (Observagio: devido ao cariter vago do
pool de constantes Strings, o exame concentra as suas quest6es sobre coleta de lixo em objetos nio-Strings, enteo a
nossa discussXo sobre a coleta tamb6m se aplicar6 apenas a objetos que nio sejam Strings.)

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.

Escrevendo um c6digo que torne os objetos explicitamente qualificados


Para a coleta
Na seglo anterior, aprendemos as teorias existentes por trAs da coleta de lixo Java. Nesta segio, mostraremos como tornar os
objetos qualificados para a coleta de lixo usando um c6digo real. Tamb6m discutiremos como 6 possivel tentar forgar a
coleta de lixo se ela for necessiria e como voc6 pode executar uma limpeza adicional nos objetos antes que eles sejam
removidos da mem6ria.

Anulando uma refer6ncia


Como discutimos anteriormente, um objeto se torna qualificado para a coleta de lixo quando nlo h6 mais referAncias a ele
que possam ser alcangadas. E claro que se nlo houver refer6ncias alcang6veis, nio imponari o destino do objeto. No que nos
diz respeito, ele ficar6 apenas flutuando no espago, sem ser utilizado ou acessado, nio sendo mais necessirio.
A primeira maneira de remover a refer6ncia a um objeto 6 configurar com nulf avari|vel de refer6ncia que
estiver apontando para ele. Examine o c6digo a seguir:
JAVA 5 I45
1. public class GarbageTruck {
2. public static void main(String [] args) {
3. StringBuffer sb = new StringBuffer ( "hello" ) ;
4. System.out.println(sb) ;
5. // O objetoStringBuffer nao esta qualificado para coleta
6. sb = nul1;
'7. / / Agora o objetostringBuffer est.6 qualificado para coleta
B. )
9. ]
A variivel de refer6ncia sb foi atribuida ao objeto StringBuffer de valor hell-o na terceira linha. Para torn6-lo
qualificado (ptara a coleta), configuramos a variivel de refer6ncia sb com null, o que remover| a inica
refer6ncia ao objeto StringBuf f er que existia. IJma vez executada a linha 6, nosso objeto StringBuf f er
he11o estar6 condenado, qualificado para a coleta de lixo.

Reatribuindo uma vari6vel de referGncia


Tamb6m podemos desassociar uma varilvel de referdncia de um objeto configurando-a para referenciar outro
objeto. Examine o c6digo abaixo:
class GarbageTruck {
pubLic static void main(String [] args) {
StringBuffer s1 = new StringBuffer("hel]o");
StringBuffer s2 = new StringBuffer("goodbye") ;
q\rql- am nrrf
vJ s ev.'r. nri nl- lr 1<1 \

// Neste ponto, o StringBuffer "hell-o" nao est5 qualificado


s1 = s2; // Redireciona s1 para refer6ncia ao objeto "goodbye"
/ / Agora o StringBuffer "hel1o" est5 qualificado para coleta
)

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

nrrhl i n al :cc fl:rl-r:naE'ani-nrrz I

public static void main(String [] args) {

Date d = getDateo
doComplicatedstuff ();

System.out.println("d = " + d) ;
)
n"k] .i^ -f-f.i^ nrl6 d6l-n:f6/\ tL
PUUIIL DUaUfL uqus YeLUqre\/

Date d2 = new lateo;


StringBuffer now = new StringBuffer (d2.toStringO );
qircl- am
efrevrrr!vuu.vrflrvf nri n|- l n lnar^rl .
^11|-
return d2;
]
]
No exemplo anterior, criamos um m6todo chamado getDate (
) que retorna um objeto Date. Esse m6todo cria
dois objetos: um objeto Date e uma StringBuffer contendo as informag6es sobre a data.li que o m6todo retorna o
objeto Date, ele nio esterS, qualificado para a coleta mesmo depois que o m6todo for concluido. O objeto
StringBuffer, no entanto, estar6 qualificado, ainda que nio tenhamos configurado explicitamente a variivel now
com null-.
146 Copftulo 3: Atribuig6es
lsolando uma referencia
H6 outra maneira por meio da qual os objetos podem se tornar qualificados para a coleta de lixo, netmo rc ainda
tiaervm referincias u,ilidas! Consideramos esse cenirio como ilbat de isolamento.
Um exemplo simples seria uma classe que tivesse uma vari6vel de instAncia que fosse a variivel de refer6ncia de outra
instAncia & mesma classe. Agora imagine a exist6ncia de duas instAncias desse tipo referenciando uma a outra. Se todas as
outras referAncias a esses dois objetos forem removidas, entio, embora cada um dos objetos ainda tenha uma referdncia
v61ida, nio haveri como algum thread ativo acessar um deles. Quando o coletor de lixo for executado, ele descobrir6 esas
ilhas de objetos e as remover6. Como voc6 pode imaginar, as ilhas podem se tornar bem grandes, contendo teoricamente
centenas de objetos. Examine o c6digo a seguir:

public class lsland {


Island i;
public static void main(String [] arqs) {

fsland i2 = new Islando


Island i3 = new fslando
Island i4 = new Islando

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.

/ / real-iza tarefas complicadas e que exigem muita mem6ria

Quandooc6digoalcangar I / realiza tarefas. . .,ostr6sobjetoslsland(antesconhecidoscomoi2, i3 ei4)


terio variiveis de instAncia para que apontem um para o outro, mas seus vinculos com o ambiente externo (i2, i3
e i4) terio sido anulados. Esses tr6s objetos estarAo qualificados para a coleta de lixo.
Abordamos tudo que voc6 precisa saber sobre tornar objetos qualificados para a coleta de lixo. Estude aFigara3-7
para refor7ar os conceitos de objetos sem referOncias e ilbas de inlanento.

Forgando a coleta de lixo


A primeira coisa que deve ser mencionada aqui 6 que, em oposigXo ao titulo desta segio, a coleta de bxo ndo podc ser
-foryodo.No entanto, a linguagem Java fornece alguns m6todos que permitirio a voc6 solicitar i JVM que execute a
coleta de lixo. Por exemplo, se vocA estiver para executar algumas operag6es limitadas pelo tempo, provavelmente
ir6 tentar minimizar as chances de um atraso causado pela coleta de lixo. Mas deve se lembrar que os m6todos
fornecidos pelaJava sio solicitagdes e nio demandas; a miquina virtual fari o que puder para executar o que voc6
solicitar, mas nio hi garantias de que o far6.
Na verdade, s6 6 possivel sugerir ) JVM que execute a coleta de lixo. No entanto, nio haver| garantias de que todos
os objetos nXo utilizador r.iao reimente removidos da mem6ria. li essencial que voc6 compieenda esse c-onceito
para o exame.
As rotinas de coleta de lixo que a Java fornece sio membros da classe Runtime. A classe Runtime 6 uma classe
especial que possui somente um objeto (o objeto Singleton) para cada programa principal. O objeto de Runtime
fornece um mecanismo de comunicagio direta com a m6quina virtual. Para capturar a instAncia de Runtime, voc6
pode usar o m6todo Runtime. getRuntime ( ) , que retornari o objeto Singleton. Assim que tiver o Singleton,
voc6 pode chamar o coletor de lixo usando o m6todo gc ( ) .
Alternativamente, vocA pode chamar o m6todo da classe System, cujos m6todos static sio capazes de obter o
objeto Singleton para voc6. A maneira mais simples de solicitar a coleta de lixo Qembre-se: 6 apenas uma
solicitaEio) 6 atrav6s de:
Qa'cf6m n- I I
JAVA 5 I47
Teoricamente, depois de chamar System. cg ( ) , voc6 ter6 tanto espago livre na mem6ria quanto possivel.
Dissemos teoicamente porque essa rotina nem sempre funciona assim. Primeiro, a JVM que voc6 estiver usando
pode nXo tAJa implementado; a especificagio da linguagem permite que essa rotin^ nilo tenha absolutamente
nenhumafungio.

pubLic class Island (


Island n;
public static void main(St.ring [] args) {
Island i2 = new IslandO;
ls1and i3 = new IslandO:
Tsland i4 = new Island():
l-l.n = t-J
i3.n = i4
i4.n =i2
i2 = nul1;
i3 = null;
i4 = nu11;
doCourlexstuff O;
m@
, til @
ma

lndicava uma public class LosE {


public static void rnain(Strinq {} args) {
-}.@.,
referGncia ativa Lost x = new tost O:
x = nul1;
docomplexstuff ( ) :
lndica uma )
t
referCncia apagada
Figuro 3-7 Obietos guo/ificodos poro o co/efo de /ixo
Em segundo luBar, outro thread (mais uma vez, consulte o Capinrlo 9) pode executar uma alocagio de mem6ria substancial
logo depois que voce processar a coletade lixo.
(
Com isso, nio queremos dizer que Sytem. gc ) 6 um m6todo inrltil - 6 muito melhor que nada. Mas 6 que voc6 nio
pode confiar em system. gc (
) para liberar um espago suficiente na mem6ria de modo que nXo precise se preocupar
com a execugeo da coleta de lixo. O exame da certifica$o estari interessado em um comportamento garantido, neo num
prov6vel.
Agora que estamos um porlco familiarizados com a maneira como isso funciona, .f".E1"gr alguns testes para ver se
conseguimos constatar os efeitos da coleta de lixo. O programa a seguir nos permitir6 saber quanto espago total na
mem6ria a J\&I tem disponivel para ele e quanto desse espago esti livre. Em seguida, ele cria 10 mil objetos Date.
Depois disso, nos informa quanto espago sobrou na mem6ria e chama o coletor de lixo (que, se for executado,
deve interromper o programa at6 que todos os objetos nio utilizados sejam removidos). O resultado final do
espago livre na mem6ria deve indicar se ele foi executado. Examinemos o programa:
f . import java.util.Date;
2. public class Checkcc {
3. public static void main(String [] args) {
4. Runtime rt. = Runt.ime. getRuntime ) ; (

5. System. out.println ( "Tota1 JVM memory: + rt.totalMemoryO );


System.out.println( "Before Memory = " rt.freeMemoryO );
7. Date d = nul1;
8. for(int i = 0;i<10000;i++) {
q d = new Date0;
l_0. d = nul1;
11. )
1,2. System. out.println ( "After Memory = r' + rt. freeMemory ( ) ) ;
13. rt.gc(\; // uma alternativa a System.gco
L4. System.out.println("After GC Memory = " * rt.freeMemoryO );
148 Copitulo 3: AtribuiE6es
15. )

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.

Fazendo uma limpeza antes da coleta do lixo - o m6todo finalize( )


A linguagemJava fornece um mecanismo para que algum c6digo seja executado imediatamente antes que um objeto seja
excluidopelocoletordelixo.Essec6digoficar6emumm6todochamado finalize( ) quetodasasclassesherdamda
classeObject. A primeira vista parece uma grande idliutilvez reu objeto tenha abeno alguns recursos que voc6 gostaria de
fechar antes que ele fosse excluido. O problema 6 que, como vod jl deve ter deduzido, nlo 6 possivel contar com o coletor de
lixo para excluir o objeto. Portanto, nenhum c6digo que voc6 insira no m6todo f inalize ( ) sobrescrito de sua
classe teri a execugio garantida. O m6todo f inalize ( ) de um objeto especifico pode ser executado, mas nio hi
como contar com ele; enteo, neo insira nenhum c6digo essencial nesse m6todo. Na verdade, recomendamos que
voc6 nlo sobrescreva de forma alguma f inalize ( ).

Cuidados relacionados com finalize( )


Hi alguns conceitos relacionados com f inalize ( ) que voc6 precisa lembrar:
I Para qualquer objeto, f inalize ( ) seri chamado apenas umavez (no maximo) pelo coletor de lixo.
r Chamar f inalize ( ) pode resultar em salvar um objeto da exclusio.
Examinaremos essas declarag6es com mais detalhes. Em primeiro lugar, lembre-se que f inalize ( ) 6 um
m6todo e qualquer c6digo que voc6 puder inserir em um m6todo conum poderi inserir em f inalize ( ) . Por
exemplo, no m6todo f inalize ( ) voc6 poderia escrever um c6digo que retornasse uma refer6ncia ao objeto
em questio para outro objeto, duqualficando efetivamente o objeto para a coleta de lixo. Se em algum momento
posterior esse mesmo objeto se tornar novamente qualificado para a coleta de lixo, o coletor ainda poderi
processar e exclui-lo. No entanto, ele lembrar6 que f inalize ( ) jLf.oi execttado paraesse objeto, e nio processar6
o m6todo mais uma vez-

Resumo para a certificagio


Este foi um megacapitulo! NXo se preocupe se vocA perceber que precisar6 revisar alguns destes t6picos quando
chegar. em capitulos posteriores. Este aqui apresentou muitos conceitos b6sicos que lhe serio rlteis
POStenOrmente.
Comegamos o capitulo revisando a pilha e o heap; lembre-se de que as variiveis locais residem na pilha, e as vari6veis de
instAncias residem, com os seus objetos, no heap.

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.

Literais e Conversio de Tipos Primitivos (Objetivo 1.3)


D Osliteraisintegerpodemserdecimais,octais(p.ex.013) ouhexadecimais(p.ex.Ox3d).
D Os literais para longs terminam com L ou 1.
D Os literais float terminam com F ou f , e os literais double terminam com um digito, com D ou com d.
E Os literais booleanos sio true e f alse.
fl Os literais para chars sio um 6nico caracrer dentro de aspas simples: 'd'.

Escopo (Objetivos 1.3 e 7.6)


E O escopo refere-se ao tempo de vida de uma vari6vel.
E Existem quatro escopos bisicos:
E As variiveis estiticas vivem basicamente pelo mesmo tempo que as suas classes.

0 As vari6veis de instAncia vivem pelo mesmo tempo que os seus objetos.

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.

Atribuig6es B6sicas (Objetivos 1.3 e 7.6)


tr Os literais de integers sio implicitamente ints.
E As express6es integer sempre geram um resultado com o tamanho de int, nunca menor.
B Os nrimeros de ponto flutuante sio implicitamente doubles (64 bit$.
150 Copftulo 3: AtribuiE6es
E Diminuir um tipo primitivo causa o corte do.s bits de ordem mais alta.
D Atribuig&s compostas (p.ex. + =) realizamumaconversio autom6tica.
El Uma vari6vel de refer6ncia armazena os bits que sio usados para se referir a um objeto.
E As varilveis de refer6ncia podem referir-se a subclasses do tipo declarado, mas nio a superclasses.

E Aosecriarumnovoobjeto,p.ex.,Button b = new ButtonO;,tr6scoisasacontecem:


E Cria-se umavari6vel de refer6ncia chamada b, do tipo Button
B Cria-seumnovo obietoButton
tr Atribui-se o objeto Button )variivel de refer6nciab

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.

Passando vari6veis para os m6todos (Obietivo 7.3)


D Os m6todos podem usar tipos primitivos e/ou referAncias a objetos como argumentos.

D Os argumentos dos m6todos sio sempre c6pias.

D Os argumentos dos m6todos nunca sio objetos reais (podem ser refer€ncias a objetos)

0 Um argumento primitivo 6 uma c6pia totalmente desvinculada do tipo primitivo original.


tr Um argumento de refer6ncia 6 outra c6pia de uma refer6ncia ao objeto original.
E O sombreamento ocoffe quando duas vari6veis com diferentes escopos companilham o mesmo nome. Isso leva a bugs
dificeis de encontrar, e a quest6es do exame dificeis de responder.

Declaragio, construgio e inicializagilo de arrays (Obi. 1.3)


O Os arrays podem conter tipos primitivos ou objetos, mas o array propriamente dito sempre ser|umobjeto.
D Quando vocd declarar um array, os colchetes poderio ficar i esquerda ou i direita do nome.

tr Nio 6 considerado vilido incluir o tamanho de um array na declaraSo.

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.

fl Os arrays sio indexados comegando pelo zero.

0 ArraylndexOutOfBoundsException ocorre se vod usar um valor de indice invilido.


B Os arrays possuem umavariivel length, cujo valor 6 a quanti&de de elementos do array.

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 As dimens6es de um array multidimensional podem ter tamanhos diferentes.

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

qual for atribuido.


D Voc6 pode atribuir um arruy de um tipo a uma refer|ncia de array j6 declarada de um de seus supertipos. Por
exemplo, um array Honda pode ser atribuido a um array declarado como tipo Car (supondo-se que Honda
estenda a classe Car).

Blocos de Inicializagno (Objetivos 1.3 e 7.6)


D Os blocos de inicializagio es6ticos rodam uma vez, quando a classe 6 carregada pela primdravez.
E Os blocos de inicializagXo de instAncias rodam sempre que uma nova instAncia 6 criada. Eles rodam depois de todos os
supercon$rutores e antes de ser executado o c6digo do construtor.

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.

Usando wrappers (Objetivo 3.1)


E As classes wrapper e$io correlacionadas aos tipos primitivos.

E Os wrappers t6m duas fung6es principais:

0 Encapsular tipos primitivos para que possam ser manipulados como objetos;

E fornecer m6todos utilit6rios para tipos primirivos (geralmente convers6es).


U Os construtores wrapper podem usar uma String ou um tipo primitivo, exceto para Character, que s6 pode
usar um tipo char.

E As tr€s familias de m6todos mais importantes seo:

E xxxValue ( ) Niousaargumentos, retornaumtipoprimitivo;


D parseXxx ( ) Usa uma String, retorna um tipo primitivo, 6 static e langa a exceEio NFE;
E valueof ( )UsaumaString, retornaumobjeto encapsulado,6 static elangaaexcegioNFE.
D O argumento do radical referencia bases (normalmente) diferentes de 10; a base biniria tem radic a72, oed,: 8e hex :
16.

Boxing (Objetivo 3.1)


tr A partir deJava 5, o recurso de boxing lhe permite converter tipos primitivos em wrappers ou convener wrappers em
uPos Prurutrvos automatrcamente.

D Usar :- com wrappers 6 complicado; v/rappers com os mesmos valores baixos (normalmente os menores
que I27) serio : :, rnzs yalores maiores nlo serio ::.

Sobrecarga Avangada (Objetivos 1.5 e 5.4)


D A ampliagio de primitivos usa o "menor" argumento de m6todo possivel.
0 Usados individualmente, o boxing e os var-args sio compativeis com a sobrecarga.
Cl Y ocl ndo pofu ampliar de um tipo wrapper para outro. @-Ulf faUra.;
D Voc6 ndo pode ampliar e depois fazer boxing. (Um int nlo pode se tornar um Long.)
O Voc6 pode fazer boingedepois ampliar. (Um int pode se tornar um Object, atrav6s de um Inreger.)
tr Vod pode combinar var-args com a ampliagio ou com o boxing.

Coleta de lixo (Objetivo 7.4)


E EmJava, a coleta de lixo fornece um nivel de gerenciamento automatico da mem6ria.

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.

E VocA nio tem como conhecer o algoritmo da coleta de lixo.


D Os objetos devem ser co niderados qulifuaiasantes que possam ser coletados como lixo.
E Um objeto est6 qualificado para a coleta quando nenhum thread ativo consegue alcangiJo.
E Para alcangar um objeto, vod precisa ter uma refer6ncia alcanSvel e ativa a esse objeto.
0 Os aplicativos Java podem ficar sem espago na mem6ria.
tr Ilhas de objetos podem ser coletadas como lixo, ainda que refiram-se umas ls outras.
152 Copftulo 3: Atribuig6es
tr Solicite a colea de lixo com System. gc ( ) ; (recomendado).
E AclasseObjectpossuiumm6todo finalize ( ).
tr Om6todofinalize( )temsuaexecugiogarantidaumavez,esumenre,/maae1antesdeocoletordelixoexcluirum
objeto.

E J6queocoletordelixoniotemexecugiogarantida, finalize ( ) podenuncaserexecxtado.

B Voc6 pode desqualificar um objeto para a coleta usando f inal ize ( ).

Teste Individual

l. Dado:
a'laq< Qcnnn {

static int throwero throws Exception { return 42; }


public static void main(String [] args) {
try {
int x = thrower0;
) catch (Exception e) i
x++;
) finallY {
System.out.println("x = " + ++x) ;
]]]
Qual6 o resultado?
A.x=42
B.x=43
C.x = 44
D. A compilagXo fdha.
E. O c6digo roda sem nenhuma saida.

2. Dado:
class CardBoard {
Short sEory = 5,'
CardBoard go(CardBoard cb) i
cb = nul1;
r6f r!rh
^h.

)
public static void main(String11 args) {

CardBoard c1 = new CardeoardO;


CardBoard c2 = new CardBoard0;
CardBoard c3 = c1 .go(c2);
c1 = null;
/ / faz algo
]]
Quando a execugXo chegar a / / faz a1go, quantos objetos estario qualificados para a coleta de lixo?
AO
B. 1
JAVAs I53
c.2
D. A compilagio falha.
E. Nio 6 possivel saber.
*r r
F.
- E langada uma excegao no tempo de execugio.

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

Mixer m2 = new Mixer0;


Mixer m3 = new ytixer (m2 ) ; m3 . go ( ) ;
Mixer m4 = m3 .m1; m4. go ( ) ;

Mixer m5 = m2.m1; m5.goo;


)
void go() { System.out.print("hi "); }

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.

B. A compilagio falha devido a um erro apenas na linha 3.

C. A compilaglo falha devido a um erro apenas na linha 4.

D. A compilagio falha devido a um erro apenas na linha 5.

E. A compilagio falha devido a erros nas linhas 3 e 5.


F. A compilagio falha devido a erros nas linhas 3,4 e 5.

8. Dado:
class Fizz {
int. x = 5;
public static void main(Stri-ng[] args) {

ftnaL Ftzz f1 = new Ftzz];


Ftzz f2 = new Fizz);
ELZZ T5 = E'LZZSWIECN\TI,TZ) i
System.out.println((f1 == f3) + " " + (fl-.x == f3.x) );
)

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.

B. Ap6s a execugio da linha 9.

C. Ap6s a execugXo da linha 10.

D. Ap6s a execugio da linha 11.


E. A compilagio falha
F. Nunca nesse programa.
a 4t r - r i
\r. .tr rangaoa uma excegio no tempo de execugio.

| 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

static { System.out.prj-nt("r4 "); }


]
class Hawk extends Raptor {
public staLic void main(String[] args) i
qa/cf am nri nf 1\nra ti l .
^rrf

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.

A, B, D, E e F estio incorretas com base no exposto acima. (Objetivo 7.4)

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'/.

A, B, D e E estio incorretas com base no exposto acima. (Objetivo 1.3)

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.

A, B, D, E, F e G estio incorretas com base no exposto acima. (Objectivo 1.3)

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.

A, B, C, D, E e F estio incorretas com base no exposto acima. (Objetivo 3.1)

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.

A, B, C, D e E estio incorretas com base no exposto acima. (Ob.ietivo7.3)

7. A estl correta, todas essas declarag6es de arrays sio v6lidas. As linha 4 e 5 demostram que arrays podem ser
convertidos.

B, C, D, E e F estio incorretas porque este c6digo compila. (Objetivo 1.3)

8. Aest6 correta. Asrefer€nciasfL,z ef3 apontamtodasparaamesmainstAncia deFizz. Omodificador


final assegura que uma vari|vel de refer6ncia nio poderi ser transferida para um objeto diferente, mas f inal
nio impede que o estado do objeto se modifique.

B, C, D, E e F estio incorretas com base no exposto acima. (Objetivo7.3)

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.

A, B, C, E, F e G estio incorretas com base no exposto acima. (Objetivo 7.3)

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.

B, C e F estio incorretas com base no exposto acima. (Objetivo 3.1)

12. Gest6correta. IJmerronalinhal0fazcomquesejalangadaumaNullPointerExcept.ion,porque e2 f.oi


definida como nulL na linha 8. Se a linha 10 fosse colocada entre as linha 7 e 8, entio F estaria correta, porque at6 que
a ultima refer€ncia seja anulada, nenhum dos objetos estari qualificado, e, depois de anulada a ultima referAncia, todos
os tr& estario qualificados.
A, B, C, D, E e F estlo incorretas com base no exposto acima. (Objetivo 7.4)

13. C e E apresentam sintaxe correta para se acessar um enum a paftir de outra classe.

A, B, D e F apresentam sintaxe incorreta. (Objetivo 1.3)

14. Desticorreta.Blocosinit static sloexecutadosnomomentoemqueaclasse6carregada,eosblocosinit


de instAncias rodam logo ap6s a chamada a super ( ) em um constmtor. Quando existem diversos blocos ini t de
um mesmo tipo dentro de uma classe, eles rodam ordenadamente, de cimapara baixo.

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

P&R Teste individuol

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.

Obietivo poro o certificoqdo

Operadores fava (Objetivo 7.6 do exame)


7.5 Escreuer aidigo que @lique czffetamente os operadores @rEiados, inc/uindo os de atibuigdo (linitadot a =, *=, -=), os operadoret
aritmdticos (linitados i,
a -, +, /, 0k, ++, - -), os operadores de comparagdo (initadw a 1, 1=, ),
)=, ==, !=), o operador insanceoJ
n,
os operadores llgicos (linitados a &, l, !, &&, l) e o operador condicional (?) para produ{r un resuhado duelado. Esreuer cddigo que
I
detenrine a igualdade de dois oQetos oa dois tiposprinitiuos.

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

OBSERVAQ6BS penrt O EXAME

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 Operadores de mudanga de bit


I Operadores bitwise

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.

Operadores de Atribuigio Compostos


Na verdade, existem cerca de 1 1 operadores de atribuiglo compostos, mas apenas os quatro mais comumente usados (+=, -
=, *= e / =), czem no exame (nio importa o que os obf etivos digam). Os operadores de atribuigio compostos permitem
que os digitadores preguigosos economizem algum trabalho de digrtagio. Eis v6rios exemplos de atribuig5es, primeiro sem
usar um operador composto,
JAVA 5 163

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.

oB SERVA9oBS pene O EXAME

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 ,'

if (sex <= 'f ') animal- = "female " + anj.mal-;


System.out.println("The animal is a " + 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

I Tipos booleanos primitivos


I Vari6veis de referdncia de obleto

Por6m, o que o operador == examina realmente? O valor da vari6vel - em outras palavras, o padreo de bits.

lgualdade de tipos primitivos


A maioria dos programadotes est6 familiarizada com a compangdo de valores primitivos. O c6digo a seguir mostta alguns
testes de igualdade em vari6veis primitivas:

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:

character 'a' == 'a'? true


character 'a' == 'b'? false
5 l= 6? true
5. 0 == 5IJ? Erue
true == false? false
Como podemos ver, se um nrimero de ponto flutuante for comparado com um inteko e os valores forem os mesmos, o
operador == tetotnard true como esperado.
JAVA 5 165

oBsERvAgOBs pene o ExAME


Ndocorfudaodnal=conooperador=--em*maexpressdobooleana.Oc6digoaseguiriuilido:

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 )

lgualdade de variiveis de refer6ncia


Como vimos anteriormente, duas vari6veis de refer6ncia podem apontar para o mesmo objeto, como o o..6o 6. g6digo
abaixo demonsffa:
JButton a = new Button("Exit") ;

'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:

import java. awt. Button;


class CompareReference {
1,uurru euaurc
*,,Lli^ ^r^el- void main(String IJ args) {
Button a = new Button (.,Exit" ) ;
Button b = new Button("Exit") ;
Button c = a;
System.out.println("Is reference a == b? " + (a == b));
System.out.println("Is reference a == c? " + (a == c));

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

lgualdade para Enums


Depois que vocd declarou um enum, ele nio pode ser expandido. Em tempo de execugdo, nio 6 possivel criar novas
constantes enum. E claro que voc€ pode ter tantas vari6veis quanto quiser apontando para uma dada constante enum, de
forma que 6 importante que se possa comparar duas vari6veis de refer6ncia enum para ver se sio "iguais", ou seja, se elas se
referem i mesma constante enum. Voc€ pode usar ou o operador == ou o m6todo equals ( ) para determinar se duas
vari6veis est6o se referindo i mesma constante entrm:
166 Copitulo 4: Operodores
class EnumEqual 1

anrrm (-nl // ; e Opc]-ona1


F--
[r-:E.rJ, }JLUE]
^-
public static void main(StringtJ args) {
Color c1 = Color.RED; Color c2 = Color.RED,'
if (c1 == c2) { System.out.println("==") ; }
if (c1.eguals (cz) ) { system.out.println("dot equals") r }

)i
O"Oj:"r o quanto ) i e feio, mas estamos preparando voc€ pa:ir- o exame). Esse exemplo produz a saida:

dot equals

Operador de comparageo instanceof


O operador instanceof 6 usado somente com vari6veis de referdncia de objeto, e voc6 pode empregiJo para verificar se
um objeto 6 de um tipo especifico. Por tipo, queremos dizer tipo de interface ou classe - em outras palavras, se o obfeto
referenciado pela vari6vel i esquerda do operador passaria no teste E-MBMBRO do tipo de interface ou classe do lado
direto do operador (o Capinrlo 2 abordou os relacionamentos E-MEMBRO com detalhes). O exemplo abaixo:
public static void main (string IJ args) {
afrih^
9u!f11: c - nau' v9rrllY
at-rina/trf^^r'\
\ lvv / ,

4+
f! |^ : F^+-h^6^f
frrDudrrus9r Cf r.i na\
oLrrrrY,/ I
\E t

System.out.print ( "s is a String" ) ;

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

oBSERVA9oSS pARA O EXAME


Pron'm perguntas eom instanceof que testem u um objeto i a instincia de lma interface, qaando a classe do objxo for implenentada
indiretamente. Una implenentagdo indinta ocore quando ma das superc/astes do oQeto implementa una intetface, ,^ i pnlpio classe da
institcia ndo ofaq- por exenplo,

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

Erro de Compilagio de instanceof


Nio6 possivel usar o operador instanceof para testar em duas hierarquias de classes diferentes, Por exemplo, o
seguinte c6digo ndo comptlatil:

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:

int [] nums = new int [3] ''


if (nums inst.anceof object) { } tt o resultado 6 true
Um anal rcnl rcmpre uma instdncia de Object. paalquer aray

A Tabela 4-1 resume o uso de instanceof presumindo-se o seguinte:


interface face { }
class Bar implements Face{ }
class Foo extends Bar { }

Iobelo 4-1 Operondos e resultodos do uso do operodor instanceof

Primeiro opetando Opemndo de instanceoj Resultado


(refer€ncia sendo testada) (tipo que compararemos
com a tefer€ncia)

null Qualquer tipo de interface ou classe false

instincia de Foo Foo, Bar, Face, Obiect

instincia de Bar Bar, Face, Object

instincia de Bar Foo false

Foo[ ] Foo, Bar, Face false

Foo[ ] Object

Foo[1] Foq Bar, Face, 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

O Operador Resto (o/o)


Um operador com o qual vocd pode n6o estar familiaizado 6 o operador de rcstooh. O operador de resto divide o
operando esquerdo pelo direito com o resultado sendo o resto, como o c6digo abaixo demonsffa:
class MathTest {
public static void main (string il args) {
int x = 15;
intY=x*4;
Swstem.ouf nrint-ln/"fhe rcsuft of L5 ? 4 is the remainder of
L5 divided by 4. The remainder is " + y) ;
1

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

Operador de concatenageo de strings


O sinal de adigdo tambdm pode ser usado para concatenar duas strings, como vimos anteriormente (e com certeza veremos
de novo):

String animal = "Grey " + ..elephant,,,.


A concatenagZo de Strings se tornari interessante quando voc6 combinar nirmeros com obietos String. Vedfique o c6digo a seguit:
String a = "String";
inl- l.r - ?.

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

De forma que poderiamos ler o c6digo anterior assrm:


"Comega com a String a, "String", e adiciona o caractere 3 (o valor de b) aela,pataproduzir uma nova string,
"String3",adicionando,ent6o,ocaractereT (ovalordec)aoresultadoparaproduziroutastri.ng,"string3?",e
exibi-la em seguida".
No entanto, se vocd inserit pardnteses envolvendo as duas vari6veis int, como vemos abaixo:
System.out.println(a + (b + c) );
obter6: String1O
O uso de parenteses fat6 com que @ + c) seja tratado primeiro, portanto, o operador 'l fancionat6 como o operador de
adigio, dado que os dois operandos sio valores int. O ponto chave aqui 6 que, dentro dos pardnteses, o operando da
esquerda nio 6 uma String. Se fosse, o operador I execttaiaaconcatenag6o de Strings. O c6digo anterior pode ser
lido da seguinte forma:
"Soma os valores de b + c, em seguida, converte a soma em uma string e corrc tena com a string da
vai|vela". ^

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

mas se a inshtgdo de saidafor alterada para

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

Aprimeiraexpresslocompar^x ey,eoresultado6false,potqueoacr6scimodex n6ooconer6antesqueotestedo


operador == seia executado. A seguir, aumentamos x e agora ele €.igad,a 3. Depois verificamos se x 6 menor do que y,
msailmentamlroualordey antesdecompari-locomxlPortanto,osegundotestel6gico6(3<4).Oresultado6t,rue,de
modo que a instrugZo de saida ser6 executada.

OBSERVAQ6ES pene O EXAME


Pmcare petgantas qlrc usen ot operadoret dc inmmento e dininligdo em uma aaridae/ f inal-,. Jd que as uaridaeis f i na I n6o podem ser
aheradas, os operadoret de inmmento e dininuQdo ndo poderdo ser asados com eks e qraQuer hntatiua defaTgr ilro wvltari em am ero do
compilador. O aidigo a nguir ndo nni co@ilada,

finalintx=5;
int y - x++,.
epmdt$ni o erm

Test.java:4: cannoL assign a value to final variable x


int y = x++i
Voc6 pode esperar uma violagio como essa camuflada em um trecho complexo de c6digo. Se identifici-la, saber6 que o
c6rligo nio seri compilado e poderi prosseguit sem percorrer o resto do c6digo.
Pode pareeer que essa qautdo uhi testando o seu conhecimento sobre um conplexo operador aitmitico, quando, na aerdade, estd testando o
sea conltecinento sobre o modificador f inal.

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:

x = (expressdo booleana) ? valor a atribuir se true: valor a atribuir se f al se


Examinemos um operador condicional no c6digo:
class Salary i
public static void main(String IJ args) {
i-nt numOf Pets = 3;
String status = (numOfPets<4)?,,Pet limit not exceeded,,:,,too many pets,,;
System.out.println(.'This pet status is '. + status) ,.

Voc6 poderia l.r o sfdigo anteriot assim:

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

Operadores Bitwise (Nno Caem no Exame!)


Certo, isto ser6 um pouco confuso. Dos seis operadores l6gicos listados acima, tr6s deles (&, I e ^) podem tamb6m ser
usados como operadores "bitwise". Os operadores bitwise foram incluidos em vers6es anteriores do exame, mas nio caem
no exameJava 5. Eis algumas instrug6es v6lidas que usam operadores bitwise:
byte b1 = 5 & 8;
DVle Dz = t | 9;
nya" Ua = 5 ^ 4;
System.out.println(b1 + " " + b2 + * \r + b3);
Os operadores biwise comparam duas vari6veis bit por bit, e retornam urnavari|vel cujos bits foram definidos com
base em se as duas vaddveis sendo compatadas tinham bits correspondentes que estavam ou ambos "ligados" (&), ou um
ou outro "ligado" ( | ), exatamente 116 "ligado" (^). A prop6sito, se rodarmos o c6digo anterior, teremos
""
015 1

Tendo dito tudo isso sobre operadores bitwise, o principal a se lembrar 6 isto:

OS OPERADORES BITWISE NAO CEPU NO EXAME!


Entio por que falamos deles? Se cair nas suas mios um livro antigo de preparagio para o exame, ou se encontrar alguns
.*"-.i simulados que ainda nio foram devidam ente atualizados, voc€ poder6 se deparar com quest6es envolvendo
operag5es bitwise. A nio ser que se sinta tio culpado a ponto de achar que merece esse tipo de punig6o, pode ignorar esse
tipo de questeo simulada.

Operadores L6gicos de Abreviagio


Hd cinco operadores l6gicos no exarne que sio usados para avaltar instrug6es que contenham mais de uma expressio
booleana. Desses cinco, os mais comumente usados sio os dois opetadotes l6gicos de abreriagAo. Sdo eles:
r && Edeabreviagio
I | | OU de abreviagio
Eles sio usados p^t iunt?Lrpequenas express6es boOleanaS a fim de formar express6es bool-eanaS maiotes' Os
operadores && e | | ava1am somente valores booleanos. Para uma expressio E (&&) ser verdadeira, ambos os
operandos ptecisam ser true - pot exemplo,
if ((2 < 3) && (3 < 4)) { }
A expressio anterior s6 6 true, porque tanto o operando um (2 < 3) quanto o operando dois (3 < 4) slo true.
O recurso de abreviagdo do operador && consiste no fato de ele ndo perder sea tempo em aua/iapder inilteis. O operador de
abrcviagdo && avalar|o lado esquerdo da operagio primeiro (operando um) e se esse operando tiver um resultado f a}se,
ele nio examinar6 o iado direito da equagio (operando dois), ]6 que o operador saber6 que a expressio completa neo ser6
u! uc.

uI4>D lUYrUAf I
public static void main(String [] args) {

boolean b = true && fal-se,'


s\/qram nrrt-.println("bool-ean b = " + b) ;

l
)

Quando executarmos o c6digo anterior, obteremos:


JAVA 5 I73
boolean b = false
O operador | | 6 semelhante ao operador &&, exceto p or ele avaliar como t rue se qualquer tm dot operadoret for t rue. Se
o primeiro operando de uma operagio OU for true, o resultado tamb6m ser6, portanto, o operador de abreviagio | | nio
perder6 tempo examinando o lado direito da equaglo. No entanto, se o primeiro operando for f alse, o operador tera que
avaliar o segundo operando para saber se o resultado da operagio OU ser6 L rue ou f a l- s e. Pteste bastante atengao no
exemplo a seguit; voc6 veri algumas pefguntas como esta no exame:
1. class TestOR {
2. public static void main (String [] args) t
3. if ((isrrsmall(3)) ll (isrrsmall(7))) {
4. System.out.println("Rqsu1t is true");
J

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

]-4. return true;


r_5. J erse t
l-6. System.out.printLn("i >= 5");
L7. return false;
18. )
t-e. )
20. )

Qual ser6 o resultado?


? java TestOR
1<5
Result is true
i>=5

Aqui est6 o que aconteceu quando o m6todo main ( ) foi executado:


1. Quando chegamos i linha 3, o pdmeiro operando da expressio | | (em ouuas palavras, o lado esquerdo da operagio
I l) foi avaliado.
2 O m6todo isltsmall- (3 ) foichamado, exibiu "i < 5" eretornou uerdadeiro.

3. J6queoprimeiroopetandodaexpressio ll,dalinha3,6igalatrue,ooperador llnioavaliar6osegundo


operando. Portanto, nunca veremos a frase "i >= 5", que teria sido exibida caso o segundo operando fosse avaliado
(chamando isItSmall (7 ) ).

4. A linha 6 set6,avaladaagora, comegando pelo primeito operando da expressio | |.

5. Om6todo isItSmall (6) 6chamado,eibe "i >= 5"eretorna faIse.


6. J6queoprimeiroopetandodaexpressio ll,dalinha6,6false,ooperador llnlopoder6ignorarosegundo
true, se o segundo operando for avaliado como true.
operando; ainda h6 uma chance da expressio ser
7. O mdtodo isItSmall (9 ) 6 chamado e exibe "i >= 5".
8. Om6todoisItSmall (9) retornafalse,portanto,aexpressiodalinha66false eahnirraT nuncaser6
executada.

oBSERVAQ6ES pene O EXAME

Osoperadoret &&e ll sdfuncionamcomoperandosbooleanos. Oexamepodetentarengand-lo,usandointeiroscrtltesseroperadoret;


174 Copitulo 4: Operodores
if (s && 6) t )

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.

Operadores l6gicos (que nio sio de abreviagio)


Existem dois operadores l6gicos que fio sdo de abreiagdo.

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.

Operadores de comparageo (Objetivo 7.6)


E Os operadores de compangdo sempre resultam em um valor booleano (t.rue ou f alse).
El H6 seis operadores de comparagao: ), )=, (, (=, == s l=. Os dois ultimos (-- .l-) sio, is vezes, chamados de
operadores de igualdade.

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.

Operador instanceof (Objetivo 7.6)


E instanceof s6 6 usado com variiveis de refer6ncia e verifica se o obieto 6 de um tipo especifico.
EI O operador instanceof s6 pode ser usado par^testr objetos (ou valores nuI1) confrontando-os com tipos de
classe que esteiam na mesma hieratquia da classe.

E Para intedaces, um obieto passa no teste instanceof se alguma de suas superclasses implementar a interface do
lado direito do operador instanceof .

Operadores aritm6ticos (Objetivo 7.6)


Cl H6 quatro operadores principais: adigio, subtragio, multiplicaglo e divislo.

E O operadot de testo (o/o) rctotnao resto de uma divis6o.


El As express6es sio avaliadas da esquerda p ata a dtreita,a n6o ser que voc€ adicione par6nteses, ou que alguns operadores
na expressio tenham maior preceddncia do que outros.

f,l Os operadores *, / e %o t6m maior preceddncia do que * e -.

Operador de concatenageo de strings (Objetivo 7.6)


f,l Se um dos operandos fot uma String, o operador * concatenat6" os operandos.
B Se os dois operandos forem num6ricos, o operador * somatl os operandos.
176 Copitulo 4: Operodores

Operadores de acr6scimo/decr6scimo (Objetivo 7.6)


D O opetador pr€-fixado 1+ + e -_) seri executado antes do valor ser usado na expressio.
E O operador p6s-fixado 1++ e --) ser6 executado depois que o valor for usado na expressio.
E Em qualquer expressiq os dois operandos sio avaliados integralmente antes que o operador se ia aphcado.
O O valor das variiveis f inal nio pode ser aumentado ou diminuido.

Ternirio (operador condicional) (Objetivo 7.6)


D Retorna um entre dois valotes baseando-se nos casos de uma expressi.o booleana ser true ou f alse.
E Retotna o valor depois de ? se a expressio for t rue
E Retorna o valor depois de : se a expressio for f a1se.

Operadores l6gicos (Objetivo7.6)


E O exame aborda seis operadores l6gicos: &, l, ^, !, && e | | .

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?

,{. Um deles compilari, apenas um ser6 true.


B. Dois deles compilario, true.
apenas um ser6

C. Dois deles compilario, dois serio true.


D. Tr€s deles compilardo, apenas um ser6 true.
E. Tt6s deles compilario, exatamente dois serio true.
F. Tr€s deles compilareo, exatamente tres sereo true.

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

if ((b1 = false) | (b1 & b3) (b1 | b2))


|

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.

E E langada uma excegao em tempo de execug6o.

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;

System. out.println (x) ;

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

A5 B, C, E e F estio incortetas com base no exposto acima. (Objetivo 7.6)

2. B e D usam cottetamente boxing e instanceof juntos.

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)

3. D est6 correta. Os fragmentos F2, F3 e F5 compilario, e apenas F3 6 true.


JAVA 5 I8I
4 B' C, E e F estio incorretas. F1 esti incorreta porque nio 6 possivel comparar um tipo primitivo com um anay.F4
usa sintaxe incoffet^Par^^cessar um elemento de um array bidimensional. (Obietivo 7.6)

4. E est6 correta. Pelo falo


{e
a abteiragdo ( | | ) neo ter sido usada, ambos os operandos sio avaliados. Uma vez que
args[1] esta^l6mdoslimitesdoanayargs,6,langadaumaArraylndexQutOfBoundsExr':ention
A B, C e D estio incorretas com base no exposto acima. (Objetivo 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

4 B, C, D, F, G e H est6o incorretas com base no exposto acima. (Objetivo 7.6)

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.

A B, C, D, E, F, H e I estio incorretas com base no exposto acima . (Objetivo 7.6)

8.

class Incr {

1,ularg ELdLru -void main(String[] args)


--,,h1 l^ ^r-rl^ t
Integer x = 7;
int Y = 2,
x*=x;
rr *-
r - rr.
r,
Y*=Yi
x_=y;
System. out . println (x) ,'

Sim, sabemos que isso 6 complicadq mas voc€ poder6 encontrar algo parecido no exame real. (Obietivo 7.6)

9. ADeFestiocorretas.O^(xor) tetorn true seexatamenteumoperandofortrue.O !inverteovalor


booleano do operando. Na linha 6,b2 = true 6 uma atribuigio, e nio uma comparagdo, e n6o 6 avaliada potque
& nlo serve d e abrcizgdo para ela.

B, C e E estao incorretas com base no exposto acima. (Obf etivo 7.6)

10. F est6 correta. O opendoroh (resto, tamb6m conhecido como m6dulo) retorna o resto de uma operagio de divis6o.

A B, C, D, E, G e H estAo incorretas com base no exposto zcin,:'a . (Objetivo 7.6)


182 Copftulo 4: Operodores
Controle de fluxo,
excesoes e
assertivas

Obierivos pqrq q
certificqe6o
I Usor InstruE6es if e switch

I Desenvolver Loops {or, do e while.


Usor Instruq6es breok e continue

I Desenvolver C6digo com Assertivos

I Usor lnstruq6es try cotch e {inolly

I Descrever o Efeiio dos ExceE6es

I Reconheceros Excec6es mqis


Comuns

( Exercicios r6pidos

P&R Teste individuol


.|84
Copitulo 5: Controle de fluxo, exceg6es e ossedivos
VocA consegr.re imaginartentando escreverum c6digo com umalinguagem que.n|g fornepauma maneira de executar
se
insru96es clondicionimente? O controle de fluxo 6 uira parte chave de quase ioda linguagem de programaXg qil , e alava
oferecl virias maneiras de execut4-lo. Algumas, como asinstrug6es i f i loops f or, iio comuns i maioria das linguagens.
Mas aJava tamb6m introduz algon, ,e.rriror de controle de fluxo que voc6 pode nlo ter usado antes - exceg6es e assenivas'

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.

Obietivo poro o certificoc6o

Escrevendo o c6digo usando instrus6es if e switch


(Objetivo 2. I do exame)
2./ Escreuer cfidigo qae inplenente ama instrugdo f ou switch; identifcar os tipos de atgunentr uti/idos para essas in.rtrapda.

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" ) ;

A expresslo entre par6ntes es deaeter corrro resultado um valor booleano true


ou f alse. Normalmente voc6 testari
algo para sabe r se 6, uerdadeiro e, em seguida, executar6 um bloco de c6digo (uma ou mais instrug6es) se o resultado for
mesmo uerdadeim e (opcionalmente) outro bloco de c6digo se nio o for. O c6digo a seguir demonstra uma instrugio i f
vAlida:

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

if (x > 3l / / n6o recomendado, mas poder6 aparecer no exame


JAVA 5 I85
Y=2i
z += 8;
a-y+x,.
A Sun considera como boa pr6tica colocar blocos dentro
de chaves, mesmo que s6 haia uma instrugio no bloco. Seja
cuidadoso com c6digos como esse, porque voc6 pode pensar que ele deve sei lido assim:

"Se xfor maior qrc 3, mtdo nnfgurc-1t eoa 2, qcom !8 e a comJlx".


Contudo, as duas riltimas linhas serio executadas de qualquer forma! Elas nio {azempane dofltxo condicional. VocA o
acharia ainda mais confirso se estivesse recuado como vemos abaixo:
if (x>3)
Y=2;
z += 8;
a=y+x;
Podesernecessirioaninhar_insrug6es if-else(emboratamb6mnXosejarecomendadoporraz6esdelegibilidade,
poftanto' testes i f aninhados devem ser mantidos em uma quantidade minima). Voc6 poder6 configurar uma instrugio
fehe p.ara que teste v6rias condig6es. O exemplo abaixo usa duas condig6es de modo que r o primeiro teste for bem
sucedido, executaremos um segundo teste antes de decidir o que fazer:

if (price < 300) {


hl11tDr^.11r^t a \ .

] 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 if (price < 400) {


getApproval ();

) 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

O exemplo produz estasaida:


<4

(R.epareque,mesmoqueosegundoelse sejaverdadeiro,aexecugionuncachegaaele.)

Emalgunscasos,voc6podeterdificuldadesemdescobrircomqualif oseuefse deveserpareado,comoneste


exemplo:
if (exam.doneO )

if (exam.getScoreO < 0.61)


q1/ctam
ujeevlrL.vsu.y!rrru+nrrt- nrin1- lnlt\Tr\/ aa:in "):

/ / A qoa\ if isto pertence?


el-se System.out.println("Java master! ") ;

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/\\

if (exam.getscoreO < 0.61)


System. out.println ( "Try again. ");
// A gual if isto pertence?
el-se
System. out.println ( ".fava master! ");

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

/ / A qoa1- if isto pertence?


)e1se {
System. out.println ( ",Java master I " ) ;
)

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 )

if (exam.getscoreO < 0.61)


System. out.println ( "Try again. ");
else
System.out.println("rTava master!"); / / Hmmmmm.'. e isLo aqui vai para onde?
E claro que o c6digo anterior 6 exatamente o mesmo dos dois rlltimos exemplos, exceto pelo seu formato.

Express6es v6lidas para instrug6es if


As instrug6es i f s6 podem avaliar valores booleanos. Qualquer expressio que tenha como resultado um valor
booleano seriadequada,masalgumasdelaspodemsercomplexas.SuponhamosquedoStuff ( )retornetrue,
int Y = 5,'
int x = 2;
if (((x > 3) && (y < 2)) | aostuttt)) i
q\rql-om nrrf nrinf lnl"rrrra/1.
JAVA5 187
)

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:

boolean boo = false:


if (boo = true) { }
Vocd pode achar ama enlre trds coitas:

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:

{ } // Ndo compila, porqtue x ndo 6 um booleano!


J,i que os testes f requeren expressdu boo/eanas, uocd precisa ter um conhecimento srilido tanto sobre os operadoret ldgicos qaanto sobre a
intaxe e remdntica do teste if .
188 Copftulo 5: Controle de fluxo, exceq6es e ossertivos

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

Express6es vilidas para switch e case


A forma geral da instrugio switch 6

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:

Test.java:6: possible foss of precision


found : i-nt
required: byte
case 128:

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.

Break e a passagem completa em blocos switch


Finalmente estamos prontos para discutir a instrugio break e mais detalhes sobre o controle de fluxo dentro de uma
instrugio switch. O mais importante a se lembrar sobre o fltrxo da execugio atrav6s de uma instruglo switch 6 o seguinte:
As con$antes case sdo aualiadat de cima para baixo, ea pineira clnrtafite case que bater com a exprusdo swi tch serri o ponto
de enlrada da exuupio.

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

instrugioswitch ou at6 que a instrugio termine. Observe o c6digo a seguir:


i-nt x = 1;
switch (x) {
case 1: System.out.println("x is one"),.
case 2: System.out.println(..x is two,,);
case 3 : System. out.println ( "x is three" ) ;

]
Syst.em. out.println ( "out of the switch" ) ;

O c6digo exibiri o seguinte:


x l_s one
x is two
x is three
out of the switch
Essacombinagio ocorreuporque o-c6digo nioghegou aumainstrugXobreak; poryagtg, l execu{io simplesmente
continuou a percorrer cada instrugio case at6 o final. Esse processamento na verdade 6 chamado de "passagem
completa" por causa da maneira como a execugio passa de uma instrugio case para a seguinte, Con.riderv a in$ntg6o case
satifafllia sinplesrnente corzo seu ponto de entrada no bloco swiLch/Em outras palavras, voc| ndo deve consideri-la assim:
"Encontre a instrugio case sadsfat6ria, execute apenas esse c6digo e saia da instrugio". Nio 6 dessa forma que funciona.
Se vocA quiser mesmo o compoftamento de "interesse apenas no c6digo satisfat6rio", insira uma palavra break em cada
instrugio case como vemos abaixo:
int x = 1;
switch (x) {
case l-: {
System.out..println("x is one") ; break;
)
taea ). I

System. out.println ( "x is two" ) ,'


]
naca ?. I

System. out.printfn( "x is two" ) ; break;


)

System.out.println( "out of the switch"),'


A execugio do c6digo anterior, agora que adicionamos as instrug6es brealg exibirS
x is one
out of the switch
es6.Entramosnoblocoswitch nainstrugiocase l.JAqueelaapresentouumacorrespond6nciacomoargumento
swi tch ( ) , passamos para a instrugio println, atingimos a palavra break e saltamos para o fim da instrugXo swi tch.
Um exemplo interessante dessa l6gica da passagem completa 6 mostrado no c6digo abaixo:
int x = someNumberBetweenoneAndTen;
switch (x) {
case 2:
case 4:
case 6:
case B:
a:ca 1O. t
192 Copitulo 5: Conirole de {luxo, exceg6es e ossertivos
System.out.println("x is an even nuricer") ; break;

)
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. : System. out.println ( "default" );


case 3 : System.out.println("3") ;
case 4: System.out.println( "4" ) ;
]
A exwugdo do aidtgo anterior exibini

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

case : System.out.println ( "4"


4 );
)

A exultpho do cddigo anteior exibini

default

Aregraalembrar,iqaeainstrugdodefault fancionaexatanentec0m0qtlalqilerzutrainstril(Aocase fiaparsagem


conpleta!

Exercfcio 5- 1

Criando uma instrugio switch-case


Tentecriarumainstrugioswitch-case usandoumvalorchar comoainstruEiocase. Incluaumcomportamento
padrio para o caso de nenhum dos valores char ser satisfat6rio.
I Cenifique-se de que umavariivel char seja declarada antes da instrugio switch.

I Cada instrugio case deve ser seguida de uma instrugio break.


I O valor default pode ser inserido no fim, na metade ou no inicio.

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.

Usando loops while


O loop whi 1e seri adequado em cenirios nos quais voc6 nXo souber quantas vezes o bloco ou instnrgio teri que ser
repeti{o,masquiserqueiuaexecugiocontinueit6quealgumacondig{o*jauerdadeira.Ainstruglow}rile temoformato
asegur:
while (expressSo) {
/ / faz al-go
i
ou
int x = 2;
while(x == 2) {
System. out.println (x) ,.

++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

while (int x = 2) { } / / inv5l-ido


Mas tamb6m por que voc6 faria isso? Em vez de testar a variivel, voc6 estaria declarando e incializandoa, portanto, ela teria
sempre o mesmo valor. Nlo seria uma condigio de teste adequada!

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" ) ;

A execuglo desse c6digo produziri


past the loop
Pelofatodeaexpressio(* > 8) avaliarcomo false,oc6digodentrodoloopwhile nuncaser|exeantado.

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

while (true) { } / / var)-do

Usando loops for


ComoadventodoJava5,oloopfor adquiriuumasegundaestrutura.N6schamaremosoestiloantigodoloopfor
de "loop f or bisico", e chamaremos o novo estilo de "loop f or aprimorado" (embora o obj etivo2.2da Sun se refira a
or- each). Dependendo de qual docum enta&o vocA' usar (incluindo a da Sun), ver6 ambos os termos, junto
ele como f
comfor-in.Ostermosfor-in,for-eache"for aprimorado"referem-setodosaomesmoconstrutorJava.
O loop f or b6sico 6 mais fleivel do que o aprimorado, mas o loop aprimorado foi criado para facilitar a programagio de
iterag6es atrav6s de arrays e de conjuntos.
JAVAs I95
O Loop for Bisico
for ser6 panicularmente
O loop ritil para o controle do fluxo quando voc€ ji souber quantas vezes teri que executar as
instru96es do bloco do loop. A declaraEio do loop f or possui tr6s partes principais, al6m do corpo do loop:

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
]

Loop for B6sico: Declaragio e inicializagio


A primeira parte da instrugio for permite que voc6 declare e inicialize nenhuma, uma ou diversas variiveis do mesmo
tipo dentro dos par6nteses ap6s a palavra-chave f or. Se voc6 declarar mais de uma variivel do mesmo tipo, terA que separi-
las comvirgulas como nalinha abaixo:

for (intx = 10, Y = 3; Y > 3; y++) { }

A for. E enquanto as outras duas partes - o teste


dularagdo e inicialiTagdo ocorrem antes de qualqaeroutra coisa em um loop
booleano e a expressio de iteraglo - sio executadas a cada iteragXo do loop, a declaraSo e ancialbaSo ocorrem apenas uma
vez, logo no inicio. VocA tamb6m precisa saber qwe o ucopo das aaiiueis dularadat no loop f terminajanto com o loop!O or
c6digo abaixo demonstra isso:
for (int x = 1; x < 2; x++) {
System.out.println(x) ; // V6lido
]
System.out.println(x); // InvaLido! x agora estii fora de escopo
/ / e nl.o pode ser acessado
Se voc6 tentarcompilar ese c6digo, obter6
Test. java: : cannot regolve
19 symbol
symbol : variable x
location: class Test
System. out.println (x) ;

Loop for B6sico: Expressio cond:cional (booleana)


A pr6xima segio a ser executada ser6 a expressio condicional, que (como todos os outros testes condicionais) tenlque
resultar em um valor booleano. VocA pode ter somente uma expressio l6gica, por6m, ela pode ser muito complexa.
Cuidado com c6digos que usem express6es l6gicas como esta:
for (int x = 0; (( ((x < 10) aa (y- - > 2)) | x --
--
?\ \.
J
| |
vrr\ / \

O c6digo anterior 6 v6lido, mas o seguint e ndo o 6:


for (int x = 0; (x > 5), (y < 2); x++) { }
| / ^--^^^^^ a^

/ / avnraccAoq

O compilador lhe informari do problema:


Testlonq. Java:20: ';' expected
for (int x = 0; (x > 5), (y.2) ; x++) { }

A regra a lembrar 6 esta: ,.a r)port, nrn*o exprerrao de teste.


195 Copitulo 5: Controle de fluxo, exceg6es e ossertivos
Em outras palavras, voc6 nio pode usar v6rios testes separados por virgulas, ainda que as ounas dvas partes de uma
instrugio for possam ter virias seg6es.

Loop for B6sico: Expressio de iteragiio


Ap6s cada execugio do colpo do loop for, a expressXo de iteragio ser6 processada. E tr.rr" p"rt. que voc€ poderi informar
o que deseja que acontegaacadaiteragio do loop. Lembre-se de que ela semp re ocorreri depoisque o corpo do loop f or for
executado! Observe a linha a segu.ir:
for (int x = 0; x < 1; x++) i
/ / c6digo do corpo que n6o modifica o valor de x
]
O loop anterior ser6 executado apenas uma vez. Na primeira vez em que entrarmos no loop, x seri configurado com 0 e
testado para sabermos se 6 menor do que 7 (e seri), paraque depois o corpo do loop seja executado. Ap6s a execugXo do
corpo do loop, a expressio de iteraglo ser6 processada, aumentando x em uma uni&de. A seguir, o teste condicional seri
verificadoej6queoresultadoagoraserlfalse,aexecugiosaltar|parabaixodoloopfor edariprosseguimentoapaftir
dd.
Tenha em mente que, fora uma saida forgada, as avaliag6es da expressio de iteragio e, posteriormente, da
expressio condicional, sio sempre as duas tltimas coisas a ocorrer em um loop for!
Exemplos de saidas forgadas incluem um break, um return, uma excegio, ou uma instrugio System. exit ( ), todas
fazem com que o loop seja encerrado repentinamente, sem executar a expressio de iteragSo. Examine o c6digo a seguir:

static boolean dostuff ( ) {


for (int x = 0; x < 3; x++) i
System.out.println ( "in for loop" ) ;
return t.rue;
]
return true;
)

A execugio desse c6digo produzir6


in for loop
O resultado da instrugio ser6 exibido apenas umavez, porque a instruglo return far6 com que a execugXo saia nio s6 da
iteragio atual do loop, mas de todo o m6todo. Portanto, a expresslo de iteragio nunca seri executada nesse caso. A Tabela 5-
L lista as causas e resultados da finalizaglo repentina dos loops.

Tobelo 5-l Cousos do finolizoE6o ontecipodo do loop

C6digo do loop O queacontecer5

break A execu$o saltari imediatamente para a primeira instru$o ap6s o loop


for.
reE,urn A execucio retornari imediatamente ao m6todo chamador.

System. exit ( ) A execugio do programa ser6 completamente interrompida; o VM


ser6encerrado.

Loop for B6sico: Caracteristicas do loop for


Nenhuma das tr6s seg6es da declaragio do loop f or sio necess6rias! O exemplo a seguir 6 perfeitamente vilido (embora
nio seja necessariamente uma boapritica):
for( ; ; ) {
System.out.println( "Inside an endless 1oop") ;
]
No exemplo anterior, todas as partes da declaragio foram
deixadas de fora, portxoto, o c6digo agir6 como um loop infinito.
No exame, ser6 importante saber que com a au$ncia das seg5es de declaragio elntcializagio, o loop agiri como um loop
whil-e. O exemplo abaixo demonstra como isso acontece:
JAVA 5 I97
i-f i - n.

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.

for (int i = 0, j = 0; (i<l-0) && (j<10),- i++, j++) {

SysLem.out.println("i is " + i + " j is " +j) ;


)

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 { }

System. out.prlntln (x) ;

efiquanto esse ndo d,

for (i-nt. x = 3; x < 20; x++) { }System.out.println(x) ;


A riltima coisa que deve ser ressaltada 6 qu e todas as trts rcgdes do lnop f or sdo independrntes uma da outra. As tr6s express6es da
instrugio f or nio precisam operar sobre as mesmas vari6veis, embora normalmente o fagam. Por6m, at6 a expressao de
intera$o, que muitas pessoas chamam erroneamente de "expressio de incremento", nio precisa incrementar ou configut"r
algo; vodpode inserirvinualmente qualquerinstru$o que qlreiraa(ecutar acadaiten$odo loop. Observe o c6digo aseguin

int b = 3;
for (int a = I; b != 1; System.out.println("iterate") ) {

b=b-a;
)

O c6digo arrterior exibiri


iterate
iterate

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.

O Loop for Aprimorado (para Arrays)


Oloopforaprimorado,umanovidadedeJava5,6umloopfor especializadoquesimplificaatarefadesefazerumloop
atrav6s de um array ou um conjunto. Neste capitulo, vamos nos concentrar no uso do f or
aprimorado para fazer loops
atrav6s de arrays. No Capitulo 7, revisaremos o f or
aprimorado ao discutirmos os conjuntos - que 6 onde o f or
aprimorado realmente faz a diferenga.
Em vez de ter hts componentes, o f or aprimorado t em dois. Vamos fazer um loop atrav6s de um array & forma bisica
(antiga), e depois usando o for aprimorado:

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

O que produz esta saida:

L234L234
Mais formalmente, vamos descrever o for aprimorado da seguinte forma:
fnrldanl araaVa . avnraq<Anl

As duas panes da instrugio f or sio:


I Declarag6o A vari6vel de bloco rudm-dularada, de um tipo compativel com os elementos do array que voc6
esti acessando. Essa vari6vel estari disponivel dentro do bloco f or, e o seu valor ser6 o mesmo que o do
elemento atual do array.
I Expressio Estadeveavaliarcomooaffayatrav6sdoqualvocequerfazeroloop.PodeserumavariAve|dearray
ou uma chamada a m6todo que retorne um array. O array pode ser de qualquer tipo: primitivo, objeto, at6 mesmo array
contendo arrays.

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.

Usando break e continue


break e continue sio usadas para encerrar o loop inteiro (break) ou apenas a iterageo atual
As palavras-chave
(continue). Normalmente, quando usamos break ou continue, executamos um teste i f dentro do loop e se
algumacondi$ofortrue (oufal-se dependendodoprograma),saimosdeleimediatamente.Adiferengaentreessas
palavras 6 se ser6 ou nio dado prosseguimente com a execugio de uma nova iteragio ou se salaremos para a primeira
instrugio depois do loop e continuaremos o processamento a partir dai.
JAVA 5 I99
oBSERVAe6rspeneoErreME
Lembre-r de que as inshagdet continue
deuem ser inseridat dentw do loop; do contuiio, uocl uerti am erm do conpilador. At inshagdu
break deuem ter usadat denho do kop ou de uma in$rugdo swi tch. Oburuagdo: Iso ndo v aplica a insturgdetbreak mtuladas.

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

Instrug6es neo rotuladas


Tanto a break quanto continue podem ser nlo-rotuladas ou rotuladas. Embora seja muito mais comum
instrugio
break e continue nio rotuladas, no exame ser6 esperado que voc6 saiba como as instrug6es break
usar instrug6es
e conEinue rotuladas funcionam. Como mencionado antes, a instrugio break (n1o-rotulada) sairi da estrutura do
loop atual e prosseguir6 na linha de c6digo posterior ao bloco do loop. O exemplo abaixo demonstra uma instrugio
break:
boofean problem = truei
whife (t.rue) {
r f lnr^h I aml {

System.out.println("There was a problem" ) ;

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

continue; / / passa para o campo seguinte do arquivo


)

/ / caso contr5rio, faz outras coj-sas com o campo


200 Copftulo 5: Controle de {luxo, exceE6es e ossertivos

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

Criando um loop while rotulado


Tente criar um loop whi 1e rotulado. Crie o r6tulo outer e fornega uma condigio para verificar se a idade em uma
variivel 6 menor ou igual a 21.
lentro do loop, ela deve aumentar a idade em uma unidade. A cada vez que o loop for
percorrido, ela verificari se a idade 6 igual a 16. Caso afirmativo, uma mensagem seri exibida solicitando sua licengi de
motorista e o fluxo continuar6 no loop externo. Do contririo, apenas seri exibida a mensagem "Another year".
r O r6tulo outer deve ficar exatamente antes do loop while comegar. Nio imporra se na mesma linha ou nlo.
I Certifique-se de que a variAvel age seja declarada fora do loop uft i 1e.

PREI'ARAQAO PARA O E)GME

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

Capturando trma excegeo usando trf e catch


Antes de comegannos, introduziremos a terminologia. O termo exapnn signtfrca'tondi$o excepcional", e 6 uma ocorr6ncia
que akera o fluxo normal do programa. V6rias coisas podem levar a exceg6es, incluindo falhas no hardware, exaustio &
rturror. os famosos erros. Qr"ndo nrn wento excepcional ocorre emJav4 diz-se que uma exce$o srcr| kngtla. O c6digo que
6 respons6vel por faznr algo com a exce$o 6 chamado de manipaladnr dz exce@s, ele captura a exce$o langada

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\ {

13. // Insira um c6digo aqui que manipule essa excegdo.


1.4. j
15.
16. / / Algum outro c6digo nao protegido (comum, ndo arriscado) comeqar6 aqui
Nesse exemplo de pseudoc6digo, as linhas 2 a5 constituema regiio protegida que ser6 controladapela cl6usula try. A
linha sete 6 o manipulador para uma excegio do tipo MyFirstException. A Linha 12 6 um manipulador para uma excegeo
do tipo MySecondException. Observe que os blocos catch aparecem imediatamente ap6s o bloco try.
Isso 6 um
requisito; se uocd tiuer um ou mait blocos catchi, eles deuem @arecer imediatamente @d: o bkco try.
Al6m disso, todos os blocos
calch precisam ficar um ap6s o outro, rcm nenhuma instrugdo ou bloco entre elet A ordem na qual os blocos catch
forem
inseridos tamb6m importa, como veremos posteriormente.

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.

Oblocofinally enfeixar6oc6digo,quevnpreserS,exesfiadoemalgumpontodepoisdobloco Lry,vunaexcegdofor


langada oundo.Mesmo se houver uma instrugio de retorno no bloco t.ry, o bloco f ina11y seri executado logo ap6s essa
instrugio!Esse 6 o local certopara fecharseus arquivos,liberarseus sockets de rede e executar qualquer outralimpezaque seu
c6digo necessitar. Se o bloco try
for executado sem exceg6es, o bloco f ina11y ser6 processado imediataminte ap6s o
blocotry serconcluido.Sehouverumaexcegio,oblocofinally seriexecutadologodepoisqueoblococatch
apropriado for concluido.

Examinemos outro exemplo de pseudoc6digo:


1: try i
2t // EsLa 6 a primeira linha da "regi5.o resguardada".

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
)

/ nd.o se pode ter c6digo entre trylcatch


/
System.out.println( "out of try b1ock" ) ;
catch(Exception ex) { }

oBSERVAQ6ES penn O EJGME

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) { }

Propagando exceg6es nio capturadas


Por que as cliusulas catch nio sio necessirias? O que acontecerA a uma excegao que for langada em um bloco try
quando nio houver nenhuma cl6usula catch esperando por ela? Realmente, nio 6 um requisito a codificagio de uma
cliusula catch paracada excegio que possa ser langada no bloco try correspondente. Na verdade, hi drividas
se 6 possivel conseguir tal proezal Quando um m6todo nio fornece uma cl6usula catch para uma excegio
especifica, diz-se que esse m6todo est6 "passando" a excegio (ou "passando a responsabilidade").
JAVA 5 205
EntXo, o que acontecer6 a uma excegio transferida? Antes de discutirmos isso, precisamos revisar rapidamente o conceito de
pi/ba de rbanadar A maioria das linguagens apresenta o conceito de uma pilha ie m6todos ou de chamadas. Colocando de
maneira simples, a pilha de chamadas 6 a cadeia de m6todor qn. r.,r programa executari para chegar ao m6todo atual. Se seu
-a
Programa comeqar no m6todo main (
) e este chamar o m6todo (
) , que chamari b m6tod6 U ) que, por s uavez, (
chamar6om6todoc( ),apilhadechamadaspoder6serrepresentadadamaneiraaseguir:

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.

l) A pilha de chamadas enquanto method30 esfi sendo executado.


4 method2fl chama method30
3 method l0 chama method2$
z main chama methodl0
I main inicia

A ordem na qual os m6todos sio colocados na pilha de chamadas

2)A pilha de chamadas enquanto method3$ esti sendo executado.


A execugio volta para method2Q
I T methatQ I method2Q vai finalizar
2 [ method$-l method l() vai finalizar
t [:"3ajn"-o*J main0 vai finalizar e aJVM terminari a sua execugio

A ordem na qual os m6todos finalizam

Figuro 5-l A pilho de chomodqs de m6todos do Jovo

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

static void doStuff ( ) t


doMoreStuff ( );

]
206 Copftulo 5: Controle de fluxo, exceg6es e ossertivos

static void doMoreStuff O {

i-nt x= 5/0; // rmpossivel dividir por zero! ArithmeticException 6 alocado aqul


)

)
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

Propagando e capturando uma excegao


Neste exercicio tentaremos criar dois m6todos que lidarlo com exceg6es. Um deles 6 o m6todo main ) , que chamari (
outro m6todo. Se uma excegio for langada no outro m6todo, ele teri que manipuliJa. Uma instrugio f seri inally
incluida para indicar que tudo foi concluido. O m6todo chamado serd denominado reverse, e inverteri a ordem dos
caracreres da string. Se a string nXo tiver caracteres, ele propagari uma excegXo at6 o m6todo main ). (
I Crie uma classe chamada Propagate e um mdtodo main ( ) , que perm anecerAvazio por enquanto.
r Crie um m6todo chamado reverse. Ele usar6 como argumento e retornar6uma string.

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

Figuro 5-2 Hierorquio do closse Exception


208 Copitulo 5: Controle de fluxo, exceg6es e ossertivos

Manipulando uma hierarquia inteira de classes de exces6es


Vimos que a palavra-chave catch permite a especificagXo do tipo de excegio que seri capturado. Na verdade'
poi. ."itnt". nais de um tipo de exceglo .- ,rttt" rinica cliusula catch. Se a classe de excegio que _v_oc6
',roc€
.rp..ifi."t na cl6usula catch nio tiver subclasses, entio, somente a classe especificada ser6 capturada' No
entanto, se a classe especificada na clAusula catch tiver subclasses, qualquer objeto de excegio com .rabclasses da classe

especifcada mmb6m seni c@tarado.

Por exemplo, a classe TndexoutofBoundsException possui duas subclasses,


ArraylndexoutOfBound,sExcetion e Stringlnd,exOutOfBoundsExcetion. VocA pode querer escrever
um manipulador que lide com as exceg6es produzidas pelos dois tipos de erro de intervalo, mas talvez nlo esteja
preocupado com qual exceglo foi realmenti gerada. Nesse caso, poderia escrever uma cl6usula catch como a seguinte:
try {

/ / Alg,rm c6digo aqui capaz de lanqar uma excegao de limites


]
catch (IndexOutOfBoundsException e) {

e . printStackTrace ( );
)

Se algum c6digo do bloco try langarArrayrndexoutof BoundsExcetion ou


Stringlndexoutof Bound.sExcetion, excegio seri capturada e manipulada. Isso pode ser conveniente, mas
a
deve ser usado moderadamente. Ao especificar a superclasse de uma classe de excegio em sua cl6usula catch, voc6
descartari informag6es valiosa, sobre ,^.xcegio. E claro que voc6 pode descobrt exatamente que classe de excegio foi gerad4
mas se quiser fazer isso, ser6 melhor escrever uma cliusula catch separada para cada tipo de excegio que lhe interessar.

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

7: byte b[] = new byte[1000];


8: raf.readFully(U, 0. 1000);
JAVA 5 209

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

Observe que acliusula caLch, de FileNotFound.Exception, foi inserida acimado manipuladorde


loException. Isso d importantelSe for feito de maneira inversa, o programa nio sericomplado. Os nanipuladores de
excegdet mais espedfcos deuen sempre ser inseridos acima dos de exngdu gerais. O c6digo a seguir nio ser6 compilado:

try {
/ / faz operag6es de E/S arriscadas
) catch (IOException e) t
/ / traLa loExceptions qerais
) catch (Fil-eNotFoundException ex) {
/ / Lrata apenas FileNotFoundException
)

Voc€ obteri o seguinte erro de compilador:

TestEx. java: 15 : exception java. io. FileNotFoundException has


already been caug'ht
] catch (FileNotFoundException ex) {

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

Declaragio de exces6es e a interface priblica


Certo, como saberemos que um m6todo langariuma excegXo que teremos que capturar? Da mesma forma que um
m6todo precisa especificai que tipo e quantos argumentos aceitari, e o que seri retornado, as exceg6es_gue Ym
m6todo pode langar derr* ser declaradas (a menoi que sejam subclasses de RuntimeException)'_Alista de
exceg6es lang adas faz pane da interface priblica de um m6todo. A palavra-chave throws 6 usada da forma
descrita a seguir para listar as exceg6es que um m6todo pode langar:

void myFunctionO throrus MyExceptionl, MyException2 {

/ / c6digo para o m6todo aqui


)

Esse m6todo tem um tipo de retorno void, que exceg6es do tipo


nio aceita argumentos e declara que langa duas
MyExceptionl eMyuxception2 (s6porqueom6todo declaraquelangaumaexcegeoniosignificaquesemPreo
fani. Ele ap enas inf o rma qu e p o fu faz|-lo).
Suponhamos que seu m6todo nio langasse diretamente uma excegXo, mas chamasse um m6todo parafa{-lo. Voc6 pode _

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

oBSERVAQ6ES pene O F)GME


Procure aidigcs qae charuem am mdtodo para declarar ama excepdo, na qaal o ndtodo que esrtuer chamando ndo manipa/e ou declare a exceg1o
uerifcada. O cddigo a ngair (que usa a palaura-chaue throw
para langar uma excegdo manaalmente - falaremos mais sobre isso a segair)
@ntenta dois grandes problenas qae o conpilador euitani:

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

fosse corigido da maneira a segair:


void doMore O throws lOException { ... i
OnitododoStuff ( ) ainda@re-rentardproblemasporqueeletanbimprecindeclararaexcegdolOException,amenlrqilea
nanipule por meio do fomecimento de am bloco Lry f caLch, com una cllasala catch que posta tratar a exregio
JUE;XCe1)C.r_On.

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;
]
)

ExaminemosmyMethodl( ).J6queaexcegioEoFException 6subclassedeToException,que,porsuavez,6


dg o<ception, elaser6,verificadaedeve serdeclaradacomoumaexcegeo quepode ser langadaporlsse m&odo. Mas
rybclasse
de onde realmente vir6 a exce$o? A interface priblica do m6todo mlzMethod2 ( ) cliam-ada aqui, declara que uma exce$o
das5stipopodeserlangda. Se esse m6todo realmente langar6 aexceSo ouchamar6outro m6todoparalang6-14 nlotem-
importAncia; apenas sabemos que temos de captlrar a exce$o ou declarar que a lanEamos. O m6todo myzt{ethodl ( ) nio
captura a excefro, portanto, decl ara que alanprL Agora examinemos outro exemplo vilido, qilethod3 ( ) .
public void myMethod3 ( ) {
// Ponha aqui algum c6digo que jogue uma NullPointerException
)
De acordo como comentirio, m6todopode langaruma excegioNullPointerException.J6que
esse
RuntimeException 6asuperclasseimediatadeNul-lPointerException,ela6umaexcegao nioueifcadaenio
precisar6 ser declarada. Podemos ver que myMethod ( ) nio declarou nenhuma excegio.

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 {

throw new MyException (l ; // LanCa uma exceqSo verificada

)
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

class MyException extends Except.ion {


void someMethod O {
doStuff ( ) ;
]
212 Copitulo 5: Controle de fluxo, exceE5es e ossertivos

void doStuff ( ) throws MyException


trY {
fhrat^t narrr MlrFv^ani i nn / ) .

catch(MyException me) {

throw me,'

Vocd terd que uber que esse cfidigo ndo serd nmpilado. Se tentar corzpild-lo, obteni

TestEx.java:8: unreported exception MyException; must be caught or


declared to be thrown
doStuff ( ) ;

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.

Relangando a mesma excesao


Damesma forma que voc6 pode langaruma novaexceglo apartir de umacl6usula catch, tamb6mpodelangara mesma
excegio que acabou de capturar. Aqui est6 uma cliusula catch que faz isto:
catch(IOException e) {
/ / paz coisas, e se voc6 decidir depois que ndo vai fazer o tratamenEo. . .
throw e;
]
Todas as outras cl6usulas catch associadas ao mesmo bloco try
serio ignoradas, um bloco f ina11y, se existir, seri
executado e a excegio ser6langada novamente para o m6todo chamador (o pr6ximo m6todo na pilha de chamadas). Se voc6
langaruma excegio verificada a partir de uma cl6usula catch, tamb6m t er|, que dzclararessa excegio! Em outras palavr as,ter|
quemanipularedeclarar,eniomanipular oudeclarar.Oexemploaseguirnio6v6lido:
public void doStuff ( ) {

try {

/ / operaedes de E/S arriscadas


] catch(fOException ex) {
// impossivel tratar
throw ex; / / Impossivel lanqar a ndo ser que voc6 a declare

]
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

Criando uma excegao


Neste exercicio tentaremos criar uma excegio personalizada. Nio introduziremos nenhum m6todo novo (s6 os herdados
de Exception), e j6 que ela estenderi Exception, o compilador a considerar6 uma exceglo verificada. O objetivo do
programa ser6 verificar se um argumento de linha de comando, representando um alimento especifico (como uma string),
sericonsiderado aceitivel ou nlo.
I Primeiro criaremos nossa excegio. Ela ser6 chama& de eadFoodException. Essa excegio seri langada quando um
alimento nio aceit6vel for encontrado.
I Crie uma classe de inclusio chamada MyException e um m6todo main ( ) , que permanecerivazio por
enquanto.
I Crie um m6todo chamado checkFood ( ) . Ele usar6 uma string como argumento e langari nossa excegio se nio
achar aceit6vel o alimento que for fornecido. Do contr6rio, nos informari que o alimento 6 aceit6vel. VocA pode adicionar
i lista qualquer alimento de que nio gostar especificamente.
I Agora, no m6todo main ( ) , vocA extrair6 o argumento de linha de comando do array de strings e, em seguida,
passar6 essa string para o m6todo checkFood ( ) . J6 que se trata de uma excegio verificada, om6todo
checkFood ( ) precisa declar6Ja e o m6todo main ( ) teri que manipuliJa (usando um bloco trylcatch).
214 Copitulo 5: Controle de fluxo, exceg6es e ossertivos

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.

Obietivo poro o CertificoEdo

Erros e Exceg6es Comuns (Objetivo 2.6 do Exame)


2.5 Reconhecer sinagdes qae reultaram em qaalquer um dos seguintes sendo lanpado: ArElndexOulOJBoundsException,
ClassCastException, IllegaL4rgumentException, Illegalsn*Exception, NullPointerException, NumberFormatException,
AssertionError, ExcEtionlnlnitialiTgrError, StackOuerfkwError ou NoC/astDeJFoundEmor. Entend.er qaais duset sdo lanpadot pela
miquina uiiua/ e reconhuer sitaagda em qtle nillrlr deuerio vr /angadot progmmaticammte'

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.

De Onde V6m as Exceg6es


Volte i p6gina anteriore dO uma olhada na ultima frase do Obletivo 2.6.Eimportante entender o que causa exceg6es e
erros, de onde eles v6m. Para o prop6sito de preparar voc6 para o exame, vamos definir duas categorias maiores de
e

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.

Exceg6es Langadas pela fVM


Comecemos comumaexcegio bastante comum, aNullPointerException. Comovimos no Capitulo 3, essa
excegio ocorre quando voc6 tenta acessarum objeto usando umavari!ryeldereferOncia com um valoratual nulf . NXo
existe a menor pbssibilidade de o compilador conseguir encontrar esses problemas antes do tempo de execugio. Vejamos o
segunte:
class NPE {
sfafi c Sl-rino
v er +r.Y g;
public static void main(String [] arcrs) {

System. out.println (s. length ( ) ) ;


]
)

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.

Exceg6es Langadas Programaticamente


V. ejamos agora as exceg5es langadas programaticamente. Lembra-se que definimos "programaticamente" como significando
algocomo:
Criado por um aplicativo e / ou por um desenvolvedor de ApI.
Por exemplo, muitas classes na APIJava t€m m6todos que usam argumentos string, convertendo essas strings em
primitivos num6ricos. Um bom exemplo dessas classes sio as chamidas "classes wrapper" que estudamos no Capitio 3.
H6 muito tempo, algum prog{amador escreveu a classe j ava . lang . rnteger e criou m6todos como parsefnt ( ) e
valueof ( ) ' Esse programador decidiu sabiamente que,-se um desses m6todos recebesse uma string que nlo
pudesse ser convenida em um nrimero, o m6todo deveria langar uma NumberFormatException. O16'A9o
parcialmente implementado poderia se parecercom o seguinte:
int parselnt(String s) throws NunlcerFormatException {
boolean parseSuccess = false;
int result = 0;
/ / faz um parsing complicado
if ( tparseSuccess) / / se o parsing tiver falhado
throw new NunlcerFormatException ( ) ;
return resul-t;
]
Outros exemplos de exceg6es program6ticas incluem um AssertionError (ok, nio se trata de uma excegio, mas esse
erro E langado Prograrnaticanente), elangaruma 11legalAr$unentException. Naverdad., o nosso nritico
desenvolvedordaAPlpoderiaterusadolllegalArgumentException paraoseum6todoparselntO.Mas
ocorrequeNumberFormatException estendelllegalArgumentException e6umpoucomaisprecisa,de
forma que, neste caso,.usar NwnlcerFormatException acomoda a nogio que Jiscutimos arrt.iior-.rrr.r L q"" '
quandovod temumahierarquia de exceg6es, deve usar a excegio mais precisa qui puder. "

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

Um Resumo das Exceg6es e Erros para o Exame


O Objetivo 2.6 lista dez exceg6es e erros especificos. Nesta segao, n6s discutimos o Stackoverf lowError. As outras
nove exceg6es e erros listados no objetivo serio abordadas em outras parres deste livro. A Tabela 5-2 resume essa lista e
fornece referAncias para os capinrlos onde voc6 poded encorrtr". ,, e erros nio discutidos aqui.
"*fog6es
Tobelo 5-2 Descrig6es e Fonles de ExceE6es Comuns.

Excegio (Localizagio do Capitulo) Descrigio Langada


Normalmente

ArraylndexOutOBoundsException

(Capitulo 3, "Atribuig6es") Langada ao se tentar acessar um array Pela JVM


com um valor de indice invilido
(ou negativo ou maior do que a
extensio do array),
21 6 Cooilvlo 5: Controle de fluxo, exceE6es e ossertivos
Langada ao se tentar converter uma Pela JVM
ClassCastException
(Capitulo 2, "Orientaglo a Objetos") vari6vel de refer6ncia em um tipo que
nio passa no teste E-UM.
lllegalArgumentException LanQada quando um m6todo recebe Programaticamente
(Capitulo 3, "Atribuig5es") r.r* irg,r-..rto formatado de forma
diferente do que o m6todo esPera.

IllegalStateException Langada quando o estado do ambiente Programaticamente


(Capitulo 6, "Formataglo") nio bate Com a operagio sendo tentada,
pot:I:Tql", usando-se um Scanner
que ,a lor lecnaoo.

NullPointerExceDtion Langada ao se tentar acessar um objeto PelaJVM


(Capitulo 3, "Atribuig6es") com uma variivel de referAncia culo
valor atual seia nuI1.
NumberFormatException Langada quando um m6todo que converte Programaticamente
(Capitulo 6, "Formatagio") uma String em um nimero recebe
uma String que nio consegue converter.

AssertionError (Este Capitulo) Langada quando o teste booleano de Programaticamente


uma instruglo retorna f af se.

ExceptionlnlnitializerError Langada ao se tentar inicializar uma variivel Pela JVM


(Capitulo 3, "Atribuig6es") estttica de um bloco de inicializaglo.

StackOver{lowError @ste Capitulo) Normalment e Tangada quando um m6todo Pela JVM


faz recurs6es profundas demais
(Cada chamada 6 adicionada i pilha).

NoClassDeffoundError Langadaquando aJVM nio consegue encontrar PelaJVM


(Capitulo 10, "Desenvolvimento") uma classe de que precisa, por causa de um erro
de linha de comando, uma questao relerente
ao classpath ou um arquivo . class que
esteja faltando.

,A. l r ,.t.
(Jbletivo poro o centttcogoo

Trabalhando com o mecanismo de assertivas


(Objetivo 2.3 do exame)
23 Esmuer aldigos qaefagan ast apropriadt de assertiuas e distingair o un de asrcftiuar adeqaado do inadequado.

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

Visdo geral das assertivas


Imaginemos que voc€ resolvesse que um n{rmero passado para um m6todo (digamos, methodA ( ) ) nunca ser6
negalivg. No momento do teste e depuraglo, voc6 quer validar sua suposigio, mis nio que, t., qrr. ..*o ver irstrug6espint,
qryupula{oresdeexcegiodetempodeexecugiooutestesif/else-quandotiverconiluidooiesenvoL'i*.nto.boi6*,'
deixar todos esses recursos inseridos trar6, no minimo, um impacto no desempenho. E ai que as asseftiv.. *r"* p"r"
ajudar. Observe o c6digo a seguir:
private void methodA(int num) {
if (num >= 0) {
/ faz al-go
/
) el-se { / / nt:m deve ser < O

// Nunca chegaremos a este cddigol


System.out.println(..yikes! num is a negative numberl " + num);
)

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

Regras das express6es de assertivas


As assertivas podem ter uma ou duas express6es, dependendo de voc6 u sar aversio sinples ov muito sinples. A primeira
expressio deve sempre resultar em um valor booleano! Siga as mesmas regras que usa Para testes i f e whi le' O
imponante 6 c :iar in teste (aTesQ afirmativo, o que significa que estari supondo que o resultado do nsteser6 true. Se
,eiment. o for, nio havei6 problemas. Se naofoitrue, no entanto, sua suposiglo estava errada, e voc6 ver6 um
AssertionError.
A segundaexpressio, naversio simples de umainstrugio assert, pode ser qualquercoisa.que resulte em
usada somente
um rialor. Lembre: expressio 6 usada para gerar uma mensagem com Strings' a qual ser6 exibida no
a segunda
rasrreamento dapilhaplra he fornecer mais algumas-informag6es de depuraglo. Ela funciona de maneira semelhante a
System.out.printl-n( ),nofatodequeivocOpoderiplssarumiipoprimitivoouumobjeto,eelaoconverterdem
uma representagio com Strings. Seu resultado lel que ser um valor!

pa ra anrbar as panes de uma instruglo assert. Lemb_re-se, a exPres-


O c6digo abaixo lista express6es vilidas e inv6lidas
sion2 6"usada apenas com a instrugXo assert sirnples, em que a segunda expresseo existe somente para lhe dar mais
algumas informag6es para a depuragio:

void noReturno {}
int aReturno { return 1; )
void go0 {
intx=1;
boolean b =

/ / as segwj-ntes instrug6es assert sdo v6lidas


^^^^es
aDDs!L /.. --
\^ -- 1\.
J/ ,

accarl- th\ .

assert true,'
^^^^rr /.. -- 1\ . x;
:ccarl- lv == 1 \
. aReturnO;
-^^^e!
oD-erL\^
/-.
--
--
1\
f/
.
. new ValidAssert O ;

// as seguintes instruqSes assert sao TNVALTDAS


^^^^e!
a>-s!Lt^ // nenhuma delas 6 booleana
/..
--
1 \
fr,
.

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,

"tlma expressio assertiva deve resultar em um valor booleano, verdadeiro ou falso?',,

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:

int assert = getlnitialValue O ;


if (assert == getActualnesult O ) {
/ / faz algo
]
Observe que no c6digo anterior, assert 6 usada como um identificador. Nio haveria problema antes da versio 1.4. Mas
lembre-sedequevoc6niopodeusar.umapalavra<have/reservadacomoidentificador,eapartirdaversio 1.4, assert rt
tamoa uma palana-chaue! A, conclusio 6

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:

javac -source 1.4 com/geeksanonymous/TestClass


Vocd pode ler esse aidigo assin: 'bonpila a classe hilClass do direhirio com/geeksanony.mous usando a maneira enpregadapela
uersio |.4, err qtre asserL ti unapalawa-chaue".

Usando a Vercio 5 de java e javac


No que se.refere ao exame, voc6 SEMPRE estari usando a versio do compilad or
Java $avac), e a versio 5 do
executor de aplicativos Java fiava). Voc6 poder6 ver quest6es sobre vers6el mais intigas de i6digosfonres, mas
essas quest6es sempre estarao no contexto de compilar e executar c6digos antigos com as vers66s atuais de javac e
Java.

Compilando um C6digo Atento is Asertivas


O compiladorJava 5 usari a palavra-chave assert por padrio. A nio ser que voc6 o instrua do conrrd.rio, o compilador
rra gerar uma mensagem de erro se encontrar a palavra assert sendo usada como identificador. Entretanto, rroc? pode
dizer ao compilador que esti dando.
a ele um .giligo aittlSg para compilar, e que ele deve fingir que 6 um compilador^antigo!
(Mais sobre comandos do compilador no C"ptt"lg 10) pig?rnos que voc€ p_ricise fazer um ieparo ripido em^um c6digo"
antigo da versio 1.3 que use assert como um identificador. Voc6 pode digitar na linha deio**iot
javac -source 1.3 CodiqoAnti_go. java
O compilador emitiri avisos quando descobrir a palavra assert usada como identificador, mas o c6digo iri compilar e
executar. Suponha que voc6 diga ao compilador que o seu c6digo 6 da versio 1.4 ou posterior, por exemp"lo:
javac -source 1.4 CodigoNaoTaoAntigo. java
Nesse caso, o compilador emitir6 erros quando descobrir a palavra assert sendo usada como identificador.
Se quiser dizer ao compilador para usar regrasJava 5, voc6 pode fazer uma das trAs seguintes coisas: omitir a opgio -
220 Copitulo 5: Controle de fluxo, exceq6es e ossertivos
source, que 6 o padrio, ou adicionar uma das duas seguites op96es de source:
-source 1.5 ou -source 5. (Vi,rcomodclaraadistinglodaSunentre 1.5e. 5?)
Se quiser usar assert
como identificador no seu c6digo, vocA PRECISA compilar usando 19pEa" -source
1. A Tabela 5-3 resume a forma como o compilador java5 reagir|a
i. assert como identificador ou como
palavra-chave.

Tobelo 5-3 Usondo Jovo 5 poro Compilor C6digo que use Assert como ldenti{icodor ou como Polovro-Chove

UnhadeComando Se assert for um Identifi cador Se assert for uma Palavra4have

javac -source 1.3 TestAsserts. java O c6digo compila com avisos. A compilagio falha.

javac -source 1.4 TestAsserts.java A compilagio falha. O c6digo compila.


javac -source 1. 5 TestAsserts. java AcompilagXofalha. O c6digo compila.
javac -source 5 TestAsserts.java A compilagio falha. O c6digo compila.
javac TestAsserts . java A compilaglo falha. O c6digo compila.

Execugio com asseltiv.ur


Agoracheganros ) par"te interessante. IJma ve z quevocAtiver escrito seu c6digo, o qual reconhece assenivas (em outras .
pi"rrr^,,rio .6digb que ,rse assert como palavrachave, para realment. .iecotar at no temPo de execugio),
"ssertivas
poderi optar por ativ6Jas ou desativllas! Lembre-se de que as asseftiuas u4n dcsatiuadarporpadrio.

Ativando assertiy.F no temPo de execugio


Ative as assertivas no tempo de execu$o com
java -ea com. geeksanonymous. TestClass
ou
j ava -enableagsertiona com. geeksanonymous . TestClass
Os switches de linha de comando anteriores informam a JVM para ser executado com as assertivas ativadas.

Desativando assertiyas no tempo de execugio


Voc6 tamb6m precisa conhecer os switches de linha de comando para a desativagio de assertivas,
java -da com. geeksanonymous. TestClass
ou
j ava -disableas gert Lons com. geeksanonymous . Tes tCf as s

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.

Ativagio e desativagio seletiva


Os switches de linha de comando para advaqAo e desativagio de assertivas podem ser usados de v6rias maneiras:
I Sem argumentos (como nos exemplos anteriores) Ativa ou desativa assertivas em todas as classes, exceto Para as
classes do sistema.
I Com o nome de um pacote Ativa ou desativa assertivas no pacote especificado e em qualquer Pacote abaixo
dele na mesma hierarquia de diret6rio (veremos mais detalhes sobre isso em breve).
I Com o nome de uma classe Ativa ou desativa assertivas na classe especificada.

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

o subpacote de com. geeksanionymous 6 o pacote twelvesteps. Lembre que emJava,


com. geeksanonymous. twelvesteps 6tratado como umpacote completamente distintosem relacionamento com
os pacotes acima dele (nesse exemplo, o pacote com. geeksanonl.mous), exceto por compartilharem alguns diret6rios.
A Tabela 54lista exemplos de switches de linha de comando paraaativagioe desativagio de asserrivas.

Tobelo 5-4 Swilches de /inho de cornondo poro osserfivos

Exemplo de linha de comando O que significa

lava -ea
java -enableassertions Ativa assertivas
java -da
j ava -disableassertions Desativa assenivas (o comportamento padrlo da versio 1.5)

java -ea:com.foo.Bar Ativa assenivas na classe com.foo.Bar

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

Usando as assetrivas apropriadamente


Nem todos osvsos udlidosdas assertivas sio considerados 4rupriados, Como acontece com tantos outros recursos emJava,
voc6 pode ultrapassar o uso pretendido para as asseftivas, ipesar dos esforgos dos projetistas da Sun para desencoraj"t irto.
Por exemplo, voc6. nuncadevemanipular uma falha de assertiva. Isso quer dizer qui nio deve capturi-la com uma cliusula
catch etentarumarecuperaglo.Quantolvalidade,noentanto,AssertionError 6umasubclassede
fhrowal>1e, o que significa quepofuser capturada. Por6m, nio o faga! Se voc6 quiser tentar alguma recuperagio, faga-a com
uma exceglo. Para &sencoraji-lo de tentar substituir uma assertiva por uma excegio, o erro AssertionError
nlo
concede acesso ao objeto que o gerou. Tudo que voc6 vai conseguir ser6 uma mensagem de String.
Entio, quem decide o gue 6 ou nio @ropiado? A Sun. Tanto o exame quanto esta segio, usam a documentaEi.o
sobre assertivas "oficial" da Sun para deterrninar o uso apropriado e nio-apropriado.
222 Copftvlo 5: Controle de fluxo, exceE5es e ossertivos

PREPARAQAO PARA O EXAME


No exame, se uocd se fuparar com a "apropriado", ndo a confunda cont "u,l/ido". Apmpiado :empre se refere d maneira cono algo deue
pakna
ser usado, d.e acordo com os desenuoiuedores oa com as pniticas ofcialnente adotadas pela Sun. Se u\cA enc\ntrar a palaura
do-nian*no
"cyrreto" n0 cyntex,tg das assertiaas, c0n0 en, 'A tinba 3 apretenta un uto cunetr para aJ assertiuas", tambim deue presamir qae essa
pa/at'ra
uni v refeindo a como as assertiaas deaem ser xsadas em aeqde comopodeiam ser zudas dc maneira adlida.

N6o use ossertivos Pard vdlidar drgumentos de um m6todo public


O c6digo a seguir mostra um uso inapropriado das assertivas:

public void doStuff(int x) {

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.

Use as assertiyas para validar argumentos de um m6todo Privado


Quando vocd escrever um m6todo private, 6 quase certo que tenha escrito (ou que controle) todos
os c6digos que o
ciamario. Quando quiser presumii que a l6gica do c6digo que estiver chamando s-u m6todo private est, correta,
poder6 testar essa suposigio com uma instrugio assert como a que vemos abaixo:
private void doMore(int x) {

assert (x > 0);


/ / faz coisas com x
)

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

public boolean modifylhings ( ) {


x++ = y;
ral- rrrn l- rrra.

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

Resumo para a certificagio


Este capitulo abordou uma 6rea vasta, toda ela envolvendo maneiras de controlar o fluxo de seu programa, com base em
f f
um teste condicional. Primeiro voc6 conheceu as instrug6es i e swi tch. A instrugio i avfia uma ou mais express6es
com relagio a um resultado booleano. Se o resultado for true, o programa executari o c6digo do bloco que estiver
inseridonainstrugioif.Seumainstrugioelse forusadaeaexpressioapresentarumresultadofalse,bc6digo
posterioraelse seriexecutado.Seainstrugioelse nioforusada,nenhumdosc6digosassociadosiinstrugioit
ser6exectrtado.

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!

',/ Exercicios ripidos


Aqui estio algtrns dos ponroschave de cada objetivo para certificagio deste capinrlo. VocA pode percorrA-los virias vezes, se
estiver interessado em passar no exame.

Escrever o c6digo usando instrug6es if e switch (Obi. 2.l)


E A instrugXo i f deve ter todas as express6es enfeixadas por pelo menos um par de parOnteses.
O O rinico argumento vAlido para uma instrugio i f 6 um valor booleano, em outras palavras, uma expressio que
tenhacomo resultado umvalor ou umavariivel booleana.
E Cuidadocomatribuig6esbooleanas(:)quepodemserconfundidascomtestesdeigualdadebooleanos (==):
boolean x = false;
if (x = true) { } / / uma atribuiqdo, entdo x sempre ser6 true!
fl As chaves serio opcionais para blocos if que tiverem s6 uma instrugio condicional. Por6m, cuidado com
JAVA 5 225
recuos enganosos.

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.

D Apalavra-chavedefault deveserusadaemumainstrugioswitch sevoc6quiserexecutarumc6digoquando


nenhum dos valores das instrug6es case coincidir com o valor condicional.
tr Oblocodefault podeserinseridoemqualquerlocaldoblocoswitch,portanro,senenhumainstrugiocase
aPresentar correspondAncia, o bloco de f aul t ser6 executado, e se ele nlo tiver uma instrugio break, continuard a
ser executado (passagem completa) at6 o final da instrugio switch ou at6 que a instrugio break seja encontra&.

Escrevendo o c6digo usando loops (Objetivo 2.2)


E UmainstrugXofor b6sicaposzuitr6spartes:adeclaragioe/ouniciahzaglo,aavaliagiobooleanaeaexpressi.ode
it€nado.

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.

Usando break e continue (Objetivo 2.2)


E Uma instrugio break niorotvladafaricom que a interagio atual & estrutura de loop mais interna seja interrompida
ea linha de c6digo posterior ao loop seja executada.
E Uma instrugio continue nXo-rotulada fari com que a iteragio atual do loop mais interno seja interrompida ea
condigio desse loop seja verificada, se ela for atendida, o loop ser6 executado novamente.
E Se a instruglo break ou continue for rotulada, ela far6, com que uma agi,o semelhante ocorra no loop rotulado e
nio no loop mais interno.

Manipulando exceg6es (Objetivos 2.4,2.5 e 2.6)


E As exceg6es vAm em duas vers6es: verificada e nXo verificada.

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

throws ou manipul6-la com um bloco trylcatch apropriado.


declari-lausando a palavra-chave
E Os subtipos de Error ou RuntimeException nio sio verificados, portanto, o compilador nio imp6e a
regra de manipulagio ou declaragio. Voc6 pode manipuliJos e tamb|m declar6-los, mas o comPilador nio se
imponari se uma ou outra coisa ocorreu.
E Se voc6 usar o bloco opcional fina]Iy, ele sempre ser6 chamado, independente de uma excegio do bloco
try correspondente ser ou nio langada e de uma excegio langada ser ou nio capturada.
tr A rinica excegio i inally ser sempre chamado seri quando a JVM for encerrado.
regra do bloco f Isso
poder6 acontecer se o c6digo do bloco try ou catch chamar system. exit ( ) .
D 56 porque f inally seri chamado nlo significa que seri concluido. O c6digo do bloco f inally pode ele
pr6prio langar uma excegio ou emitir um System. exit ( ) .

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.

Trabalhando com o mecanismo de assertivas


E As assenivas lhe fornecerio uma maneira de testar suas suposig6es durante o desenvolvimento e a depuragio.

E As assertivas geralmente slo ativadas durante o teste, mas desativadas durante a distribuigio.

E Voc6 pode usar assert


como uma palavra-chave (na versio 1.4) ou um identificador, mas nio como ambos. Para
asserL como um identificador (por exemplo, o nome de um m6todo), use o
compilar c6digos antigos que usem
flagdelinhadecomando -source 1. 3 em javac.
E As assertivas sio desativadas no tempo de execuglo por padrio. Para ativi-las, use o flag de linha de comando
-ea ou -enabl-eassertions.
fl VocA pode desativar as assertivas seletivamente usando o flag -da ou -disableassertions.
E Se voc6 ativar ou desativar assertivas usando o flag sem nenhum argumento, estar6 ativando ou desativando-as
no Ambito geral. E possivel combinar switches de ativagio e desativagio para ter as assertivas ativadas em
algumas classes e/ou pacotes, mas nXo em outros.

D Voc6 pode ativar ou desativar assertivas por classe, usando a sintaxe a seguir:

iarra -ea -da:MvClass TestClasS


E VocA pode ativar ou desativar assertivas por pacote, e qualquer pacote que especificar tamb6m incluir6 todos
os subpacotes (pacotes abaixo na hierarquia do diret6rio).

tr Nlo use assertivas paravalidar argumentos de m6todos priblicos.


tr Nio use express6es asserrivas que causem efeitos colaterais. A execugio das assertivas nio 6 sempre garantida,
portanto, nlo seri bom rer um compoftamento que se altere dependendo das assertivas estarem ativadas.

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.

2. Dados dois arquivos:


1. class One {
2. public static void main(SLrinq[] args) {
3. int assert = 0;
4. )
ql

1. class Two {
2. public static void main(Stri-ng[] arqs) {
3. assert false) ; 1

A\

E as quatro seguintes chamadas de linha de comando:


javac -source 1.3 One.java
javac -source 1.4 One.java
javac -source 1.3 Two.java
javac -source 1.4 Two.java
Qual6 o resultado? (Marque todas as corretas)

,d Apenas uma compilaeeo teri sucesso.

B. Exatamente duas compilag6es tereo sucesso.


228 Copftulo 5: Controle de {luxo, exceg6es e ossertivos

C. Exatamente tr0s compilag6es terio sucesso.

D. Todas as quatro compilag6es terio sucesso.

E. Nenhum aviso serl produzido pelo compilador.


F. Pelo menos um aviso ser6 produzido pelo compilador.

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)

A" String doFileStuff O { return "b"; }


B. String doFileStuff O throws IOException { return "b"; }
C String doFileStuff(int x) throws loException { return "b"; }
D. String doFileStuff O throws FileNotFoundException { return "b"; }
E. String doFileStuff O throws NunberFormatException { return "b"; i
E String doFileStuff ( ) Lhrows NumberFormatException,
FileNotFoundException { return "b"; }

4. Dado:
alaqc Tnhrrl- {

public static void main(string[] args) {

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

Quais afirmativas sio verdadeiras? (Marque todas as corretas)


JAVA 5 229
A. A linha 6 6 executada exatamente O vezes.
B. A linha 5 6 executada exatamente 1 vez.
C. A linha 6 6 executada exatamente 2vezes.

D. O bloco f ina11y 6 executado exatamenre O vezes.

E. O bloco finally 6 executado exatamente 1 vez.


F. O bloco f ina11y 6 executado exatamente 2vezes.
G. Ambas as chamadas produzem as mesmas exce96es.

H. Cada chamada produz uma excegio diferente.

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

Qual opgio, inserida na linha 4, produz a s atd^ 12?

,{"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) {

3. Util_s u = new Ping0;


4. System.out.print(u.getlnt(args[0]));

;. int setrnt(strins ars) t


7. return Integer.parselnt (arg) ;
B, }
9. )
10. class Utils {
11. int getlnt(String x) throws Exception { return 7; }
t2. j
E as tr6s modificag6es possiveis:

C1. Declarar que ) langauma Exception.


main (

C2. Declarar que Ping . getlnt ( ) langa uma Except ion.


C3. Encapsular a chamada de getrnt ( ) em um bloco try / catch.

Qual(is) modificagio(6es) permite(m) que o c6digo compile? (Marque todas as coretas)


,A. Cl sozinha 6 suficiente.
B. C2 sozinha 6 suficiente.
C C2 sozinha 6 suficiente.
D. C1 e C2 sio obrigat6rias.

E. Cl eC3 sio obrigat6rias.


E C2 e C3 sio obrigat6rias.
G Todas as trAs modificag6es sio obrigat6rias.

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

t l. Quais afirmativas s6o verdadeiras? (Marque todas as corretas)


.4. Eapropriadousarassertivasparavalidarargumentosparam6todosmarcadoscompublic.
B. li apropriado capturar e manipular erros de assertivas.
C Nao 6 apropriado usar assertivas para validar argumentos de linha de comando.

D li apropriado usar asseftivas para gerar alertas quando vod alcang um c6digo que nio deveria ser alcanEado.

E, Nna 6 apropriado que assertivas modifiquem o estado de um Programa.

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.

E. A compila$o falha devido apenas a um erro na linha 10.


JAVA5 233
F. A compilagio falha devido apenas a um erro na linha 11.
G. A compilagio falha devido a erros em virias linhas.

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)

5. Cest6correta.x atingeovalordell,emcujopontootestewhile falha.x 6entloincrementada(depoisdoteste


de comparaglo!), e o m6todo println ( ) roda.
A, B, D, E e F esteo incorretas com base no exposto acima. (Objetivo2.2)
6. Besticorreta.Depoisques3Olangaaexce$opa$s2$,s2O alangaparaslO,emaisnenhumc6digodes2Oseri
o<ecrrtado.

A, C, D, E, F, G e FI estio incorretas com base no exposto acima. (Objetivo 2.5)


7, CeDestiocorretas. Integer.parselntpodelangarumaN'umlcerFormaLException,e
IllegalArgumentException 6asuasuperclasse(ouseja,umaexcegi.omaisampla).
A, B, E e F nio estlo na hierarquia de classe de rrrumberFormatException. (Objetivo 2.5)

8. A e C estio corretas. Lembre-se polim6rfica, de forma que o compilador


de que ahrtha 4 est6fazendo uma chamada
implementada, a excegio ter6 sido declara& & forma suficiente, e se
sabe que uma exceglo poder6 ser langada. Se C 1 for
C3 for implem entada, a excegio terisido manipulada de forma suficiente. C2 nlo 6 necessiria em nenhum dos casos.

B, D, E, F e G estio incorretas com base no exposto acima. (Objetivo 2.4)

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, B, C, D e F estio incorretas com base no exposto acima . (Objetivo 2.1)

10. Dest6correta.Umcontinue rotuladofuncionaapenasparaloops.Nestecaso,emboraor6nrlosejavilido, label


nio 6 um r6tulo em uma instrugio loop, 6 um r6tulo em uma insrrugio i f .
A, B, C e E estio incorretas com base no exposto acima . (Objetivo2.2)
lL C, D e E sio instrug6es corretas.

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.

A, B, C, D, E e G estlo incorretas com base no exposro acima. (Ob.ietivo 2.1)


14. E esti correta. Nio hi nenhum problema em aninhar blocos trylcatctr- Como de costume, quando uma excegio 6
langada, o c6digo do bloco catch 6 executado, e depois o c6digo do bloco f ina11y 6 execuiado.

A, B, C, D e F esteo incorretas com base no exposto acima . (Objetivo 2.5)


15. E est6 correta. A chamada deveria ser j ava Miner, em cujo caso seria produzido nul1 nul1.
A, B, C, D, F, G e H estio incorreras com base no exposto acima. (Objetivo 2.6)
16. B, C e D estio corretas. B no-rmalmente 6 usada para relatar um problema de ambiente, por exemplo, uma tentativa de se
acessanrm r€curso que esd fechado. C geralmente 6langda em metodos de API que tentem convefter argumentos Stringr
mal-formados emvalores num6ricos. D geralmente 6langdaem m6todosdeA?Iquerecebam argumentos mal-formados.

A e E sio langadas pelaJVM. (Objetivo 2.6)


236 Copitulo 5: Controle de fluxo, exceg6es e ossertivos
Strings, E/S,
FormataEio e
Parsing

Obierlvos pqrq q
certificoe6o
Usor Siring, StringBuilder e
StringBuffer

E/S de Arquivos Usondo o Pocote


iovo.io
I Seriolizog6o com o Pocole iovo.io

I Trobolhor com Dotos, N0meros e


Moedos

Usor Express6es Regulores

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.

Obietivo poro o certificoE6o

String, StringBuilder e StringBuffer (Objetivo 3. I do exame)


3.1 Discutir as diferengas entre as classes Sning, StringBailder e StingBffir.

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.

Strings sio objetos inalter6veis


Comegaremos com alguma informaglo de apoio sobre strinp. Naverdade, voc6 nXo precisari dessas informag6es no teste,
mas um pouco de contexcualizaglo sempre ajuda.A manipulagio de "strings" de caracteres 6 um aspecto fundamental da
maioria das linguagens de programa$o. EmJava, cada caractere de uma string 6 um caractere Unicode de 16 bits. J6 que
caracteres Unicodet€m 16 bits (e nio os restritos 7 ou 8 bits que a ASCII fornece), um conjunto de caracteres sofisticado e
ntemaqonal |facilmente representado em Unicode.
EmJava, as strings sio ob.ietos. Exatamente como acontece com outros objetos, voca pode criar a instancia de uma String
com apalavra-chave new, como vemos abaixo:

String s = new StringO;


Essa linha de c6digo cria um novo objeto da classe String e atribui a vari6vel de refer€ncia s a ele. At€ aqui os objetos String
se parecem iguais aos outros objetos. Agora, daremos um valor a String:

s = "abcdef";
Como talvez vocA jA soubesse, a classe String possui virios construtores, portanto, podemos usar um atalho mais eficiente:

String s = new String("abcdef") ;

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 s2 = s; / / faz s2 apontar para a mesma Stringr que s


At6 aqui tudo bem. Os objetos Stringparecem e$ar se comportando exatamente como os outros objetos, portanto, por
que toda a confrsio? Inalterabilidade (que diabos 6 inalterabilidade?) ! Uma vez que voc6 tiver atribuido valor a uma String,
esse valor nunca poderi ser alterado - ele 6 in alterivel, sticongelado, nio se mover6, acabou-se, esta concluido - tamb6m
discutiremos as raz6es posteriormente, nio nos deixe esquecer. A boa nova 6 que embora o oletoStingseja inalterivel, sua
uariduel de r@nciando o 6,rpo.rtanto, continuando com nosso exemplo anterior:

s = s.concaL(" more stuff"); // o m6todo concato anexa


// um literal ao fim
Mas espere um momento, nXo acabamos de dizer que as Strings slo inalter6veis? Entlo, o que significa essa conversa de
JAVA 5 239
"acr6scimo ao final da string"? Boapergunta; examinemos o que aconreceu realmente...

OVMpegouovalordaStrings(queera"abcd,ef") eadicionou"more stuff"aofinal,nosdandoovalor


"abcdef more stuff".JiqueasStringssioinalter6veis,oVMniopoderiainseriressanovaStringnaquela
referenciada por s, poftanto, criou um novo objeto String, dzu a ele o valor "abcdef more stuf f " e fez com que s
o referenciasse. Nesse ponto de nosso exemplo, temos dois objetos String: o primeiro que criamos, com o valor "abc&f" e
osegrndocomovalor"abcdef more stuff".Tecnicamente,agorahitr6sobjetosString,porqueoargumento
literal "morestuf f " que foi concatenado 6 por si s6 um novo objeto String. Contudo, temos referAncias apenas )
'abcdef " (referenciado por s2) e "abcdef more stuf f " (referenciado por s).
E se ni.o tMssemos a visi,o ou a softe de criar uma segunda vari6vel de refer6ncia para a String "abcdef " antes de
chamarmoss = s.concat("more stuff ");?NessecasoaStringoriginalnioalteradacontendo"abcd.ef"
ainda existiria na mem6ria, mas seria considerada "perdida". Nenhum c6digo de nosso programa teria como referencii-la -
estaria perdid aparan6s.E bom observar, no entanto, que a String "abcdef" original nio foi alterada (nio pode ser,
lembre.se: ela b inalter,hnl; s6 a vari6vel de refer6ncia s foi alterada para referenciar uma String diferente. A F tgara Gt mostra
o que acontecer6namem6riaquando voc€ reatribuirumavariivel de referAncia. A linhatracejada indicaumarefer6ncia
o<cluida

Para recapinrlar nosso primeiro exemplo:


String s = "abcdef"; // cria um novo objeto String, com o val-or "abcdef",
/ / faz s apontar para ele
String s2 = s; / / cria uma seg,unda vari6vel de refer6ncia apontando para
// a mesma String
s = s.concat(" more stuff"\i // cri.a um novo objeto String, com o valor
// "abcdef more stuff", faz s apontar para ele.
// (modifica a referOncia de s, da antiga
/ / String para a nova. ) ( Lembre-se de que
/ I s2 ainda est6 se referindo d
// SLring "abcdef" original).
Examinemos outro exemplo:

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

Iremos expandirese exemplo. Comegaremos com:

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

Figurc 6-1 Obietos Sfring e suos voridveis de refer6ncio


valor "\tava". Em todos esses casos chamamos v6rios m6todos do objeto String para criar uma nova String alterando
outra ji existente, ruls nunst aaibminos i Sting recim<iada uma vaiivel derefer6ncia.
Mas, podemos inserir umapequena inversio no exemplo anterior:
String x = ",Java";
x = x.concat(" Rules!"); // Agora estamos atribuindo x ir nova String
System.out.println(\rx = " + x) ; // a saida ser6:
/ / x = rTava Rules!
Dessa vez, quando o VM executar a segunda linha, um novo ob.ieto String ser6 criado com o valor Java Rules!" e x ser6
configurado para referenci6-lo. Mas espere, ainda hi mais: agora o objeto String original, Java", foi perdido e ningu6m o
esti referenciando. Portanto, nos dois exemplos criamos /aar objetos String e someite smavariivel de refer6ncia, & modo
qug um d9s dois objetos String foi abandonado. Consulte a Figora63 par:r ver uma representaglo gr6fica desa triste
est6ria- A linhatracejada indicauma refer6ncia excluida

Examinemos esse exemplo urnpouco mais detalhadamente:


String x = "Java"i
x = x.concat(" Rules!");
System.out.println ( "x = N
+ )<); // a saida 4: x = Java Rules!
x. tolowercase ( ) ; / / sem atribuiqdo, cria uma nova String abandonada
System.out.println( \x = \ + x); / / sem atribuiqdo, a saida ainda 6:
// x = Java Rules
x = x.tolowerCaseO ,- / / cria uma nova String, atribuida a x
JAVA 5 24I

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

Figura 6-2 um obieto Sfring 6 obondonodo quondo criodo

System.out.println("x = " + x) ; // a aLrtbuiqdo origina a saida:


//x=javarules!
A discussio anterior cont6m as chaves para a compreensXo da inalterabili&de do objeto StringJava. Se voc0 entender
realmenre os exemplos e diagramas, at6 mesmo detrilsparafrente, d€ve conseguir acenar 80 por cento das perguntas sobre
objetos String do exame.

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.

Fatos importantes relacionados aos obietos String e a mem6ria


Nesasegio discuriremos como a linguagemJavamanipulaobjetos de stringnamem6riae algumas das raz6es que estio
por tris desses compoftamentos.
Um dos objetivos principais de qualquer linguagem de plogramaglo sofisti cada|faznr vneficiente da mem6ria. Com o
crescimento dos .plicatinos, 6 muito iomum que strings literais ocupem grandes espagos da mem6ria, e que geralmente haja
muita redgndAncia dentro do universo das strings literais de um programa. Para tornar a lingu€emJava mais eficiente no
242 Copllulo 6: Strings, E/S, FormotoE6o e Porsing
uso da mem6ria, a JVM deixa reservada uma 6rea especial chamada "pool constante de strings". Quando o
compilador encontra uma string literal, verifica o pool para ver se ji existe uma id€ntica. Se uma coincid6ncia for
encontrada, a refer6ncia ao novo valor literal seri direcionadapara a String existente e nenhum objeto String
literal novo ser6 criado (a String existente simplesmente teri uma referCncia adicional). Agora podemos comegar a
ver por que tornar objetos String inalteriveis 6 uma id6ia tlo boa. Se diversas vari6veis de referOncia apontam para
a mesma String sem nem mesmo terem informagio disso, serra muito ruim se alguma delas pudesse ter o valor da
String alterado.
Voc6 pode estar pensando: "Bem, est6 tudo muito bom, mas e se algu6m sobrescrever a funcionalidade da classe
String; isso nio poderia causar problemas no pool?". Essa 6 uma das principais raz6es por que a classe String 6
marcada com final. Ningu6m pode sobrescrever os compoftamentos de nenhum dos m6todos do objeto String,
Portanto, pode estar certo de que esses objetos em cuja inalterabilidade estl confiando sio, realmente, inalteriveis.

Passol: String x = "Java";

Variivel de
referGncia String

Passo2: x = x. concat

Vari{vel de
refer€ncia String
",Java Rul-es !

Repare, no Passo 2, que nilo


h6 nenhuma referGncia
v6lida i String'Java"; esse
objeto foi "abandonado", e
foi criado um novo objeto.

Figuro 6-3 Um obiefo Sfring onfigo sendo obondonodo

Criando nov.ls strings


Prometemos anteriormente falar mais sobre as diferengas sutis entre os diversos m6todos de criagio de um objeto String.
Examinaremos alguns exemplos de como umastringpode ser criada, pressupondo que nio exista nenhum outro objeio
String no pool:
1 - String s = 'abc"; / / cria um objeto String e uma
/ / varilvef de referGncia
Nesse caso simples, 'abc" ser6 inserido no pool e ro referenciari.
2 - String s = new String(..abc,,); / / cria dois objetos e uma
/ / varilvel de refer6ncia
Nesse j5 que-usamos a palavra-chave new, a linguagem JavaciarS,umnovo objeto String na mem6ria comum (e nio
"aso,
no pool) e s o referenciari. Al6m disso, a string literal "abco seri inserida no pool.

M6todos impoltantes da classe String


Os m6todos a seguir sio alguns dos mais usados da classe String, a16m de serem os que mais provaveLnente
aparecerio no exame.
r charAt( ) Retornaocaracerlocalizadonoindiceespecificado
I concat( ) Anexa uma String ao final de ourra (" +" tamb|mfunciona)
JAVA 5 243
I equalslgnorecase( ) Determina a igualdade de duas strings, ignorando a caixa
f length( ) Retorna o nrimero de caracreres de uma String
I replace( ) Substitui as ocorrAncias de um caracter por um outro caracter
r substring( ) Retorna uma parre de uma String
r tolowerCase( ) Retorna uma String com os caracteres em caixa alta convenidos para baixa
r toString( ) Retorna o valor de uma String
I toUpperCase( ) Retorna uma String com os caracteres em caixa baixa convertidos para alta
I trim( ) Remove os espagos em branco no inicio e no fim de Strings
Vejamos esses m6todos com mais detalhes.
public char charAt(int index) Esse m6todo retorna o caractere localizado no indice especificado da classe
String. Lembre-se de que os indices de String t6m inicio no zero. Por exemplo,
String x = "airplane";
system.out.println( x.charAt(2) ); // asaida6'r'
public String concat(String s) Esse m6todo retorna um objeto String com o valor da string que foi passada para ele
acrescido ao final da string usadapara cham6Jo. Por exemplo,
String x = \\taxi";
System.out.println( x.concat(" cab") )t // a saida 6 "taxi cab"
Os operadores de sobrecarregados + e + : executam fung6es semelhantes a do m6todo concat ( ) . Por exemplo,
String x = "library";
System.out.println( x + " card"); // a saida 6 "library card"
1. Stri-ng x = "Atlantic";
2, x += \r ocean"
3. System.out.println( x ); / / a saida 6 "Atlantic ocean"
Observe no exemplo anterior, cuja saida foi "Atlantic ocean", que o valor de x i realmente alteradollembre-se de que
o operador + : 6 um ope rador de aaibuSdo, poftanto, a linha 2, na verdade, esti criando um novo objeto String, "At1an-
tic ocean",eatribuindo-oavari6velx.Depoisquealinha2forexecutada,astringoriginalquex estavareferenciando,
"At I ant i c ". ser6 abandonada.
publicbooleanequalslgnoreCase(Strings) Essem6todoretornariumvalorboof eano (true ou false)
baseado na coincid6ncia entre o valor da String do argumento e o usado para chamar o m6todo. O m6todo retornari true
mesmo quando os caracteres dos objetos String que estiverem sendo comparados tiverem caixas diferentes. Por exemplo,

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+

OBSERVAQ6ES pene O EXAME

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

String Il x = new String[3];


qi'c|-6n nTint-'ln1 v lana|-h/l l.
^lrf

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"

public String trimQ


Esse m6todo retorna um objeto String cujo valor 6 a String usada para chamar o m6todo,
por6m, com qualquer espato em branco precedente ou interno removido. Por exemplo,
c+'.in^v-\1^.i\\.
vLlfrry
^ -

System.out.println( x + "x" ); // o resuTLado 6 " hi xn


System.out,println( x.Erim( I + "x") ; //oresultado6"hix"

As classes StringBufrer e StringBuilder


fu classes java.lang.StringBuffere java.lang.StringBuilder devem serusadas quando voc6 tiver que fazer muitas alterag6es em
strines de caracteres. Como discutimos na segio
stringp secio anterior, Strine sio inalter6veis, portanto, se vod opt
obietos String
anterior. os objetos ar por fnnr
optar
muitas manioulac6es obietos. terminar6 com virios deles abandonados em seu pool.
manipulagdes envolvendo esses objetos, Dool. (Mesmo que
rcnhamos acesso agigabytes de RAMhojeem dia, nio 6 uma boaid6iadesperdigarmem6riacomobjetos dopool de
Strings descartados.) Por outro lado,
Strines descartados) StrineBuffer podem ser alterados repetidamente sem deixar para
obietos do tipo StringDuffer
lado. os objetos p
tr6s um rastro de objetos String descarados.

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.

Usando StringBufrer e StringBuilder


Na se-gio anterior, vimos que o exame pode testar o que voc6 entendeu sobre a inalterabilidade do objeto String
com fragmentos de c6digo como este:
String x = *abc";
x.concat("def");
SysEem.out..println("x =' + x) ; / / a saida €! $x = abc"
J6 que nenhuma nova atribuigiofoi gerada, o novo objeto String criado com o m6todo concat ( ) foi
abandonado instantaneamente. Tamb6m vimos exemplos como este:
String x = n-5."t
x = x.concat("def");
SysEem.out.println("x = " + x); // a saida 6 .x = abcdef"
Obtivemos um objeto String novo a panir da operagio, mas a desvantagem 6 que a string "abco anterior foi
perdida no pool de strings, ocupando, poftanto, espago na mem6ria. Se estiv6siemos usando um objeto
StringBuffer emvez de um objeto String, o c6digo ficaria assim:
StringBuffer sb = new StringBuffer("abc");
sb,append(t'def ");
System.out.println("sb="+sb); // a saida 6 "sb = abcdef"
Todos os m6todos de StringBuffer que discutiremos operam sobre o valor do objeto que estiver chamando o
m6todo. Portanto, uma chamada a sb. append ( "def " ) ,' na aerdade ectd atescentando "def" a i mesma (StringBuffer
sb). As chamadas desses m6todos podem ser encadeadasumx as outras. Por exemplo,
StringBuffer sb = new StringBuffer("abc");
sb.append("def") .reverse() .insert (3, "---") ;
System.out.println( sb ) ; // asaida 6 "fed---cba"
R.p.o que, em cada um dos dois enemplos anteriores, houve uma s6 chamada a new, de forma qtre, nos dois *emplos, n6s
nio criamos nenhum objao adicional. Cada exemplo precisou de apenas um objeto String)Gx par-arodar.

oBSERVAQoBS pene O EXAME:


Pmuauelmefie 0 exame aaaliani rcu conheciaento nbn a diferenga entre objetos Stringe StringBtlfer. Jd que os objetos StringBtfferpodea
nr alteradoq ofragnento de cddigo a segair se comportari dfenntenmte de amfragnento de aidigo semelbante qrc w oSetos Shing

StringBuffer sb = new StringBuffer("abc");


sb.append("def");
System.out.println( sb ) ;
Nesse caso, a saida nni; "abcddef "

M6todos importantes das classes StringBuffer e StringBuilder


O m6todo aseguir retornaum objeto StringX:orcom ovalor do argumento acrescido ao do objeto que chamouo m6todo:
public synchronized StringBuffer append(String s) Comovimos anteriormente, ese m6todo atualizar6 ovalordo
objao que o chamou, tendo ou nio o vdor de retorno sido atribuido a uma variivel. O m6todo usari muitos argumentos
diferentes, boohattot, char, furbla,Jkat, int, longe outros, por6m, o mais prov6vel de se encontrar no exame seri um objeto
String.Poro<emplo,
Strj-ngBuffer sb = new StringBuffer("set ");
sb.append("point") ;
System.out.println( sb ) ; // a saida 6 "set point"
StringBuffer sb = new StringBuffer("pi = ");
sb.append(3.14159f);
System.out.println( sb ) ; // asaida 6 "pi = 3.74L59"
246 Copitulo 6: Sirings, E/S, FormotoE6o e Porsing

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.

oBSERVAQ6TS pene O EXAME


Muitas dat perguntas do exame que abordam os fllpicos dute capitulo usam ama parte nnplicada p dfrcil de ler) da sintaxe Jaaa conhecida
como mltodos encadeados. Uma instrugio com mitodos eacadeados aPrerenta a teguinteJormageral:

resultado=m6todo1( ) .m6todo2( ) .m6todo3 ( ) ;


Na teoria, uma quantidade ilinitada de mdtodos pode or roroirodo dessa maneira, embora normalmente n6o s/am encontrados mais que tr€r.
Aqui estd como decifrar esses "atalblr pr/iticls Jaua" quando enconhd-los:

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

Obietivo poro o Certificog6o

Navegagio de Arquivos e E/S (Objetivo 3.2 do Exame)


i.2 Dado um cendrio enaoluendo a nauegagdo em sistemas de arquiuo; a kitura de arqilalr oa a escrita en arqaiuos, desenao/uer a solugdo
JAYA 5 247
cln'eta atandl ar seguinter cksu ()s uerys em combinagdo) dr jaua.io: BaferedReader, BffiredlViter, File, FileRtader, Filell/riter e
PrifiIYriter.
O hipico referente a E/ S ten un bishirico estranho com a certifcagdo SCJP. Estaua incluido nat uendet do exame at6 a /.2, depo*foi
remoyido na aersio 1 .4 e depois incluido nlaamefite na uersdo
Jaua 5.
E/S 6 um t6pico imenso, de forma geral, e as APIsJava que lidam com E/S de uma forma ou de outra sio tamb6m
imensas. Uma discussio geral de E/Spoderia incluir t6picos como E/S de arquivos, E,/S de conrrole, E/S de threads, E/S
dealto desempenho, E/Sorientado a.6ytes, E,/S orientalo a caracreres, filtragem e wiapping de E/S, serializaglo, e outros.
Felizmente para n6s, os t6picos de E/S incluilos no exameJava 5 se restringe"m aE/S piaciacreres e serial dEi".
Eis um resumo das classes de E/S que voc6 precisari entender para o exame:

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.

Criando Arquivos com a Classe File


Os objetos do tipo File slo usados para representar os arquivos (mas nlo os dados dos arquivos) ou diret6rios que existem
no disco fisico de um computador. Apenas para nos certificarmos que estamos sendo claros, quando falarmos de um
objeto do tipo File, diremos File, que significa arquivo em ingl€s. Quando estivermos falando sobre o que exisre em um
disco rQido, o chamaremos de arquivo, emportugu0s (a nlo ser que se trate d€ um nome de variivel em algum c6digo).
Comecemos com algtrns exemplos b6sicos de criagio de arquiv.os, de escrita neles e & leitura a panir deles. Primeiramente,
vamos criar um novo arquivo e escrever algumas linhas de dados nele:

// o exame Java 5 se concentra em

// classes de java.io
nlaqc lalri farl I

public statj-c void main(String [] args) {


File file = new File ( "fileWritel. txt,, ) ; / / Ajnda n5o hii
// um arquivo!
248 Copitulo 6: Strings, E/S, Formoloq6o e Porsing

]
]
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?

system. out.println (file. exists ( ) ) i // olhe novamente


] catch(fOException e) { }

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

ti::.:-nar duas saidas:


essas

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,

boolean newFile = false;


JAVA s 249

newFile = file.createNewFile ();

System. out . println (newFile ) ;


Voci poderia uer algo como a seguinte linba de aldigo so{nha, o que i mais difcit de /er, mas que realiqa a muma coisa:

Syst.em. out.println (file. createNewFile ( ));

Usando FileWriter e FileReader


Na pritica, voc6 provavelmente nio vai usar as classes FileSflriter e FileReader sem as encapsular com wrapping
(falaremos mais sobre "wrapping" em breve). Tendo dito isso, vamos em frente e vejam-os r-" op.r"g6"'aJEZS at
arquivo semwrapping:
import java.io.d;
class writer2 {
public static void main(String [] args) {
charl] in = new char[50]; // para armazenar a ent.rada
int size = 0;
trY {
File file = new File( // aper'as um objeto
"fileWrite2.txt") ;
FileWriter fw =
new FileWriter(fi1e) ; / / cria um arquivo propriamente dit.o
fw.wrj-te("howdy\nfolks\n,'); / / escreve caracteres no
I / arqurvo
fw. flush( ) ; / / Timpa antes de fechar
fw.close0; / / fecha arcruivo ao terminar
FileReader fr =
newFileReader(file) ; // FileReader
/ / objeLo
size=fr.read(in); //16o arquivoint.eiro!
System.out.print(size + " "); // quantos bytes lidos
for(char c : in) // exibe o array
System. out.print (c) ;
fr.c1ose0,. // novamente, sempre fecha
i catch(IoExcept.ion e) { }

)
o que produz a saida:
1-2 howdv
folks
Eis o que acaboude acontecer:

l.FileWriter fw = new FileWriter(file) feztr6scoisas:


a- CriouumavariiveldereferdnciaFile\Writer. fui.
b Criou um objeto FilerJfriter eo atribuiu a fi/4/.

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

Antesde avangarmos,vamosfalarsobre flush( ) e close( ). Quandovoc6 escreve dados emumstream, certa


quantidade de &dor r.ri"r*azenadaem buffer, e nunca 6possivel sabei ro^rrtt":.aqug{o dos dados seri
lyfimaparte
,ealmerrt. en',riada. VocA pode iareaLzar mtttas operag6es & escrita emum stream antes de fech6Jo, e chamar o m6todo
f lush ( ) garante que a ,lltima parre dos dados seja de fato escrita no arquivo. Sempre que terminar de usar um arquivo,
seja lendo Ju escrevendo nele, vtc6 deve chamar o m6todo close ( ) . Ao realizar E/S de arquivos, voc6 est6 usando
recursos preciosos e limitados do sistema operacional; portanto, quando tiver terminado, libere esses recursos chamando
close ( ).
Agor4 de voka ao nosso rikimo exemplo. Aquele programa ceftantente funaonarl" mCI ele 6 inadequado por alguns motivos:

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.

Combinando Classes de E/S


Todo o sistema de E/S deJava foi elaborado tendo-se em mente a id6ia de se usar diversas classes combinadas. Essa
combinaglo de classes de E/S 6 is vezes chamadade u.,rappingeisvezesde tncadeamento. O pacote java.io cont6m cercade 50
classes, 1.0 interfaces e 15 exceg6es. Cada classe do pacote tem um prop6sito bem especifico (criandose uma alta coesio), e as
classes foram elaboradas paraserem combinadas entre si de inrimeras formas, para lidar com uma ampla gama de situag6es.
java.io, tentando
Quando chegar a hora de trabdhar com E/S na vida real, vocA ceftamente se ver6 debrugado sobre a API
descobrir de quais classes ir6 precisar, e como faz&las trabalhar juntas. Para o exame, vocA ter|, delazer o mesmo, mas n6s
reduzimos artificialmente a A?I. Em termos de estudar para o Objetivo 3.2 do exame, podemos fazer de conta que todo o
pacote java.io consiste das classes listadas no Objetivo 3.2 do exame e resumidas na Tabela6-t,a nossa mini API de E/S.

Tobelo 6-'l iovo.io Mini API

Classe Estende de Argumentos Principais M€todos Principais


de iava.io do(s) Construtor(es)

t r-l-e Obj ect rk1t6


+:v,
qrrrnd
v er +++y createNewFi-1e ( )

SLring delete ( )
String, String exists ( )
isDirect,ory ( )
r_st, l-le ( )
1i-st o
mkdir ( )
renameTo ( )

FileWriter Wri-ter F'AIC close (

String f 'l rrqh /


wrrte (

Buf feredWriterWriter Wrr-ter


flush ( )
newline ( )
write ()

PrintWriter Writer File (em Java 5) cl-ose o


String (em .Tava 5) flush ( )
r\lrt-nrrt-Q|-r6am
vu uys es u! usrrl format ( )
* ,
nrint-fl\*
yrr:ru! \,

Writer nrini/\
Y!:frg \ / ,
nri-r1n/\
v! f rref rr \ /

write ( )

FileReader Reader t are read ()


String
Bu f f eredReader Reader Reader read( ) readline ()
* Discutidos posteriormente
JAVA 5 25I
Ago1a, di8amos 9ue guis6ssemos achar uma maneira mais f6cil de escrever dados em um arquivo
e ler o contetdo desse
*lta para a mem6ria. Comegando com a tarefa de escrever dados no arquivo, eis um processo para se determinar
Tq*"9 *
de quars classes rremos precisar, e como as colocaremos para trabalhar juntas:

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:

File f ile = new FiIe (..f ilewrite2 . txt.') ; I / cria File


um
Printwri-ter pw = new Prj-ntWriter(fi1et ; // passa o arquivo para
// o construtor de
// PrintWriter
Ok, hora de um pequeno teste. Antes deJava 5, Print\Triter nio tinha construrores que usassem nem String nem File. Se
voc6 estivesse escrevendo um c6digo de E/S emJava 1.4, como faria um Print\flriter iscrever dado. .-
,r- Fil.? Dica: voc6
pode descobrir a respo$a estudando a mini API de E/S na Tabela G1.

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:

I Pode ser construida usando-se um File.

2. Estende\7riter.
Dadas essas informag6es, podemos escrever o seguinte c6digo (lembre.se: este 6 um exemplo deJava 1.4):

File file = new File("fileWrite2.txt,'\; / / eri a rrm otrief o Eile


FileWriter fw = new Fil-eWriter(fi1e); // cria FileWriter
um
// que enviarS. a sua
// saida para urn File
Printwri-ter pw = new Printwriter(fw); // cria um PrintWriter
// qre enviarii a sua
// saida para um Writer
pw.println( "howdy" ) ; // escreve os dados
pw. prinLln ( " folks " ) ;

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 =

new File ( "fileWrite2. txL" |; / / eri e rrm ohiet- o File E

/ / abre "filewrite2 . txt."


FileReader fr =

new FileReader(fife); / / cria um FileReader para obter


// dados a partir de 'file'
BufferedReader br =

new Buf f eredReader ( fr),- / / cria um BufferReader para


252 Copllvlo 6: Strings, E/S, Formotog6o e Porsing

/ / obLer os seus dados a partir de um Reader


String data = br.readlineO; / / Ld aLguns dados

OBSERVAQ6TS pene O EXAME


quase garantido qae aoci encontrari quutdu flo exame que testardo o seu conhecinento de cono as classes de E/ S
E poden ter encadeadas.
St)tto ,;iA*n ngdi ndo lhe tiuerfcado-clara, recoruendamos que uoci use a Tabela 6-1 cono referdncia e etcreua aldigos parafaTgr
experilncias sobre qaais combinagdes de encadramento s6o adlidat e quais sdo inudlidas.

Trabalhando com Arquivos e Diret6rios


Anteriormente, n6s aludimos fato de que a classe File 6 us adaparacnar arquivos e diret6rios. Al6m disso, os m6todos de
ao
File tamb6mpodem serusadosparaapagar arquivos, renomeiJos, determinarseum arquiv_o_exise, criar arquivos
tempor6rios,?nodificar os atribrrtos de nm arquino e difere_nciar entre arquivos e diret6rios. Uma questao que
freqiientemente cria confusio 6 o fato de que um objeto do tipo File 6 usado para rePresentar ou vm arquiuo ov um diretrlrio.
Faliremos mais sobre ambos os casos em seguida.
Vimos anteriormente que a de clar a$o

File file = new rile(..foo,,) ;

Sempre cria um objeto File, e em seguida faz uma das duas seguintes coisas:

L Se " f oo " NAO existir, nio 6 criado nenhum arquivo,


2. Se " f oo " exittir, o novo objeto File refere-se ao arquivo existente.
ReparequeFile file = ne\^/ File (*foo"); NUNCAcriaumarquivo.Existemduasmaneirasdesecriarum
arquvo:
I Chamaro m6todo createNewFile ( ) em um objeto File. Por exemplo:

File file = new File("foo") ; / / ainda ndo existe um arquivo


file . createNewFile ( ) ; // cria um arquivo. "foo", qnre
// 6atribuidoa'fi1e'

2. CriaumReader, ouumVriterouumaStream. Especificamente, criaumFileReader, umFile\flriter, umPrint\(riter,


um FilelnputStream, ou um FileOutputStream. Sempre que cria uma instAncia de uma dessas classes, voc6
automaticamente cria um arquivo, a nio ser que ji exista um, por exemplo:

File file = new File(.'foo,'); / / ainda ndo existe um arguivo


Printwriter Pw =
nevr' Printwriter ( file) ; / / ari a rrm ohiefo PrintWriter E
// cria um arquivo, r\foo", ao qual
// ,+:1a' 6 at-rihrridn E aFritrrri
/ / 'pvr' ao PrintWriter
A criagio de um diret6rio 6 semelhante I de um arquivo. Novamente, usaremos a convengio de nos referirmos a um obieto
do tipo File, que represente um diret6rio real, comb um objeto Directory File, com D mairirculo (mesmo que seja do tipo
Filej E chamaremos os diret6rios reais, presentes em um computador, simplesmente de diret6rio. Caramba! Assim como
na criagXo de um arquivo, criar um diret6rio 6 um processo de duas etapas; primeiramente n6s criamos um objeto Dlrxtory
(File), e em seguidalriamos um diret6rio real usando o seguinte m6todo mkdir ( ) :

File myDir = new File ( "mydir" ) ; / | rri: rrm nlriol-n

myDir.mkdirO; / / cria um diret6rio real

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;

Cuidado ao criarnovosdiret6rios! Comovimos, construirumReaderou \trfritercriariautomaticamenteumarquivo, caso


nio existaum, mas nio acontece o mesmo com diret6rios:

File myDir = new File("mydir',) ;


//myDit.mkdir0; // chamada amkdiro omitida!
File myFile = new File(
myDir, "myFile.txt");
myFile.createNewFileo; // exceqio se ndo houver mkdir!

Isso irigeraruma exce$o parecida com

java.io.IoException: No such file or direcforv

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,

File existingDir = new File("existingDir,,); // atribui um diret6rio


System. out . println ( exist j-ngDir. isDirectory ( ) ) ,
File existingDirfile = new File(
existingDir, "existingDirFile.txt"); / / aluribu! um arcrurvo
System. out.println (existingDirFile. isFile ( ) ) ;
FileReader fr = new FileReader (existingDirFile) ;
BufferedReader br = new BufferedReader(fr); / / cria um Reader
String s;
while( (s = br.readline0) != nul1) // 16 dados
System. out.println (s) ;
br.closeO;

a seguinte saida serl gerada:


l-rrra

:::.r'" sub-dj-r dara


line 2 of text
line 3 of text
Preste atengio especial ao que o m6todo readline ( ) retorna. Quando nio houver mais dados para ler, readline ( )
retorna um valor null - esse 6 o nosso sinal para parar de ler o arquivo. Al6m disso, repare que nAo chamamos um
metodo f lush ( ) . Ao ler um arquivo, nXo 6 necessirio fezer flushing, de forma que vod nem sequer enconrrar6 um
m6todo f lush ( ) em um tipo de classe Reader.
Al6m de criar arquivos, a classe File tamb6m lhe permite fazer coisas como renomear e apagar arquivos. O seguinte c6digo
-
demonstra alguns dos recursos mais comuns referentes a apagar arquivos e diret6rios (via derete ( ) ), e renomear
arquivos e diret6rios (via renameTo ( ) ):

File delDir = new File ( "de1dir" ) ; / / crLa um diret6rio


delDir.mkdirO;
File de]Filel = new File(
delDir, "de1Fi1e1.txt") ; / / adiciona um arquivo ao diret6rio
254 Copftulo 6: Strings, E/S, Formotog6o e Porsing

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.

Obietivo poro o CertificoE6o

Serializagao (Objetivo 3.3 do Exame)


i.i Desnwtruraidigo que serialiry e / oa fusnialiry ofieas urando as seguintusAPIs delamin: DaulnputShvan, DataOatpatStream,
JAVA 5 255
Filelnputstrean, Fileoatpatstrean, oblutlnputStrean, objectoutputstrean e seiati\abte.

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

Trabalhando com ObjectOutputStream e Objectl nputStream


A migica da serializagio bisica acontece com apenas dois m6todos: uma para serializar objetos e escrevA-los em
um stream, e um segundo para ler o stream e deserializar os objetos.
Obj ectOutputstream. writeobj ect ( ) // serial-iza e escreve
Obj ectinputstream. readObj ect ( ) // AOe deserializa
As classes j ava. io . Obj ectoutputstream e j ava . io . Obj ectlnputstream sio consideradas como
de alto nivel no pacote java.io, e, como aprendemos anteriormente, isso significa que voc6 os usari para
encapsular classes de n(vel mais baixo, tais como java.io.FileOutputStream e java.io.Filelnputstream. Eis um
pequeno programa que cria um objeto (CaQ, o serializa, e depois o deserializa:
i mnnrl. "i arra i n * .

class Cat irylenentg Serial-izalcle | | ll t


public class SerializeCat {
public static void main(String[] args) {
Cat c = nevr c,aE(lt ll 2
try {
FileOuLputStream fs = new FileOutputstream( "testser. ser" ) ;

ObjectOutputstream os = new ObjectOutputstream(fs),.


os.writeobject (c) ; t/ 3
os. close O ;
) catch (Exception e) { e.printstackTraceO ; }
trv {
FilelnputStream fis = new Fil-elnputStreann( "testser. ser" ) ;

Objectlnputstream ois = new Objectfnputstream(fis) t


c = (Cat) ois.readObject(), ll 4
ois.closeO;
) catch (Exception e) { e.printstackTraceO; }

)
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

serializa o objeto e depois escreve o objeto serializado em um arquivo.


4. Deserializamos o objeto Cat chamando o m6todo readObject ( ). O m6todo readobject ( ) retorna um
Object, de modo que precisamos convener o objeto deserializado de volta em um Cat. Novamente, tivemos de passar
pelos passos tipicos de E/S para configurar isso tudo.

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

nrirrafa int- nnl 1:rqi za.

nrrhl in /-allarlinf cizal t colLarSize = size; ]


public int getCol-farSize ( I I r^fr1rn nnl I arQi zo. I

Agora crie um Dog... Primeiramente, voc6 cria um Collar (*coleira") para o Dog:
Coffar c = new Collar(3) ;

E entio cria um novo Dog, passando a ele o Collar:


Dog d = new Dog(c, 8);
Agor4 o que acontece se voc6 salvar Dog? Se o objetivo 6 salvar e depois restaurar um Dog e se o Dog restaurado for uma
duplicata erata daquele que foi salvo, entlo o Dog precisa de um Collar que seja uma duplicata qrata do Collarr que estava
atribuido a Dog no momento em que ese riltimo foi salvo. Isso sigpifica que tanto Dog quanto Collar devem ser salvos.
E se o pr6prio Collar tivesse referAncias a outros objetos - talvez um objeto Color, por exemplo? Isso fica bem
complicado rapidamente. Se fosse responsabilidade do programador conhecer a estrutura interna de cada objeto a
que Dog se referisse, para que o programador pudesse salvar o estado de todos os objetos que com certeza
estivessem relacionados a Dog... Isso daria trabalho. Seria um pesadelo, mesmo com os objetos mais simples.

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

cfass Dog implenenLs SerLalizable {


/ / resxo do c6digo id6ntico ao anterior
/ / SeriaTizabl-e ndo tem m6todos para implementar
]
E agora podemos salvar o Dog com o seguinte c6digo:
JAVA 5 257
'imnnrl- :*'*..-..i
i=rra in t
public class SerializeDog {
public static void main(StringlJ args) 1
Co11ar c = new Co11ar(3);
Dog d = new Dog(c, 8);
trY {
FileOutputstream fs = new FileOutputstream( "testser. ser,, ) ;
ObjectOutputstream os = new ObjectOutputstream(fs),.
os.writeObject (d) ;
os. close O ,.

) catch (Exception e) i e.printstackTraceO; )

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

Eis a listagem completa:


import java.io.*;
pubfic class SerializeDog {
public static void main(String[] arqs) t
Collar c = new Collar(3) ;
Dog d = new Dog(c, 5);
Svsrem orrf . nri nf l n ( "hefore. co11ar size is "
+ d. getCollar ( ) .getCollarSize ( ) ) ;
cry t
FileOutputstream fs = new FileoutputStream( "testser. ser" ) ;

ObjectOutputstream os = new ObjectOutputstream( fs) ;


os.writeobject (d) ;
os. c1ose O ,.

) catch (Exception e) { e.printstackfraceO; }


try {
FilelnputStream fis = new Filelnputstream("testser.ser") ;
Objecttnputstream ois = new ObjecLlnputStream(fis) ;
d = (Dog) ois.readobjectO;
ois.closeO;
) catch (Exception e) { e.printStackTraceO; }

System.out.println("after: coffar size is "


+ d. getCollar ( ) . getCollarSize ( )) ;

]
class Dog implements Serializable {
private Coll-ar thecollar;
258 Copitulo 6: Strings, E/S, FormotoE6o e Porsing

private int dogSize;


public Dog(Co11ar col1ar, int size) {
theCollar = col]ar;
dogSize = size;
)
public Collar get.CollarO { return theCollar; }

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

Isso produz a seguinte saida:

before: co11ar size i-s 3


afterr collar size i-s 3
Mas o que aconteceria se nio tiv6ssemos acesso ao c6digo-fonte da classe Collar? Em outras palavras, e se nio
tiv6ssemos a opgeo de tornar a classe Collar serializ6vel? Ficamos restritos a um Dog n1o-serializ6vel?
Obviamente, n6s poderiamos criar uma subclasse de Collar, marcar a subclasse como Serializable, e usar a
subclasse emvez da classe Collar. Mas isso tamb6m nio 6 sempre uma opgio, por virios motivos potenciais:

1.. A classe Collar poderia ser final, impedindo a criagio de subclasses.

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.

Entio... O que voc6 faz se quiser salvar um Dog?


liai q.te entra o modificador transient. Se vocd marcar avari|velde instAncia Collar de Dog como trran-
sient, a serializaglo ir6 simplesmente ignorar o Collar durante o processo:
class Dog implements Serializable {
private Uransient Col1ar theCollar; // adicionamos transient
/ / resto da classe id6ntica i ancerror
]

class Collar { / / ndo 6 mais Serializable


// mesmo c6digo
I

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?

Usando writeobiect e readObject


Considere o problema: n6s temos um objeto Dog que queremos salvar. O Dog tem um Collar, e o Collar tem um
estado que deve tamb6m ser salvo como parte do estado de Dog. Mas... O Collar nda |Sefializable, de forma que
precisamos marc6-lo como transient. Isso significa que, quando o Dog for deserializado, ele voltar6 com um
Collar nulo. O que podemos fazer para nos certificarmos de que, quando for deserializado, o Dog receba de
al-guma forma um novo Collar com as mesmas caracteristicas daquele que estava atribuido a Dog quando este
dltimo foi salvo?
JAVA 5 259
A serializagio Java possui um mecanismo especial para esse caso - um conjunto de m6todos privados que vocQ
pode.implementar na sua classe que, se presente, ser6 chamado automaticimenre durante a sirializagi6 e a
dese{*izaglo. E quase_ como se os m6todos fossem definidos na interface. Serializable, excero pelo fato de que nXo
sio! Eles fazem parte de um contrato de callback especial que o sistema de serializagio lhe oferece, o qual '
basicamente diz "se voc6 (o programador) tiver um par de m6todos que batam .o* Lrt" exata assinatura (voc6 veri
isso logo adiante), estes m6todos serio chamados durante o p.ocesso de serializagio/deserializagio,
Esses m6todos lhe permitem interferir
19 processo de serializagio e des-serializagdo. Assim, eles sio perfeitos
para.resolver o.problema com Dog e Collai: quando um Dog esti sendo sdvo, vot6 pode interferir no meio da
serializaglo e dizer ,"A prop6silo, eu gostaria de adicionar o estado da vari6vel (int) de Collar ao stream quando
o Dog for serializado". VocO adicionou manualmente o estado do Collar i representagio serializada de Dog,
mesmo que o pr6prio Collar nXo seja salvo.
E claroqne vod precisari restaurar o Collar durante adxializa$o, interferindo no processo e dizendo: "Eu vou ler aquele
int extra que sakei no stream de Dog e us6Jo para criar grn novo Collar, e depois airibuir esse novo Collar ao Dog que e$6
-
sendo deserializaclo". Os dois m6todos apeciais que vod define devem rer asinaturas EXATAMENTE como e$as;
private void writeObject (ObjectOutputstream os) {
/ / aqvi entra o seu c6digo para salvar as vari6veis de Co11ar
]

private void readObject (ObjectfnputSt.ream os) {


/ / aqur entra o c6digo para ler o estado de Collar, criar um novo Col]ar,
/ / e atribui-lo ao Doq
]
Sim, n6s vamos escrever m6todos que t6m o mesmo nome daqueles que estivemos chamando! Onde sio colocados
esses m6todos? Vamos modificar a classe Dog:

class Dog implements Serializable {


transient priwate Collar theCollar; | | nilo Dod€mos geriaLizar ieto
private int dogSize,.
public Dog(Co11ar col1ar, int size) {
theCollar = collar;
dogSize = size;
]
public Co1lar getCollarO { return theCollar; }
Drivate void writaObject (ObjectorltDutstrearn oF) l
/ / Ianqa loException // r
try {
os.defaultwriteobject ( ) t // 2

os . writelnt (theCollar. getcol-l-arSize ( ) ) ; // 3

) catch (Exception e) { e.printStackTraceO; }


)

Drivate voidt readObj ect (Obj ecthDut,st,ream ie ) {


/ / l-anqa IoException, ClassNotFoundException // 4

trY {
is.defaultaeadObject () ; // s
theCollar = new Coll-ar(is.readlntO ); // 6

) catch (Exception e) { e.printStackTraceO,- }

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

Como a Heransa Afeta a Serializagio


A serializagio 6 muito interessante mas, para apliciJa efetivamente, voc6 ter6 de entender como as superclasses
da sua classe afetam a serializagio.

oBSERVAQ6ES pnnn O EXAME


Se uma superclasseforSeialiqable, entdo, de aeordo com ar regrat nornais de interfaceJaua, todas at ubclasses dela automaticanente
inplenmtardo Seialiqable inplicitanente. Em outrat palauras, uma subclasse de uma clasn marcada cono Seialiqabh parsa fio teste E-UM
para Serialiqable, e, portanto, pode ser salaa sen qae se precisa marcar explicitanente a subclase como seriali4luel. E sinplesnente inpossiuel
vber se arzta claxe d niali4iuel ou ndo, A NAO SER$(JE uoci possa uer a drvore de heranga da clase para uerifcar se alguma das
superclasset implementa Seialiryble. Se a classe ndo utender explicitamente nenbama oatra, e ndo implenentar Seialirybk, entdo uoc€ ube
COM CEKTEZA que a classe ndo i seriali4luel, porque a elasse Object NAO implementa Seialiqabk.

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 {

// restante do c6diqo de Dog


]
Agora voc6 tem uma classe Dog serializ6vel, com uma superclasse nio-serializ6vel. E funciona! Mas existem algumas
implicag6es potencialmente drias. Paraentender completamente essas implicag6es, vamos voltarever adiferengaentre um
objeto oriundo & deserializagio e um objeto criado com new. Lembre.se de que quando um objeto 6 construido comnew
(em vez de ser deserializado), acontece o seguinte (nesta ordem):

1. Todas as variiveis de instAncias recebem valorespadrXo.


2. O construtor 6 chamado, o que imediatamente chama o constnrtor da superclasse (ou algum outro construtor
sobrecarregado, at6 que um dos construtores sobrecarregados chame o construtor da superclasse).

3. Todos os construtores de superclasses finnliz.urr.


4. As vari6veis de instAncias que sio inicializadas como parte das suas declarag6es recebem os seus valores iniciais (em vez
dos valorespadrXo que recebem antes de os construtores das superclasses finalizarem as suas tarefas).

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

c]ass Doq extends Animal implements Serializable {

/ / restante do c6digo de Dog


)

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

Dogd = new Dog(35, "Fido");


System.out.println("before: " + d.name + " "
+ d.weight) ;

try {

Fileoutputstream fs = new FileOutputstream("testSer. ser") ;

ObjectOutputstream os = new ObjectOutput.Stream(fs) ;

os.writeobject (dr ;

os. close O ;

] catch (Exception e) { e.printstackrraceO; }


trv {
FilelnputStream fis = new Filelnputstream( "testser. ser" ) ;

Objectlnputstream ois = new ObjecLlnputStream(fis) ;


A
v -- /n^^\
\uvvt r^a^.th-iaat-l\,
vrD.rsqsvvjevur/
^ic /

ois.closeO;
) catch (Exception e) { e.printStackTraceO; }

System.out.println("after: " + d.name + * \


+ d.weight) ;

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

oBSERVAQ6ES pene O EXAME


Se uoci seialiqar am conjunto 0u afll affE6 todos os elementos deuen ser seiali4lueis! Un sd elemento ndo-seiali4luel que sfafar,i a
seialiqapdo falhar. Obsene tambim que, enqaantl as interfaces dos conjuntot ndo sdo serialiqiueis, o sdo as classes conmtas dos conjantot
naAPIJaua.

A Serializageo nao 6 para Estiticos


Finalmente, voc| poder| perceber que falamos APENAS sobre varilveis de instAncias, e neo sobre variiveis
esdticas. As vari6veis estiticas devem ser salvas como parte do estado do objeto? Nio 6 importante saber o estado
de uma variivel estetica no momenro em que o objeto'foi serializado? Sim e'nio. Pode ser i.nport"ttte, mas neo faz
parte do estado da instincia de forma alguma. Lembre-se de que voce deve pensar nas vari6veis estiticas
puramente como variAveis de CLASSES. Elas nio t0m nada ver com instAncias individuais. Mas a serializaglo se
aplica apenas a OBJETOS. E o que acontece se voce deserializar^ trAs instincias diferentes de Dog, todas as quais
foram serializadas em momentos diferentes, e todas as quais foram salvas quando haviam valores diferentes de
uma mesma variSvelestitica da classe Oog . Qual instAricia seria a "vencedbra"? O valor e$etico de qual instAncia
JAVA 5 263
seria lsado para substituir aquele atualmente presente na (rinica) classe Dog atualmente carregada? Entendeu o
problema?
As vari6veis est6ticas NLINCA sio salvas como parte do estado do objeto, porque elas nio perrencem ao objeto!

oBSERVAQ6ES pene O EXAME


E quanto a DatalnpatStream e DataOulputstream? Elas utdo nos objetiuos! Ocorre qae, enquantt o exane estaua sendo criado, decidiu+e
qile eiJas duat c/assu ndo caiiam flaPrlaa, mas a/gudm se esqueceu de retini-/at tlos objetiuos. Portanto, uocd consegaiu unafo/ga. E ana
coisa a menos com qae re preoillpar.

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.

Obietivo poro o Certificog6o

Datas, Nfmeros e Moeda (Objetivo 3.4 do Exame)


i.4 UsarAPIs padrdo J2SE no pacote jaua.text parafonnatar ou exibir conetanente datas, nilmeros e ualores monetdrios para uma
/ocalidade espufrca; e, dado um nndrio, deterrtinar os mdtodos propriados caro uoci qaeia usar o local padrlo ou algum outro local
especifn. Desmuer o propdtito eo an da classe jaua.fiil.L.ocale.
A APIJava fornece um conjunto extenso (talvez extenso um pouquinho demais) de classes para$td6-lo a trabalhar
com datas, ntimero e moedas. O exame testari o seu conhecimento das classes e m6todos bisicos que voc6 usar6 para
trabalhar com datas e que tais. Ao terminar esta seqio, voc6 dever4 ter uma base s6li& em tarefas, como: criar novos
objetos Date e DateFormat, convener Strings em Dates e vice-versa, realizar fung6es de calend6rio, exibir valores
moneterios corretamente formatados, e fazer tudo isso para qualquer localidade do planeta. Na verdade, um dos
principais motivos pelos quais esta seglo foi adicionada ao exame foi para testar se vo c6. 6 capaz de realizar
internacionalizagno (ds vezes abreviada como "i18n') bisica.

Trabalhando com Datas, Nrimeros e Moedas


Se voc6 quiser trabalhar com datas de todo o mundo (e quem nio quer?), precisari familiarizar-se com pelo menos quatro
classes dos pacotes java.text e java.util. Na ve rdade, jiadmitiremos logo, voc6 poderi encontrar perguntas no exame que
usem classes que nio foram mencionadas especificamente no objetivo da Sun. Eis as quatro classes relacionadas a datas que
voc€ precisad entender:

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.

Orquestrando Classes Relacionadas a Datas e Nfmeros


Quando trabalhar com datas e ntmeros, vocA freqiientemente usari diversas classes juntas. E i-portante entender
como as classes que descrevemos acima se relacionam umas com as outras, e quando usar quais classes em
conjunto. Por exemplo, voc6 ter6 de saber que, se quiser format ar a data para um local especifico, tera de criar o
seu objeto Locale antes do seu objeto DateFormat, porque voc6 precisari do seu objeto Locale como um
argumento para o m6todo de criaglo de DateFormat. A Tabela 6-2 fornece uma visio geral de casos comuns de
264 Copilvlo 6: Strings, E/S, FormotoE6o e Porsing

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.

Tobelo 6-2 Cosos de Usos Comuns oo se Trobolhor com Dolos e N0meros

Caso de Uso Etapas

Obter a data e ahora atuais 1. Crie um Date: orte d = new DaE.e ( );


2. Obtenha o seu valor: String s = d.toStrj.ng0i

Obterum objeto que lhepermita 1.. Crie um Calendar:carendar c Calendar. getlnstance () ;


realizar c6lculos de data e hora no seu local 2. IJse c.aaa(. . ) e c.ro11 (. ) para realizar manipulaE6es
de data e hora.

Obter um objeto que lhepermitarealizar 1. CrieumLocale:


cilculos de data e hora em um local diferente. Locale loc = new Locale(1ingtua); ou
Locale foc = newlocafe(1ingua, pais)i
2. Crie um Calendar para esse local:
Calendar c = CaLendar.getlnstance(1oc);
3.Usec.aaa(. .)ec.ro11 (. .) parareahzar manipulag6es
de data e hora.

Obter um objeto que lhe pe rmitareafinar 1. CrieumCalendar:


cilculos de dataehora,e depois formatar Calendar c = Calendar.getlnstanceO;
o resultado em diferentes locais com 2. Crie uml-ocale para cada local:
diferentes estilos de datas. Locale 1oc = new Locale(. .);
3. Convena seu Calendar em um Date:
Date d = c.getTime0;
4. CrieumDateFormat
paracadaLocale:
DateFormat df = DateFormat.getDatelnstance
(sty1e, loc) I
5. Use o m6todo formatfl paracriar datxformatadas:
String s = df.format(d)i
Obterum objeto que lhe permita 1. Crie um Locale para cada local:
formatar nrimeros ou moedas em diversos locais.
Y r r
Localeloc : i tt
newl,ocale(. . Ji
2. Crie um NumberFormat:
NumberFormat nf = NurnberFormat.getlnstance(loc) ; OU
NumberFormat nf = Num.berFormat.
getcurrencylnstance ( l-oc) ;
3. Use o m6todo formatQ para criar saidas formatadas:
String s = nf.format(alqunNfmero);

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

Na nossa JVM, que usa um local dos Estados Unidos, a saida 6


1st date Sat Sep 0B 1_9:46:40 MDT 2001
Ok, para refer6ncia futura lembre-se de que h6 um trilhio de milisegundos a cada 3L e 2/3 anos.
Embora a maioria dos m6todos de Date tenham sido depreciados, ainda 6. aceitllelusar os m6todos getrime e
setrime, embora, como veremos em breve, seja um pouco inadequado. Vamos adicionar uma hora ) nossla instAncia de
Date, a panir do exemplo anterior:
imnnyf
frrrvvrL -.i-r'- ,,!il *,
Jqvo.uLft. ,

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

O que produz (novamente, na nossaJVM):


1st date Sat Sep 0B 19:46:40 MDT 2001
new time Sat Sep 0B 20:46:40 MDT 2001

$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 \.

Calendar ca1 = Calendar.getlnstanceO ;


Quando voc6 obt6m uma refer6ncia Calendar, como cal no exemplo acima, a variivel da sua refer€ncia Calendar na
verdade est6 se referindo a uma instAncia de uma subclasse concreta de Calendar. Nio 6 possivel saber com certeza qual
subclasse voc6 receberi (muito provavelmente, se-ri j ava . uti
1 . GregorianCalLndar), mas isso nio lhe {arA
diferenga. Voc6 estar6usando a API de Calendar. (A medida queJava continua a se espalhar peio mundo, p aramanter a
coesio, voc6 poder6 encontrar novas subclasses de Calendai especificas para diferentes locai$.

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

if (c. SITNDAY == c. getFirstDalofWeek ( ) ) ll #2

System.out.println("Sunday j-s the first day of the week");


System.out.println("trillionth mi1li day of week is "
+ c. get (c.DAY-OF-WEER) ) ; /l *3
c.add (Calendar.MONTH, 1) ; ll *4
Date d2 = c.getTime()t il*s
System.out.println("new date " + d2.toStringO );

Isso produz algo como


1st dafp sef serl 0B 19:46:40 MDT 2001
Sunday is the first day of the week
trillj-onth mi1lj- day of week is 7
new date Mon Oct 08 20:46:40 MDT 2001
Vejamos os detalhes deste programa, concentrando-nos nas cinco linhas salientadas:
1. Atribuimos a Data d1 I instAncia c de Calendar.

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

Date d1 = new Date(1000000000000L);

DateFormat[] dfa = new DateFormat[5];


dfa [0] = DateFormat. getlnstance ( ) ;
dfatll = DateFormat.getDat.elnstance( ) ;
dfa[2] = DateFormat.getDatelnstance (DateFormat. SHORT) ;
dfa[3] = DateFormat. gletDatefnstance (DateFormat.MEDIUM) ;

dfa [4] = DateFormat.getDatelnstance (DateFormat.LONG) ;


dfa [ 5 ] = DateFormat . getDatelnstance (DateFormat . FULL) ;

for(DateFormat df : dfa)
q\/qf am nrrl- nri
vJvuelrtvuL.v!fllLrrr\u! nl- l n ldf f nm:f /Al \ \ .
\sr/ /,

que, na nossaJVM, produz


9/8/01,7:46 PM

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

) catch (ParseExcept.ion pe) {


268 Copitulo 6: Slrings, E/S, FormotoE6o e Porsing

System.out.println( "parse exc" ) ; )

que, na nossaJVM, produz


d1 = Sat Sep 08 L9:46:.40 YIf,lT 2001
9/8/01
parsed = Sat SeF 08 00:00:00 MDT 2001
Repare que, pelo fato & e$armos usando um estilo sHoRT, perdemos alguma precisio quando convertemos o Date em
uma String. Essa per& de precisio surgiu quando convertemos de volta para um objeto Date, e a hora passou de 7:46
para mela-norte.

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

c. set (20L0 , I:., L4) i / / 14 de dezembro de 20L0


/ / (a contagem dos meses comeqa
em 0)
Date d2 = c.getTimeO;

Locale locIT = new Locale("it", f Laffa

Locale locPT = new Locale("pt"); Portugaf


Locale locBR = new Local-e("pt", \\pDnI. Brasil
Locale l-oclN = new Locale("hi", \ T\TZ I India
Locale 1oc,JA = new Locale("ja");

DateFormat dfUS = DaleFormat.getlnstanceO i


System.out.println("US " + dfUS.format(d2) ) ;
JAVA 5 269

DateFormat dfUSfull = DateFormat. getDatefnstance (

DateFormat . FULL ) ;
System.out.print.ln("US fu11 .' + dfUSfull.format(d2) );

DateFormat dffT = DateFormat.getDatelnstance(


DateFormat.FULL, l-ocfT) ;
System.out.println("ftaly " + dfIT.format(d2) ) ;

DateFormat dfPT = DateFormat.g'etDatelnstance (

DateFormat.FULL, l-ocPT) ;
Svsl-om orrl- nrinl- 'l n1.'p^rfrraal '. + rlfp.n f^.lm^l-//lrl\v-t )
I t

DateFormat dfBR = DateFormat. get.Datefnstance (

DateFormat.FULL, l-ocBR) ;

System.out.println("Brazi1 " + dfBR. format (d2) ) ;

DateFormat dfIN = DateFormat.getDatelnstance(


DateFormat.FULL, locIN) ;
System.out.println("India " + dfTN.format (d2)) '

DateFormat df.IA = DateFormat. getDatelnstance (

DateFormat. FULL, locrTA) ;

System.out.println(",Japan " + dfJA. format (d2) ) ;

Isso produz, em nossaJVM


US 1,2/14/1,0 3:32 PM

US ful1 Sunday, December l-4, 20L0


Italy domenica 14 dicernbre 2010
Portugal Domingo, 14 de Dezembro de 2010
Rrazil T)omincq, 14 de Dezembro de 2010
Tnr{i: 2}2a?? 21 2?22?? t2?2

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.

oBSERVAQ6ES peRA O EXAME


I-zmbre-se de que tanto os objetos DateFormat qtlaltto os NamberFormat podem ter os seas /ocais defntdot tonente n0 nlnentl da
instanciagdo. Cuidado czm cddigzs que tentam modficar o local de una instdncia existente - ndo existe nenhtm mitodo que fapa isso!

Existem mais alguns m6todos em Locale (getnisplayCountry ( ) e getDispl-aylanguage ( ) ) que voc6


precisari conhecer para o exame. Esses m6todos lhe permitem criar Strings que representem o pais e a lingua de
determinado local em termos tanto do local padrio quanto de qualquer outro local:
Calendar c = Calendar.g'et.InstanceO ;

c. ser (2070 , LL, ],4) ;


Date d2 = c. getTime ( ) ;

Locale locBR = new Locale("pt", "BR"); / / Brasil


Locale l-ocDK = new Locale("da", "DK"); // Dinamarca
Locale loclT = new Locale("it", ., IT,,); / / IL6,Iia
270 Copirulo 6: Strings, E/S, FormotoE6o e Porsing

System.out.println("def " + locBR.getDisplaycountry( ) ) ;


System.out.println("loc " + locBR.getDisplaycountry(locBR) ) ;

System,out.println("def " + focDK.getDisplaylanguage( ) ) ;


Sysbem.out.println( "1oc " + locDK. getDisplaylanguagle (locDK) ) ;

System.out.println( "Dtr " + 1ocDK.getDisplaylanguage (locrT) ) ;

Isso produz, em nossaJVM,

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

NuniberFormat[] nfa = new NumberFormat[4];

nfa [0] = NumberFormat. getrnstance ( ) ;


nfa [1] = NumberFormat.get.Instance (locFR) ;
nfa12) = NumberFormat.qetcurrencylnstance ( ) ;
nfa [ 3 ] = NunlcerFormat . getcurrencylnstance ( locFR) ,

for(NumberFormat nf : nfa)
qlrqlam arrf nrintlnlnf fnmal /f1 ) ).

Isso produz, na nossaJVM,

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

System.out.println(nf .format(f1) + " "1 ;


JAVA 5 271
try {
System. out.println (nf .parse ("1234.567,, ) ) ;
nf . setParselntegeronly ( true ) ;
System.out.println (nf .parse ( "1234. 567" ) ) ;
) catch (ParseException pe) {
System.out.println( "parse exc" ) ;
J

Isso produz, na nossaJVM,

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.

Tobelo 6-3 CrioEdo de lnstdncios poro os Principois Closses de iovo.text e de iovo.util

Classe Principais Opg6es de Criagio para as Instincias

util . Date new DateO;


new Date (lonq milisegnrndosDesdeOlOl70) ;

util . Calendar Calendar. geLlnstance ( ) t


Calendar. getfnstance (Locale ),
util . Local-e Locale. getDefault ( ),
new locale (St.ring lingua) ;
new locale(String 'I inarra Ql-r'ina
frrY naiq\
Y\4Av, '
t

text . DateFormat DateFormat. getlnstance ( ),


DateFormat . getDatelnstance ( ) ;
DateFormat . getDatelnstance ( estif o ) ;
DateFormat. getDatefnsLance (esti1o, Loca]e) ;

text . NumberFormat NumberFormat. getlnstance ( )


NumberFormat . qetlns tance ( Locale )
NumberFormat . getNumberlns tance ( )
NumberPormat . getNumberf ns tance ( Local e )
NumberFormat . getcurrencyTnstance ( )
NumberFormat . getcurrencylnstance (Locale )

Obietivo poro o Certificog6o

Parsing, Tokenizagilo e Formatagio (Objetivo 3.5 do Exame)


3.5 Escreuer aidigo que urc as APIs J2SE padrdes dos pacotesjaua.atil e jaua.uti/.regexparafotwatar oufaryrparcing de $ings ou
ttreams. Para stringt, escreuer aidigo q/./e ilre as classes Pattern e Matcher e o mdtodo String.s?lxt, Reconhecer e asarpaddes de exprusdu

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?

Buscas Usando Metacaracteres


Por pura sorte, regex 6 um mecanismo poderoso para lidar com os casos que descrevemos acima. No cerne desse mecanismo
reside a ideia de um metamatter. Como um exemplo simples, dg** que queremos procurar, em algwrs dadosfonte, por
todas as ocorr6ncias de digitos num6ricos. Em regex, a seguinte expressio 6 usada para se procurar por digitos num6ricos:

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

Entio, por exemplo, tendo-se:


fonte: "a 1 56
indice: 0]-2345678
padrSo: \w
regex retornar6, as posig6es 0 ,2,4,5,7 e 8. Os fnicos caracteres nessa fonte gue n6o batem com a definiglo de um caracer de
palavra sio os espagos em branco. (Observagio: neste exemplo, colocamos os dados-fonte entre aspas para indicar
claramente que nio havia espagos em branco nem no comego e nem no fim.

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

t a- fA-F I Busca pelas seis primeiras letras do alfabeto, em mairlsculas ou minrisculas.

Entio, por exemplo,


fonte: "cafeBABE"
indice: 01234567
pattern: Ia-cA-C]
retornaas posig6es 0, 7, 4, 5, 6.

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.

Buscas Usando Quantificadores


Digamos que queremos criar um padrio regex para procurar por literais hexadecimais. Como um primeiro passo,
vamos resolver o problema para nrimeros hexadecimais de um digito:
0 txxl t0-9a-fA-Fl
A expresslo acima poderia ser descrita como: "encontre um conjunto de caracteres no qual o primeiro caracter
seja um "0", o segundo ou um 'x" ou um "xo, e oterceiro seja ou um digito de "0" a "9", ou uma letra de "a"
seja
a
*f o
ou uma letra mairiscula de "A" a'F". tlsando a expressio anterior, e os seguintes dados,
fonte: "12 0x 0x12 OXf 0xcr"
indice : 0I234561 890L234567
regex retornaria 6 e 1,1,. (Observagio: 0x e Oxg nio sio nimeros hexa v6lidos.)
Como segundo passo, vamos pensar em um problema mais ficil. E se quis6ssemos apenas que regex encontrasse
ocorr€ncias de nrimeros inteiros? Os inteiros podem ter um ou mais digitos, entio seria 6timo se pud6ssemos dizar "rrm
ou mais' em uma expresslo. H6 um conjunto de construtores regex chamado de quantificadores, que nos permitem
especificar conceitos tais como "um ou mais". Na verdade, o quantificador que representa 'um ou mais" 6 o caracter " + ".
Veremos os outros em breve.

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.

Os outros dois quantificadores que iremos examinar sio:


* Zero ou mais ocorrAncias

? Zero ou uma ocorr6ncia


JAVA 5 275
Digamos que voc6 tenha um arquivo de texto contendo uma lista, delimitada por virgulas, de todos os nomes dos
arquivos- em um diret6rio que contenha virios projetos importantes (a prop6sito, nio 6 assim que n6s organizariamos
nossos diret6rios!). VocA deseja criar uma lgta de todos os arquivos cujos nomes comecem com pro j 1. Voc6 poderi
e.ncontrar arquivos .tYE, .java,.pdf, quem sabe?
Que tipo de expressio regex n6s poderiamos criar paraencontrar esses
diversos arquivos proj 1? Primeiramente, vamos daruma olhada em.o-o poJeria ser uma parti desse texto:

. . . "proj3. txt,projlsched.pdf ,projI,proj2,projl . 1ava" . . .


Para resolver esse problem4 iemos usar o operador regor ^ (circwrflexo), o qual mencionamos anteriormente. O operador
regex nlo cai no exame, mas ele nos ajudari a criar uma solu$o ideal para o nosso problema. O ^ 6 o simbolo de negaSo em
rego<. Por o<emplo, se quiser encontrar nrdo, exceto letras 4 b e c em um arquivo, voc€ poderia usar

[ ^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:

?6 ganancioso, ?? 6 relutante, para zero ou um


o 6 ganancioso, 'e? 6 relutante
, para zero ou mais
+ 6 ganancioso, + ? 6 relutante, para um ou mais

O que acontece quando temos a fonte e o padrio seguintes?


fonte: yyxxxyxx
padrio: . *xx
Primeiramente, estamos {azendo algo um pouco diferente aqui, ao procurarmos por caraceres que ajam como prefixo da
pane est6tica 0o<) da expresslo. Acreditamos que estamos dizendo algo como: "encontre conjuntos de caracteres que
276 Copftulo 6: Sirings, E/S, Formotoqdo e Porsing

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.

Quando Metacaracteres e Strings Colidem


At6 aqui, estivemos falando sobre regex de um ponto de vista te6rico. Antes de podermos coloc6-lo em pritica, temos de
discutir mais uma questao. Quando chegar a hora de implementar regex em nosso c6digo, seri bem comum que os nossos
dados-fontes e /ou as nossas express6es sejam armazenados em Strings. O problema 6 que metacaracteres e strings nXo
funcionam muito bem juntos. Porexemplo, digamos que queremos apenas criarum simples pa&io regex queprocurepor
digitos. Poderiamos renrar algo como

String pattern = "\d" i / / erro de compilaqdo!


Essa linhade c6digo nio vai compilar! O compiladorvO a barra\ e pensa "ok, 16vem umaseqii6nciade escape ,talvezseja
uma nova linha!" Mas nio 6 isso, em seguida vem o d e o compilador diz 'nunca ouvi falar de uma seqiiAncia de escape
\d'. A maneira de satisfazer o compilador 6 adicionar uma outra barra invertida na frente de \d:
String pattern = "\\d" ; / / um metacaracter que pode ser compilado
A primeira barra invertida dv ao compilador que tudo o que vier em seguida deve ser interpretado literalmente, e nio como
uma seqiiAncia de escape. E quanto ao metacaracter ponto Q? Se quisermos usar um ponto na nossa expressio como um
metacaracter, sem problemas, mas e se estivermos lendo alguns dados-fonte que por acaso usem ponros como
delimitadores? Eis uma outra forma de estudar as nossas opg6es:
Stringp=\\.',;//oregexv6issocomoometacaract
\r\
ef-.i-^
vulJrrY h
v -- \. // o compilador v€ isso como uma
JAVA 5 277
/,/ seqr.i6ncia de escape invelida em \lava
// o compilador fica feliz, e o regex ve um
// ponto, e nao um metacaracter
Um problema semelhante pode ocorrer quando voce passar metacaracteres a um programa Java por meio de
argumentos de linha de comando. Se quisermos passar o metacaracter \d para o nosso programa java, a nossa JVM
faz a coisa certa se dissermos
? java ooRegex "\d"
Mas 6 possivel que o seu JVM talvez nio faga. Se tiver problemas para executar os seguintes exemplos, voc6 pode
tentar adicionar uma barra invenida (ou seja, \ \d) aos seus metacaracreres de linha de comando. Nio se
preocupe, voc€ nio ver6 nenhum metacaracter de linha de comando no exame!

AO TRABALHO
A linguagen Jaua defne diuersas seqii1ncias de uc@q inclaindo

\n = linerted (que uocd poderi enczfrtrar no exame)

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

Localizando Dados atray6s da Correspond6ncia de Padr6es


Depois que vod
aprendeu um pouco de regex, usar as classes java.util.regex.Panern @attern) e java.util.regex.Matcher
(Matcher) 6 bem simples. A classe Pattern 6 usadaparaarmaznnar uma representagio de uma expressio regex, para que
possa ser usada e reusada por instAncias da classe Matcher. A classe Matcher 6 usada para chamar o motor regex com a
intengio de se realizarem operag6es de corresponddncia. O seguinte programa mostra Pattern e Matcher em agio,
e 6 uma boa base para voc6 iniciar os seus pr6prios experimentos com regex:

import java.util. regex. * ;


a]acc Paaav f

public static void main(String [] args) {

Pattern p = Pattern.compile (args [01 ) ;


Matcher m - p.matcher(args [1] ) ;
boolean b = false;
q\rcl-6m
vJ v eer!! t drrl- nrinl-lrl\DAl-l-arn i< \ +m nal-tarnl\\.

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\\.
/,

System. out . flush ( ) ;

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.

Tokenizando com String.splitQ


O m6todo split ( ) da classe String usa uma expressio regex como o seu argumento, e rerorna um array String
-
preenchido com os tokens produzidos pelo processo de divisio (ou tokenizagio). Essa 6 uma forma ritil de tokenizar
pedagos relativamente pequenos de dados. O seguinte programa usa args [ 0 ] para armazenar uma string-fonte, e
args [ 1] para armazenar o pa&io regex a ser usado como delimitador:
imnnrf iarzr
Jsws.sLfr.
rrtsi I x.,

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

IJm inconveniente de se usar o m6todo voc6 desejarl ver os tokens no


string. split ( ) 6 que freqiientemente
ter criado os
de tokenizagXo ap6s
momento em que est1o sendo produzidos, e, possivelmente, interromper uma operaEio
grande arquivo-. nrimero
tokens de que p*.ir". Po, ex.mplo, .ro.6 pod"ri" buscar um nrimero de telefone em um Se esse

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:

System.out.println ( "\" \\" ) ;

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("\\.");

Tokenizando com Scanner


A classe java.util.Scanner 6 o Cadillac do processo de tokenizaqio. Quando precisar executar tarefas s6rias de tokeniza$o, use
Scanner- essa maravilhosa classe tem de tudo. Al6m das fung6es bisicas de tokenizagio fornecidas por
String . split ( ) , a classe Scanner oferece os seguintes recursos:
r Scanners podem ser construidos usando-se arquivos, streams ou Strings como fontes.

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

Se esse programa for chamado com


? java ScanNext ..1 true 34 lni,
ele produziri
hits ssssibis2
E claro que nio estamos fazendo nada com os tokens depois de os obter, mas voc6 pode ver que os tokens de s2
sio convenidos para osseus respectivostipos primitivos-. lJm ponto fundamental 6 q.tt
m6todos
"q"i
chamados hasNextXxx ( ) testam o valor do pr6ximo token, mas neo o obt€m realmenti, nem se movem para o
pr6ximo token nos dados-fonte. Todos os m6todos nextxxx ( ) realizam duas fung6es: obtdm o pr6ximo t6ken, e
em seguida se movem para o token seguinte.
A classe Scanner tem m6todos nextxxx o (por exemplo nextlong o ) e hasrexLxxx o (por exemplo
hasNextDouble ( ) ) para todos os tipos primitivos exceto char. Al6m disso, a classe Scrnn.r te* .rh m6todo
useDel imi ter ( ) que lhe permite definir o delimitador como qualquer expressio regex v6lida.

Formatando com printfQ e formatQ


Qual seria a div_ersio de relat6rios cont6beis se nio pud6ssemos alinhar os pontos decimais? O que seria de n6s se nio
pu&ssemos colocar nrimeros negativos entre parenteses? Quest6es vitais como essas fizeram a equipe & criagio do exame
incluiraformataEiocomopanedoexameJava5.Osm6todosformatO eprint.f O foram-adicionadosa
java.io.PrintStream emJava 5. Esses dois m6todos se comportam exatamente da mesma maneira, enteo tudo o que
dissermos sobreum aplica-se a ambos. (Diz a lenda que a Sun adicionou printf ( ) apenas para agradar aos veihos
programadores de C.)

Nosbastidores,om6todo formatO usaaclassejava.utif .Formatterpar^f.azerotrabalhopesadode


formatagio. VocA pode usar a classe Formatter diretamente se quiser, mas, para o exame, tudo o que precisari
saber 6 a sintaxe b6sica dos argumentos que vocA passa ao m6todo f ormat O . A documentagio parJesses
argumentos de formatagio pode ser encontrada na API de Formatter. Iremos apresentar brevemente a sintaxe para
formatagio de Strings, o que ser6 mais do que suficiente para permitir que voct realize diversas tarefas de
formatagio E gabarite todas as quest6es de formatagio do exame.
Vamos comegar parafraseando a documentagio API para formatagio de strings (para uma abordagem mais
completa, muito mais completa do que voc6 precisa para o exame, consulte a API de java.util.Formarter):
printf ("string de formataqdo", argumento (s) ) ;
A string de formatagio pode conter tanto informag6es de strings literais
nXo-associadas com argumentos quanto
dados de formatagio especificos de argumentos. A dica para determinar esti olhando para dados
se voc6
formatados 6 que estes sempre comegam com um simbolo de porcentagem (o/o). Vejamos um exemplo, e nlo entre
em pAnico, explicaremos tudo o que vem depois do o/o em seguida:
System.out.printf("?2$d + t1$d", L23, 455);
Isso produz

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

r "-" Justifica o argumento ) esquerda


! "+" Inclui um sinal (+ ou -) com este argumento
I '0" Preenche os vazios deste argumento com zeros
I '," lJsa separadores de agrupamentos especificos do local (ou seia, a virgula em 123,456)
I "(" Coloca nfmeros negativos entre par€nteses
width Este valor indica o ndmero minimo de caracteres a serem exibidos (se quiser ter colunas bem
organizadas e bonitas, voc6 usari este valor o tempo todo).

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;

System.out.printf (">ts1$ (7d< \n" , rL) ;

System.out.printf (">t0, 7d< \n", i2\ ;


System.out. format ( ">%+-7d< \n", j.2) ;
System.out.printf(">%2$b + t1$5d< \n", i1-, false);
Isso produz:
> (123)<
>01,2,345<
>+12345 <

>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 ;

Isso produz algo como

Exception in t.hread \\main" j ava util . . 11 legalFormatConversionEx-


ception: d != java.lang.Double

Resumo para a certificagio


Strings A coisa mais importante a se lembrar sobre Strings 6 que os ofietotString sio inalteriveis, mas x rcfer€ncias a
Strings nio! Voc6 aprendeu que pode criar uma nova String usando outra j6 existente como ponto de partida, mas se nio
ahibairumavarT6vel de referAncia a uma nova String, ela ficar6 perdida para seu programa - voc6 nlo ter6 como acessar sua
nova String. Recapitule os m6todos imponantes da classe String.

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.

Usando String, StringBuffer e StringBuilder (Objetivo 3.1)


E Os objetos String sio inalter6veis, por6m, as variiveis de refer0ncia String nio.
E Se voc6 criar uma nova String sem atribuila, ela{icar| perdida para seu programa.

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

E A classe String 6 f inal - seus m6todos nio podem ser sobrescritas.


284 Copitulo 6: Strings, E/S, FormotoE6o e Porsing

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/S de Arquivos (Objetivo 3.2)


E As classes de java.io que vod precisa entender sXo File, FileReader, BufferedReader, File\7riter, Buffered\(/riter e
PrintVriter.
D Um novo objeto File nio significa que h6 um novo arquivo no seu disco rigido.
tr Objetos File podem representar um arquivo ou um diret6rio.
D A classe File lhe permite gerenciar (adicionar, renomear e apagar) arquivos e diret6rios.
O Os m6todos createNewFile ( ) e mkDir ( ) adicionam entradas ao seu sistema de arquivos.
fl File\Writer e FileReader sio classes de E/S de baixo nivel. VocA pode us6-las para escrever em arquivos e 16-
los, mas normalmente elas devem ser encapsuladas.
fl As classes de java.io devem ser "encadeadas" ou "encapsuladas" (esse 6 um uso comum do padrlo de projeto
decorador).
E E bastante comum "encapsular" um BufferedR eader em um FileRead er, para se ter acesso a m6todos de nivel
mais alto (mais convenientes).
E bastante comum'encapsular" um BufferedVriter em um FilelW'riter, para se ter acesso a mdtodos de nivel
E,
mais alto (mais convenientes).

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.

Serializagio (Objetivo 3.3)


D As classes que voc6 precisa entender esteo todas no pacote java.io; incluem: ObjectOutputStream e
ObjectlnputStream principalmente, e FileOutputStream e FilelnputStream, porque voc€ as :utilizar| para criar
streams de baixo nivel para serem usados pelas classes ObjectXxxStream.

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.

Datas, Nrimeros e Moeda (Objetivo 3.4)


E As classes que voc6 precisa entender slo java.util.Date, java.util.Calendar, java.text.DateFormar,
java.text.NumberFormat e java.util.Locale.
D A maioria dos m6todos da classe Date foram depreciados.
tr Um Date 6 armazenado como um 1ong, e refere-se ao nrimero de milisegundos desde 1o. de janeiro de 1970.
fl Os objetos Date sio uma esp6cie de ponre entre as classes Calendar e Locale.
D Calendar fornece um poderoso conjunto de m6todos para manipulagio de datas, para realizar tarefas como
obter dias da semana, ou adicionar determinado nirmero de meses ou anos (ou outros incrementos) a uma data.
tr Crie instincias de Calendar usando m6todos est6ticos de f6brica (getrnstance ( )).
E Os m6todos de Calendar que voc6 deveri entender slo add ( ) , que lhe permite adicionar ou subtrair virias
partes (minutos, dias, anos e assimpordiante) dedatas, e ro11 O, guefuncionacomo ad.d ( ), masnio
incrementa as partes maiores de uma data (por exemplo: adicionar 10 meses a uma data de outubro modi{ica o
m6s para agosto, mas nio incrementa o valor do ano de Calendar).

E InstAncias de DateFormat sio criadas usando-se m6todos estiticos de fibrica (getrnstance ( ) e


getDatelnstanceO ) .
B Existem diversos "estilos" de formatagio disponiveis na classe DateFormat.
E Os estilos de DateFormat podem ser aplicados a diversos Locales para se criar uma s6rie de saidas para
determinada data.
tr O m6todo DateFormat. f ormat ( ) 6 usado para se criar Strings contendo datas devidamente formatadas.
D A classe Locale 6 usada em conjunto com DateFormat e NumberFormat.
E Tanto objetos DateFormat quanto NumberFormat podem ser construidos com um Locale especifico e
imutivel.
E Para o exame, vocA deveri entender o processo de criaglo de Locales usando-se linguas ou uma combinagio de
lingua e pais.

Parsing, Tokenizagio e Formatagao (Objetivo 3.5)


D regex 6 uma abreviaEio de express6es regulares, que sio padr6es usados para se procurar por dados dentro de
grandes fontes de dados.

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 Estude os quantificadores gananciosos ?, 't e + .

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.

f,l A tokenizagio 6 o processo de se dividir dados em pequenos pedagos delimitados.


D Na tokenizaglo, os dados que vocA deseja dividir sXo chamados tokens, e as strings que separam os tokens seo
chamadas de delimitadores.

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.

E Os m6todos f ormat ( ) printf ( ) tAm funcionalidades indAnticas.


e

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,,) ;

Objectlnputstream is = new Object.InpuLStream(fis) ;


CardPlayer c2 = (CardPlayer) is.readObjectO;
is.closeO;
) catch (Exceptionx ) { }

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.

3. Dado que bw 6 uma refer6ncia a um BufferedWriter v6lido. E o seguinte fragmento:


15. BufferedWriter b1 = new BufferedWriter(new File("f") );
16. BufferedWriter b2 = new Bufferedwriter(new Filewriter("f1-") );
1,'7 . Bufferedwriter b3 = new BufferedWriter (new PrintWriter ("f2" ) ) ;
1-8. BufferedWriter b4 = new BufferedWriter (new Bufferedwriter (bw) ) ;
Qual6 o resultado?
A. A compilaglo tem sucesso.

B. A compilagio falha devido apenas a um erro na linha 15.


C. A compilaglo falha devido apenas a um erro na linha 16.

D. A compilaglo falha devido apenas a um erro nalinha 17.

E. A compilagXo falha devido apenas a um erro na linha 18.


F. A compilaglo falha devido a erros em diversas linhas.

4. Dado:
c_Lass 'l't(u I

public static void main(String[] arqs) {

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

Short s1 = (short) ((new Short((short)343)) / (new Short((short)49)));


if(s1 == 7) 5 += "=5 ";
if(s1 < new fnteger(7+1) ) s += "fly ";
System. out . println ( s ) ;

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.

7. Usando a menor quantidade de fragmentos possfvel (e preenchendo a menor quantidade


possivel de espacos dm branco), comElete o c6diso abaixo de forma que a classe trie um
diret6rio chamado "dir3" e ciie tanib6m um arqlivo chamado "f i143" dentro de "dir3".
Observe que vocC pode usar cada fragmento no m6ximo uma vez, ou deixS-lo sem uso.
C6digo:
import java.io.
al acc M:lrar I

public static void main(String[] args) {

)
Fragmentos:
FileDescriptor,' Di ranf nnr.

trY { . createNewDir ( ) ; File dir F r-re

t) (Exception x) ( "dir3" 1 ;

f i I ^ . createNewFile O ; = new File = new File


dir (dir, "fi1e3" ) ; (dir, file); nra:faFila/\ '

] catch ("dir3". "fi1e3"); .mkdj-rO; File file

8. Quais afirmativas s6o verdadeiras? (Marque todas as corretas)


A. DateFormat. getDate ( ) 6 usado para converter uma String em uma instAncia de Date.
B. Tanto os objetos DateFormat quanto os NumberFormat podem ser constnildos para ser especificos a um l-ocale.
C. Tanto os objetos Currency quanto os NumberFormat devem ser construidos usando-se m6todos est6ticos.
D. Se o Locale de um instancia de tqumnerFormaE for diferente do arual, ele deve ser especificado no momento dacia{ao.

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

9. Quais opg6es compilarao e rodareo sem exceg6es? (Marque todas :N corret,rs)


A. System.out.format("?b", I23l ;
B. System.out. format("%c", "x") ;
C. System. out.printf ( "ta" , ]-23) ;
D. System. out.printf ( "tt" , t23) ;
E. System.out.pri-ntf ("td" , 1,23.45) ;
F. System.out.printf ( "8f " , 1,23 .45) ;
G. System.out. format(\ts", new Long("t23") ) ;

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

B. Os objetos do tipo StringBuffer sio seguros em relagXo aos threads.

C Todas as trAs classes t6m m6todos append ( ) sobrecarregados.


D. O " + " 6 um operador sobrecarregado para todas as tr,3s classes.

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.

I l. Dado que I I 19280000000L 6 aproximadamente o n0mero de milisegundos de 1". de


janeiro de 1970 at6 20 de junho de 2005, e que voc6 deseja exibir essa data em alemao, usando
o estilo LONG tal que " ,June " ser6 exibido como ".Juni " , complete o c6digo usando os
fragmentos abaixo. Observagio: vocC pode usar cada fragmento no m6ximo uma vez ou entao
deix6-lo sem uso, e pode ser que n6o precise preencher todos os espagos.
Code:
import java.
import java.
class DateTvro {
public static void main(Strinq[] args) {
Date d = new Date(1119280000000L);
DateFormat. df =
);

System. out . println (

]
Fragmentos:
io. *; new DateFormat ( Locale. LONG

nio. *, DateFormat..getfnstance ( Locale.GERMANy


utif. * i DateFormat.getDatelnstance ( DateFormat..LONG
text. *; util.reg,ex,' DateFormat.GERMANY
date.*; df.format(d)); d.format(df));

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 +\ ") ;

C. String path = File.separator + d;


System. out.print (f i1e. exists ( ) t') ;

D. String path = File.separator + d,.


System.out.print(file.isFile() +" ") ;

13. Dado:
n'l ace Dnl i <h I

public static void main(String[] args) {


int x = 4;
StringBuffer sb = new StringBuffer(". . fedcba") ;

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

4. // lnsira o b1oco de c6digo agui


s. ]
6. )

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

A.Scanner sc = new Scanner("123 A 3b c,45, x5x,76 82 L");


while(sc.hasNextIntO ) System.out.print(sc.nextlntO + \ ") ;
B. Scanner sc = new Scanner("123 A 3b c,45, x5x,76 82 L").
useDelimiter(" ");
while(sc.hasNextIntO ) System.out.print(sc.nextIntO ") ;
C. Scanner sc = new Scanner("123 A 3b c,45, x5x,76 82 L");
while(sc.hasNext O ) {
if (sc.hasNextfntO ) System.out.print(sc.nextlntO + N ") ;
else sc.nextO; )
D. Scanner sc = new Scanner("123 A 3b c,45, x5x,76 82 L").
useDelimiter(" ");
while(sc.hasNextO ) {
if (sc.hasNextlnt() ) System.out.print(sc.nextTnt() + " ") ;
else sc.nextO; )
E. Scanner sc = new Scanner("L23 A 3b c,45, x5x,76 82 L");
do{
if (sc.hasNextIntO ) System.out.print(sc.nextfntO ") ;
) while ( sc.hasNextO );
F. Scanner sc = new Scanner("i-23 A 3b c,45, x5x,76 82 L").
useDel-imiter(" ");
do{
if (sc.hasNextlntO ) System.ouE.print(sc.nextlntO + " ") ;
] while ( sc.hasNextO );
| 5. Dado:
i mnnrf -.._.*-.
i:rra in * ;

public class Testser {


public static void main(String[] args) {
SpecialSerial s = new SpecialserialO;
try {
Objectoutputstream os = new ObjectOutputstream(
new Fileoutputstream( "myFi1e" ) ) ;
os.writeObject (s) ; os. close ( ) ;
ql/q,-am brinf /++c z + \ $\.
^rr,-

Objectlnputstream is = new Objectlnputstream(


new Filelnputstream( "myFi1e" ) ) ;
SpecialSerial s2 = ( Specialserial ) is . readObj ect O ;
is. close O ;
System.out.println(s2.y + " " + s2.zl;
) catch (Exception x) {System.out.println("exc"); }
)

class SpecialSerial j-mplements Serializable {


transient int y = 7;
static int z = 9;
JAVA 5 293
)

Quais opg5es slo verdadeiras? (Marque todas as corretas)


A. A compilagdo f.alha.
B. Asaida61009
C.Asaida6to o ro
D.AsaidaEto t g
E. Asaida6ro z ro
F. Para dterar o processo padrio de deserializa$o, vod sobrescreveria o m6todo readobj ect ( ) de Specialserial.
G. Para alterar o processo padrio de des-serializagio, vocA sobrescreveria o m6todo def aultReadobj ect ( ) de
SpecialSerial.

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.

A, B, C, D, F e G estlo incorretas com base no exposto acima. (Objetivo 3.5)


2. C esti correta. E vilido que uma classe implemente Serializable mesmo que a sua superclasse nio o faga. Entretanto,
quando voc6 deserializar esse tipo de objeto, a superclasse nio-serializavel deve rodar o seu construtor. Lembre-se de que
os construtores nio rodam em classes deserializadas que implementem Serializaf[s.

A, B, D, E e F esteo incorretas com base no exposto acima. (Objetivo 3.3)


eredwriters somente podem ser constru(dos encapsulando-se um rVriter. As linhas 16,
B esti correta. Buf f
lTet9esteocorretasporqueBufferedWriter,Filewriter ePrintWriter estendemWriter.
(Observaglo: Buffered\Triter 6 uma classe decorator. As classes decorator sio usadas extensivamente no pacote java.io
para lhe permitir estender a funcionalidade de outras classes)

A, C, D, E e F e$eo incorretas com base no exposto acima. (Objetivo 3.2)


4. B, C e D estio corretas. Lembre-se de que o m6todo equals ( ) para os wrappers de integers somente retornario
true seosdoistiposprimitivoseosdoisvaloresforemiguais.ComC,6validof.azerunboxingeusar::.EmD,6
vilido criar um objeto wrapper com uma expresseo, e fazer unboxing dele para comparagio com um tipo primitivo.
A, E, F, e G estio incorretas co.m base no exposto acima. (I-embre-se de que A esti usando o m6todo equals ( ) para
tentar comparar dois tipos diferentes) (Objetivo 3. 1)
5. Eesticorreta.AclasseDateselocalizanopacotejava.uLil,demodoqueelaprecisaserimponada(import),eos
objetos DateFonrnt devemsercriadosusandeseumm6todo static como DateFormat . getlnstance ( ) ou
T1=f
ueugr' 6E-^.m.|-
vlrrqu . d6fTf-f LaI99 r I .
vsuuaLeIIrD ^TndFrnaa t,/

A, B, C e D estio incorretas com base no exposto acima. (Objetivo 3.4)


6. A est6 correta. Uma instAncia
do tipo Computer ("computador") Tem-Um Keyboard ("teclado"). Pelo fato de
Keyboard nio implementar Serializable, qualquer tentativa de serializar uma instAncia de Computer cuasari o
langamento de uma exceglo.
B, C, D e E estio incorretas com base no exposto acima. Se Keyboard implementasse Serializable, enteo dois
objetos teriam sido serializados. (Objetivo 3.3)
7.

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.

i mnnrf i:rrr rrt- i I * .

i mnart- i :rzr I avt- * .

class DateTVo {
public static voj-d main(Strinq[] args) {
Date d = new Date(1119280000000L);
Dat.eFormat df = DateFormat.qetDatelnstance(
DateFormat. LONG, Locale. GERMANY) ;

System. out.println (df . format (d) ) ;

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.

C e D estio incorretas com base no exposto acima. (Objetivo 3.2)


13. C est6 correta. Lembre-se de que os m6todos StringBuffer usam indices que comegam pelo zero, e que os
indices finais normalmente sio exclusivos.
A, B, D, E, F e G esteo incorretas com base no exposto acima. (Objetivo 3.1)

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

I Usor Comporoble e Comporotor

t/ Exercicios 16oidos

P&R Tesle individuol


296 Cooftulo 7: Gen6ricos e Coniunlos
Os gen6ricos sXo possivelmente o recurso mais comentado de l_ava 5. Algumas pessoas.os adoram, outras os odeiam,
mas"eles vieram paraficar. Na sua forma mais simples, eles podem ajuCry -Vtottt"r o. c6digo mais f6cil de escrever e
mais robusto. No que t6m de mais complexo, podim s.r mrrito, muito dificeis de criar e de manter. Felizmente, os
criadores do .*"-. d..idiram abordar o l"do tn"ir simples dos gen6ricos, cobrindo os recursos mais comuns e riteis, e

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.

Obietivo poro o certificoEdo

Sobrescrevendo hashCode( ) e equals( ) (Obietwo 6.2 do exame)


6.2 Dininguirar sobrescrigdu arretas dos ndadot hashC,ode e Eaal^s das incurctas, e upbma difrrwqa mhe == e o mfitudo Euals-

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.

OCapinrlogabordar6wait( ),noLify( )enotifyAll( ).Om6todofinalize( )foiabordadonoCapinrlo3.


Portanto, nesta seElo examinaremos apenas os m6todos hashcode ( ) e equals ( ) . oh, iso &ixa de fora tostring (
) , nlo? Ceno, falaremos sobre ele agora mesmo porque s6 levar6 dois segtrndos.

Tobelo 7-1 M6fodos do c/osse Obiect qbordodos no exorne

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.

int hashCode ( ) Retorna o valor int do c6digo de hashing de um objeto, de modo


que esse objeto possa ser usado em classes Collection que
pr.gu.* o hashing, incluindo Hashtable, HashMap e HashSet.

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.

String toString ( ) Retorna uma "representaglo em texto" do objeto.

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

HardToRead h = new HardToReadO ;

System. out.println (h) ;

A execugio da classe HardToRead nos forneceri o interessante e significativo resultado,

% 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 +

". My shoe size is " + shoeSize) ;


)
)

Este resultado ficar6 um pouco mais inteligivel:

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.

Quando voc6 tiver que saber realmente :


se duas referdncias slo id6nticas, use : . Mas quando tiver que saber se os
pnipriw oQetw (e nio as referAncias) sio iguais, use o m6todo equals( ). Para cada classe que escrever, voc6 teri que
decidir se fari sentido considerar iguais duas instAncias diferentes. Em algumas classes, voc6 pode definir que dois
objetos nunca serio iguais. Por exemplo, imagine uma classe Car que tenha vari6veis de instAncia para itens como
marca, modelo, ano, configurageo - com certezavocA nio iri gostar se seu carro comegar a ser tratado como o mermr
carro de outra pessoa que possui ahibutos id^4nticos. Seu carro 6 seu carro e voc6 nio ir6 querer que seu vizinho Billy saia
dirigindo nele s6 por que, 'bem, na verdade 6 o mesmo carro; o m6todo equals$ informou isso". Portanto, dois canvs
nunca deuen ser considerados exatamente iguais, Se duas referdncias apontarem para to// carro, entio, vocA saberi que ambas
estio relacionadas a am carro, e nio a dois que tenham os mesmos atributos. Assim, no caso de uma classe Car talvez
voc6 nunca precise, ou queira, sobrescrever o m6todo equalsQ. Sabemos, por6m, que a est6ria nio termina aqui.

O que significar6 a neo sobrescr:Sio de equals( )


H6 uma limitagio potencial escondida aqui: se voc6 nio sobrescrever o m6todo equals ( ) , ndo ?odeni usar o objeto como
a cbaue em ama tabela de hashing e provavelmente neo obteri Sets precisos, de forma tal que nlo haja duplicatas conceituais.
O m6todo equals ( ) de Object usa somente o operador : : p^racomparag6es, portanto, a menos que vocA
sobrescreva eguals ( ) , dois objetos s6 serlo considerados iguais re as duas ryfer€ncias apnntarcm para o metno objeto.
Examinemos o que significa nio poder usar um objeto como a chave de uma tabela de hashing. Suponhamos que voce
298 Cooftulo 7: Gen6ricos e Coniuntos
tivesse um carro, muito especfn (digamos, o Subaru utilidrio vermelho deJohn, e nio o modelo menor, roxo, de Moe e
M"ry), e quisesse inserir em um objeto HashMap (um tipo de tabela de hashing, a qual examinaremos posteriormente
neste capitulo), de modo que pudesse pesquisar um carro em particular e recuperar o objeto Person correspondente ao
propriet6rio. Voc6 adicionaria a instAncia do carro como a chaue do objeto HashMap (junto com um objeto Person
corresponden!. ggTo o.y'1/a)..Contudo, o que aconteceri quando quiser faznr uma pesquisa? VocA quer informar ao
conjunto de HashMap: "Aqui est6 o carro. Agora fornega o objeto Person associado a ele". Por6m, teri problemas a
menos que ainda tenha uma referAncia ao mesmo objeto que usou como chave quando o adicionou ao coipnto. En
outras palauras, uoci ndo pode riar um oQeto Car iddntico e usdJo na puqaiv.
A conclusio 6 essa: se voc6 quiser que os objetos de sua classe sejam usados como chaves de uma tabela de hashing (ou
como elementos de qualquer estrutura de dados que use a equivalAncia para procurar - e/ov recuperar - um objeto),
teni que sobrescreuer equ'al-s ( ) para que daas instdncias diferentes pwsam ser consideradas iguais. EntXo, como corrigiriamos o
exemplo do carro? Voc6 pode sobrescrever o m6todo equals ( ) , a fim de que use o VIN (Vehicle Identification
Number) exclusivo como base da comparagio. Dessa forma, poderi empregar uma instAncia quando adrcionS-La aum
conjunto e essencialmente criar outra id6ntica quando quiser fazer uma pesquisa baseando-se nesse objeto como chave.
E claro que sobrescrwer o m6todo equals ( ) de Car tamMm permitir6 o surgimento da posibilidade de mais de um
objao representando um carro exclusivo existente, o que pode nlo ser seguro em seu projeto. Felizmente, as classes String e
wrapper firncionam bem como chaves em tabelas de hashing - elas sobrescrevem o m6todo equals ( ) . Portanto, emvez
de usar a irstAncia real do carro como chave no par carco/propriet6:io, vod poderia empregar simplesmente uma String que
representasse o identificador exclusivo do carro. Assim, nunca ted mais de uma instAncia representando um carro especifico,
mas ainda podera usar o curo - ou, em vez dele, am dc seus alributos - como a chave da pesquisa.

lmplementando um m6todo equals( )


Digamos que voc6 decidisse sobrescrever equals ( ) em sua classe. O c6digo poderia ficar com o formato a seguir:

public class EoualsTest {


public static void main (String [] args) {

Moof one = new Moof(8);


Moof two = new lqoof (8) ;
if (one. equals ( two) ) {
System.out.println("one and two are equal");
]
)

class Moof {
private int moofval-ue;
Mnnf f irf rr:l l {

moofValue = val;
)

public int getMoofValue ( ) {


return moofValue;
)
public boolean equafs(Object o) {
if ( (o instanceof Moof) && ( ( (Moof )o ) . getMoofValue ( )

== 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:

pubfic boolean equals(Object o) {


if ( ( (Moof)o).getMoofValueO == this.moofValue) {
// a Linha anterior compila, mas 6 ma1-escrita!
return E.rue;
] else {
return false;
-)
)

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:

if ( (o instanceof Moof) && (( (Moof)o).getMoofValue( )

== 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

pessoa) talvez seja interrompido no tempo de execuglo de maneira inesperada.

OBSERVAQ6TS pene O EXAME


l-.embre-sedequeosmdtodosequals( ),hashCode( )rLoString( ) tiotodospilblicu.Ocddigoaseguirndoseriauma
sobrucrigdo udlida do mdtodo eqwal-s ( ) , embora padesse parecer qile sim te uocd n6o o/hasse com bastante atengdo durante 0 €xat//€:

class Foo {boolean equals(Object o) { } }

E cuidado tambdm com ot tipos de argumento. O ndtodo abaixo d ama nbrecarga e nio ama sobrucrig1o do mdtodo equals ( ).'

class Boo {public boolean equals (Boo b) { }}

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.

Entendendo os c6digos de hashing


Para entender o que 6 apropriado e colreto, teremos qlre examinar como algurs dos conjuntos usam os c6digos de hashing.

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.

Chave Algoritmo do C6digo de


C6digo de

Alex A(f) + L(12) + E(s) +X(24) =42


Bob B(2)+o(15)+B(2) = le
Dirk D(4) +l(e) + R( 18) + K( | l) = 47
Fred F(6) + RilS)+ E(s) + (D) = 33

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

oBSERVAQ6ES pene O EXAME


En casos reais de hashing, n6o d raro ter mafu de uma entrada em un deptitito. Norma/nente, a recuperagdo adeqaada barcada en hashing 6

am procesto de duas etapas:

/ . Encontrar o deprisito certo (usando hashcode ) /. (


2. Procurar no dEdsito o elemento mto (anndo equals ( ) ).

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

HasHash(int xVal) {x = xVal; }

public boofean equals(Object o) {


HasHash h = (HasHash) o; / / Nao tente isso em casa
// um teste instanceof
if (h.x == this.x) {
return true;
1 01e6 r

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.

oBSERVAQ6SS peRA O EXAME


Um mdtodohashCode (
) qae retnme 0 mesmo uakrpara todas as instincias, vndo elas iguais oa ndo, ainda seni un mdtodo utllido - e atd
muno @ropiado! Por exerrpk, o aidigo ndo estaria uiolando 0 cnnhatz.
public int hashCodeo {return 1492; }
Dois ofietos com um ua/or x tgua/ a 8 terdo o mesmo aidtgo de hathing. Pordn, 0 metmr aconteceria con dofu nbjetls dferenter, um com o aalor
dexiguala/2 eoouhvcom um uakriguala-920. EsemdtolahashCode ( ) rimaitoinefciente; lenbre+e disso,porqaefardcomque
todos ot objetos s/an innidos no mesmo depdsito, mas, meJmr assim, o objeto podeni ser encontrado depois que o conlanto uascu/har no inico
depiitl - usandrt eqoaT.s ( ) -, tentando desesperadaante knliryC @6s muita puquisa, o objeto correto. En oatrat palatras, o aldigo de
hashing ndo @ttdou em nada a aalerar a pesqlis4 embora afnalidade do hashtng :e1a obter etsa uelocidafu! No entanto, esse adtod.o qae returflla
someflte um cddigo de basbing seria conidtrado
@npriado e atd comto porqae ndo tiola o contrato. Rqetirei nais xtma ae<r correto ndo ignfica
necessariamente bom.

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

Condigio Obrigat6rio Nio 6 obrigat6rio (mas


permitido)

x.equals (y) == true x.hashCode( ) ==


rz hr chl^nr{o
J .A4ssrrvvsv
/\ \|

x.hashCode( ) ==
x.equals(y) == true
rr hach(-nAa / \
I

Sem requisitos
de hashCode ( )

x. hashCode ( \ r- x.equals(y) == false


y. 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:

class SaveMe implements Serializable{


transient int x;
1nt y;
SaveMe(int xVal, int yval) {

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.

Ob;etivo poro o certificog6o

Conjuntos (Objetivo 6. I do exame)l


5.1 Dado um cenirio de pmleto, deterwinar qaait classu ef oa intefaces deuem w utadot para se implemennr adequadamente o pmjeto, inclaindo o

aso da interface Conparable.

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

conjuntos do pacote java.util est6 repleh de interfaces e

Mas o que fazer com um coniunto?


H6 algumas operag6es bisicas que normalmente sio em conjuntos:
a Adiaonar objetos ao conjunto.
I Remouer objetos do conjunto.
I Saberse am objeto (oagntpo de objetos) est6 no conjunto.
I Renperarum objeto no conjunto (sem remov6Jo).
I Iterarpelo conjunto, examinando cada elemento (o um ap6s o outro.

Interfaces e classes-chave da estrutura de coniuntos


No exame, voc6 ter6 que saber qual conjunto selecionar n base em um reouisito declarado. A API de coniuntos
comesa com um grupo de interfaces, mas tamb6m forn virias classes .orr.r.t"r. As principais interfaces q.te voc6
teri que conhecer no exame (e na vida) sio as sete descr a segurr:

Col-f ection Sorted Set


Ll-st Sorted Map
Queue
As principais classes concretas de implementagio que ter6 que conhecer no exame sio as treze a seguir ft6
outras, mas o exame nio as abor& especificamente):

mapas coniuntos istas Filas Utilitirios


HashMap HashSet rr-r-T
!!aylfDL
i
^l D-.i ^-.i f frrArrarra
uJ Yevuv
.ClleCtiOnS

Hashtable LinkedHashSet Arrays


TreeMap TreeSet Linkedlist
LinkedHashl.{ap
Nem todos os coniuntos da estrutura implementam realrnente a interface Collection. Em outras palavras, nem todos os
conlantos passam no tute E-(JM se @licado o C)tktrioo. Especificamente, nenhuma das classes e interfaces relacionadas a maPas
JAVA 5 305
sio derivadas de Collection. Portanto, embora SonedMap, Hashtable, HashMap, TreeMap e LinkedHashTable sejam
todas consideradx confuntoq nenhuma 6 realmente derivada de Collection. Para tornar as coisas um pouco mais
confusas, na verdade hi tr6s empregos simultlneos para apalavra"conjunto":

<<interhce>> <<interfuce>>
Set Queue

<<interhce>>
SortedSet

t *T:*] F-"-.,"'E ['."y1 tr'.til [-";f f-:"{l F..@-;1

<<interface>>
SortedMap

r"**il r'.",ffi;l [-;ili i,.*,',,1

implementa

Figuro 7-2 A hierorquio de inlerfoces e c/qsses de conjunlos


I conjunto, que representa qualqaerumadas estruturas de dados nas quais os objetos sio armazenados e Passam Por
iterag6es.

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

Coniuntos Itens exclusivos (classes que implementam Sed.

Mapas Itens com uma identificagio exclusiva (classes que implementam Map).

Queues Itens arranjados na ordem em que serio processados.

A Figura 7-3 ilustra a estrutura dos objetos List, Set e Map.


Mas h6 outras vers6es dentro desses tr6s tipos:

Classificada(Sorted) Nio-classificada(IJnsoned) Ordenada(Ordered) Nio.ordenada (Unordered)

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

Set O territ6rio do vendedor (duplicatas nio sio permitidas)

Baldes com os c6digos de Hashing


ffi Eq WA | ] E@
,/ ,rt \snformado{
Valores Gancho Chave Inglesa Inversor de fase LaPacltor oe rluxo

HashMap: Os produtos do vendedor (Chaves geradas a partir das lDs dos produtos)

Figuro 7-3 Obietos List, Sef e Mop


Talvez precisemos ser explicitos com relageo ) diferenEa entre classificado e ordenado, mas primeiro temos que
discutir o conceito de iteragdo. Quando pensamos em iteragio, podemos considerar a iteragio em um array usando,
digamos, um loop f or para acessar cada elemento em ordem ([0], [1], [2], e assim por diante). Iterar em um coniunro
geralmente significa percorrer os elementos um ap6s o outro comegando no primeiro elemento. No entanto, )s vezes,
at6 mesmo o conceito de pineirc 6 um pouco estranho - em um objeto Hashtable nio h6 a nogio de primeiro, segundo,
terceiro e etc. Nesse objeto, os elementos slo inseridos em uma ordem ca6tica (at6 onde sabemos) com base no c6digo
de hashing da chave. Mas, algo tem que vir primeiro quando iteramos; portanto, quando voc6 iterar em um Hashtable,
na verdade, haveri.uma ordem. Mas at6 onde podemos saber, ela 6 completamente arbitririae pode ser alterada de
maneira aparentemente aleat6ria com modificag6es no conjunto.
Ordenado Quando um conjunto 6 ordenado, significa que vocA podeiterar em seus elementos em uma ordem
especifica (nio aleat6ria). Um conjunto Hashtable nio 6 ordenado. Embora ele tenha uma l6gica interna para
determinar a ordem (com base nos c6digos de hashing e na implementagio do pr6prio conjunto), voc6 nlb ver6
nenhuma ordem quando iterar pelo coniunto. O conjunto Arraylist, no entanto, mant6m a ordem estabelecida pela
posigio do indice dos elementos (exatamente como um xray).LinkedHashSet mantlm a ordem estabelecida pela
insergXo, portanto, o rlltimo elemento inserido ser6 o riltimo do conjunto (diferente de Arraylist, no qual voc6 pode
inserir um elemento na posigio especifica do indice). Para concluir, hi alguns conjuntos que mant6m uma ordem
conhecida como ordem nataral dos elementos, e eles nio sio apenas ordenados, mas tamb6m classificados. Examinemos
como a ordem natural funciona em coniuntos classificados.
Classificado Um conjunto dasufcado significa que a ordem do conjunto estl determinada por alguma(s) regra(s),
conhecida(s) como ordem de classificagio. IJma ordem de classificagio nio tem nada a ver com o momenro em que o
objeto foi adicionado ao conjunto, nem com a riltima vez em que foi acessado, nem em que "posigio" foi adicionado.
A classificagio 6feitacom base em propriedades dos pr6prios objetos. Voc6 coloca objetos no conjunto, e o conjunto
descobriri em que ordem coloc6-los, com base na ordem de classificagio. Um coniunto que mantenha uma ordem
(por exemplo qualquer List, que usa a ordem de insergio), na verdade, nio 6 considerado classfcado a nio ser que use
algum tipo de ordem de classificagio. Na maioria das vezes, a ordem usada 6 algo chamado de ordem natural. O que
isso significa?
VocA sabe como classificar alfabeticamente - A vem antes de B, F vem antes de G, e assim por diante. Em um conjunto
de objetos String, a ordem natural 6 alfab6tica. Para objetos Integer, a ordem natural 6 por valor num6rico - 1 antes de 2,
e assim por diante. E para objetos Foo, a ordem natural6,hX, ndo sabemos. Nio h6 ordem natural par Foo, a menos ou
at6 que seu desenvolvedor fornega um4 por meio de uma interface (Comparable) que defina como as instAncias de
uma classe podem ser comparadas entre si (a instAncia a
vem antes de b, ou b
vem antes de a?). Se o desenvolvedor
decidir que os objetos Foo devem ser comparados entre si com o uso do valor de alguma varilvel de instAncia
(digamos que haja uma chamada bar), um conjunto classificado ordenar6 os objetos Foo de acordo com as regras da
classe Foo de como usar a vari6vel de instAncia bar
para determinar a ordem. E claro que a classe Foo poderia
tamb6m herdar uma ordem natural de uma superclasse emvez de definir a sua pr6pria ordem, em alguns casos.
Afora a ordem namral especficada pela interface Comparable, 6 possivel tamb6m definir outras ordens de classifica$o
diferentes usandose runa outra interfacs Comparator. Falaremos sobre como usar Comparable e Comparator paradefinir
JAVA 5 307
as ordens de classificagio mais adiante neste capitulo. Por agora, basta ter em mente que a ordem de classificagio
(incluindo a ordem natural) ndo 6 a mesma coisa que ordenar por insergio, acesso ou indice.
Agora que conhecemos o ordenamento e a classificagio, examinaremos cada uma das tr6s interfaces e, em seguida,
nos aprofundaremos em suas implementag6es concretas.

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.

oBSERVAQoES pene O EXAME


Ao usar Hashset ou I;inkedHashset, os objetos que uocd adicionar a eles deaerio sobrescrezer hashCode ( ) . Se ndo o fTgrem, o
ndtodt padrAl Ob j ec t . hashCode ( ) pennitir,i qae nilhplot objetos que uoci poderia considerar como "stgnficatiuamente igaais"
sejan adicionados ao seu conjanto d.e "tluplicatas ndo pennitidas".

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.

oBSERVAq6TS pena o EXAME


Vocd pode elininarfacilmente algarnas retplstas re reconhecer que, por exentplo, um co{anto M@ nio pode ser a classe escolhida quandofor
necessdrio am coryiunto de pares none/ ualor, jd que M4 i arua interface, e ndo ama c/asse conneta de inrplenentagdo. A rvdapda do exame 11

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

Iobelo 7-2 C/osses concretos de imp/ernentocdo de infe#oces de coniunfos

Classe Mapa Conjunto Lista Ordenado Classificado

Hash-l.{ap Nio Nlo


Nio Nio
TreeMap X Classificado Por
ordem natura/
ouregras de comparagio
personalizadas

LinkedHashMap X Porordem N"ao


de insergio ou
ultimo acesso

HashSet N"ao N*ao

TreeSet X Classificado Por ordem natara/


ou regras de comparagio
personalizadas
LinkedHashSet X Por ordem
de insergio Nio
JAVA 5 309
Arraylist X Por indice Nlo
Vector X Por indice Nlo
Linkedlist X Por indice Nio
Dri nri + l-
ef r;f'lrrarro
Ysvsv Classificado Por ordem de
"coisas a fazer"

OBSERVAq6ES pene O EJGME

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.

Obietivo poro o CertificoE6o

Usando a Estrutura dos Conjuntos (Objetivo 6.5 do Exame)


6.5 IJsarJungdes do pacotelaua.utilpara umuer cddigo qae manipule uma lista clarifmndo-a, realiqandn nela urua buva bindria, ou conuertendo-a

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.

I Fornece mecanismos de insergio e de busca mais poderosos do que os dos arrays.


Vejamos como se usa um Arraylist que contenha Strings. Um dos principais objetivos do projeto da Estrutura dos
Conjuntos foi oferecer uma rica funcionalidade no nivel das principais interfaces: List, Set e Map. Na pritica, voc6
geralmente instanciari um Arraylist polimorficamente, desta forma:
r 'i ^F
lIDL h.'r'i
rrryufr af nar^r Arr:rzT.i
d!!qj!rru\/, qj- / \ .
-

A panir do Java 5, voc0 poderi usar


List<String> mylist = new Arraylist<Strlng> ( ) ;

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

Arraylist.<String> 6 semelhante a String ] , no sentido de que declara um container


De virias maneiras, [
capaz de zen^r apenas Strings, mas que 6 mais poderoso do que um String J . Vejamos alguns dos recursos t
^rm
que um Arraylist possui:
imnarf
rrr(yvru ir.': r:f il *.
Jsvs.surr. ,

n"l-'-l rl6ctArr^\rT.i
ysv4+v i a al ac< <f {

publ-ic static void main(String[] args) {


310 Copitulo 7: Gen6ricos e Coniuntos

List<String> test = new Arraylist<String> ( ) ;


(t- rinc q - "hi /.

test. add ( "string" );


l-aqf add/c\.

test.add(s+s);
System. out.println (test. size ( ) ) ;
System. out.println (test. contains (42l, | ;
System. out . println ( test . contains ( "hihi " ) ) ;

test . remove ( "hi " ) ;


System. out.println (test. size ( ));
])
o que Produz:
3

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.

Autoboxing com Conjuntos


Em geral, os conjuntos sio capazes de armazenar Objetos, mas nio tipos primitivos. Antes de Java 5, um uso bastante
comum das classes wrapper er^p^ra fornecer uma maneira de se colocar um tipo primitivo em um conjunto. Antes de
Java 5, voc6 precisava encapsular manualmente um tipo primitivo antes de poder coloci-lo em uma coleglo. Com Java
5, os tipos primitivos ainda precisam ser encapsulados, mas o autoboxing faz esse trabalho para voc6.

List mylnts = new ArrayI,ist (l ; / / decfaraqdo pr6-.Tava 5


myfnts.add(new Integer(42)l; / / era preciso encapsular um int
A partir de Java 5, podemos usar
mylnts.add(42) ; / / o autoboxing cuida disso!
Neste riltimo exemplo, ainda estamos adicionando um objeto rnteger a myrnts (e nio um int primitivQ; mas
o que acontece 6 que o autoboxing reaJizao encapsulamento para n6s.

Classificando Conjuntos e Arrays


T6picos referentes i classificagio e busca foram adicionados ao exame paraJava 5. Tanto con untos quanto arrays
podem ser classificados e busiados usando-se m6todos da API.

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-

ct- rrf f ***,


rAA I \rn6nr16r,,
----"-- );
\

stuff . add ( "Boulder" ) ;


qfrrff arirl /\\Iai 1 / \ .

5-r,,€€ ^aa /\\^^r.^hrr\


LU! r . dUU \ Aspell ,l ;
JAVA 5 3I I
stuf f . add ( "Te1luride" ) ;

System.out.println("unsorted .. + stuff) ;

Collections. sort (Etuff) t l/ #2


System.out.println("sorted " + stuff) ;

Isso produz algo como:


unsorted IDenver, Boulder, Vai]-, Aspen, Telluridel
sort.ed [Aspen, Bou]der, Denver, Tellurj_de, Vaill
A linha 1 esti declarando_ um Arraylist de Strings, e a linha 2 est6 classificando o Arraylist alfabeticamente.
Falaremos mais sobre a classe Collections,.iunto com a classe Arrays, em uma segio posterior. Por ora, vamos nos
ater i classificagio.
Vamos imaginar que estamos construindo a melhor aplicagio de automagio de casas j|f.eita. Hoje, estamos nos
concentrando no home theater, e mais especificamente no centro de controle do DVD. J6 temos o software de E/S
paraler e €screver dados entre o arquivo dvdrnf o . txt e as instAncias da classe ovornf o. Eis aqui os principais
aspectos da classe:
class uvu-Lnto {

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

Eis os dados de DVDs presentes no arquivo dvdinfo.txt:


Donnie Darko/sci-f i/Gyl1enhal1,,Jake
Raiders of the Lost Ark/action/Ford, Harrison
200L/scL-fi/??
Caddy Shack/comedy/Murray, Bil-1
Star Wars/sci-f i/Ford, Harrison
Lost in Translation/comedy/Murray, Bilt
Pat.riot Games /action/Ford, Harrison
No nosso aplicativo de automaqio de casas, queremos criar uma instAncia de D\rDrnf o Dara cadalinha de dados oue
tivermos lido a dvdinf o. txt. Para cada instAncia, faremos parsing dr linhr de dados (embra-sle
panir doarquivo
de st.ring. split ( ) ?) e preencheremos as trAs variiveis de instAncias de ovbrnto. Finalmenre. oueremos
colocar todas as instincias de nvntnto em um Arraylist. Imagine que o m6todo populatel,ist (') (abaixo) faga
tudo isso. Eis um pequeno fragmento de c6digo do nosso aplicat'ivo:
'
Arraylist<DVDfnfo> dvdlist = new Arraylist<DVDInfo> ( ) ;
popul-atelis:uO; / / adiciona os dados do arquivo ao Arraylist
System. out. println (dvdlist ) ;
Voc6 poderi receber uma saida como esta:
lDonnie Darko sci-fi Gy11enha11, .fake
, Raiders of the Lost Ark action Ford, Harrison
, 200L sci-fi ??
, Caddy Shack comedy Murray, Bill
, Star Wars sci-fi Ford, Harrison
312 Copftulo 7: Gen6ricos e Coniuntos

, Lost in Translat.ion comedy Murray, Bill


, Patriot Games action Ford, Harrison
l
(Observagio: N6s sobrescrevemos o m6todo toString ( ) de DVDInfo,.portanto, quando chamamos println ( )

p^rao AirayList, ele chamou tostring ) ( para cada uma das instAncias.)

Agora que temos um Arraylist preenchido, vamos classific6lo:


Colfections. sort (dvdlisL) ;

Ops!, voc6 recebe algo como:


TestDVD. java:13 : cannot fi-nd symbol
s)rmbol : method sort ( java.util.Arraylist<DVDInfo>)
focation: class java.util.Coffections
Colfections. sort (dvdlist) ;
O que est6 acontecendo aqui? N6s sabemos que a classe Collections possui um m6todo sorL ( ) , e mesmo assim este
erro di entender que Coliections NAO remum m6todo sort ( ) capazde trabalhar com um dvdlist. Isso
a
significa que deve hiver algo errado com o argumento que estamos passando (ava:-nfo).
Se vocA j6 descobriu qual 6 o problema, n6s chutariamos que voc6 o fez sem a ajuda da obscura mensagem de erro
airma.. Afinal, .o-o ,. classificam as insdnciai de DVDrnf o? Como 6 que n6s conseguimos classificar
^oxr^d^
instAncias de String? Quando voc6 consulta Collections. sort ( ) na API, a suaprimeirareagio poderia ser
entrar em pAnico. Mas nio se desespere. Mais vmavez, a seglo dos gen6ricos lhe.ajudari a ler. a estranha assinatura
desse m6toio. Se voc6 ler a descrigio do m6todo sort ( ) de um argumento, ver6 que esse m6todo usa um argumento
List, e que os objetos em List precisam implementar umainterface chamada_Comparable. Ocorre que String
implementa Comparable, e 6 por isso que-fomos capazes de classificar uma lista de Strings usando o m6todo
Collections. sort O .

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

O m6todo compareTo ( ) retorna um int com as segu.intes caracteristicas:

I negativo Se thisobject < anotherobject


I zero SethisObject == anotherObject
I positivo Se thisObject > anotherObject
O m6todo sort ( ) usa compareTo ( ) para determinar como o List ou o array de objetos deve ser classificado.
Como voc€ tem a opgio de implementaicompareTo ) ( para as suas pr6prias classes, poderi usar quaisquer
crit6rios que desejaipara classificar as instAncias das suas classes'
Voltando ao nosso exemplo anterior para a classe DVDInfo, podemos optar pela solugio mais ficil e usar a
implementaEio da classe String de compareTo ( ) :
cfass DVDfnfo implements Conparable<D\IDlnfo> { // +r
/ / a6di ao exi sfente

^"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.

oBSERVAQAO pene o EXAME


Einpoftante/embrarque'quandosobresrezaequals O,uociprecisailsartlmargamentodotipoObjecL,ma!,quantlosobrescreae
compareTo O , uocl deue lltar tlm argumento do tipo qae utd clatsfiundo.

Juntando tudo, a nossa classe DVDInfo deveri se parecer com a seguinte:


cl-ass DVDInfo implements Comparable<DVDTnfo> {
Qfrinn Iit-la.

a|-rinn don16.

(t-rinn 1a:dAafnr.

DVDfnfo(String t, Stri-ng g. String a) i


title = t; g'enre = g; leadActor = a;
)
public String toStringO {
ret.urn title genre + "+leadActor+"\n";
]
public :Lnt coqrareTo(Dt/Dlnfo d) t
roturrr title. corqrareTo (d. getTitle () ),
)
public String getTitle ( ) {

return title;
)

// // vuLrvo
^111r^a
dafF^'^
vsuLgrD g
^ ^^!!^-.^
DgLLct-

Agora, quando chamarmos Collections. sort (dvdlist); obteremos


[2001 sci-fi ??
, Caddy Shack comedy Murray. Bill
, Donnie Darko sci-fi Gyllenhall, Jake
, Lost in Translation comedy Murray, Bill
, Patriot cames action Ford, Harrison
, Raiders of the Lost Ark action Ford, Harrison
, Star Wars sci-fi Ford, Harrison
l
Viva! Nosso Arraylist foi classificado por titulos. E claro que, se quisermos que o nosso sistema de automagio de
-
casas fique realmente bacana, provavelmente iriamos q.terer classificar coleg6is de DVDs de v6rias formas
diferentes. Uma.vez que classificamos nosso Arraylisiimplementando o m6todo compareTo ( ), parece que
estamos em um beco sem saida. 56 podemos implementar compareTo ( ) uma vez emuma classe,intlo como
fazemos para classificar nossas classes em uma ordem diferente daquela que especificamos em nosso m6todo
compareTo ( ) ? Boa pergunta. Por sorte, a resposta vem logo em seguida.

Classificando com Comparator


Enquanto estava procurando o m6todo Col-lections . sort ( ) , vocA deve ter reparado que existe uma versio
soblecarregada de q9r_t (_) qre usa um List E algo chamado de Comparator ('comparado4. A interface Comparator
lhe fornece a capacidade de classificar uma dada colegio de uma s6rie de formas difirentes. A outra coisa ritil sobre a
interface Comparator 6 que voc6 pode uslJa para classificar insdncias de qualquer classe - at6 mesmo classes que
voc6 nio pode modificar -, ao contr6rio de interface Comparable, que lhe iorgi a modificar a classe cujas instincias
voc6 deseja classificar. A interface Comparator tamb6m 6 Eastante f6cil de implementar, rendo apenas um m6todo,
31 4 Copitulo 7: Gen6ricos e Con juntos
compare (). Eis uma pequena classe que pode ser usada para classificar um List de instAncias de DVDInfo, por
g6nero.

import java.utiJ-.*;
class Genresort implements Comparator<DVDlnfo> {
public int compare(DVDInfo one, DVDfnfo two) t
return one. getcenre ( ) .compareTo (two. getcenre ( ) ) ;

O m6todo Comparator. compare ( ) retorna um int


cujo significado 6 o mesmo do valor de retorno do m6todo
Comparable. compareto i. Neste caso, estamos tirando vantagem disso ao pedir que compareTo ( ) faga o
(
trabalho de comparaglo para n6s. Eis um programa de teste que nos permite testar tanto o nosso c6digo Comparable
quanto o nosso novo c6digo Comparator:
imnnrf iarrr rrfil *.

'imnnrt- i:rr: in *. / / *^---1


// ^L^r I ^!, t :I.ecisa
PVlrUr4Lslf-L\' ! diStO
public cl-ass TestDVD {

Arraylist<DVDInfo> dvdlist = new Arraylist<DVDlnfo> ( ) ;

pubLic static void main(Stringll arqs) i


new TestDVDO.goO;
]
n"].'lia vvrs aal\ \ / I
vuvfru "^.iz{ Yv

nnnrrl afaT.i c|- I I .

System. out println (dvdlist ) ;


. / / a saida, conforme lida a parti-r do arquivo
Collections. sort (dvdlist) ;
System. out . println (dvdlist ) ; / / a saida, classificada por titulo

Genresort gs = new GenreSort ( )


Collections. sort (dvd1ist, ers) ;
System. out . println ( dvdlist ); / / a saida, cfassificada por g6nero
]
nrrl.rlin
vgv+4vwvfgyvyg4l4
rrnid nnnrr'lat-6T.icl- I\ I

/ / 16 o arquivo, cria j-nstAncias de DVDInfo e


// preenche o Arraylist dvdlist com essas instAncias
]
)

VocA ji viu as duas primeiras listas de saidas, eis a terceira:


IPatriot Games action Ford, Harrison
, Raiders of the Lost Ark action Ford, Harrison
,
a:rtdrr
vusvJ ehaaL nnmadrr
vvrrresj M11rr^\/
rrsrr eJ Ri l 1

, Lost in Translation comedy Murray, Bill


, 200L sci-fi ??
, Donnie Darko sci-fi Gyll-enhall, Jake
, Star Wars sci-fi Ford, Harrison
l
Pelo fato de as interfaces Comparable e Comparator serem tio parecidas, estera atento para o fato de que o exame
poderi tentar lhe confundir. Por exemplo, poderia ser pedido que voc6 implementasse o m6todo compareTo ( ) na
lnterf.ace Comparator. Estude a Tabela 7-3 para memorizar as diferengas entre essas duas interfaces.
JAVA 5 3I5
Tobelo 7-3 Comporondo Comporoble e Comporolor

iava.lang.Comparable java.util.Comparator

int objOne. conpareTo (objT\uo) int compare (objOne, objT\ryo)


Retorna O mesmo que Comparable
negativo se obj One < objTwo
zerose objOne == oj)l'rwo
positivo se ob j One > objTwo
Vod precisa modifi car a classe Voc€ cria uma classe separada
cujas irstincias deseja classificar. daquela cujas instlncias deseja classificar.

56 pode ser criada uma seqii6ncia de classificagio. Podem sercriadas muitas seqiiAncias & classificaglo.

Implementada freqtientemente na API por: Elaborada para ser implementada


String, $?rapper classes, Date, Calendar... com o obietivo de classificar
instAncias de outras classes.

Classificando com a Classe Arrays


Estivemos usando a classe java.util.Collections para classificar conjuntos; vamos ver agora como usar a classe
java.util.Arrays para classificar arrays. A boa noticia 6 que classificar arrays de objetoJfunciona da mesma forma
como classificar conjuntos de objetos. O m6todo Arrays. sort ( ) 6 sobrescrito da mesma forma que o m6todo
Collections. sort O .
I Arrays. sort (arrayToSort)
I Arrays. sort (arrafloSort, Comparat.or)
Al6m disso, o m6todo Arrays . sort ( ) 6 sobrecarregado zilh6es de vezes para fornecer alguns m6todos de
classificagio para todos os tipos de primitivos. Os m6todos Arrays . sort i ) qn classificam tipos primitivos
s.emPle o
.fazem
com base na ordem natural. Nio se engane com uma questio do exame que ten6 classificar vm array
de primitivos usando um Comparator.

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.

oBSERVAQoTS pene O EXAME


l{isfalamos um bocado nbre a clastifcapdo por ordem nataral e nbre o aso de Comparatorc para classficar. A r)ltina regra qae uocd
preasani memoriTar 6 que, tempre qile quiser classificar ilm affal oa um coiunto, os elementos contidos nesses objetos deuem vr todos
mataamente companiueis. Em oatrat pa/atras, se uocd tiuer un Obj ecL I J e colocar obietor CaE e Dog dentro dele, ndo Dodeni
clasfici-k. Em geral, objetos de tipos dfferentes deuem vr considerados cono NAO sendo mataamente compariueis, a nio ser q)e se-fa
indicado explicitanente qae sio.

Fazendo Buscas em Arrays e em Conjuntos


As classes Collections e Arrays fornecem m6todos que lhe permitem procurar por um elemento especifico. Ao fazer
buscas em conjuntos ou arrays, aplicam-se as seguintes regras:

I As buscas sio realizadas usando-se o m6todo binarySearch () .

I As buscas bem-sucedidas retornam o indice int do elemento sendo procurado.


r Buscas mal-sucedidas retornam um indice int que representa o ponto de insergdo. O ponto de insergio 6 o lugar no
conjunto/ array onde o elemento seria inserido para manter o conjunto / array corretamente classificado. Pelo fato
de valores de retorno positivos e O indicarem buscas bem-sucedidas, o m6todo binarySearch ( ) usa nrimeros
negativos para indicar pontos de insergio. lJma vez que 0 6 um resultado vilido para uma busca bem-sucedida, o
primeiro ponto de inserglo disponivel 6 -1. Assim, o ponto de insergio 6 realmehte represenrado como (-(ponto
de insergio) -1). Por exemplo, se o ponto de insergXo de ,rma busca estiver no elemento 2, o valor real do'fonto
retornado ser6 -3.
r O conjunt o/ anay onde esti sendo feita a busca deve ser classificado antes que voc6 possa procurar nele.
I Se voc6 tentar procurar em um array ou conjunto que ainda nio foi classificado, os resultados da busca nXo serio
prevrsrvers.

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

System.out.println("now reverse sort") ;


ReSortComparator rs = new Resortcomparator0; / / +3

Arrays . sort ( sa, rs ) ;


for(String s : sa)
System.out.print(s + " ")'
q\/qfam nrri- nrinl- ln{"\nonc = "
+Arrays.binarySearch(sa,"one")); // #4
Qrr<l-om
rf r ue.rL. vqL IIf L If I \ vrlE
N
^rrf , ^-i-ts]h/\^FA
P! --

+ 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

)
]
)

o que produz algo como:


four one three two
one=1
now reverse sort
two three one four
one = -1
one=2
Eis o que aconteceu:
Linha 1. Classifica o arruy sa, alfabeticamente (a ordem natural).
*um", que 6 1.
Linha2 Procura pela localizagio do elemento

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.

oBSERVAQ6TS pene O EXAME


Ao reto/uer quesldes sobre busca e classifcap1o, os dois errot mais cotzuns tdo:

l. Procurar em tlm an"El ou conjunto que ndo tenha sido c/assficado.


2. Usar um Comparator oa sd na classifcagdo ou sd na basca, mas ndo em ambas.

Convertendo Arrays em Listas e de Volta em Arrays


Existem alguns m6todos que lhe permitem converter arrays em Lists, e Lists em affays. As classes List e Set possuem
m6todos toArray ( ), e a classe Arrays poszui um m6todo chamado aslist ( ) .
O m6todo Arrays . aslist ( ) copia um array para dentro de um List. A API diz, "retorne uma lista de tamanho
fixo baseada no array especificado (modificag6es feitas na lista retornada sio escritas diretamenre no array)." Quando
voc6 usa o m6todo asl,ist
O , o array e o List ficam unidos como se fossem um s6. Quando voc6 atualiza um deles, o
outro 6 atualizado automaticamente. Veiamos:

String[] sa = {"one"
List slist = Arrays.aslist(sa); / / cria um List
System.out.println("size " + s],ist.sizeO ) ;

System.out.println( "idx2 " + sl-ist .geL(2) |;

qT,iqt- qal- /? "qiv.\ // modifica List


sa[1] = "five"; // modifica o array
fnrlQfrind c . <al

System.out.print(s + " ");


System.out.println("\nsf [1] " + slist.get (1) ) ;
Isso produz
sj-ze 4

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

for(int x=0; x<3; x++)


i-r,. add (x) ;

Object[] oa = iL.toArray(]; / / tri r rrm *--*r


=rrarr _JlecE.
Al

Integerll taz = new Integer[3];


ia2 = iL. toArray (ia2) ; / / rri a rrn :rr:\/ Tnf 6ft6r

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

List<Dog> d = new Arraylist<Dog>O;


Dog dog = new Dog("aiko");
d :Ari ldnn\ .

d. add (new Dog ( "cl-over" ) ) ,'


d. add(new Dog ( "magno1ia" ) ) ;
Iterator<D,o9> i3 = d.iterator(); ll cria un Lteragor
while (i3.hasNextO ) {
Dog d2 = i3.nex!O; / | ndo 6 preciso converter
System. out. println (d2 . name) ;
)
System.out.println("size " + d.size() ) ;
System.out.println("getl- " + d.get (1) .name) ;
System.out.println("aiko " + d.indexOf (doS) ) ;
d. remove (2 ) ;
object[] oa = d.toArrayO;
for(Objecto:oa) {

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

System.out.print(o + " ").

Se voc6 inserir a seguinte linha de c6digo,


Set s = new HashSeto; // lnsira este c6digo
receber6 uma saida como esra:

true true true false true


e iarra I:nc. Ohiect@e09713 42 b
E i*pon.nt. saber que a ordem dos objetos exibidos no segundo loop for nXo 6 previsivel: Hashsets e
LinkedHashS.S garantem nenhum.tipo & ordenagio. Al6m disso, repare que a quarta chamada a add ( 1 falhou,
""g uma entradaduplicada (uma String com o valor a) no Set.
porque tentou inserir

Se inserir esta linha de c6digo,


Set s = new TreeSet0; // insira este c6digo
vocA receber6 algo assim:

Exception in thread "main" java.lang.ClasscastExceptlon: java.


1ang. String
at j ava. lang . Integer . compareTo ( Integer . j ava: 3 5 )
at java.util-.TreeMap. compare (TreeMap. java : 1093 )
at java.util.TreeMap.put. (TreeMap. java: 465)
at java.util.Treeset.add(TreeSet. java: 210)
A questio6 que, sempre que voc6 quiser classificar um conjunto, os seus elementos deverlo ser mutuamente
compariveis. Lembre-se
!e que, a nio ser que seja especificado o contr6rio, objetos de tipos diferentes nio sio
mutuamente comPaf avers.
320 Cooitulo 7: Gen6ricos e Coniuntos

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 { }

enum Pets {DOG, CAT, HORSE }

al acc ManrFact I

public static void main(String[] args) {


Mapcobject, Object> m = new Hashlvlap<object, Object>O;

m.put("k1", new Dog("aiko")); // adiciona algruns pares de chave / va]-or


m.put ("k2" , Pets.DOG) ,

m.put (Pets.CAT, "CAT key" ) ;


Dog d1 = new Dog("clover"\; // vamos manter esta refer6ncia
m.put(d1 , "Dog key");
m.put(new CatO , "Cat key") ;

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,

public int hashCodeO {return 4; } // #2

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+

obteremos algo como:


DogB4

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.

Usando a Classe PriorityQueue


A riltima classe relativa a conjuntos que voc6 precisari conhecer para o exame 6 PriorityQu:ue. Ao contr6rio de
estnrturas bisicas de filas que seguem o esquema primeiro-a-entrar-primeiro-a-sair por padrio, PriorityQueue ordena
os seus elementos usando uma prioridade definida pelo usuirio. A prioridade pode ser simplesmente a ordem natural
(na qual, por exemplo, uma entrada 1 teria maior prioridade do que uma entrada 2). Al6m disso, PriorityQueue pode
ser ordenada usando-se um Comparator, que lhe permite definir qualquer ordenamento que quiser. As filas possuem
alguns m6todo nio encontrados em outras interfaces de conjuntos: peek O, poll O e of f er O .
i mnnrf i:rz: rr I i 'l * .

class PQ {
static class PQsort
implements Comparatorclnteger> { / / ordem inversa
public int compare(Integer one, fnteger two) {

return two - one; / / rrnl-rnvina

public static void main(Strj-ng[] args) {

int[] ia = {1,5,3,1,6,9,8 }; / / dados n5o-ordenados


eriorityQueue<fnteger> pq1 =
new PriorityQueue<Integer> (); / / usa a ordem natural-

fnrf inl- v . i:\ // aarranz: fil:

na1 nffar /v\ .

for(int x : ia) // revisa a fila


System.out.print(pq1 .poll() + " ");
System. out . println ( "");

PQsort pqs = new PQsort ( ) ; / / obL6m um Comparator


Prj-orityQueue<Integ'er> pq2 =
new PriorityQueue<Integer> ( 10, pqs ) ; // usa o Comparator
for(int x : ia) // carrega a fila
na? nffar 1v\

System.out.println("size " + pq2.sizeO ) ;


System.out.println("peek " + pq2.peekO ) ;
System.out.println("size " + pq2.sizeO ) ;
System.out.println("po11 " + pq2.po11 O ) ;
System.out.println("size " + pq2.sizeO ) ;
for(int x : ia) // revisa a fila
System.out.print(pq2.po1l 1 I + " ") ;
JAVA 5 323

Esse c6digo produz algo como:

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.

Visio Geral dos M6todos para Arrays e Conjuntos


No que se refere a essas duas classes, j6 abordamos os m6todos mais complexos que voc6 poder6 encontrar no exame.
A Tabela 74 apresentaum resumo dos m6todos que voc6 tamb6m precisa conhecer. (Observagio: A sintaxe t [ ]
ser6 explicada mais adiante neste capitulo; por agora, pense nela como significando "qualquer array que NAO seja um
array de tipos primitivos.")

Tobelo 7-4 Principois M6todos em Arroys e Coniunlos

Principois M6todos em iovo.util.orroys DescriE6es

static List aslist (f t I ) C-onvene um ar:ry em um List (e vincula um ao outro).

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.

Procura um valor em um array classificado com


static int binarySearch (T[ ], key, Comparator) Comparator.

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 [ ] )

Classifica os elementos de um array usando um


public staticvoid Eor! (T[ ], Comparator) Comparator.

public static String tostring (Object[ ] )


Criam uma String que possui o conterido de um array
public static String toString (primitive [ ] )
324 Copitulo 7: Gen6ricos e Coniuntos

Principois M6todos em iovo.util.Collections DescriE6es

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 reverse (List) Inverte a ordem dos elementos em um List.

static Comparator reverseOrder ( ) Retornam um C-omparator que classifica o inverso da atual


static Comparator reverseOrder (Comparator) seqiiAncia de classificaglo do conjunto.

static void Eort (List) Classificam um List ou pela ordem natural ou por um
static void sort (List, Comparator) Comparator.

Visio Geral dos Mtitodos para List, Set, Map e Queue

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.

Tobelo 7-5 Principois M6todos em Lisl, Set e Mop

Principois M6todos do Inter{oce List Set Mop DescriE6o

Adicionam um elemento. Para Lists,


boolean add (element)
opcionalmente adicionam o elemento em um
boolean add (index. element)
ponto indice.

boofean contains (object) Procuram em um conjunto por um objeto (ou,


boolean containsKey (object key) X
X
opcionalmente, por Maps com urna chave),
bool-ean containeValue (obj ect value) retornam o resultado como um valor booleano.

object get (index) x


ObtAm um objeto de um conjuntq atrav6s de
object get (key) um indice ou uma chave-

int indexOf (object)


Obt6m alocalizagio de um objeto em um List.

Iterator iterator ( ) Obt6m um Iterator panr um List ou Set.

Set keyset, ( ) Retorna um Set contendo as chaves de um lvlap.

Dut (key, value) Miciona um par de chave / valor a um ldap.

remove ( index)
Removem um elemento atrav6.s de um indice,
remove ( obj ect ) X
remove (key) do valor do elemento ou de uma chave.

i-r Retorna o nrimero de elementos de um


rrrL ^i-^/\
srze t, x
coniunto.

ObjectI I toArray (1 Retornam um arraycontendo os elementos do


X X
r[ ] toArray (Tt I ) conluruo.

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

OBSERVAQ6TS pene O E)GME


E inpotante conhecer a/guns detalhes da ordenagdo natural. O rcguinte cddtgo lhe qudm,l a entender as poigdu rclatiuat de caractms naitisculos,
minilscu/os e eJ\a[os na ordena€do natura/:
JAVA 5 325
String[] sa = {"tf f.", f<'i\, \,>f <,,, l,>FF<\\ }; / / est6. ordenado?
\\>
PriorityQueue<String> tre3 = new Priorj-tyeueue<String> ( ) ;
for(String s : sa)
na? nffarlc\ .

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,

Obietivo poroi o CertificoEdo

Tipos Gen6ricos (Objetivos 6.3 e 6.4 do exame)


5.3 Estreuer cddiga qt/e ilse a., uersdu gendricar da API dos Conluntos, en particular as tnterfans Set,List e Map e as clatses de implenentagio.
Reconhecer as kmitagdes da API nda-gendica dos Co$untos e como refatorar cddigo para usar as uersdes gendicas.

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.

A Forma Antiga de se Usar Conjuntos


Eis uma revisio de um Arraylist pr6-Java 5 criado para armazenar Strings. (Dissemos "criado" porque isso era tudo o
que voc6 podtafazer - criar o conjunto -, mas nada garantiaque o Arraylist iria armazenar apenas Strings).

List mylist = new ArraylistO; // impossivel- declarar um tipo


mrrT.i cf ad.l / \E'rad
---- " \, i / / iv a1 a anazan^ Qf rihdc

mylist.add(new Dog ( ) ) ; // e armazena Dogts tamb6m


myl-ist. add (new fnteger (42) \ ; // eAnLegers...

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:

List<String> mylist = new Arraylist<String> ( ) ;


mylist . add ( "Fred" ) ; / / OK, armazena SLrings
mylist.add(new Dog( ) ) ; / / erro de compilagSo ! !

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

Stri-ng s = mylisL. get (0 ) ;

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

Com c6digo pr6-Java5, nio-gen6rico, o m6todo getDoglist ( ) seria


public Set getDogl,ist ( ) i
Set dogs = new HashSet0;
/ / c6digo para adicionar apenas Dog,s., . Cruzem os dedos. . .
return dogs; / / um Set de QUAIQUER COISA funcionar6 aqui
)

e o chamador precisaria de uma conversao:

Dog d = (Dog) getDoglistO .gret(0);

(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

Gen6ricos e C6digos Antigos


A coisa mais f6cil sobre os gen6ricos que voc6 teri de saber para o exame 6 como atualizar c6digo nio-gen6rico para
torn6-lo gen6rico. Basta adiiion"r n*iipo entre sinais de maior e menor (< >) imediatamentg ap6so dpo do
conjunto, TANTO na declaragio davai|velquanto nachamadaao construtor, incluindo qualquer l.ugar em que voc6
declare uma variivel ( isso significa argumentoi e tipos de retorno tamb6m). Um List pr6Java 5 criado p/r^ arm zerr^r
apenas lntegers:
r!I>Li ^F mi'r
rttyll>L
.i
^r - *ar.r
IIsw LrrarzT,i
dt!4J!f c{-
oL 1\
\ /
.
t
-

se torna
List<Integer> mylist = new Arraylist<lnteger> ( ) ;

uma lista criada para arm zenar apenas Strings passa de


public List changeStrings(Arraylist s) { i

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

Misturando Conjuntos Gen6ricos e Nio-Gen6ricos


E aqui que as coisas comegam a ficar interessantes... Imagine que tenhamos um Arraylist, do tipo lnteger, e o estamos
passando para um m6todo de uma classe de cujo c6digo-fonte nlo temos acesso. Ser6 que isso aqui vai funcionar?

/ / uma classe Java 5 usando um conjunto gen6rico


'imnnrf iarr: rrf i l *.

public class Testlegacy {


public static void main(String[] args) {
List<Integer> myl,ist = new Arraylist<Integer> ( )'
|
// | .^n"irlnl-^
vv.LJ
da fLfyvinn aenanifinn
esyve

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

Eis a classe antiga, nio-gen6rica, que queremos usar:


'imnnrf i:rr: rrt- i'l *.

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

public static void main(String[] arqs) {


IJist<Inteqer> mylist = new Arraylist<fnteger> ( ) -

mrrr.i cf ^AA (4\ ;


myl-ist.add(6);
Inserter in = new fnserter ( ) ;
in.insert(myl,ist); // passa List<Integer> para o c6digo antigo
]
)
class Inserter {
// m6todo com um argumento List nao-gen6rico
void insert(List list) {
list.add(new Integler(42)\; // adiciona d lista a ser recebida
)

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

oBSERVAQ6TS pene O EXAME


Ao uur conjuntot anlgos (sen tipo eEedfn)caidado comproblemas de unboxingl Se uocd declarar am conjanto ndo-gendico, o mitodo
-
get ( ) SEMPRE retomard una referlncia do tipo jaua.lang.Objut. Lznbre-se de que o uaboxing ndo i c@a7de conuerter um Objut erz
un tipoprimitiuo, nem meimt se a referincia duse Objut apontarpara am Integer (oz algun outro tipoprinitiuo) no he@. O unboxing
somente conuerte de una referincia a uma clatse wrapper (como um Integer au uru Lnng) para un tipo pinitiuo.

Mais ama coisa a se tomar cuidado com re/ag6o a anboxing

List test = new Arraylist ( );


test.add(43);
i -r
rfru i-- -- / T-r^^^-\
lfrlLs\Js!/ r^^r ^^F
Ls-L.vsL\v/ /n \ ,
t / / 6 preciso converter I !

List<Integer> test2 = new Arraylist<Integer> ( )'


test2.add(343) ;

int x2 = test2.qet(O); // a conversdo ndo 6 necess6ria


Cuidado com conuercdesfaltando em conjantos pri-Jaua 5 ndo-gendicos.

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

Pense nisso por um minuto.


Continue pensando...
Nlo, isso nlo funciona. H6 uma regra bastante simples aqui - o tipo da declaragio davari|vel precisa bater com o tipo
que vod passa ao tipo real do objeto. Se vod declarar List ( Foo ) foo, entio qualquer coisa que vod atribuir ) refer6ncia
fooDEVEserdotipogen6rico (Foo>.Nioumsubtipode (Foo).NXoumzupertiposw (Foo).Apenas (Foo).
Estes estlo errados:
List<Object> mylist = new Arraylist<JButton>O; // NAo!
List<Numlcer> numbers = new Arraylist<Integer>O; // NAOI

// lembre-se de que Integfer 6 um subtipo de Number


Mas estes esteo corretos:
List<'JButton> myl,ist = new Arraylist<JButton>O; // sLm
List<Object> mylist = new Arraylist<Object>O; / / sLm
List<Integer> mylist = new Arraylist<Tnteger>O; // sim
At6 aqui, tudo bem. E s6 manter id6nticos o tipo gen6rico da refer6ncia e o tipo gen6rico do objeto ao qual ela se
refere. Em outras palavras, o polimorfismo aqui se aplica apenas ao tipo "base'. E, por "base", queremos dizer o
pr6prio tipo da classe do conjunto - a classe que pode ser personalizada com um tipo. Neste c6digo,
List<JButton> myl,ist = new Arraylist<.TButton> ( ) ;

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

class Child extends Parent { }


public class Testpoly {
public static void main(String[] argrs) {
ParentlJ myarray = new childt3l; // sim

o que significa que ramb6m 6 permitido que voce faga isto


Object[] myArray = new'JButton[3] ; // slm
mas nio isro:
List<Object> lisL = new Arraylist<JButton>O; // NAOI

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 Dog extends Animal- {


public void checkupO { // implementa c6digo especifico de Dog
System. out.println ( "Dog checkup" ) ;

)
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

a.checkup?; // n6o importa com qual subtipo de animal o


// m6todo checkupO sobrescrito de cada Animal execute
)

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 Cat extends Animal {


public void checkupO { /,/ implementa c6digo especifico de Cat
System. out . println ( "Cat 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( ) };

AnimalDoctor doc = new AnimalDoctor ( ) ;


JAVA 5 335
doc.checkAnimals(dogs); // passa o Dog[ ]
doc.checkAnimals(cats) ; / / passa o Cat[]
doc.checkAnimals(birdsl ; / / passa o 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 ( ) ;

/ / isto funcionou quando usErmos arrays em vez de Arraylists


doc.checlrrnLnals(dogs) i // anvLa un r,iat<Dog>
doc.checklninals(cats) i ll enwi.a un r,ist<Cat>
doc.checlrAninalg (birds) ; l l enwLa un t ist<Bird>

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

doc. checkAnimals (dogs) ;

Anj-malDoctorGeneric. java : 52 : checkAnimals ( java.util.


336 Copitulo 7: Gen6ricos e Coniunlos

Arraylist.<enj-ma1>) in AnimalDoctorceneric cannot be applied


( j ava . util_ . List<Cat> )

doc. checkAnimals ( cats ) ;

AnimalDoctorGeneric . j ava: 53 : checkAnimals ( j ava. util .

Arraylist<Animaf>) ln AnimalDoctorceneric cannot be applied to


( j ava. uti1 . List<Bird>)

doc. checkAnimals (birds ) ;

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

animal-s[0] = new CatO;


animals[1] = new DogO;
Pane do beneficio de se declarar um array usando-se um supertipo mais abstrato 6 que o pr6prio array poderi
arm zen r objetos de virios subtipos do supertipo, e enteo voc6 poder6 manipular o arcal asiumindo que tudo nele
pode responder ) interface Animal (em outras palavras, tudo no array pode responder a chamadas a m6todos definidas
na classe Animal). Assim, estamos usando o polimorfismo aqui nio para o objeto paru o qual a ref.er|ncia do array
aPonta, mas sim para o q-ue o array pode de fato ARMAZENAR - neste caso, qualquer subtipo de Animal. VocO pode
Iazer o mesmo com gen€ncos:
List<Animal> animals = new Arraylist<Animal> ( ) ;

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

6 inv6lido para Arraylist, mas nio para arrays? Por que


A pergunta permanece - por que isso 6 inv6lido? E por que
nlo6possivelpassarumArraylist(Dog) aumargumentodeArraylist<Animal)?Naverdade,oproblemaE
igualmente perigoso esteja voc6 usando arrays ou um conjunto gen6rico. Ocorre apenas que o compilador e aJVM se
comportam de formas diferentes p^ra e para conjuntos gen6ricos.
^rr^ys
A razio pela qual 6 perigoso um conjunto (array ou Arraylist) de um subtipo para um m6todo que use um
passar
conjunto de um supertipo 6 que voc6 poderia adicionar alguma coisa. E isso significa que voc6 poderia adicionar a
coisa ERRADA! Isso provavelmente 6 muito 6bvio, mas, pelo sim pelo nio (e para reforgar o conceito), vamos
analisar alguns cen6rios. O primeiro 6 simples:
j^ -,^ji €^^/)
^,,Lr
PuvffL vvfu lvv\ {

Doq[] dogs = {new DoSO, new DogO};


:rlAlnim:l/d^dc\. n^-r I
\svvv, , ,// , <an nrnhla-^
----ltta,
^-_-l^
crrvf4 u^ uv:| t I nara
yqrq ^m6i-6dd

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

e o m6todo original permanece o mesmo:


public void addAnimal(Animal[] anj-mals) {
animals[0] = new Dog(); // Oh, ndol Acabamos de col-ocar um Dog
// em rrm arrav Cat!
)

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

h6 como reconhecer o desastre de se colocar um Cat em um Arraylist ( Dog )


e vice-versa (e a coisa fica exatamente
como os problemas que voc6 tem quando usa c6digo antigo, sem tipo especifico).
Assim, este, na verdade, 6 um c6digo VAtnO:
public void addAnimal (List<Animal> animals ) {
animals. add (new Dog ( ) ) ; isto 6 sempre v61ido,
uma vez que Dog pode
ser atribuido a uma refer6ncia
de Animal

public static void main(String[] argrs) {


List<Animal> animals = new Arraylist<Animal> ( ) ;
animals.add(new Dog( ) ) ;
animals.add(new DoS( ) ) ;
AnimalDoct.orGeneri-c doc = new AnimalDoctorGeneric ( ) ;
doc.addAnimal(animals); // OK, uma vez que animals bate
/ / com o arsumento do m6todo
)

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

in AnimalDoctorceneric cannot be applied to (java.util.


List<Dog> )

doc . addlnimal ( animals ) ;

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

public static void main(String[] args) {

List<Animal> animals = new Arrayl,ist<Animal> ( ) ;


animals.add(new DoS ( ) ) ;
animals.add(new Dog ( ) ) ;
Animal-DoctorGeneric doc = new AnimalDoctorGeneric ( ) ;
doc.addAnimal (animals\ ; / / passando um Animal- List
)

Agora, o que vocA disse nesta linha


public voj,d addAnimal(List<? super Dog> animals)
foi essencialmente: "Ei, compilador, por favor aceite qualquer List com um tipo gen6rico que seia do tipo Dog, ou um
supenipo de Dog. Nada mais baixo na irvore de heranga poder6 entrar, nus qualquer coisa mais alta do que Dog pode."
VocE provavelmente j6 entendeu por que isso funciona. Se voc6 passar um lista do tipo Animal, enteo 6 perfeitamente
vilido adicionar um Dog a ela. Se voc6 passar uma lista do tipo Dog, 6 perfeitamente v6lido adicionar um Dog a ela.E
se voc6 passar uma lista io tipo Object,iINDA 6vilidordii;ott"t"rr- Dog a ela. Quando usa a sinraxe <z super
. . . >, voc6 est6 dizendo ao compilador que pode aceitar o tipo que estA no hdo direito de super ou qualquer um
dos seus supertipos, umayez que - e esta 6 parte principal do que faz isso funcionar - um conjunto declarado como
qualquer supertipo de Dog seri capaz de aceitar um Dog como elemento. List < Object ) pode usar um Dog.
List < Animal )pode usar um Dog. E List ( Dog )
pode usar um Dog. Dessa forma, passar qualquer um desses ir6
funcionar. Assim, a palavra<have super na notaglo do coringa perrnite que vocA tenha umi forma restrita, mas
ainda possivel, de adicionar a um conjunro.

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.

Com base nas explicag6es anteriores, descubra se o seguinte ir6 funcionar:


imnnrf iarr: r'ri1 *.

public class testWildcards {


public static void main(String[] argrs) {
List<Integer> mylist = new Arraylist<Integer> ( ) ;

Bar bar = new BarO;


bar . dofnsert (myl,ist ) ;

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

Bar bar = new Bar ( ) ;


bar. dof nsert f mwT,i st- ! :

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

As tr6s que nio irio compilar sio


llnstrugiot:List<?> foo = new Arraylist<? extends Animal>O;
Problema: nio 6 possivel usar a notagAo com coringa na cnagio do objeto. Assim, new Arraylist<? extends
Animal> O nio compilari.
I Instrugio: List<? extends Dogr> cl,ist = new Arraylist<lnteger> ( ) ;
Problema: Nio 6 possivel atribuir uma lista de Integers a uma refer6ncia que aceita apenas um Dog (incluindo
quaisquer subtipos de Dog, 6 claro).
l lnstruglo: List<? super Animal> dT,ist = new ArraylistcDog> O;
Problema: Nlo 6 possivel atribuir um Dog a <? super Animal>. O Dog est6'baixo" demais na hierarquia da
classe. Somente ( Animal ) ou ( Obiect ) teriam sido vilidos.
342 Copitulo 7: Gen6ricos e Coniuntos

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

Criando a sua Pr6pria Classe Gen6rica


Vamos tentar criar a nossa pr6pria classe gen6rica, para termos uma ideia de como isso funciona, e depois veremos
alguns detalhes remanesceftes sobre a sint"axe dos-gen6ricos. Imagine que algu6m tenha criado.r-".f".r. Rental
('aluguel'), que gerencia um pool de itens que podem ser alugados.
public class Rental {
nri rral- a T. i qi- rant-a l Dnn l .

private int maxNum,.


public Rental(int ma><IrTum, List rentalPool) {
this.maxNum = maxNumi
this. rentalPool = rentalPool ;

)
nrrhlin Ol-!iadt-
vvJ ev u aal-Ponl-al
yeur\srf uq! /\
\ /
It

// bloqueia at6 que haja algo disponivel


return rentalPool.Set (0) ;
]
public void returnRental(Object o) {
rentalpool . add (o) ;
]
)

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

System. out.println ( ..Cannot add a non-Car,, ) ;


/ / provavelmente langa uma exceqao
)))
Mas quanto mais vocA olha, mais vocA percebe que:
1. Voc6 ex6fazendo pr6pria verificagio de tipo no m6todo returnRental ( ) . Nio 6 possivel modificar o tipo
a sua
do arg-umento de returnRental ( ) para usar um Car, uma vez que se trara de uma sobrescrigio (e nio uma -
sobrecarga) do m6todo & classe Rental. (Sobrecarregar acabaria com a sua flexibilidade polim6rfica com Rental).
2. VocA realmente nio quer criar zubclasses separadas para cada tipo possivel de coisas que podem ser alugadas
(carros, computadores, sapatos de boliche,iriangas, e assim por diante).
Mas com a sua intelig6ncia natural (aumentada por este cenirio complicado), vocA rapidamente percebe que pode
criar a classe Rental como um tipo gen6rico - um modelo para qudquer tipo de coisJque pode Jer aluga& -i irto
resolve o seu problema.
(N6s dissemos complicado... Uma vez que, na realidade, voc6 poderia muito bem querer ter diferentes
comPortamentos para diferentes tipos de coisas que podem ser alugadas, mas at6 mesmo isso poderia ser resolvido de
forma mais limpa atrav6sde algum tipo d.e composigio de componamento, em vez de com a [eranga (usando-se o
padrio de projetos Estrat6gia, por exemplo). E nio, os padr6es de projetos nio caem no exame, mas ainda assim
achamos que vocA deveria ler o nosso livro sobre padr6es de projetos). Assim, aqui est6 a sua nova e aprimorada classe
gen6rica Rental:

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;

this. rentalPool = rentalPool ;

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

Vamos testar esse c6digo:


class TestRental {
public static void main (String[] args) t
/ /cria alguns Cars para o Pool
Car c1 = new CarO;
Car c2 = new CarO;
List<Car> carlist = new Arraylist<Car> ( ) ;
carlist . add ( c1 ) ;
carlist . add ( c2 ) ;
Rentalceneric<Car> carRental = new
Rentalceneric<Car> (2, carlist) ;
/ / reLira agora um car, e ndo serd necess6rio converter
Car carToRent = carRental.getRentalO ;
carRental . returnRental ( carToRent ) ,'
/ / ser6. que podemos colocar alguma outra coisa na carlist original?
carlist. add (new Cat ( "Fluffy" ));

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

TestGenerics (T anlnstance) { / / rama lln f in^ do


ue
:rrrrmanl-n
qrY4rrelrev

this. anlnstance = anlnstancei


)

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; }

/ / faz um teste, criando com <String, Integer>

public static void main (String[] arg.s) {


UseT\do<String, Tnteger> twos =

new UseTwo<String, Integer> ( "foo" , 42) ;


Strino theT = ft^roq acf.F/I. / / ralnrna rrma efrih-

int thex = twos.getx(l; // reLorna Integrer, faz unboxing para um intt


1

!_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
)

Criando M6todos Gen6ricos


At6 agora, todos os exemplos que vimos usam o tipo de parametro da classe - o tipo declarado com o nome da classe.
fo.1 exemplg, na declaraglo UsiTwo < T,X ), n6i *r-br os marcadores T e X em todo o c6digo. Mas 6 possivel
definir um tipo parametrizado emum nivel mais detalhado - o do m6todo.
Imagine que voc6.queira criar_um m6t9do que use uma instAncia de qualquer tipo, instancie um Arraylist desse tipo e
adrcione a rn$ancia ao Arraylist. A classe em si nXo precisa ser gen6rica; basicamente, n6s queremos apenas um
m6todo u!4it6rio ao qual possamos passar um tipo e que seja capaz de usar esse tipo para construir um 6onjunto com
tipo especifico. Usando um m6todo-gen6rico, pod.-os declarai o m6todo ,.- r"r- tipo especifico e depoiJobter a
-
informagio do tipo com base no tipo do objeto passado ao m6todo. Por exemplo:
imnnrl-
-*"*.*-**.
i:rz: rrli l *
;
public class CreateAnArraylist {
public <T> void makeArraylist(T t) t / / Loma um objeto de umn
I / |-ipo desconhecido e usa um
nFrA ranfaqanl-ar r n
v finn
Lrvv

-trl-st<'I'> -L f sE. = new Arrayl,ist<T> ( ); / / agora podemos criar o

/ / l.ist usando "T"


list.add(t);
346 Copitulo 7: Gen6ricos e Coniuntos

No c6digo.acima, se voc6 chamasse o m6todo makeArraylist ( ) com uma instAncia de Dp& o


/n6todo se

componaria como se tivesse tido esta aparAncia o tempo todo:


public void makeArraylist(Dog t) {
List<Dog> list = new Arraylist<Dog> ( );
list.add(t);
)

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)

oBSERVAQ6E,S pene o EXAME


E tentador uquuer qse o argumentt do nhodo NAO eshi onde aocd declaroa a uariduel de pardwetro de tipo T. Para usar ama aaiduel de

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,

public void makelist(r t) { }

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:

public class Radio {


public <T> Radio(T t) { } // construtor v61ido
]
Se uocd KEALMENTE qaerfaryr algo absrdo (ou nr despedido), pode declarar uma clasv com um ttlme que s/a o meimo do marcador do
pardmetro do tipo:

class x { public <X> X(X x) t } }

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

mitodos geniicos. Este aidigo ndo i u,llido:


public class NunberHolder<?> { z atlum; } // NAOI

Mas se uocl sub$ituir o <?> por am identifcador a,ilido, tudo bem:

public class NumberHolder<T> { T aNum; } // Sim


98o/o detudo o que voc6 provavelmente fari com os gen6ricos 6 simplesmente declarar e usar coniuntos com tiPo
especificado, inituindo usilos (e pass6-los) como argumentos. Mas agora voc6 sabe muito mais (por6m, de forma
alguma tudo) sobre a maneira como os gen6ricos funcionam.
JAVA 5 347
Se esse assunto ficou claro e filctl paravocA, excelente. Se foi... Complicado, saiba que a adigio dos gen6ricos i
Fg""F:* J"yt chegou perto de cansat .tm" revolta entre alguns doi desenvolvedoies Java mais exp"erientes. A maioria
dos criticos simplesmente estava descontente com a complexidade, ou nio estava convencida de que o beneficio de se
ter coniuntos com tipos especificados.
" :*l
pena pelos milhares de regrinhas que voc6 tem de decorar agora. E
que, go.mlava 5, ficou mais dificil p5nder a linguagem. Mas icredite em n6s... Nunca vimos niigudm levar
".tF*
mais do que dois dias para entender os gen6ricos. Isso sio s6 48 horas consecutivas.

Resumo para a certificagio


N6s comegamos com uma breve revisio do m6todo toString ( ) . O m6todo toString0 ser6 chamado
automaticamente quando voc6 solicitar a system. out . println ( ) que exiba um objeto - voc6 o sobrescreve
parafaz{lo retornar uma String de dados significativos a respeito dos seus^objetos.
a finalidade do operador_ = :_(saber se duas vari6veis de referAncia apontam para o mesmo
4 :.gYit, ryvislmop
gbjtt.) e do m6todo equals ( ) (siber se dois objetos sio tignrfcatiuanmte eqriaahtet). VocA conheceu a dewantagem
de nio sobrescrever equals ( ) - pode n5o ser possivel enconirar o objetoem um conjunto. Discutimos.r* poi.t o
como escrever um m6todo equals ( ) adequado - nio esquega de usar instanceof e referenciar os atrib-utos
significativos do objeto. Revisamos os conrratos de sobrescr(io de eguals ( ) e hashCode ( ) . Conhecemos a
teoria existente por tris dos c6digos de. ha;higg.e a difgre.lgg entre c6digos de hashing v6lidos, apropriados e eficientes.
Tamb6m vimos que mesmo sendo muito ineficiente, 6 v6lido que um m6todo hashCode ( ) sempre rerorne o
mesmo valor.
A seguir passamos para os conjuntos, momento em que conhecemos os conjuntos Iist, Set e Map, e vimos a diferenga
entre conjuntos ordenados e classificados. Aprendemos os atributos principais das classes comuns de conjuntos, e-
quando us6-los.
Abordamos os detalhes sobre as classes Collections e Arrays: como classificar e como procurar nelas. Aprendemos
sobre como converter arrays em Lists e de volta para affays.
Finalmente, nos dedicamos aos gen6ricos. Os gen6ricos lhe permitem forgar a segrranga de tipos, em tempo &
compilagXo, para conjuntos ou outras classes. Os gen6ricos aju&m agararnir que, quando voi6 receber um item de
uma colegio, ele ser6.do tipo que voc6 espera, sem que seja necessirianenhuml conversio. VocA pode misturar
c6digo antigo com c6digo que usa gen6ricos, mas isso pode causar exceg6es. As regras para o polimorfismo mudam
g.ulndo voc6_ usa os gen6ricos, apesar de que, usando coringas, voc6 ainda pode criar conjuntos polim6rficos. Algumas
declarag6es de gen6ricos permitem a leitura a panir de umionjunto, mas nio permitem a attahzagio do conjunio.

Enfim, foi um capitulo muito interessante.

Exercicios ripidos
Aqui estio alguns dos pontos principais do Capitulo 7.

Sobrescrevendo hashCode( ) e equals( ) (Objetivo 6.2)


O equals( ),hashCode( ) e tostring( ) siopriblicos(finalize( ) 6protegido).
E Sobrescreva toString ( ) para que System. out . println ( ) ou ouuos m6todos possam obter algo 6til, como
o estado de szu objeto.

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 sobrescrever equals ( ), compare os atributos significativos dos objetos.


D equals ( ) que foram realgados:
Aspectos do contrato de
JE 4t"xln:,x. equals (x) 6 verdadeiro.
QEtir&rico:sex.equals(y) forverdadeiro,y.equals(x) tamb6mter6queserverdadeiro.
QEtanitiuo:sex.equals(v) ey.equals(z) foremtrue, z.equals(x) tamb6mser6.
}fr, cotttisterte v6rias chamadas a x. equals (y) retornario o mesmo resultado.
348 Copitulo 7: Gen6ricos e Coniuntos

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:

D E consistente: virias chamadas a x. hashCode (y) retornarAo o mesmo inteiro'

E x. equals (y) for true, x.hashCode ( ) == y.hashCod.e ( ) deve ser true


Se

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

Conjuntos (Objetivo 6.1)


E As atividades comuns dos conjuntos incluem a insergio e a remoElo de objetos, a verificagio de objetos incluidos, a
recuperagXo dos mesmos e a iteragio.

D TrAs significados para "conjunto":


E conjunto - representa a estrutura de dados na qual objetos sio armazenados;

D Collection - java.util.Collection - Interface estendida por Set e List;


E Collections - uma classe que
^rmazen
m6todos utilit6rios esteticos de conjuntos.

E As quatro uersdesbasicx dos conjuntos sio as L)stas, Conluntos, MEar e Filas:


E Listas de itens: Ordenada, repetigio perruitida, comum indice,

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 Filas de itens a serem processados: Ordenados por FIFO ou Por prioridade.


E As quatro subvers6es bisicas dos conjuntos sio: classficada, ndo- clarifcada, ordenada e ndo-ordenada.

D Ordenado significa a iteragio em um conjunto, obedecendo a uma ordem especifica nio-aleat6ria.


D Classificado significa aiteragio em um conjunto, obedecendo uma ordem classficada estabelecida.

E A classificagio pode ser alfab6tica, num6rica ou definida pelo programador.

Atributos principais das classes comuns de coniuntos (Obietivo 6.1)


[J Arraylist: iteragio e acesso aleat6rio r6pidos;
fl Vector: Como um Arraylist um pouco mais lento, principalmente devido a seus m6todos sincronizados;
O Linkedlist Adequado para ainsergilo de elementos ao final, ou seja, para pilhas e filas;
E HashSet: Assegura a nio existAncia de duplicatas, nio fornece ordenamento;
tr LinkedFlashSet: Sem duplicatas; iterapor ordem de insergio;
D TreeSet: Sem duplicatas; itera na ordem classificada;
E HashMap: atualizag6es mais ripidas (pares-chave/valor); permite uma chave nul1 e muitos valores nu1l;
E Hashtable: Como um HashMap mais lento (semelhante a Vector, devido a seus m6todos sincronizados). Nenhum
valor ou chave nu11 6 permitido;
E LinkedHashMap: iterag6es mais r6pidas; itera por ordem de insergio ou de rtltimo item acessado, permite uma
chave nu1I e muitos valores nul1;

E TreeMap: Um mapa classificado.


tr PriorityQueue: IJma lista de coisas a f.azer ordenada pela prioridade dos elementos.
JAVA 5 349
Usando Classes de Conjuntos (Objetivo 6.3)
E Os conjuntos s6 podem armazanar Objects, mas tipos primitivos podem ser usados com autoboxing.
D Faga iterag6es com o loop for aprimorado, ou com um Iterator via hasNext o & next ( ).
D hasNext ( ) determina se existem mais elementos; o Iterator nao se move.
E next ) retorna o elemenro seguinte r move o Iterator adiante.
(

E Para funcionarem corretamente, as chaves de um Map devem sobrescrever eguals ( ) e hashcode ( ) .


tr As filas usam of fer.( ) paraadicionar um elemento, poll ( ) para remover o primeiro item da fila, e peek ()
para ver o primeiro item da fila.

Classificando e vasculhando arrays e listas (Objetivo 6.5)


D A classificagio pode ser feita na ordem natural, ou arrav6s de um Comparable ou de virios Comparators.
E Implemente Comparable usando compareTo ( ); fornece apenas uma ordem de classificagio.
E Crie v6rios Comparators para classi{icar uma classe de v6rias formas; implemente compare ( ) .
D Para um List ser classificado e vasculhado, os seus elementos devem ser compar6veis.

0 Para ser vasculhado, um array ou List deve ser classificado primeiro.

Classes Utilit6rias: Collections e arrays (Objetivo 6.5)


tr Ambas essas classes de java.util fornecem
tr Um m6todo sort ( ). classifica usando um comparator ou usando a ordem natural
D Um m6todo binarySearch ( ). Busca em um aftay oul-ist prdclassificado.
D Arrays aslist ) cria um List a parrir de um array e vincula um ao outro.
. (

U Collections. reverse ( ) inverre a ordem dos elementos de um List.


E Colf ections. reverseorder ( ) retorna um Comparator que classifica ao contririo.
E Lists e Sets tAm um m6todo toArray ( ) para criar arrays.

Gen6ricos (Objetivo 6.4)


E Os gen6ricos lhe permitem forgar a seguranga de tipos, em tempo de compilagio, par4 conjuntos (ou outras classes
e m6todos declarados usando-se parAmetros de tipos gen6ricos).

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

List list = new Arraylist ( ) ;


/ / mais c6dioo
uLtrrre
cts-.I -^
-^ -- -rr-i=a.get(0); // ndo6 preciso converter
String s = (String)list.get'(0) ; // convers6o obrigat6ria
tr Voc6 pode passar um conjunto gen6rico para um m6todo que use um conjunto nio-gen6rico, mas os resultados
podep ser desastrosos. O compilador.nXo poderi impedirque o m6todo insira o tipo errado no conjunto
anteriormente seguro em relagio ao tipo.
D Se o compilador colseguir reconhecer que um c6digo de tipo inseguro esti potencialmenre colocando em perigo
algo que voc6 originalmente declarou como de_dposeguro, voc6 riceber6 um aviso do compilador. Por eiemplo,
se passar um List ( String ) para um m6todo declarado como

void foo(List al,ist) { al,ist.add(anlnreger),. }


o compilador emitiri um aviso, porque o m6todo add ( ) 6 potencialmente uma "operagio insegura".
I Lembre-se de que "compila sem erros" nio 6 o mesmo que "compila sem avisos". No exame, um aviso de
compilagio nio 6 considerado como erro ou falha de compilagio.
tr A informagio de tipos gen6ricos nXo existe no tempo de execudo - ela s5 existe para a seguranp em tempo de
compila$o. Misturar gen6ricos com c6digo antigo pode criar um c6digo compilado que poder6 langar uma exce$o no
tempo de exean$o.
350 Copitulo 7: Gen6ricos e Coniunlos

D As atribuig6es polim6rficas aplicam-se somente ao tipo-base, e nio ao parAmetro de tipo gen6rico. Voc6 pode usar

List<Animal> alist = new ArraylisL<Animal>O; / / sim


Mas nio
List<Animal> al,ist, = new ArraylistcDoS>O; // n6'o

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:

public <T> void makelist(T t) { }


T como o tipo de retorno. Esse m6todo tem um tipo & retorno void, mas para usar T dentro do
ndo estivsando
argumento do m6todo voc6 deve declarar o < T ) , o que acontece antes do tipo de retorno.

Teste individual

l. Dado:
import java.util.*;
class Test {
public static void main(String[] args) {

/ / :.'nsira o c6digo aqui


x.add("one";;
x.add("Lwo"1;
x.add("TWO");
System.out,println(x.poll O);
)
JAVA 5 35I
)

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

for (int j = 0; j <= 10; j++)


row.add(i * j);
table.add(row) i
)
for (List<Integer> row : table)
q\t<l-am nrinl- ln Irnt^rl .
^rri- rr\.vYf /,

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

C.list<l,ist<Integer>> table = new Arraylist<Arraylist<Integer>> ( ) ;


D.f,ist<f,ist, Inteqer> tabl-e = new List<List, Integer>O;
E.List<List, Integer> table = new Arraylist<List, Integer>O;
F.list<l,ist, fnteger> table = new Arraylist<Arraylist, Integer>O t
G. Nenhuma da" anteriores.

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

x.add(" x") ; x.add("xx") ; x.add(*Xx") ;


/ / insira o c6digo aqui
for(String s: x) System.out.printfn(s) ;

))
E a saida:

xx
Xx
x
Qual c6digo, inserido em / / insira o c6digo aqu j., produziri a suda acima? $4arque todas as corretas)

A. CoLlections. sort (x) ;


B. Comparable c = Collections.reverseO ;

ColLections. sort (x, c) ;

C. Comparator c = Collections.reverseO ,'

Collections. sort (x, c) ;


D. Comparabl-e c = Coflections.reverseOrderO ;

Collections. sort (x, c) ;

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 ;

1,2 . q. add ( "Veronica" ) ;


13. q.add("Wa1lace");
14. q.add("Duncan");
15. showAll (q) ;
16. ]
L1 .

18. public static void showAll (Queue q) {

19. q.add(new Integer(42]']r;


20 . while ( lq. isElmpty O )
2L. System.out.print(q.removeO + " ");
22. ]
Qual 6 o resultado?
A. Veronica Wallace Duncan
B.Veronica Wallace Duncan 42

C. Duncan Wafface Veronica


D.42 ouncan Wallace Veronica
E. A compilagio falha.
F. Ocorre uma excegio em tempo de execugio.

6. Dado:
public static void before ( ) {

Set set = new TreeSet ( ) ;


set. add ("2" );
set.add(3);
JAVA 5 353
set.add("1");
Iterator it = set. iterator ( ) ;

while (it.hasNextO )
Svstem 6lll- nrinj- lif navl-
.rfvr:u l\
\ /
+ \\ $.|.
I I I

Quais das seguintes afirmativas sio verdadeiras?


A. O m6todo before O exibir|12
B. O m6todo before <l exjbiritZl

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; }

Quais afirmativas estio corretas? (Marque todas as correks)


A. Como est6, o c6digo nio compilar6.
B. Como est6, o c6digo produit|asuda2.
C. Como est6, o c6digo produrzir|asarda3.
D. Se o m6todo hashCode ( ) for ativado, retirando-se o / /, a saida seri 2.
E. Se o m6todo hashCode ( ) for ativado, retirando-se o / /, asaidaser63.
F. Se o m6todo hashCode ( ) for ativado, retirando-se o / /, o c6digo nio compilari.

8. Dado:
12. public class AccountManager {
13. private Map accountTotals = new HashMap0;
14. private int retirementFund;
15.
354 Copftulo 7: Gen|ricos e Coniuntos

16. public int getBalance(Strj-ng accountName) {


L7. Integer total = (Integer) accountTotals.qet(accountName);
18. if (totaI == nul1)
L9. total = Integer.valueof (0) ;
20, ret.urn total-. intValue ( ) ;
2L. )

23' public void setBalance(string accounLName' int amount) t


24. accountTotals.put(accountName, Tnteger.valueOf(amount) );

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

D. Substituir CI linhas l7-20por


int tot.al = accountTotals.get (accountName) t

if (total == null)
total = 0;
return total;
E. Substituir as linhas 17-20 por

Integer t.ot.a1 = accountTotals.gret (accountName) i


if (total == nu1I)
t.otal = 0;
return total;
F. Substituir as linhas 17-20 por
return accountTotals. get (accountName) ;

G. Substituir alinha 24 por


accountTotals.put (accountName, amount) ;

H. Substituir alhrha 24 por


accountTotals.puL (accounLName, amounL. intValue ( ));

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) {}
)

class Wolf extends Animal implements Carnivore<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> {}

B. Modificar a interface Herbivore para


interface Herbivore<E extends Animal> extends Hungry<E> {}
C. Modificar a classe Sheep para
class Sheep extends Animal implements Herbivore<Plant> {

public void munch(Grass x) {}


i
D. Modificar a classe Sheep para

class Sheep extends Plant implements Carnivore<Wolf> {


public void munch(Wolf x) {}
]
E. Modificar a classe Volf para
class Wolf extends Animal implements Herbivoreccrass> {
public void munch(Grass x) {}
)
F. Nio 6 necess6rio fazer nenhuma modificaglo.

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

public static void main(String[] args) {

Group g = new GrouPO;


g. add(new Person( "Hans" ) ) ;
g.add(new Person ( "Lotte" ) ) ;
g.add(new Person( "Jane" ) ) ;
g. add (new Person ( "Hans " ) ) ,'
g. add (new Person ( ".Tane" ) ) ;
System.out.println("Total-: " + g.sizeO ) ;

)
nrrhl
y$ry4+!
in hnnlaan :AAfohiont- nt t

System.out.println("Adding: " + o),'


return super.add(o);
)

]
nla<q Parcnn {

nri rrafo fi na l Cl-ri nd hana.

public Person(String name) { this.name = name; }

public String toStringO { return name; }


]
Quais das seguintes coisas ocorrem pelo menos uma vez quando o c6digo 6 compilado e executado? M*q* todas as
corretas)

A.Adding Hans
B.addingr Lotte
C. Adding ,fane
D. total: 3

E. total: 5

F. O c6digo nio compila.


n 4r ^ r
G. E langada uma excegeo no tempo de execugio.

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

14. Dado que String implementa java.lang.CharSequence, e:


import java.util.*;
public cLass LongWordFinder {
public static void main(String[] args) {
StrinslJ array = { "123", "72345678",
ListcString> list = Arrays. aslist (array) ;
Collection<String> resultlist = getlongwords (1ist) ;

// INSTRA A DECLARACAO AQUT

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 )

B.publj-c static <E extends CharSequence> List<E>


getlongwords (CollectioncE> co11 )
C. public st.atic Collection<E extends CharSequence>
getlongwords ( Col- lection<E> coll_ )
D. public static List<Charsequence>
getlongwords ( Col I ect ion<CharSequence> co 1 1 )
E.public static List<? extends CharSequence>
getlongwords (Collection<? extends CharSequence> co11)
F. st.atic public <E extends CharSequence> Collection<E>
getlongwords (Collection<E> co11 )
G, static public <E super CharSequence> Collection<E>
getlongwords (Collection<E> co11 )

15. Dado o c6digo a seguir,


12. Treeset map = new Treeset ( ) ;
13. map.add("one");
14. map.add("two");
15. map.add("three");
16. map.add("four");
17. map.add("one");
18. Iterator it = map.iteratorO;
19. while (it.hasNext() ) t
358 Copftulo 7: Gen6ricos e Con juntos

20. System.out.print( it.next0 + " " );

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.

| 6. Dado um m6todo declarado como:


public static <E extends Nudber> List<? super E> process(List<E> nums)
Um programador deseja usar esse m6todo da seguinte forma:
// INSIRA AS DECLARAqOES AQUT

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;

ListcNumber> output = nu11,'


D,f,istctrtumber> input = null;
Arraylistcrnteger> output = nu11;
E.r,ist<Number> input = nu1l;
List<Number> output = nu11;
F.listcrnteger> input = nu11;
List<Integer> output = nul1;
G. Nenhuma das anteriores.

Respostas do teste individual


1. D e Festio corretas. O m6todopoll Oassocia-se comQueues. AclasseLinkedlistimplementaainterface
Queue.
nXo implementa Queue, e o instanciamento polim6rfico restringiria x a
A esti incorreta porque a interface List
chamar apenas os m6todos declarados na interface List. B, C e E estio incorretas com base no exposto acima.
(Objaivo6.3)
2. B est6 correta.
A est6 incorreta porque List 6 uma interface, de modo que vocd nio pode usar new List ( ) independentemente
de quaisquer tipos gen6ricos. D, E e F estio incorretas porque List s6 usa um parimetro & tipo (um Map usaria dois,
e nio um List). C |tentadora, mas incorreta. O argumento do tipo <List<rnteger>> deve ser o mesmo para os
dois lados da atribuigio, embora o construtor new Arraylist ( ) do lador direito seja um subtipo do tipo
declarado de List i esquerda. (Objetivo 6.4)
JAVA 5 359
3. B e D. A resposta B 6 verdadeira porclue, freqiientemente, dois objetos diferentes podem retornar o mesmo valor
paraoc6digodehashing. D6verdadeiraporquese acomparagiodehashCode( ) retornar: :, osdois
objetos podem ou nio ser iguais.

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.

A, C, D, E e F estio incorretas com base no exposto acima. (Objetivo 6.3)

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.

A, B, C e D estlo incorretas com base no exposto acima. (Objetivo 6.5)


7. CeDestiocorretas.SehashCodeO nioforsobrescrito,entaocadaentradair|paraoseupr6priodep6sito,eo
m6todo sobrescrito equals ( ) nlo ter6 efeito no que diz respeito a determinar a equivalAncia. Se
hashCode () for sobrescrito, entio o m6todo equals ( ) sobrescrito veri t1 e t2 como duplicatas.

A, B, E e F estio incorretas com base no exposto acima. (Objetivo 6.2)


8. B. E e G estio corretas.
A esti errada porque voc€ nlo pode usar um tipo primitivo como parAmetro de tipo. C est6 errada porque um
Map usa dois parAmetros de tipo separados por uma virgula. D esti errada porque um int nio pode fazer
autoboxing para um nu1 1, e F est6 errada porque um nu1 1 nio pode ser desencapsulado para um 0. H est6
errada porque voc6 nio pode fazer autoboxing de um tipo primitivo apenas tentando chamar um m6todo com ele.
(Objetivo 6.4)
9. G esti correta. Se uma correspond6ncia for encontrada, binarySearch ( )retornar6 o indice do elemento da
corresponddncia. Se nio for encontrada, binarySearch ( ) retornar6 um nrimero negativo que, se invertido e
depois diminuido, lhe informa o ponto de inserEio (indice do array) no qual o valor buscado deveri ser inserido
no array para que a classificagio apropriada seja mantida.
A, B, C, D, E, F e H estio incorretas com base no exposto acima. (Objetivo 6.5)

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

A, B, C, D, E e G estio incorretas com base no exposto acima. (Ob.ietivo 6.4)


13. A, B e G sio obrigat6rias. O m6todo asl,ist O converte um array em um List. Voc6 pode encontrar o indice de
um elemento de um List com o m6todo binarySearch ( ) , mas, antes de fazcr isso, voc6 deve classificar a lista
usando sort ( ).
F est6 incorreta porque contains ( ) retorna um booleano, e nio um indice. C, D e E estio incorretas porque
esses m6todos nio estao definidos na interface List. (Objetivo 6.5)

14. F esti correta.


A chega perto, mas esti errada porque o valor de retorno 6 vago demais. A rlltima linha do m6todo espera que o
valorderetornoseiaCollectioncstring>,enioCollection<? extends CharSequence>.Best6
errada porque longWords foi declarado como Collection<E>, e isso nio pode ser implicitamente convertido
em um List.<E> para bater com o valor de retorno declarado. @mbora n6s saibamos que longwords na
verdade 6 um ArraylistcE>, o compilador s6 tem conhecimento daquilo que foi declarado) C, D e E estio
erradas porque nio declaram uma variivel de tipo E (nio hi nenhum < > antes do valor de retorno), de modo que
o corpo do m6todo getlongwords ( ) nio vai compilar. G est6 errada porque E super CharSequence nlo
faz sentido
- super poderia ser usada em conjunto com um coringa, mas nio com uma vari|vel de tipo como E.
(Objeaivo6.3)
15. D est6 correta. TreeSet assegura entradas sem repedgeo; al6m disso, se acessado, retomari elementos na ordem
natural, o que para Strings ignrfca afabdtica.

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

I Closses inlernos locois de m6todos

I Closses internos on6nimos

I Closses estdlicos oninhodos

a/ Exercicios rdpidos

P&R Teste individuol


362 Copitulo B: Closses internos
A classesinternas (incluindo as classes est6ticas aninhadas) aparecerio em todo o exame. Emboranio hajaobietivos
oficiais do exame eipecificamente sobre classes internas, o Objetivo 1.1 inclui classes internas (tamb6m conhecidas como
aninhadas). O mars rmporranre e que o codigo usado para representar perguntas sobre qaal7aert6pico no exame pode
envolver classes internas. A menoJque vocA iompreenda detalhadamente as regras e a sintaxe delas, 6 provivel que erre
perguntas que poderia responder corretamente. Como seji ndo bastasse o exame ar tdo dffcil.
Este capitulo examinar6 asvantagens desvantagens (pr6s e contras) das classes internas e o colocar|frenteaexemplos com
e
os tipoi de sintaxe (geralmente de"apar6ncia.rtrirha)]ot qoais vocA ver6 no decorrer de todo o exame. Portanto' na
verdade,voc|ter6 dbis objetivos neste capitulo: aprender o necess6rio para responder as perguntas que avaliarem seu
conhecimento sobre classes internas, e aprender iomo ler e entender os c6digos de classes internas para que possa
acompanhar corretamente o fluxo de perguntas que testarem seu conhecimento em outros tdpicos.
Entio, por que todo o espalhafato relacionado is classes internas? Antes de entramos no assunto, temos que lhe avisar (se
voc6 ji nio souber) que as classes internas tOm gerado debates apaixonados do tipo amor e 6dio desde que foram
introduzidas na nerslo linguagem. Pelo menos dessa vez, tentaremos ser reseryados em nossas opini6es e apenas
1.1 da
apresenraremos os fatos & maoeita q.te voc6 precisari
para o exame. Ficar6 sob sua responsabilidade decidir como - e at6
q.t. ponto - deve us6-las em seu pr6prio desenvolvimento. E s6rio. Nem mesmo o toirr q.t. .ts"r-os revelar6 o que
Jchamos realmente delas certo, c&o, vamos dizer entio! Achamos que elas tAm alguns empregos poderosos e eficientes
-
em siruag6es muito especificas, incluindo c6digos que sejam mais f6ceiJde ler e de manutengio simples, mas tamb6m
podem ser usadas de maneira excessiva e levar a um c6digo tlo claro quanto um labirinto em um milharal, gerando a
sindrome conhecida como "impossivel de ser reutilizado"... Cridigos que senrpre sio infiteis.

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

I Classes internas an6nimas


I Classes estiticas aninhadas

Obietivo poro o certificog6o

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.

Codificando uma classe interna "comum"


IJsamos o termo comilmpararepresentar classes internas que niosejam:

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 { }

Muito f6cil. E se voc6 compilar isso,

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;

// definisSo da cfasse interna


class Mylnner {
public void seeOuter() t
364 Cooitulo B: Clqsses internos

System.ou!.grintln(r'Out,er x is " +:{)i


)
I / / fecha a definiQdo da classe interna
j // fecha aclasseexterna
O c6digo anterior perfeitamente vilido. Observe que a classe interna est6 realmente acessando um membro privado da
6
classe externa. Issoesti correto, porque a classe interna tamb6m 6 um membro da classe externa. Portanto, exatamente como
qualquer membro da classe externa (digamos, um m6todo de instAncia) pode acessar algum outro membro dela, privado
ou nio, a classe interna - que tamb6m 6 um membro - pode fazer o mesmo.
Ceno, portanto, agora que sabemos como escrever um c6digo que conceda i classe interna acesso a membros da classe
externa, como o usaremos?

Instanciando uma classe interna


Para instanciar uma classe interna, uocdprecisa ter una instdncia da clasrc e^"terna que possa ser associada a ela. Nio hi exceg6es a
essa regra; uma instAncia de classe interna nunca pode existir individualmente sem um relacionamento direto com uma
instAncia especifica da classe externa.

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 {

Mylnner j-n = new Mylnner ( ) ; / / cria uma instdncia interna


in caaOrrt-or1\ -

a l a << Mr;Tnnar I

public void seeOuter ( ) {


System.out.println("Outer x is " + x) ;

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\, \ ,.

lllouter.Mylnner inner = mo.new ltylnner()t


inner. seeOuter ( ) ;

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 mo = new Myouter1; // vai comegar uma instAnciat


I,Eouter.Mylilrer inner = ttro.new lrDrfnner ( ) t
anner-seeolrfer()
]
Voc6 pode considerar essa situagio como se estivesse chamando um m6todo na instAncia externa que, por acaso, fosse um
m6todo de instanciagio especial da classe interna chamado com o uso da palavra-chave ner. e insttcilgio de uma classe
interna 6 o ilnico cen6r.io no qual vocA chamar6 new emumainstincia, e nio para conshairvmainstAncia.
Aqui est6 um resumo ripido das. diferengas entre um c6digo de instanciaglo de classe interna que estej a dzntv da classe
externa (por6m, sem ser est6tico) e um qu e ex€lafora daclasse externa:
I De dentro do c6digo da instAncia da classe externa, use o nome da classe interna normalmente:
public stat.ic void main (String[] args) {
MyOuter.Mylnner inner = new MyOuterO.new MylnnerO;
inner.scootrfArl)'
)
r De fora do c6digo dainstAncia da classe externa (incluindo o c6digo do m6todo est6tico da classe externa), o nome da
classe interna agora deve incluir o da classe externa

MyOuter. Myfnner
e para instanciar, vocA precisa usar uma referAncia i classe externa,

new MyOuter( ) .new Mylnner( ); ou outerobjRef.new Uylnner( );


se i6 tiver uma instAncia dela.

Referenciando a instAncia interna ou externa de dentro da classe interna


Como um objeto re{erenciari a ele pr6prio normalmente? Usando a referdncia this. Revisio ripida de this:
r A palavra-chave this pode ser usada dentro do c6digo da instAncia. Melhor dizendo, nio pode ser usada dentro do
c6digo static.
r A referAncia this apontariparao objeto que estiver sendo executado no momento. Em outras palavras, o objeto cuja
refer6ncia foi usadapara chamar o m6todo que estiver sendo executado.

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 {

Mycl-ass mc = new MyClass O ;

mc.doStuff(this); // passa uma refer6ncia ao objeto executando myMethod


]
Dentro de um c6digo de classe interna, a referlncia thi s apontari para a instAncia da classe, como era de se esperar, j6 que
this sempre referencia o objeto que est6 sendo executado. Por6m, e se o c6digo da classe interna precisar de uma referdncii
explicita i instAncia da classe externa a qual a instAncia interna estiver associada? Em outras palivras , nmo uoc6 nimti am
ponteiropara a "ryfer€ncia Lhis extema"?Embora normalmente o c6digo da classe interna nio precise de uma refer6ncia i
classe externa, porque j6 ter6 uma implicita que estar6 usando para acessar os membros dessa classe, pode precisar da
referAncia se tiver que pass6-la para algum outro c6digo como vemos a seguir:
nl:cc MrzTnnor I

public void seeouter ( ) t


System.out.printlp(\tQqter x is " + x) ;
System.out.println("fnner class ref is " + this);
System. out.printl-n (\Outer cl-ass ref is \\ + Myouter. this) ;
366 Copitulo B: Closses inlernos

Se executarmos o c6digo completo como 6 feito abaixo:

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

Obietivo poro o certificoe6o


Classes internas locais de m6todo
O escopo de uma classe interna comum se encontra dentro das chaves de outra classe, por6m, fora do c6digo de qualquer
m6todo (em outras palavras, no mesmo nivel que uma variivel de instAncia 6 declarada). Ainda assim, voc6 tamb6m pode
delinir uma classe interna dentro de um m6todo:

cl-ass Myouter2 {

private String x = "outer2";


JAVA 5 367
void doStuff O {
cfass Mylnner {
public voj_d seeOuter ( ) {
System.out.println("Outer x is " + x);
j / / fecha o m6todo da cfasse interna
j / / fecha a definiqdo da classe interna
\ / / fecha o m6todo doStuff0 da classe externa
j // fecha aclasseexterna
Oc6digoanteriordeclaraumaclasse,Myouter2,comumm6todo,doStuff ( ).Por6m, duttrodedoSLuff ( ),
outra classe, MyTrurer, 6 declarada com seu m6todo pr6prio, seeouter ( ) . O c6digo acima 6 completamente inritil,
no entanto, p orqve ndo instancia a clase intemalS6 por que vo cE declarou a clxse, neo significa que criouuma insldncia dela.
Ponanto, se quiser realmente llsara classelnterna (digamos, para chamar seus m6todos), entao, voce ter6 que criar uma
instincia dela em algum loc al dentro fu ndtodo, mas abaixo da defnipdo da dasse intema. O c6digo abaixo mostra como instanciar
e usar uma classe interna local de m6todo:

a'lacc MrrOrrfar? I

private String x = "Outer2";


void doStuff O {
class Mylnner {
public void seeouterO {
System.out.println("Outer x is " + x);
j / / fecha o m6todo da classe interna
\ | / focha a dofininSo da classc interna

MyTnner m1 = new Mylnner ( ) ; / / Esta linha deve vrr


/ / Aaaai c rl: nla<<

mi. seeout.er O ;
) / / fecha o m6todo doStuff ( ) da classe externa
I // fecha a classe externa

O que um obieto interno local de m6todo pode ou neo fazer


A classe interna local de mtitodo sd podeni ser instanciada dentro do nhodo ondefor defnida. Melhor dizendo, nenhum c6digo que
estiver sendo executado em qualquer outro m6todo - dentro ou fora da classe externa - poder6 instanciar a classe interna
local de m6todo. Como os o6ietol da classe interna comum, o objeto da classe interna local de m6todo compartilhar6 um
relacionamento especial com o objeto da classe que o estiver encapsulando (externa) e poderi acessar seus membros
privados (ou qualquer outro). No entanto, o obleto da classe interna nio poderd asar as uai,luefu locah do ndtodo onde a classe interna
estiuer.Por que nio?

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 {

nri rra1-e Sfri


v!+vsev r16J x = "OUter2";
void doStuff O {

String z = "local variable";


al:qc M\/Tnhar I

public void seeouter ( ) {


qlrqt- em orr1- nr:int1n("Ogter X iS " + x) ;
Svsfem-out-ni:int1n("Local variable z is " + z); // Ndo vai compilar!
368 Copitulo B: Closses inlernos

\ / / fecha o m6todo da classe interna


j / / fecha a definigdo da classe interna
\ / / fecha o m6todo doStuff ( ) da classe externa
j //fechaaclasseexterna
A compilagio do c6digo anterior realmente preocupari o compilador:
Myouter2.java:8: local variable z is accessed from within j-nner class;
needs to be declared final
q\/ql-am nttl- nrinflnlNT,^.al rrariah1 a z iq \'+ zl.

Marcar a vari6vel Ioca| z com f inal corriglr.^ o problema:


final String z = "1ocal variable" ; / / Agora o objeto interno pode usii-la
Apenas um lembrete sobre os modificadores de um m6todo: as mesmas regras das declarag6es de vari6veis locais
sio aplicadas )s classes internas locais de m6todo. VocA nio pode, por exemplo, marcar uma classe interna local
de m6todo com public, private, protected, static, transient e algo semelhante. Os rinicos
modificadores que voc€pader,i aplicar a essa classe sio abstract e f inal
mesmo tempo como para qualquer outra classe ou m6todo.
- mas 6 claro que nunca os dois ao

oBSERVAQ6ES pene O EXAME


L.embre-se de que uma c/ase /oea/ du/arada em um mdtodo static
terd acesn rlmente a membros staticda classe extenta, uma ue<
que nenbuma instdncia associada da c/asse externa. S e uocd e#iuer em un ndtodo s t a t i c
ndo baueni a referdncia Lhis, portantl, a
classe intema de um mdtodo s t a t i c
utd suleita as mesmas restipdes desse mdtodo. Em outras pa/arras, ndo tem ace$o a "uaidueis de
in$dncia".

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.

Classes internas an6nimas simples, versao um


Observe o c6digo abaixo; vilido, por6m, estranho ) primeira vista:
class Popcorn {
public void pop ( ) t
q\/cl-am nrr1- nrirts ln / rtnana^r^r, \ -
vJvuutt.vsu.yrfllufrr\ yvvuvrll /,

cl-ass Food {

Popcorrr D = nevt eopcorn() {


public void popfl {
System. out.println ( "anonlmous popcorn,' ) ;
JAVA 5 369
I;
)

Examinemos o que ocorreu no c6digo anterior:


r Definimos duas classes, Popcorn e Food.
I Popcorn tem um m6todo, pop ( ) .

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.

Examinemos apenas o c6digo da classe an6nima:


? P6n^6rn vn _
= nar^r
rruYv Ddn^nrn/l
rvyvvrrl\/ {L

3. public void popo {

4. System. out.printl-n ( "anonlzmous 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.

oBSERVAQ6ES peRA O EXAME


Geralnente, d diftcil identifcar o ponto-e-uirgula de fechamento. Portanto, uocd pode uer am cridigo conl este n0 exame:

?
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") ;

6. ) // Fllta o ponto-e-virgiula aecesgdrio p,ara finalizar a instrugto en 2!!


7. Foo f = new FooO;
Voci precisard de um cuidado especia/ com a sintaxe qaando houuer classes internas enuoluidas, porqae o aidigo da linba 6 parece perfeitanente
natural. Ndo estamos acostumadot a uer o ponto-e-uirgala depois de chaues (a ilnica oatra sitaagdo em qae isso ocorre t1 em atalhos na
inicialirygdo de anay).

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

class Horse extends animal-{


void bucko { }
]
class animal {
void eato { }

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

Observe o c6digo inv6lido a seguir:


nlacc Dnnnnrn
vvv v! rr fr

publ-ic void pop0 {


System. out.println ( "popcorn" ) ;

]
cLass Food {

PoPcorn P = new PopcornO {

^,,1-1
Puvffu ^ ,,^r,{ sizzle ( )
.i
vvrs t
System. out.println ( "anonymous sizzling popcorn" );
]
public void pop ( ) {
System. out.println ( "anonlmous popcorn" ) ;
]
];

public void poplt ( ) {


p.pop O ; / / oK, Popcorn tem um m6todo pop o
p. sizzle (l ; / / Inv6lido ! Popcorn ndo tem sizzfe ( )

]
]
A compilaglo do c6digo anterior nos dara,
Anan i:rr: . 1q ' .^nh^f racnl rrav crmlln
uJ f L'!vr l

symbol : method slzzle ll


location: class Popcorn
p,sizzle);

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

emqueCookable 6umainterfanemvezdeumtipodeclassenioabstract.Porque,pensebem, uoc6niopode


emboraparega que 6 isso que o c6drgo est|fazendo. Mas 6 claro que ele nio est6 instanciando um
instanciar uma inteface,
objeto Cookable, est6 criando a instAncia de um novo implementador an6nimo de Cookable. Portanto, voc6 pode ler a
linhaabaixo,
Cookabfe c = new Cookable0 {

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,

Runnable r = newRunnabl-el); // impossivel instanciar a interface


enqaantl a qae re encontra abaixo d udlida, porque estui instanciando ua implementador da inteface Runnable (una classe de
iruplenentaqdo aninina):

Runnable r = new Runnable O { / / chave em vez de ponto-e-virqula


public void runo { }
);

Classe interna an6nima definida no argumento


entendeu o que abordamos at6 agora neste capitulo, entio, essa riltima parte seri simples. No entanto, s e inda atiuer
Se vocA
um pouco confixo com relaglo is classes an6nimas, deve reler as seg6es anteriores. Se elas nio estiverem muito claras,
372 Copitulo B: Closses internos

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.

Obietivo poro o certificoc6o


Classes est6ticas aninhadas
Guardamos o mais Iicil para o final, como um tipo de gentilez .

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.

Instanciando uma classe aninhada estitica


Use a sintaxe padrio para acessar uma classe aninhada est6tica a p^ftir da sua classe imediatamente externa. A
sintaxe para a instanciagio de uma classe aninhada estatica 6 um pouco diferente daquela de uma classe interna
comum, e tem este formato:
nl:qq Rial.)rrt-or I

static class Nest {void go( ) { System.out.println("hi"); } }

]
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

oBSERVAq6ES pene O EXAME


Assim como aru mdtodo estdtico n6o terz acesso is aai,iueis de instdncjas e m,itodosndo-sEatic da c/asse, uma clasrc estdtica
aninhada ndo tem acetso ir uaritlueis de instincias e aos mdtodos ndo-sLaLic da claxe extema. Procare por c/asses aninhadas
static con aldigo que se czmplfte tuml uma classe ndo+stdtica (intena regukr).

Resumo para a certificagio


As classes internas aparecerio em todo o exame, independente do t6pico, e essas serio algu.mas dasquest6es mais
dificeis do exame. VocA est6 familiarizadocom a sintaie, )s vezes, bizirrae sabe como identificar definig6es de classes
internas vilidas e inv6lidas.
Examinamos primeiro as classes internas "comuns", em que uma classe 6 membro de outra. Voce aprendeu que codificar
uma classe interna significa inserir a defrnigio dessa classe nas chaves da classe encapsuladora (externa), p.ot6m, fora de
qualquer m6todo otioutro bloco de c6digo. Aprendemo s que a instdnciade uma classe interna compartilha um
ril".ion^-.nto especial com uma instAnci-a espicifica da clari. e*t.ttt", . que esse relacionamento. permite que.a classe.interna
acesse todos os membros da classe externa, iniluindo os marcados com private. VocA aprendeu que para instanciar uma
classe intern4 precisa de uma refer6ncia ) instAncia da classe externa.

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.

Classes internas locais de m6todo


D Uma classe interna local de m6todo 6 definida dentro de um m6todo da classe encapsuladora.
D Para a classe interna ser usada, vocA precisa instanci6Ja, e essa instanciagio deve ocorrer dentro do mesmo
m6todo, por6m, ap6s o c6digo de definigio da classe.
E Uma classe interna local de m6todo.nio pode usar variiveis declaradas dentro do m6todo (incluindo
parAmetros), a menos que essas variSveisie.lam marcadas com f inal.
E Os rinicos modificadores que voc6 pode aplicar a uma classe interna local de m6todo sio abstracL e
f inal (nunca os dois ao mesmo rempo, no entanto).

Classes internas an6nimas


E As classes internas an6nimas nio t6m nome, e seu tipo deve ser uma subclasse do tipo nomeado ou um
implementador da interface nomeada.
D Uma classe interna an6nima 6 sempre criada como pane de uma instruEio, portanto, nio esquega de fechar a instrugio,
com uma chave, ap6s a definigXo da classe. Essa 6 uma d"s raras vezes em que voc6 ver6 uma clave seguida de um
pontoe-virgula em Java.
D Por causa do polimorfismo, os inicos m6todos que voc6 poder6 chamar em uma refer6ncia ) classe interna an6nima
serio os delinidos na classe (ou interface) da variivel de referOncia, ainda que a classe an6nima seja, na verdade, uma
subclasse ou um implementador do tipo da vari6vel de referAncia.

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: ] ) ;

Classes aninhadas esteticas


D As classes aninhadas estiticas sio classes internas marcadas com o modificador static.
E Tecnicamente, uma classe aninhada est6tica nio 6 uma classe interna, mas, em vez disso,6 considerada uma classe
aninhada de nivel superior.

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:

BigrOuter.Nested n = new BigOuter.NestedO ;

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.

l. Dado o c6digo a seguir,


public class MyOuter {
376 Cooftulo 8: Closses internos

public static class Myrnner {public static void foo ( ) { } }

]
que instruglo, se inserida em uma classe diferente de MyOuter ou Mylnner, criar6 uma instAncia da classe aninhada?

,{. Myouter.Mylnner m = new Myouter-Myfnner( );


B. uyouter.Mylnner mi = new Mylnner( );
C Myouter m = new uyouter( );
Myouter.MyInner mi = m.new Myouter.MyInner( );
D. Myrnner mi = new MyOuter.Mylnner( );

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.

B. Ela nio tem acesso a membros nlo-sLatic da classe encapsuladora.

C Suas variiveis e m6todos devem ser static.


D. Se a classe externa se chamar Mlouter, e a classe aninhada se chamar Myrnner, ela pode ser instanciada usando
new Myouter.Myfnner( ) ;

E. Ela deve estender a classe encapsuladora.

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. Dado o c6digo a seguir,


class Boo {
Boo(String s) t ]
BooO t ]
]
class Bar extends Boo {
BarO { }
Bar(String s) {super(s) ; }
voi_d zoo O {
/ / insira o c6digo aqui
]
]
quais das instrug6es abaixo criam uma classe interna an6nima de dentro da classe Bar? (Marque todas as corretas)

,d eoo f = new eoo(24) { };


B. Boo f = new Bar( ) { };
C Boo f = new Boo( ) {Stri-ng s; };
D. gar f = new Boo(String s) { };
E, Boo f = new Boo.Bar(String s) { };
JAVA 5 377
5. Dado o c6digo a seguir,
1. class Foo {
2. class Bar{ }

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)

A. foo.Bar b = new Foo.Bar( );


B. Poo.Bar b = f .new ear( );
C. Bar b = new f .Bar( );
D.ear b = f .new Bar( );
E. P'oo.Bar b = new f .Bar( );

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.

D. Pode implementar virias interfaces, independente de tamb6m estender uma classe.

E. Pode implementar virias interfaces, se nio estender uma classe.

8. Dado o c6digo a seguir,


public class Foo {
Foo() {System.out.print ("foo") ; }
class Bar{
Bar( ) {System.out.print ( "bar" ) ; }
public void go() {System.out.print ("hi") ; }

]
nrrhl ic <j- :l- ic rrnid main /qt- rina f l :ra<) {

Foo f = new FooO,-


f .makeBar O ,'
]
rrnid maLaF.arI\ t

(new BarO t]).goO;


]
378 Cop(tulo B: Closses internos

qual ser6 o resultado?


A. A compilagio falhar6.
B. Um erro ocorreri no tempo de execugio.

C. foobarhi
D. barhi
E. hi

9. Dado o c6digo a seguir,


1. public class TestObj {
2. public static void main (String [] argrs) t
3. Object o = new Object0 {
4. publ j-c bool-ean equa]s (Obj ect obj ) t
5. return true;
6. )
7. ]
8. System.out.println(o.equals("Fred") ) ;
q]

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.

E. A compilaglo f.alhari por causa de um erro na linha 4.


F. A compilagXo falhari por causa de um erro na linha 8.

G. A compilagio falharipor causa do erro em uma linha que nio 6 a 3, 4 ou 8.

| 0. Dado o c6digo a seguir,


1. public class HorseTest {
2. public static void main (String [] args) {
3. class Horse {
4. public String name;
5. public Horse(String s) {
6. name = s;
7. )
B. ]
9. Object obj - new Horse("Zippo");
10. Horse h - (Horse) obj;
1,1. System.out.printfn(h.name) ;
t2. ]
1? ]
qual serd o resultado?
A. Uma excegio de tempo de execugio ocorrer6 na linha 10.
B. zipppo
C. A compilagio f.alhar| por causa de um erro na linha 3.
D. A compilaglo falhari por causa de um erro na linha 9.
E. A compilagdo falhar6 por causa de um erro na linha 10.
F. A compilaglo falharipor causa de um erro na linha 11.

I l. Dado o c6digo a seguir,


1-. public class HorseTest {
2. public static void main lsrrino [t aras] {

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.

E. A compilagd,o f.alhar|por causa de um erro na linha 10.

12. Dado o c6digo a seguir,


publ-ic abstract cl-ass AbstractTest {
public int getNum0 {
return 45;
)
public abstract class Bar {
public int getNumo t
return 38;
]
)

public static void main (String [] args) {

AbstractTest t = new AbstractTestO {


public int getNum( ) {
retwrn 22;
]
];
AbstractTest.Bar f = t.new BarO {

public int getNumo {


return 57;
]
];
q\/c1-am arrl- nrinf lnlf nal-\Trrmt\ + \'t\ + | dafT\Trrmf ]).
380 Copitulo B: Closses internos

qual ser6 o resultado?


4.57 22
B. 43 s8
c.4s 57
D. Uma excegio ocorrer6 no tempo de execugio.
E. A compilagio falhar6.

Respostas do teste individual


1. A. Mylnner 6 uma classe aninhada est6tica, portanto, deve ser instanciada com o uso do nome do escopo
completo que 6 MyOuter.Mylnner.
A resposta B esti incorreta porque nio usa o nome da classe encapsuladora na instrugio new. C est6 errada
porque usa a stnraxe ,rrcor.et". Quando voc6 instanciar uma classe aninhada. chamando a palavra-chave new
.* ,rrn" instAncia da classe encapiuladora, nio teri que usar o nome dessa classe. A diferenEa entre A e C 6
que C est6 chamando new em uma instAncia da claise encapsulador^, ern uez de chamar a,palavra-chave
iioladamente. D est6 incorreta porque nio usa o nome da classe encapsuladora na declaragio da variivel.
,)
B e D. A resposta B est6 correta porque uma classe aninhada estitica nio 6 associada a uma instAncia da classe
encapsuladori e, porranto, nio podi or m.mbros nio-static da classe (da mesma forma que um m6todo
"cersar
stalic niopodeacessarosmimbrosnioesr6ticosdeumaclasse).Dusaasintaxecoffetaparainstanciagiodeuma
classe est6tica aninhada.

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

I Reconhecer Estodos e TronsiE6es de


Threods

I Usor o Bloqueio de Objetos poro


Evitor o Acesso Simult6neo

I Escrever C6digo que Use woii0,


notifyfl ou noiifyAll0

r' Exercicios 16pidos

P&R Teste Individuol


384 Copftulo 9: Threods

Obietivo poro o certificoEdo

Definindo, instanciando e iniciando threads


(Objetivo 4. I do exame)
4.1 Escreuer cddigos qae defnam, instanciem e initiem nouos tbreads asando tantolaua.lang.Thread quantoiaua.lang.Rannable.

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 Uma instAncia da classe java.lang.Thread;

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:

public void runO {


/ / se.u c6diqo Dara o traba]ho acrui
)

Escrevasempre o c6digo queprecisaserexecutado nothreadseparadodeumm6todo ). O m6todorun nn() chamar6 (


outros m6todos,6 claro, mas othreaddeexecu$o - anovapilhade chamadas - sempre comegarlchamando run ). Entlo, (
onde entrari o m6todo run (
) ? Em uma das duas classes que vod pode usar para definir o trabalho de seu thread.

VocO pode definir e instanciar um thread de uma das duas maneiras:

I Estender a classe java.lang.Thread

I Implementar a interface Runnable


VocA ter6 que conhecer as duas no exame, embora no mundo real seja muito mais provivel que implemente
Runnable emvez de estender Thread. Estender a classe Thread 6 mais f6cil, mas, geralmente, nio 6 uma boa
prhrica no modelo OO. Por qu6? Porque a criagio de subclasses deve ser reservada para classes que estendam uma
classe j6 existente, por elas serem uma versio mais especializadada superclasse mais gen6rica. Portanto, a rinica
situaglo em que realmente faz sentido (da perspectiva do modelo OO) estender Thread 6 quando temos uma
verslo mais especializada de uma classe Thread. Em outras palavras, por que rucd tem um czntportamento de Thread mais
espunliqado. No entanto, h6 chances de que o trabalho necessirio, na verdade, s6 possa ser executado por:ul;;' thread.
Nesse caso, voc6 deve projetar uma classe que implemente a interface Runnable, o que deixar6 sua classe livre
para estender alguma aatra classe.

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:

I Estender a classe Thread;

I sobrescrever o m6todo run ( ) .

O formato 6 este:
386 Copftulo 9: Threods

cl-ass MyThread extends Thread {

public void run ( ) {


System.out.println( "Tmportant job running in MyThread" ) ;

]
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:

cl-ass MyThread extends Thread {


public void runo {
q\/ai-am nrrl. nrirl-ln t"Tmn^rj-:hl- inh rrtnnino in MvThrcad") .

]
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:

class MyRunnable implements Runnabfe {


public void runo {
Qa'dfan arrf nrihf lnl$Tnn^rf:nl- -inh rrrrlnlpg in MyRUnnabfe,,);

]
)

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

OBSERVAQ6TS pene O EXAME

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:

Thread t = new Thread(new MyThread( ) );


Isso d am pouco estranho, nas adlido. Neste caso, na uerdade, uocd sd precisa de um Rttnnable, e criar oatro Thread d an exagerl.

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

I O thread passar6 do estado novo Para o estado exuutduel.

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.

OBSERVAQ6ES pene EXAME


Nno h,i natla especial na mitodo run ( ) da lingaagen laua. Cono main ( ) , sinrylesmente i o nome (e a assinatara) do mdtado que o

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:

Runnabler = new Runnabfeo ;


r.runO; / / V61ido, mas ndo inicia um thread separado
O exemplo abaixo demonstra o que abordamos at6 agora: definigio, instanciagXo e inicializaEio de um thread:

class FooRunnable implements Runnable {


public void runO {
for(int x =1; x < 6; x++) t
System. out . print.ln ( "Runnable running" ) ;

]
]
public class TestThreads {
public static void main (String [] args) {

FooRunnable r = new FooRunnableO;


Thread t = new Thread(r) ;
t. start O ;
)

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

System. out. println ( "Run by "


+ Thread.currentThread( ) .qetName () ) ;

]
)
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 (, ;

Thread t = new Thread(nr) ;


t. setName 1"nred,,) ;
t. start O ;

A execugio desse c6digo pro duziri a saida especial a seguir:


? java NameThread
NameRunnable runninq

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

NameRunnable nr = new NameRunnable ( ) ;


Thread t = new thread(nr) ;
// t.setName("Fred");
t.start O ;

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

Iniciando e executando mais de um thread


JAbrincamos o bastante; passemos para a execugio real de aiiosthreads (mais de dois, na verdade). J6 temos dois threads,
porqn" o m6todo main ( ) comega no seu pi6prio thread, e depois't. start ( ) iniciou um seganlo thread. O
i6digo a seguir cria somente uma instAncia de Runnable e tr6s de Thread. Todas as tr6s instAncias de Thread t6m a
mesma instlncia de Runnable, e cad^ thread recebeu um nome exclusivo. Para concluir, todos os tres threads
foram iniciados com uma chamada a start ( ) nas instAncias de Thread.
390 Coo(tulo 9: Threoqs
class NameRunnable implements Runnable {

public void runO t


for (int x = 1; x < 3; x++) {
q\rct-am
rJruvaLt.vuL.v! nrrj. nrinl. lnl"Rrrn
\ r\urr krv
vJ
\'

+ Thread. currentThread ( ) . getName ( ) ) ;


+ " , x is " + x);

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

Thread one = new Thread(nr);


one . setName ( "Fred" ) ;
Thread two = new thread(nr);
two. setName ( "Lucy" ) ;
Thread three = new Thread(nr);
three. setName ( "Ricky" ) ;
cl-arl-ll.
^n6
l-r^rn cf :rl- I\ .

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

3) methodlf comega um novo thread

Figuro 9-1 - lniciolizoEdo de um threod


A execugio desse c6digo produzid o seguinte:

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

* ", X is " + x);

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:

Run by Fred, x is 345

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

Run by Lucy, x is 344


...e continua...
Repare que h6 um padrio claro aqui. Se observarmos apenas a saida paraFred, vemos os nfmeros
nio
aumentando um de cada vez, como esperado:
Rttn bl Fred, x is 345

Ran b1 Fred, x is 345


Ran b1 Fred, x is 347
E o mesmo acontece se observarmos apenas a saida de Lucy ou Ricky. Cada um deles est6 se compoffando,
individualmente, de uma forma bem ordenada. Mas juntos - caos! No fragmento acima, vemos Fred, depois Lucy e depois
Ricky (na mesma ordem em que originalmente iniciamos os threads), mas depois Lucy toma a vez de_Fred. Que falta de
educagiol E depois Ricky e Lucy se alternam por alguns irutantes, at6 que Fred tenha outra opornrnidade. Eles se revezam
dessa forma por t.mpo, depois disso. Finalmente (depois da parte mostrada acima) Fred finaliza, e depois Ricky, e
"lgom
entio Luryfinalizacomrlmalongaseqiidnciade saida. Assim, mesmo queRickytenhacomegado em terceiro, eleterminaem
segundo. E, se executarmos novamente, obteremos um resultado diferente. Por qu6? Porque isso i decisdo do agendador, e nds
ndo o contmlamorlO que faz surgir outro ponto principal que deve ser lembrado; stlporqae udrios tbreads sdo iniciador em uma
ordem esperifca ndo ignfica qae wio executadot netsa ordem. Aordem nXo 6 garantida pelo agendador para nenhum grupo de
threads iniciados. E a duragio tamb6m nlo. Nio sabemos, por exemplo, se um thread ser6 executado at6 a conclusio, antes
que outros tenham uma chance de serem iniciados; se todos terio sua chance de serem processados ou se as duas coisas
icontecerlo. H6 uma maneira, no entanto, de iniciar um thread sem que seja executado at6 que algum outro tenha sido
(
concluido. VocA pode fazer isso com o m6todo j oin ) , o qual examinaremos posteriormente.
Um thread deixa de ser um thread quando seu m6todo run ( )6 concluido.

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!

Se voc6 tiver uma referAncia a um Thread, e chamar start (


) , ele 6 iniciado. Se chamar ) mais uma vez, isso start (
causari uma excegio (uma IllegalThreadStateException, que 6 um tipo de RuntimeException, mas voc6 nio precisa se
preocupar com o tipo exato). Isso ocorre independentemente de o m6todo run ) ter ou nXo finalizado em relagio ) (
primeira chamada a s tart (
) . Apenas um novo thread pode ser iniciado, e apenas u mavez. Um thread que estiver
rodando ou inativo nlo pode ser reinicializado.

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.

oBSERVAQAO pene EXAME


Espere porpergunlas n0 exa e que aua/iardo sea conbecimento do que i oa ndo garantido! Voc|precisa ser capaTde olhar o aidigo de am
tread e determinar se a saida serd realmente exibida de ama maneira esbecifrca ou se isso i indeterrnin,l:uel.
JAVA5 393
Mdtodos da classe iava.lang.Thread Alguns dos m6todos que podem nos ajudar a influenciar o agendamento
de threads sio os seguintes:

public static void sleep(long millis) throws rnterruptedException


public static void yieldo
public final void joinO throws InterruptedException
nrrhrl ic final rrnid qe|-Priori 1-rr(int.
uJ \ f rlL naurPrinri
rlevv! r tv! f trr\
uf /

Ebomressaltarquetantosleep( ) quantojoin( )t6mvers5essobrecarregadasnXomostradasaqui.


M6todos da classe iava.lang.Obiect Toda classe em Java herda os tr6s m6todos a seguir relacionados a rreads:

public final void wait ( ) throws InterruptedException


public final void notifyo
public final void notifyAll ( )
O m6todo wait ( ) tem trAs vers6es sobrecarregadas (incluindo a listada aqui).
Examinaremos o comportamento de cada um desses m6todos neste capitulo. Primeiro, no entanto, discutiremos
os diferentes estados nos quais os treads podem se encontrar.

Obietivo poro o Certificocdo

Estados e Transig6es de Threads (Objetivo 4.2 do Exame)


4.2 Reconhecer os estado: em que um thread pode existir, e identifcar at forwas pelas quais an thread pode passar de um estado para 0utr0.

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.

Estados dos threads


O tread s6 pode {icar em um dos cinco estados abaixo (consulte aFigtrag-2):
I Novo Esse 6 o estado em que o tread se enconrra depois que a instAncia de Thread foi criad4 mas o metodo
start ( ) nlo foi chamado. Ele se torna um obieto Thread ativo, mas ainda nio 6 um tread de execucio. Nesse
momento. o tread 6 considerado inatiuo.

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

Figuro 9-2 lronsigdo enfre os estodos dos threods


Mas esses sio , naverdade,m6todos estlticos da classe Thread - ebs ndo afetan a instdncia L;em vez disso, sio definidos
para sempre afetar o thread sendo atualmente executado. (Esse 6 um bom exemplo de por que 6uma m6 id6ia usar
umavari6veldeinstAnciaparaacessarumm6todostatic -podecausarconfusio.H6umm6todo,suspend( ),
na classe Thread, que perrnite a outro sualuspenslo; mas esse m6todo {oi reprovado e nio estari
um tread informar a
no exame (nem sua contrapartida, resume ( ) ). Hi ainda o m6todo stop ( ) , que tamb6m foi reprovado e nio
ser6 avaliado. Tanto susp-end ( ) quanto stop ( ) se mostraram muito perigosos, ponanto, voc€ nlo deve us6-los
e, nio esquega, porque foram reprovidos, nio aparecerio no exame. Nlo estude nada sobre eles, nio os use. Lembre-se
de que um tread no estado bloqueado ainda| considerado atiw.
I Inativo Um tread 6 considerado inativo quando seu m6todo run ( ) 6 concluido. Ele po& continuar sendo um
objeto Thread utiliz6vel, mas nio seri mais um tread separado de execugXo. lJma vez que um tread estiver inativo, nunca
poderi ser ativado novamente (tipo aquela coisa: "eu vejo treads mortos"). Se voc€ chamar start ( ) em uma
irstAncia inativa de Thread receber6 uma excegio de tempo de execuglo (e nio do compilador). E, provavelmente, nio
ser6 necesdrio um cientista espacial para lhe dizer que se um tread est6 inativo, ele nio 6 mais considerado atiw.

lmpedindo a execugeo do thread


Umtread que foi interrompido geralmente significaque passoupara o estado inativo. Mas o objetivo4.2avaliasua
habilidade para reconhecer quando um tread seri tirado do estado de execugio, por6m, sem entrar novamente no estado
execut6vel ou inativo.

No que dizrespeito ao exame, nXo estamospreocupados com o bloqueio de umtreadcausadoporE/a (digamos,


aguardando algo chegar de um fluxo de entrada do servidor). Estamos falando do seguinte:

I Suspensio

I Espera

I Bloqueio, porque precisa de um objeto bloqueado

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) { }

public cl-ass ManyNames {


public static void main (Stri-ng [] args)

/ / Cria um Runnable
NameRunnable nr = new NameRunnableO;

Thread one = new Thread(nr);


one. setName ( "Fred" ) ;
Thread two = new Thread(nr);
two . setName ( "Lucy" ) ;
Thread three = new Thread(nr);
three. setNane ( "Ricky" ) ;

cl-arf/1.
^no
l-r^rn q|- :rl- I l .

l-hrao qi-arl-/\.

A execu$o desse c6digo exibiriFred, Lurye Rickyse alternando de maneiraadequada

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

OBSERVAQAO pene EXAME


Sd porque o miitodo sleep ( ) do thread expirou e drpoit desperloa, n6o signtfca qae retomari ao estado de exuapdo! L,erabre-se de que
quando um thread d despertado simplesmente retorna a0 estado executduel. Portanto, o tempo especifcado em sl-eep (
) ser,l o periodo
nfuimo durante o qua/ o lhread nio rcrd exuutado, mas nio seni operiodo tota/ durante o qua/ o thread ndo executari. De modo que uoc6
nio pode, por exenplo, confar no mdtodo sl-eep (
) nno un tinerpfeitanma prcciso. Embom em naias @litatiws usm sl-eep ) (
nmotimerselasr.{uimtenmteadequada,mdprvcisasaberqaeotenpoespafuadanestemdtodo ndo d amagarantia de que o thread comeganl a ser
executado iouamente logo q*i ptriodo ixpirar eo tiread dupertar.

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

Criando um thread e colocando-o em suspenseo


Neste exercicio criaremos um tread de contagem simples. Ele contar6 at6I}},fazendo uma pausa de um segundo antes de
cada nrimero. Al6m disso, continuando com o tema da contagem, ele exibir6uma st ingacadadeznimeros.

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.

Prioridade dos threads e o m6todo yield


Para entender yield ( ) , voc6 teri que compreender o conceito das prioridadu dos treads. Os treads sempre sio
executados com algum nivel de prioridade, geralmente representado por um nrimero entre 1 e 10 (embora em alguns casos
o intervalo seja menor que 1O). O agendador da maioria dosJVMs usa o agendamento prwmptiuo com base enpioidadu (o
que implica algum tipo de divisio do tempo). Isso nio signfica qae todos os Jl/Ms unm a diuisdo do tempo. A, especificagio JVM
nio imp6e ao VM a implementagio de um agendandor com divisio do tempo, onde seja aloc ado para cadatread um
periodo adequado e, em seguida, ele seja retornado para o estado executivel, dando oportunidade para outro tread ser
executado. Embora muitos JVMs realmente usem a divisio de tempo, outros podem usar um agendador que permita a
um tread permanecer sendo ex ecutado at6 que conclua seu m6todo run ( ) .
Na maioria dosJVMs, no entanto, o agendador usa prioridades para os treads de uma maneira significativa. Quando um
tread entra no estado executSvel e tem prioridade maior do que os outros treads do pool e do que o tread que e$A sendo
executado, o tbreatl sendo executado cowprioridade nenorgeralmente i retornadopara o estado executduel e o de maiorpioridade i
selecionado para exnugdo. Melhor dizendo, 6 comum o tread sendo executado nio ter uma prioridade menor do que os do
pool. O thread que estiuer rcndo pmcetndo teni prioridade tgaal ou maior do qae a prioridade ntais aha dos tbreads do pool.Isso 6 a coisa
mais pr6xima de uma garantia que voc0 obteri da especificagioJVM; portanto, nunca poder6 confiar nas prioridades dos
treads para garantir um comportamento correto paraseu prograrna.

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:

FooRunnable r = new FooRunnableO ;

Thread t = new Thread(r);


t- <of Dvi nri
.*-.'-J
rrr ta )
'',;

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.

I Uma chamadaa join( )

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

Figuro 9-3 O m6fodo join( )

Obietivo poro o certificocdo


Sincronizando o c6digo (Objetivo 4.3 do exame)
4,i Dado am cendio, escreuer cddigo quefapa 0 utt @rlpriadr do bloqaeio de objetos para proteger uaidueis utiticat ou de instdncias de
prob/emas referentes a dcesso simultineo.
JAVA 5 399
Voc€ consegue imaginar o problema que pode ocorrer quando dois threads diferentes com acesso ) mesma
instincia de uma classe chamarem m6todos nesse objeto, e esses m6todos alterarem o estado do obieto? Em outras
palavras, o que pode acontecer se doisthreads diferentes chamarem, digamos, um m6todo configurador no nermy
objeto? Um cenirio como esse pode corromper o estado de um objeto (alterando os valores delua vari6vel de
instAncia de maneira inconsistente) e se o seu estado compartilhar dados com outras parres do programa, bem, 6
horrivel demais at6 mesmo paravisualizar.
Mas s6 porque gostamos de terror, examinaremos um exemplo do que pode acontecer. O c6digo a seguir
demonstra o que aconteceria se dois threads diferentes estivessem acessando os mesmos dados de uma conta.
Suponhamos que duas pessoas tenham um tallo de cheques cada uma, referente ) mesma conta (ou que duas
pessoas tenham cart6es ATM, mas os dois cart6es estejam associados i mesma conta).

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

private int. balance = 50;


pubfic int getBalance ( ) {
return balance;
]
public void withdraw(int amount) {
bafance = bafance - amounLt
)

]
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:

1. O objeto Runnable cont6m a refer6ncia a apenas uma conta.


2. Dois threads slo iniciados, representando Lucy e Fred, e cada um receber6 uma referAncia ao mesmo objeto
Runnable (que cont6m uma referAncia i conta real).
3. O saldo inicial da conta 6 de 50, e cada retirada serA exatamente igual a 10.
4. No m6todo run ( ), percorreremos um loop cinco vezes, e em cada loop:
I Faremos uma retirada (se houver o bastante na conta);
I Exibiremos uma declaraglo se a conta exceder o :aldo (o que nunca deve ocorrer, j6 que verificaremos o saldo antes
de fazer uma retirada).
5. O m6todo makewithdrawal ( ) da classe de teste (representando o comportamento de Fred ou Lucy) faz o
seguinte:
I Verifica o saldo para saber se hi o bastante para
^retk^d^;
T Se houver o ba$ante, exibiri o nome de quem estiver fazendo a retirada;
I Ficar6 em suspensio durante 5OO milissegundos - apenas o tempo suficiente para dar ao outro s6cio uma chance de
acessar antes de a retirada ser realmente feita;
400 Copitulo 9: Threoos

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! ");

privat.e void makeWithdrawal(int amt) {


if (acct.qetBalanceO >= amt) {
System. out.println (Thread. currentThread ( ) . getName ( )

+ " is going to withdraw" ) ;


trY {
Thread.sleep(500) ;
) catch(Int.erruptedException ex) { }
acct.withdraw(amt) ;
System. out.println (Thread. currentThread ( ) . getName ( )

+ " completes the withdrawal");


) else {
System.out.println(*Not enough in account for "
+ Thread.currentThreadO.getNameO + " to withdraw "
+ acct. getealance ( ) )
)

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

1 l'rad ic anin- f^ rrithArrt.r


JAVA 5 401
2. Lucy is going to withdraw
3. Fred completes the withdrawal
4. Fred is going to withdraw
5. Lucy completes the withdrawal
6. Lucy is going to withdraw
7. Fred completes the withdrawal
8. Fred is going to withdraw
9. Lucy completes the withdrawal
10. Lucy is goinq to withdraw
11. Fred completes the withdrawal
12. Not enough in account for Fred to withdraw 0

13. Not enough in account for Fred to withdraw 0

14. Lucy completes the withdrawal


15. account i-s overdrawn!
16. Not enough in account for Lucy to withdraw -10
17. account is overdrawnl
18. Not enough in account for Lucy to withdraw -10
19. account is overdrawnl
Embora a cada vez que voc6 executar esse c6digo a saida possa ser um pouco diferente, percorreremos esse
exemplo especifico usando as linhas numeradas da saida. Nas primeiras quatro tentativas, tudo est6. correto. Fred
verificou o saldo na linha 1 e viu que estava tudo bem. Na linha 2,Lucy verificou o saldo e viu que est6 tudo bem.
Na linha 3,Predfez sua retirada. Nesse momento o saldo qtre Lury verificou (e acreditou qtre fosse preciso), na verdade, se
alterou depois da ihima vez qtre foi verificado. E agora Fred est6 verficando o saldo nouamente, antes de Lury concluir sua
primeira rdrada. A essa alrura, Fred tambdm est6 vendo um saldo potencialmente impreciso, porque sabemos que Lury vai
concluir sua retirada. E posivel, 6 claro, que Fred conclua a sua antes de Lucy, mas nio foi iso qu€ aconteceu aqui.

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

Thread A acessari Obleto 2 somente

Thread B acessari Obleto I e entio o Objeto 2

Figuro 9-4 Problemos do ocesso simulfdneo


Esse problema 6 conhecido como "condigio de corrida", no qual mriltiplos threads podem acessar o mesmo recurso
(normalmente as vari6veis de instincia de um objeto), e podem produzir dados corrompidos caso um thread corra
"rapido demais" para entrar em aEXo antes que uma operagio que nlo deveria ser interrompida possa finalizar.
Impedindo que o saldo da conta seia excedido Entio, o que pode ser feito? A solugio 6 realmente muito simples.
4O2 Cooitulo 9: Threods

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

E como voc6 protegeria os dados? E preciso fazer duas coisas:

I Marcar as vari6veis com private;


I sincronizar o c6digo que altera as vari6veis.

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

" is going to withdraw"),'


trY {
Thread.sleep(500) ;

) catch(InterruptedException ex) { }
acct.wj-thdraw(amt);
System. out.println (Thread. currentThread ( ) . getName ( ) +

" completes the withdrawal");


) else {
System.out.println("Not enough in account for "
+ Thread. currentThread ( ) . getName ( )

+ " to wj-thdraw " + acct.getBalanceO );


)

]
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

Not enough in account for Fred to withdraw 0


JAVA 5 403
Not enough in account for Lucv to withdraw 0

Not enough j-n account for Fred to withdraw 0

Not enough 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 Seumaclassetivertantom6todosslmchronized quantonio-slmchronized, udriostbreahpodrrdoacessaros


mitodos nlo-symchronized da classe! Se houver m6todos que nio acessem os dados que voc6 esti tentando proteger,
entXo, nio ser6 preciso marci-los como sincronizados. A sincronizaglo tem um impacto no dcsempenho (ou pode at6
cansar um impasse se usada incorretamente), ponanto, 6 melhor nio usi-la sem uma b oarozilo.

I St o, thread enhar em suspensdo, e/e mantdm os vus b/oqueiot - nio ot /ibera.

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.

I Voed Pode sincroniqar um bloco de cddigo em ueqde am nitodo.

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 (

System. out.println "not slmchronized" ) ;


(

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\/ \

srmchrnni zcd(MttCl aqq nlacq\ IL

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

Sincronizando um bloco de c6digo


Neste exercicio tentaremos sincronizar um bloco de c6digo. Dentro desse bloco obteremos o bloqueio de um
objeto Para que outros threads nio possam altera-lo enquanto o bloco de c6digo estiver sendo executado.
Criaremos tr6s threads, todos tentando manipular o mesmo objeto. Cada thread exibir6 a mesma letra 1OO vezes e,
em seguida, a exibigio passar6 para a pr6xima letra. IJsaremos um objeto StringBuffer.

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.

O que acontecer6 se um thread nio puder obter o bloqueio?


Quando um thread tentar acessar um m6todo slmchroni zed. e o bloqueio j6 estiver sendo usado, diz-se que ele
foi inpedido de obter o bloqaeio de un objeto. Essencialmente, o thread entrari em um tipo de pool desse objeto especifco e ter|
que aguardar at6 que o bloqueio seja liberado e ele possa novamente passar para o estado executlvel/em execuEeo.
No entanto, s6 porque um bloqueio foi liberado nio significa que algum thread especifico iri usilo. Pode haver
tr6s threads aguardando um rinico bloqueio, por exemplo, e nlo h6 garantias de que o thread que esteja esperando
h6 mais tempo seri o primeiro a obter esse bloqueio.

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.

Tobelo 9-l Metodos e o sfofus do b/oqueio

Abrem mlo do bloqueio Mant€m o bloqueio Classe que define o mdtodo

wd,r \- \ ) notify ( ) (Embora o thread provavelmente j ava. lang. Obj ect


saia do c6digo sincronizado depois
dessa chamada. Portanto, abrM mlo
dobloqueio)
inin/ I java. lang. Thread
sleep ( ) j ava . lang. Thread
yield( ) j ava. 1angr. Thread
406 Copitulo 9: Threods

Entio, Quando Eu Preciso Sincronizar?


A sincronizaglo pode ficar bem complicada, e voc6 pode estar se perguntando.pgr que iria.querer se dar a esse
trabalho, ,r-i lrei q,re pode evitiJo. Mas lembre-se do exemplo antes de "condigio de corrida" , com Lucy e
Fred fazendo r"qnei di conta deles. Quando usamos threads, normalmente precisamos usar alguma
sincronizagio em algum lugar para nos certificarmos de que nossos m6todos nio ir6o interromper uns aos
outros t" hor" os nossos dados. Geralmente, sempre que mais de um thread estiver
"rr^i^,bag;ng""d"
acessando dados mut{veis"(mbdificlveis), voc6 sincroniza p"ra prot.gir oJ dados, para cenificar-se de que dois
threads nXo os estio modificando ao mesmo tempo (ou que um nio os estA modificando ao mesmo temPo em
que o ourro os est6 lendo, o que tamb6m leva a cbnfusA,ei). ryao ( preciso se preocupar com variiveis locais -
cada thread recebe a sua pr6pria c6pia de uma vari6vel local. Dois threads que executem o mesmo m6todo ao
mesmo tempo usario diferentes c6pias das vari6veis locais, e nio interferirio um com o outro. Entretanto, voc6
precisa se preocupar com campos itatic
e nio-static, caso eles contenham dados que possam ser
modificados.
Para dados modific6veis em um campo nlo-static, voc6 normalmente usar6 um m6todo nlo-static para _

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.

nri rzaf o i ht n^nql- af i .E i al .1 .

public static slmchronized int getstaticFieldO {


return staticField;
]
public static slmchronized void setstaticField(
int staticField)
Thinq.staticField = staticField;
)
public slmchronized int qetNonstaticFieldO {
return nonstaticField;
]
public symchronized void setNonstaticFj-eld (
int nonstaticField) {

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?

Classes Seguras em Relag6o a Threads


Quando uma classe foi cuidadosamente sincroniz-adapara proteger os seus dados (usando-se as regras que acabamos de
aPresentar, ou usando alternativas mais complicadas), dizemos que a classe 6 "segura em relagio aoi thtr"d.". Muitas classes
nas APIsJava j6 usam a sincronizagio internamente para tomar i classe "segura". Por exemplb, String$uffer e StringBuilder
sio classes quase iddnticas, exceto pelo fato de que todos os m6todos em StringBuffer sio sincronizados quando neiess6.rio,
enquanto que os de StringBuilder nio sio. Em geral, isso torna StringBuffer segura de se usar em um am-biente
multithread enquanto Strin-gBuilder nio 6. @or outro lado, StringBuilder 6 um-pouco mais ripida, porque nio precisa se
preocupar com a sincroniza$o)
Entretanto,_mesmo.quando uma classe for "segura", na maioria dos casos 6 perigoso confiar nessas classes para fornecer
a protegio de thread que voc6 precisa. (Ora, o fato de usarmos repetidamente aspas em torno de "segura" tinha de
significar algo, nlo?) Voc6 ainda precisa pensar com cuidado sobre como usar6 eisas classes. Como um exemplo,
considere a seguinte classe.

import java.util.*;
public class Namelist {
private List names = Collections.slmchronizedlist(
nar.r T.i nlra^r.i cf r \ ) ;

public void add(String name) {


narnes. add (name) ;

)
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

final NamelisL n1 = new Namel,ist ( ) ;


n1 . add ( "Ozymandias " ) ;

class NameDropper extends Thread {


public void runo t
St.ring name = n1 .removeFirstO;
System. out. println (name) ;
)
)

Thread t1 = new NameDropper ( ) ;


Thread t2 = new NameDroppero;
tl. start O ,-

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.

Thread L2 nio chama remove ( o ) .


A saidaaqui 6

Ozlzmandias
nu11
Entretanto, se executarmos o programa novamente, poderi acontecer algo diferente:

Thread L1 executanames . sizeO, que retorna 1.


Thread t2 executanames . size ( ), que retorna 1.

Thread t1 executa names . remove (0), que retorna Ozymandias.


Threadt2 executanames.remove(0),quelangaumaexcegloporquealistaagoraest^vazia.
O que voc6 precisa perceber aqui 6 que, em uma classe "segura" como aquela retornada por synchronizedlistQ, cada m6todo
individualestisinCronizado.Assim,narnes.sizeO est6slmchronized,enames.remove(0)tamb6m.Mas
nada impede que outro thread faga alguma outra coisa na lista no espago entre essas duas chamadas. E 6 ai que podem
ocorrerproblemas.
Hiumasolugio aqui: nlo confie em Collections . slmchronizedlist ( ) . Emvez disso, sincronize o c6digo
vocAmesmo:
imnnrr i=rz: ,rfil *.

public class Namel,ist {


private List names = new r-inkedl,ist ( ) ;
pubfic synchronized void add(String name) {

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

5- nrirrate ReSO111.Ce reSOUrCeB = new Resorrrce():


7. pubLic int read() {
B. slmchronized(resourceA) { // Pode haver impasse aqui_
9. slmchronized(resourceB) {
10. return resourceB.vafue + resourceA.value;
1-r. )
1.2. )
13. )
L4.
15. public void write(inr a, int b) {
16. synchronized(resourceB) t // Pode haver impasse aqui
1-'7 . slmchroni zed resourceA) { (

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.

Obietivo poro o certificoc6o


lnteragio entre os threads (Objetivo 4.4 do exame)
4.4 Dado am cenirio, escreuer ctidigo quefapa uto apropriado de wait, notfi ou notfrAll.
O fltimo item que precisamos examinar 6 como os threads podem interagir entre si para comunicar - entre outras coisas -
ostatusdeseusbloqueios.AclasseObjectpossuitr6sm6todos-wait( ),notify( ) enotifyAll( )-que
ajudam os threads a obterem informag6es sobre o status de um evento importante para eles. Por exemplo, se a
tarela de um thread for a distribuigio de correspondAncia, e a de outro for o processamento de corresponddncia,
410 Copitulo 9: Threods

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

/ / Obt6m o formato do usu5ri-o


// Calcula as etapas da m6quina para fazer o formato
/ / Envia as etapas para o hardware

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

O pseudoc6digo abaixo mostra esse projeto:


public void userloopO {
while (true) {

/ / ObL6m o formato do usu6rio


/ / CaIcuIa as etapas da n6quina para fazer o formato
/ / Modrfica objetos comuns com as novas etapas da m5quina
]
)
public void hardwareloopO {
while (true) {

/ / Obt6m as etapas do objeto comum


/ / Envia as etapas para o hardware

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 {

8. System.out.println("Waiting for b to complete.


9. b.wair O ;
10. ] catch (InterruptedBxception e) i)
1l-. System.out.println(..Total is: .. + b.total);
42. )
l-3. )
L4. )
l_5.
16. class ThreadB extends Thread {
I7 . int total;
1_8.

19. public void runO {


20. slmchronized(this) i
21_. for(int i=0;i<100;i++) {
22. total += i;
23. )
24. notifyo;

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:

slmctrronj-zed(anotherObject) { // este 6 o proprietarj-o do bloqueio em anotherObject


try {
anotherobject.wait ( ) ,
// o thread libera o bloqueio e espera
/ / Para continuar, o thread precisa do bloqueio,
/ / enLdo poder6 ficar bloqueado at6 que o obtenha.
] catch(InterruptedException e) { }
)
O c6digo anterior aguardariat| quLenoti fy ( ) seja chamado em anotherObj ect.
swahrorizarl(th) q\ Ir nnfifrr/\
rrvuflJ\/r 1
J

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

oBSERVAQoES pene O E)GME


paando o mdtodo wa it( ) for chanado em um objeto, o thread que e$iaer executando use aidigo abinl mdo de tea bloqueio
imediatamente. I\o entanto, quando noLify (
| for chamado, isso nio txCnifta qae o thread abrird mdo de sea bloqueii na mesma bora.
Se o thread ainda eftiuer concluindo o ctidigo sincroniqado, o bloqaeio ndo seni liberado atd que ele saia duse nidtgo. Portanto, sri porque
no t i fy ( ) foi chamado nio signtfca que o bloqueio se tornani disponiuel nesse mlmentl.

Usando notifyAll( ) quando houver a possibilidade de muitos threads estarem


esPerando
Na maioria dos cenarios, 6 preferivel notifi car todls osthreads que estiverem esperando por um objeto especifico. Se isso
acontecer, voc6 poder6 usar notifyAll ( ) no objeto pira permitir que todosbs threadi saiam da lrea de espera
e retornem ao estado execut6vel. Isso seri particularmente imponante se voc€ tiver threads aguardando um objeto,
por6m, por diferentes raz6es, e quiser se cirtificar de que o thread certo serA notificado.
notifyAll ( );/ / Notificar6 todos threads que estiverem esperando
Todos os threads serio notificados e comegario a competir pela obtenglo do bloqueio. J6 que o bloqueio ser6
usado e liberado por cada thread, todos eles entrario em agio sem a necessidade de uma notificagioidicional.
Como mencionamos anteriormente, um objeto pode ter muitos threads esperando, e o uso de notify ( ) afetarit
aPenasym deles. Qual e*atamente nio ser6 especificado e depender6 da implementagio da JVM, porranro, voc6
nunca deve confiar que determinado thread ser6 notificado no lugar de outro.
Nos casos em que podemos ter muitos threads esperando, a melhor maneira 6 usar noti fyAll ( ) .
Examinaremos isso em um c6digo. Nesse exemplo, h6 uma classe que a(ecuta um calculo e muitos threads de leitura que
estio esperando para receber o c6lcrrlo concluido. Em algum momento, muitos *reads & leitura podedo estar esperando.
1. class Reader extends Thread {
2. Calcu]ator c;

4. nrrl-r'l i c Raarlor /l-: l nrrl I


^f ^r ^il ^l
q
c = cafc,.
6. )

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 (

) , somente um thread de leitura seria notificado, em vez de todos.

Usando wait( ) em um Loop


Na verdade, ambos os exemplos anteriores (Machine/Operator e Reader/Calculator) tinham um mesmo problema. Em
ambos,haviapelomenosumthreadchamandowaitO,eoutrothreadchamandonotifyO ounotifyAllO.
Isso funciona muito bem, desde que os threads na espera rcnham comegado a esperar antes de o outro thread executar
notifyO ounoLifyAllO.Masoqueacontecese,porexemplo,oCdculatorrodarprimeiroechamarnotifyo
antes de os Readers terem comeEado a esperar?

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

public void addJob(Machinelnstructions job) {


slmchronized (jobs) {
jobs.add(job) ;
jobs.notifyO;

public void run0 {


urhila ttrrra\ I

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) { }

// Se chegarmos aqui, saberemos que jobs ndo est6 vazio


Machinelnstructions instructions = jobs.remove(0),.
/ / Envia as instruq6es da miiquina para o hardware

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

Reparetamb6mquetanto o m6todo run ( ) quantoo add.Tob ( ) sincronizamno mesmoobjeto-alistadetrabalhos.


Tssoocorrepordoismotivos.Um6queestamoschamandowaitO enotifyO nestainstAncia,entiopfecisamos
smcromzar para evlrar uma excegio IllegaiThreadState. O outro motivo 6 que os dados na lista de trabalhos sio
416 Copitulo 9: Threods

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

quaisndosdo-join( )estart( ).ATabela9-2 listaosmdtodotprincipafuqueuocdprecisaniconltecernoexame,czmosnitodos


static exibidw em itdlico.

Tobelo 9-2 M6lodos principois dos threods

Classe Obiect ClasseThread Interface Runnable

wait0 staft0 run0


notdyQ jeld( )
notifyAll0 tlttp( )
join0

Resumo para a certificagSo


Este capinrlo abordou o conhecimento necessirio sobre threads que voc6 precisari aplicar no exame da certificagio. Os
threads podem ser criados pela extensio da classe Thread ou a implementageo da interface Runnable. O rinico m6todo
que deve ser sobrescrito na intertace Runnable 6 run (
) , mas o thread nio se tornarA. um tltread de execugio at6
que algu6m chame o m6todo start ( )do objeto Thread. Tamb6m examinamos como o m6todo sleep (

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

Criando, instanciando e iniciando novos threads (Objetivo 4.1)


0 Os threads podem ser criados pela extensio de Thread e a sobrescrigio do m6todo public void run ( ).
B Os objetos dos threads tamb6m podem ser criados com uma chamada ao construtor de Thread que usa um
obieto Runnable como argumento. Diz-se que o objeto Runnable 6, o tlestino do thread.
JAVA 5 417
o Voc6 pode chamar start ( ) em um objeto Thread somente uma vez. Se start ( )for chamado mais de
vmavez em um objeto Thread, uma excegio RuntimeException seri langada.
u E vilido criar muitos objetos Threadusando o mesmo objeto Runnable como destino.

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.

TransigSo entre os estados dos threads (Objetivo 4.2)


E Uma vez que um novo thread for iniciado, ele sempre entrari no estado execut6vel.

E O agendador de threads pode alternar um thread entre os estados execut6vel e de execugio.

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

tr Um thread inativo nio pode ser iniciado novamente.

Sleep, yield e join (Objetivo 4.2)


E A suspensio 6 usada para retardar a execugio por um periodo de tempo e nenhum bloqueio seri liberado quando um
thread entrar em suspensio.

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.

Problemas do acesso simultaneo e threads sincronizados (Obietivo 4.3)


E Os m6todos slmchronized impedem que mais de um thread acesse o c6digo de um m6todo critico do
objeto simultaneamente.
tr VocA pode usar a palavra-chave slmchronized como o modificador de um m6todo ou para iniciar um bloco de
c6digo sincronizado.
4l I Copitulo 9: Threods

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.

Comunicando-se com os objetos atrav6s da espera e notificagno (Objetivo 4.4)


E O m6todo wait ( ) permite que um thread diga: "Nio hi nada que eu possa fazer aqui, portanto, coloque-me em
seu pool de espera e me avise quando acontecer algo que me interesse". Basicamente, uma chamada await ( )
significa "espere-me em seu pool", ou "quero ser inserido em sua lista de espera".
D O m6todo no t i f y ( ) 6 usado para enviar um sinal a somente um dos threads que estiverem aguardando no pool
de espera desse mesmo objeto.

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.

fl Todosostr€sm6todos-wait( )/notify( )/notifyall( ) -devemserchamadosdedentrodeum


conteno sincronizado! O thread ter6 que chamar wait ( ) /notify ( ) em um objeto especifico, e seri necessirio
que tenha o bloqueio desse objeto.

Threads em impasse (ObjetiYo 4.4)


I O impasse ocorre quando a execugio do thread 6 interrompida porque o c6digo est6 esperando que os bloqueios sejam
removidos dos objetos.
D O impasse pode ocorrer quando um objeto bloqueado tentar acessar outro objeto bloqueado, que por sua vez
esteja tentando acessar o primeiro objeto citado. Em outras palavras, os dois threads estio esperando a
liberagio do bloqueio um do outro; ou se.ia, os bloqueios nunca serlo liberados!
tr O impasse 6 inadequado. Nio tente cri6lo.

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

new Thread(new Messager("Wallace") ) .start () ;


new Thread(new Messager("cromit") ) .start ( ) ;
]
private String name;
public Messag:er(String name) { this.name = name; }
public void runO {
moqc:aol1 ).

message(2);
)
prj.vate slmchronized vold message(int n) {
System.out.print(name + \-" + n + " ");
)
JAVA 5 419

Quais dos seguintes sio resultados possiveis? (lr4arque todas as corretas)

A Wallace-1 Wal]ace-2 Gromit-1


B. Wallace-l- Gromit-2 Wallace-2 Gromit-1
C Wallace-1 Gromi-t-1 Gromit.-2 Wallace-2
D. cromit-1 cromit-2
E. Gromit-2 Wall-ace-1 Gromit-l Wal-lace-2
H Oc6digoniocompila.
G Ocorre umeffo no tempo de execu$o.
2. Dado:
public class Letters extends Thread {
nri rral- o Qf ri r
----.19f nalne;
nrrLrl i c T.of i- arc lQf rina n:mol t
L

this.name = name;

public void writeO {


System. out.print (name) ;
System. out . print (name ) ;
]
public st.atic void main(String[] args) {
new Letters ( "X" ) .start ( ),.
new Letters ("Y") .start( ) ;
)

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; } }

3. O seguinte bloco de c6digo cria um Thread usando um alvo Runnable:


Runnable target = new MyRunnableO;
Thread myThread = new Thread(target);
Quais das seguintes classes podem ser usadas para criar esse alvo , de forma que o c6dtgo arterior compile corretamente?
,t public class MyRunnable extend.s Runnable{public void runo {}}
B. public class MyRunnable extend.s object{public void. runo{}}
C public class MyRunnable implements Runnable{public void runO{}}
D. public class MyRunnable implements Runnabl-e{void runO {}}
E. public class MyRunnable implements Runnabfe{public void startO{}}
420 Copitulo 9: Threods

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.

5. Dado o c6digo a seguir,


1. class MyThread extends Thread {
2.
3. public static void main(String [] args) {

4. MyThread t = new l'tyThreado;


5. Thread x = new Thread(t);
6. x.startO;
t1

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

qual ser6 seu resultado?


A. A compilagno falharit
8.1..2..3..
c.0..1..2..3..
D.0..1..2..
E. Uma excegeo ocorrer6 no tempo de execugio.

6. Dado o c6digo a seguir,


L. class test {
2.
3. public static void main(String [] args) {

4. printAll (args) ;
JAVA 5 421

s. )

; public stati-c void printAll(Strins[] lines) {

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

9. Dado o c6digo a seguir,


1. public class WaitTest {
2. public static void main(Srring [] args) {
422 Copitulo 9: Threods

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?

,{, SuacompilagXofalhar6porqueaexcegaorllegalMonitorstateExceptiondewait( )nio6manipulada


nalinhaT.
B. 1.23
c13
D.L 2

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

contents . append (message ) ;


contents . append (" \n" ) ;
]
public String getcontentsO { return content.s.toStringO; }
)

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.

C. Sincronizando apenas o m6todo Ios ( ) .


D. Sincronizando apenas o m6todo getContents ( ).

E. Sincronizando log ( ) e getContents ( ).


F. Nada pode tornar 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

Qual6 o resrltado desse c6digo?

A Exibexefinaliza.
B. Exibex enuncafinaliza.
C ExibexY efinalizaquaseimediatamente.
D. Exibe xY comum atraso de 10 segundos entre X e Y.

E. ExibeXY comumatrasode 10000segundosentreX eY.


E Oc6digoniocompila.
n 4t |
G E langada uma ex@o
' no tempo de exeor$o.

14. Dado o c6digo a seguir,


class MyThread extends Thread {

ItyThread ( ) {

System. out. . print ( " My'Ihread" ) ;


)
public void run0 {
System.out.print ( " bar" ) ;

)
public void run(String s) {
System. out.println ( " baz" );

public class TestThreads {


public static void main (String [] args) t
424 Copiiulo 9: Threods

Thread t = new MyThread0 {

public void run0 {


q\rcfam
rJ D usrrr. nrrf
vsL r nri
v!
nfl
f !rurl! n l\ $ fnn" ) :

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; }

static void actBusyO {


try {
Thread.sleep(1000) ;

) 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

| 6. Dado o c6digo a seguir,


1. public class Test {
2. public static void maj-n (String [] args) {
3. final Foo f = new Foo O ;
4. Thread t = new Thread(new Runnable0 {
5. publ-ic void run ( ) {
6. f.doStuffo;
t. ]
B. ));
9. Thread g = new ThreadO {
10. public void runo {
11. f.doStuffo;
1 '> \

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.

E. Uma excegio ocorrer| no temPo de execuqio'


F.xis5
xis6
17. Dado:
public class TwoThreads {
static Thread laurel, hardy;
public static void main(String[] args) t
laurel = new Thread0 {
public void run0 {
System. out.println ( "A" ) ;
try {
hardy.sleep(1000);
) catch (Exception e) {
System. out.println ( "B" ) ;
i
q\rcfam
rf e uqrr. nrrl-
vuu nrint-ln
. v! rarLrlr I irf-") :

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

Respostas do teste individual


1. C est6 correta. Ambos os threads exibirio duas mensagens cada. wallace-1 deve vir antes de wallace-2,
e Gromit-1 deve vir antes de Gromit-2. Fora isso, as mensagens Wallace e Gromit podem vir em
qualquer ordem.
A, B, D, E, F e G estlo incorretas com base no exposto acima. (Objetivo 4.1)
2. E e F estio corretas. Tanto E como F fazem ambos os threads bloquearem no mesmo objeto, o que impedir6
g|! os threads rodem simultaneamente, e garantir|xxYY ou YYx*. E um ponco incomum bloquear em um
objeto como system. out, mas 6 perfeitamente vilido, e ambos os threads estio bloqueando no mesmo
objeto.
A nio pode garantir nada, uma vez que nio tem sincronizagio. B e D sincronizam em uma instincia da classe
Letters
- mas como existem duas instincias diferentes no m6todo main ( ) , os dois threads nlo bloqueiam um
ao outro e podem rodar simultaneamente,. resultando em saidas como XYXY. C nio vai compilar, pbrque esti
tentando sobrescrever run ( ) com um m6todo static, e tamb6m est6 chamando um m6todo nio-stitic
a partir de um m6todo estitico. G nio vai compilar porque System. out . class nio existe. Um literal de
classe deve comegar com um nome de classe. System. out 6 um campo, e nio uma classe, de forma que
System. out. class nio 6 um literal de classe vilido. (Objetivo a.3)
3. C est6 correta. A classe implementa a interface Runnable com um m6todo run ( ) v6lido.
A esti incorreta porque as interfaces sio implementadas, e nlo estendidas. B esti incorreta porque embora a
classe tenha um m6todo public void rin ( ) vilido, ela nio implementa a interface Runnable. D est6
incorreta porque o m6todo run ( ) deve ser publ ic. E esti incorreta porque o m6todo a ser implementado 6
run ( ), e nlo start ( ) . (Objetivo 4.1)

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 (

) deve declarar que langar6 a excegio rnterruptedException.


A resposta E est6 incorreta, mas estaria correta se a excegio rnterrupetdException tivesse sido tratada
(A 6 precisa demais). B est6 errada (mesmo se a excegio rnterruptedException fosse manipulada)
porquetodo c6digoJava, inclusive o m6todomain( ),6 executado emthreads. C est6incorreta. O m6todo
sleep ( ) 6 suatic, portanto, mesmo se for chamado em uma instincia, continuari a{etando o thread que
estiver sendo executado. (Objetivo 4.2)

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.

AsrepostasCrE"GeHestioincorretas. Osm6todos isrnterrupted( ) e interrupt ( ) slom6todosde


instAncia &Thread.Osm6todossleep( ) eyield( ) siom6todosstatic deThread.Dest6erradaporque
synchroni z ed 6 uma palavra<have e a estrutura slmchroni z ed ( ) faz parte da linguagem Java. (Objetivo 4.2)
9. D est6 correta . t e 2 rerio eibidos, mas nio haver6 retorno da chamada a wai t porque nenhum outro thread
nodficar6 o thread principal, portanto, 3 nunca ser6 impresso. O programa ficar6 paralisado na linha 7.

A resposta A est6 incorreta; rllegalMonitorstateException 6 uma excegio nXo-verifica&. B e C estio


erradas, 3 nunca ser6 exibido, jl que esse programa ficari em um estado continuo de espera, E esti incorreta porque
rllegalMonitorStateExceptionnuncaser6langadaj6quewait( ) serifinalizadoemargrdentrodeum
428 Cooitulo 9: Threqqs

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:

class TheCount extends Thread {


public void runO {
for(int i = 1;i<=100'++') {
System.out.print(i + .. ") -
1f(i t 10 == 0)
System. out.println (..Hahaha,, ) ;
try { fhread.sleep(1000); }
catch(InterruptedException e) {}

)
public static void main(String [] args) {
new TheCount ( ) .start ( ) ;
)
)

Exercicio 9-2: Sincronizando um bloco de c6digo


Seu c6digo pode ficar parecido com este quando concluido:

1. class Ins)mc extends Thread {


2. StringBuffer letter;
?

4. public Inslmc(StringBuffer letter) {


5. this.letter = letter;
6. )
'7.

8. public void runo {


9. slmchronized(letLer) {
10. for(int i = 1;i<=100;++i) {
11-. SysLem.out.print(letter);
]-2. )
l-3. System.out.println( ) ;
1,4. // Incrementa a letra em StringBuffer:
l-5. char temp = letter.charAt(0);
16. ++tempt
1,7. letter.setCharAt(0, temp);
l-8. )
1q l
20.
2L. public static void main(String [] args) t
22. StringBuffer sb = new StringrBuffer ( "A" ) ;
23 . new Inslmc ( sb) . start O ;
24. new fnslmc (sb) . start ( ) ;
25 . new Ins)mc (sb) . start ( ) ;
26- )
430 Copitulo 9: Threods
i.
.:;

*
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

I Usor Closses de Arquivos JAR

I Usor Closspoths poro Compilor


C6digo

a/ Exercicios r6pidos

P&R Teste lndividuol

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

Obletivos poro o CertificoE6o

Usando os comandos javac e java (Objetivo 7 .2 do Exame)


7.1 Dado am exemplo de c,6digo e un cen,lio, esmuer aidigo qae use or deuidos nodifcadores de acesso, dwlaragdes de pacotet e in$ntgdu
inportpara interagir con (atrauis do acessl 0u da beranga) o aldigo do exempb,
7.2 Dado am exemp/o de uma classe e uma linba dc comando, dtterminar o clmpnrtanentl espnadn en tempo dc exuugdo.

/
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 javac


O comando javac 6 usado parachamzr o compiladorJava. No Capitr:Io 5, n6s falamos sobre o mecanismo das assertivas e
sobre quando voc6 poderia usar a opgio - source ao compilar um arquivo. Existem muitas outras opg6es que voc€ pode
especificar ao rodar j avac; opg6es paragerar informag5es de depuragio ou avisos do compilador, por exemplo.Parao
ex^me, voc6precisar6 entenderas opg6es -classpath e -d, as quais abordaremos nasp6ginas seguintes. Al6m disso,6
importante entender a estrutura desse comando. Eis a visio geral:
javac [opq6es] [arquivos-fonte]
Existem mais algumas opg6es de linha de comando chamadas @argf i1es, mas voc€ nio precisard estud6Jas para o
exame. Tanto as [opg5esJ quanto os [arquivos - f onte] sio partes opcionais do comando, e ambas permitem
multiplas entradas. Seguem abaixo alguns comandos j avac v6lidos:
javac -he1p
javac -cl-asspath com:. -g Foo.java Bar.java
A primeira chamada nio compila nenhum arquivo, mas exibe um resulno das opg6es vilidas. A segunda chamada passa ao
compiladorduas opgSes (-classpath, aqualtemelapr6priaum argumento de com: . e -9),epassaao compilador
dois arquivos . j ava a serem compilados (Foo . j ava e Bar . j ava). Sempre que vocd especificar multiplas opg6es e/
ou arquivos, eles dever6o ser separados por espagos.

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

javac -d classes source/MyClass. java


Esse comando tamb6m demonstra como se seleciona um arquivo . j ava de um subdiret6rio do diret6rio aparit do qual
o comando foi chamado. Vamos agota dar uma r6pida olhada em como os pacotes funcionam em rcLagilo d opgio - d.

Suponha que n6s temos o seguinte arquivo . j ava na seguinte estrufura de diret6rios:
package com. wickedlysmart ;

public cl-ass Myclass { }

myProj ect

| - - <arrraa

ll
I I --com

|- -wickedlysmart

| --MyClass.java

| - -ur4DDED
^1 -^^^^
|

ll
| | --com
I

|- -wickedlysmart

| - (Myclass . class vem para c6)


| -
Se voc6 estivesse no diret6rio source, compilaria MyClass . j ava e colocaria o arquivo MyClass . cf ass resultante
no diret6rio classes/com/wickedlysmart com o seguinte comando:
javac -d . ./classes com/wickedlysmart/MyC1ass. java
Esse comando poderia ser lido como: "Pata de{inir o diret6rio de destino,volte para o ditet6rio myProj ect e depois v6
para o diret6rio cl-asses, o qual ser6 o seu destino. Entio, compile o arquivo chamado MyClass . j ava. Finalmente,
ponha o arquivo MyC 1 a s s . c 1 a s s resultante dentro da estrutura de diret6rios que bata com o seu pacote, neste caso
classes,/com/wickedlysmart." Pelo fato de MyClass . j ava estar em um pacote, o compilador sabia que
devia colocar o arquivo . class resultante no diret6rio cf asses/com/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 ;

public class MyCIass { i

myProj ect
I

I - -cnrrrna

| | --com
I

|- -wickedlysmart
I

l--uyclass.java
434 Cooitulo l0: Desenvolvimento

| --classes

E o seguinte comando (o mesmo do exemplo anterior):


javac -d /classes com/wickedlysmart/t"tyClass. java
. .

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

such file or directory)

Iniciando Aplicativos com iava


O comando j ava 6 usado para chamar a miquina vimralJava. No Capitr:lo 5, n6s falamos sobre o mecanismo das assettivas e
sobre quando voc6 podetia usar flags como - ea ou - da ao iniciar um aplicativo. Existem muitas outras opg6es que voc€ pode
especificar ao executar o comando j ava, mas, para o exame, precis da entender apenas as opg5es - c 1 a s spa th (e a sua irmi
gemea - cp) e - D, as quais iremos abordar nas pdginas seguintes. Al6m dissq 6 impottante entender a estrutura desse comando.

Eis avisio geral:


java [opc6es] class [argumentosl
Aspartes [opg6es] e [argumentos] docomandojava sioopcionais,epodemambastermultiplosvalores.
Vocd deve especiftcar exatamente um arquivo de classe para ser executadq e o comando j ava assume que voc€ esti
falando de um arquivo . cf ass, entao nao especifique a extensio . cl-ass nalinha de comando. Eis um exemplo:
java -DmyProp=myvalue MyClass x 1

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.

Usando as Propriedades de Sistema


Java 5 tem uma classe chamada j ava . util . Properties, que pode ser usada para se acessarinformag6es persistentes
de um sistema, tais como as versdes atuais do sistema operacional, do compiladotJava ou da m6quina virtualJava. Al6m
de forneceresse tipo de informagdo pa&iq voc6 podetambdmadicionare obteras suas pr6prias propriedades. Observe o
seguinte c6digo:

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

j ava. specif ication.vendor=Sun Microsystems Inc.


user. language=en
JAVA 5 435
java.version=1.5.0 02

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.

Lidando com Argumentos de Linha de Comando


Vamos voltar a um exemplo de se abrir um aplicativo e passar a ele argumentos a partir da linha de comando. Se tivermos o
seguinte c6digo:
public class CmdArgs {
public static void main(StringlJ args) {
int x = 0;
for(String s : args)
System.out.println(x++ + " element = " + s);

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

static public void main(StringlJ args)


public static void main(String... x)
static public void main(String bang_a_gongI J )

Procurando por Outras Classes


Na maioria dos casos, quando usafinos os comandos j ava e j avac, queremos que esses comandos procurem por
outras classes que serio necess6rias para completar a operagdo. O caso mais 6bvio 6 quando as classes que n6s criamos usam
classes fomecidas pela Sun noJ2SE (agora chamado tambem deJava SE), por exemplo quando usarnos classes de java.lang
ou j ava . ut i l. O outro caso comum 6 quando queremos compilar um arquivo ou executar uma classe que use outras
classes que tenham sido criadas fora do que 6 fornecido pela Sun, por exemplo as nossas pr6prias classes anterioffiente
criadas. I-embre-se de que, para qualquer classe, a m6quina virnralJava tetd de encontrar exatamente as mesmas classes de
suporte que o compilador j avac precisou encontrar em tempo de compilagio. Em outras palavras, se j avac precisou
teracessoajava.util .HasMap,entioocomandojavaamb6mprecisat6encontrarjava.util.HashMap.
Tanto j ava quanto j avac usam o mesmo algoritrno bisico de busca:
436 Copitulo I 0: Desenvolvimento
1. Eles t6m ambos a mesma lista de lugares (diret6rios) onde procuram por classes.
2. Ambos procuram nessa lista de ditet6rios na mesma ordem.
3. Assim que encontram a classe que estavam procurando, eles interrompem a busca por essa classe. No caso de as listas de
busca conterem dois ou mais arquivos com o mesmo nome, o ptimeiro arquivo encontrado ser6 usado.

4. O ptimeiro lugar onde eles procuram 6 nos diret6rios que contem as classes que v6m com oJ2SE.

5. O segundo lugar onde procuram 6 nos diret6rios definidos por classpaths.

6. Classpaths significam "caminhos de busca de classes". Eles sdo listas de diret6rios nos quais podem ser encontradas
classes.

7. Existem dois lugares onde classpaths podem ser declarados:


Um classpath pode ser declarado como umavari6vel de ambiente de sistema. O classpath declarado aqui 6 usado por
padrio sempre que j ava ou j avac sio chamados.
Ou entlo, o classpath pode ser declarado como uma opg6o de linha de comando paraj ava ou j avac. Classpaths
declarados como opg6es de linha de comando substituem o classpath declatado como vari6vel de ambiente, mas s6
persistem durante o tempo que durar a chamadz.

Declarando e Usando Classpaths


Classpaths consistem de um nrimero vari6vel de lociltzag6es de diret6rios, separados por delimitadores. Para sistemas
operacionais baseados no Unix, sio usadas banas notmais para construir localizag6es de diret6rios, e o sepatados 6 sinal de
dois pontos O. Por exemplo:
-classpath / com/ foo/ acct: / com/ foo
especifica dois diret6rios nos quais poder6o ser encontradas classes: / com/ f oo / acct e / com/ f oo. Em ambos os
casos, esses diret6rios ficam absolutamente ligados h.ruz do sistema de arquivos, que 6 especificada pela barra inicial. E
importante se lembrar que, quando especifica um subdiret6rio, vocd NAO est6 especificando os diret6rios acima dele. Por
exemplq na d eclaragdo acima, o ditet6rio / com NAO ser6 usado na busca.

OBSERVAE6BS pene O EXAME

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:

-classpath / com: / foo: .

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.

Vejamos agora como podemos usar com. f oo . MyClass em outra classe:


package com.foo;
public cl-ass MyClass { public void hi O { } }
E no pr6ximo arquivo:
import com. foo.MyClass; /,/ qualquer uma das importaq6es funcionarS
i mn^rf d^fi f^^ * .

public class Another {


void go O {
MyClass m1 = new MyClass O ; // nome-c6digo
com.
^^- roo.lvlyulass
I ^^ rr- -dl - m2 = new com. foo.MyClass O ; / / nome completo
m1.hi O ;
mz.hiO;
i
)
E f6cil se confundir quando vocd usa instrug6es import. O c6digo acima 6 peffeitamente vdlido. A instrugio import 6
como um nome-c6digo Para o nome totalmente qualificado da classe. Voc€ define o nome totalmente qualificado da classe
com uma instrugio import (ou com um coringa em uma instrugio import do pacote). Ap6s ter definido o nome
totalmente qualificado, voc€ pode usar o "nome-c6digo" no seu caidigo - mas o nome-c6digo est6 sempre se referindo ao
nome totalmente qualifi cado.

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

I Um subdiret6rio dentro de com chamado wickedlysmart


I Dois arquivos em wickedlysmart chamados Utils . cl-ass e Date . class
Finalmente, o diret6rio que tiver todos esses atributos precisa ainda estat acessivel (via um classpath) de uma das duas
seguintes maneiras:

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

2. O caminho at6 o diret6rio tem de ser corretamente relativo ao diret6rio atual.

Caminhos Relativos e Absolutos


Um classpath colegio de um ou mais caminhos. Cada caminho em um classpath 6 ou absoluto ou relativo. Um
6 uma
caminho absoluto em Unix comega com umabana (/) (no \7indows, seria algo como c:\). Essa barra inicial indica que este
caminho comega pelo diret6rio-raiz do sistema. Por estar com egando na,ruz, nio importa qual seia o diret6rio atual - o
caminho absoluto de um diret6rio 6 sempre o mesmo. Um caminho relativo 6 um que NAO comece com uma barra. Eis
um exemplo de uma estrutura de diret6rios completa, e um classpath:

/ (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?

dirA? dirB? dirC?


F6cil demais? E quanto i mesma pergunta, mas com o diret6rio atual sendo a ruz (/)? Quando o dttet6tio ataal 6 dttA,
enteo dirB e dirC
serio usados na busca, mas nio dirA (embre-se, n6s nio especificamos o ditet6rio atual
adicionando um ponto O ao classpath). Quando o diret6rio atual6 a raiz, ewmavez que dirB n6o 6 um subdiret6rio
diteto da raiz, nio ser6 feita busca em nenhum diret6rio. Ceno, e se o diret6do atual fosse dirB? Novamente, nio serd
feita busca em nenhum diret6rio! Isso ocorre porque dirBnio tem um subdiret6rio chamada dirB. Em outras
palavras,Javaprocurar6porumdiret6riochamadodirB dentrodedirg (enioenconuara),sempetceberquei6est6
em dirB.
Vamos usar a mesma estrutura de diret6rios e um classpath diferente:

/ (raiz)
I

| --dirA
I

|- -dirB

| - -airc

-cp /dirB : /dirA/dirB/dirc


Neste caso, em quais diret6rios seri feita a busca se o diret6rio atual for dirA? E se o diret6rio atual for o diret6rio-raiz?
Neste caso, ambos os caminhos no classpath s6o absolutos. Nio importa qual seja o diret6rio afual; uma vez que
caminhos absolutos estio especificados, o resultado da busca ser4 sempre o mesmo. Especificamente, s6 ser6 feitabusca
em dirC, independentemente do diret6rio atual. O primeiro caminho (/dira; 6 inv6lido porque dirB ndo 6 um
JAVAs 439
subditet6rio direto da niz,entdo nunca seri feita busca em dirB. E, repetindo mais uma vez,lm^vez que o ponto (.)
nZo foi colocado no classpath, o diret6rio atual s6 entrari na busca se por acaso ele fot descrito em algum outro lugar no
classpath (neste caso, dirC).

Obietivo poro o Certificogdo

Arquivos fAR (Objetivo 7.5)


7.5 Dado o nome comp/etamente qualifcado de ama classe distribuida dentro e / oufora de un arquiao JAk, canstruir a estr*tara de
diretdrios @mpiada para esa cl.asse. Dada ua exenplo de aidigo e um clasEatb, deterzinar se o clarpatb perrnitinl que o aidigo compile con
sucest0.

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

|- - (crie My,Jar. j ar aqui )

| --mYAPP

|- -uti1s
I

I l--Dates.class (pacote myApp.utits;)


| - -Conversions. clags n il

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

oBSERVAE6BS pene O EXAME

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.

Usando ..lirelllblext com Arquivos fAR


Quando voc6 instalaJava, € cnada uma enorme anote de diret6rios contendo coisas relacion adas comJava, incluindo os
arquivosJAR que cont€m as classes que v€m com oJ2SE. Como dissemos anteriormente, j ava e j avac t€m uma lista
de locais que acessam quando estio procurando por arquivos de classes. Entettada dentro da sua 6rvo rc de dtet6rios)ava,
existe uma 6rvore de subdiret6rios chamada jre/Lib / exL.. Se voc€ colocar arquivosJAR no subdfuet6rio ext, j ava e
j avac poderio encontr6-los e usar os arquivos de classes contidos neles.
Nio preciso mencionar esses subdiret6rios em uma instugio classpath - a procura nesse diret6rio 6 uma fungio interna
6
deJava. A Sun recomenda, no entanto, que voce somente use esse recurso para testes e desenvolvimento internos, e nio
pata software que pretenda distribuir.

oBSERVAQoBS pene O EXAME

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

Obietivo poro o Certificocdo


Usando lmportag6es Est6ticas (objetivo 7. I do Exame)
7'1 Dado att exernplo de cridigo e um cendrio, escreuer cfidigo qae ase os deuidos nodfrcadoru de acesso, dularapdu de pacotes e in$rapdet
importpara interagir com (atrauis do ace$o ou da herangQ o aidigo do exempl0.

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":

Antes das importag6es est6ticas:

public cl-ass Teststatic {


public static void main(StringlJ args) t
System. out . print]n ( Integer.lvl,i\X_VALUE ) ;
System. out. . println ( Integer. toHexStrj-ng (42) ) ;
1

l
i
Depois das importag6es est6ticas:

import stat.ic java. lang. System.out; // t


import static java. 1ang. Integer. *; // 2
.i
hl'1^'1 rU r^^n.qf rf i nTmnnrt I
I/UUf ^ ^'l --^
LrdDD ICDLOLdLIUTTTLIJUT L I

public static void main(String[] args) {

out.printl-n (MAX VALUE) ; // z

out . prj-ntln (toHexst.ring (42) ) ;


)
lt
Ambas as classes produzem a mesma saida:

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

Eis algumas regras para se usar importag6es estiticas:


I import sEaLic; static import est6incorreto.
A sintaxe deve ser
I Cuidado com membros static com nomes ambiguos. Pot exemplo, se fizer uma importagdo est|icapafaa
classe Integer e para a classe Long, uma referdncia a MAX-VALUE causar6 um erro de compilaglo' uma l'ez que
tanto Integer quanto Long possuem uma constante MAX-VALUE , eJava nio poder6 saber a qual
MAX_VALUE vocd est6 se referindo.
I Epossivelfazerwma'tmportagdoest6ticaemrefer€nciasaobjetosstatic,constaotes(embre-sequeelassio
static e final-). e m6todos static.

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.

Usando javac e java (Objetivo 7.2)


E Use - d para modificar o destino de um arquivo de classe quando ele for gerado pelo comando j avac.
E Aopgio - d pode criat, automatjcamente, classes de destino dependentes do pacote, caso o diret6ri o-ruz do pacote i6
exisa.

fl Use aopgdo -Demconjuntocomocomando java quandoquisetdefinirumapropriedadedesistema.


tr As propriedades de sistema consistem de pares de nome = valor que devem ser anexados diretamente ap6s -D, por
exemplo, j ava -Dmyproperty=myvalus.
tr Os argumentos de linha de comando sio sempre tratados como Strings.
u O argumento de linha de comando java nfmero 16 colocado no elemento 0 do array; o argumento 2 € colocado no
elemento 1, e assim por diante.

Procurando com java e javac (Objetivo 7.5)


E j ava e j avac usam ambos o mesmo algoritmo P^t^procurat por classes.
E A busca comega pelos locais que cont6m as classes que v€m com oJ2SE.
D Os usu6rios podem definirlocais de busca secund6rios usando classpaths.
0 Padr6es de Classpaths podem ser definidos usando-se vari6veis de ambiente do SO.
JAVA 5 443
E Pode-se declarat um classpath na linha de comandq e ele substirui o classpath padrio.

O Um mesmo classpath pode definir muitos locais de busca diferentes.


0 Em classpaths do Unix, sio usadas batas (/) p^x sepzu:^r os diret6rios que compSem um caminho. No rVindows, sio
usadas barras invertidas (\).
E Em Unix, sio usados dois-pontos (:) panseparar os caminhos dentro de um classpath. No Windows, sio usados
pontos-e-virgulas (r.
D Em um classpath, para especificar o diret6rio atual como local de busca, use um ponto (.)

El Em um classpath , uma vez encontrada uma classe, a busca 6 interrompida, de modo que a ordem dos locais de
busca 6 importante.

Pacotes e a Procura (Objetivo 7.5)


E Quando uma classe 6 colocada dentro de um pacote, deve ser usado o seu nome totaLnente qualificado.
E Uma instrugdo import fornece um nome-c6digo para o nome totalmente qualificado de uma classe.
D Para que uma classe possa ser localizada, o seu nome toalmente qualificado deve ter um relacionamento intimo com a
estrurura do diret6rio onde ela reside.

El Um classpath pode conter tanto caminhos relativos quanto absolutos.


0 Um caminho absoluto comega com uma / ou uma \.
D Apenas o diret6rio final de um dado caminho ser6 vasculhado.

Arquivos fAR (Objetivo 7.5)


Q E possivelatmazenar toda uma estrutura atb6rcade diret6rios em um mesmo arquivoJAR.
0 E possivel procurar em arquivosJAR usando-se j ava e j avac.
0 Quando voc6 inclui um arquivoJAR em um classpath, deve incluir nZo somente o diret6rio no qual se localiza o
arquivoJA\ mas o nome desse arquivo tamb6m.

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.

lmportag6es Estiticas (Objetivo 7. | )


B Voc6 deve comegar uma instrugio de importagdo estitica desta forma: import static
E Voc€podeusarimportagdesestiticasparaciaratalhosparamembrosstatic (vari6veis,constantesem6todos
statie) de qualquer classe.

Teste Individual

l. Dadas estas cl:Fses de diferentes arquivos:


package xcom,'
public class Useful {
int increment(int x) { return ++x; }

import xcom.*; // linha l"

class Needy3 {
public static void main(Srringll args) {
xcom.Useful u = new xcom.UsefulO; // Iin}ra 2

System.out.println(u. increment (5) ) ;


)

Quais afirmativas sio verdadeiras? (I\4atque todas as cortetas)


A Asaida60.
B. Asaida65.
444 Copitulo l0: Desenvolvimento

C. Asafda66.
D. Acompilagtrofdha.
E. O c6digo compila se a linha 1 fot removida.
E O c6digo compila sealinha2formodificadapara
Useful u = new UsefulO;

2. Dada a seguinte estrutura de diret6rios:


or9
| -- Robot.cl-ass
I

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

Qual comando, inserido independentemente na linha 1, compila? (I\4arque todas as corretas)


A. import static java.lang;
B. import static java. lang. Integer;
C. import static java. 1-ang. Integer. * ;
D. import stat.ic j ava. 1ang. Integer. *_VALUE,'
E import static java.lang, Integer.MAX_VALUE;
E Nenhuma das instrug6es acima usa sintaxe de importagio vilida.

4. Dado:
import static java. lang. System. * ;
JAVA 5 445
class _ {
static public void main(String. . . _A_V_) {
Cf rin^ < N/.
vut^rr: Y --

f or ( int x=0 i ++x


" _A_v_.length; )

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.

5. Dado o classpath padrSo:


/foo
E esta estrurura de diret6rios:
foo
I

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

B. Definir o diret6rio arual como xcom e depois chamar


javac -classpath B.java
C. Definit o diret6rio atual como test e depois chamar
javac -classpath xcom/B. java
D. Definir test e depois chamat
o diret6rio atual como
javac -classpath xcom B.iava
E. Definir o diret6rio arual como Eest e depois chamar
javac -classpath xcom:. B.java
446 Copftulo l0: Desenvolvimento
6. Dados dois arquivos:
package xcom;
public class Stuff i
public static final int MY-CONSTANT = 5;
public static int doSt.uff(int x) i return (x++)*x; )

import xcom,Stuff.*;
import j ava. 1ang. System. out ;

cl-ass User {

public static void main(Stringil args) {

new Userll.goO;

void goO { out.println(dostuff(MY_CONSTANT) ); }

i
Qual 6 o resultado?
a* 25

B. 30

c. 36

D. Acompilagdofalha.
E E langada uma exceg6o no tempo de execugio.

7. Dado que dois arquivos:


a=b. j ava
c_d. class
Estio no diret6rio atual, qual(is) chamada(s) de linha de comando podeiafrnahzar sem erros? (I\4arque todas as corretas)

A java -Da=b c_d


B. java -D a=b c_d
C. javac -Da=b c_d
D. javac -D a=b c d

8. Dados tr6s arquivos:


package xcom;
public class A i
/ / insira o c6digo aqui
)

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)

A void go() { System.out.println(..a.go"); }


B. public void goO { System.out.println("a.go"); }
C. private void goO { System.out.println("a.go"); }
D. protected void goO { system.out.println("a.go"); }

E Nenhuma dessas opg6es permitir6 que o c6digo compile.

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 .

B. O valor da prcpriedade aaa 6 bbb.

C. O valor dapropriedade aaa 6 ccc.


D. O valor daptopriedade bbb 6 aaa.
E. O valor dapropriedade bbb 6 ccc.

E A chamadando frnalizat6 sem erros.

10. Se existirem tr6s vers5es de MyClass.iava em um sistema de arquivos:


Avetsio 1em /foo/bar
Aversio 2 em / foo/bar /baz
Aversio 3 em / foo /bar /baz /bing
E o dasspath do sistema incluir:

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

I l. Quais afirmativas sio verdadeiras? (Marque todas as corretas)


.d O comando j ava pode acessar classes de mais de um pacote, a partir de run mesmo arquivoJAR.
B. Os atquivos JAR podem ser usados com o comando j ava, mas nio com o comando j avac,
C. Parapoderemserusadospor java,osarquivosJAR deuemsercolocadosnosubditet6rio / jrellibl extdentroda
dtvore de diret6rios J2SE.
448 Copitulo l0: Desenvolvimenlo

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.

| 2. Dados dois arquivos:


package pkg;
public class xit i
nrrl-r-lia crrina gluelt (String a, String b) { return a+b;
z
}

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

E a seguinte estrutura de subdiret6rios:

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

Respostas do Teste Individual


'l'. D est6 cotreta. O m6todo increment ( ) deve ser matcado com public para ser acessado fora do pacote. Se incre-
mentQ fosse public, C, E e F estariam corretas.

A e B sio saidas incorretas, mesmo se increment ( ) for publ i c. (Objetivo 7.1)


Z B,EeFsSoexigidas.AfnicamanekadeseacessaraclasseDog6atrav6sdeF,que6umainstrugiopack^ge,IJmavez
que voc6 s6 pode ter uma instrugio package em u1n arquivo-fonte, ter6 de obter acesso is classes Robot e Pet usando
instrug6es import. A opgio B acessa Robot, e a opgio E acessa Pet.

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.

4 B, D e F estlo incorretas com base no exposto acima. (Objetivo 7.1)


4. B est6 correta. Esta questdo estd usando identificadores v6lidos (mas inapropriados e esquisitos), importag6es est6ticas,
var-args em main ( ) e l6gica de pr6-incrementagio.
JAVA5 449
A, C, D, E, F eG estio incorretas com base no exposto acima. (Obiewo7,2)
5. Cesticorreta.ParaqueB.javapossacompilar,primeiroocompiladorprecisasercapazdeencontrarB.java.
Depois de encontr6-lo, precisa encontrar tamb6m A. cl-ass. Pelo fato de A. class estar no pacote xcom, o
compilador ndo a encontrat| se for chamado a partir do diret6rio xcom. Lembre-se de que - c las spath nio est6
procurando por B . j ava, esta procurando por quaisquer classes de que B . j ava precise (neste caso, A. class).
A, B, and D esteo incorretas com base no exposto acima. E esti incorreta porque o compilador nio consegue enconffar
B. j ava. (Objetivo 7.2)

6. D est6 corteta. Para importar membros estAticos, a instrugZo import deve comegar com: import static.

A, B, C e E estio incorretas com base no exposto acima. (Obietivo 7.1)


7. A est6 cotreta. -D nio 6 um flagde compi-lagio, eo parnome = valor associado com -D precisavirlogo depois de -D,
sem espagos.

B, C e D estao incorretas com base no exposro acima. (Objetivo 7.2)

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.

A B, D e E estio incorretas com base no exposto acima. (Objetivo 7.1)

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, B, C e E estio incorretas com base no exposto acima. (Objetivo 7.5)


11. AeDesteocoffetas.
B esti incorreta porque j avac
tambdm pode usar arquivosJAR. C est6 incorreta porqueJARs podem estar
localizados em . . . / jre / Iib / ext,
mas eles tambEm podem ser acessados se residirem em outros locais. E esti
incorreta, os arquivosJARmant€m estruturas de diret6rios. (Obietivo 7.5)
72. Hest6,coteta.

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.

Instalando e executando o MasterExam


A partir da tela de abertura voc6 poder6 fazer zinstzlagdo pressionando os bot6es do MasterExam. Isso iniciari o processo
de instalagio e criari um grupo de programas chamado "I*arnKey". Pata executar o MasterExam use as opg6es Iniciar I

Programas I karnKey. Para ter acesso i tela de abertura, clique em Runlnstall,

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.

Suporte t6cnico da LearnKey


Para solucionar problemas t6cnicos no software (instalagio, operagio, remogio de instalag6es) e para enviar perguntas
relacionadas a qualquer conterido do treinamento on-line da LearnKey, visite o site www:learnkey.com ou mande uma
mensagem de coreio eletr6nico para techsupport@learnkey.com.
JAVA2 453
Este livro foi impresso nas o{icinas gr6ficas da Editora Vozes Ltda.,
Rua Frei Luis, 100 - Pet6polis, RJ,
com papel fornecido Pelo editor.

Você também pode gostar