Você está na página 1de 480

Elogios ao Guia de estudos para programador

e desenuoluedor em Jaua

2 certif cado pela

S an@

como

"Kathy Sierra 6 uma das poucas pessoas no mundo que consegue fazer coisas complicadas parecerem murto simple;. E 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 .. rreza nio encontra paralelo na sunEd. s.* a""iar, h6 centenas i; -

;;;, frffi;; #.##T; assistido ;;; terem alunos que beneficiaram


ffi;#i.
se

de

a suas aulas"

de
Sun

,1

Victor Peters, fandador da Next Snp Education

Inslrutor Certifcado Jaua pela

aJq.

"Quero agradecer

**Jira

diiil;;;

sentir6 em uma sala de aula como se algu6m estivesse realmente lhe ensinando os conceitos e fria. As perguntas no final dos capftulos tambm slo MUTIo boas e estou certo de "ilde que aju&rio os candidatos a passarem no tesi. Fique alerta para esse livro incrivelmente astuto".

Kathy pelo EXCELENTE guia de esudos. O livro 6 bem.escrito,.informa especificamente o que voc6 ri'U.r.ro.*"-..."d,conceito 6 explicaio de maneiraclaracom autilizagio deum exemplo davidareal' Da
a

orr. foi escrito, voc6

se

maneiraformal

Atfred RaouJ

Desenuoluedor de Solugdu

na

IYeb

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

O exame de certificagio

de transformar com-plexidade em simplicidade ao oferecer um do que 6 necessirio para o exame da certificaqXo". percurso dirigido no aprendizado

"Ben demonstra uma aptidio comprovada e fantistica

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

habilidade em expressar claramente conceitos complexos aos que assistem consguem se tornar especialistas no que Ben tem a ensinar".

"por

sua

a seus

treinamentos' todos os alunos

DauidNdgq Diretor Geral, Ndge Astociatet

"Achei
ideal de

este

livro exrremamente 6til para ajudar o candidato a passar no exame. Ele foi muito bem escrito, com a qtrantidade

^Cit ALTAMENTE RECOMENDADO!"

come"."ri"r b.*-ftJ-oi

p"At*r. .or' qrr. .'oo.? se esquega

de que est6 estudando Para um teste

tio dificil'

-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


-Yaie Nagornl

ecertar 980/o(60 de 61). Esse sucesso nio teria sido possivel sem

este livro!"

,,EvfizoSCJp

emJulho de 2004 e consegui 957o (58/.6l).Kathy e Ben t6m um estilo incrivel de escrever' literdmente-grav"ra- ot.o.t..itos principais na minha cabega."
1.4

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

ww.altabooks.com.br e-mail: altabooks@altabooks.com.br

ESeitrrRl*|E wu{w.osborne.Eorn

JAVA

5V

ParaaComtrnida&Java

Sum6rio
capirulo | - DEclAnag6es
ldentificodores e

coNTRoLE DE AcEsSo....................................
.........

Polovros-chove........... Closses

Encontrondo Outros

..................'...... 2

Objetivo para a Certificagio............ ldentificadores e JavaBeans (Objetivos 1.3 e 1.4)


ldentificadores

............3
....--.-.-.. 3

Legais

...................

Objetivo para a Certificagio.............. Declarar Classes (Objetivo l. I do Exame)

..........6
.....-.'............... 6

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

Concreta

.....' | 0

Objetivo

paraaCertificag6o............

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

.............

.......... ll .'........ I I

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


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

t4
14

Membros Protecl e

Deiolhes de Detolhes de Deioult.... Vori6veis Locois e Modificodores de

Defoult Protect

.......
.................

19

Acesso

..................... 23

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


M6todos Abs M6todos

Synchronized (vor-orgs)

..'.......... 27

M6iodos com Listos de Argumentos Vori6veis

.......-...-.......--.. 27

Declorondo Primitivos e Iniervolos de Primitivos DeclorondoVori6veis de Voridveis de Vori6veis Locois (Automotic/Stock/Method)

Refer6ncio Instdncios Arroys

............. 30

...........' 30
........-.... 3l

.........

Declorog6es de

..........'.. 33

JAVA Voridveis e M6todos

5 VII

Stotic.........'.. ..........

................ 35 ...... 37

Declorondo Construtores, M6todos eVoridveis em um enum

CAPITULO

2'

ORIENTAAO A OBf ETOS...................................o.......................... 49

Objetivo para a certificagSo Objetivo para a Certificagio

.............
I do

Beneffcios do encapsulamento (Objetivo 5.

exame)

.........50
................ 50

Heranga, E-Um, Tem-Um (Obletivo 5.5 do Relacionamentos E-Uy e

Exame)

.....52 ............55

TEM-UM

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


Polimorfismo (Obietivo 5.2 do

Exame)

........58
.......58

Objetivo para a Certi{ica9io............ Subscrevendo / Sobrecarregando (Obfetivos

1.5 e 5.4

do

Exame)

..........60
................... 60
............... 63 ..... U ................ ................ .......

Chomondo o versOo do superclosse de um m6todo subscrito Exemplos de subscrilos de m6iodo v6lidos e ndo-v6lidos ................
Sobrecorgos

Chomqndo m6todos sobrecorregodos ............. Polimorfismo em m6todos sobrecorreqodo e subscrilo

v6lidos

&
65

&

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


Conversio de Vari6veis de Refer6ncia (Objetivo 5.2 do

Exame)

,.............68 ....68 .........7


|

Objetivo para a certificagio

.............

lmplementando uma Interface (Obietivo 1.2 do

exame)

................71

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


Tipos de retorno v5lidos (obfetivo 1.5 do

exame)

74 ........74
.....
.................
74

Tipos de retorno de m6todos sobrecorregodos............. A Subscrig6o e os Tipos de Retorno, e Retornos Covorionies

75

Objetivo para a certificag6o


Aspeclos bdsicos do

.............

Construtores e instanciaEio (Objetivos I .6 e 5.4 do

exame)

.........77
.........77
....................
77

construtor Codeiqdeconslrulores................. Regros dos construtores ..............

..............77 ................ 78
................
79

ldentifcando se um constru Como voc6 pode ter o certezo de que um conslrutor podr6o ser6 criodo? O que oconlecer6 se o conslruiuor do superclosse tiver orgumentos?...........

..........80

vlll
Objetivo para a Certificagio

........... Objetivo para a Certificagio............................. Acoplamento e Coesao (Objetivo 5. I do Exame)

Vori6veis e m6todos stotic Acessondo vori6veis e m6todos stotic

..........

................. 85 ................... 85

..........88
........ 88

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


J

Pilha e Heap

- Uma Revisio

.... 102

Objetivo para a certificagio

.............
I

Literais, Atribuig6es e Vari6veis (Objetivos

.3 e 7.6 do

Exame)

........ 103 ... 103

Literois de ponto Literois

flutuonte strings......... primitivos refer6nciq

.......1U
................ 05
.................... ]07
.......... I l0

Volores literois poro

Convers6o detipos

AtribuiE6es de vori6veis de

Usando umavari6vel ou elemento de array que nlo tenha sido Vori6veis de instdncio de tipo primiiivo e de obieto Voridveis de instdncio primitivos Vori6veis de insi6ncio de refer6ncio o obietos Vori6veis de instdncio de orroy Tipos primitivos e obielos locois (de pilho, outom6ticos)
Refer6ncios de Obietos

.......... I 13

.................

1.l3

..........-....... I 13

................... I 14 ...................... I l5
........... I 16

1ocois.......... ouiro

Airibuindo umo vori6vel de refer6ncio o

.................117

Objetivo para a Certificag6o............


Passando varieveis para m6todos (Objetivo 7.3 do

exame)

........ | | .......... I l8
............ l19

AlinguagemJavausaasemnnticadepassagemporvalor?
Objetivo para a certificagio
DedaraEio, construgao e inicializaEio de arrays (objetivo 1.3 do
Declorondo um orroy de tipos Construindo orroys Construindo orroys

exame)

...122
..... |-22
.....122

primitivos

unidimensionois multidimensionqis

...........123 .........124

JAVA

5 IX

lniciolizondo elementos em um loop ........... Declorondo, construindo e inciolizondo em umo linho Construindo e iniciolizondo um orrov on6nimo AtribuiEoes v6lidos poro os elemenlos do Arroys de tipos primitivos

..........

Arroys de referGncio AtribuiE6es de vori6veis de refer6ncio de orroys unidimensionois Atribuigoes de vori6veis de re{er6ncio de orroys multidimensionois Blocos de Iniciolizo96o ..............

............... o obietos

orroy

...................126 .............126 ...........127 . .............128


............ l2B

.............. ............

....................129 .|30 ...............


..............
'130

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


Usando classes wrapper (Objetivo 3. I do exame)

t33
133

Osconstrutoreswrqpper Os m6todos volueOf0 ... ...


Usando os utilitidos de conversio das classes

wrapper octol)

.........133 ............. ]34


.............. | 34 .l35

porseXrx$ e

volueOffl .

....

..

............

to/rxxStringfl (bose bindrio, hexodecimole Boxing,

.............136 .......... 137

::,

Onde Pode ser Usodo o

equolsfl Boxing

.................. l3B

Objetivo para a Certifica96o............


Sobrecarregando (Objetivos 1.5 e 5.4 do

Exame)

........ | 39 ...... 139


r39 r40
141 141

Sobrecorregondo do Moneiro Di{icil- Correspond6ncio de M6todos Sobrecorgo com Boxing e Vor-orgs Ampliondo Vori6veis de Refer6ncio Sobrecorgo no CombinoE6o de AmplioE6o com Boxing Sobrecorgo em CombinoE6o com Vor-orgs

142

Objetivo para a certificagio


Coleta de lixo (Objetivo 7.4 do

exame)
............... ............

.... 143
............ 143

Vis6o total do gerenciamento da mem6ria e da coleta de lixo

Quondo o coletorde lixo 6 execulodo?

Como o coletor de lixo funciono? Escrevendo um c6digo que torne os objetos explicitamente qualificados Anulondo umo refer6ncio ............... Reotribuindo umo voridvel de referGncio lsolondo umo refer6ncio ............... ForEondo o coleto de lixo Fozendo umo limpezo ontes do coleto do lixo - o m6todo finolize( Cuidodos relocionodos com finolizefl ......... . .

..............144 ..144

) ..

...........144 ......145 .............146 .......146

...

....... l4B .......... 148

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


Operadores Java (Objetivo 7.6 do
Operodores Operodores de Atribuigdo

exame)

.................. 162
......162 .........162

deAtribuiE6o Compostos

x
lguoldode de tipos pdmilivos lguoldode de vori6veis de referGncio lguoldode poro Enums Operodorde comporog6o inslonceo{ Erro de CompiloE6o de instqnceof .................

...........'..'..-..'164 ..."...... 165


r65 .......... 166 ...............-167

O Operodor

Resto

(%)

.'.........

168

Operodor de concotenoE6o de strings Acr6scimo e

decr6scimo Ooerodor condicionol. Operodores L6gicos

Exome!) OperodoresL6gicosdeAbrevioE6o................ Operodores l6gicos (que n6o s6o de obrevioE6o) Operodores L6gicos ^ e !...........
Operodores Bitwise (N6o Coem no Resumo para a certificagio

......... ]70 ..........'171 ...............172 ...................172 .....'........'172 ...........174 ..............174

cApiTULo 5 - coNTRoLE DE FLUxo, ExcEg6es


Objetivo para a ceftificagio .......
Escrevendo o c6digo usando instruE6es if e switch (Objetivo 2. I do exame)
Express6es v6lidos poro instruE6es if

E AssERTlvAs...o............. 183

t84
.......... 184
..................
186

............

A instruE6o cose Exercicio 5- | Criando

Breokeopossogemcompletoemblocosswitch......... defoult

.....190

.........192

Objetivo para a certificagio


Loops e lteradores (Objetivo 2.2 do

exame)

... 193 .............. 193

LoopforBdsico Declorog6oeiniciolizoE6o................ Loop for Bdsico: Express6o condicionol (booleono) LoopforBdsico: Express6ode iterog6o.. LoooforB6sico:Corocleristicosdolooofor.............. O Loop forAprimorodo (poro Arroys)
LoopforBdsico:

.................,l95
.....|95 .|95 .........

......196 ......196 .........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.............. Erros e ExceE6es Comuns (Objetivo 2.6 do Exame)


De Onde V6m os Exceg6es LonEodos pelo ExceE6es LonEodos Progromolicomente Um Resumo dos ExceE6es e Erros poro o

......214
...................214
.....214 .....................214 .................215 .............215

ExceE6es JVM

......... Exome

Objetivo para a certificagio Ti'abalhando com o mecanismo de assertivas


(Objetivo 2.3 do

...216
..........216

exame) ...............

Regros dos express6es de ossertivos

................218 ....219 ............219


219

ldentificodorx Polovro-Chove Usqndo o Versdo 5 de lovo e Compilondo um C6digo Alenio ds Assertivos

................ iovoc

Aiivondo ossertivos no tempo de execuc6o Desotivondo ossertivos no tempo de execuEdo


AtivoE6o e desotivoE6o

seletivo

...220 ................220 ..................22|.

N6o use ossertivos ooro volidor orqumentos de um m6todo o0blico.

Use os ossertivos poro volidor orgumentos de um m6todo ......222 N6o use ossertivos poro volidor orgumenios de linho de .......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 ....223

privodo. comondo

..................222

coloteroisl

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


Objetivo para a ceftificagSo

.............

String, StringBuilder e StringBuffer (Objetivo 3. I do


Strings s6o obietos Fatos importantes relacionados aos objetos String e a

exame)

.......238
......... 238 ...................238
.......................24
|

inolter6veis

Criondo novos slrings M6todos importon'les do closse

mem6ria

String.........

............242

..............242
......244

StringBufferx Usondo StringBuffere M6todos importantes das classes StringBuffer e

StringBuilder StringBuilder StringBuilder

.............245
......245

Objetivo para a Certificagio..


NavegaEio de Arquivos e E/S (Objetivo 3.2 do
Criondo Arquivos com o Closse File ............. Usondo FileWriter e FileReoder Combinondo Closses de E/S Trobolhondo com Arquivos e Direi6rios

Exame)

246
...............246
.................247 ..................249 ......................250
.......252

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


SerializagSo (Objetivo 3.3

do

Exame)

......254
........254

xil
Trobolhondo com ObiectOutputStreom e Gr6ficos de Usondo wrileObiect e Como o HeronEo Afeto o A SeriolizoEoo n6o 6 poro Est6ticos

ObiectlnputStreom Obietos reodObieci Seriolizog6o ................

................255 ...............256
............... 258

.........260 ...............262

Objetivo para a Certificasio.............. Datas, Nrimeros e Moeda (Objetivo 3.4 do


Trabalhando

Exame)
Nimeros

...263
.... ...............263 .................265 .............266 ............270

Orquestrondo Closses Relocionodos o Dotos e


A Closse A Closse

Colendor DoleFormol ...............

A Closse NumberFormot

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


Parsing, Tokenizag6

e Formatagao (Objective 3.5 do

Exame)

........27 | .......271

O Ponto Pr6-definido

Buscqs Usondo Melocorocreres ......................., Buscos Usondo Quqnti{icooores ................

,,,,.........'273 .............275
......275

Quonti{icodores Quondo Metocorocleres e Strings Locaf izando Dados atrav6s da Correspond6ncia de


Tokens e Delimitodores

Gononciosos.............. Colidem Padr6es... ................ .........

.....................276
....277

..............279
......279

Tokenizondo com String.splitfl Tokenizondo com Sconner

..............280

cApiTuLo7-GENfRlcosEcoNfuNToso.........o...o.ooo......o.o...................oo........zgs
Objetivo para a certificagio

.............

Subscrevendo hashCode( ) e equals( ) (objetivo 6.2 do


O que significor6 o n6o subscriEdo de equolsfl
lmplemenlondo um m6fodo equols( O conlroto de equols( )
Entendendo os c6digos de

exame)

.......296
...296
...............297 .. ...............298 ............300 ............300
......30'l

... ....... .

.................

hoshing ................ ... Objetivo para a certificag6o ............. Conjuntos (Objetivo 6. I do exame)
lmplementondo hoshCodefl O conlroto de hoshCodefl
Interfoces e closses chove do estruturo de

........302

.......304
.......... 304
........304

coniuntos

A Interfoce Se1.............. A Interfoce Queue........

.........307 ..........308

JAVA

5 XIII
309

Objetivo para a Ceftificag6

o .................. Usando a Estrutura dos Conjuntos (Objetivo 6.5 do

Exame)

....... 309

Clossificondo A Interfoce Comporoble Clossificondo com Comporotor

Coleg6es

.......

..

3l

.............. ClossificondocomoClosseArroys........ Fozendo Buscos em Arroys e em Coniuntos .............. ConverJendo Arroys em Listos e de Voltq em Arroys

................... 312

....3j3
.....315 ......315

..........3j7

................... Coniuntos. VisSo Gerql dos M6todos poro Lisl, Set, Mop e Queue......
Usondo o Cfosse PriorityQueue Vis6o Gerql dos M6iodos poro Arroys e

..................322

.....32g
..............324

Objetivo para a Certificagio Tipos Gen6ricos (Objetivos 6.3 e 6.4 do

Exame)

..........32s .........325

Criondo o suo Pr6prio Closse


Criondo M6todos

Gen6rico Gen6ricos

......342
......................345

cAPiTULo 8 - ctAssEs 1NTERNAS......................................................................


Objetivo para a certificagiio
Classes
lnslonciondo umo closse interno Referenciando a instincia interna ou externa de dentro da classe

36 |

.............
interna

.......362

................3U
...........365

Objetivo para a certificagio


Classes internas locais de

m6todo

...366
.............366
..................... 367

O que um objeto interno local de m6todo pode ou n?rofazer

Objetivo Para a ceftificagao .............


Classes internas

an6nimas

................ 368 ........369

Objetivo para a certificagio


Classes est6ticas

aninhadas

...373
....... 323

xtv CAPiTULO 9 - THREADS............o..o.........................................................................383


Objetivo para a certificagSo

.............

.......384
.......... 384 ............... 385

Definindo, instanciando e iniciando threads (Obletivo 4. I do

exame) Criando um thread

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


Estados e Transig6es de Threads (Objetivo 4.2 do

........393

Exame)

.......... 393

Criando

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


Sincronizando o c6digo (Objetivo 4.3 do

.398

exame)
o

....... 398

se um threod n6o puder obter Ent6o, Quondo Eu Preciso Closses Seguros em ReloEdo o

O oue ocontecer6

Sincronizor? Threods

bloqueio?

""""'405

..."' 405
407

"""'

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


lnteragio entre os threads (Objetivo 4.4 do
Usondo woit( ) em um

exame)
esperando

"409
...'.4
"
|3

Usando notifyAll( ) quando houver a possibilidade de muitos threads estarem

Loop

"

414

Exercicio 9-l: Criondo um threod e coloconoo-o em Exercicio 9-2: Sincronizondo um bloco de c6digo

suspensfio..........'...

"""""""'428 ..""""' 429

cApiTULO l0 - DESENVOLVIMENTO

........o.............o..o...............o..........oo............ 43 |

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


Usando os comandos iavac e java (Obietivo 7.2 do
Comoilondo com

......432

Exame)

...-..." 432
..............432

-o

Usondo os Propriedodes de Sistemo Lidondo com Argumentos de Linho de Comondo

"""""' """"""

434 435

Declorondo e Usondo

Pocoleseo

Closspoths Procuro

"""""""' 436 """""""'436

JAVA

5 )ry

Cominhos Relotivos e Absolutos

...... ....438

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


Arquivos JAR (Objetivo

7.5)

439 .....439
.............440

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

JAR...........

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


Usando lmportaE6es Est6ticas (Objetivo 7.1 do

Exame)

..............441 ..............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
Kathy Sierra foi desenvolvedora-lider do
exame SCJP paralaval. Sierra trabalhou como instrutora sAnior da Sun e' em 1997, fundou oJavaranch.com, a maiorcomunidade sobreJava nalnternet. Os seus livros recordistasdevendassobreJava
e ela 6

receberam v6rios prAmios da revista Sofrware Development Magazine, Java Champions da Sun.
6

ji

tamb6m membrofundador do programa

Bert Bates tem sido desenvolvedor-lider de virios exames de certificagio da Sun, incluindo o SCJP paraJava 5. Ele tamb6m 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
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 rlm dinAmico aprendizado, rico em diversas fottt.." conterido di treinamento multimidia existent., "o, "irrrro, "'q.r"l videoclips, 6udio, grificos totalmenfe animados e ilustrag6es animadas. O site do LearnKey na web 6 midias, como

O karnKey fornece conrerido

www.kamKey.aorrl

Os Astros da Revisio T6cnica


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.

Nio

Em primeiro lugar,

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

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

)O/II

Agradecimentos
Kathy e Bert gostariam de agradecer
as pessoas a

seguir:

r I r r r I r I

Topas incrivelmente esforgadas da Osborne: Tim Green, Jim Kussow, Jody McKenzie e Jennifer Housh por 1s egssoas 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. Os nossos anjos Solveig Haugland
e

Midori Batten, por virem nos salvar quando realmente esr6vamos em apuros!

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.
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).
Nossos melhores amigos
e

especialistas emJava, Bryan Basham,

Kathy Collina e SimonRoberts.

umexame.

As criangas, Eden e Skyler, por ficarem horrorizadas que os adultos - fora da escola - estivessem estudando tanto para

O chefe doJavaranch Trail, Paul \(heaton, por manter

melhor comunidadeJava da Internet.

Steve Steltin_g,\a;reZaffery, KimberlyBobrow, Keith Ratliffe o conhecedordeJavamais dedicado einspiradordo planeta,,JariPaukku.

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,

r r

Darren e Mary, obrigado por nos manter sios

por nos ajudar com

os nossos

novos amigos peludos, Andi

Kara.

Finalmente, Eric e Beth Freeman pelo incentivo continuo.

)o/il1

Preficio
O principal objaivo deste liwo
aJava 5.
6

ajud6-lo

a se

preparar

e passar

no exame de cenificagio SCJP da Sun Microrystems referente

t6picos que a maioria dos desenvolvedoresJava encontrarlo nos seus A boanoticia 6 que o exame tende a "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
representasse a certeza de que o candidato ente nde osfundanenns de io ex"*. foi qn diarquivos APIs, tais como aquelas usadas para E/S " "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

intengio dos criadores

estabelecidos pela Sun para o exame.

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 t-6picos em uma ordem mais adequada para o esnrdo do material. os repeumos parcialirente p"r" "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 I I I 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!

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!
As notas Ao trabalho descreverXo aspectos priticos de t6picos da certificagXo que podem nio aparecer no exame, mas que serlo riteis no mundo real.

possivelmenteirXo enfocadas no exame. NXo

Os exercicios priticos foram incluidos no decorrer dos capitulos. Eles o ajudario a aprimorar as aptid6es,que se limite a leios exercicios! Eles fornecem a pritica na execugio com a Aprender fazendo 6 uma maneira eficaz de aumentar sua capacidade. qual voc6 teri que estar familiarizado.
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 I I

O Resumo para

Certificagio 6 uma revisio sucinta do capitulo


6

uma reiteraglo dos pontos importantes

relacionados ao exame.

O Exercicio Mpido no finalde cada capitulo usado para uma revisio de ultima hora.

umalistade verificaEio com os principais pontos do capitulo. Pode ser

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.

O Teste Individual oferece perguntas que simulam

JAVA

5 XIX

lntrodu96o
Organizagio
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.
Este

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 retornasse ao livro v6rias vezes e fizesse uso de todos os m6todos que ele oferece para revisar o material:
se

voc6

L Z
3.

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.
Reteia todat as notas da segdo Alerta no Exame. a

criar o exame. Eles sabem com o que voc6

Lembre-se de que essas observag6es foram escritas por autores que ajudaram se deparar6 - e com o que dwe tomar cuidado.

Indiuidaais.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).
Refapa wTestet Faga ot exercicios.Voc6

4.

fez os exercicios quando leu cada capitulo? Se nlo os fez, faga-os agora! Esses exercicios foram 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
e

conhecimento totd da linguagemJava

nio

apenas

impraticiveis, geralmente associados. Mas esse exame tentarA avaliar seu as 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
a

de Associado,ProgramadoreDesenuoluedoresteo

associados com

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

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


tecnologiaJavap.ar3criaraplicativos\fleb.

as pessoas que estiverem usando o JSP $ava Server Pages) e o servlet da 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)

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

O exame de desenvolvedor

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


6

criando aplicativos com tecnologiasJava EE eJava \7eb

Services Developer Pack. Para fazer este exame,

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


a

Projetista Empresarial Cenificadopara

Tecnolo

1gr_J2EE

(SCEA)
passe no exame de

Essa certificagXo se destina a projetistas empresariais e,

ponanto, nio requer que o candidato

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

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

Na maioria de seus exames de cenificaglo,

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.

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.
Para desencorajar.a simples

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

sentir confurc ao retponderpergantas de

nilltipla
qw

escolha, use seu rascunho

para anotar as duat ou hs respostas que

conddera as mais pttadaeit e, em seguida, vtblinbe a @osta rascanho qaando uocljd tiuerpercorido 0 terte t/ma ueg

acha que possiuelmente

a corwta.

Aqai utui un

exemplo de

como

fcani

seu

2l.BouC

)3.AouC
exlrenamente titil paa uocl marcar a petgilflta e darpmsseguinenta Posteriorrzente, podeni retomar e resgatar inediatamente na onde 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,

Iso

uri

raciocinio de

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:

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

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

Um cenirio Uma

pequena descrigXo da tarefa que voc6 deverireaJizar.

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.

Um conjunto

de fragmentos rpresentando 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.

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

A maioria

JAVA

5 XXIII
o

oBSERVAe6rspeneonl<eME
No
que

n ,trto

mundo. Em geral, o nfhaare

fu questdes de arrastar-e-soltar, h,l um grande problena com o software de teste em muitos dos centros Pmmetric em todo lbe penzite reuisar at questdes que jd respondeu qilantas aerys quiw.

qautdu de arrastar-e-so/tar, entretanto, maitos candidatos tim relatado qae, se eles pedirem para reuer a questdo, o nfwaru 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.

No

caso das

aPaga a rerpo$a

pora traba/har

O cenhx de teste deueia lhefornecer o ruateria/ necesnirio para que uoei algurc casos, os centrosfomeeeram marcadores e qaadm in@ropriadog por urem peqilefllr 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.
Isso nos rerlete a ouho problema que os candidatos tdm re/atado. nas questdes

por escrito.

En

Dicas para a hora do exame


O tempo para conclusio do exame ser6 de quase trs horas.
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 com a Sun emwww.suned.sun.com, antes deprestar o exame.
as

VocA pode responder

perguntas em qualquer ordem


as

percoirido otlste. Nio hi penalidades para


Perguntaem branco,

respostas erradas,

tamb6m pode volt ar paramarcol suas respostas depois que tiver ponanto, 6 melhor marcar uma resposta do que deixar uma imediato. lembre como

Uma estrat6gia adequada


F.m seguida, voc6 poder6

ao fazer o exame 6 percorrJo uma vez e responder todas as perguntas que souber de

voltar e responder

as

outras. Responder uma pergunta pode fazer com que

se

responder

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. pedag6gico 6 simplesmente uma ficha 3X5 ou 4X6 com uma pergunta na frente e a resposta atris. Crie voc6 mesmo esses 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.
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.

Quando voc6

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
suas notas. Se estiver cansado de estudar, talvez possa comegar seu exame alguns
a

opornrnidade

pa ra

rever

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
tempo nessa leitura.
as

rapidamente.cada pergunta, observando seu

tipoi

perguntas do exame. Elimine as f6ceis, respondendo.as imediatamente. Leia assunto. Como diretriz, tente gastar^menos do que 25 por cento de seu

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.

voc6 nXo estiver totalmente ceno de sua reposta a uma pergunta, responda assim mesmo, mas marque a caixa Mark para indig.ar W9 fazer uma revisio.posterior nela. Caso voc6 fiqrr. i.ntpo, pelo menos ter6 forneci'do r pri*.ir" fve que lhe veio i cabega, em vez de deix6Ja em branco.
Se

r.*

t fjrt" e*

Em segundo lugar- rwise todg o teste, empregando

inteiro parecer dificil, voc6 saberi que nio poder6 gastar mais

pequenos blocos - Por exemplo, "Preciso responder L0 perguntas

percepglo que obteve na primeira leitura. Por exemplo, se o teste de circa de ,r- *irr.rto .- cada pergunta. Dirrij, o ..*po
a

cada 20

minutos".
a

Nesse estigio, provavelmente seri uma boa id6ia saltar as pergunras que exigirem mais rempo, marcando-as para leitura. Tente terminar essa fase antes de chegar a 5G6O por cJnto doiempJdo teste.

pr6xima

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
Se

dessa etapa, voc6 ter6 respondido todas as pergpntas do_teste, apesar de nlo te r ceneza em alzumas das respostas. ficar 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 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.

incluirem a opgio "N5o 6cotttpil"t".Eseja alenapara pistas

O grande final
Quando estiverconfiante de todas as respostas, termine o exame enviando-o para avaliagio. Depois, do que parecerio os 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.
Se LO

voc6 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. detalhe tamb6m estari em um relat6rio que teri sido impresJo auromaticaminte na mesa do inspetor do exam?.
especificas; em vez disso,

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.

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

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

,ro1r"rn.rrr..'Considere.se um po.tco
Se

mostrari que ireas vod precisa fortalecer.

-"is

esperanga. Tente aproveitar o que ganhou com a experiAncia e preParese Pararcntar informado. Voc conhece o fbrmato do teste um Pouco melhor e o relat6rio

fizer o teste mais uma vez sem demora, provavelmente voc Isso o ajudari a concentrar seus estudos na area certa'

se

lembrari

de

virias

das Perguntas que pode

ter errado.

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 I I I I
P&R
Decloror Closses e Interfoces Desenvolver Inlerfoces e Closses Abstroct Usor Primitivos, Arroys, Enums e ldentificodores Legois Usor M6todos Stotic, NomeoEdo JovoBeons e Vor-Args Exercicios R6pidos
Teste

lndividuol

2 Copitulo

: 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 i refrescar a sua mem6ria sobreJava, caso tenha estado afastado da Jinguagem por algum tempo.

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

Classe Um modelo que descreve os tipos de estado e de comportamento que os objetos do seu tipo podem ter.

ObietoNomomentodaexecugio,quandoaM6quinaVirtualJavaflavaVirtualMachine,ouJVlvf eflcontt^^p^l^.rrachave 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. 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.

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 Ferrari poderia substituir o m6todo acelerar ( ) .
a

todos os autom6veis, mas uma Jrlklasse

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

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.

de nomeagdo JauaBeans.

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.

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:

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 I

Identificadores Legais As

regras que o compilador usa para determinar se um dado nome 6legal.

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 I

Osidentificadoresdevemcomegarcomumaletra,umcifrio($)ouumcaracterdeconexdo,comoounderscore(_).Os
identificadores nio podem comegar com um nfmerol
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.

Os identificadores emJava si.o case-sensitive; foo

Foo sio dois identificadores diferentes.

Seguem alguns exemplos de identificadores legais e ilegais;


I nf a .

primeirq identificadores legais:

int gc,' int 2 w; int _$; int eis_um_nome_bastant.e_detalhado3ara_um_identif


Os seguintes sdo ilegais (agora voc

icador

ji

sabe o por qud):

int
i ht

:Jr;
-A .

int
I nr

e#;
I .

anE. /9,.

4 Copftulo

: Declorog6es e Conlrole de Acesso

Tobelo

1-l

Listo Completo de Polovros-Chove Jovo (ossert odicionodo em

.4, enum odicionodo em 1 .5)

abstract
char double

boolean

break

byte
^^nl_ i nlra

case

catch
do

class else
:Jvuv

const
extends

final
implements

default finally
import

float
instanceof
package

for int
hri rt^l-a

if
long

interface
protected
super
trans]-enE
enum

nati-ve

public
switch
Ery

strictfp
throws
asserE

short return synchronized this voLatile void

staEic
throw

while

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 originais 6e 66digo, e 80% do esforgo seri despendido na manutengio e nas melhorias subseqiientes do c6digo. Concordar

ftil

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

com um coniunto

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.
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 aParncia igualmente bagungada, usando apenas dois espagos depatdgnfo em vez dos quatro espagos do padrio Sun'

Dito isso, vocd ver6 que muitas das quest6es do exame nio seguem

N6s tamb6m bagungaremos nossas chaves de forma artificial, linha... oh nio! Por exemplo:

e,

em alguns casos, colocatemos v6rias declatag6es na mesma

1. class Wombat implements Runnable { private int i; 2, 3. public synchronized void runO i if (i*5 l= 0) { i++; i 4. for(int x=0; x<5; x++, i++) 5. 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:

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

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

ConstantesAsconstantesJavasdocriadasmarcando-sevariiveiscomostatic efinal.Elasdevemsernomeadas
MIN_HEIGHT / /ALTURA_MINIMA

usando-se leftas maifsculas com cafacteres underscore como seoaradores:

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

componentes criados por diferentes desenvolvedores. AAPIJavaBeans alguns fundamentos para o exame.

garantir que as ferramentas podetio reconhecer e usar 6 um tanto complexa, mas voce s6 precisar6 estudar

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

getSt.opped

ptopriedade for booLeana, o prefixo do m6todo getter 6 ou get ou is. Por exemplo, tanto ( ) quanto isstopped ( ) sio nomesJavaBeans vilidos pataum^ propdedade booleana.
deve ser

I O ptefixo do m6todo setter propriedade chzmada s i z e.

set.

Por exemplo,

setsize ( ) 6 o nomeJavzBeanv|Idopar^lma

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 argumento que represente o tipo da propriedade. I
As assinaturas de mdtodos

public,

com um tipo de retorno

void

um

getter

devem ser marcadas como pubL

retorno que bata com o tipo do argumento do mdtodo s et Em segundo lugar,

ter

ic, nio usar argumentos e ter um tipo de

pan

ptopiedade em questao.

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

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). 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 void setCustomerName (String s) public void modifyMyValue(int v) public void addXlistener{MyListener
oB SERYAQoBS pene O EXAME

m)

Alguns exemplos de assinaturas de m6todosJavaBezn inuilidar


t

/ / nrcai sa sFr nrrl-r1ic


t ylvvlve

/
m)
I

/
I

n6.o se pode
eLLv

usar 'modify'

/ / crra

da l- inn d. l-iStenef

diqque uoci precisa saber os identifcadoru legais para nzmes de uaridueis, mas as regras s6o ar nermas para TODOS os 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
O objetiuo
sd componentes Jaua.

um determinado componente Jaua deue ser nomeado. En outras palauras, uocd deue ser capaqde reconheeer qae um dado identifcador mesml qile e/e ndo se conforme a padrdes de nomeapdo. Se a qaestdo do exame estiuer lhe perguntando sobre conuengdes de nomeapdo
tzmente se um dado identifcador

d legal

iri

e ndo

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!, incluir o uso apropriado de dularagdes package e inport (incluindo irportagdu utriticas).
e

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

I r

56 pode haver uma classe

publ i c

em cada arquivo de c6digo-fonte.

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 { } precisa esrar em rr- ".qrlirro'd. c6digo-fonte chamado Dog. j ava. 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.
.,!

p
".\ \

\,

r I I

import e package aplicam-se a todas as classes denffo de um arquivo de c6digo-fonte. Em outras palavras' nio 6 possivel declarar multiplas classes em um atquivo e t6las em diferentes pacot;s, ou usar diferentes importag6es.
As declarag6es

nio-public. Arquivos que nio tenham classes pub 1 i c podem ter um nome que nio seja o mesmo de nenhuma
Um arquivo pode ter mais de uma classe
as regras

das classes do arquivo.

No Capitulo 10' discutitemos mais de talhes sobre


um recurso novo doJava 5, importag6es estAticas.

envolvidas com a dec langdoe o uso de importag6es, pacotes e

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
classe simples:

de

class Myclass { r I

}
de

Esse.c6digo iri compilat sem ptoblemas, mas yqgepqdelamblq adeio.nar rao-digga4tr-es antes da modificaderes ee dividemsnc duas..patsgp_r-ias : _!t_"-aiq..aores de acsso:

cla.r-ag,oda classe. Os

public,prolecLe4 pLivate. M-odificadoresquen6ose.r,eferemaacesso(incluindo strictfp,

inal eabstract).

Examinaremos os modificadores de acesso ptimeiro para que voc6 aprenda como restringir ou permitir acesso a uma classe o controle de acesso emJava 6 um pon.o --plicado porque pusterrr q\la$a ea.rtrok;de acesso (niveis dg qgesso) 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 nenhunraostrl-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 trs 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.
que criar'

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

i:i

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

,o*.grr/"roronlroa1sEt.c/ient.(Jtilities. Ainda

Acesso a Classes o que significa acessar uma classe? Q-uando dizemos

if gl-stgilfisa-Su-eaclAS!94-p-oi9g:9r-r1!tl.dlsp.g',rniq9coie4q;*

qug o g{dig-o-de uma classe.(a classe A) tem acesso a ou-tra-Gla-csE-E),

Criar uma instdncia da classe B.

8 Copftulo

: DecloroE6es e Controle de Acesso

a I
l-.i.a

E:ttdpfZd6Xq,!.(em outras palavras, tornar-se uma


Acessarcertos m6todos
e

subclasse da classe B).


e

da classe B, dependendo do controle de acesso desses m6todos vari6veis dentro .:_:,:::____,".;_r.

variiveis.

da classe

pritica, acesso signific a uisibilidadp. Se. a c-lasse A nio puder uera classeB,o nivel de acesso dos m(lodos e variiveis dentro 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 fazer aptova.Simplesmente marque a resposta 'A compilagio I6gica. Afin"i,i;;ai; -as o que fLrr ro ..rr,.-po "o falha'e passe para a questao seguinte.

publ i c dd alo-das as classes, de todos os pacotes, acesso.d .{ge.sqg Pirblico Uma declaragio de classe com ^p^lavr^-chave pfbliC?. Em outras palavras, lg/a.s as classesdo p_-ni;qersoJava QU) tdm acesso a uma classe priblica. No entanto, ndo -.l"sS.e 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?-@sp'$!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)


Vocpodemodificarumadeclzraglodeclasseusandoaspalavras-chavefinal"ab.sEract,oustricF.D.!sse;.
modiicadores exi*sfen-rm-adigio-a.qualqueffontrolede acesso existentnaslasse, entiovoc6 poderia, por eremplq declarar

UQ(!.classecomopublic efina]*ao.mesrf,rotempo.Nlar:r.dqd.semprequevocepodemisturarmodificadoresndo{F.fgtgqtesaacesso.Vocpodeusarstrictfp emcombinagiocomfinal,porexemplo,masniodevenunca,iamais, m tc rvmaclassecomof inal- eabstract aomesmotempo.Voc6ver6porquenasduaspr6ximassegSes.


Voc6 nio precisard saber como

strictfp funciona, entio nos concentfafemos apenas em modificar uma classe como final- ouabstract.Paraoexame,voc6s6precisasaberquestrictfp 6umapalavra-chavegguepodeserusadapara
significaquequa-lquet
Sem esse modificador, os

.nodifijarumaclasseouunm6tgdo*.m4snuocamavan|vel.Marcarumaclassecomostrictfp c6digo de m6todo na classe se conformar6 is regras do pa&io IEEET54pzrzpontos flutuantes.

JAVA pontos flutuantes usados nos m6todos poderio


se

classecomostrictfp,aindaassimvoc6poder6obterumcomportamentostrictfp
declarando o m6todo como strictfp. Voc tem assuntos mais importantes para se preocupar.

comportar de forma variante conforme aplataforna.Se ndo declarat a param6todosespecificos, Se voc6 nio conhece o pa&io IEEE 754,agotanio6 o momento pam aprend6-lo.

gg[gper

ClassesFinaisQuandousadanadeclaragilodeumaclasse,ap.flV3;3;9bave-final significaqueaclasseemquestdonao subcla,ssificada' Em outras palavtas, ne*gblqggclr-g1a.ss-eppd-ejas.rar,s aslenJef @erdar de) uma clasie f ina1, 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
irslegrent?g5g
.qem vo_qQ. s_4!e1.

lhedar6asegur"ogad.qoe-ningu6mpoder;,modtficata

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
classe

inal

paraseguranga,masapenasqo".rdotivercertezadequeasua

$,

EI?a-94 que a

su,a

de fato j6 disse tudo o que precisa ser dito nos seus m6todos. Marcaiuma.larr".orno f significa, na classe nunca ser6 aprimorada, ou mesmo modificada para uso mais especifico, por outro programador.

inal-

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
nadLrd6
Fsv.leJv

palavra-chave

inal

na declaragio:

^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 cert.Beverage class Tea e:itends Beveraqe{ 1 error


subcl_ass
Napr6tica,vocquasenunczciars"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 cefteza de que o dono de um Boxster lhe diria que o caffo dele 6. capaz de fazer coisas que o Subaru apenas ,.sonha em fazer". Observe a seguinte classe abstract:

abstract class Car { nri rr:f a dnrrl.l *_*-,e prlce;

'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, receber6 eros de compilagio como o seguinte:

se

voce tentar instanciar um Car em outro corpo de c6digo,

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
Pro.Clr_19-lyeptQes

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

subclasses que as subclasses concretas herdam funcionalidad.r, comportamentos especificos da subclasse.

ousetPriceO.Aocolocarm6todosnZo-abstract emumaclasseabsEract,vocediatodasas concletas (e concreto significa apenas nio-abs!.5agt) implementagSes de m6todos herdadas. A boa noticia 6
.

preiiii-

implementar apenas os m6todos que definem

(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
q..e voc6 tire vantagem do

abstract
e

polimorfismo,

(incluhdo interfaces, que serio discutidas mais adiante neste capitulo) permite lhe d6 o maior grau possivel de flexibilidade e extensibilidade. Voc6 aprender6

mais sobre polimorfismo no Capitulo 2.

Nig pqssivl

Uf"C -.laeSe-abgLract-'p:ecisa-ser

mar:catrtm^classe como abstract e f inaf ao mesmo tempo. Elas t6m significados quase opostos' subclassificada, enquanto que uma classe f inaf nlo deve ser subclassificada. Se voc

"it"..rrfombinagiodemodificadoresabstract nio ir6 compi-lar.

efinal,usadosparaumadeclatzglodeclasseoum6todo,oc6digo

Exercfcio

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 um pacote chamado food e a subclasse pode pertencer ao pacote def ault (significando que ela ndo ser6 colocada em acesso def ault. expLicitamente). Torne a superclasse pubf ice d i subclasse

abstracg

1.

Crie a superclasse da segrrinte maneuzl.


n:nlraa fnnd.

nrrhtic ehsl-recf class pruit{ vuvr+v

/* 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
subdiret6rio food.

o arquivo Fruit.class

no

Al Obietivo poro o CertificoE6o

Declarar Interfaces (objetivos


1'2' Desenaolaer aidigo qae declare uma

l.l

e 1.2 do Exame)
de c/asses aninhadat),

1'l Desenuolaer aidigo qae declare clases (incluindo clasus abttract e todas asformas 4rEiado de dukmgdet package e inport (incluindo impo,tapdet utriticas). nttrfott
Desenuoluer aidigo que

intefans e enum!, e inclua

o uso

qae dec/are uma classe abstract. Desenuoluer cddigo que ettenda

nri ,l^n

inplenente ou estenda uma ou mais interfaces. Desenuoluer c;digo abttract

Declarando uma interface


estabeleceria: "Essa 6 uma interf"ceboon.eable. Qualquertipo de classe que @plementar e;19r;y_q-r-9p6$go do_sm6todosbounce ) e setBounceFactor ) ".

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

.rru

irt.riu..

precisa concordar em

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

voce estara dizendo que as duas classes podem ser tratadas como "coisas saltitante-s", o qr..

gbi!9,uadadg-.tsltediferentes e-fortegaaelas.umacaracteristicaemiomum.Pore*emplJ,'vocpodequererquetantoa 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,
classe

As interfaces podem ser implementadas por qualquet clasEe, de,.quglguq 6rvore de heranEa. Isso permiur6 que voc use

quevocpodeusarparachamarosm6todosbounce(
relacionamento entre interfaces
e classes.

) esetBounceFor(

.-Jr.r"

traduzido por..coisas

)".AFigura1_1 ilustrao
O que vocd declara

interface Bounceable void bounce( ); void setBounceFactor(int. bf)

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

Oqueo
compilador
v6.

I
i

Class Tire implements Bounceable public void bounce( ) i... ] public void setBounceractor(int bf)t

O que a classe precisa fazer (todos os mdtodos precisam ser

implementados e definidos como


p{rblicos)

l-l A Re/ogdo Entre /nferfoces e C/osses 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 mtodos abstr-aqt. outro ponto em que as interfaces diferem das classes abstract 6 que elas
Figuro

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 ,. ' I

Todososm6todosdeinterfacesioimpliciamentepublic eabstract.Emoutraspalavras'vocenaoprecisadigitar
realmente os modificadores

publ ic

ou

abstract,

na declaragio do m6todo, mas mesmo assim ele sempre ser6

PubIic eabstract.
Todasasvariaveisdefinidasemumainterfacedevemserpublic,

static

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 synchronized. (Falaremos mais sobre esses modificadores a seguir) i 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. \ I r Os tipos de interface podem ser usados polimorficamente (consulte o Capitulo 2paramais detalhes)'
c

ou

A linha

a seguir 6

uma declaragio de interface v6lida:

public abstract interface RoIlable { } voce Digitat o modificador abstract 6 considerado redundante; as interfaces serio implicitamente abstract caso essas duas declarag6es sio vilidas e funcionalmente id6nticas: .ligite ou n6o abstract. 56 6 preciso saber que 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
]

Vocprecisalembrarquetodesosrn6todosdeinterfaces6opublic
definigio daintetface.

eabstract

independentedoqueestivetoa

procure m6todos de interface declarados com qualquercombinaglo que envolvapublic ou abstract, ou sem vilidas e modificadores. por exemplo, as cinco declarag6ls de m6todo a seguir, se declaradas dentro de uma interface, serio
idnticas!

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' / /abstract j6 est6 imPlicito

JAVA

13

i static void bounce ( ) t I private void bounce O { I protected void bounce ( ) ;


I
,.

/ interfaces definem m6todos de instAncias / / os m1todos de interface sio sempre public / / (iden)
/

Declarando constantes de interface


Voc6 pode inserir constantes em uma interface. tenham ace ! s !A qE "s.--!S?.cq_tls!.4ol9.

Ao fazer isso, gq-r?8!I?g::.g.p-4a,s-ap clajises que implementarem

interface

Ao colocar

as constantes diretamente n ainterface,qualquer classe que impleme ntar aintefiace ter6 acesso direto is constantes, como se as tivesse herdado.
de-

Yo4-ef9gi.tilg lembrar
nrrhlin

uma reg,ra fundamental para constantes de interfaces. Elas devem sempte se1

et=f i^ +inal.

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"dggde."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):

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

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; ant x = 1; statii i-nt x = 1; final int x = 1;


6,,L] i^ l ^r-!l^ 1luuaru >L4Lru ant x = 1;

// varece nao-static e n50-fina1, mas n50 6, // parece defaul-t, ndo-final e ndo-static, mas ndo 6! // Neo mostra final ou public // Ndo mostra static ou public
// Nao mostra final

4t*^1 ryuuras larrdr rrrt x = 1,. ^,,Ltl^

static final int x = 1 public static final int x = 1;


pualquer combinapio

/ Nao most.ra static // Nd,o mostra public // o que voc6 recebe implicitamente
/
.f

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

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
tle nomeapdl

enio-sLaLic

e,seapropriado,ilsarnomesdemdtodosqaeobedtpanaospadrdes

JauaBi^.

ZU,

tlisso, d.esenuoluer aidigo que declare e use ama lista de argunentos de extensio uaiduel. e agora

J6

vimos o que significa usar um modificadot em um a declangdo de classe, declatagdo de um m6todo ou uma vari6vel.

veremos o que significa modificar uma

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 mtodos e vari6veis normalmente receberem controle de acesso exatamente da mesmas forma, abordaremos ambos nesta segio.

Enquantoumaclasrcs6podeusardoisdosquatroniveisdecontoledeacesso(default
podem usar todos os quatro:

oupublic),osmembros

r I I I

public protect default 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 controle qoais voc6 dever6 usar o seu conhecimento sobre controle de acesso. Algumas quest6es testam v6rios conceitos de o desconhecimento de uma pequena parte que seja do assunto poder6lhe custar uma de acesso ao mesmo tempo, enrio questio inteira.
em uma classe ter acesso a um membro de outra classe? Por agora, ignore quaisquer diferengas entre m6todos e vari6veis. Se a classe A tiver acesso a um membro da classe B, isso significa que o membro da com voc6 classe B est6 visivel para a classe A. Quando uma classe nZo tem acesso a ouffo membro, o compilador vai brigar

O que signific

o fatode o c6digo

por tentar acessar algo que voc6 nio deveria nem saber que existe!
Voc6 precisa entender duas quest6es difetentes telativas ao acesso:

I I

Se Se

o c6digo de um m6todo em um classe pode acessarDm membro de outra classe 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

{ ,' rrnid rrqpZ.___ *-_-\zoo(,) t

nrrl.r'lin

Zoo

z = new ZooO; / / se a linha anterior compilar,

Moo

terS

acesso

JAVA

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
/ / mAraAn nrrl-r'] i a

l
O segundo tipo de acesso refere-se
aftavs da heranga.
a quais membros de uma supetclasse (se 6 que existem) uma subclasse pode acessar 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

Nio

esse

membro.

class Zoo {
nrrhl i n (f ri na nnnl Morhnrl uvvrrrLuarvs
// \\

I t

return
l

"Wow

baby";

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

em

A Figura

1,-2

faz a comparagdo entre uma classe herdando um membro de outra classe, e acessando um membro de outra

classe usando uma referncia de uma inst6ncia dessa classe. se concentra em se as duas classes envolvidas estao no mesmo pacote ou em diferentes. N6o se esquega, no entanto, q,te se apnipria classe A nio puder ser acessada pela classe B, ent6o nenhum Pacotes membro da classe A poderi, ser acessado pela classe B.

Muito do controle de acesso (ambos os tipos)

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

dostuff
)

goFast

( ( (

goFast

Convertible doThings(
)

Sportscar sc = new Sportscar( sc.goFas!( );

){

)t

Driver
doDriverSEuff (

Sportscar car = new Sportscar(

){

car.goFast( );

)t

Convertible con = new Convertible ( con.goFast( ),


)

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


Trs 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


package book;

herdado

Observe o seguinte arquivo-fonte:

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

i
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, independentemente de se ambas as classes estarem no mesmo pacote ou nio:

a subclasse

herda esse membto,

JAVA
n:^Lrd6 ^arf.

17

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 import cert . Roo; class CIoo extends Roo { public void testcloo ( ) { System. out . println (doRooThings ( ) ) ;
l
]

Roo se encontra

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 areferncia 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 referncia 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 foi declarado. Vamos fazer uma pequena modificagio na classe Roo apresentada em um exemplo o membro private
antedot.

cert; public class Roo { private String doRooThings ( ) { / / Imagine o c6digo divertido que entra aqui , / / a c]-asse Roo sabe disso
package
ratlrrn rrfrlnrr.

mas apenas

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:

Copitulo 1 : DecloroE6es e Controle de Acesso

package
i mn^rf +rrryv!

notcert;
D^^.

e ^6rf

cl-ass useAr{oo t

public void testlt o Roo r - new RooO;


qvcfam ^,,f nrintln

tt

// Ate aqui, tudo bem; a classe Roo 6 prlblica (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,
verdade. Um membro

private

e, no que diz respeito a qualquer c6digo fora da classe Roo, isso invisivel para qualquet c6digo fora da pr6pria classe do membro.

herdar um membro private da sua supetclasse? Quando um membro 6 declarado 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 mtodo 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 "rec6mdeclarado-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.

private,

se uma subclasse tentasse

nanlrana

rarf

public class Roo { private String doRooThings ( ) { // Imagine o c6digo divertj-do que entra aqui, / / orttra classe saber6 disso return "fun" .l
O m6todo

mas nenhuma

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 public void testClooO {

bem

aj-nda, a superclasse Roo 6 prlblica

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

Enbora

em ueqde acerd-/a diretamente. Os ndtodos de acesso conpatiueis con JauaBeans tm aforna get<noneDaPropriedade) ou, para booleanos, is<noneDaPropriedade> e set<nomeDaPropriedade>, efornecem um lugar onde uocd pode uerifcar e oa ua/idar antes de retomar ou

JAVA
modficar um ualar.

19

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

r'ffit"tt

con =

l'

nehr

convert.ible( );

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 pacote diferente.
Observe
nanl::ao narf

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
as duas classes

edefault

sioquaseidnricos,mascomumadiferengafundamental.Um

seguintes:

i f i z --- *--*JaEfon,.

public class OtherClass

20 Copftulo 1 : DecloroE6es

e Controle de Acesso
/ /

woiri festTr () { L
System. out
.

/ / O LsLv faro dc nio haver modificador v

/ indica acesso padrao


);

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

Como pode ver, o mdtodo

testlt

capitulos.

No method matching

testlt O found in class certification. Othercfass. o. testlt ( ) ,'


O deOtherClassporque

Pelosresultadosacima,vocpodeverqueAccessClassniopodeusarom6todotestlt
la, o compilador reclama, e n6s nao temos nem id6ia de quem sejam Daniel e Ftancesca.

test.It O temacessopadtio,eAccessClassnioest6nomesmopacotequeOtherClass.Assim,Accessclassn6opodev6def ault


e

Os comportamentos

protected

protect

diferem apenas quando falamos sobre subclasses. Se a palavra-chave

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.

fotusadaparadefinirummembro,qualquersubclassedaclasseque fazadeclangdopodeacess6-lo atrauisda

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

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 refetncia 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
o membro

umainstinciadasuperclasse.Emoutfaspalavfas,protecL =henn7a,Protect niosignificaqueasubclassepossatratar

usandoumarefernciaisuperclasse.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 malvola aqui>)

Detalhes de

protect
protect
0embre-se de que uma vari6vel de instdncia 6 um

Vamos dar uma olhada em uma vari6vel de instincia membro) de uma superclasse.

certif ication ; public class Parent { protected int x = 9; // acesso protect


package
I
acersiael a todas as outfas classes dentm do Pacote O c6digo acima declara a vari6vel x como protected. Isso ^totn certification, bem como herdduelpor gttaisquer subclasses defora do pzcote. Agora vamos criar uma subclasse em um pacote

JAVA
diferente, e tentar usar
a

21

vari6vel x (que a subclasse herda):

package
imnnri-

other; / / Pacote diferente


fiaal-inn Drranf.

carfi

class Child extends Parent { public void tesrlr ( ) { System. out . printl-n ( "x i_s \ + x) ;

problema; Child herda x


Sem

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

classe Parent.

package other,.

import certif ication. Parent ; class Child extends Parent {


^,,L1 yulf .i^..^ir fu vvfu !^^FTlLsDLru . () \/ {
L

// 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
System. out
l
O compilador alegtemente nos mostra qual
9'i:rr=n u -d . nl- ho- /alai fu. vurrLr/ Lrlf I .l i --'Jqva
6

printl-n ( "x is " + x) i

o problema:

other/Child.java:9: x has protected access in certification.Parent


Svsl-em otrt nrinf ln($X in
yqlgllur9-y.^l'

naranf

iq

rt r n v\.

^,u exceto

que um membro p ro t e c t tem, essencialmente, acesso de nivel do pacote ou padrio a todas as classes, vimos que as subclasses de fota do pacote podem herdar um membro prot.ect. Finalmente, j6vimos 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.

;;:.*belecemos
as subclasses.J6

Ainda h6 mais uma questZo que nao consideramos... Q"ul 6 a aparncia 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 referncia 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?
que a subclasse de fora do pacote herda o membro protect, ele (conforme herdado pela subclasse) torna-se 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.

Nio! Depois

private

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 modificadorprotected, passaremos para o acesso padrio, uma molezacomparado a protect.ed.

22 Cqpitulo

: 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. certif ication; public class Parent { int x = 9; / / Ausncia de modificadores de acesso / / indica acesso padrSo (de pacote)
package
)

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

t.

Pacote B

Convertible

[H-el *l
f *1"".

c;;ctb;l

E-tr-ll
Chave:

dofhings (

Sportscar sc = new Sportscar( ),

){

r------------1

l
Onde goFast 6
Declarado na mesma classe.

sc.goFast( );

I dot'tore( )( f I sorast( );I

It

L-.r-F:'=*[

I.

lnvocando goFast$ usando-se uma Refer6ncia A classe na qual goFastQ foi


declarada.

Invocando goFast$ usando.


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:

Chi1d. j ava:4

: Undefj-ned variable : x System.out.println("Variable x is " + x) t 1 error

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?

O compilador nos d6 o mesmo erro de quando um membro

package

certif ication

public cl-ass Parent{

JAVA

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 =


this.doMore(x);
]

7;

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
A partir da mesma classe A partir de qualquer classe do mesmo A partir de uma subclasse do mesmo

Pubtc Sim
pacote pacote Sim Sim Sim Sim

Protect
Sim Sim Sim
Sim,

Default Sim Sim Sim

Private
Sim

Nio
N6o

A partir de uma subclasse de fora do mesmo pacote A partir de qualquer


classe que

atrauis

Nio N6o

Nio Nio

da heranga

nio

seja

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 srie de outros modificadores que vocd pode usar em declarag6es de membtos. Dois deles j6 lhe sio fami-liares f e porque n6s os aplicamos a

- inal

abstract -,

24 Coollulo

I : Decloroc6es e Conirole de Acesso


declaraE6es de classes anteriormente neste capitulo. Mas ainda temos de dar uma

chroni

zed, nat

ive, strictf

ripida olhada em trans p, e depois uma longa olhada no grande modificadot - stat ic.

ient, syn-

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. mas voc6 deve us6-la com muito cuidado. Impedir que uma restrigio quanto a soUstitoigao propicia boa seguranga, 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 f inaf showsample ( ) , como o seguinte c6digo est|tentando f^zetl

inal-,

mas nio podemos substituit o mdtodo

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


f ileNumber
e

}
as

Argumentos de m6todos sio essencialmente o mesmo que variiweis locais. No exemplo_anterior,.

recordNuniber seguem todas as regras aplicadas avari6veis locais. Isso significa podem ter o modificador f inal-: public Record getRecord(int fileNumber, final int recNumber) { }

vari6veis que elas tamb6m

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

JAVA

25

emvez disso, com ponto-e-virgula. Em outras palavras, eIa ndo tem uru corpo de ndtodo. Voc6 marca um m6todo como quandoquerforgarassubclassesaforneceraimplementagloemquestao.Porexemplo,seescreverumaclasse 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.

abstract abstract

classeinvilida:

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
publi-c class I1lega1C1ass{

public abstract void dolt


)

classe

anterior produzird o seguinte erro


1

se

voc a tentar compiJar:

f11ega1Class. java:

: 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 compilar sem problemas:

abstract
{

sem nenhum m6todo

abstract.

O seguinte exemplo ir6

publi-c abstract cl_ass LegalClass void goodMethodO {


/
)
1
J

/ insira

um monte de

c6digos reais de implementagdo aqui

No exemplo anterior, goodMet.hod ( ) nio m6todo abstract:

abstract.

Trs dicas diferentes lhe dizem que

nio

se trata cle

um

I I I
nio

O m6todo nio est6 marcado como corpo de m6todo.

abstract.

A declaragio do m6todo inclui chaves, em vez de terminar com ponto-e-virgula. Em outras palavras, o m6todo tem um
O m6todo inclui c6digo de implementagio.
ser que a subclasse tambdn seia

Qualquer classe que estenda uma classe

abstract deve implementar abst.ract. A tegra 6 a seguinte:

todos os m6todos

abstract

da superclasse. a

Aprimeirasubclasseconcretadeumaclasseabatraet
supetclasse.

deveimplernentattoda.sosm6todosabst,ract da

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

Concretosignificaapenasnio-abstract,entao,sevoctiverumaclasseabstract estendendooutraclasseab-

public abstract class Car extends Vehicle { public abstract void goUpHill O ; / / X:-naa abstract
nrrhl i a rrni r{ dan--TLirrrrrrgD v vvrq uvvqr yqvrf -^^
/\ \/

I t

/ C6digo especial para o carro entra aqui

26 Copitulo I : Declorocoes e Controle deAcesso


I )

public class Mj-ni extends Car i public void goUpHilI ( ) t / / c6digo especifico para o Mini subir ladeiras
i
]

Entio, quantos mtodos tem a classe Mini? Tr6s. Ela herda


nunca ser implementado na classe Car (permanecendo

sio pfblicos e concretos (nio-abstract). Mas, pelo fato de goupHill

getType O e doCarrhings O , porque eles ( ) ser abst.ract na superclasse Vehicle, e abstract, portanto), isso significa que a classe Mini - como a
os m6todos

primeiraclasseconcretaabaixodeVehicle-precisaimplementatom6todogoupHill O.Emoutraspalavras,aclasse
Mini nio pode deixar
a

implementagio do m6todo

abstract
abstract.

mas a classe Car pode, porque Car, como Vehicle,6

pa:.aapr6xjrr'a classe abaixo dela na 6rvote dehetanga, 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 rd( | // requerido reverse( ) // requerido turn ( int rdhichway) //requerido

enable4wd( goForward( reverse ( )


/

) )

abst.ract gooffRoad(
I

//

rttrn{\
vsLLL

nin

.lJrtyrvttt.

imnlamenEado

Os m6todos
subclasse

abstract devem set implementados por uma nio-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 nioabs t rac t, entao ela precisa implementar o mdtodo ab -

enable4wd( \ // oPclonaL goOffRoad( ) // requerido

declarado na sua superclasse, SUV e precisa implementar tamb6m turn ( ) , que nio foi implementado por SL]V

stract

turn (int, whichWay) //requerido

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


Ptocure por classes concretas que nio fornegam implementag6es pata m6todos c6digo nio vai compilar:

abstracL

da superclasse. O seguinte

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 implementagio do m6todo abstract da superclasse, na verdade f oo int I ) da classe B parega ser uma 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. stracL
e

Um m6todo nio pode nunca, jamais, ser marcado como

private

ao mesmo tempo. Pense um pouco

abstract e f inal ao mesmo tempo, nem como ab- os m6todos abstract precisam ser implementados

(o

JAVA

27

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

que na pr6tica significa serem substituidos por uma subclasse), enquanto que m6todos f e ndo podem jamais ser substituidos por uma subclasse. Ou, dizendo de outra forma, uma designagio 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

inal private abstract inal-

abst;act

sio

abstract. stat ic.

Finalmente,voc6precisasaberqueomodificadorabstract
Abordaremos os m6todos seria inv6lido:

stat ic
(

mais adiante

.r.rt. obl.ti-ro,

niopodenuncasercombinadocomomodificador mas, por zgora,bastalembrar que o seguinte

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


<f ^li

and

abstract static void doStuff O; M6todos Synchronized


A palavra-chave
discutiremos isso

nized
tipica
se

s6podeseraplicadoamdtodos-ndoavari6viis,nemclasses,apenasam6todos.Umadeclarag6osynchronized
parece com a seguinte:

s)mchroni zed indica que um mdtodo s6 pode ser acessado por um thread de cada vez. N6s i exaustio no Capin lo 9, mas, por agora, tud; o que nos intereisa 6 saber que o modificador synchro_

public synchronized Record retrieveUserlnfo(int id) { } Voc6 precisa saber tambdm que o modificador synchroni zed. pode ser acompanhado
niveis de controle de acesso (o que significa que ele pode ser usado juntamente com

por qualquer um dos quatro


C, palavras-chave

modificadoras de acesso).

qualqueiu-" d", t

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, a "p..rui 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 Nativos O modificador native

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 Com

subjacente na qual aJ\M esti rodando. O inconveniente disso 6 que, se aplitaformasubjacente for capazde srrportar 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

strictfp forgaospontosflutuantes(equaisqueroperagoescompontoflutuante)aaderirem aopadriolEil,ET54. strictf p,6 possivel prever como os seus pontos flufuantes se comportarao,independentemente daplatafotma
11ma

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 I

argumentos Aquilo que voc6 especifica entre pardnteses quando

est6 inuocantlowm

m6todo:

dostuff("a", 2l;
rraid daQt-rrff

// estamos invocando dostuff, entdo a

&

2 sao argumenros

patdmettos Aquilo na assinatura dom6todo indica o que o m6todo deve receber quando forinvocado:

,r /Qf-]-^ s, l-r -\ f I roirro9 ^ l-nt a) \ j // estamos esperando dois

28 Copftulo 1 : Declorog6es e Conlrole de Acesso

// pardmexros: String e int


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

I I I I

Tipo var-atg Quando

p"ia-.t.o

declara um pardmeftovar-arg, vocd deve especificar o tipo do(s) argumento(s) que esse do seu m6todo pode recebet. @ode ser um tipo primitivo ou um tipo de obieto.)

Sintaxe b4sica Para declarar um mdtodo usando um parAmetro vat-arg, voc escreve depois do tipo um sinal de reticncias (...), um espagq e depois o nome do array que ir6armazenar os parimetros recebidos.

Outfos pardmetros E v6lido tef outfos parametros em um m6todo que use um vaf-afg. Lirnites dos var-args O var-arg deve ser o riltimo parametro
por m6todo.
na assinatura do metodo, e voc s6 pode ter um var-arg

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:

/ / sin1caxe incorreta void doStuff4(int x...) { } 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 toneladas de classe tem um construtor, e, se voc6 nio criar um explicitamente, o compilador vai criar um para voc. Existem 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 {


protected void
)

/ este 6 o construtor de Foo este 6 um m6todo


^^-6herr,
yvr

Foo

O {

com um P6ssimo nome,

rrilida

A primeira coisa
11rrl

a se reparar 6 que os construtores se parecem um bocado com m6todos. Uma diferenga fundamental 6 que n6o poie nonca, i"mais, ter um tipo de retorno.., Nunca! As declarag6es de construtores podem ter, no .orrrtr.rtor 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

invalidos:

cJ-ass Eooz
/

/ consLrutores vSlidos
}

Foo2O {

private Foo2 (byte b){} Foo2 (int x) { i


Fnal/inf v inl-

v)

t)

JAVA

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 I

Primitivos Um primitivo pode

long, double

ou f

l-oat.

maioria dos casos o seu valor possa

ser de oito tipos diferentes: char, boolean, byte , short , int , IJmavez declarado, o seu tipo primitivo nio pode nunca ser modificado, embota na
se

modificar.

Vari6veis de refetncia 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 referncia 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
l nf v

b,'
;

boof ean myBooleanprimit ive

/ decl-ara tr6s primi_tivos

j_nt

Em vers6es anteriores do

para o maior) byte, short, int e long, e que doubles sio maiores do que floats.

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

Voc tamb6m precisar6 saber que os tipos num6ricos (tanto inteiros quaflto de ponto flutuante) sio todos assinalados, 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

= negativo

ryi / \

I
bit de sinal

00100r.1

bits de valores:
byte: 7 bits representam 27 ou 128 valores diferentes: de 0 a 127 ou de -128 a -1

t__=\
bit

fe

valores

short

short: 1 5 bits podem representar


111110100000011

21

ou 327 68
-1,

valores: de 0 at6 327 67 ou de -327 68 a

Figuro 1-6

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) f6rmula -2&it" -r) pa112- calcular o intervalo negativo, e usamos -l&its - - 1 pata o intervalo positivo. Novamente, souber as duas primeiras colunas desta tabela, estar4 em boaforrnzpzra o exame.

se

voc

Tobelo

l-3

Intervolos de Primitivos Num6ricos Bits


Bytes

Tipo b)'t'
short
1nt

Intervalo Minimo

Intervalo Miximo
21

-1
1

t6
5Z
oz+

)15 .r3r
163

a15

)3r
L

long
float double

a63_L I

JZ
oz+

n/d n/d

n/d n/d

^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 intervalo para nimeros de ponto flutuante 6 complicado de determinar, mas felizmente voc6 nZo precisa sab6-los para o 64 bits, e um float armazena32). exame (embora 6 esperado que voc6 saiba que um double

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 65535 (o que significa qualquer coisa maior do que um tipo short. Embora tanto chars quanto suficiente p^tz ^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 refetncia 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 referncia:

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
de acerso

Podem usarqualquer um dos quatro niueis


trs nodficadoret de acesso)

(o que significa que eles podem ser marcados com qualquer um dos

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 sient

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-

zumavari|ve.Tdeinstincia.Primeiro,daremosumar6pidaolhadanadiferengaentrevari6veisdeinstAnciase
a

variiveis locais. A FiguraT-7 compara amaneirapelaqual os modificadores podem set aplicados


com varidveis.

m6todos em contraste

Vari6veis locais

Varidveis (nioJocais)

Mtodos

final

finaL
nrrhf i ^ yuvf+e

tinaL
nrrl.r'l'i ysvrre hr^|-a-l-aA Fr vevv nrirr.f-a D LdLIU a ues

protected

private st.at. ict 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 mtodo. 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 ^r^^"in o valor em uma vari6Lvel de instincia, a vari6vel propriamente dita s6 vive dentro do escopo do m6todo. 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- ,rvalor. 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 mtodo 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

'...-', t count = i; // Ndo vai compilarl Nao 6 possivel acessar count // de fora do m6todo logino

dnenmafhina/int

i \

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
O c6digo acimaproduz a seguinte saida:

loca1 variable count is


Mas por que

10
9

instance variable count is

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
hrr'|.\'l i IJu!fre ^ r'^.i A Deuer-s\frrL raf qi to vvfu (inf <.i zo\ ofzs/ I I

33

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


)

]
Entio vocd decidiu que - para melhor Iegibilidade
a

- voc qu er dx ^o parrametro o mesmo nome que a vari6vel de instincia para qual o seuvalor se destina, mas como resolver a cotseo dos nomes? Use a palavrz-chavethis. Apalavn-chave sempre, sempre, semPre se refere ao ob,eto sendo executado atualmente. O seguinte c6digo mosta isso na pretica:

this

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

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

Como

cizrwavai|vel

de refer6ncia a um array (declarar)

Como criar um objeto array (construir) 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, e

ArrayList
/eitara
e assim

mat muitat uerys uoci det/ard usar am dos tipos Collecion fu


classes Collection oferecen maneiras

j ava . ut i 7 (incluindo HashlvIap,


de acessar am objeto (para inurgdo, apaganentl,

TreeSet). At

na*fuxzueis

por diante) e, ao contniio dos ara1s, podem se expandir ou contrair dinamicamente i medida que uoci adiciona ou remoae 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 seguido por colchetes em um dos lados do identificador.
Derlaranclo um

iri

arrnazefl r (um objeto ou um primitivo),

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
/ / Pccnmond:dn

Thread [ ] threads; Thread threads [ ];


AO TRABALHO Ao

// val-i-do, mas menos leglvel

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

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


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.

O primeiro exemplo

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. e usar, e

No Capitulo 3, passaremos um bom tempo discutindo arrays, como os trnciahzar multidimensionais... Fique l-igado!

como lidar com arrays

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

inal- nSopode jamaisserrearibuidaparareferir-seaum objeto diferente. Os dados dentro do objeto podem ser modificados, mas a varidvel de referncia 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 avairdveldercfernciaparafaz-laserefeir a um obieto difetente. Decore isto: nio existem objetos f inal, apenas referdncias f inal. Explicaremos isso com mais detalhes no Capinrlo 3.
aobjeto f inal?Umavari6veldereferdnciamarcadacomo f
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
finrl

cfasse
rrnirl vvru

Baz
an/ Jv
\

o nrltodo
\ /

f inal

nio

classe Bat estende

Ba

rinaffid
variivel

so

classe Roo fi"al i"t sir.


42;

a uariduelf
=

inal nio

pode receber um valor novo, depois de ter sido criado o m6todo inicial (a

,roi-ffi"rrgsize

auibuigio inicial de um
(

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

JAVA

35

Vari6veis Transient
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.
Se

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

M6todos
Vari6veis

Uma classe aninhada dentro de outra classe, mas n6o dentro de um m6todo (falaremos mais sobre isso no Capitulo 8).
Blocos de inicializagdo

O que voc nlo pode marcar como s t

at i c:

Construtores (nio faz senado;os constfutores somente s6o usados para criarinstAncias)
Classes (a

nio

ser que esteiam aninhadas)

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

M6todos de classes internas


Vari6veis locais

vari6veis de instincias

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 OVERWHELMING ('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:

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
enum convengio de c6digos da Sun que detetmina que
fazJo aqui.
as

da

constantes tenham os seus nomes em mairisculas,6 uma boa id6ia

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 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!
v6 ver

Declarando um enum fora de uma classe:

enum

CoffeeSize { erc, HUGE, oVERWHELMTNG I

/ n5o pode ser / / private nem protect


/

class Coffee
l
J

CoffeeSize size;

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 { enum coffeesize {erc, uuce,


^l

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

colocagdo de

JAVA ponto-e-virgula no final da declatagdo do enum:

37

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 public static flnal CoffeeSize public static final CoffeeSize

BTG =

new Cof f eeSize (..BIG,'


HUGE =

0) ;

new CoffeeSize ('.HUGE,,,


OVERWHELMTNG =

I)

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

do tipo Cof f eeSi ze, e, como ver6 em um capitulo postedor, voc6 pode iterar atrav6s dos valor de um enum invocando o mtodo val-ues ( ) em qualquer tipo de enum. Q.,Tio se preocupe com isso neste capitulo.)

deCoffeeSj-ze iomofazendopatedieumarray

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 | .._^ ----r:-re1 de instancia vd!r4! / uttt4

private int ounces;


publj-c
ral-

uma

vari6vel de instdncia que o valor

de cada enum tem

int

getounces

Oi

rrrn

nrrndac.

i
)

cJ_ass colIee

CoffeeSize size;

cada instAncia de Coffee tem


enum CoffeeSize

um

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

println (drinkl- . size . getounces out.println (drink2. size. getOunces


.

(
(

))

));

exibe exibe

16

]
Os principais pontos a se lembrar sobre os constflrtores de

enums sio:

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 literal 8 ao construtor. (I',los bastidores, 6 claro, voc6 pode imag1nar que BIG passando o que usa um tamb6m 6 passado ao construtor, mas nio precisamos saber - nem nos importarmos com - os detalhes.)

NUNCA

int,

int

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 OVERWHELMING 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 OVERWHELMING de alguma forma substitua o m6todo getlidCode O .
Isso parece esttanho, mas voc6 precisa entender as regras bisicas de declaragio:

JAVA
(-nffcaQ i za I

39

BIG(8),
HUGE (r_0) ,

OVERWHELMING

bloco de c6digo que defina / / o "corpo" para esta constante public String getlidcode O { // substitua o m6todo / / definido em Coffeesize
(

16

tt

// t,

ininie

rrm

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

reEurn ounces;

public String
rafrrrh !rQrr.

get.LidCode

()

{ // este
/| / ^^1

m6t.odo

6 subsriruido
OVERWHELMING

/ pe!a consranre

/ / 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 palawas-chave reais e quais ndo sio.
a

palavras-chave, entao, certifique-se de que sabe identificar quais 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 abstract 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 miodos de todas as interfaces da drvore de heranga da interface que a classe est6 implementando.

40 Copftulo I : Decloroc6es e Controle

de Acesso

f inal-, abstract, synchronized e assim por Tamb6m vimos os outros modificadores, incluindo static, 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 poder6 ser modificada, mas o objeto a que se refere pode ser modificado. Voc6 viu que

f inal- nunca

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

E E D E E O fl E

Um arquivo de c6digo-fonte
Se

s6 pode ter uma classe

o arquivo de c6digo-fonte tiver uma classe priblica, seu nome terA que coincidir com o dessa classe.

O arquivo s6 pode ter uma instrugio de pacote,porm,v6izs de importaqdo. A instrugeo de pacote (se houver) deve ficar na primeira linha (fora os comentarios) do arquivo de c6digo-fonte. A instruq6o de importaqio
Se nao
(se

houver) deve vir depois do pacote


as

e antes da

declaragio de classe.

houver instrugio de pacote, arquivo de c6digo-fonte.

instrug5es de importagio terZo que ser as primeiras (fora os comentArios) do

As instrug6es de pacote e de importagio slo aplicadas a todas as classes do arquivo.

O arquivo pode ter mais de uma classe nio priblica.

JAVA

5 4I

Os arquivos que nio tiverem classes pfblicas nio apresentario restrig6es de nomeagio.

Modificadores de acesso a classe (Objetivo l.l) 0 ga ts 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 E

As interfaces podem ser implementadas por qualquer classe, de qualquer drvore de heranga.

A interface

como uma classe 100%o abstract, e ser6 implicitamente

modificadot abs t rac

abstract

caso

voc6.ligite ou nio o

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) implementa (mas nio precisa declarar as exceg6es da interface).

o tipo de retorno exatos dos m6todos que

E Umaclassequeestiverimplementandoumainterfacepodeelapt6priaserabstract. E Umaclassedeimplementagioabstract nloprecisaimplementarosm6todosdainterface(masaprimeirasubclasse


concreta pfecisa).

E E E E

A classe

s6 pode estender uma classe (sem heranga

multipla), por6m, pode implementar v6rias.

As interfaces podem estender uma ou mais interfaces. As interfaces nio podem estender uma classe ou implementar uma classe ou interface.

Quando ftzer o exame,vetifique l6gcas do c6digo.

se as declaragSes de

interface e classe sio v6lidas antes de verificar outras

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

Um membro

protect

classe do pacote da subclasse, exceto Pelas

herdado por uma subclasse de outo pacote nio pode ser acessado por nenhuma outra pr6prias subclasses dessa.

Vari6veis locais (Objetivo 1.3) D As declarag6es de varidveis locais (de m6todo, autom6ticas, de pilha) nio podem ter modificadores 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.

de acesso.

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
mas

opcional,

nio foram implementados. t rac

E E

Os m6todos abs

terminam com urn ponto-e-virguIa, e ndo chaves.

H6 tr6s maneiras de identificar um m6todo n6o

E E E

O m6todo ndo 6 marcado

abstract como abstract.


as chaves.

O m6todo possui chaves. O mdtodo possui um c6digo entre

E Aprimeiraclassenio-abstrata(concreta)aestenderumaclasseabstract deveimplementartodososmdtodosabstract 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

43

E D

O modificador

nat ive

s6 6 aplicado a m6todos. s6 6apJicado aclasses em6todos.

Omodificadot

strictfp

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,
m6todo var-arg.

o chamado

O E E

Um parimetrov^r-zrgedeclarado com

sintaxe tipo... nome; por exemplo:

doStuff (int...

x) {

Um m6todo var-arg s6 pode ter um parim etro var'zlrg. 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".

As variiveis

f inal

apresentam as seguintes propriedades:

E E

Nao podem ser reinicializadas, uma vez que tiverem um valor atribujdo.
As vari6veis de refer6ncia

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 referncia 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
attay.Por exemplo,
se

Horse estender Admal,entd,o um objeto Horse pode ser colocado em um arav di Animal.

do

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, protected ou private.

44 Copitulo I : Decloroc6es e Controle

de Acesso

E E E E

Os

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

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

int

enum podem enum

ter argumentos e podem ser sobrecarregados.

nuncapodem ser chamados diretamente no c6digo.Eles sio sempre chamados


6.

automaticamente quando um enum

irttcidtzado.

"
r':f

deum enum

opcionar Ambos sio v6ridos:

*: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.) 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
3. Qual das seguintes afirmativas
^t ^a^^

5 45 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.
JAVA

4. Quais das seguintes sio declarag6es v6lidas? (Marque todas as corretas.) A. int gx; B. int 123;

int _1,23; D. int #dim;


C.
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. 3. 4,
Fl

public static

voi_d

main(String tJ args)

doStuff (1) ; doStuff (7,2)


l

5.

/ insira c6digo

aqui

Qual destas opg6es, inseridas independentemente na l-inha 6, ir6 compilar? (N{arque todas as correras.)

A. static B. static C. static D. static E. static

void void void void void

doStuff(int... doArgs) { } doStuff (int [ ] doArgs) { } doStuff(inr doArgs...) { } doStuff(int... doArgs, int y) t i 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

: DecloroE6es e Controle de Acesso

8. Dado o c6digo: 1. enum Animals i 2. DOG("woof"), CAT(*meow"), FISH("burble")

3. 4-

String sound; Animals(String s) { sound = ",

6. class TestEnum { 7. static Animals a; public static void main(StringtJ args) { 8. 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 D. A compilagio
falha devido a um erro na linha 2 falha devido a um erro na linha 3

E. A compilag6o falha devido a um ero

naltnha 4

F.

A compilagio falha devido

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

O c6digo compila.
Se apenas a Se apenas

linha 1 for temovida, o c6digo compila.

ahnha3 for removida, o c6digo compila. linha 5 for removida, o c6digo compila.

D.

Se apenas a

E. F.

Se as Se as

linhas 1 e 3 forem removidas, o c6digo compi,la. linhas 1,3 e 5 forem removidas, o c6digo compila.

Respostas do Teste Individual


1.
da sua interface.

C e D estio coffetas. C esti correta porque uma classe abstract nio precisa implementar nenhum dos m6todos 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

47

3. A 4.

C estd correta.
est6

incorreta porque

as classes

s6 "herdam de" ouffas interfaces.

implementam interfaces, mas nio as estendem. B est6 incorreta porque est6 incorreta com base nas regras anteriores. (Objetivo 1.2)

as

interfaces

A, C

eG

slo identificadores v6lidos.


e

B est6 incorreta porque um identificador nio pode comegar com um digito. D, E identificadores devem comegar com $ ou uma letra. (Obietivo 1.3) 5. 6.
B
e

F estao incorretas porque os

D usam

os prefixos v6lidos

A, C e E estao incoffetas

get e is. potque add, delete

put nio sio nomes

de prefixosJavaBeans padr6es.

(Obietivo 1.4)

Ae E usam sintaxe vat-atgv6Jrdz.


BeCusamsinaxevar-arginv6lida,eD6invilidoporqueovar-argdeveseroultimoargumentodom6todo(Obietivo1.4)

7. A

sdo declaragSes de arrays corretas;

um array tridimensional.
ser que voc

C, D e F estao incoffetas, ndo 6 possivel incluir o tamanho do seu array em uma declaragdo a n7'o instancieoobjeto anay.E usaumasintaxedeinstanciamentoinv6lida. (Objetivo 1.3)

tambdm

8. 9.

A estd correta; enums podem ter consffutores B, C, D, E


e

vari6veis.

F estio incorretas; todas essas linhas usam sintaxe correta. (Objetivo 1.3)
5 6 a rinica que

D e F estio corretas. A linha

nio vai compilar, porque

os

enums nio podem

ser locais a

um m6todo.

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 I I I I I I I I l/
P&R
Decloror Interfoces Decloror, Iniciolizor e Usor Membros
de Closses

Usoro Sobrecorgo eo SobrescriE6o


Desenvolver Consirulores Descrever o Encopsulomento, o Acoplomenlo e o Coes6o

Usoro Polimorfismo
Relocionor Modificodores e HeronEo Usor Conslrutores de Superclosses e Conlrutores Sobreco rregodos

Usor ReloE6et 6-UU e TEM-UM


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

\.roleTtvo poro

nl

. r.

..1. 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. promessas/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:
Esse cenario ressalta duas das

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

(umm6todosetsize(int

a),porexemplo)e,emseguida,protegeressavari6vel
essa alt eragdo

com, digamos, um modificador de acesso private. Por6m, logo que voc6 fizer

em

seu

c6digo, innnonper,l

o dos

A capacidade de fazrr alterag6es no c6digo de implementagio seminterromper o c6digo das outras pessoas que o estiverem 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.
usando,
Se

voc6 quiser obter f6cil manutengio, flexibilidade e extensibilidade (e 6 claro que voc6 quer), seu projeto deve Mantenha suas variiveis de instAncia protegidas (com um modificador de acesso, geralmente

incluir o encapsulamento. Como fazer isso?

I I I

privat.e).

Crie m6todos de acesso public, e exija que o c6digo chamador use diretamente a vari|vel de instAncia.
Para os m6todos, use a conveng1o de nomeagioJavaBeans de

esses

m6todos, emvez de acessar

seLcsomeProperty>

get<someProperty>.

JAVA

5 5I

A Figura

2-1 ilustra o conceito do encapsulamento, forgando os chamadores do c6digo poderem acessar as variiveis diretamente.

usar m6todos em vez de

Chamamos os m6todos de acesso de


pomposos
acusadorcs
e

capturadores e confgaradores.
as

modifcadorcs. (Pessoalmente,

nio gostamos dapalavra

voc6 os chamar, eles serio os m6todos que

apar6ncia simples, e 6 provivel que voc6

ji

outras pessoas os tenha usado:

embora algumas pessoas prefiram os termos mais modfiear.) Independente da maneira como terio que usar para icessar suas varilveis de instincia. Slo de

B b = new BO;

int x = b.getSize0; b.setsize(34);

Qretsize

()

setSize

()

St.rinq s = b.getName0;
b.setName( "Fred')
;

getName setName

()

()

Color c = b.getcolorO;
b. set.Color (b1ue)
;

getcolor
set.Color

() ()

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 privados; apenas os m6todos acessadores

sio marcados como 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!
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

Que

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 left = leftNum; right = leftNum/3;
)

IeftNum) i

// 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 vari6vel de referAncia testada for do tipo ao qual est6 sendo comparada. Este c6digo:

se a

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

53

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
E
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 r

Para promover a reutilizagilo de c6digos 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


]
// maiq c6dia

shape,, ) ;

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

-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.
Repare que a classe 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 vvs4Y crldio6


)

class TilePiece extends


n"l.'l yulfre in rzniA vvfs na|-aAi:nanf Yeu^sJqeslru\/

GameShape {
1\ I
L

System.out.println("getting adjacent tiles"


J

//
\

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

(player) ;

(tile) t
do9hapes(GanshaDe shape)
(

public static void


)

shape . displayShape

i
Gera a saida:

displaying displaying

shape shape

JAVA

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 piavraschave 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 / / o qte pode incluir tanto m6todos quanto vari6vers
] Ocarro(Car)6umtipodeveiculoffehiclQ,pofianto,aArvoredeveterinicio

de Car,

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 Car
6 a zuperclasse de

Car.

6 a subclasse de

Vehicle.
Subaru.

Car

6 a superclasse de

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


nri rraf e Hel ter mVHalter;
)

Animal-

No c6digo anterior,

Horse tem uma variivel de instAncia do tipo Halter, Poftanto' voc6_pode dizer que "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.
a classe

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 r a redvzir bugs". Qiuanto mais especializada. a classe, mais prov6vel que possa ser reutilizada de fato podem "jnd, .* o.rt.o, aplicativos. Se voc6 inserir todos o. c6digoJrelacionados a Halter diretamente na classe Horse, 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 tie(Rope r) """


A

Halter

tt"(""p" r)

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

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
l

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 ".lasse Horse o far| ou, como nesse exemplo, solicitarA a outrem parafaz6-lo. No entanto, para o chamador 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
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

Projeto orientado a obietos Os relacionamentos f-Ulrt e TEM-UM

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.

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
reconhecer quando os erros sdo de
do

nnpikgdo

e quando sdo de

polimorfsno. Alin disso, deterrtinar quando a conuersdo senl necerdria 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 Fora os objetos do tipo Object, todotos objetosJava sio polim6rficos, no sentido de que em relaSo ao seu proprio tipo e em relagio ) classe Object.
Lembrese de que a rinica maneira de acessar um objeto imponantes a memorizar sobre as refer6ncias:
6 atrav6s de

ser

eles passam

considerado polim6rfico. no teste E-IIM feito


h6 algumas coisas

uma vari6vel de refer6ncia,

I r r r I

Uma vari6vel de refer6ncia s6 pode ser de um tipo objeto que referencie posa se modificar).

e,

uma vez declarado, esse tipo nunca pode ser modificado (embora o

Uma referOncia 6 uma variivel, de forma que pode ser reatribuida para outros objetos declaradacomo f inal).
referenciando.

(a

nio

ser que a refer6ncia seja

O tipo de uma variivel de refer6ncia determina os m6todos que podem ser chamados no objeto o qual Uma vari6vel de refer6ncia pode apontar para qualquer objeto do mesmo tipo que muito importante - pode se referir a qualquer subtipo do tipo declarado!
a

vari6vel est6

refer6ncia declarada, ou - isto 6

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


// mais c6dica
]

GameShape,

Arrimatable

t // Niot

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

criadoru de Jaua decidiram ndo permitir a beranga nilltipla d qae ela pode acabar bagungando o c,idigo. prob/ena i qae se uma clasv estender dttas oatras c/astes, e ambat as superc/asses tiuerem, digamoq um mitodo Basicaaente, o 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

ntiltipla".

raTdo

pela qual

os

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

apenas ai subclasses

voc6 poderia fazer? VocA j6 sabe a resposta - criar uma interface, Animatable, e fazer com que di cameshape q.rc possam sei animadas implementem essa interface. Eis o seu c6digo:

JAVA

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

,,\;

) Lltal> /t /| ^^:^ ^aa:-^ Lvufvv

Agora n6s temos uma classe PlayerPiece que passa no teste E-LIM tanto para a classe GaneShape quanto para 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 referncia:

r I I I

Um obj

ect

(uma vez que qualquer objeto herda de Obj

ect)

Um GameShape (umavez que

PlayerPiece

estende GameShape)

Um

PlayerPiece (umavez que 6 isso que realmente 6) 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 ( ) ; ^ prayer; ^^+ uDJecE. o -= *1 --., ^Li 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 GameShape, PlayerPiece e Animatable - quais desses quatro tipos conhecem o m6todo display ( ) ? VocA adivinhou

ect,

e PlayerPiece, como 6 de conhecimento do compilador, t6m um m6todo tipos de refer6ncias pode ser usado para chamar display ( ) . Lembre-se de que, para o compilador, um PlayerPiece E-UM GameShape, enteo o compilador diz'estou vendo que o tipo

display

as classes

GameShape
desses

(),

entio qualquer um

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 "s da referincia) sio 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, 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,
chame conshatores de superc/asses, cznstfl.rtzre! sobrescritos oa sobrecatregados.
e

identifcar

e devnuoluer cddigo que declare ef ou

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


rf

q\/qj- Fm nrrf nrintln ousrL'.vuL.P!

(.'Horse gqLrrlY i-^ eaf frvrrE \

1-'r.' r ^^f c veev, rrsJ

errv

=-4 hOrSe tfeats");

]
)

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 como aqueles ot quair ser,iforpado a abst.ract da superclasse. Portanto, voc6 deve considerar os ndtodos

abstract

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, a.eat\\; // Executa a versdo Animaf de eato b.eat (\; / / Executa a versSo Horse de eato

rnas

6 tut objeto Horse

JAVA

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

No c6digo anterior,

Animalc=newHorse0; c.buck(l; / / rmpossivel


|

chamar buckO;

/ A cl'aes'e Aninral nio possui

asse m6todo

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 compilador

voc6

ndopodertl ter um modficador de acesso mais restritiuo do que o m6todo que foi sobrescrito (por exemplo, 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 referncia 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:

O m6todo novo

public class TestAnimals { public static void main (String [] args) { Animal a = newAnimalo; Animal b = new Horse() i / | Refer6ncia Animal, nag 5 urn objeto a.eat); // Executa a versao Animal de eato b.eatO; // Executa a versdo Horse de eato
]
]

Horse

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

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.
A vari6vel
As regras para a sobrescrita de um m6todo sio as seguintes:

I I I I I

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.

O O O

tipo dz retomo

deae ser o mesmo,

ou um subtipo, do tipo de retorno declarado no m6todo sobrescrito original da


a

superclasse (Falaremos mais sobre isso daqui


nfuel de acesso n6o deue ser

algumas piginas, quando discutirmos os retornos covariantes).

nais rutritiuo que o do m6todo sobrescrito. que o do m6todo sobrescrito.

niuel de

acesso

pode ser menos restitiao

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

Voc6

n6o pode sobresmuer um mdtodo marcado com

f :-na]-.

Voc6 nio pode sobrescrever um m6todo marcado com static. Veremos um exemplo daqui a algumas p6ginas, quando discutirmos os m6todos static com mais detalhes.

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

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

63

o m6todo e' em seguida, volte aqui e tirmine com o c6digo adicional d. mirrh" subclasse para 6 preciso que a versio 1y 3t$g"lf !:"* ressaltar qry :,.t?o usando a palavra-chave da superclassZ t.1" suDclasse)' t tacrl tazer lsso no codrgo super, como vemos a seguir:
p-a.ra.

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
superclasse

da

.".."r.J"";;;;i;;dt;;'d"

public class Animal { public void ear O {


ntthlin rznid

} /\ / \ / t

nrint-Vnrrrcalf rvstpsr!

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

/ /,/ // //
/
l

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. (Lembrese de que m6todos static nio podem ser sobrescritos.)

oBSERVAq6ES pane o EXAME


Se am

sobretcritor, o conpiladar

ama refeftnciapolinilfica (do sapet'po)para apontarpara o objeto do subtipo com o m1todo cbamando a uersdo do ndnio do srpen;po.-Se o aeoAo do supet;po dul)rar uma exnpdo uerifcada, mas o mdtoda do subn'po ndo of7.er, o conpilador ainda assim pensani qie uoc6 uni chamando ,nao qae declara ama"excegdo
aocd

mitodofor sobreterito, mar

anr

arunini

que

uocd eshi

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) Animala=newDog2O; Dog2 d = new Dog2O; d.eatO;// ok a.eatO; ll erro de coogilagao I / Exceg6,o n6o relatada
) ) Este aldigo ndo coapilanl deuido exce\zo dularada no mdtodo eat ( eaL ( asado sela a uertdo de Dog a qual ndo dulara a excegdo.

de

Aninal.

Isso

ocom mesmo qtle, em tempo de exuugdo, 0 mit4do

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

2-1 lista exemplos de sobrescrig6es nio-viLlidas Odo m6todo classe Animal.

A Tabela

eat

de Animal, dada a verslo anterior da

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 pela versio da superclasse

public void eat ( ) throws lOException { public void eat ( string food) { publicStringeat( ){
}

nio

declarada

IJrru sobrecarga vilida, e nio uma subscrigiq poque a lista de a{gumentos foi aherada

Nio
}

6 uma subscriglo por causa do tipo de 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 p.lt fa:to de uma das coisas com as quais os deienvolvedoresJava novatos mais se confundem serem incluimos "q.ri sutis diferengas entre m6todos sobrecamgados e sobrescitos. justamente as
se

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

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 rrnid chanaesizc(inf vvrs vlrgrrYe Puvfrv


Os m6todo a seguir sio
n,,1.r1 .in trruurI9

size. String name, float


do m6todo

pattern)
)
:

{ }.

sobrecargas u,itidas

changeSize
name)

(
}
I

public void changeSize(int size, String


ini frrL urrqrtverr!= ^h:ndaqizotini- \rlru qize f I^al-

{
I

naftern)

public void changeSize(float pattern, String throws rOException { }

name)

JAVA

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

{ f / i nr rr r, ctsri evL-ng } S) {
}

nrrhl i c rrni rl rlnqtrrf vvru u---e vuvrrL

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

subclasse

a excegdofoi uerifcadapelo compilador. Mas o mitodo doStuf f ( Bar o sobrepds, altemando a lista de argumentlr, portanto a excepdo lOExcept.i on

)
i

ndofoi defotma alguma substcrito! 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. 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:

A decisio sobre qual dos m6todos coincidentes chamar ser6 baseada nos argumenros. Se voc6 chamar o m6todo

class Adder {

public int addThem(int x, int y) return x + v;


)

// Sobrecarrega o m6todo addThem para adi-cionar doubles public double addThem(double x, double y) { return x + y;
) )

em

vez de ints

/ A partir de outra classe, chama o m6todo public c1ass TestAdder { public stat.ic void main (String [] args) Adder a = new Adder0;
/

addThemo

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
a

m6todo, portanto,

int

anterior, a primeira chamada a a. ad.dThem (b, c) passa dois tipos int para o primeira versio de addThem ( ) - a versio sobrecarregada que usa doii argumen^tos de tipo

para o m6todo,.portanto, a segunda verseo de addThem double - ser6 chamada.

-ser6chamada.Asegundachamadafeitaaa.addThem

(22.5, 89.361 passadoistiposdouble( ) - a versio sobrecarregadl que usa dois argumentos

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

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

liorr., jL que 6 esse objeto

Qual das vers6es sobrecarregadas seri chamada? Voc pode estar querendo responder: "A ,9ge usa qm 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

Sli*ll, a opgio por qual m6todo m6todo) nio 6 decidida dinamicamente no tempo de sobrecamgado chamar (em outras palavras, a assinatura do 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 mtodo 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.
Ainda que o objeto real no tempo de execugXo
seja

um objeto llgrse e."q"

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
)

67

public class Horse extends Animal { public void eat0 { System. out.println ( ..Horse eating hay .. ) ;
) .ia vvfq nrrh'l re rrniA
yslf

a:|- tqt-rind \uL!frrY


cqu

c\
o/

I I

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


) )

versao dos tr6s m6todos

Observe que a classe Horse tanto sobrep6s quanto sobrescreveu o m6todo eat ) . A Tabela 2-2 mostra que eat ) ser6 executada dependendo de como forem chamadas.

Iobelo

2-2

Chomodos o rn6fodos Resultado

e sobrescrifos

C6digo de chamada de m6todo

Animala=newAnimal( ); a.eat( );
Horseh=newHorse( ); h.eat(
)

Generic Animal Eating Generically


Horse eating hay
Hone eating hay O polimorfismo funciona - o tipo do objeto real fttrone), e nio o tipo da refedncia (Aninral), 6 usado para determinar que m6todo eat( )
ser6 chamado.

Animal ah = new Horse ( ) ; ah. eat ( he . eat ( "App1es " ) ;


Horse he = new Horse

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


)

a2,eaX

Animal a2 = newAnimal (

("treats");

Erro do compilador! O compilador percebeu qtre a classe Animal nio possui


um m6todo eat( ) que use uma String.

Animal ah2 = new Horse ( ) ; ah2 . eat ( " carrots " ) ;


oBSERVAQ6ES
Ndo
se deixe enganar

compilador nlo se preocupou com o fato de quetalvez o objeto real no tempo de e:<ecugio seja um objeto Hone.

Erro do compilador! O compilador conrinuou examinando somenre o tipo da refer6nciae viu que Animal nio tem um m6todo ea( )qtre use uma srring. O

pene O EXAME
sobruamgado,
e ndo robretcrito

prr uril mitodo que s/a

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 referncia ao objeto Foo pode chamar somente a aersdo sem argilnentLr' mN 0 que ten a referncia 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. Mtodo sobrecarregado
lista de argumentos Deve ser alterada
Pode ser alterado

M6todo sobrescrito

Nio

deve ser alterada deve ser alterado

tipo de retorno
Exceg6es

Nio

Podem ser alteradas

Podem ser reduzidas ou eliminadas.

68

Copftulo 2: Orientog6o o obietos

Nio devem ser langadas


Acesso Pode ser aherado

exceg6es verificadas novas ou mais abrangentes


deve se tornar mais restritivo (pode ser menos restritivo)

Nio

Chamadas

O tipo da refer6ncia determina qtre verslo sobrecarregada

O tipo do

objeto

(em otttras palavras, ocorrer6


a

ti1o da inrfincia real na memtiia)


ser6 selecionado. Isso

tipos de argumentos deilarados) seri


(baseada nos sel-ecionada.

todo

instante.

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
Tree

Sobrecarregado
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

(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

O objetivo atual

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

saber dferenciar enor de conrpilagdo de erms de tempo de execapdo relacionados

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

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 , for(Animal animal : a) {
animal.makeNoise ( ) ;

new Animal

O );

if (animal instanceof Dogr) { animal .playDead(li // lentou realizar

um coq)orta.mnto de D,og?

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

cannot.
de c6digo

find

slzmbol

O compilador

if:

est6 dizendo:

'Ei,

a classe

Animal nio tem um m6todo playDead

()

". Vamos modificar o bloco

if (animal instanceof Dos) { oog d. = (Dog) anirnal; // conwertendo a variSvel de refer6ncia


d.playDeadO;
]
e melhorado bloco de c6digo cont6m uma conversio, que neste caso 6 is vezes chamada de conuersdo 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.
redutora,

O novo

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)

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

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)

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

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
Embora
isso

pene O EXAME
que foran

Os niadorcs do exame irdo lhe diryr

t/a

potencialmente uerdadeiro, eles

forgadot a eo/ocar toneladas de aldigos em pequeills espapos 'por causa do sistema do exane". TAMBEM gwtam de ser obvums. O aidigo ngainte:

Animala=newDogO; Dogd= (Dog) a;


:
s.uvsvvvesr!

rlnnnacrrrff

/\ / \

Pode rcr substituido

por

e$e,

nuito nais

jlcil

de ler:

Ani-ma1
( (Dog)

a = new DogO;
()

a) .doDogStuff

;
esses

Neste caso, o conpiladorprecisa de todos

parnteses, caso contniio

pentari que eshi recebendo ama infuwgdo innmpleta.

JAVA

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: seguinte classe ir6 compilar:

bounce ( ) e setBouneeFactor

()

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

ji

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
interface, ou subclasses que

da

nio

sejam as declaradas por esse m6todo.

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

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:
Mas.espere_,

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 / / BeachBall (8a11) implementa Bounceable public void bounceO
/ / a6di an hnrrnna

de

t
i an rla

acnaaif
vePevflfvv

Ra:nhpr1

rr

I uqur amri

72

Copftvlo 2: OrientoEdo o objetos

public void setBounceFactor(int bf) { / / c6digo bounce especifico de BeachBall aqui para definir
/

um

fator de bounce
de

/ se a classe Ball Liver definido quaisquer m6todos abstract, eles terao / / 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.


E perfeitamente

vilido informar, por exemplo, o. seguinte: public class Ball implements Bounceable, Serializable, Runnable

...

VocA pode esrender somente uma classe, mas implementar muitas. Por6m, lembre-se de que a criaglo de subclassei 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 public interface

pode estende

outra interf.ace, mas nunca implementar algo.

O c6digo abaixo 6 perfeitamente v6lido: Bounceable errtends rdoveable

}
a

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

O que isso significa? A primeira

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:

No entanto,

frublic cLass

PrograrEner extends Eqrloyee, Geek


classe

{ , ||

I,rrvlLj-Aol
Java.

Como mencionamos anteriormente, uma


interface pode estender virias interfaces.

nio pode estender virias outras em


{

No entanto, uma

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

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
implemenLou

nao

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( ); void setBounceFacEor(int bf) abstract Ball implements
;

Bounceabl-e

^
I

/*ndo serSo implementados Ball quaisquer m6todos de Bounceable */ void beSpherical( ){}
em

class Tire implements Bounceable public woid bounce( ) { ) public void setBounceFactor (int bf) {
}

class BeachBall exEends Ball

public void bounce( ){ } 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
intet'aces e clastes:

pene O EXAME
As linhas a seguir
mostram exemplos de dulamgdu udlidas e ndo udlidat de

Procure utiliqagdes ndo udlidas de exten$u e inplenentapdes.

class foo {
ala<< R:r

} E'^^ f
J

//

oK

imnlamanfc

// Ndo! Ndo 6 trtossiveL impTementar uma cLasse

74

Copftvlo 2: OrientoE6o o objetos

interface eaz { } interface Fi { i interface Fee implements Baz { interface Zee implement.s Foo { int.erface Zoo extends Foo { interface Boo extends Fi {
} }

} }

// oK // oK // Ndo! A interface ndo Pode / / impTementar uma interface // Ndo! A interface ndo Pode
/ / im9sTementar uma
c

fasse // Ndo! A interface ndo pode estender


/,/uma cf asse
//

//
}

OK. A interface pode estender interface

uma

class Toon extends Foo, Button {


cl-ass Zoom implements Fi, Fee {
}

interface

Vroom extends

fi, Fee {
nas

// Ndo! A c-lasse ndo pode estender / /miTtiplas cl.asses // OK. A cTasse pode implementar miTtipTas / /interfaces // OK. A interface pode estender / /n67tip7as interf aces

MemoiTe isto e pmcare abusos cometidos

pmbhna real pode

petgilntar qae estiuerem n0 exame. IndEendente do que as perguntas parEam aualiar, o Antes de cair na arwadilha, digaruos, de acompanbar o fluxo de am thread 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
ser a declaragdo da classe ou interface.

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

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

apenas

o tipo de rerorno

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

v6.1i-da em ,Java 1.5

] Com oJava 5, esse c6digo compilari sern problemas. com o flag source, desta forma:
Se

voc6 tentasse compil6Jo usando um compilador 1.4 ou

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

sobrecarga, inclusive as dos modificadores de acesso e exceg6es declaradas, mas elas


de retorno. os m6todos sobrecarregzdos podem ter o tipo de retorno alterado, mas os m6todos dos retnftilr couariantes. 56 por ter conhecimento disso

nio sio relevantes para a discussio sobre o tipo


No exame, voc6 ter6 que saber que

que estiverem sobrerreuendo outros sri poden fa$-/o dentro dot linitu 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 public class TestChewable
/
{

Chewable

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 no teste
mdtodo

una clasn abs

trac t

ou anta interface, e rzemoriry que qaa/quer objeto qae passar

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

- por exemplo:

public abstract class Animal { } public class Bear extends animal { } public class Test { public Animal go ( ) { return new Bear (\ ; / / OK, Bear
] ]
Esse aldigo

$a!-um/' Animal

ini

compilar, o ualor de retorno

um subtipo.

JAVA

77

Obietivo poro o certifico6o

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,
cznJtratlres de superc/assu, con$rutoret sobrescritot ou sobrecanegados.

e cddigo qae dec/are

efou cbane

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


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:

Notou o que est6 faltando?

class Foo { int size;


Qlri Fan r vv nd nama. nam6 i nf ci za\ { I efri \ve!+rrY nn

this.name = name; this.size = size;


J

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 Foo

f f

= new Foo O ; / / Ndo

vai compilar,

nao h5 um

construtor correspondente

mas a linha a seguir ser6 compilada,

= new Foo("Fred", 43);

problemas. os argumentos correspondem ao //construtor de Foo.


Sem

//

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?

Portanto,

Cadeia de construtores
Sabemos que os construtores serXo chamados no tempo de execugio quando voc6 digitar classe como vemos abaixo:

new em algum tipo

de

Horseh=newHorseo;

78 Copitulo 2: OrientoEdo

o obietos

Mas o que ocorreri realmente quando voc6 digitar Animal estende Object.)

new Horse

) ? (Assuma que

Horse estende Animal e que

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

O construtor

de

Animal seri chamado (Animal

6 a superclasse de Horse).

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

4. As vari6veis 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
3.

o
calls

Animal O
(

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

para faze.r o exame (e para compreender o restante " cesta segao). v oce preasara se lembrar-se delas, portanto, estude-as mars de uma vez.

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).
O nome do construtor deve coincidir com o da classe.
Os construtores nio devem ter um tipo de retorno.
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.
Se voc6 nlo inserir um construtor no c6digo de sua classe, um constnrtor padrio seri gerado automaticamente pelo compilador.

I I r

r I I

O construtor padrio ser|


Se

sempreum

construtor sem argumentos.

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

))

digitarachamadaasuper(
T Uma chamada
zuperclasse.

voc6 inserir um construtor (emvez de ficar esperando pelo construtor padrio gerado pelo compilador) e ndo

)ouathis(

),icon?iladirinseini,automaticamente,irztachanadarsuper(')

sen

argt/mentos, como a primeira instrugdo do constrvtor.

super

( ) pode ser sem argumentos ou incluir os argumentos passados para o construtor da

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

79

construtor padrio nuncatenha argumentos, voc6 pode inserir

seu pftipit

construtor sem argumentos.

t I I r r

podeni,fazer uma chamada ao m6todo de uma instAncia, ou acessar uma vari6vel de instAncia, at6 que Y?: executado o tenha construtor da superclasse.
ndo

Apenas vari6veis e m6todos


)

. (Exemplo:
classes

super (Animal
ndo

static
.

p9{eqr s9r

NAME

))

acessados como pafte da chamada a super ( ) ou this v6lido, porque NAME 6 declarada como uma variivel static. s serupre que

As

abstract

t6m construtores e eles sio chamado

uma subclasse concreta 6 instanciada.

As interfaces

t6m construtores. Elas nio fazem pane da irvore de heranga de um objeto.


6 dentro de outro construtor. Em outras palavras, efetivamente um construtor como vemos abaixo:

voc

$i1 maneira pela qual um constmtoS pode ser chamado nio pode escrever um c6digo que chame
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 {Bpr3,chegamos celrnroo nennum construtor para ela.

a classe

anterior, porque nio foi

Certo, e quanto a esta


rlaqq IJ^rc6 f

classe?
1

void Horse( ) {
i

Pode paruer que o compilador nlo crrari um construtor, porque \-rDserve novamente a classe Horse anterior.

ji

existe um na classe Horse. Existe mesmo?

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

O construtor padrXo Ele


ndo terd atgumentor.

te

ri

mesmo

modfirador dt

acesso da classe,

Ele incluir6 uma

cbamada sem atgamenttt ao constrator da stperclatse

(super

).

80 Copitulo 2: OrientoE6o

o obietos
sua classe.

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


Tobelo

24

Codigo do construto r gerodo pelo compilodor

C6digo do closse (digitodo por voc6)

C6digo do construlor gerodo Pelo com pilodor


class Foo { roo( ) { ( );

cfass Foo {

Eulrer )
)

cfass Foo { FooO {}


]

class Foo { Foo( ) { Euper( ),


)

nrr].'linalaceFnn

{l

class Foo { public roo() { super( );


)

class Foo { class Foo { } I,OO(Srrngs) tJ


)
)

F^^/qfrinn

q\

auper( );
]

class Foo { } !oo(Scrfngsl tj


super ( ) ;
] ]

Nenhum , o

compilador nao precisa inserir

cfass Foo {

class Foo { ) voidFooO {}


]

void Foo O {} roo() ( super( );


)

(void

Foo

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

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
^l Lfq-r^^^

a seguir 6
rulrrrrqa ^61*-l

um exemplo do problema:
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


um construtor
segurr:

se sua superclasse ndo tiaer

am consttator tem argllmentus, entio, em tua tubc/asse

podenl usar o conshvtorpadrdofomecidipek nrpilador.

super

( j sem arg,rmerrios,
}

E simples assim.

voc6

nio conseg,riri rr.*

Ji

uoc6 nio que o coirpilador s6 pode inserir a chamada a -

-.r-o

compilar;lg"

.;;; ; lafii.

"--

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

^^^-

Tshirt ( ) { supero; // j // j //

vai funcionar! Chama um construtor sem argumentos Clothing( mas esse construtor ndo existel
Ndo

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 prr*"t acreditam que o construtor padrio de alguma forma consrnrtor iia.ao q,r. rro.6 "bte.i.'Algrn",trot que ter6 (lembre de que o conshtttorpadrd.o i sempre da supercLsse, coincidiri ** o "rru*entos "o'rrrt*to, usados na chamadi ) super ( ) fornecida pelo compilador. nos constrator sem argunento) ou
Por6m, embora os constnrtores nio possam ser sobrescritos, voc6 j6 viu que eles podem ser sobrecarregados, normalmente o sio.

am

"rgrr*.ntot

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

idAntica ao construtor padrio. que o 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.
que

Foo anterior possui dois construtores sobrecarregados, o que usa.uma string


essa classe 6

outro sem argumentos.

Ji

nio h6 um c6digo na versXo sem argumentos, na verdade,

de um construtor normalmente 6 usada para fornecer maneiras alternativas de os clientes animal, poderi pass6-1o para instanciareir objetos de uma classe. Por exemplo, se o-cliente souber o nome d9 um construtor de Animal que use strings. Mas se ele nio souber o nome, poderi chamar o constnrtor que nio usa

A sobrecarga

".-

argumentos, e este fornecei6

n* tto-.
{

padrlo. Veja como funciona:

1. public class enimal 2. String name;

3. 4.

Animal(String name) this.name = name;

s. )
7. Animal O { this (makeRandomName 8.
10.

O)

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

83

I java Animal Fluffy


Zeus

t java Animal
Rover

I java Fluffy
Zeus

Animal-

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

object (
Animal
(

(Strinq
)

) chama super (

,r

2. Animal

l.main( )
Figuro 2-7

qhama this ( randoml-yChosenNameString) chama new Animal( ) no pilho de chomodos

Construfores sobrecorregodos

8 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.
Linha
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 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 para

Linha 11 Observe que o m6todo makeRandomName ( ) foi marcado com

static!

Isso porque voc6, ndo

ji

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.

static

r r

Linha 12 A linha 12 nio tem nada a ver com construtores, gera um nfmero aleat6rio entre O e 4.

mas j6 que estamos todos aqui para aprender... Ela

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 "rsustlado entAo apenas diga para si mesmo: "Calma", e d prosseguimento).

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

Linha

20

Estamos chamando o constnrtor sobrecarregado que usa uma string representandQ o nlme.

desse exemplo de c6digo esta na finha 8. Emvez de chamar super ( ) , estamos this ( ) que nmpre tWtf* una chinad.a a uatro cunstrator da mesma classe. Certo, mas o que aconteceri chimando 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 ( ).

O ponto chave a exrrair

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
vilida
I . J6 que essas chamad"r p.eiim* ^.onrtrutor.
as duas

ser a primeira instrug-Xo de um construtor, voc6. nio.pode usar de maneira

per ( )

Issb tamb6m significa que o compilador no -.r-o em um construtor que possua uma chamada a uhis ( ) .

nio inserir6 uma chamada a su-

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


doStuff
)
(

public void doStuff ( )


go(),.
)

AgoravocE consegue enxergar o problema?

siirplesment. r.

.orrit-tor.r

E claro que sim. Apithafoi exndida!Elaficou maior e maior, a!6 qu9 . e o i6dig" do m6todo foi deiramado, esvaindo-se parafora daJVM e.caindo no chio. Dois robrecarregados chinando this, sio dois construtores chamando um ao outro. Repetidamente, resultando em

ibtin

* 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 a manutengio de v6rias vers6es do c6digo desse construtor imponante. Basicamente, os que escrerrei e fazer .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

85

Obletivo poro o CertificoEdo


Static (Objetivo
Aldm

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. disso, usar identifcadores utilidos para nomes de uaritiaeis.

Variiveis e m6todos stat:c


O modificador 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

static

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.

ininterrupta do total de instAncias 6 usar o modificador


Pertencem

lesposta tanto parao cenlrio do m6todo

utilitirio,

classe, emvez de a qualquer instAncia especifica. Na verdade, vocA pode usar um m6todo ou variivel sem ter absolutamente nenhuna in$incia dessa classe. 56 precisa ter a classe disponivel para poder chamar um m6todo ou acessar uma variivel As variiveis tamt6tn ier acessadas sem ter a instincia de uma classe. Mas se houver instAncias, avari|vel dessa classe ier6 companilhada por todas as instAncias da classe; s6 haveri uma c6pia.

static

sempre executado da mesma forma, quanro para a contagem As variiveis e m6todos marcados co"m

static.

static

static

static.

static static

poi.-

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


]
)

frogCount 6 configurada com zero, quando a classe Frog 6 carregada pela ' a)aat (A prop6sito, ioc. nilo precisard rellmente " 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
instdncia de Frog rc1a

No c6digo anterior, a vari|vel static priqgira vez pela JVM , antes que qualqaer

emmain( ) e o resultadoser6:
Frog count
esse

is

now

Agora imagine o que aconteceria

se

frogCount fosse uma variivel de instAncia (em outras palavras,

ndofosse

unidc):

c6digo for executado, ainda criari tr6s instAncias de Frog em main ( ) , mas o resultado seri... Um Quando erro do compilador! Nunca poderemos fazer esse c6digo ser executado, porque nem ele mesmo ser6 compilado.

class Frog
i nf nrrhlin

{
\ / /L r,1. r, n.

f rnaanrrhf E'r^ft/\ ! +vv

// DecTara e inicializa

a vari6vel

de instAncia

fr^d/l^rrnf rrvvvvsrrL
)
1

/ / Nlodifica o valor do construtor

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
ndo b,l ana instincialSem

falar que nio h6 instincias da-classe ativa na mem6ria e, mesmo se houvesse, o m6todo O mesmo se aplica a m6todos de instAncia; um m6todo static nio pode "trti. chamar diretamente um m6todo nio staLic. Considere static : classe, nlo stat.ic : instlncia. Tornar o 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.

nio

saberia nada sobre elas.

oBSERVAQ6ES

pene O EXAME
cometidos

[Jm dos enos maisfreqiientet aaiduel). O aidigo a rcgair

aaiiaelndostatic) apartirdomitodomain( )
i
um exenpk
de

porprogramadoru laua iniciantet

tenlar

acessar

una uarihuel

de

in$6ncia (o qae ignfrca una

(quendotennenhamainfomag1osobrein$incias,prrtantz,ndopodeaeessara 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) System.out.println("x j-s " + x) ;
)

bon qae aoc6 saiba qae use aidigo nunca uri compilado, porque n6o 6 possiuel

acessar

uma uariiuel n6o

sEaLic

(de instdnciQ

patir

de um mitodo

static.
a

Apenas inagine o compilador diqpndo


t4

exibir!"

I-,embre-rc de qae

a cksse que execata o

mitodomain

( |

'Ei,

ndo tenbo iddia de que uaiduel


e ndo uma instdncia da classe.

x do objeto Foo aocd ettui tentando E claro que aparte corrplicada no

exane seni qae


uariduel ndo

perglnta
a

ndo pareceni tdo

sLatic

paftir

6bria quanto o c1digo anterior. O problena sobre o qual uocd estari sendo aualiado acesiar tlma senl. canuflado no aidigo qle pareceni aaa/iar oatra qautdo, Por exempk, seria de am mitodo

static

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)


nta pnlpria
classe.

de

Acessando yari6yeis e m6todos


usaria o operador ponto na refer6ncia
nl:ce Frnn I

static

Jriquevocnioprecisaterumainstinciaparachamarumm&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
a

uma instAncia:

int frogSize =
nrrhlia vgvf!v+fr9Yv9rrvVv*!v\, in{-

0;
I

aat-FranQizaI\

return frogSize,'

JAVA

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


essa

getFrogsize ( )

referenciapara chamar um m6todo

de Frog, a atribuimos a variavel de refer6ncia f e, em seguida, usamos

na instdnciaFrogque acabartos

rriar.Emoutras palavras, o m6toio

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 -6ioldo static (ou vari6vel static) serl usar o operador ponto n0 nome da classe, e nio na refer6ncia a uma 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
l

Mas apenas. p ar.a.tornar isso realmente confuso, a linguagem Java tamb6m permite que voc6 use uma uai,iuel de referncia de objeto para acessar um membro static:

Frogf=newFrog0; int frogs = f.getFrogCount()t //

Acessa o m6todo

est6tico getFrogCount

usando

esse novo objeto a variivel de refer0ncia f e, em seguida, usamos a referAncia I para charnar um m6todo 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 mas o membro stat.icainda nio tem conhetimento da instAncia especifica usada para cham6lo. No exemplo, o compilador sabe que a refer6ncia 6 do tipo Frog e, porranro, o m6todo da 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 ser declarada com o tipo Frog. A Figura 2-8 ilustra os efeitos do modificador sobre m6todos e variiveis.

No c6digo anterior, instanciamos um objeto Frog, atribuimos

static!

static,

static

stat.ic

Outro ponto

a lembrar 6 que os n,itodos ndopodem sersobrecarregadar! Isso nXo significa que eles ser redefinidos em uma subclasse, mas redefinir e sobrecarregar ndo sio a mesma coisa.

static

nio possam

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

sintaxe a

disso,algocomoAnimal

[x] .doStuf f ( ) 6 apenas um atalho (o truque da sintaxe)... O compilador usar6' emvez .doStuff O.Reparequenlousamosaquioloop for apimoradoloJava1.5
t6lo feito. Espere ver uma mistura

(abordaJo no Capitulo 5), embora pud6ssemos pr6ticas deJava 1.4 eJava 5 no exame.

de estilos de programaglo e

classe Foo int size = 42; slatic void doMore( ){ int x = sVe;
]

O m6todo static neo 6 capaz de


acessar uma

variivel de inst6ncia

(nio-static)

classe Bar
void go ( ); stat,ic. void doMore ( fft );
J

O m6todo static ndo 6 capaz


){

de acessar um m6todo niostatic

classe Baz sEatic int count; static void woo( ){ } static void doMore( ){ woo( );
i nF v ^^irnF .

O m6todo static 6 copoz de acessar um m6todo ou uma


variivel static

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

modo que o que e$;mos discutindo neste capitulo

JAVA

89

t6picos, acoplamento e coesio, t6m a ver c.om a qualidade de um projeto oo. Em geral, o bom projeto 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

RXtpede acoplamentofraco oo l?k

r I r

Facilidade de criagio Facilidade de manurengio Facilidade de melhorias

Acoplamento
Vamos comegar f.azendo uma tentativa de definigio
do_

as classes 6 mais forte... E isso nlo 6 bom. Em outras palavras, se qual B foi implementada, entio A e B t6m acoplamenio forte.

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

acoplamento. Acoplamento 6 o grau em que uma classe

".oplr*.nro."r..' sabe mais do que deveria sobre a maneira pela

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

ser danificada.

"lg,rm"

Opiorcasopossivel6ahorrivelsituagioemqueaclasseAsabedecoisasnio-relativas)APlsobreaclasseB,ea B 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
classe

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; pubJ.ic float adjustedSalesRat-e;

/ deveria ser private / / deveria ser private


/
{

public float getSalesRate(String region)


salesRate = new ItoTaxes() .doColorado( / / faz c61culos com base na reqiSo return adjustedSalesRate ;
]
)

| oh nAo, de novo

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 {


)

class Fil-eSaver { SaveOptions getFileSaveoptionsO {


) Este

classe que faz tudo, dividimos o sistema em quatro classes principais, ca& .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.

projeto 6 muito mais coeso. Em vez de uma

tr-" iom

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

a sobrecarga ,o

conversio de refer}ncia,os tipos de retorno

e os

constnrtores'
a

Abordamos E-UM e TEM-IIM. n-UVt 6 implementado usando-se variiveis de instAncias para se referirem a outros objetos.

heranga, e TEM-UM 6 implementado usando-se

*rdo p".* r. .eferir a um o6jeto

O polimorfismo veio em seguida. Embora o tipo de uma variivel de refer0ncia nio possa ser modificado, ele pode ser cujo tipo seja um subtipo do seu pr6prio. Aprendemos como determinar quais m6todos sio invociveis para determinada variivel de referOncia.

sobrescritos, j6 que, na verdade

JAVA 5 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

9I

, 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 necess6ria e cemo usar o operador insLanceof .
6

A implementagio

podem estender outra interface.

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

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 tr

O encapsulamento

aluda a ocultar a implementagio por

tris

de uma interface (ou

API)'

O c6digo encapsulado fornece dois recursos:

E E E E E tr

As vari6veis de instAncia sXo mantidas protegidas (geralmente com o modificador

private).

Os m6todos capturadores e configuradores fornecem acesso a variiveis de insdncia.


se refere

O relacionamento E-Uvt O relacionamento n-UU "E-UM", "herda TEM-UM significa que

) heranga.

6 representado pela palavra-chave

extends.
de outra classe, ou a outra

de" e "6 um subtipo de" sio todas express6es equivalentes. a instincia de uma classe

'tem uma" refer6ncia I instAncia

instAncia da mesma classe.

Heranga (Objetivo 5.5)

D A heranga 6 um mecanismo que permite que uma classe seja uma subclasse de outra,
variiveis e m6todos da superclasse.

e, dessa forma, herdar

D A heranga 6 um conceiro

fundamental, que est6 por tr6s do E-UM, do polimorfismo, da sobrescrigio, da


e, portanto, herdam os m6todos de

sobrecarga e da conversio.

fl

Todas as classes (exceto


i:ats

obj ect) sio subclasses do tipo obj ect,

ob-

Polimorfismo (Objetivo 5.2)

E U E E E E
D O

Polimorfismo significa "muitas formas". Uma vari|vel de refer6ncia


6 sempre de

um s6 tipo imutivel, mas ela pode referir-se

um objeto do subtipo.

Um mesmo objeto pode ser referido por vari6veis de instAncias de muitos tipos diferentes sejam do mesmo tipo ou de um supenipo do objeto. O tipo
da

desde que elas

variivel

de refer6ncia

(nio o tipo do objeto) determina quais m6todos poderlo


se

ser chamados!

As chamadas polim6rficas a m6todos

aplicam apenas a m6todos de instAncias sobrescritos.

Sobrescrig6o e sobrecarga (Objetivos 1.5 e 5'4)


Os m6todos podem ser sobrescritos ou sobrecarregados; os construtores podem ser sobrecarregados, mas nio sobrescritos. Os m6todos

abstrac L
a

deuerz

ser sobrescritos pela primeira subclasse concreta

(nio

abstract).

No que diz respeito

ao m6todo sobrescritos, o m6todo novo:

E D
O

Deve ter

mesma lista de argumentos;

subclasse

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

tr Nio deve ter um modificador de acesso mais restritivo;


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

ou qualquer excegio nio

E tr E fl

Os m6todos f

inal

nio podem

ser sobrescritos.

56 os m6todos herdados podem ser sobrescritos, e lembre-se de que os m6todos

private

nio sio herdados.

Uma subclasse usar6


m6todo sobrescrito.

super. overridenMethodName ( )para chamar a versio

da superclasse de um

EJ Sobrecarga significa reutllizar o mesmo nome de m6todo, mas com argumentos diferentes.

Os m6todos sobrecarregados:

D fl
El

Devem ter listas de argumentos diferentes;


Podem ter tipos de retorno diferentes, contanto que as listas de argumentos tamb6m sejam diferentes;

Podem ter modificadores de acesso diferentes; Podem lancar exceQ6es diferentes.

JAVA

93

E tr
Q

os m6todos de uma
O polimorfismo
O tipo de objeto
cte execugao.
(e

superclasse podem ser sobrecarregados em uma subclasse.

6 aplicivel

sobrescrigio e

nio )sobrecarga.
determina qual m6todo sobrescrito seri usado no ternpo
ser6 usado no tempo de compilaglo.

nio o tipo

da vari6vel de referncia)

tr E E 0

O tipo de refer6ncia determina qual m6todo sobrecarregado

Conversio de Vari6veis de Refer6ncia (Objetivo 5.2)


Existem dois tipos de conversio de variiveis de refer6ncia: a conversio redurora e a ampliadora.

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. 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 tr E fl E D E tr tr E E E E

Quando voc6 implementauma interface, est6 cumprindo o seu contraro.

Voc6-implementa uma interface ao sobrescrever apropriada e concretamente todos os m6todos definidos pela interface.

Uma mesma classe pode implementar muitas interfaces.

Tipos de Retorno (Objetivo 1.5)


Os m6todos sobrecarregados podem modificar os tipos de retornol os m6todos sobrescritos nio podem, exceto no caso de retornos covariantes.
Os tipos de retorno de referAncias de objetos podem aceitar

nul-L

como valor de retorno

Um array 4 um tipo de retorno vilido para declarar

para retornar como um valor.

Para m6todos com tipos de retorno primitivos, pode ser retornado qualquer valor que possa ser converrido implicitamente para o tipo de retorno.
Nada pode ser retornado
a partir de um void, mas voc pode decidir nXo retornar. E permitido que voc6 use 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.

simplesmente

return,

M6todos com um tipo de retorno que M6todos com um tipo de retorno que

6 6

uma referOncia

um objeto podem retornar um subtipo.

uma interface podem retornar qualquer implementador.

Construtores e Instanciamento (Objetivos 1.6 e 5.4)


Nio
se

pode criar um objeto sem que seja chamado um constnrror.

Toda superclasse da 6rvore de heranga de um objeto chamari um construtor. 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
da classe e

com o mesmo nome

nio um construtor,
da maneira a seguir: de sua superclasse, que chamar6 o

A execugio do construtor ocorrer6

O construtor chamari o construtor

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

Os construtores podem usar qualquer modificador de acesso (at6 mesmo

private!).
super

O compilador criar6 um co nfirutor padraose voc6 nio criar nenhum construtor em sua classe.

O construt or padrdo

wconstrutor
de

sem argumentos com uma chamada tamb6m sem argumentos a

).

A primeira instrugio

super

todo construtor deve ser uma chamada a thi s

) (um construtor

sobrecarregado) ou

).

94 Copitulo 2: Orientogdo o obietos

tr
D E D B

O compilador adicionarS,umachamada a super

this( ) ouasuper( abstract

),a

menos que voc i|tenhainserido uma chamada a

).

Os membros de instAncia s6 podem ser acessados dqoir de o construtor da superclasse ser executado' As classes
possuem constnrtores que sio chamados quando uma subclasse concreta 6 instanciada.

As interfaces nio t6m constnrtores.


superclasse nlo tiver um construtor sem arg'umentos, vocA_teri que criar um construtor e inserir uma chamada a super ( ) com argumentos que coiniidam com os do construtor da superclasse'
Se sua

D tr E

Os construtores nunca sio herdados, portanto, nXo podem ser sobrescritos.

Um constnrtor

rhis (

s6 pode ser chamado diretamente por outro constnrtor (usando uma chamada a

super

( ) ou

)).

Quest6es relacionadas com chamadas a

this (

):

tr B
O

56 podem aparecer como a primeira instrugio de um construtor.

O A lista de argumentos

determina que construtor sobrecarregado ser6 chamado.

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


instincias.

que

nio

sejam afetados pelo estado de quaisquer

i instAncia - s6 existiri uma static. 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
paraarmazonar dados que sejam especificos ) classe, em vez de Use variiveis c6pia de uma vari6vel

static

"om da classe, por exemplo: nome

o op.t"dor na verdade

um truque sint6tico, e o compilador substituiri

variivel

de referAncia pelo

d.doStuff O ; se torna:
Dog.doStuff ( ) ;

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.
indesejivel de
se

E D E
D

O acoplamento forte

6 o estado

ter classes que desobedecem is regras do acoplamento fraco.


e

A coesio refere-se ao nivel em que uma classe tem um rinico A alta coesio
6o

bem definido papel ou responsabilidade.

estado desej6vel de uma classe cujos membros dio suporte a um rinico e bem definido papel ou
de uma classe cujos membros

responsabilidade.

A baixa coesio 6 o estado indesejivel


nio-focados.

dlo suporte av6rios pap6is ou responsabilidades

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

95

D. Os relacionamento Tem-Um sempre dependem do polimorfismo.

E. Os relacionamento Tem-Um
2. Dado:

sempre t6m acoplamento forte.

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
4. Dado:

o obietos

class Top { public Top(String s) { System.out.print("8");


J

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.
refere-se
a

B. A classe

um pequeno nfmero de outros objetos.


de vari6veis.

O objeto cont6m apenas um pequeno nrimero


atrav6s de uma

D. O objeto 6 referido
de m6todos.

variivel an6nima, e nio diretamente.

E. Avari6veldereferAncia6declaradaparaumtipodeinterface,enioumaclasse.Aintertacef.orneceumpequenonimero

E
F

14.

improvivel

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

97

7. Usando os fragmentos abaixo, complete o seguinte c6digo de forma que ele compile. 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)
j
)

o;

Fragmentos: Use cada um dos seguintes fragmentos quantas vezes for preciso, ou deixe sem uso: AgedP
(

this
)

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"; } getTypeO { return this; } C.Plant D. tulip getTlpe0 { return new Tulip0;
9. Dado:

1. class Zing { 2. protected Hmpf h;


+ t ^ E ^1 ^^^ ufa-D nl:cc rr'^^vvuvP umnf --.f anr{c YJ---^I ) as 7i nn I }

Quais opg6es slo verdadeiras? (Marque todas

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


10. Dado:

6-umWoop.

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

coesXo 6 o

principio daprogramaglo OO mais intimamente associado com o ato de certificar-se


mais intimamente associado com o ato de
se

de que a classe

foi

elaborada com um rinico e bem-focado prop6sito.

D. A coesio 6 o principio daprogramagio OO


objeto seja visto como tendo muitos tipos.

permitir

que um mesmo

JAVA

99

13. Dado:

1. class DoS { } 2. cl-ass Beagle extends


3.

DoS

4. class Kennel { 5. public static void main(String [] arfs) Beagrle b1 = new Beagle ( ) ; 6. 7. Dog dogl = new DogO; Dog dog2 = b1-; 8. 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) X x1 = new XO; 6. X x2 = new yO; 7. Y yl = new YO; 8. 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
4.

est6 incorrera porque sobrecarregar um m6todo

nio 6 o mesmo que o implementar. (Objetivo

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


5.

base

no exposto acima. (Objetivo 1.6)

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


6.

base na tese de

doutorado acima. (Objetivo 5.1)


e,

A esti correta. Embora um m6todo f inal nio possa ser sobrescritos, neste caso o m6todo 6 private, portanto, escondido. O efeito 6 que um novo e acessivel m6todo f lipper 6 criado. Assim, nXo ocorre
B, C, D
e

polimorfismo neste exemplo; o m6todo chamado 6 simplesmente o da classe-child, e neo ocorre nenhum erro.
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

estio corretas. A e D sloexemplosde retornos covariantes, ouseja,

subtipos de

Plant.

Flower

Tulip

sio ambos

B est6 incorreta,

String

nlo 6 um subtipo de Plant. (Objetivo

1.5)

9. D est6 correta, Woop

herda um

Hmpf

de

zing.
5.5)

A, B, C e E estlo incorretas com base no exposto acima. (Objetivo

l0.A,B,EeFestiocorretas.AeBsioexemplosdesobrescrigXo;especificamente,B6umexemplode
sobrescrigio usando-se um retorno covariante. E e F sio exemplos de sobrecarga.

D estio incorretas. Sio de sobrescrigio inv6lidas, porque


invilidas porque
os seus

os seus tipos de retorno sio incompativeis. E sio

sobrecargas

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


12.

base no

exposto acima. (Objetivo 1.5)

A resposta C est6correta.

A
13.

refere-se ao encapsulamento, B refere-se ao acoplamento

refere-se ao

polimorfismo. (Objetivo 5.1)

A e B estio corretas. Entretanto, no tempo de execugio, A langari uma ClasscastException porque refere-se a um objeto Dog, o qual nio necessariamente s ericapaz de realtzar tarefx deBeagle.
C
e

dogl

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

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

AtribuiE6es

Obiefivos pqrq q certificqe6o


I I I r I t
P&R
Usor Membros de Closses Desenvolver C6digos Wropper e de

Autoboxing Determinor os Efeitos de se Possor Vqri6veis o M6todos


Reconhecer Quondo os Obietos se Tornom Quolificodos ooro o Coleto de Lixo

Argumentos de linho de comondo poro o m6todo Moin


Exerc(cios r6pidos
Teste

individuol

102 Copftulo 3: AtribuiE6es

Pilha e Heap
Para
a

- Uma Revisio
virias partes (m6todos, variiveis
e

maioria das pessoas, entender os fundamentos sobre a pilha e o heap facilita bastante a comPreensio de t6picos passage* d. o polimorfismo, threads, exceg6es e coleta de lixo. Nesta segio, nos limitaremos a uma "rg.r*.ntos, visio geral, mas expan&remos esseJt6picos virias vezes ao longo do livro. como
a

No gerd,

objetos) dos programas emJava residem em um dos dois seguintes lugares da riem6ria, a pilha ou o heap. Por agora, nos preocuparemos apenas com tr6s tipos de coisas: varilveis de instAncias,
as

vari6veis locais e objetos:

I r

As vari6veis de instAncias e os objetos residem no heap.

Asvarilveislocaisresidem napilha.
e

Vejamos um programa emJava,

como os seus diversos pedagos sio criados

mapeados na pilha e no heap:

l-. class Collar {


2.

3. class Dog { 4. Co11ar c; 5. String name;


6.

// vari6vel de instAncia / / vari6vel- de instAncia


{

7.
B.

public static void main(String [] arss)

Dog d; / / vari1vel 1oca1: d 9. 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
alguns pontos principais:
e

do heap depois que o programa atinge

linha

19.

Em seguida, apresentamos

objeto

String

Vari6veis de instAncias setName go O

dogName

name

dog

main

()

pbleto co11ar

Figuro

3-l

Visto gero/ do pilho e do heop

JAVA

IO3

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.

I r r I r r r r I I I

LinhaT-main ( ) 6colocadonapilha.
Linha 9 - a variivel de referAncia

d
6

criada na pilha, mas ainda nio existe um objeto Dog.


e6

Linha Linha Linha Linha

10
1

- um novo objeto oog

criado,

atribuido i variivel de referAncia d.

- uma c6pia & vari6vel -

de referAncia

d 6 passada para o m6todo


e

go

()

13 14

o m6todo go ( ) 6 colocado na pilha, com o parimetro


6

dog como umavariivel local.


de

- um novo objeto co11ar

criado no heap,

atribuido ) vari6vel de instAncia

Dog.

Linha17-setName() 6adicionadoipilha,comoparAmetrodogName comoasuavari6vellocal.


Linha
18

- a variivel

de

instincia name agora tamb6m

se

re{ere ao objero

String.
aiko.

Repare que duas vari6veis locais difermtesreferem-se ao mesmo objeto oo9r. Repare que uma vari6vel local
e

uma variivel de instAncia referem-se ambas ) mesma String

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:

// char literal 42 // inE literal false // booTean literal 2546789.343 // double literal

-b'

Literais inteiros
tr6s maneiras de representar nrimeros inteiros na linguagemJava: decimal (base 10), octal (base 8) e hexadecimal (base 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.
16).

Hi

Literais

Os inteiros decimais nio precisam de explicagio; voc6 os tem empregado desde a primeira s6rie escolar 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: ou at6 antes disso.

decimais
Hi

int length =
Literais
inclusio

343;
6

octais
de

Os inteiros octais usam somente digitos de 0 a7 .Emlava, o inteiro um zero na frente do nrimero. como vemos abaixo:

representado na forma octal com a

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 =

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
Literais hexadecimais Os nrimeros hexadecim
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 Todos


esses

0xcafe

siov6lidos.

especificados como

literais inteiros (octal, decimal e hexadecimal) sio definidos como int por padrXo, mas tamb6m podem ser 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,

double
f

loat

o nime ro I1,3QI87 4.9881024 6 o valor literal. Os literais de ponto flutuante sio definidos como (64 bits) por p adrio, ponanto, se vocA quiser atribuir um literal de ponto flutuante a.umavariSvel do tipo (32 bits), tenl que anexar o sufixo F ou 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

definido como

booleanos sio a representaglo do c6digo-fonte para valores boolean. Um valor boolean s6 pode ser 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++".

t = true; // V6l-ido bool-ean f = 0; // Erro do compilador!


boolean
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

produzirlo erros

de

compilador:

char e = -29; char f = 70000


incluindo
os caracteres de

// Possivel perda de precisSo; precisa de uma conversSo // Possivel perda de precisSo; precisa de uma conversSo
se quiser representar um caractere que nio possa ser digitado como um literal, alimentaglo de linha, nova linha, tabulagio horizontal, backspace e aspas simples e duplas.

VocA tamb6m pode usar um c6digo de escape

char c = '\"'; char d = '\n';

// Aspas duplas // 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
exemplo com duas maneiras de representar um literal de string:

um

Strinq s = "BrII Jov"; System.out.println( "8i11" + ",Joy")


Embora
as

strings nio sejam primitivas, foram incluidas nesta segio porque podem ser representadas com valores literais 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, variivel que estar6 i esquerda. Bem, certo, mas nio espere ser avaliado com algo do tipo:

para atribuilo

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

bits.
objea?

Portanro, o valor de um avariLvelprinitiw6 evidente, mas o que estaria dentro de um dep6sito de

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

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


segur:

o c6digo a

int x = 7;

/ /

/ / aurflqrvqv arri1-rrlinin

ffLE!4f

I ifar-1

int y = x + 2; // atribuiqdo inL z = x * y; // atribuiqao


O mais imponante
a

com uma

expressao (incluindo um valor

literal)
int.
Se

com uma expressao


voltarmos ao

lembrar

6 que

um inteiro literal (como 7) 6 sempre implicitamente um tipo

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 ficar estranhas. O c6digo a seguir 6 v6lido,

int.

Aqui,

as coisas

comegam a

byLe b = 27;
mas somente porque o compilador compafiaautomaticanenrao valor literal para o tamanho de um tipo palavras, o compilador executa a conuersdo. O c6digo anterior 6 id6ntico ao seguinte:

byte. Em outras

k,,F^ ' vrus h -- /L,-r^\ ! \!rus/ 27; // Converte explicitamente o valor literal inteiro para um tipo byte

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.
Parece que o

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 - mesmo se esses tipos byte forem muito pequenos. Multiplique um tipo Certo, agora por um byte e ter6... Um tipo por um e ter6 um tipo int. Divida um tipo chegamos )pane estranha. Veja isto:
Sabemos que um

int

short

int

short

int.

byte b = 3; byte c = B; byted=b+ct

problemas, 3 cabe em um byt.e / / Sem problemas, 8 cabe em um byte / / xeo deveria ter problemas, a soma dos dols bytes / / cabe em um tipo de byte
Sem

//

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

primitivos anteriormente neste capinrlo, na seglo de objetos foi abordada no Capitulo 2.

de atribuig6es, mas agora, a

um tipo em outro. Examinamos a converslo de tipos discutiremos com mais detalhes. A conversio

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

um

valor int

sempre cabe em um long

(Jma conversio explicitatem o formato

seguir:

float a = 100.001f; int b = (int)a; // ConversSo explicita, um tipo de j-nt


double d = 100L;

um

tipo de float

pode perder informag6es

como

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:

//

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


^1 ^^^ UIdDD LqDLTITIJ ^-^Ll-^ \
r

eo

comPilactor sabera drsso:

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


)

POntO

um um Quando voc6 rconverter r rnrimero de ponto flutuante, em ,l tipo inteiro, o valor perder6 todos os digitos depois do I r. I ' a 1 . ^ decmal. 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


(o
ala<c l-acf ira I

executado adequadamente. Mas, o que aconteceria

se

valor

long

fosse

muor

que

t27

maior nrimero que um byte pode armazenar)? Alteremos o c6digo para descobrir:

public static void main(String [] args) { long 1 = 130L; byte b = (byte)1; System.out.println("The byte is " + b);
]
O c6digo
O; --.tJovd

ser6

compilado adequadamente,

quando o executarmos, obteremos o resultado

seguir:

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

loat

de qualquer

valor

atribua-o

um tipo

short

usando a converseo.

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
atribuir um valor literal que
seia

muito grende para


E

avariivel

Tamb6m veremos um erro do compilador

se

renrarmos

ele saiba que

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:
llactR\rl- aq i:rr: . q. .

possroJ_e l aa- or f : h^6ri 1-.1 ^ -Loss ^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 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


Isso nos leva aos operadores compostos de atribuigXo.

ocorrer quando

esses

bits superiores forem eliminados".

O c6digo a seguir seri compilado,

byte b = 3; //
e

Sem

problemas - adiciona 7 a b (o resultado 6 10)

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


conteildo da aari,iuel da direita seni copiado,

voc6 atribuir uma vari6vel primitiva aoutra,

por exemplo,

int a = 6; intb=a;
O c6digo anterior pode ser lido como: "Atribui o padrio de bits do ntmero padrio de bits de a e insere a c6pia na variivel b.
Portanto,
IJsamos
a

I variivel

int

a. Em seguida, copia o

vari6veis, agora, contem o padrio de bits do nrimero 6, mas nio apresentam outro relacionamento. vari6vel , somente para copiar seu conterido. Nesse momento, as duas vari6veis possuem conteridos id6nticos
as duas

(emoutraspalavras,uakresidnticos),massealterarmososconteidosdea
Examine o exemplo abaixo:

oub,aoutravari6velnloser6afetada".

class Val-ueTest { public static void main (String ll args) { int a = 1-0; // Atribui-se um valor a a

l0 Copfiulo 3: Atribuig6es
System.out.println("a = " + a); intb=a; System.out,println("a = " + a + "after change to b");
)

saida desse programa serA:

tjava ValueTest a=10 a = 1-0 after change to


Observe que o valor de
duas

a permaneceu igual a 10. O ponto chave a lembrar 6 que mesmo depois que voc6 atribuir a a b, as 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 referncia de objeto da maneira abaixo:

Button b = new Button0;


A linha anterior executa tr6s operag6es essenciais:

I I r

Cria uma vari6vel de refer6ncia chamada b, do tipo

Button.

Criaumnovo obieto
Atribui
o objeto

Button

namem6ria.

zutcon

rec6mcriado ) vaiivelde referlnciab


a

Voc6 tamb6m pode atribuir o valor nul1 vari6vel nio referenciar6 nenhum obieto:

uma vari6vel de referncia de objeto, o que significa simplesmente que a

Button c = null;
A linha anterior cria um
espago para gera realmente um objeto Buuon.
a

vari 6vel de rcfer1neiaButton (o dep6sito de bits para um valor de refer6ncia) , mas

nio

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


vglrfv

{ /\ I r

nrrlrlin

rzniA

AnFnncfrrff vveLBLL\/

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.

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
No c6digo anterior, vimos que Foo possui um m6todo doFooStuf

tamb6mniohaver6problemasseeleforumobjetoBar,jiqueBarherdouom6tododoFooStuff

).Voc6niopode

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

'I1I

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

stati-cints=343; int x; {x=7;intx2=5;} Layouto { x += B; int x3 = 6;}


rrnid dnQFrr++l\ I

inty=6; for(intz=0iz<4;z++li y+=z+x;


] ]

/ // // // // // // //
/

classe

vari6vel est6tica var!6ve1 de instAncia bLoco de inicializaqdo construtor


m6Lodo

vari6vel 1ocal bl-oco de c6digo 'for'

]
Como acontece com
escoPo:
as

vari6veis em todos os programas Java,

as deste

programa (s, x, x2, x3, y

e z)

t6m todas um

I I I I I I

s 6 umavariivelstatic. x 6umavariiveldeinstAncia. y 6 uma vari6vel local Qs vezes chamada de vari6vel "local de m6todo").
z E.umavariiveldebloco.

x2
x3

|umavarilvel
6

de bloco

init, um tipo

de

variivel local.

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: t6moescopomaislongo;elassiocriadasquandoaclasse6carregada,eduramportodoo
6

I Asvari6veisstatic r I I

tempo em que a classe permanecer carregada naJVM.


As vari6veis de instAncia sio o segundo tipo mais longevo; elas sio criadas quando uma nova instAncia criada, e existem at6 que a instAncia seja removida.

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

Tentaracessarumavari6veldeinstAnciaapartirdeumcontexto

static

(normalmenteapartirdemain

()

).

class ScopeErrors { i-nt x = 5; public static void main(Stringll args)

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


]

Tentar acessar uma vari6vel local

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


\,
L

]
vvrv vv!

y++;
)

t/ / /

Ltav ^<^

LUrttIJf ^^-^il-

Jqr

,,;'lnaal rvuqt y E

: q

nn/\ \ / vv

Tentar usar uma vari6vel de bloco depois que o bloco de c6digo

jA

terminou

de executar.
a

E bastaote co-n- declarar e usar uma variivel dentro de um bloco de c6digo, mas cuidado para neo tentar usar depois que o bloco finalizou:

vari6vel

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 a

maneira 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
Tenba um caidado eEecial cum

o E)GME
efflr
de escEo de blocos de aidigo. Vocd podeni ai-los em

swiLches,

try- catctres,

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
a

umidueis de instdncia (tarnb|mchamadas de vari6veis membros) sio vari6veis definidas no nivel da classe. Isso significa que 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


classe e

um membro da

classe,

nio

pois esti dentro das chaves iniciais dessa

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
Vari6vel de refer6nciade obieto

Valorpadrio

nu11 (nio faz refertncia anenhum objeto)

byte, short, int, long float, double


boolean char
AOTRABALHO
Voc6 deue inicialiqar todas as suat uariiueis,

0.0
-f !4Abe ^^

'\u0000'

nesnl

se estiuer

pmgramadores

qtre precisarem

faryr

a manutengdo en sea aidigo (dEois qae

atribaindo a elas o ualor padrdo. Sea cr6digo fcanl nais fricit de ser lido; os 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;


nrrtrl ic (t-rina

vari6,ve1 de referGncia de instAncia


I I

nal-rFit- urs \ / l6/\ Ysurf

return t.it1e;
1

public static void main(String [] args) { Book b = new Booko; System.out.println("The title is .. + b.getTitleO );
]

I4

Copitulo 3: AtribuiE6es
Esse

c6digo seri compilado adequadamente. Quando o executarmos, o resultado seri:

title is nu1l A variivel title nio foi explicitamente


The
variivel de instAncia
ser6

inicializada com a atribuigio de uma string, portanto, o valor da 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

nuII.

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

Quando tentarmos executar

a classe

Book, a JVM produzirS, o erro

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
oa in$anciado.

pnlpio aral for dularado

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 '

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
das chaves de de viagem no

tempo

seguir, o inteiro

year

definido como uma vari6vel autom6tica, porque

esr6

dentro

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
corrigir seu c6digo, precisamos fornecer um valor para o inteiro uma linha separada, o que 6 perfeitamente vilido:
Para

year.

Neste exemplo atualizado, ele foi declarado em

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)

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

bloco condicional ldgico

or

rcm

un

podeni irforrnar sempre se uma uaiduel localfoi inidaliqada antes do uto. Por exempl0, n uoci inicialiqti-la dentro de um (en outras palauras, am bloco de aidtgo que pode ndo ser executado, como o bloco de uma instrugdo , ou }oop ualor literal ou f a l- s e como altematiua), o conpi/ador saberd que a inicialiTgjdo talueq nio ocorra e podeni produ{r

true

if

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

condiriona/, cpenat para deixar o conpilador satisfeito, Voci compilador n1o eshi mtisfeito,

poder infomar com cerieqa, em algamat situagdes uoci ter,i que inicialiTar saa uaiduelfora do bloco sabe porque isso d importante seji uiu o adesiuo de pdra-cboqae: "puando o

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

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


com nul-]"

a vari6vel

de referancia

1oca1

//

Arrays locais
Exatamente como em qualquerorrtra refer6ncia aobjeto, deve-se atribuirumvaloris referncias de arrays declandasdentro de um m619d9 ante; que sejamusadas.Isso significa apenas que voc6 precisadeclarar e constnriro nio ser6 "o"y.Irio.ntanto, necessirio.inicializar explicitamente os elementos de um array.J6dissemos iso antes, mas 6 imponante 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 I ---J4vq. -- -dwL f)i mon<.i nn
.

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 =
vi4re+Y11u Jv,

a,-

Srrsl-cm 6ttf nr.irf'lh/\ruJuuerLLtvuu.y!frlLrrr\

L^.i-L+ a.rrcr9lrL

tr +: q.rrsfvrrL hoinlrt ,

r
I

"after change to b" ) ;


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

No exemplo anterior, um objeto Dimension a 6 declarado

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

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 referncias 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 na eulfrrv // Agora, y e x referenciam o mesmo objeto String ! - ^t
qtri Svstem orrf nri nl- l n 1"\/ ru!+lry nn -= \\ + \/lI t' \ J J '

'18

Copftulo 3: AtribuiE6es

/ Agora, o objeto foi alterado / /referlncia a x System.out.println("y string = " + y); x = x + " Bean"i
/
)
VocA pode achar que o objeto String armaz.enar| os caracteres as strings sXo objetos. Examinemos qual seri a saida:
9'i:rr: cf ri nft

com

o uso da

Java Bean

depois que

variivel

x for alterada, porque

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 refernciaparafa(-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 I

[Jma nova string 6 criada, deixando o objeto String original intocado.

A referAncia usada para alterar o objeto String (ou em vez disso, para criar um novo objeto String pela alteragio
c6pia do original) seri atribuida ao novo objeto String.

de

uma

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 quanto s referenciarXo o mesmo objeto Stiing. Mas quando a linha 3 for executadao em vez de alterar o objeto referengia{9 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)
oa niltras operagdu de nodtftagdo

7.3 Detenninar o efeito nbre as referncias dc olxos nos parimetros.

e sobre os

ualoru

pimitiuos quando

eles sdo passados a mdtodot que

realilam atribuipdes

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 um objeto na mim6ria (no heap). O mais imponante que voc precisa lembrar 6 que nio estari rn*rit" d. ".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 referncia, 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
Dimension originat
C:\ (e

alterar o objeto

rinico) ciado nahrta4.

Java Pro j ec ts \Re f erence> j ava Ref erenceTes t


mndirz/\ \/ r{ haia}rf srrlsrvrrL 1A fv

Raf^r6

dim =

11 11

After modifyO d.height =

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

da resryito

alinguagemJavapassaobjetos usando avariivel de refer6ncia, isso significa queempregaaparsagempnrrcfefinciano que 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) !

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

Nio. faz diferenga

int

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

( ). Por6m, doStuf f ( ) ndotemc0m0acessarauariduelde ( ) pode alterar o que f estiverreferenciando, mas nio o conterido real (padrio de 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!
original,porexemplo parachamar om6todo setName
referlncia

f.

Assim,

doStuf f

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
rF mnr{ i frz /\a); r*..,.-*--f

System.out.println("Before modifyO a = " + a); 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 6 passada para um m6todo chamado uma unidade. A saida resultante teri este formaro:

modify

) , que a

aumentari em

Refnremndifvll
rllvgf

!J

a=l

number =

depois que foi passada para o m6todo. Lembre-se de que somente uma alpia de a m6todo. Quando uma vari6vel primitiva 6 passada para um m6todo, ela 6 pasadapor ualor, o que significa "passar por c6pia dos bits davari|vel,.

Aftermodifvl) a=1 Observe que a nio se alterou


passada para o

foi

Na sala de aula
O mundo sombrio das variiveis
No momento em que vod pensou que havia decifrado tudo, viu um trecho que, na sua opiniio, deveriam estar. VocA pode ter encgntradg c6digo
manerras; examinaremos apenas
-um
a

de c6digo com

que mais provavelmente the confundir6

.com

variiveis que nlo estavam se componando da maneira variiveis sombreadas. E possivel sombrear uma variSvel de v6rias
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
myBar.barNum

is 28 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 original de Foo permanecerl intocada.

\-/oleTrvo po ro

Al

,.1. o cenrTrcocoo

Declaragio, construsio e inicializagdo de arrays (Objetivo I.3 do exame)


1.3 Desenuoluercddigo qae dulare, inicialiry
disso, usar ident'ficadores uilidos
e

unpimitiuos, affEtq

ertramt e obletos como aaidueis esfliticag de instincias e

/orais.Akn

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 r I

Como criarumavariivel de nfunciade xray (declaraio) Como criar um ofrxo de array (consrugXo) Comoprymcheroarraycomelementos (inicializagXo)
dessas tarefas e voc6

H6v6rias maneiras diferentes de executar cadauma

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

uerdade e/as s6o arrals gerencidueiq

jd

que os usam em sua estruturQ.

rcr expandidat ou mnhaidas dinamieamente quando uocd adicionar ou remouer elementos (na H,i am tipl Cnlkctinn para ama grand.e uariedade de neces$dades. Vocd

precisa de ama classficagdo nlpida? De un gwpo de objetos rcm repetigdu? Uma maneira de acersar um
encadeada?

plr

nomef ualor?

Una lista

O Capitalo 7

os

abordani com mais detalhes.

Declarando um array
tipo primitivo, seguido
Os arrays sio declarados atrav6s da descriglo do tipo de elemento que armazenario, os quais podem ser um objeto ou um de colchetes ) esquerda ou direita do identificador.

Declarando um array de tipos primitivos


int[] key; int key []; // Colchetes anLes do nome (recomendado) /,/ Colchet.es depois do nome (v61ido, mas menos legivel)

Declarando um array que referencie objetos

Threadl] threads; Thread threads [];

// Recomendado // 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 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:
6

int[5]

scores;
a

O c6digo anterior nio conseguir6 passar pelg compilador. Lcmbre-se de.que voc6 instancie realmente o objeto de array. E ai que o tamanho importari.

JVM nio

alocarS.espago at6 que

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

colchetes. especi{icando quantos elementos desse construgio de um array de tipo

int:

tipo o array

armazenarS.

new seguida pelo tipo do array, com A seguiriemos um exemplo da

int[] testscores; testscores = new int[4];

/ Declara o array de tipo int //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

referncia do
array int[ ]

FFT;T;I
0123
Valores Indices

Figuro 3-2
Voc6 tamb6m pode declarar e construir

Um orroy unidimensiono/ no pilho

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. estamoscriandoumainstdnciadeThread,mas,emvezdisso,umrinico objetodearEThread.Depois&inclusXodas instrug6es anteriores, aindanio haver6, realmente, objetos Thread! oBSERVAQAO

Nio

pene O EXAME
napilha, dtpois que uma instrugdo ou
por exenpk, qae o aidigo anteriorpmduq@enas

Contidere cuidadoumente qilantts objetos estardo


esperado que uoci taiba,

bloco do aidigofor exuutado, No exame seri objxo (o aral atribuido a uaiiuel de referncia cbamada

124 Copitulo 3: AtribuiE6es


thread). O ilnico
atribaido a
objeto referenciadopor threafu contim cinco uaridaeis de referinciaTbread, mas nenbum

objetoTbreadfoi criado ou

essas uaridueis de referincia.

Lembre-se de que os arrays devem senpreterum tamanho atribuido no momento em_que forem construidos. 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
Portanto, nlo o faga,

= new

int[]; //

Ndo

serii compilado, precisa de

um tamanho

e se voce

ver isso no teste, nio hesite em marcar a resPosta "A compilagio falhar| '

oBSERVAQAO
Voc pode uer as

pene O EXAME
e

palauras conslrair, criar

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

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

JVM precisa

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:

rnyArraylO] = new
myArray[0] myArray[0]

intt l[ ]

rnyArray = new

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

intt2l;

inti3lt

1;

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

JAVA

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)ouobjetoscitadospelasvariiveisdereferniradoarray.
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{erncia a ele. Por6m, nos referimos a arrays como, por exemplo, "um array de cinco strinp", embora isso, na realidade, signifique, "um array de crnco refernciat 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];


Animal. A pr6xima etapa

peES:

Temos_um objeto de array na pilha, com tr6s refer6ncias nu11 do tipo Animal, mas ainda nio temos nenhum objeto ser6 criar alguns objetos Animal e atribuir a eles posig6es de indice no array relerenciado por

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
elemento

pl

arralfora do intervalo. Por

exerup/0, re am

affal

knpani a

excegdo

ArraylndexOutOfBoundsExcept ion,
as

tiaer trls e/enentot, a tentatiua de acessar o

pois em ltm

affal

de tus elementos, os ualores atllidos

para

uer a tentatiua de utiliqagdo de um nilmero negatiuo clmo am indice do anE. seguir, temos exenplot de tentatiuat ud/idas e inud/idas de acesso ao affaJ. Certfique-w de reconhecer quando elas causam exagdes de tempo de

os indices serdo

0, I e 2, Voci tambin pode

exuagdo e ndo erms de nmpilador! puase todas compilador como re spostas possiueis.

petgtlntas do exame listam tanto exngdu de tempo de execugdo quanto envs de

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 int [] z = new int[2]; int Y = -3' zlyl = 4; / / ExceqSo de tempo de execugSo. y 6 um nfmero negativo
F las dos

5!

poden ser dfrceis de loca/iqar em um kop complexo, mas ese seri o momentr mais prouiuel em que suryirdo problemas con
de

os indiees

anals

perguntas do exame. ser

Um array bidimensional (um array preenchido com outros arrays) pode

inicializado da maneira

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

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:
A variivel

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

Declara uma vari6vel de refer6ncia ao array

int

chamada

dots.

Cria um array

int

de

tamanho igual a tr6s (tr6s elementos). 6,9 e 8.

Atribui
Atribui

aos elementos os valores

o novo objeto de array ) vari6vel de refer6ncia

dots.
as

O tamanho (extensio do array) 6 determinado pela quantidade de itens separados por virgulas entre funcionalmente equivalente ao mais longo descrito a seguir:

chaves.

O c6digo

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

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 ser6 atribuido ) variivel de referncia scores). O array scores tem um tamanho igual a trs, 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.

objao {ue

JAVA

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


Quofro obielos s6o criodos:
1

rsr. Oog{'Aiko"}};

objeto Dog referenciodo por puppy e por myDogs ( 0 )

orroyde Dog

[ ] re{erenciodo

pornyDogs
[1

2 obieios Dog re{erenciodos pormyDoss

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

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
scores
AFigura3-5 mostrao resultadodadeclaragio, consruglo einicializagXo deum arraybidimensionalemumainstruso.

Construindo e inicializando um array an6nimo


O sggundo atalho 6 cham ado de aalao
i nf I l l-6clq-^ra< ac an'a1 andnimo

epode ser usado para construir e inicializar um array e, em seguida,

atribui o arrayaumavari6veldeclarada anteriormente, que fagarefer6nciaaoutro aftay:

- --- -i,' {4 ,7 ,2}


; e,

testscores = new int [ ]


O c6digo anterior criouum array

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:

int

com tr6s elementos, inicializou os tr6s com os valores 4, 7 e 2,

em segu^ida,

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:

obieio orroy

2-D Cat t

I t

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 nl-rian|rlvvv vvJvvL\r, /l row Oh'iccl{)}:

Ltsv : varauq; /| // '^x^ s --<r I r^, 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, de 32 bits. Portanto, o c6digo a seguir inL armazenar6 qualquer valor que seja permitido para uma vari6vel 6v61ido:

vm arlay

int

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

que implementem

o array for declarado como um tipo de interface, seus elementos poderAo fazer refer|ncia a qualquer instAncia das classes 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

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 qualquer tamanho), mas ndo a um item que ndo seja um array inL, podeni ser reatribuida a qualquer array lnclusive valores Lembre-se de que todos os arrays sXo objetos, portanto, uma aaiduel de reueftncia de atral nio pode ser atribuida a um tipo primitivo int. O c6digo a seguir demonstra atribui$es vilidas e inv6lidas de arraln primitivos:

de refer6ncias ao objeto de array. Por exemplo, se vocA'declarar

int.

inL

um array inL, avariivel de referAncia declarada

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 refernciado 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
portanto, te

Un anal Car nio pode ser atibuido ao anal Honda. Nem todo carro i da marca Honda, an aral Honda, ele ndo comportaria o arral Car atribaido a aai,iael de refer1ncia Honda. Pens bem: am 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 .
Vocd ndo pode inuerter at atribai{6e! udlidas.
uoc6 tiuesse

dtclarado

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:

A regras

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 referncia 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 int[] bl-ocks = new int[6]; blots = blocks; / / OK, blocks 6 um array int

de arrays

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 books[0] = nunbers, //vALrDo, numbers 6 um array int
A Figura

r-nt. em vez de um

valor int

3-6 mostra um exemplo de atribuig6es v6lidas e invilidas para refer6ncias a um array.

Blocos de Inicializageo
E
falamos sobre dois lugares de uma classe onde voc6 pode colocar c6digo que realize operag6es: m6todos e contrutores. 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 referncia ao Afiay


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

cat objto cat

Cat obj6to

aluffy
-n r a o .loato uh a.r.y 8m pdo- .. t.f.stE Cat t-D . u

Variavel de referencia ao

ArayCatllll2-D

A variavel d6 referncia 2-D

SOMENTE pode s referir a um array Cat 2-O

o .loato

cahtl r.l.rlr

d. u dj.ro e .rr.y Il2-D8mrbd... I u E!.y Cat l-D

Figuro 3-6 AtribuigOes de oroys volidos Atribuig6es Inv6lidas


de Refer6ncias de

inv6lidos

Arrays

|
I

um array 1-D a uma I refer6ncia a array 2-D I B mycats = myCats [0] tOl ; | N5o 6 possivel atribuir um objeto ndo-array a // I uma refer6ncia a array 2-D I c mycats [1] = mycats [1] l2l; | possivel atribuir um objeto ndo-array a I / / Nl,o 6 uma referncia a array 1-D D myCats [0] [1] = morecats' / / N5o 6 possivel atribuir um objeto array a uma refer6ncia n5o-array // qats [0] [1] s6 pode se referir a um objeto Cat

A mycats = myCats [0]; / / Nd,o 6 possivel atribuir

"*,r,
----------*
v61.ido

---"-"--'--">

Inv6lido

132 Copitulo 3: AtribuiE6es


blocos de inicializaglo 6 bem complexa. Eles nXo t6m nomes, nio usamnada. Um bloco de inicializagdo esttitico ,6d^ oro ue7, quando a classe 6 carregada pela 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

Como voc6 pode ver,


argumentos

a sintaxe dos

. ,rio ,.iorrram

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

constnrtores , a ordem em qae 0s blocos de inicialiqagdo

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"); }
nl- ln("1st { efrullr!vuu.yt4.Ae+ I Slzstem.orri-nri

insl-a.nce init");

} } }

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


staf ir: { Svst^* arrts nvj-r1-/""nd 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 r I I

Os blocos deiriciahzagiro rodam na ordem em que aParecem.

Osblocosde'tncialuagXoest6ticosrodamumavez,quandoaclasre.6.carregadapelaprlmeiravez.
Os blocos de inicializagio de instincias rodam sempre que uma instl.ncia de classe 6 criada. Os blocos de inicializagio de instAncias rodam depois da chamada que o construtor faz a super ( )
essas regras
.

Com

em mente, a seguinte

sai

da deverifazer sentido:

1st static init

static init 1st instance init 2nd instance inic


2nd
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, Exc ept i onlnlnini ta1 i z at i onError. Veiamos um exemplo,
a

JVM pode langar um

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:


OBSERVAQ6ESpeneoEJ(AME

3)

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. \,roleTtvo poro

..f. o cefitttcocoo

Usando classes wrapper (Obietivo 3.1 do exame)


J.I
Desenuoluer aidigo que ase ar classes wr@perprinitiuas (tais como Boolean, Character, Doable, Integer, etc.), ef ou autoboxing unboxing. Discutir as dzferenpas entre as classes Sting, StingBuilder e StringBffin
e

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

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

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

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,

fntegfer
ou

i1 hteger i2

= new Integer(42); = new Integer (,.42,, 1 ;


new Float

Fl-oat f1
E

(3.IAf\

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
Char

Byte

byte
char

ou

String
ou

Character
Double

Double

String float ou String Float Float int ou String Int.eger Int long ou String Long Long short ou String Short Short 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
double
diferenciamaiusculasdeminisculascomovalortrue oufalse.AntesdeJava5,umobjetoBooleanniopodiaser
usado como expressio em um te$e

booleano - por exemplo, Boolean b = new Boolean("fa1se") ; // ndo compila com Java 1.4 ou anterior
i f /h\

ApartirdeJava5,umobjeto Boo:.earropodcserusadoemumtestebooleano,porqueocompiladorir6,f.aznr
automaticamente o unboxing do objeto para um na pr6xima seglo - entio fique alena!

boolean. Iremos

nos concentrar nas fun96es de autoboxing deJava 5

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,

Os m6todos valueOf( )

Integer i2 = Integer.valueOf("101011". 2);

/ converte 1-0101-1 em 43 / / atrlbui o val-or 43 ao


t

/ / nbi'ero
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 sio os mais freqiientemente usados e mais proviveis de estar no exame.
a seguir

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); byte b = i2.byteValue0; short s = i2.shortValueo;


double d = i2.doubleVa1ueO;

/ cria um novo objeto wrarx)er // conwerte o valor de i2's em um


/
/ / nrimi
t- i rrn ].xrf a

/
/

vm
Aa sv

outro m6todo xxxValue


4A4vvYe!

/ / / ,

Taraaar

/ mais

um m6todo

xxxValue

/ / Aa 'rnranar

Float f2 = new Float(3.14f); short s = f2.shortvalue0t


System.

out.println

(s ) ;

/ // // // //
/

objeto wrapper converxe o valor de i2's em um primitivo short o resultado 6 3 (truncado, nao
um novo

cria

arredondado)

Iobelo 3-3 M6todos wrapper comuns de conversdo


M6todo
s=static

n=excegeoNFE
ByeVdue
doubleValue FloatVdue IntValue IongVahre ShortMue
ParseX:o<42

Boolean

Byt

Character

Double

Float

Integer

Iong

Short

ParseX:o< 4z (com a base)

valueOf. s,n

valueOf

s,n

(com abase)

Tosfting

toStringi(primitivQ x
toString
s

(primitivo,
as

base)

Resumindo,

primitivexorValue$ primitive parsdGo<(String) \(lrappervahrcOf(String)

assinaturas essengiais dos m6todos wrapper de conversio sio:

-paraconverterumtilfrapperparaumprimitive - para converter um String para um primitive -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


Alguns exemplos desses m6todos em agio:

do tipo que chamou o m6todo.

136 Copitulo 3: Atribuiqoes double d4 = Double.parseDouble ("3.14") System.out.println("d4 = " + d4); Double d5 = Double.valueOf ("3. 14" ) ;
;

System.out.println(d5 instanceof Double long L2 = Long.parselong("101010", 2); System.out.println("L2 = " + L2) ; Long L3 = Long.vafueOf("101010", 2t; System.out.println("L3 value = " + L3);

/ converte um Strinq em um primitivo // o resul_tado 6 "d4 = 3.14" / / cria um objeto Double // o resultado 6
/

Os exemplos abaixo envolvem o uso da base como argumento (nesse caso, biniria):

/ // // //
/

bin6ria para um primitivo o resultado 6 "L2 = 42' Strrng bin6ria para objeto Longl o reswLtado 6 "L3 value = 42"
S:uring

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

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 ) , que com cefteza pode ser encontrado em todas as classes. Discutiremos mais o m6todo ) no capitulo sobre Conjuntos, mas, por enquanto, enfocaremos como esse m6todo est6 relacionado com as classes wrapper que, como sabemos, ) sem sio marcadas com f ina1. Todas as classes wrapper possuem a versio de uma in$6ncia de

toString (

atgamentls

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 =
Estudar a Tabela 3-3

376"
as

diferengasentre

xxxvalue( ),parseXxx( ) evalueOf (

6.

melhor maneira de

se

preparar para esta segio do teste.

Se

voc6 conseguir entender bem

),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; int x = y.intValueO;


x++,'

/ cria / / abre
/
/ / rrca aql-a

JAVA

I37

y = new fnteger(x),'
Svstem orrl- nrinf
vgu.yt4rrUJlr\f_

/ / fecha novamente
= " + it. / / exibe

lnI"rr

Agora, com o novo e aprimorado lava 5, voc6 pode usar

Integer y = new Integer(557)


Y++ i

System.out.printl-n("y = " + i);


Ambos os exemplos produzem
a saida:

/ // // //

cria abre, incrementa,


fecha novamente

exlbe

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. 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 =
T- | rllLeljer ^-^e ^ -

567;
y,

/ cri-a um wrapper / / atribui uma segunda vari5vel / / de refer6ncia AO wrapper


/

System.

out.println

(y==x)

Y++ i

System.out.println(x + * " + y); System. out.println (y==x) ;


O que produz a saida:

/ // // // // //
/

verifica se elas estao se referindo ao mesmo objeto abre, usa, fecha novarnente
exibe os valores verifica se elas estao se refcri ndn : ntrietos diferentes

Erue

567 568

false
Assim, nos bastidores, quando o compilador chegou

linha y++; ele teve de substitui-la por algo como isto:

int x2 = y.intValue0 ;
x2++;

y = new Integer(x2);

/ abre // usa / / fecha novamente


/
a

Como suspeit6vamos, precisa haver uma chamada

new em algum lugar do c6digo.

Boxing, ==requalsQ
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
Acabamos de usar

::

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 m6todo equals ( ) os consi&ra iomb sendo "significativamente equivalentes", e, portanto, retorna

valor

int,

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
Este exemplo produz a saida:

equa1" ) ;

object meaningfully equal


same Ugh! O maodo equals ( ) parece estar funcionando, mas o que aconteceu com

diiendoqueil- ei2

sXoobjetosdiferentes,quando:: est6dizendoquei3

economizar mem6ria, duas instAncas dos seguintes objetos wrapper foremo mesmo:

: : s : Por que razio : est6 nos ei4 sioomesmoobjeto?Para. . serio sempls : : quando os seus valores primitivos
! ? !

I I r I

Boolean

Byte

character de\u0000at6\u007f (7f 6I27 Short ernteger de-I28a&127

emdecimal)

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

t
.

System. out

println

++s ) ;

/ abrindo / / abre, incrementa, encapsula


/

novamente

return !ifSo;
J

/ abre, reLorna o inverso

oBSERVAQoES pene O DC{ME


I-*mbre-se de qae as uaiiueis de referncia 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

Pzrqae

Ette aidigo conpila unproblemas, mat aJI/M knga umaNullPointerException quando tenta ehamardoSXuf 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

aalores de retomo udlidot (incluindo retnrnls coaaiades)

um mitodo eshi sobresmuendo oa sobncamgando comtanente ouho mitodo, para o mitodo en questdo.

identifcar

5.4 Dado un ceniio, dueruolueraidigo que dulan ef or ebame mdtodat sobrescritos ou sobrecamgados...

Sobrecarregando da Maneira Dificil

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:

- Correspondncia

de M6todos

r I f

Ampliago
Autoboxing Var-arp
Quando umaclassetem m6todos sobrecarregados, umadastarefas do compilador6 determinar qual m6todo usarsempre nlo usanenhumrecurso novo deJava5:

que encontrarumachamadaao m6todo sobrecaregado. Vejamos umexemplo que

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


menor argumento que seja mais amplo do que o parAmetro.

se

encontrada,

JVM

usa o m6todo com o

VocA pode verificar que, se houver apenas uma versio do m6todo go ( ) , e ele usar um double, essa versio todas as quatro chamadas a go ( ) .

se

r|usaAapara

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

permitiria que go ( )

se a tnica versio de go ( ) fosse a que usa um Integer, o recurso de boxing de Java 5 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:

Como vimos anteriormente,

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 = qo{b,b);
)

5;

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

A ampliagio A ampliagio
as

6 6

preferida em vez do boxing preferida em vez dos var-args


6

Neste ponto,

mentes curiosas querem saber: o boxing

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 significaria? Voltemos o nosso raciocinio para a nossa atribuigio polim6rfica favorita:
e, em caso

positivo, o que isso

Animal_
Mantendo

a = new DogO;
mesmo raciocinio, uma chamada poderia ser:

esse

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
| / / / ^^-^ IJAL q ..* UrL T ^6!V1r9

um

Inteqer

void test (Long x) {


]

I--embre-sedequenenhartadasclasseswr@perpodeseamp/iardeumaparaoutralByLes
ndo
se

ndoseampliamparashorts,Shorts

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

WidenAndBox.

java: 5 : applied to (byter

java. lang.Long) in WidenAndBox cannot be


de ampliagio para

Mas o 6 estranho que o compiladorPODE fazerumaoperagio de boxingseguidaporumaopera$o 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


qrrqf6m sJ p Lvlr!. nrrtfrrufLL vqu.}/t nriniln /Lr?\ t, . \p-

um

objeto Byte

public static void main(String [] args) t byte b = 5; go(b); // este byte pode ser transformado
) )
Esse

em um

Object?

exemplo compila (!), e produz

a saida:

Uau! Eis o que aconteceu nos bastidores quando o compilador, m6todo go O :

depois aJVM, chegou

linha que chama o

1. O byte b foi encapsulado com boxing em um Byte. 2. A referncia 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
um objeto do tipo Object neste cenirio, apenas um objeto do tipo Byte!).

houve

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
correspond6ncia de um m6todo? Vejamos:
a

ampliagio ou com o boxingemum cenirio de buscapela

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); box_vararg(5,5) ;

// precisa ser ampliado e usa var-args / / preclsa ser encapsul-ado com boxing e usa var-args

JAVA

'143

]
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 I r r I

A ampliagio de primitivos

usa o

"menor" argumento possivel do m6todo.


e

Usados individualmente, boxing

var-args sio compativeis com

sobrecarga.

NAO

possivel ampliar de um tipo wrapper para outro. possivel ampliar e depois fazer boxing.

@-tnt frlha.;
nlo pode se tornar um Long)
se

NAO

(Jm

int

E possivel fazer boxing e depois ampliar. (Um args com ampliagio ou com boxing.

int

pode

tornar um Object, via Integer.) E possivel combinar var-

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)


gmantido

T.4Dadoumexemplodealdigo,reconheceropontoemqueumoletosetornaqualifcadoparaacoletadelixo,edeterminaroquedeoquendoi pek $stema de colcta de lixo. Reeonhuer 0 cnnpnftamentr de Slsten.gc e dafnaliryg1o.

Visio total do gerenciamento da mem6ria e da coleta de lixo


a seglo pela qual voc6 estava esperando! Finalmente chegou do gerenciamento da mem6riae coleta de lixo.

Esta 6

hora de nos aprofundarmos no interessante universo

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.

O gerenciamento

+,queniooferecemacoletaautom6ticade Essaopera$opodeserexecutadavAiuvezns,eemlinguagenscomoCouC+ 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 cincia 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.
heap

Un

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


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

Na seglo anterior, aprendemos

removidos da mem6ria.

Anulando uma refer6ncia


Como discutimos anteriormente, um objeto
se

que possam ser alcangadas. E claro que se nlo houver refer6ncias alcang6veis, nio diz respeito, ele ficar6 apenas flutuando no espago, sem ser utilizado ou acessado,

torna qualificado para a coleta de lixo quando nlo h6 mais referAncias a ele imponari o destino do objeto. No que nos nio sendo mais necessirio.

A primeira maneira de remover

a refer6ncia a um objeto 6 configurar com estiver apontando para ele. Examine o c6digo a seguir:

nulf

avari|vel

de refer6ncia que

JAVA

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


nrrhl i n al :cc

Date

t
I

fl:rl-r:naE'ani-nrrz

public static void main(String [] args) Date d = getDateo


doComplicatedstuff
)
.i^ n"k] PUUIIL -f-f.i^ DUaUfL nrl6 uqus d6l-n:f6/\ YeLUqre\/ tL

();

System.out.println("d = " + d) ;

Date d2 = new lateo; StringBuffer now = new StringBuffer (d2.toStringO );


qircl- am efrevrrr!vuu.vrflrvf ^11|nri n|- l n lnar^rl
.

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
tiaervm referincias u,ilidas! se tornar qualificados para a coleta de lixo, netmo Consideramos esse cenirio como ilbat de isolamento. rc ainda

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:

Um exemplo simples seria uma

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

i4.i

i3; // i2 refere-se a i3 i4; // i3 refere-se a i4 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 nI I

JAVA

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

-} .@.,

referGncia ativa lndica uma referCncia

public class LosE { public static void rnain(Strinq {} args) Lost x = new tost O: x = nul1;
docomplexstuff ( ) :
)

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

Runtime
System.

rt. = Runt.ime. getRuntime ) ; out.println ( "Tota1 JVM memory:


(

7.
8.
q

l_0.

System.out.println( "Before Date d = nul1; for(int i = 0;i<10000;i++) d = new Date0; d = nul1;


)

Memory

"

+ rt.totalMemoryO ); rt.freeMemoryO );

11.
1,2.

13. L4.

out.println ( "After Memory = r' + rt. freeMemory ( ) ) ; rt.gc(\; // uma alternativa a System.gco System.out.println("After GC Memory = " * rt.freeMemoryO );
System.

148 Copitulo 3: AtribuiE6es

15.
1-6. ]

Agora, executaremos o programa

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 nem toda a mem6ria 6 liberada com uma passada de GC.
as

linhas 13 e 14 dentro de um loop. VocA poder6 ver que

Fazendo uma limpeza antes da coleta do lixo


A linguagemJava fornece um mecanismo para que algum c6digo
classe

o m6todo finalize( )
executado imediatamente antes que um objeto seja

seja

finalize( ) quetodasasclassesherdamda Object. 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 ( ).
excluidopelocoletordelixo.Essec6digoficar6emumm6todochamado

Cuidados relacionados com finalize( ) Hi alguns conceitos relacionados com f inalize ( )

que voc6 precisa lembrar:

I r

Para qualquer objeto, f

Chamar

inalize ( ) seri chamado apenas umavez (no maximo) f inalize ( ) pode resultar em salvar um objeto da exclusio.

pelo coletor de lixo.

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 instAncias residem, com os seus objetos, no heap.
as

variiveis locais residem na pilha,

e as

vari6veis de

Revisamos os literais v6Llidos para tipos primitivos e Strings, e depois discutimos os fundamentos da atribuigio de valores 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

I49

as implicag5es de se usar variiveis nio-inicializadas, e a imponincia do fato de que as vari6veis locais 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

Abordamos
deaem

do "sombreamento".
O t6pico seguinte foi
a

criagio de arrays, no qual falamos sobre declarar, construir


e

inicializar arrays uni

multidimensionais.

Falamos sobre arrays an6nimos

sobre arrays de referOncias.


e de

Em seguida, revisamos os blocos de inicializagio est6ticos


Caramba!

instAncias, qual a apar6ncia deles e quando eles sio chamados.

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 E
D D D E fl

Asvariiveis locais (vari6veis

de

m6todo$ residem napilha.

Os objetos e as suas variiveis de instincias residem no heap.

Literais e Conversio de Tipos Primitivos (Objetivo 1.3)


Osliteraisintegerpodemserdecimais,octais(p.ex.013)
Os literais para

ouhexadecimais(p.ex.Ox3d).

longs

terminam com

L ou 1.
ou com d.

Os literais float terminam com Os literais

F ou f , e os literais double terminam com um digito, com D


e

booleanos sio true

alse.

Os literais para

chars

sio um 6nico caracrer dentro de aspas simples: 'd'.

Escopo (Objetivos 1.3 e 7.6)

E E

O escopo refere-se

ao

tempo de vida de uma vari6vel.

Existem quatro escopos bisicos:

E 0 fl
D

As variiveis estiticas vivem basicamente pelo mesmo tempo que

as suas classes.

As vari6veis de instAncia vivem pelo mesmo tempo que os seus objetos. As vari6veis locais vivem pelo mesmo tempo que os seus m6todos na pilha; entretanto, se o m6todo chamar outro m6todo, elas ficam temporariamente indisponiveis. 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 B

As express6es integer sempre geram um resultado com o tamanho de Os nrimeros de ponto flutuante sio implicitamente doubles (64 bit$.

int,

nunca menor.

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
As varilveis de refer6ncia podem referir-se
a subclasses a

um objeto.

E E

do tipo declarado, mas nio a superclasses.

Aosecriarumnovoobjeto,p.ex.,Button b = new ButtonO;,tr6scoisasacontecem:

E B tr

Cria-se umavari6vel de refer6ncia chamada b, do

tipo Button

Cria-seumnovo obietoButton
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)

Quando um array de objetos for instanciado, os objetos do array nio serio instanciados automaticamente, mas todas refer6ncias receberio o valor padrio nul1. Quando um array de tipos primitivos for instanciado, todos os elementos receberio seus valores padrio.
As vari6veis de insAncia serio sempre inicializxlas com um valor padrlo. As vari6veis locais/autom6ticas/de m&odo nunca recebem um valor padrio. la, receberiumerro do compilador.
Se

as

tr tr E

voc6 tentar usar uma antes de inicializ6-

Passando vari6veis para os m6todos (Obietivo 7.3)

D D D 0 tr E

Os m6todos podem usar tipos primitivos e/ou referAncias a objetos como argumentos. Os argumentos dos m6todos sio sempre c6pias. Os argumentos dos m6todos nunca sio objetos reais (podem ser referncias a objetos)

Um argumento primitivo 6 uma c6pia totalmente desvinculada do tipo primitivo original.


Um argumento
de refer6ncia 6

outra c6pia de uma refer6ncia ao objeto original.

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 tr E

Quando vocd declarar um array, os colchetes poderio ficar

esquerda ou

direita do nome.

Nio

considerado vilido incluir o tamanho de um array na declaraSo.


a

Voc6.precisa incluir o tamanho de um array quando o construir (usando new)

menos que esteja criando um array

anorumo.

E fl fl 0 B tr E E E

Os elementos de um array de objetos nio sio criados automaticamente, embora os elementos de arrays primitivos
recebam valores

padrto.
se

Voc receber6 uma excegio NullPointerException referenciar um objao reai. Os arrays sio indexados comegando pelo zero.

tentar usar o elemento de um array de objetos

e esse

elemento

nio

ArraylndexOutOfBoundsException ocorre
Os arrays possuem umavariivel

se

vod

usar um valor de indice

invilido.

length,

cujo valor 6 a quanti&de de elementos do array.

O ultimo indice que voc6 poder6 acessar seri sempre uma trnida& menor do que o tamanho do array.
Os arrays multidimensionais sio apenas arrays compostos por outros arrays. As dimens6es de um array multidimensional podem ter tamanhos diferentes.
de tipos prirnitivos aceitar6 qualquer valor que possa ser promovido implicitamente ao tipo declarado para o array. Por exemplo, uma vari6vel pode ser inserida em um array

Um array

q6e

int.

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

vod atribuir um

array

uma referAnc ia de array

ji

declarada, o array ter6 que estar na mesma dimensXo

&

refer6ncia ao

JAVA qual for atribuido.

'I5I

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.


as regras

Se

existirem v6rios blocos init em uma classes, eles seguem

indicadas acima, e rodam na ordem em que

aparecem no arquivo-fonte.

Usando wrappers (Objetivo 3.1)

E E

As classes wrapper e$io correlacionadas aos tipos primitivos. Os wrappers t6m duas fung6es principais:

0 E
U

Encapsular tipos primitivos para que possam ser manipulados como objetos;

fornecer m6todos utilit6rios para tipos primirivos (geralmente convers6es).

Os construtores wrapper podem usar uma String ou um tipo primitivo, exceto para Character, que s6 pode usar um tipo char. As trs 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
16.
bases

(normalmente) diferentes de 10; a base biniria tem radic a72,

oed,:

8e

hex

Boxing (Objetivo 3.1)

tr
D

A partir deJava 5, o recurso

de

boxing lhe permite converter tipos primitivos em wrappers ou convener wrappers em

uPos Prurutrvos automatrcamente.

Usar

que I27) serio

:-

com wrappers 6 complicado; v/rappers com os mesmos valores baixos (normalmente os menores

: :,

rnzs yalores maiores

nlo serio

::.

Sobrecarga Avangada (Objetivos 1.5 e 5.4)

D 0
Cl

A ampliagio

de

primitivos

usa o

"menor" argumento de m6todo possivel.


a

Usados individualmente, o boxing e os var-args sio compativeis com Y ocl


ndo pofu
ndo

sobrecarga.

ampliar de um tipo wrapper para outro. @-Ulf faUra.; ampliar


e

D O tr

Voc6

pode

depois fazer boxing. (Um

Voc6 pode fazer boingedepois ampliar.

int nlo pode se tornar um Long.) (Um int pode se tornar um Object, atrav6s de um Inreger.)

Vod

pode combinar var-args com a ampliagio ou com o boxing.

Coleta de lixo (Objetivo 7.4)

E tr J

EmJava,

coleta de lixo fornece um nivel de gerenciamento automatico da mem6ria.


da coleta de

A finalidade
56
a

lixo 6 excluir objetos que nio possam

ser alcangados.

seja feita essa operagio.

II'/M decide exatamente quando executar o coletor

de lixo; voc6 (o programador) s6 pode recomendar que

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 B

J6queocoletordelixoniotemexecugiogarantida,
Voc6 pode desqualificar um objeto para
a

finalize (

) podenuncaserexecxtado. ).

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
F. *r

6 possivel saber.
r

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 AcompilagofalhaD 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 int int int
Eggs { doX(Long x, Long y) { return 1-; } dox(Iong. .. x) { return 2; }

dox(Integer x, Integer y) { return 3;

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,

c31D.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 ( ) ; m4. go ( ) ; Mixer m4 = m3 .m1; m5.goo; Mixer m5 = m2.m1;
)

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

B. A compilagio falha devido a um erro apenas na linha


C. A compilaglo falha devido a um erro D. A compilagio falha devido a um erro apenas na linha

apenas na linha 4.
5.

E. A compilagio falha devido a erros nas linhas

3 e 5.

F. A compilagio

falha devido

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


)

true B. fal-se true C true false D. fa]se false


A. t.rue

E. Acompila$ofalha.
ry | E r.: '4rrangaoa uma excegao no tempo de execu$o.

9. Dado: class Knowing t static final long tooth = 343L;


^F-ts.i^ - L4UIU 1^h^ f Vrr\j Uvf u tlnnn \ rvrry ^^Tf fnnfh\ uvvutl/ It

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 eJ u uvrrr. vuu ^rrf hFl . ^ri rrruf Pr n I f^^th \ .

]
)

Qual6 o resultado?

A. 343 340 340 B. 343 340 342 c 343 34L 342 D. 343 341, 340 E. 343 341, 343

E
\r

Acompilagofalha.

ari'tt. 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
de lixo. eles podem ser qualificados para coleta

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"); Long x2 = Long.valueOf("L23"); 5. long x3 = xl,,longValue$; 6. 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

I57

A. Ap6s a execugio B. Ap6s a execugio


C. Ap6s D. Ap6s
a

da linha 8. da linha 9.

a execugXo da

linha

10.

execugio da linha 11.

E. A compilagio falha F. Nunca nesse programa.


a \r. 4t r .tr rangaoa uma excegio no tempo de execugio. r i

3. Dado: 1. class Bigger { 2. public static void main(Stringl] args) 3. // insira o c6digo aqui 4. )
q1

"l

5. class Better { . enum Faster {Higher, Longer}; 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,
{ q\rql- am 611l- nri t vtsLe!.r. hf f \\r?
\\

\ I. } t J

static { System.out.prj-nt("r4 ");


]

class Hawk extends Raptor { public staLic void main(String[] args) i


qa/cf am ^rrf nri nf 1\nra ti l .

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

pre E. 11, 14 pre F. pre rL 14 G. pre r! 14


D, 11- 14
H. A ordem

b1 b2 b1 b2

b2 bI b2 bl-

13 r2 hawk 12 13 hawk 13 12 hawk r2 13 hawk

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 catch ou f inal1y. (Para o exame, acostume-se com esses fechamentos horriveis com
A, B, C e E estio incorretas com
base est6

dentro dos blocos

) )

) .)

no exposto acima. (Objetivo 1.3)


(

2. C est6 correta. Apenas

um ob.ieto tamb6m est6 qualifi cado.

Cardnoard

c1

) est6 qualificado, mas (Objetivo 7.4)

ele

tem um objeto wrapper Shon que

A, B, D, E e F estio incorretas com

base no exposto acima.

3. C est6 correta, a compilagdo falha. A declaragio


A, B, D e E estio incorretas com
base

dos var-args est A correta, mas invade usa um


a

tipo shorL,

de

modo que

o argumento 7 precisa ser convertido para esse tipo. Com

conversio,

resposta 6 B,

'a

f el'/.

no exposto acima. (Objetivo 1.3)


a

4. C est6 correta. Uma ClassCastExcept.ion

int

6langada na linha 7 porque o1 refere-se t I . Se a linha 7 fosse removida, a saida seria 4.

um

int [ ] [ ] , e nlo a um

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


e

essas declarag6es

de arrays sio v6lidas. As linha 4 e 5 demostram que arrays podem ser

B, C, D, E

F estio incorretas porque

este

c6digo compila. (Objetivo 1.3)

8. Aest6
final

correta.

AsrefernciasfL,z

ef3

assegura que uma vari|vel de refer6ncia


se

apontamtodasparaamesmainstAncia deFizz. Omodificador nio poderi ser transferida para um objeto diferente, mas f inal

nio impede que o estado do objeto


B, C, D, E
e

modifique. no exposto acima. (Objetivo7.3)

estio incorretas com

base

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

A, B, C, E, F
10.

estio incorretas com

base

no exposto acima. (Objetivo 7.3)


de refer6ncia, essa

C e E estio corretas. Quando um objeto tem uma vari6vel


no heap.

variivel reside dentro do objeto,

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

E estio corretas. Por causa dos tipos de retorno dos m6todos,

essas

chamadas requerem o autoboxing para

compilar.
e

estio incorretas com base no exposto acima. (Objetivo 3.1)

12.

definida como
os

e2 f.oi Gest6correta. IJmerronalinhal0fazcomquesejalangadaumaNullPointerExcept.ion,porque 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 referncia seja anulada, nenhum dos objetos estari qualificado, e, depois de anulada a ultima referAncia, todos
tr& estario qualificados.
base

A, B, C, D, E e F estlo incorretas com


13. C
e

no exposto acima. (Objetivo 7.4)


a

E apresentam sintaxe correta para se acessar um enum


1.3)

paftir

de

outra classe.

A, B, D e F apresentam sintaxe incorreta. (Objetivo


14.

Desticorreta.Blocosinit

static

sloexecutadosnomomentoemqueaclasse6carregada,eosblocosinit

de instAncias rodam logo ap6s a chamada a super ( ) em um constmtor. Quando existem diversos blocos um mesmo tipo dentro de uma classe, eles rodam ordenadamente, de cimapara baixo.

ini t

de

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,'
':
.;
I

,'

Oblerlvos pqru o cerllflco96o


I t
P&R
Usondo Ooerodores Exercicios r6pidos
Teste

individuol

i.i
l:ri

,"
':,,

'162 Copftulo 4: Operodores


Sevoctivervai6veis,k6alter6-las.Aumentariseuvalor,assomar6,deslocar6seusbits,asinverter6ecompataxdumas com
as

que provavelmente nurlca usar6 no

outras. Neste capinrlo, voc6 aprender6 como fazer tudo isso emJava. Adicionalmente, voce aprender6 como fazer coisas mundo reil, mas que 6 quase certo de estafem no exame.

Obietivo poro o certificoqdo

Operadores fava (Objetivo 7.6 do exame)


aritmdticos (linitados

7.5 Escreuer aidigo que @lique czffetamente os operadores @rEiados, inc/uindo os de atibuigdo (linitadot a =, *=, -=), os operadoret )=, ==, !=), o operador insanceoJ a -, +, /, 0k, ++, - -), os operadores de comparagdo (initadw a 1, 1=, 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 I

O operador * pode ser usado para adicionar um primitivo num6rico concatenagio se um dos operandos for uma String.
Os operadores
as suas

outro, ou para rea)tzar :uma operagdo de

&, I e ^ podem todos eles ser usados de duas maneiras diferentes, apesar de que, nesta verslo do exame, 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 I I

Ao

se atribuir um valor a um primitivo, o tamanho faz drfetenga. Certifique-se de saber quand ir6 ocorrer, quando a conversio explicita 6 necessiria, e quando poderao ocoffer cortes.

o uma corrvetsdo implicita

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

Ao

se

atribuir um valor aumavai|vel de referncia,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
afastar dos bits capitulo uoc
tuipicos que ndo

@roxinar IIJAO uenl

e se

da

APL Muitos

tripicos da uersd.o

utqam mais no exanel Resumindo, o exame Jaua 5 difere do exame / .4 por e 1 .4 relacionados a lperadzres flram remouidos do exame, de modo qile neste

I I I I

Operadores de mudanga de bit


Operadores bitwise

Complementosbindrios
Assuntos referentes

i divisio porzero
d @enas qae e/es ndo caem

Ndo 6 que uns tdpicos ndo s/am importantes,

mab n0 exane,

e nosso objetiuo

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

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

z).

x*=2+5;
fosse aualiada duta

forna:

x = (x * 2) + 5; // precedncia incorreta
uma ue<que a nuhiplicapdo tdn precednda sobre a adigdo. Pordrz, em ueTdisso, a exprer1o ti direita senQre
aualiada destafonna:
6 cokcada entrc paftnleses.

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


1

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

igualdade

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

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

Nrimeros
Caractetes

Tipos booleanos primitivos


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
testes de igualdade em vari6veis primitivas:
a

seguir mostta alguns

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

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

i) (x = vr
(= =)

i um inteim (e ndo un booleano/, o resultado de 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 { *,,Lli^ ^r^el1,uurru euaurc 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
s$digo cria trs vari6veis de referncia. 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:

Bt..

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

// ; e Opc]-ona1 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
[r-:E.rJ, F--

anrrm (-nl

}JLUE]

)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:
4 f! +

c - nau' v9rrllY at-rina/trf^^r'\ lvv \


: F^+-h^6^f frrDudrrus9r Cf r.i oLrrrrY,/na\ I t

/ ,

|^ \E

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 dos seus subtipos, antes de se tentar urna conversio "redutora":

instanc eof ,p^r

saber se ele 6 a instAncia de

um

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

protegeoprograrnacontraatenativadetentarumaconversio

JAVA

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

um objeto

a instincia de

lma

interface, qaando a classe do objxo

Una implenentagdo indinta ocore quando ma institcia ndo ofaq- por exenplo,

das superc/astes do oQeto implementa

una intetface,

for implenentada

,^

i pnlpio

classe

da

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 wperclasnt implementar a inteface.
Al6m dissq

(igfieando

que

pasuni

no te$e

lnsEanceof)

se algama de suas

aI se,

6 vilido testar se a refer6ncia de um objeto claro, Por exemplo:

nu11

6a

instincia de uma classe. Isso sempre resultar6 em

class InstanceTest { public static void main(String [1 args) 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

Nio

Erro de Compilagio de instanceof 6 possivel usar o operador instanceof para testar em duas hierarquias class cat { } class Dog { public static void main(String tl args) Dogd=newDogO; System.out.println (d inst.anceof Cat) ;
) )

de classes diferentes, Por exemplo, o

seguinte c6digo ndo comptlatil:

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 @atncia

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


Primeiro opetando
(referncia sendo testada)

instanceof
Resultado

Opemndo de instanceoj (tipo que compararemos com a teferncia)

null
instincia de Foo instincia de Bar instincia de Bar Foo[ ] Foo[ ] Foo[1]

Qualquer tipo de interface ou classe


Foo, Bar, Face, Obiect Bar, Face, Object

false

Foo
Foo, Bar, Face

false false

Object

Foq Bar, Face, Object

Operadores aritm6ticos
Temos certeza de que vocd est6 familiaizado com os operadores aritrn6ticos b6sicos.

I I I I

+ adiglo

x /

subtragio

multiplicagio

divisio

EIes podem ser usados da maneira padrio:

int x = 5 * 3; intY=x-4; system.out.println("x - 4 is " + y); // Exibir6 O Operador Resto (o/o)

11

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

169

A execugSo

da classe MathTest

exibiri

linha a seguir:
3

The resul-t of 15 ? 4 is the remainder of 15 divj-ded by 4. The remainder is

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

seguit:

String a = "String";
inll.r ?.

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:

i-nt c = 7,' System. out.println (a + b + c) O operador * atuafi, como um sinal de adigZo quando
,.

String3

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

vai|vela".
A regra
a

corrc tena com a

string

da

lembrar

6:

Se um dos operandosfor ama

String,

o operador

atuari

c0m0 um operador de concatenagdo de

SLrings,

forem nilrterot, o operador * funcionani como o operador de adipio.

Se ot dois @erandot

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*
Se

seri concatenado a string retornada. Mas se f oo ( operador* serdusadoparasomaro algarismo 7 comovalorretornadopor foo ( ). retornar uma

est6sendousadoat6quedescubraoqueom6todo

SLring, entio,T

foo ( ) tetotnarilt, retornar um nfmero, o


desta forma:

Finalmente, voc ptecisa sabet que 6 v6lido mistutar o operador aditivo composto

(*=) com Strings,

String s s += "45"; s += 67;

= \\A23"i

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 mas tambdm c0m0 esse resultado rcni. exibido. Mesmo bauendo pelo menot taber tdo s6 qual a saida do ctidigo que eftiuer

rcndo

neia

peryuntas que nriarAo diretamente seu conhecimento em strings, a eoncatenagdo de ftrings @ancenl em outras petguntas cada objetiuo. Faga um teste! Por exenpk, uoc6 pode aer uma linha como

di{a

d.e

de

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 static int PIaYers = 0; 2. public static void main (String [] args) { 3. System.out.println("players online: " + players++); 4. System.out.println("The value of players is " + players); 5. System.out.println("The value of players is now " + ++players); 6. 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 players ; 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

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/

aheradas, os operadoret de inmmento e dininuQdo ndo poderdo ser asados com eks compilador. O aidigo a nguir ndo nni co@ilada,

inal-,. Jd que as uaridaeis f qraQuer hntatiua defaTgr ilro

i na I
wvltari

n6o podem ser

em am

ero do

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

sea conltecinento sobre o modificador

inal.

Operador condicional
Ooperadorcondicional

6umoperadortemirio(temtrsoperandos)usadoparaavaliarexpress6esbooleanas

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:

demodo

x = (expressdo

booleana)

valor

atribuir

se

true:

valor

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 System.out.println(.'This pet status is '. + status)
,.

many

pets,,;

Voc6 poderia

l.r

o sfdigo anteriot assim:

"Configura numOf Pets igual a 3. A seguir, atdbui uma String avati|vel starus. Se numOf 4, atibur6"Pet limit not exceeded"; do contr4rio, atibwrd"too many pets".

Pets

for menor do que

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 6

Tendo dito tudo isso sobre operadores bitwise, o principal a se lembrar


OS OPERADORES BITWISE

isto:

NAO CEPU NO EXAME!

Entio por que falamos

.*"-.i

deles? Se cair nas suas mios um livro antigo de preparagio para o exame, ou se encontrar alguns 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 boolean b = true && fal-se,' s\/qram nrrt-.println("bool-ean l
)

[] args)

b = " + b)

Quando executarmos o c6digo anterior, obteremos:

JAVA

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 { public static void main (String [] args) 2. 3. if ((isrrsmall(3)) ll (isrrsmall(7))) { 4. System.out.println("Rqsu1t is true");
J

6. 7. 8.

if ((isrrsmall(6)) ll (isrrsmall(9))) t System.out.println("Rsgult is true");


]
)

e.
10.

l-1. public static boolean isltSmall(int 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. )
,.

i)

t-e.
20.
)

Qual ser6 o resultado?

? java
1<5

TestOR

Result is true i>=5


Aqui est6 o que aconteceu quando o m6todo main

( ) foi executado:

1. 2 3. 4. 5. 6.

Quando chegamos I l) foi avaliado.

linha 3, o pdmeiro operando da expressio | | (em ouuas palavras, o lado esquerdo da operagio

O m6todo

isltsmallisItSmall

(3

foichamado, exibiu

"i <

5" eretornou

uerdadeiro.

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

(7 ) ).

A linha 6 set6,avaladaagora, comegando pelo primeito operando da expressio |

Om6todo

isItSmall (6) 6chamado,eibe "i >= 5"eretorna faIse.

true, se o segundo operando for avaliado como true. 7. O mdtodo isItSmall (9 ) 6 chamado e exibe "i >= 5". 8. Om6todoisItSmall (9) retornafalse,portanto,aexpressiodalinha66false eahnirraT nuncaser6
operando; ainda h6 uma chance da expressio ser
executada.

J6queoprimeiroopetandodaexpressio ll,dalinha6,6false,ooperador llnlopoder6ignorarosegundo

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

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 I

&Endo-abreviado
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 ele a;nda dati prosseguimento e avahatS" o segundo operando, mumo quando souber q*e a expressdo seri Erue.

true,

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


contra:

// z = 7 depois deste c6digo

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 nioabreviagio 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;
como

xor false
al se
porque TANTO o primeiro operando (2 < 3) quanto o segundo (4 > 3) avdtam

A expressio actma avaJia como f

crue. booleano:
}

O operador ! (inversio booleana) retorna o oposto do valor atual de um

if ( l (? == 5) ) { Sysfem.out.println("not equal") ;
not egual
Eis um ouuo exemplo usando

pode ser lido como "se nio for verdade que 7 == 5", e a instrugio produz esta saida:

booleanos:

boolean boolean

t = true; f = false;

System.out.prinLln("! " + (t & !f) + " " + f);


produz asuda:

! true false
No exemplo anterior, repare que o teste & teve sucesso (exibindo modificou, de modo que ela exibiu f alse.

true),

que o valot da variavel

booleana f

n6o se

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 importantes do que voc aprendeu neste capitulo.

I75

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 nesse momento. direito se o esquerdo for avaliado como true, porque o resultado i|setkrcconhecido como

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
teste

6usadoparadeterminarseoobjetosendoreferidoporumavari6velderefernciapassano 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.
e

Os operadores s - - sereo usados em todo o exarne, varidvel que esti sendo atuaJizada.

**

voc6 deve prcstzraatengdo a se eles s6o prefixados ou posfixados

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
El

Os operadores de compangdo sempre resultam em um valor H6 seis operadores de comparagao:


operadores de igualdade.

booleano (t.rue

ou f

alse).

), )=, (, (=, == s l=. Os dois ultimos (-- .l-)

sio, is vezes, chamados de

Quando compata car cteres,


Operadores de igualdade

linguagemJava usa o valot Unicode do caractet como o valor num6rico.

fl

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 referncia, == retotna true somente se ambas as referncias apontatemparao
objeto.

mesmo

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
classe que esteiam na mesma hieratquia da classe.

com tipos de interface do

Para intedaces, um obieto passa no teste lado direito do operador instanceof

instanceof
.

se

alguma de suas superclasses implementar

Operadores aritm6ticos (Objetivo 7.6)


Cl
H6 quatro operadores principais: adigio, subtragio, multiplicaglo e divislo.

E
El

O operadot de testo

(o/o)

rctotnao resto de uma divis6o.

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. Os operadores *,

f,l

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 E E
Retorna um entre dois valotes baseando-se nos casos de uma expressi.o Retotna o valor depois de ? se a expressio for t Retorna o valor depois de
: se a

booleana

ser

true

ou f

alse.

rue

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 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. 5.
o. l

Boolean b;

// insira o c6digo aqui


\

7.
A.

Qual opgio, inserida indepentemente na linha 5, ir6 compilar? (I\zlarque todas as corretas)

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. 3. 4. s. 6. 7. 8.
ol

public st.atic void main(Stringtl args) t fl-oat f1 = 2.3f ; floar n il f2 = {{.42.0f1 , {t.tt, 2.3tll , {2.6f., 2.tf}} float tl t: = {z.tt} ; Long x = 42Li // insira o c6digo aqui System.out.println("true");
)

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

verdadeiro?

,{.

Um deles compilari, apenas um ser6 true.


apenas um ser6

true. C. Dois deles compilario, dois serio true. D. Trs deles compilardo, apenas um ser6 true. E. Tt6s deles compilario, exatamente dois serio true. F. Trs deles compilareo, exatamente tres sereo true.
B. Dois deles compilario, 4. Dado: crass lorK

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?

AC.

test

case

B. production

tesE case live2


6 hngada uma excegio no tempo de execugio.

D. Acompilaglofalha.

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 E

Nio 6 produzida nenhuma

saida.

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 x

x
*= *=

I80

Copitulo 4: Operodores

9. Dado:

1. class Maybe { 2. public static void main(Stringtl args) { boolean b1 = t.rue; 3. 4. boolean b2 = false; system.out.print(!fatse ^ fatse) ; 5. system.out.print(* $ + (!b1 & 1bz = true))); 6. 7. system.out.println(' " + (b2 ^ b1)) ; 8. )
q]

'.
O que
6

verdadeiro?

,d

true. B. A linha 5 produz false. C. A linha 6 produz true. D. A linha 6 produz false. E A linha 7 ptodtz true.
A linha 5 produz

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) juntos. incorreta. F estl errada

2.

B A

D usam cottetamente boxing e instanceof

estd incorreta porque os operandos est6o invertidos. C e E usam sintaxe instanceof 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

true.

JAVA

5 I8I

4 4.

B' C, E e F estio incorretas. F1 esti incorreta porque nio 6 possivel comparar um tipo primitivo com um anay.F4
(Obietivo 7.6)

usa sintaxe incoffet^Par^^cessar um elemento de um array bidimensional.

E est6 correta. Pelo falo

a abteiragdo ( | | ) neo ter sido usada, ambos os operandos sio avaliados. Uma vez que {e args[1] esta^l6mdoslimitesdoanayargs,6,langadaumaArraylndexQutOfBoundsExr':ention

B, C

D estio incorretas com base no exposto acima. (Objetivo

7.6)
se

5.

E esti correta. Nas duas primeiras


abrevia$o

vezes em que o teste i f 6 execuadq tanto x como y sio incementadas uma vez (s6 alcangax++ natercekaitetagno).Apartirdatercaraiteragdodoloop,y nuncamais6usadqporcausadooperadorde

4 6.

B, C, D, F, G

est6o incorretas com base no exposto acima. (Objetivo 7.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.

B, C, D

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

B, C, D, E, F, H e I estio incorretas com base no exposto acima . (Objetivo 7.6)

class Incr
--,,h1 l^ ^r-rl^

1,ularg ELdLru -void main(String[] args) Integer x = 7; int Y = 2,

x*=x;
rr

*-

r, - rr.

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
& nlo serve
B, C
e
d

potque

abrcizgdo para ela.

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.

B, C, D, E, G

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 I I I I I (
P&R
Usor InstruE6es if e switch Desenvolver Loops {or, do e while. Usor Instruq6es breok e continue Desenvolver C6digo com Assertivos Usor lnstruq6es try cotch e {inolly Descrever o Efeiio dos ExceE6es

Reconheceros Excec6es mqis


Comuns
Exercicios r6pidos
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 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'
se

As instrug6es
ma.reira

e swi tch sio tipos de controles condicionais/de decisio.que permitirio aseu pro gramaagt de em uma "bifurcaglo do caminho", dependendo do resultado de um teste l6gico. A linguagemJava fornece tr|s estruturas de loop difeientes - f or, whi Ie e do - portanto, voc6 poderi executar o mesmo c6digo -As exceg6es the proporcionario,uma maneira simples e repetidamente ar6 que o res"hrao ae Agu-a condigio seja true. 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

iif..enre

de execugXo associada

i manipulagio

de exceg6es.

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.

Com

Obietivo poro o certificoc6o Escrevendo o c6digo usando instrus6es if e switch (Objetivo 2. I do exame)
2./
Escreuer cfidigo qae inplenente ama instrugdo

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"


)

ou f alse. Normalmente voc6 testari es deaeter corrro resultado um valor booleano 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

A expresslo entre par6ntes

true

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

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

I85

Y=2i z += 8; a-y+x,.
A Sun considera como boa pr6tica colocar blocos dentro
"Se

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:

xfor

maior qrc 3, mtdo nnfgurc-1t eoa 2, qcom

!8

comJlx".

Contudo, as duas riltimas linhas serio executadas de qualquer forma! Elas nio {azempane acharia ainda mais confirso se estivesse recuado como vemos abaixo:

dofltxo condicional.

VocA o

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

de

el s e i f :

I r I

Voc6podeterumounenhumelse paraumdadoif,eeledevevirdepoisdequaisquerinstrug6eselse Vocdpodeterdemuitosounenhumelse


Depois que um
else

if.

if

paraumdadoif,eelesdevemvirantesdoelse (opcional).

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

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

sejaverdadeiro,aexecugionuncachegaaele.)

Emalgunscasos,voc6podeterdificuldadesemdescobrircomqualif

oseuefse deveserpareado,comoneste

if if
/

(exam.doneO

(exam.getScoreO < 0.61)


lnlt\Tr\/ aa:in "):

q1/ctam nrrt- nrin1ujeevlrL.vsu.y!rrru+

/ 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


as

apropriadamente recuados. Alguns candidatos tm at6 uma frase de efeito para a maneira como apresentadas: tudo que puder ser feito de maneira mais confusa, assim seri.
Esteja preparado para perguntas que al6m de

perguntas sio

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)


q\rql-om nrrf

&& (y <
nrinf

2)) | aostuttt)) i

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 ( ) 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,, ) ;
VocO pode ler o c6digo

tor

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

false,e1==
int'i

if

um valor

t.rue.MasnioemJava! Oseguintec6digomostrainstrug6esif quepodemparecerv6lidas,masnio


1. = O.

booleano. Em algumas linguagens, O ==

sio, seguidas de substitutos v6lidos.


irrraTnf f: l qoTnf

nl-

if if if if if if

(truelnt) (truelnt == true)


(1)

(falseInt == fal-se) (truelnt == 1) (falselnt == 0)

/ // // // // //
/

inv6lido
inv5aido

inv6lido
inv6Tido

v6lido
v6Lido

oBSERVAQ6ESpeneOE)(AME
Um ero clmtlm qtle os programadoru cometea teshl-la. Cuidado com aldigot como o seguinte:
(e que pode ser

dficil

de

identfimr) i atribair ama uari,iael

booleana quando a intenpdo seria

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

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
ueTde estar sendo aualiado se d uerdadeiro) n0 argunentl da insrap1o Bem, a oppdo 3 estti correta.

if!

E inilrtl, mas rctr?ta. Dado que o resultado de qualquer atibaQdo i igual ao ualor da aai,iuel incluido @rir essa 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

intaxe

requeren expressdu boo/eanas,

uocd

precisa ter um conhecimento srilido tanto sobre os operadoret ldgicos qaanto sobre a

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

e veja como pode ser confuso ter testes

if

if 6 com a instrugXo switch. Observe o c6digo do bloco aninhados, mesmo com apenas alguns niveis:

else-

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|- 6m vuu rJ p uelr r nrrF y! fIIurrr . nrinr'ln / \

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

switch (express6o)

case constantel: bloco de c6digo case constante2: bloco de c6digo default: bloco de c6diqo

i
A expressio
que, se voce de

um switch deve avaliar um char,

byte, short,

a um tipo int diferente, incluindo os tipos num6ricos 1ong, f loat e double.

nio estiver usando um enurg

s6 vari6veis e valores que

outras palavras, implicitamente convertidos)

ou, a panir do Java 5, um enum. Isso significa puderem ser promovidos automaticamente (em serio aceitos. VocA nio conseguiri compilar se usar algum tipo

int

O rinico argumento que uma instrugXo case poder6 avaliar seri aquele que apresentar o mesmo tipo que a instruSo

JAVA

I89

swi 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 constante com um valor literal. Nio 6 o suficiente ser f ina1, ela deve ser uma constante no tempo de compila$o. Por

tch

inai

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


l

match" ) ;
do que um tipo

Oura regra que voc6 poderia nio esperar envolve a pergunta: "O que aconteceria se uma variivel menor int fosseusadanainstrugloswitch?"Examineoexemplodeinstrugioswitch aseguir:

bYte g = 2'

switch(g)

case 23: case 128:


)
Esse

c6digo nXo seri compilado. Embora o argumento da instruglo swi

implicitamente em um tipo
compilador sabe disso!
Se

int. - o segundo

tch seja v6lido

argumento de

case

- um tipo bpe 6 convertido

(128) 6 muito grande para um tipo

byte

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 nio ser6 compilado porque usa duas instrug6es case com o mesmo valor igual a 80:
a

seguir

int

temp = 90;
I

quri talr lr- amnl

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:


J

System.out.println("90") ; default: System.out.println("default")

-c

varoo

tt't

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
como os

swiLch, case.

Por exenp/0,

uocd pode

enclntrar exempks que nio serian ttd/idos

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

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

ponto

de enlrada da exuupio.

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

Em outras palavras, ap6s

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
case

durante

execugAo de uma instrugAo

swj-tch, o

processamentopassar6imediatamentedoblocoswitch
programa simplesmente continuar6
a

paraainstrugioposterioraele.Seapalavra-chaveforomitida,o
at6 que uma palavra

executar os outros blocos

break

seja

encontrada na

JAVA

191

instrugio

switch i-nt x = 1; switch (x) {

ou at6 que a instrugio termine. Observe o c6digo

seguir:

case 1: System.out.println("x is one"),. case 2: System.out.println(..x is two,,); case 3 : System. out.println


]
Syst.em.
(

"x is three"
)
;

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") ;
)
taea ). I

break;

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

mostrado no c6digo abaixo:

int x = someNumberBetweenoneAndTen; switch (x) {


case 2: case 4: case 6: case
a:ca

B:
1O. t

192 Copitulo 5: Conirole de {luxo, exceg6es e ossertivos

System.out.println("x is an even nuricer") ; break;


) 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

Ainstrugloswitch exibir6"x is an even number"ounloexibir|nada,issodependerAdonrimeroestarentre


case
1

nio

6 necess6ria;

o final da instrugio swi

tch

j6 ter6 sido

atingido.

como: /

Observagio: pelo fato de a passagem completa ser pouco intuitiva, a Sun recomenda que voc6 adicione um coment6rio, / pas sagem compl eta, quando usar essa l6gica em seus Programas.

A instrugio case default


number"quandonenhumadasinstrug6escase switch ou como a riltima 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
Ese,usando oc6dtgoanterior,voc6quisesseexibir"x
(os

is an odd

nrimeros pares) fosse satisfat6ria? VocA nlo poderia inserir o resultado depois da instrugio

adicionar

agora que ela 6 empregada com uma finalidade completamente diferente) a instrugio case ao c6digo anterior:

A rinica alteragXo que precisaremo sfazpr ser|

default

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

instrag1o

case def auLE


t

pode ndo uir

nofnal

da inshagdo

switch.

Procure-a em locait e$ranhos como aemos abaixo:

inL x = 2: switch (x)


ea<a

arrf 2, r vJrLerrrtvuu.v!frruril\ nr.i6f Qrrcfam

l-/\rarr\. z

It

default. : System. out.println ( "default" case 3 : System.out.println("3") ; case 4: System.out.println( "4" ) ;


]

);

exwugdo do aidtgo anterior exibini


2

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 :
na<a ?.
4

System.

out.printl-n ( "defaulL"
r nri tsr

);

Qrrcl- am

vse

^11t-

nf 'l n / $?" I 4aAe+

case : System.out.println ( "4"


)

);

exultpho do cddigo anteior exibini

default

Aregraalembrar,iqaeainstrugdodefault fancionaexatanentec0m0qtlalqilerzutrainstril(Aocase
conpleta!

fiaparsagem

Exercfcio 5- 1 Criando uma instrugio switch-case


Tentecriarumainstrugioswitch-case usandoumvalorchar comoainstruEiocase. Incluaumcomportamento
padrio para o caso de nenhum dos valores

I I I
Al . t.

Cenifique-se

char ser satisfat6rio. de que umavariivel char seja declarada antes da instrugio switch.
case
deve ser seguida de uma

Cada instrugio

instrugio break.

O valor

default

pode ser inserido no fim, na metade ou no inicio.

L/OleTrvo poro

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

,.

]
valor booleano. O corpo do loop 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

while

Nesse caso, como em todos os loops, a expressio (teste) ter6 que resultar em um

194 Copitulo 5: Controle de {luxo, exceg6es e ossertivos


no loop, de modo que quando a condiglo for verificada noyamente seri avaliada como f loop seri finalizada.
palavras, voc6

alse

e a execugeo do

Qualquer variivel usada na expressio de um loop nio pode escrwer

while

deve ser declarada antes da expressio ser

avalia&. Em outras

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

false naprimeiravezqueoloopwhile

que ele pode nem mesmo ser exectrtado. Se


a

expressio do teste for

forverificado,ocolpodoloopser6ignoradoeoprogramacomegareaser
seguir:

executado na primeira instrugio depois dele. Examine o exemplo

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);
)seriexibidaumavez,aindaqueaexprusdos/aaualiadacomofalse.Lembre-se 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.
de que o

AinstrugioSystem.out.println(

oBSERVAQ6ESpeneOE)(AME
Como nos tettes

if

procure loops

whil-e

(e testes

while

de loops

do

booleano.

-whi 1e) clm ilma expressdo


e

que ndo resalte em um

Examine

os exenplos

abaixo de exprutduwhile uilidas

ndo-udlidar

intx=1; while (x) { } while (x = 5) t ] while (x == 5) { } while (true) { }

/ Nao compila; x nio 6 booleano / / Ni,o compila; resolve como 5 (resultado da atribuiqSo)
/
.i vaLLwt A^ // // rr.<l

F^df ue>Le ^

/{a uL

i nrra l rvqqrsqseda^o

/ / var)-do

Usando loops for


ComoadventodoJava5,oloopfor adquiriuumasegundaestrutura.N6schamaremosoestiloantigodoloopfor
de "loop f ele como f

or

bisico",

chamaremos o novo estilo de "loop f

or- each). Dependendo de qual docum enta&o vocA' usar (incluindo a da Sun), ver6 ambos os termos, junto comfor-in.Ostermosfor-in,for-eache"for aprimorado"referem-setodosaomesmoconstrutorJava.
O loop f or b6sico 6 mais fleivel do que o aprimorado, mas
iterag6es atrav6s de arrays
e de

or

aprimorado" (embora o obj etivo2.2da Sun

se

refira

loop aprimorado foi criado para facilitar

programagio de

conjuntos.

JAVAs I95
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: O loop

O Loop for Bisico for ser6 panicularmente

r I I

Declara$oeinicializa$odevariiveis

A expressio booleana
Aexpressiodeiteragio

(teste

condicional)

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 ^rrt nrinl-lnt"i iq

{ " + i).

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 separilas comvirgulas como nalinha abaixo:

for (intx = 10, Y = 3; Y > 3; y++) {


A

for. E enquanto as outras duas partes - o teste booleano e a expressio de iteraglo - sio executadas a cada iteragXo do loop, a declaraSo e ancialbaSo ocorrem apenas uma terminajanto com o loop!O vez, logo no inicio. VocA tamb6m precisa saber qwe o ucopo das aaiiueis dularadat no loop f c6digo abaixo demonstra isso:
dularagdo e inicialiTagdo ocorrem antes de qualqaeroutra coisa em um loop

or

for (int x = 1; x < 2; x++) { System.out.println(x) ; // V6lido


]

System.out.println(x);
Se

// InvaLido! x agora estii fora de escopo / / e nl.o pode ser acessado


symbol

voc6

tentarcompilar ese c6digo, obter6


19

Test. java:

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


O c6digo anterior
6

---

?\ \.
| |

vrr\

v6lido, mas o seguint e ndo o 6:


} | / ^--^^^^^ / / avnraccAoq a^

for (int x = 0; (x > 5), (y < 2); x++) {


O compilador lhe informari do problema:

Testlonq. Java:20: ';' expected for (int x = 0; (x > 5), (y.2)


A regra a lembrar
6 esta:

; x++) {

,.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 instrugio for possam ter virias seg6es.
as ounas dvas partes de

uma

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. fazem com que o loop seja encerrado repentinamente, sem executar a expressio de iteragSo. Examine o c6digo

exit (
a

),

todas

seguir:

static boolean dostuff ( ) { for (int x = 0; x < 3; x++) i System.out.println ( "in for
return t.rue;
]

loop" ) ;

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 5L lista as causas e resultados da finalizaglo repentina dos loops. Tobelo

5-l

Cousos do finolizoE6o ontecipodo do loop

C6digo do loop

O queacontecer5
A execu$o saltari imediatamente para a primeira instru$o ap6s o loop

break
reE,urn System.

for.

A execucio retornari imediatamente

ao

m6todo chamador.

exit (

A execugio do programa
ser6encerrado.

ser6

completamente interrompida; o

VM

Loop for B6sico: Caracteristicas do loop for Nenhuma das tr6s seg6es da declaragio do loop f or sio necess6rias!
nio
seja necessariamente uma

O exemplo a seguir 6 perfeitamente vilido (embora

boapritica):

for( ; ; ) { System.out.println( "Inside an endless 1oop") ;


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

No exemplo anterior, todas as partes da declaragio foram

JAVA
i-f i n. {

I97

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 ndo podeni ser usadafora dele. Pordn, ama uariduel apenas inicialiTada na inthwgdo f (rzat dularada anteriormente) pode ser usadafora do loop. Por exempk, o cddigo abaixo d uilido,

or

or

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
aprimorado para fazer loops atrav6s de um array ou um conjunto. Neste capitulo, vamos nos concentrar no uso do f aprimorado ao discutirmos os conjuntos - que 6 onde o f atrav6s de arrays. No Capitulo 7, revisaremos o f aprimorado realmente faz a diferenga.

or

or

or

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; System. out.print (a Ix] ) ; for(int n : a)
x++)
/

/ Ioop for b5sico /


J-oop

for aprimorado

198 Copftulo 5: Controle de fluxo, exceg6es e ossertivos


System. O que produz L234L234
Mais formalmente, vamos descrever o
fnrldanl araaVa . avnraq<Anl

out.print

(n)

esta saida:

for

aprimorado da seguinte forma:

As duas panes da instrugio f

or

sio:

I Declarag6o I Expressio

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.
ou uma chamada contendo arrays.

Estadeveavaliarcomooaffayatrav6sdoqualvocequerfazeroloop.PodeserumavariAve|dearray m6todo que retorne um array. O array pode ser de qualquer tipo: primitivo, objeto, at6 mesmo array

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: rr ln nAac . Ia T.a\ I f nr \ .
.

'

v6lidas

fnrllnnn Farllann

for(int[]n:twoDee)t for(inL n2 : twoDee[2]) for(Strings: sNums) ; for(Objecto:sNums);

for(Animal a : animal-s) i

/ // // // // // // // // //
/

loop atrav6s de um array de longs fazendo autoboxing dos objetos Long para dentro de longs faz um loop atrav6s do array de arrays faz um loop atrav6s do 3e. sub-array faz um loop atrav6s do array de Strings define uma referncia Object para cada String deflne uma refer6ncia Animal para
um

faz

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 (continue). Normalmente, quando usamos break ou continue, executamos um teste i f dentro do loop e se algumacondi$ofortrue (oufal-se dependendodoprograma),saimosdeleimediatamente.Adiferengaentreessas
As palavras-chave
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

I99

oBSERVAe6rspeneoErreME
Lembre-r de que as inshagdet

break
.
_A

deuem

deuem ser inseridat dentw do loop; do contuiio, uocl uerti am erm do conpilador. At inshagdu ter usadat denho do kop ou de uma in$rugdo swi tch. Oburuagdo: Iso ndo v aplica a insturgdetbreak mtuladas.

continue

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, instrugio continue 6 usada dentro de um teste i f como vemos abaixo:

for (int i = 0; i < 10; i++)


System.

out.printfn ( "fnside if (foo.doStuff O == 5) {


continue;
)

1oop" ) ;

/ mais c6digo do 1oop, que ndo ser6 executado quando o t.este if / / for verdadeiro
/

acima

Instrug6es neo rotuladas


usar instrug6es

break quanto continue podem ser nlo-rotuladas ou rotuladas. Embora seja muito mais comum break e continue nio rotuladas, no exame ser6 esperado que voc6 saiba como as instrug6es break e conEinue rotuladas funcionam. Como mencionado antes, a instrugio break (n1o-rotulada) sairi da estrutura do
Tanto
a

instrugio

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

continue nio

while (!EOF) { / / 16 vm canpo de


if f Fh6ra r^7=c :

um

arquivo
6m\ I

nr^hl

continue;
)

/ passa para

o campo

seguinte do arquivo
com

/ caso contr5rio, faz outras coj-sas

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 para voltar ao loop (t.."1o programa ffr.."{ p"r" o ."*po r.g.tittt. do. arquivo e usari a instrugXo outros campos. Se o comando break fosse usado,.o c6digo estiver no ?inal do arquivo) . .o.tti-ttrr"r a leituri dos 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

continue

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 palavrachave 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 nri nfln(\'Orrt-er eJsLerrr.vuu.y-rrrurrl\ vsevr
"l
+vvy.

nnn t'\:

// n5o seri

exibido

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

for (int j=0; j<5; j++) { System. out.println ( "He11o" continue outer;

JAVA

5 20]

/ fim do loop for interno System. out.println (..outer,, ) ; //


/

Nunca 6

exibido

]
System.

out..println
desse

(..Good-Bye,, ) ;

A execugio

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


variivel
Tente criar um loop whi 1e rotulado. Crie o r6tulo outer e fornega uma condigio para verificar se a idade em uma 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 I

O r6tulo

outer

deve ficar exatamente antes do loop

while

comegar.

Nio imporra se na mesma linha

ou

nlo.

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 \JoleTrvo poro

o centttcocoo

.ctc

Manipulando exces6es (Obietivos 2.4 e 2.5 do exame)


2.4 Escreuer aidigos quefagan uso @ropiado de
sabscrilos oa
excegdes e de

clduvlat

de nanipulapdo de exngdu (try,

nhb,fnalfi)

e declarar mdtodos

nio,

os

qmis /ancem exrcSdes.

2.5 Rcconbecer o efeito de ama exnpdo lanpada em um ponto etpufrn dofragwento de an cddigo.
tenpo de exuugdo, uerifcada oil um etro.

bom ressahar que a

excegdo

pode ser de

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 trs 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 apropriado quando uma excegio ocorrer. Por exemplo, se voc6 chamar um m6todo-que abra um ar.quivo, -o *"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'irrves.l E'v.ahf r<l\rrJr i ^h\ {

8. 9. 10.
1-1. ]
1)

// Inslra um c6digo aqui que manipule essa exceq6o. / / Essa 6 a linha seguinte do manipulador de exceeao. / / F,ssa 6 a riltima linha do manipulador de exceqao'
c:l-ctr aM\rqa.^ndEynonfi
\.rJ vvvv^.gg

nn\

13.
1.4. j
15.

// Insira

um

c6digo aqui que manipule essa excegdo.

16. / /

Algum

outro c6digo nao protegido

(comum, ndo

arriscado) comeqar6 aqui try.

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 Isso 6 um do tipo MySecondException. Observe que os blocos catch aparecem imediatamente ap6s o bloco Al6m disso, todos os blocos requisito; se uocd tiuer um ou mait blocos catchi, eles deuem @arecer imediatamente @d: o bkco forem precisam ficar um ap6s o outro, rcm nenhuma instrugdo ou bloco entre elet A ordem na qual os blocos

try.

calch

catch

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.
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 ttt. pt.ndoc6digo: try. No entanto, isso dexatamenre o que queremos. Imagine se seu c6digo fosse parecido

Observe que

&*

try

{ i \roNaRedg

.anl- rrraAr-r

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

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.
agruPado em um bloco

Um dos beneficios
que Poss, ocorrer

de us.1r a manipulagio de exceE6es 6 que o c6digo de manipulagio de alguma excegio especifica ser escrito somente vmavez. Voltando rroiso c6digo anterior, pode "o haver tr6s locais diferentes-no bloco capazes de gerar uma exceglo MyFirstException, mas o.rJ. qr.r q.t. .1" ocorra seri manipulada pelo mesmo bloco (da linha Z). Discutiremos ourros-beneficios da manipulaglo de exceg6es peno do fim deste capitulo.

!a regilo controlada precisa

Lry

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

Usando finally Os blocos t.ry e catch

try

Os manipuladores de excegio representam um local inapropriado para a limpeza depois da execuglo do c6digo do bloco 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.

try

Oblocofinally
langada ou

enfeixar6oc6digo,quevnpreserS,exesfiadoemalgumpontodepoisdobloco

Lry,vunaexcegdofor

ndo.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 for executado sem exceg6es, o bloco f ina11y ser6 processado imediataminte ap6s o

blocotry serconcluido.Sehouverumaexcegio,oblocofinally seriexecutadologodepoisqueoblococatch


apropriado for concluido.

try

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. 10:
11
:
1

!2:
1?. L4:
1

finally { // Ponha aqui o c6digo para liberar qualquer recurso / / |'enhamos a]ocado na c15.usu1a trv.

que

1-5: / / l.,tais c6digo aqui


6 iniciada "a primeira linha do bloco try, a linha 2. Se nio houver exceg6es langadas no bloco try, a 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

Como antes,.a execuglo

langada, a clausala f inal1y tamb6m ser6 executada. Posteriormente examinaremos alguns cen6rios nos quais f pode nio ser executada ou concluida.

dequefinally

sempreseriexecutada.seaexcegioforlangada,a&iiukfinally seriexecutada.Seaexcegionaofor

ina11y

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 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 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 permitiri que o c6digo de limpeza seja executado at6 mesmo quando nXo houver uma cl6usula catch.

try

try

inalIy

204 Copitulo 5: Conlrole de fluxo, exceg6es e ossertivos


O c6digo vilido aseguir demonstra um bloco

try

com f

inally,

por6m, sem

catch:

trY
/

/ faz aTgo

{ ) finally faz a limPeza //

]
O c6digo v6lido
a

seguir demonstra os blocos

try, catch

inally:

try
/

/ faz al-go ) catch (SomeException ex) // 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 trY { / / faz a1-go
/
)

erroneamente:

/ nd.o se pode ter c6digo entre trylcatch System.out.println( "out of try b1ock" ) ; catch(Exception ex) { }
/

oBSERVAQ6ES penn O EJGME


cliasula try sem uma cldusula catch oa f inaLly. Uma cldusula Lry indiuidaal resaltari 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
Nda

considerado udlida asar uma

em um etro do conpilador.

cldusula

catch

ow

cllaula f

inall-v,

mas ndo as daas.

oBSERVAQ6ESpeneOE)(AME
V'oci ndo pode conpilado:

inseir nenham

ctidigo entre os blocos

try

catch

(oa

try

f inal-l-y).

O cddigo a seguir nio seri

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

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 ) e este chamar o m6todo Programa comeqar no m6todo main ) , 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 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.

"-;il"

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
3

method2fl chama method30 method l0 chama method2$


main chama methodl0 main inicia

z
I

A ordem na qual os m6todos sio colocados na pilha de chamadas

A pilha de chamadas enquanto method3$ esti sendo executado. A execugio volta para method2Q I T methatQ I method2Q vai finalizar
2)

2 [ method$-l t [:"3ajn"-o*J

method

l()

vai finalizar

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?

excegdofora duse mitodo. Isso

resltani

em uma interrupgdo da

ndq*ina uirtual Jaua [1./M, taua Virtaal Machine)

Tanbim podeni langar a e o rastreamento da

pilba seni exibido na vida. O aidtgo a segair /anga ama excepio,

class TestEx { public static void main (String [] args)


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 seri outro m6todo. Se uma excegio for langada no outro m6todo, ele teri que manipuliJa. Uma instrugio f 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

inally

I r I I

Crie uma classe chamada

Propagate e um mdtodo main


reverse.

) , que

perm anecerAvazio por enquanto.

Crie um m6todo chamado

Ele usar6 como argumento e retornar6uma string.


a0

Em

reverse, verifique se a string tem um comprimento igual comprimento for igual a 0, ele langar6 uma nova excegXo.

usando o m6todo

String . length (

) . Se

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

as exceg5es como um conceito. Sabemos que elas sio langadas quando um problema de algum tipo ocorre 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 emsua nSosio,bem,vmaexcepioaessaregra.Todaexcegio6ainstAnciadeumaclassequepossuiaclasseException hierarquia de heranga. Em outras palavras, as exceg6es sio sempre alguma subclasse de j ava . lang . Exception.

Temos discutido
e que

Quando uma excegXo 6langada, o objeto de um subtipo Exception especifico 6 instanciado e inserido no de exceg6es como um argumento para a cliusula catch. Uma cllusula catch real tem este formato:

manipulador

try
)

/ / a1 ortm e6di qo acrui

catch (ArraylndexoutofBoundsException e)
e )
.

printStackTrace

();

JAVA
Nesse exemplo,

207

6 a instAncia de

Como ocorreria com qualquer outro objao, vod pode chamar

uma classe charnada resumidamente de ArrayrndexoutofBoundsException.


seus metodos.

Hierarquia de exces6es
Todas as classes de exceE6es sio subtiFos da clase Exception. Essa classe 6 derivada da classe derivada da classe obj ect). A figura 5-2 mostra a hierarquia das classes de exceg6es.
de

Throwable

(que 6

Como voc6 pode ver, hiduassubclasses que derivam de Throwable: Exception e Error. As classes que derivam 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 aplicativosrrio conseguem se recuperar de-um erro, ponanto, nio precisarnos manipul6-los. Mesmo se seu c6digo 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
disso, porque algum recurso
de

um erro de programagio, mas, em vez

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 Exception chamado RuntimeException. Essas exceg6ei sio um caso esp.iial potqne, ls vezes, indicam realm.rrt. "rrorno 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.

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

A linguagemJava fornece muitas

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
Senl esperado que
necessdrio conhecer nenham dot ndtodos contidot nas c/asvs

uocd

saiba qae ot tipos

cLm 0 trr7 da palatra-chaue

tion).

throw

Exception, Error, RuntimeException e Throwabl e


ur
c@turados (enbora raramente sela c@turado algo que ndo

Throwabl e , inc/uindo Except i on

Error.
Excep-

podem ser langados

e que podem

s/a un snbtipo

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

poi. ."itnt". nais de um tipo de exceglo .- ,rttt" rinica cliusula catch. Se a classe de excegio que _v_oc6 .rp..ifi."t na cl6usula catch nio tiver subclasses, entio, somente a classe especificada ser6 capturada' No
entanto, se a classe especificada na clAusula especifcada mmb6m seni c@tarado.

a palavra-chave

catch

permite

a especificagXo do

tipo

de excegio que seri capturado. Na verdade'

catch

tiver

subclasses, qualquer objeto de excegio com

.rabclasses

da

classe

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

printStackTrace

);

algum c6digo do bloco

excegio seri capturada e manipulada. Isso pode ser conveniente, mas 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.
a

Stringlndexoutof Bound.sExcetion,

try langarArrayrndexoutof BoundsExcetion

ou

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
)
Esse aidtgo uai c@turar todas
.

printstackTrace
at

excegdu geradas.

claro que nenbum manipu/ador de excegdo pode

nanipular indiuidualmente

de maneira

@mpiada

cada exnpdo e uma pngmnagdo


sri ueVpmuauelmenn

feita

dessa maneira

prejadicani o objetiuo

do

pnyta Ot manipuladoru

de excepdo que ca?tararem

naitos enos de uma como tratar.

reda{rdo a confabilidad.e

de rea pmgrama Porque d possiuel que c@turem uma excegdo que ndo saibam

Correspond6ncia de exceg6es
voc6 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.
Se

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

quecorrespon&aosupertipodaexcegio,entAo,aexcegioser6propagada
de excegdes.

para baixo na pilha de chamadas. Esse processo 6 chamado de coresponddncia

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"; 7: byte b[] = new byte[1000]; 8: raf.readFully(U, 0. 1000);

JAVA

5 209

10: 11 : t2: 13: t4: 15: 1-6: !7 : 18 :


1q.

catch(FileNotFoundException e) { System. err. println ( ',Fi1e not f ound,, System.err.println(e.getMessageO); e.printStackTraceO;


)

catch(fOException e)

System.err.println("fO Error,'); Syst.em. err.println (e. toString ( ) ) ;


e.
l )

printstackTrace

,.

20: 21 : j
Esse

programacurto_tenta abrir um arquivo

exceg6es, a maioria delas sendo algum em sabersomente se a excegao hngada

tipo

foi exatamente o problema.

ler alguns dados nele. A abenura e leitura de arquivos podem gerar muitas roException. Suponha que nesse program; estiv3ssemos'inreressados ^Caso foi rileNotFoundnxceition. contr6rL, nio nos importar6saber qual
e

de

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

6 uma subclasse de roException. Porranto, poderiamos manipuli-la na cl6usula cuja finalidade 6 capturar todos ossubtipos de roExcep_tion, mas ter?amos que tesrar Jexcegio p"ra

elaser6manipuladapelacl6uzulacatch
de

tempo de execugio, nenhuma das cl6usulas

quecomeganalinha15.Seoutraexcegioforgerada,comoalgumtipode-excegio catch ser6 executa&, . .*..glo ,. ri'propagadap".""b"i*o n" pilha de


"

chamadas.

Observe que acliusula caLch, de

loException.

Isso

importantelSe

excegdet mais espedfcos deuen

FileNotFound.Exception, foi inserida acimado manipuladorde for feito de maneira inversa, o programa nio sericomplado. Os nanipuladores sempre ser inseridos acima dos de exngdu gerais. O c6digo a seguir nio ser6 compilado:

de

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)


Se

pensarmos 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

exceg6es do tipo declaraquelangaumaexcegeoniosignificaquesemPreo MyExceptionl eMyuxception2 (s6porqueom6todo fani. Ele ap enas inf o rma qu e p o fu faz|-lo).

m6todo tem um tipo de retorno

void,

que

nio aceita argumentos e declara que langa duas

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 que ndo tiuer recebido tratamento c0m0 tlma exegdo langada. Essa regra 6 conhecida

catch,

oa entdo listar cada exagdo uerifcada

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 para langar uma excegdo manaalmente - falaremos mais sobre isso a segair) uerifcada. O cddigo a ngair (que usa a palaura-chaue

throw

@ntenta

dois grandes

problenas qae o conpilador euitani:

void doStuff O i
doMore ( ) ;
)

void doMoreO
]

{
(

throw new foException


Primeiro, o mdtodo doMore fosse corigido da maneira a segair:

( )

langa uma excepdo uerifcada, mas ndo a dulara! Ponim, suponha qae o mdtodo

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
doMore
JUE;XCe1)C.r_On.

void

Novamente, algumas exceg6es estio dispensadas


langldo

dessa regra. Um objeto do tipo RuntimeException pode ser 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 ndo uerifcadas, e as excegdes ndo ueifcadas ndo precisam

todos os seus subtipos sio exceg6es Aqui estl um exemplo:

nr

especifcadas ou nanipaladas.

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


esse

uma

NullPointerException

De acordo como comentirio,


precisar6 ser

RuntimeException 6asuperclasseimediatadeNul-lPointerException,ela6umaexcegao

m6todopode langaruma excegioNullPointerException.J6que nioueifcadaenio 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 Exception) da maneira a seguir:

class MyException extends Exception {


E sevocA langar
a

}
a

excegeo, o compiladorse certificar6 de que adeclare damaneira

seguir:

class TestEx { void doStuff O

throw new MyException (l


) O c6digo anteriorpreocupari o compilador:

; //

LanCa uma exceqSo

verificada

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

for langado, ele teni que ser manipulado oa declarado. Esses objetos sio chamados excetl as que sio rubtipor /e RuntimeExceptiort, consideradas exupdes nio uerifcadat Estla preparado para identifcar mitodos que ndo sigan a regra da ruanipulagdo ou declaragdo, coml em
excegdes uerifcadas e incluem todas as excegdes,

Exception

de

class MyException extends Except.ion void someMethod O { doStuff ( ) ;


]

212 Copitulo 5: Controle

de fluxo, exceE5es e ossertivos

void doStuff ( ) throws MyException

trY
)

{ narrr MlrFv^ani i nn / )
.

fhrat^t

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.

Eror e exceg6es verificadas e nio verificadas. Objetos do tip o Error 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:
Voc6 teri que saber
nXo sXo objetos
a

diferenga entre um objeto

Exception,

class TestEx { publLc static void main (String [] args)


}r:AMaFhnrl )
1

static void badMethodO { / /


doStuff
)
()

Ndo 6 necess6ri-o

declarar

um

erro

static void doStuffO { // try {


throw new Error
)
(

Ndo

6 necess5rio declarar

um

erro

);

catch (Error me) { throw me; / / Capturamos, mas depois relanqamos


]

f6ssemos langar uma excegio verificada em vez de run erro, enteo, o m6todo doStuf f ) teria que declarar a excegio. nio 6 um subtipo de Exception, nio ter6 que ser declarado. Voc6 est6livre para Mas lembre: Ji que o objeto 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.
Se

nrror

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

f#f*"t try
{

ilril.

Conhecemos gerentet de

rofware que n6o amditaran qaindo uiran am pigramador

callBadl"Iethod

);
} manipuldJa realmente. Voc6 nem newo podeni informar qae a
excegdo

] catch (Exception ex) {


Notou aQofaltando? Ndo onita a
lclrretl, Plrque nunca aerd o rastreamento

excepdo capturando-a sem da

pi/ha.

Relangando a mesma excesao


Damesma forma que voc6 pode langaruma novaexceglo apartir de umacl6usula excegio que acabou de capturar. Aqui est6 uma cliusula catch que faz isto:

catch, tamb6mpodelangara

mesma

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

try

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

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

Primeiro criaremos nossa excegio. Ela


alimento nio aceit6vel for encontrado.

ser6

chama& de eadFoodException.
e

Essa

excegio seri langada quando um , que permanecerivazio por

Crie uma
enquanto.

classe de

inclusio chamada

MyException

um m6todo main

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.

Agora, no m6todo main


passar6 essa string para o

checkFood

( )

( ) , vocA extrair6 o argumento de linha de comando do array de strings e, em seguida, m6todo checkFood ( ) . J6 que se trata de uma excegio verificada, om6todo 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


captur6Ja?

main

( ) declare o m6todo, porque se main ( ) passar a excegXo, quem mais exar|lLpara

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)


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'

2.5

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

O tratamenro de exceg6es

OBSERVAQ6TSpeneOF)(AME
As Ao
questdes desta sepio prouauelmente ser6o algo do tipo longo de exame, as questdes apretenturAt
essas

:'Eh

aqui algun cddigo que acabou defaTer buteira, qaal

excegdo ser,l

langada?"

algun aldigo

e lhe pedird.o

para deterrztinar se o aidigo uai rodar, ou


sea sacesso.

se serd lanpada

una

excegdo.

Uma ueTque

que$des sdo tdo comuns, entender saas caasas ,!fundamentalpara 0

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


e dO uma olhada na ultima frase do Obletivo 2.6.Eimportante entender o que causa exceg6es e de onde eles v6m. Para o prop6sito de preparar voc6 para o exame, vamos definir duas categorias maiores de exceg6es e erros:

Volte i p6gina anterior


erros,
e

I r

Exceg6es da JVM As exceg6es ou erros que sXo ou exclusivos ou mais logicamente langados pela JVM.
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 g; v er +r.Y

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

/ recursividade causando problemas

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

Novamente, apenas

desse

JVM

sabe

quando

esse

momento ocorreri,

ea

JVM

ser6 a fonte

Exceg6es Langadas Programaticamente


V.

ejamos agora

as

algocomo:

exceg5es langadas programaticamente. Lembra-se que definimos "programaticamente" como significando

Criado por um aplicativo

ou por um desenvolvedor de

ApI.

Por exemplo, muitas classes na APIJava tm 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.

parcialmente implementado poderia

H6 muito tempo, algum prog{amador escreveu a classe j ava . lang . rnteger e criou m6todos como parsefnt 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
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 erro E langado Prograrnaticanente), elangaruma 11legalAr$unentException. Naverdad., o nosso nritico
esse

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)


ArraylndexOutOBoundsException

Descrigio
Normalmente

Langada

(Capitulo 3, "Atribuig6es")

Langada ao se tentar acessar um array com um valor de indice invilido (ou negativo ou maior do que a extensio do array),

Pela

JVM

21

Cooilvlo 5: Controle de fluxo, exceE6es e ossertivos


ClassCastException

(Capitulo 2, "Orientaglo a Objetos") lllegalArgumentException (Capitulo 3, "Atribuig5es")


IllegalStateException (Capitulo 6, "Formataglo")

Langada ao se tentar converter uma vari6vel de refer6ncia em um tipo que nio passa no teste E-UM.
LanQada quando um m6todo recebe r.r* irg,r-..rto formatado de forma

Pela

JVM

Programaticamente

diferente do que o m6todo esPera.


Langada quando o estado do ambiente nio bate Com a operagio sendo tentada, pot:I:Tql", usando-se um Scanner que ,a lor lecnaoo. Langada ao se tentar acessar um objeto com uma variivel de referAncia culo

Programaticamente

NullPointerExceDtion (Capitulo 3, "Atribuig6es") NumberFormatException (Capitulo 6, "Formatagio") AssertionError (Este Capitulo)

PelaJVM

valor atual seia

nuI1.

Langada quando um m6todo que converte uma String em um nimero recebe uma String que nio consegue converter. Langada quando o teste booleano de

Programaticamente

Programaticamente

uma instruglo retorna f af se.


Langada ao se tentar inicializar uma variivel Pela JVM estttica de um bloco de inicializaglo.

ExceptionlnlnitializerError
(Capitulo 3, "Atribuig6es") StackOver{lowError @ste Capitulo)

Normalment e Tangada quando um m6todo faz recurs6es profundas demais (Cada chamada 6 adicionada i pilha).

Pela

JVM

NoClassDeffoundError (Capitulo 10, "Desenvolvimento")

Langadaquando aJVM nio consegue encontrar PelaJVM 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.

,.t. ,A. l r (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 coloca em comentirios:

nio poderievitilas

quando estiver escrevendo um c6digo. VocO

as

if (x>2&&y) / / faz al-go ] else if (x .2 / / faz al-go


'l o1co f

ll Y)

// xdeveser2 / / faz ortrra coisa


]
VocA escreve instrug6es

print

com elas:

while (true) if G>21


break;

JAVA

217

System.out.print("ff
wrong");
]

we

got here something went horribly

Adicionadas ) linguagem Java n? verseo 1.4, as assertivas permitireo que voc6 tesre suas suposig6es duranre o e.xceg6es.quesestpaenanvlcorrerdo,umavezqueoprog?amativersaidoda'faseiedlsettrolrri-.rrtoefortoialmente' distribuido.

desenvolvrmento, sem o desgaste (tanto de seu tempo quanto de sobrecarga no programa) de escriver manipuladores para

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,", ^r.nivas incluindo como ativi-las, usl-lxe naus6-las.

Visdo geral das assertivas


Imaginemos que voc resolvesse que um n{rmero passado para um m6todo (digamos, methodA negalivg. No momento do teste e depuraglo, voc6 quer validar sua suposigio, mis nio que, t., qrr.

qryupula{oresdeexcegiodetempodeexecugiooutestesif/else-quandotiverconiluidooiesenvoL'i*.nto.boi6*,'
deixar todos esses recursos inseridos trar6, no minimo, um impacto no desempenho. E ai que as asseftiv.. ajudar. Observe o c6digo a seguir:

..*o

) nunca ser6

ver irstrug6espint,

*r"*

p"r"

private void methodA(int num) {

if
/

(num >=

0)

/ faz al-go ) el-se { / / nt:m deve ser < // Nunca chegaremos a este cddigol System.out.println(..yikes! num is a negative numberl " + num);
O

]
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;
]
As assertivas

escnto assrm:

nio s6 permitem que seu c6digo permanega mais limpo e menor, mas, como elas ficam inativas, a menos que seram especilicamente "postas em agio" (ativadas), o c6digo ser6 executado como se tivesse sido

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 (que vocA nunca, jamais deve manipular!) imediatamente,'de modo que voc6 possa corrigir a falha na l6gica que levou ao problema.

AssertionError

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


]
Simples

de fluxo, exceE5es e ossertivos

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 algumas informag5es a mais ao ra$rearnento da pilha. As duas vers6es booleana) por dois pontor, q,r. ".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,
um rialor. Lembre:

naversio simples de umainstrugio assert, pode ser qualquercoisa.que resulte em expressio 6 usada para gerar uma mensagem com Strings' a qual ser6 exibida no rasrreamento dapilhaplra he fornecer mais algumas-informag6es de depuraglo. Ela funciona de maneira semelhante a
usada somente
a segunda

System.out.printl-n(
uma representagio com

Strings.

),nofatodequeivocOpoderiplssarumiipoprimitivoouumobjeto,eelaoconverterdem Seu resultado lel que ser um valor!

pa ra anrbar as panes de uma instruglo assert. Lemb_re-se, a exPression2 6"usada apenas com a instrugXo assert sirnples, em que a segunda expresseo existe somente para lhe dar mais algumas informag6es para a depuragio:

O c6digo abaixo lista express6es vilidas e inv6lidas

void noReturno {} int aReturno { return 1; void go0 { intx=1; boolean b =


/

/ as

segwj-ntes
/.. -\^ -th\
.

instrug6es assert sdo v6lidas

^^^^es aDDs!L accarl-

1\. J/

assert true,'
^^^^rr :ccarl-^^^e! oD-erL\^

/.. lv
/-.

--

1\

. .
. .

== 1 \
--1\ f/

x; aReturnO; new ValidAssert O ;

^^^^e! a>-s!Lt^

// as seguintes instruqSes assert sao TNVALTDAS // nenhuma delas 6 booleana


/.. 1 \ fr, .

assert (x)

assert
ac<arl-

0;
lv == 1 'l
.

nenhrrma del

as retorna

um val-or

assert(x == 1) assert(x == 1)

:
:

noReturn { ) ;

ValidAssert va;

JAVA

2'I9

oBSERVAe6rspaneoEl<eME
Se uoc6 se dtparar cam
a

palawa "expressio"

exprusio booleana) ou i rcgunda (o ualor a ser exihido n0 rastreamentl da pilhQ, entdo, ir$re prenna exprusio, o teste boo/eano. Por exemp/0, se /he pergmtanzos o rcguinte,

em uma pergunta sobre asertiuas e ela n6o especifcar

n esti

se

refeindo i
se

pineira

express1o (a

quiuti

,tj'triuao i prineira

"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
essas asseftivas

Sevoc6quiserusarassertivas,teri.queconsiderarprimeiro comocompilarcomelasemseuc6digoecomoser|aexecupdocom ativadas. As duas situag6es.requerem aversio 1.4 ou iuperior e isso nos conduiao primeiro problema:
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

usada como um identificador.

Nio

lembre-sedequevoc6niopodeusar.umapalavra<have/reservadacomoidentificador,eapartirdaversio tamoa uma palana-chaue! A, conclusio 6


VocA pode usar

haveria problema antes da versio 1.4. Mas


1.4,

assert

rt

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

classe

uersio

|.4, err qtre asserL

hilClass do direhirio com/geeksanony.mous usando a maneira enpregadapela

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

dizer ao compilador que esti dando.

deio**iot

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.3 CodiqoAnti_go. java O compilador emitiri avisos quando descobrir a palavra assert

javac -source 1.4 CodigoNaoTaoAntigo. java


Nesse caso, o
Se

compilador emitir6 erros quando descobrir a palavra

assert

sendo usada como

identificador.

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?)
como identificador no seu c6digo, vocA PRECISA Se quiser usar A Tabela 5-3 resume a forma como o compilador java5 reagir|a 1.

i.

assert

assert

compilar usando 19pEa" -source 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 com avisos.

Se assert

for uma Palavra4have


falha.

javac -source 1.3 TestAsserts. java O c6digo compila

A compilagio

javac -source 1.4 TestAsserts.java A compilagio falha.

O c6digo compila. O c6digo compila. O c6digo compila. O c6digo compila.

javac -source 1. 5 TestAsserts. java AcompilagXofalha. javac -source 5 TestAsserts.java javac TestAsserts . java
A compilagio falha.

A compilaglo falha.

Execugio com asseltiv.ur


pi"rrr^,
Agoracheganros ) par"te interessante. IJma ve z quevocAtiver escrito seu c6digo, o qual reconhece assenivas (em outras . no temPo de execugio), ,rio .6digb que ,rse assert como palavrachave, para realment. .iecotar at "ssertivas que as asseftiuas u4n dcsatiuadarporpadrio. poderi optar por ativ6Jas ou desativllas! Lembre-se de

Ativando assertiy.F no temPo de execugio


Ative
as

assertivas no tempo de execu$o

com

java -ea
ou

com. geeksanonymous.

TestClass

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
ou

com. geeksanonymous.

TestClass

j ava -disableas gert Lons com. geeksanonymous . Tes tCf as s

Ji que as asseftivas slo desativad x por padfro, usar

*o

os switches de desativag5" q"+ parccer desnecess6rio. De fato, o dor switches, da maneira que mostr-amos no exemplo anterior, lhe fornecer6 simplesmente o comPortamnto , padrlo (em ouras palavras, vod obteri o mesmo rgsultado independente do uso dos switches & desativagio). Por6m, -cle modo que- elas figuem ati.vadas para.algumas vocp tamb6m pode ativar e desativar as assertivas seletivamente, 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 I I

Sem argumentos (como nos exemplos anteriores) Ativa ou desativa assertivas em todas as classes, exceto Para as classes do sistema.

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).
Com o nome de um 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
A linha

-da : com. geeksanonymous' Foo

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 ^--^ lava t- - ^. -ea -od:com.geeksanonymous. . .

JAVA

221

A linha
ele

P-acote coru.geeksanonlmous e en todos

nio

O"

ativar asserrivas no imbito geral, por6m desativando-as no pode nio estar familiarizado com o termo ubpacote, ji que era muito usado antes da exist6ncia das assertivas, O nbpacote pode ser qualquer pacote de um subdiretorio mencionado. Por exemplo, observe a 6wore de diret6rio abaixo,
os yus^

de comando anterior informa

i JVM para

tubpac.oteslVoc6

:::*
apalrcan
I

i nr

.)rmous

_Foo

_twelvest.eps
_StepOne

_StepTvo
Essa

irvore lista tr6s diret6rios.

geeksanonymous

twelvesteps

e tr6s c]asses:
com. geeksanonymous com. geeksanonlzmous
. .

Foo

twelvesteps. Stepone

com. geeksanonlzmous . twel-vesteps . StepT\^ro

subpacote de com.

geeksanionymous

com. geeksanonymous.
os pacotes acima dele (nesse

6 o pacote twelvesteps. Lembre que emJava, 6tratado como umpacote completamente distintosem relacionamento com exemplo, o pacote com. geeksanonl.mous), exceto por compartilharem alguns diret6rios.

twelvesteps

A Tabela 54lista exemplos Tobelo

de switches de

linha de comando paraaativagioe desativagio de asserrivas.

5-4

Swilches de /inho de cornondo poro osserfivos

Exemplo de linha de comando


lava java -ea -enableassertions

O que significa

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.


java -ea -dsa lava -ea -da:com.too

Ativa assertivas no pacote

com.foo e

em todos os seut subpacotes


nas classes do sistema
no

Ativa assenivas no Ambito geral, por6m desativando,as Ativa assertivas no Ambito geral, por6m desativando-as
todot os sets subpacotes

pacote

comrfoo

em

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
fhrowal>1e,

6umasubclassede

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 nlo concede acesso ao objeto que o gerou. Tudo que voc6 vai conseguir ser6 uma mensagem de

AssertionError 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
ser usado,

"apropriado", ndo a confunda cont "u,l/ido". Apmpiado :empre se refere d maneira cono algo deue oa com as pniticas ofcialnente adotadas pela Sun. Se u\cA enc\ntrar a palaura pa/at'ra "cyrreto" n0 cyntex,tg das assertiaas, c0n0 en, 'A tinba 3 apretenta un uto cunetr para aJ assertiuas", tambim deue presamir qae essa comopodeiam ser zudas dc maneira adlida. uni v refeindo a como as assertiaas deaem ser xsadas em aeqde
exame, se uocd se fuparar com
d.e a

pakna

acordo com os desenuoiuedores

do-nian*no

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 " e*I*tadas (normal-.ote .sao deiativadas em um aplicativo distribuido), a imposigio nio ocorrer6 se elas nio ,.dmlrrr. forem ativadas. Voc6 nXo ir6 querer um c6digo de acesso priblico que s6 funcio ne condicionalmente, dependendo das

assertivas estarem ou
Se

nio ativadas.

voc6 tiver que validar argumentos de m6todos


se os

publ ic,

poder6 usar_exceg6-es para langar, digamos, uma

I 1 I ega lArgumentExi ept i on

valores passados ao m6todo nio forem v6lidos.

Use as assertiyas para validar argumentos de um m6todo Privado


os c6digos que o Quando vocd escrever um m6todo private, 6 quase certo que tenha escrito (ou que controle) todos 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


restrig6es

eo

aa{gumeniosprivat e,n x o}oa^6todospubl ic.

fomecido antes dele 6 o modificador de acesso. Portango, impgnha 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
publ ic'1 5" ,r, prbgr* a preitsar i"
para forgar sua utilizaglo.

Na verdade,

esse 6 apenas

um caso especial da regra: "Nio use asseftivas para validar argumentos de um m6todo de linha de comando, voc6 poderi ,tt"t o tttecattismo de exceg6es

"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

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

223

Nio

use express6es assettivas que possam causar efeitos colaterais!


a seguir seria

O c6digo

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


inseridonainstrugioif.Seumainstrugioelse forusadaeaexpressioapresentarumresultadofalse,bc6digo posterioraelse seriexecutado.Seainstrugioelse nioforusada,nenhumdosc6digosassociadosiinstrugioit
ser6exectrtado. Este capitulo abordou uma 6rea vasta, toda ela envolvendo maneiras de controlar o fluxo de seu programa, com base em 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

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 (esses tipos

slo

byte, short, int

char), oupode avaliar enums.

int

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 correspondncia, a instrusio case default ser6 executad4 caso haja uma.

No tempo

VocA conheceu as trs 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 vez. O principal beneficio do loop f seus valores na definigio do loop.

bloco e ser6 verificada a cada iteragio do loop. O loop do nio verifica a condigio antes de percorrer o loop uma or 6 o recurso de iniciahzar uma ou mais vari6veis e aumentar ou diminuir

As instrug6es break e continue podem ser rotuladas ou nio-rotuladas. Quando nio 6 rotulada, a instrugio 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.

break

seri executado. Para interromper

Quando houver uma correspond6ncia entre a expressio switch e o valor de case, o c6digo posterior a case 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
imediatamente depois dobloco

deverivir

oucatch emitirum System.exit( ).


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, apalavrachave throw Z usada em uma definigio do m6todo, junto com uma lista de todas as exceg6es verificadas que

try).

Ele sempre serl chamado, exceto em casos especiais, quando o c6digo de

try

O objeto

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.
na versio 1.4, slo uma nova ferramenta ritil de depuragio. Voc6 aprendeu como por6m, mantendo-as desadvadas quando o aplicativo for distribuido. Se voc6 tiver pode us6Jas em testes, ativando-as, 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.

As assenivas, adicionadas

i linguagem

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,
tenhacomo resultado umvalor ou umavariivel booleana.

uma expressio que

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

5 225

As instrug6es
escreven

switch

podem avaliar somente os tipos de dados

byte, short, int

char.

VocA

nio pode

long s = 30; switch(s) { }

E E

O argumento
Se a

de case deve ser umavariivel literal ou f ina1, ou uma expressio constante, incluindo um nio pode ter uma instrugio case que inclua uma variivel que nio seja final ou um intervalo de valores.

enurn" Voc6

condigio 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
nenhum dos valores das instrug6es

sevoc6quiserexecutarumc6digoquando

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 fl E B
D D E

UmainstrugXofor b6sicaposzuitr6spartes:adeclaragioe/ouniciahzaglo,aavaliagiobooleanaeaexpressi.ode
itnado.
Se uma variivel for incrementada ou avaliada dentro de um loop f dentro da declaragXo do loop f or.

or

bisico, ter6 que ser declarada antes do loop ou

Uma variivel declara&

(e

nio

apenas inicializada) dentro da declaragio do

do loop (em outras palavras, o c6digo abaixo do loop

for

nio poder6

us

loop f or blsico nio poder6 ar avariivel).

ser acessada

fora

variivel tem que

Voc0 pode inicializar mais de uma variivel na primeira parte da declaragio do loop ser separada por uma virgula.

for

b6sico; cada

inicializaSo de

Uma instruglo f Com um

or aprimorada (uma novidade doJava 5) tem duas panes, parasefazerloop atrav6s de arrays ou conjuntos.

declaragio

ea

expressio. E usada apenas

for aprimorado, a expressio 6 o array ou conjunto atrav6s do qual voc6 dese jafazer oloop. Com um f or aprimorado, a declaraglo 6 avari|vel do bloco, cujo tipo 6 compativel com os elementos
affay ov conjunto, e essa variivel cont6rn o valor do elemento para aiteraglo em questio.

do

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

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 &
ea

estrutura de loop mais interna seja interrompida


seja

linha de c6digo posterior ao loop seja executada.

E E

Uma instrugio continue nXo-rotulada fari com que a iteragio atual do loop mais interno condigio desse loop seja verificada, se ela for atendida, o loop ser6 executado novamente.
Se a

interrompida

ea

instruglo

break

ou

continue

for rotulada, ela

far6,

com que uma agi,o semelhante ocorra no loop rotulado

nio no loop mais interno.

Manipulando exceg6es (Objetivos 2.4,2.5 e 2.6)

E E B

As exceg6es vAm em duas vers6es: verificada

nXo verificada.

As exceg6es verificadas incluem todos os subtipos de

Exception, excluindo as classes

que estendem

RuntimeException.
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. E Os subtipos de Error ou RuntimeException nio sio verificados, portanto, o compilador nio imp6e
declari-lausando a palavra-chave
regra de manipulagio ou declaragio. Voc6 pode manipuliJos e tamb|m declar6-los, mas o comPilador imponari se uma ou outra coisa ocorreu.

a se

nio

E tr

Se

voc6 usar o bloco opcional f

try

ina]Iy, ele sempre ser6 chamado, independente de uma excegio do bloco correspondente ser ou nio langada e de uma excegio langada ser ou nio capturada.
i
regra do bloco f
Isso

inally ser sempre chamado seri quando a JVM for encerrado. 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 pr6prio langar uma excegio ou emitir um System. exit ( )
A rinica excegio
.

pode ele

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

tr 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 (nxception 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. Algumas exceg6es slo criadas pelos programadores, outras pela JVM.

fl E E E E fl E
D

Trabalhando com o mecanismo de assertivas


As assenivas lhe fornecerio uma maneira de testar suas suposig6es durante o desenvolvimento e a depuragio. As assertivas geralmente slo ativadas durante o teste, mas desativadas durante a distribuigio.

Voc6 pode usar

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 flagdelinhadecomando -source 1. 3 em javac.

assert

compilar c6digos antigos que usem

As assertivas sio desativadas no tempo de execuglo por padrio. Para ativi-las, use o flag de linha de comando

-ea
Se

ou

-enabl-eassertions.
-da ou -disableassertions.

VocA pode desativar as assertivas seletivamente usando o flag

no Ambito geral. E possivel combinar switches de ativagio e desativagio para ter algumas classes e/ou pacotes, mas nXo em outros. Voc6 pode ativar ou desativar assertivas por
classe, usando a sintaxe a seguir:

voc6 ativar ou desativar assertivas usando o flag sem nenhum argumento, estar6 ativando ou desativando-as as assertivas ativadas em

iarra -ea -da:MvClass TestClasS

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
portanto, nlo seri bom rer um compoftamento que

garantida,

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

roi. rrrn

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.
E ir
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 javac -source 1.4 javac -source 1.3 javac -source 1.4 ,d
B.

One.java One.java Two.java Two.java


as

Qual6 o resultado? (Marque todas

corretas)

Apenas uma compilaeeo teri sucesso. Exatamente duas compilag6es tereo sucesso.

228 Copftulo 5: Controle

de {luxo, exceg6es e ossertivos


sucesso. sucesso.

C. Exatamente tr0s compilag6es terio D. Todas as quatro compilag6es terio

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
(Marque todas
as

// insira o c6digo

aqui,iricompilareproduzirasaidab?

corretas)

A" String B. String C String D. String E. String E String


4. Dado:
alaqc

doFileStuff O { return "b"; } doFileStuff O throws IOException { return "b"; } doFileStuff(int x) throws loException { return "b"; } doFileStuff O throws FileNotFoundException { return "b"; } doFileStuff O throws NunberFormatException { return "b"; i doFileStuff ( ) Lhrows NumberFormatException, FileNotFoundException { return "b"; }
{

Tnhrrl-

public static void main(string[] args) Strrng s = \r-"; try {


doMath(args [0] ) ;

s += "t ";
]

// Iinha

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 ^.-_J4Va i^--J qvq T-^,.r rrrPuL T6-..! f rrPuL n v as

Quais afirmativas sio verdadeiras? (Marque todas

corretas)

JAVA

5 229

A. A linha
C. A linha

6 6 executada exatamente

vezes.

B. A linha 5 6 executada exatamente


D. O bloco f ina11y

vez.

6 6 executada exatamente 2vezes.


6 executado exatamenre
6
O

vezes.

E. O bloco
G. Ambas

finally

executado exatamente 1 vez.

F. O bloco f ina11y
as chamadas

6 executado exatamente

2vezes.

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.

)
a s atd^ 12?

Qual opgio, inserida na linha 4, produz

,{"inty=x; B.inty=10; CintY=It; D.inty=12; E. int Y = 13; E Nenhuma das anteriores permitiri

que

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

s3O; s3O;
)

throws Exception s += \\2"; 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"); A ClassCastException B tllegralstateException C NumberFormatExcepLion


D. t 1 legalArgumentException

}
as

Qual opgio poderia ser usada para se criar um bloco catch apropriado? (&Iarque todas

corretas)

E. Excepti-onInInitiali zerError F. ArraylndexOutOf BoundsException

8. Dado: 1. class Ping extends Utils { 2. public static void main(String [] argrs) Util_s u = new Ping0; 3. 4. System.out.print(u.getlnt(args[0]));

int setrnt(strins ars) t ;. return Integer.parselnt (arg) ; 7. B, } 9. ) 10. class Utils { 11. int getlnt(String x) throws Exception { return 7; t2. j
E
as

tr6s modificag6es possiveis:

) langauma Exception. C2. Declarar que Ping . getlnt ( ) langa uma Except ion. C3. Encapsular a chamada de getrnt ( ) em um bloco try / catch.
C1. Declarar que

main

Qual(is) modificagio(6es) permite(m) que o c6digo compile? (Marque todas

as

coretas)

,A. Cl sozinha 6 suficiente.

B.

C2 sozinha 6 suficiente.
C2 sozinha
6

C
D.

suficiente.

C1 e C2 sio obrigat6rias.

E. Cl

eC3 sio obrigat6rias.

E C2 e C3 sio obrigat6rias. G Todas as trAs modificag6es


9. Dado: class Swi11
{

sio obrigat6rias.

JAVA

23I

public static void main(String[] args) String s = "-",'


switch(Timezone.CST) case EST: s case CST: s case MST: S
{

default:
] System. out
) )

s case PST: s
.

+= \e,'; += t c,, i += \m".' += rtl'rt += "p,,;


(

println

s);

enum TimeZone {EST, CST, MST, PST } Qual6 o renrltado?

-c B. -x
.4"

-cm

D. -cmp E. -cmXp

E
G
a

Acompila$ofalha.
3r t 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 t

de fluxo, exceE6es e ossertivos

l. Quais afirmativas s6o verdadeiras?

(Marque todas as corretas)

.4. Eapropriadousarassertivasparavalidarargumentosparam6todosmarcadoscompublic.

B. li apropriado

capturar e manipular erros de assertivas.

C D
E,

Nao 6 apropriado usar assertivas para validar argumentos de linha de comando.

li apropriado
Nna 6

usar asseftivas para gerar alertas quando

vod alcang um

c6digo que nio deveria ser alcanEado.

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 B for(x : C int y = D. for(int E. for(int, F inL y =


|

y : x) { int y) t 0; for(y : x) { y=0, z=0; z<x.length; z++l { y = xlzli y=9, int z=0; zcx.length,' z++) { y = xLzJ; 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) Integer xl- = 5; 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"; LIcase x4: s += "e";
LZ. j

L3.
14 ]
)

SysLem.out.println(s);

1s.

Qual6 o resultado?

,{. abc B. abcde

A compilagio falha devido apenas a um erro na linha 7.


8.

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

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.


a erros em

G. A compilagio falha devido

virias linhas.

14. Dado:

class Hnu { static String s = \-" i public static void main(String[] args) try {
Exception( ) ; ) catch (Exception e) {
ne\^/

throw

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 A. nu1l B.

de fluxo, exceE6es e ossertivos

null null

C. E langada uma ClassCastException. D. E langada uma NullPointerException.

E. E langada uma NoClassDefFoundEror.

ArichmeticException. G. 6 langada uma rllegalArgumentException.


F.
E langada uma

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
2.
Eest6correta.Ainstrugio
resultariaem OF ( 11

it |invllda.Oif-else-else
111.
base no exposto acima.
(e

devesermodificadoparaif-else

if-else,oque

6:

A, B, C, D e F estlo incorretas com


B
e

(Objetivo 2.1)
- 3 , e a dasse

F estio coretas. A classe One compilari

emitir6 um aviso) usando o flag 1

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


nenhuma exce$o. E 6 v6,lido que
esse

as

mesmas exceg6es, exceg6es mais restritas,

ou

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
dedividirporzero.
B, C, D, E e G e$eo incorretas com base no exposto acima. (Objetivo2.5)

porcausadatentativa

5. Cest6correta.x atingeovalordell,emcujopontootestewhile falha.x


de comparaglo!), e o m6todo

println

6entloincrementada(depoisdoteste

) roda. alangaparaslO,emaisnenhumc6digodes2Oseri

A, B, D, E e F esteo incorretas com


o<ecrrtado.

base

no exposto acima. (Objetivo2.2)

6. Besticorreta.Depoisques3Olangaaexce$opa$s2$,s2O
A, C, D, E, F, G e FI estio incorretas com
base

no exposto acima. (Objetivo 2.5)

7,

IllegalArgumentException

CeDestiocorretas. Integer.parselntpodelangarumaN'umlcerFormaLException,e
6asuasuperclasse(ouseja,umaexcegi.omaisampla).
classe de

A, B, E e F nio estlo na hierarquia de

rrrumberFormatException. (Objetivo

2.5)

8. A e C estio corretas. Lembre-se

polim6rfica, de forma que o compilador implementada, a excegio ter6 sido declara& & forma suficiente, e se C3 for implem entada, a excegio terisido manipulada de forma suficiente. C2 nlo 6 necessiria em nenhum dos casos.
de que ahrtha 4 est6fazendo uma chamada
sabe que uma exceglo poder6 ser langada. Se C 1 for

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 demais blocos rcdario caso precisa ser o riltimo.

235

nio

seja encontrada nenhuma instrugio

break. Observagio: d.efault nio

A, B, C, D
10.

F estio incorretas com base no exposto acima . (Objetivo 2.1)

Dest6correta.Umcontinue rotuladofuncionaapenasparaloops.Nestecaso,emboraor6nrlosejavilido, 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)
corretas.

label

lL C, D e E sio instrug6es
A
est6

incorreta. E aceit6vel usar assertivas para testar os argumentos de m6todos


a

private.
vod nio
o

B esrl incorraa Embora os erros de assertivas possam ser capturados, 12'

Sun recomenda que

faa. (Objetivo 2.3)

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

langada, o c6digo do bloco

catch

em aninhar blocos trylcatctr- Como de costume, quando uma excegio 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 rcurso 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 I

Seriolizog6o com o Pocole iovo.io

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


a

por alguns dos pontos fracos da classe String (por exemplo

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


se

poderi

ser

modificado

entio o que acontece quando um objeto String parece estar

modificando? Vamos &scobrir.

Strings sio objetos inalter6veis


Comegaremos com alguma informaglo de apoio sobre strinp. Naverdade, voc6 nXo precisari dessas informag6es no teste, 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
mas um pouco de contexcualizaglo sempre ajuda. caracteres Unicode

tm 16 bits (e nio os restritos 7 ou ntemaqonal |facilmente representado em Unicode.

bits que

ASCII fornece), um conjunto

de caracteres sofisticado e

EmJava, as strings sio ob.ietos. Exatamente como acontece com outros objetos, voca pode criar com apalavra-chave new, como vemos abaixo:

instancia de uma String

String s = new StringO;


Essa
se

linha de c6digo cria um novo objeto da classe String e atribui a vari6vel de referncia parecem iguais aos outros objetos. Agora, daremos um valor a String:

ele.

At aqui

os objetos

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

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


as

Mas espere um momento, nXo acabamos de dizer que

Strings slo inalter6veis? Entlo, o que significa essa conversa de

JAVA
"acr6scimo ao final da string"? Boapergunta; examinemos o que aconreceu realmente...

239

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

stuf f " que foi concatenado 6 por si s6 um novo objeto String. Contudo, 'abcdef " (referenciado por s2) e "abcdef more stuf f " (referenciado por s).
literal "more
E se ni.o tMssemos
a

temos referAncias apenas

visi,o ou

softe de criar uma segunda vari6vel de refer6ncia para

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 objeto String original de valor "Java". A Figura G2 most raacriagio deum objeto String sem a atribuigio a uma refencia
6

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 String'Java" original inalterada). Que tal se adicionarmos:
o

valor 'JAVA", mas

ele

foi perdido

,e

x ainda relerencia a

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

referncla String

Figurc valor "\tava". Em todos


outra
esses casos

6-1

Obietos Sfring e suos voridveis de refer6ncio

ji

existente, ruls nunst aaibminos

chamamos v6rios m6todos do objeto String para criar uma nova String alterando i Sting recim<iada uma vaiivel derefer6ncia.

Mas, podemos inserir umapequena

inversio no exemplo anterior:

String x = ",Java"; x = x.concat(" Rules!"); System.out.println(\rx = "


Dessa vez, quando o

+ x)

// Agora estamos atribuindo x ir nova String // a saida ser6:


/ / x = rTava Rules!

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 =


x. tolowercase ( ) ;

+ )<);

System.out.println( \x = \ + x);

x = x.tolowerCaseO

,-

// a saida 4: x = Java Rules! / / sem atribuiqdo, cria uma nova String / / sem atribuiqdo, a saida ainda 6: // x = Java Rules / / cria uma nova String, atribuida a x

abandonada

JAVA

24I

Passo

l: Slring

Varidvel de referGncia Str

Strinl__\

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 discussio anterior cont6m

// a aLrtbuiqdo origina a saida: //x=javarules!

as chaves para a compreensXo da inalterabili&de do objeto StringJava. Se voc0 entender realmenre os exemplos e diagramas, at6 mesmo detrilsparafrente, dve 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);


e

Qual seri o resultado? E quantos objetos String

vari6veis de refer6ncia foram criados antes da instruEio

println?
s1
e

Resposta:.O resuhado desse fragmento de c6digo 6 "spqg_winter spring summer". H6 duas variiveis de refer0ncia, 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 por tris desses compoftamentos. Um dos objetivos principais
das raz6es que

estio

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 linguemJava mais eficiente no

242 Copllulo 6: Strings, E/S, FormotoE6o e Porsing


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

uso da mem6ria,

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
referncia 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";
Nesse caso simples,

/ cria um objeto String e uma / / varilvef de referGncia


/

'abc"

ser6

inserido no pool e ro referenciari.

2 - String s = new String(..abc,,);


Nesse "aso,

/ cria dois objetos e uma / / varilvel de refer6ncia


/

j5 que-usamos

no pool) e

o referenciari.

palavra-chave new, a linguagem JavaciarS,umnovo objeto String na mem6ria comum (e nio 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 I

charAt(

) concat( )

Retornaocaracerlocalizadonoindiceespecificado

Anexa uma String ao final de ourra (" +" tamb|mfunciona)

JAVA

243

equalslgnorecase(

Determina

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


public String concat(String
s) Esse

// asaida6'r'

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


Os operadores de sobrecarregados + e +

)t

// a saida 6 "taxi cab"


a

executam fung6es semelhantes

do m6todo

concat

) . Por exemplo,

String x = "library"; System.out.println( x + " card"); 1. Stri-ng x = "Atlantic"; 2, x += \r ocean" 3. System.out.println( x );

// a saida 6 "library card"

/ 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, "At1antic ocean",eatribuindo-oavari6velx.Depoisquealinha2forexecutada,astringoriginalquex estavareferenciando, "At I ant i c ". ser6 abandonada.

publicbooleanequalslgnoreCase(Strings)

Essem6todoretornariumvalorboof eano

(true

ou

baseado na coincid6ncia entre o valor da String do argumento e o usado para chamar o m6todo. O m6todo retornari mesmo quando os caracteres dos objetos String que estiverem sendo comparados tiverem caixas diferentes. Por exemplo,

false) true

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 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
Os arrals tdm um atribato (e n6o ou

String Il x = new String[3];


qi'c|-6n ^lrf nTint-'ln1 v lana|-h/l l.

Esse m6todo retornari um objeto String cujo valor seri o da String public String replace(char old, char new) usada para chamar o m6todo, aatalizado de modo que qualquer ocorrncia 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',


public String substring(int begin) iublic String"substring(Int begfi, int

'x') );
O m6todo

/ a saida 6

"oXoXoXoX"

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:

end)

substring

( ) 6 usado para retornar umapane(ou.

/ como num passe de m6gina, o valor de cada char // 6 o mesmo que o seu indicel // asaida 6 "56789" System.out.prinLln ( x.substring (5) ) ; // asaida6"567' System.out.println( x.substring(5, B) ) ; String x = "0123456789";
/
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 String x = "A New Moon"; System.out.println( x. toUpperCase O
public String

chamar o m6todo, por6m, com os caracteres que estiverem em letras minfsculas agoraconverddos paramairisculas. Por exemplo,

/ a saida 6 "A

NEW MooN"

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,

trimQ
-

c+'.in^v-\1^.i\\. vLlfrry
^

System.out.println( x + "x" ); System.out,println( x.Erim( I + "x")

// o resuTLado 6 " //oresultado6"hix"

hi

xn

As classes StringBufrer e StringBuilder


fu classes java.lang.StringBuffere java.lang.StringBuilder devem serusadas quando voc6 tiver que fazer muitas alterag6es em opt ar objetos String stringp de caracteres. Como discutimos na secio anterior. os obietos Strine sio inalter6veis, portanto, se vod optar por fnnr strines segio anterior, muitas manioulac6es envolvendo esses obietos. terminar6 com virios deles abandonados em seu pool. (Mesmo que manipulagdes objetos, Dool. rcnhamos acesso agigabytes de RAMhojeem dia, nio 6 uma boaid6iadesperdigarmem6riacomobjetos dopool de p Strings descartados.) Por outro lado. os obietos do tipo StrineBuffer podem ser alterados repetidamente sem deixar para Strines descartados) StringDuffer lado, objetos 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

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


J6 que nenhuma nova atribuigio

/ a saida ! $x = abc"
concat ( ) foi

foi gerada, o novo objeto String criado com o m6todo 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
nio criamos nenhum objao adicional.
que, em cada um dos dois enemplos anteriores, houve uma s6 chamada a new, de forma qtre, nos dois Cada exemplo precisou de apenas um objeto String)Gx par-arodar.

*emplos, n6s

oBSERVAQoBS
nr

pene O EXAME: w

Pmuauelmefie 0 exame aaaliani rcu conheciaento

nbn a diferenga entre objetos Stringe StringBtlfer. Jd que os objetos StringBtfferpodea oSetos Shing alteradoq ofragnento de cddigo a segair se comportari dfenntenmte de amfragnento de aidigo semelbante qrc

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, String.Poro<emplo,
char,

furbla,Jkat, int, longe outros, por6m, o mais prov6vel de se encontrar no exame seri um objeto

Strj-ngBuffer sb = new StringBuffer("set "); sb.append("point") ; System.out.println( sb ) ; StringBuffer sb = new StringBuffer("pi = ");
sb.append(3.14159f);

// a saida 6 "set point"

System.out.println( sb ) ;

// asaida 6 "pi = 3.74L59"

246 Copitulo 6: Sirings, E/S,

FormotoE6o e Porsing

Este m6todo retorna um objeto StringBuilder e atualiza o public StringBuilder delete(int start, int end) 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 System. out.println(sb.delete (4, 6) ) ;


public StringBuilder insert(int offset, String

("0L23456789" ) ;

// asaida6"0\236789"

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 sb.reverse{);


System. ouL . pri-nt1n ( sb)
;

man

a plan a canal Panama");

/ / a saida 6 "amanaP lanac a nalp a nam A"

public String toStringQ


um objeto String:

Esse m6todo retorna o valor do objeto StringBuffer que chamou o m6todo como

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
os fllpicos

Muitas dat perguntas do exame que abordam

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, Aqui estd como decifrar esses "atalblr pr/iticls Jaua" quando enconhd-los:
/ . Descubra o qae a chamada do mdtodo da

embora normalmente n6o

s/am encontrados mais que trr.

2.

Use

como o objeto que

chanari

o segando ndtodo (a

exhvma esquerda rctomani (cbamaremos ase aa/or dc x). partir da uqaerda). Se hoauer somente dois ndtodos encadlados, o rualtado da
o

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
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
cln'eta atandl ar seguinter

5
e

247

cksu ()s

uerys em combinagdo) dr jaua.io: BaferedReader,

PrifiIYriter.

BffiredlViter, File, FileRtader, Filell/riter

O hipico referente a E/ S ten un bishirico estranho com a certifcagdo SCJP. Estaua incluido nat uendet do exame at6 remoyido na aersio 1 .4 e depois incluido nlaamefite na uersdo Jaua 5.

a /.2, depo*foi

Felizmente para n6s, os t6picos de E/S incluilos no exameJava 5 se restringe"m aE/S piaciacreres

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

serial

dEi".

Eis um resumo das classes de E/S que voc6 precisari entender para o exame: 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.

I F{:.

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.
Esta classe 6 usada para escrever em arquivos de caracteres. Os seus m6todos ( ) 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 FileVriter

write

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

fio usadas para /er e etcreuer b1tes, e os Rcadert e lVriters sdo utados para ler e esmuer caratteres. (Jma ueqqae todos 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
elases de stream
de

os

aipins

E/

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 ingls. 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 // classes de java.io


nlaqc lalri farl I

em

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 classe

propn)nede, File, uoci ndo estti criando um arqaiao"*'"r'q"i"o 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. *.

;br.il;;;;i;"""h"*"

e rodar

i"di."ia.3.

esse

programa, quando observar o conterido do diret6rio atual, voc6 nio descobriri chamado f ilewritel . txt. Quando cria uma nova instAncia da

class Writerl- { publj-c static void main(String [] args) { / / aviso: possiveis exceg6es Ery { boolean newFlle = false; / / 6 anan:q rrm ntr'iefn File fi-le = new File ("fileWrite1.txt" ); / / procura por um arquivo real System. out.println ( f i1e. exists ( ) ) i / / Lalvez crie um arquivo! newFile = fiIe. creaLeNewPile ( ) ; / / iA aviqr'a? System. out . println (newFile ) ; // olhe novamente system. out.println (file. exists ( ) ) i ] catch(fOException e) { }
v syerrqs srr vvJ v ev

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: I Primeira Execugio A primeira chamada


essas

quenew

FileO

exists

) retornou f alse, que era o que esper6vamos... lembre-se de

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

SegundaExecugeo Aprimeirachamadaaexists O retornatrue porquen6scriamosoarquivodurantea

I boolean exists ( ) Estem6todo retorna true se conseguirencontraro arquivo. I bootean creatlilevrFile ( ) 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

249

newFile = file.createNewFile
System. out
.

();

println (newFile ) ;
i
mais

Voci poderia uer algo como a seguinte linba de aldigo so{nha, o que

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

arquivo semwrapping:

at

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)


aCriouumavariiveldereferdnciaFile\Writer. fui. Criou um objeto FilerJfriter
eo

feztr6scoisas:

b c

atribuiu
(e

a fi/4/.

Criou um arquivo vazio em disco

voc6 pode provar que isso aconteceu).

2.Escrevemost2caracteresnoarquivocomom6todowriteO,erealizamosumf}ushO
4. O m6todo

eumcloseO.

3. Criamos um novo objeto FileReader, que tamb6m abriu o arquivo em disco para leitura.

readO leuoarquivointeiro, umcaracterdecada vez,eo

colocouem

5. Exibimos o nfmero de caraaeres cujotamanho ('size") foi lido, e fizemos um loop atrav6s do alray caracter que tenhamos lido, e depois fechamos o arquivo.

char[ ] in. rn CIdbindo cada

250 Copitulo 6: Sfrings,

E/S, Formotogdo e Porsing

Antesde avangarmos,vamosfalarsobre

flush( ) e close( ). Quandovoc6 escreve dados emumstream, certa buffer, e nunca 6possivel sabei ro^rrtt":.aqug{o lyfimaparte dos dados seri quantidade de &dor r.ri"r*azenadaem ,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:
os separadores de

1.

Quando esr6vamos escrevendo dados no arquivo, inserimos manualmente


nossos dados.

linha (neste caso \n) em

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.

a essas limitag6es, normalmente n6s sempre usaremos classes E/S de nivel mais alto, como BufferedWriter ou BufferedReader, em combinafro com FilelVriter ou FileReader.

Devido

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 juntas. Para o exame, vocA ter|, delazer o mesmo, mas n6s descobrir de quais classes ir6 precisar, e como faz&las trabalhar 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


Estende de

Classe de iava.io

Argumentos Principais do(s) Construtor(es)

Mtodos Principais

t r-l-e

Obj

ect

k1t6 r +:v,

qrrrnd v er +++y

createNewFi-1e

SLring

String, String

mkdir

delete ( ) exists ( ) isDirect,ory r_st, l-le ( ) 1i-st o


(
)

renameTo

FileWriter
Buf

Wri-ter

F'AIC

close

String
Wrr-ter

f 'l rrqh /
(

wrrte

feredWriterWriter

flush

newline

write PrintWriter Writer File (em Java 5) String (em .Tava 5)


r\lrt-nrrt-Q|-r6amu! vu uys es usrrl

()

cl-ose o

flush

format
nrini/\
Y!:frg \ /

)
,

nrint-fl\* yrr:ru!
rr

\, \ /

Writer
FileReader
Bu

write
read

nri-r1n/\ f rref v!

Reader

t are

()

String
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 classes rremos de quars precisar, e como as colocaremos para trabalhar juntas:

1.

Sabemos que queremos' em ultima instincia, trabalhar com um objeto File. Entio, quaisquer que sejam que usarmos, uma delas precisa ter um constnrtor que use um objeto do tipo File. 6-1, podemos ver que

as

outras classes

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

3. Quando

observamos os construtores de Print\7riter, vemos que podemos construir um objeto Print\Triter um objeto do tipo File, entio, tudo o que precisamos fazer para criar um objeto Print\Y/riter 6 o seguinte:

tivermos

File f ile = new FiIe (..f ilewrite2 . txt.') Printwri-ter pw = new Prj-ntWriter(fi1et

; ;

/ // // //
I

File passa o arquivo para o construtor de PrintWriter


um

cria

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 das pontas da cadeia, e que queremos um objeto Printtlflriter na ourra ponta. Podemos ver na Tabela GL que um

uma

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

Pode ser construida usando-se um File.

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,'\; FileWriter fw = new Fil-eWriter(fi1e);

/ / eri a rrm otrief o Eile

Printwri-ter pw = new Printwriter(fw);

pw.println( "howdy" ) ; pw. prinLln ( " folks " ) ;


A

/ // // // // // //
/

FileWriter que enviarS. a sua saida para urn File cria um PrintWriter qre enviarii a sua saida para um Writer
um

cria

escreve os dados

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 /

/ 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

String data = br.readlineO;


OBSERVAQ6TS E

/ obLer os seus dados a partir de um Reader / / Ld aLguns dados


/

pene O EXAME

poden ter encadeadas. quase garantido qae aoci encontrari quutdu flo exame que testardo o seu conhecinento de cono as classes de E/ S St)tto ,;iA*n ngdi ndo lhe tiuerfcado-clara, recoruendamos que uoci use a Tabela 6-1 cono referdncia e etcreua aldigos parafaTgr
e

experilncias sobre qaais combinagdes de encadramento s6o adlidat

quais sdo inudlidas.

Trabalhando com Arquivos e Diret6rios


fato de que a classe File 6 us adaparacnar arquivos e diret6rios. Al6m disso, os m6todos de 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.

Anteriormente, n6s aludimos

ao

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:

Chamaro m6todo

createNewFile ( ) em um objeto
;

File. Por exemplo:

File file = new File("foo") file . createNewFile ( ) ; 2.

/ ainda ndo existe um arquivo // cria um arquivo. "foo", qnre // 6atribuidoa'fi1e'


/

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,'); Printwriter Pw = nevr' Printwriter ( file) ;

/ /

/ ainda ndo existe

um

arguivo

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


myDir.mkdirO;

/ | rri:

rrm nlriol-n

/ cria

um

diret6rio real
esses

Assim que tiver um diret6rio, vocd pode colocar arquivos nele e trabalhar com

arquivos:

rile myFile = new File(rnyDir, "myFile.LxL"); myFile. createNewFile ( ) ;


c6digo 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
Esse

como voce poderia escrever dados no arquivo

myFile: PrintWriter pw = new PrintWriter(myFile);

JAVA

253

pw.println ("new stuf pw. flushO ;


pw.closeO;

f );

,,

nio existaum,

Cuidado ao criarnovosdiret6rios! Comovimos, construirumReaderou \trfritercriariautomaticamenteumarquivo, caso mas nio acontece o mesmo com diret6rios:

File myDir = new File("mydir',) ; //myDit.mkdir0; File myFile = new File( myDir, "myFile.txt"); myFile.createNewFileo;
Isso

//

chamada

amkdiro omitida!

// exceqio se ndo houver mkdir!

irigeraruma exce$o parecida com

java.io.IoException: No such file or direcforv


VocApodeapontarumobjetoFile paraumarquivooudiret6rioexistenre.Porexemplo,imaginequej6tenhamosum

existingDir, no qud reside um arquivo linhas de texto. Quando voc6 roda o seguinte c6digo,
subdiret6rio chamado

existingDirrile . txl,
// atribui

o qual cont6m algumas

File existingDir = new File("existingDir,,); System. out . println ( exist j-ngDir. isDirectory ( ) ) , File existingDirfile = new File( existingDir, "existingDirFile.txt"); System. out.println (existingDirFile. isFile ( ) ) ; FileReader fr = new FileReader (existingDirFile) BufferedReader br = new BufferedReader(fr); String s; while( (s = br.readline0) != nul1) System. out.println (s) ; br.closeO;
a

um

diret6rio

/ aluribu!

um arcrurvo

/ cria

um Reader

// 16 dados

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") de1Fi1e2 . createNewrile ( ) ;
Aal Fi I a1 Aal afa / \

/ adiciona um arquivo ao diret6rio


/

aE:aga um

arquivo

System.out.println( "delDir is + delDir.deleteO);

"

/ lcenta apagar / / o diret6rLo


/
);

File

newName

= new File ( delDir, "newName.txt"

delFi1e2 . renameTo (newName ) ; File newDir = new File("newDir"); defDir. renameTo (newDir) ;
Isso gera a saida:

/ um novo objeto // renomeia o arquivo // renomeia o diret6rio


/

delDir is false
e nos deixa com um diret6rio chamado que podemos deduzir desse resultado:

newDir

que cont6m um arquivo chamado newName . txt. Eis algumas regras

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 Filelnputstrean, Fileoatpatstrean, oblutlnputStrean, objectoutputstrean e seiati\abte.

255

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

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
um stream, e um segundo para ler o stream e deserializar os objetos.
Obj
e escrevA-los em

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"
ectOutputstream os = new ObjectOutputstream(fs),. os.writeobject (c) ; t/ 3
Obj

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
Esse 6

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. um exemplo simplificad o da serializagno na prhtica. mais complexas associadas com aserializagio.

Ao longo

das

pr6ximas p6ginas, veremos algumas das quest6es

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) thecollar = col-Iar; doqSize = size;


)

public Coll-ar getcoll-ar() { return theCollar;


t nl:qq f-n]l:r intf nnl 1:rqi za. cizal t
(

nrirrafa nrrhl in

/-allarlinf

colLarSize = size; ]
I I r^fr1rn nnl I arQi zo.
I

public int getCol-farSize


)

Agora crie um Dog... Primeiramente, voc6 cria um Collar (*coleira") para o Dog:

Coffar c = new Collar(3)


Dog

E entio cria um novo Dog, passando

a ele

o Collar:

d = new Dog(c, 8);

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.

Agor4 o que acontece

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 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 antertace Seridizable. Se quisermos ulvar objetos Dog por er<emplo, rcremos de modificar a classe Dog da seguinte forma

serializiveis,

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

257

'imnnrl- :*'*..-..i in i=rra

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.
ObjectOutputstream os = new ObjectOutputstream(fs),. os.writeObject (d) ;
os. close O
)
,.

ser,, ) ;

) 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
tornarmos serializ6vel, enteo neo haverh problemas:

ea

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-'] in yuv+re )
rrre

} l

inf

aat-(-nllareiual\ Yvuvvrrs!er-v\/

It !eusrrr rafrrrn

an1l:reiza.

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 tiv6ssemos a opgeo de tornar a classe Collar serializ6vel? Ficamos restritos a um Dog n1o-serializ6vel?

nio

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

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 de Collar, voc6 nlo ter6 como fazer todos esses reparos (panindo do principio que voc6 sequer iria querer TENTAR esse caminho). OU
2.
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?

li

ai q.te entra o modificador transient. Se vocd marcar avari|velde instAncia Collar de Dog como trransient, 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
I

/ ndo 6 mais Serializable // mesmo c6digo


/

Agora n6s temos um Dog serializivel, com um Collar nlo-seializivel, mas o Dog marcou o Collar como

sient; asuda6 before: collar size is 3 Exception in thread *main" java. lang.NullPointerException
Usando writeobiect e readObject

tran-

E agora, o que n6s faremos?

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

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

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 / / e atribui-lo ao Doq
]

um novo

Col]ar,

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 private int dogSize,. public Dog(Co11ar col1ar, int size) { theCollar = collar; dogSize = size;
]

Dodmos

geriaLizar ieto

public Co1lar getCollarO { return theCollar; } Drivate void writaObject (ObjectorltDutstrearn oF) l / / Ianqa loException try { os.defaultwriteobject ( ) t os . writelnt (theCollar. getcol-l-arSize ( ) ) ; ) catch (Exception e) { e.printStackTraceO; }
)

// r
// //
2
3

Drivate voidt readObj ect (Obj ecthDut,st,ream ie ) { / / l-anqa IoException, ClassNotFoundException trY {
is.defaultaeadObject
()

//

;
}

// s
//
6

theCollar = new Coll-ar(is.readlntO ); ) 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, ou tratar, mas recomendamos que as trate.

writeobj ect ( ) pode langar exceg6es. Voc6 as pode declarar


apartirdewriteobjectO,est6dizendoAjVMpararealizar

2.QuandovocdchamadefaultWriteobjectO

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, se voc6 nXo implementar um m6todo

defaultReadobj ect ( ) readobj ect ( ) .

cuidar| da deserializagio normal que ocorre

6. Finalmente, criamos um novo objeto Collar paru o Dog usando o tamanho que serializamos manualmente. atpolt de te.mos cha=mado def aultRea-aoni ect ( ) , ou os dados streamed ffivemos de chamar

readlnt (l

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

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.
Se uma superclasseforSeialiqable, entdo, de aeordo com

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

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

3. Todos os construtores de superclasses

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
Mas esrat

26I

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

variivel num deveri ser 10. Quando a instAncia

voc6 serializar uma instAncia de Foo tlepoh que o m6todo changeNum ( ) rodar, o valor da 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
se

Obviamente,

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 referncias 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
v

St- ri +Afvnq p6111g; eL

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,


Dog

FormotoE6o e Porsing

d = 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


(l- ri rn n:ma
.

Serializable

Dog(int w, String n) i weight = w; name = ni


)

/ l:erdado / / ndo herdado


/

)
nl aqc Anim:] I

/ ndo serializ6ve-

int weight =
]
que produz esta saida:

42;

before: Fido afLer: Fido

35 42
seu

O ponto principal aqui 6 que, pelo fato de Animal nio ser serializ6vel, o weight de Dog, herdada de Animal, quando Dog foi deserializado.

construtor rodou e resetou

variivel

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
seria

263

problema?

lsado para substituir aquele atualmente presente na (rinica) classe Dog atualmente

carregada? Entendeu o

As vari6veis est6ticas NLINCA sio salvas como parte do estado do objeto, porque elas nio perrencem ao objeto!

oBSERVAQ6ES
E

pene O EXAME

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

un objxo Dog

flcil ucreuer aidigo de rcrialiqagdo, poden ocotrer problemas referentes is uersdes das clasxs, no mando real, Se uoed sahar 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
especifn. Desmuer
o

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

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


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
Se

usem classes que nio foram mencionadas especificamente no objetivo da Sun. Eis as quatro classes relacionadas
voc precisad entender:

datas que

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. como "01/01 /70" ov"January
loacis em todo o mundo.

I j ava. text . DateFormat


l,

Esta classe 6 usada paraf.ormatar datas nio apenas fornecendo virios estilos 1970", mas tamb6m paraformatar datas para diversos locais em todo o mundo.

I java. text.NumberFormat I java.util.Locale

Esta classe 6 usada para f.ormatar nrimeros e moedas para diversos

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 1. Crie um Date: orte d = new DaE.e ( ); 2. Obtenha o seu valor: String s = d.toStrj.ng0i
1..

Obter a data e ahora atuais Obterum objeto


que

lhepermita

Crie um Calendar:carendar

realizar c6lculos de data e hora no seu local

2. IJse

c.aaa(.
hora.

Calendar. getlnstance

()

) e c.ro11 (.

) para realizar manipulaE6es

de data e

Obter um objeto que lhepermitarealizar cilculos de data e hora em um local diferente.

1.

CrieumLocale:

Locale loc = new Locale(1ingtua); ou Locale foc = newlocafe(1ingua, pais)i


2.

Crie um Calendar para

esse

local:

3.Usec.aaa(. .)ec.ro11 (.
de data e hora.

Calendar c = CaLendar.getlnstance(1oc);

.)

parareahzar manipulag6es

Obter um objeto que lhe pe rmitareafinar cilculos de dataehora,e depois formatar


o resultado em diferentes locais diferentes estilos de datas.

1.

CrieumCalendar:

Calendar c = Calendar.getlnstanceO;
2. Crie uml-ocale para cada local:

com

Locale 1oc = new Locale(.

.);

3. Convena seu Calendar em um Date:

Date d = c.getTime0;
4.

CrieumDateFormat

paracadaLocale:

DateFormat df = DateFormat.getDatelnstance

(sty1e, loc)

5. Use o

m6todo formatfl paracriar datxformatadas:

String s = df.format(d)i
Obterum objeto que lhe permita formatar nrimeros ou moedas em diversos locais.
Localeloc
Y

1.

Crie um Locale para cada local:


r r

newl,ocale(. . Ji

tt

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
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 e 10. de janeiro nimero de milisegundos (voc6 sabe, sio 1000 deles por segundo), entre a data sendo representada ^rmazenao 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:
'imnnrla1:ec i:rra rrl- i l { { *.

m6ern=f66

public static void main(String[] args)

Date d1 = new Date(1-000000000000L); // um trilhSol System.out.println("1st date " + d1.tostrinS() ) ;

JAVA

265

Na

nossa

JVM, que

usa um local dos Estados Unidos, a saida 6

1st date Sat Sep 0B 1_9:46:40


Embora
a

MDT 2001
a cada 3L e

Ok, para refer6ncia futura lembre-se de que h6 um trilhio de milisegundos

2/3

anos.

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

setrime,

maioria dos m6todos de Date tenham sido depreciados, ainda

6.

aceitllelusar os m6todos

getrime

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

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

Nio

Calendar c = new
dafTncfanno I \.

Calendaro; // inv6l-ido, Calendar 6 abstrata


cal-endar,
voc6 precisa usar um dos m6todos estAticos sobrecarregados

Para poder criar uma instAncia de

no exemplo acima, a variivel da sua referncia 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 . 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$.

Calendar ca1 = Calendar.getlnstanceO ; Quando voc6 obt6m uma refer6ncia Calendar, como cal

uti

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:
imnnrliarra rrf i l *-

class Dates2 { public static void main(String[] args)


Date d1 = new Date(1000000000000L);
(rr<t-am eJJuelr.vuu.!,rIIILIII\ ^-;hf ^rrf ln/$1^t I-L i-ts^ uqLC

r\ + A1 F^ef rira/\ T UI .LvJL!IttV\r

\. r,

Calendar c = Calendar.getlnstanceO

266 Copitulo 6: Sirings, E/S, FormotoE6o e

Porsing

e.setTine(d1);

ll ll

#L

if (c. SITNDAY == c. getFirstDalofWeek ( ) ) System.out.println("Sunday j-s the first day of the week"); mi1li day of week is " System.out.println("trillionth
+ c. get (c.DAY-OF-WEER) c.add (Calendar.MONTH,
1)

#2

Date d2 = c.getTime()t

/l *3 ll *4 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)

c.add(Calendar.YEAR, 2) ; c . add (Calendar. DAY_oF_WEEK, -2);


5. Convena o valor de

// // // //

subtrai 4 horas do valor adicj-ona 2 anos ao valor subtrai dois dias do valor de c

de de

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:

c 6 8 de outubro de 2001 c.rol](Calendar.MONTH, 9); // repare no ano da saida


asqrrma mre

//

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

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 dfa [4] = DateFormat.getDatelnstance dfa [ 5 ] = DateFormat . getDatelnstance


for(DateFormat df : dfa)
q\/qf am nrrl- nri
vJvuelrtvuL.v!fllLrrr\u!

(DateFormat.MEDIUM)

(DateFormat.LONG) (DateFormat . FULL)

;
;

nl- l n ldf

f nm:f

/Al \ \
\sr/ /,

que, na nossaJVM, produz

9/8/01,7:46 Sep B, 2001


9/B/0L

PM

Sep

8,

2001

Septemlcer

8,

2001

Saturday, September 8, 200L


Examinando esse c6digo, percebemos algumas coisas logo de cara. Primeiramente, parece que DateFormat 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
6

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


que, na nossaJVM, produz

Porsing
)

System.out.println( "parse exc" ) ;

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.

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,

AO TRABALHO
A API para DateFormat.parse(
expeilncia, parseQ ndo

explica que, porpadrio, o mdtodo parse ( ) d ben to/erante ao faqerparsing de datat. Pela nosa 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"); Locale locBR = new Loca]e("it",


IJsar
esses

"CH");

// Italiano / / Suisa

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


em 0)

,.

/ 14 de dezembro de 20L0 / / (a contagem dos meses comeqa


/

Date d2 = c.getTimeO; Locale Locale Locale Locale locIT = locPT = locBR = l-oclN =
new Locale("it", new Locale("pt"); new Local-e("pt", new Locale("hi",
\\pDnI. \ T\TZ I
f Laffa

Portugaf

Brasil India

Locale 1oc,JA = new Locale("ja");


DateFormat dfUS = DaleFormat.getlnstanceO i System.out.println("US " + dfUS.format(d2) ) ;

JAVA

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
Svsl-om orrlnrinl'l
(

DateFormat.FULL, l-ocPT)
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


DateFormat

(d2) ) ;

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 Rrazil T)omincq, 14 de Dezembro de
Tnr{i: 2}2a?? 21 2?22?? t2?2

2010 2010

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 instanciagdo. Cuidado czm cddigzs que tentam modficar o local de

nlnentl
que

una instdncia existente - ndo existe nenhtm mitodo

da 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"); Locale l-ocDK = new Locale("da", "DK"); Locale loclT = new Locale("it", ., IT,,);

/ Brasil // Dinamarca / / 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 loc def loc

Brazil
Brasi-1

Danish
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. formatar nrimeros ou valores monetArios:

Nio

surpresa que essa classe seja usada para

fLoat f1 = L23.4567f:
Locale locFR = new Locale('fr"); 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 ) ). / / Er^rra

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

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

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

ji

Opg6es de Criagio para as Instincias

util

Date

new DateO; new Date (lonq milisegnrndosDesdeOlOl70) Calendar. geLlnstance ( ) t Calendar. getfnstance (Locale ),

util . Calendar util


.

Local-e

Locale. getDefault ( ), new locale (St.ring lingua) ; Ql-r'ina frrY new locale(String 'I inarra

naiq\ Y\4Av,

'

text . DateFormat

DateFormat. getlnstance ( ), DateFormat . getDatelnstance ( ) ; DateFormat . getDatelnstance ( estif o ) ; DateFormat. getDatefnsLance (esti1o, Loca]e)
NumberFormat. getlnstance ( ) NumberFormat . qetlns tance ( Locale ) NumberFormat . getNumberlns tance ( ) NumberPormat . getNumberf ns tance ( Local e ) NumberFormat . getcurrencyTnstance ( ) NumberFormat . getcurrencylnstance (Locale

text

NumberFormat

Obietivo poro o Certificog6o Parsing, Tokenizagilo e Formatagio (Objetivo 3.5 do Exame)


3.5 Escreuer aidigo que urc
as

APIs J2SE padrdes

dos

ttreams. Para stringt, escreuer aidigo q/./e ilre as classes Pattern

pacotesjaua.atil e jaua.uti/.regexparafotwatar oufaryrparcing de $ings ou 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,

ohs)

en Stingt deformatos.

272 Copitulo 6: Sirings, E/S,

Formoioqdo e Porsing

Comegaremos com mais um aviso: esta pequena segio regex. Nesta segio, abordaremos tr0s id6ias bisicas:

nio vai lhe transformar de iniciante em regex em guru

de

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.
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
pelo bisico.
Esteja voc procurando por coisas ou tokenizando coisas, muitos dos conceitos sio os mesmos, enteo comecemos 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
ab

as ocorrAncias

(ov con'eEondincia) da

expressdo

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

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


Matcher m = p.matcher("abaaaba"); boolean b = false; while (b = m. find( ) ) { System.out.print(m.startO + " ");
]
)

/ a expressdo / / a fonLe
/

JAVA

273

]
Isso produz:

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

Nio

fonte:
l_n(I]-ces

abababa

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
pode ser reatiliqado.
e,

dEoh que am caracter dafonte tenba sido usado em ama ocorrncia,

e/e ndo

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

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

o argumento
adiante.)

"\d"

do m6todo

compile,

transformando-o em

4, 6,7 e 8. (Se quiser tentar isso em casa, voc6 teri de "escapar" "\ \d", mas falaremos mais sobre isso logo

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 \s
\w

Umdigito
Um caracterde espago em branco
(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 serem procurados, usado colchetes e um hifen:
a

serem procurados, usando colchetes;

intervalos de caracteres a

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 a- f ou A- F, mas NAO procura por uma combinagSo fa:

busca

por ocorrOncias

das

letras

274 Copltulo 6: Strings,


t

E/S, FormoioE6o e Porsing

a- fA-F

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


e/es

de

conjantos. Embora esrr,s clnstratlres ndo caiam flo exane, a c/asse jaua. ati /. regex.Pattern.

sdo bastante ilteis, e bons exemplos

deles

poden ser encontrados na API para

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
seja

A expresslo acima poderia


seja

*f

um "0", o segundo

ser descrita como: "encontre um conjunto de caracteres no qual o primeiro caracter ou um 'x" ou um "xo, e oterceiro seja ou um digito de "0" a "9", ou uma letra de "a" 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.)

se quis6ssemos apenas que regex encontrasse ocorrncias 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.

Como segundo passo, vamos pensar em um problema mais ficil. E

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 seguinte saida regex
a

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

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
lll nr^r

essa

expressio apenas ao pedago do arquivo de texto que listamos acima, o regex retorna
ndf

le.ha.l

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]

?\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 , para zero ou mais


para um ou mais

o 6 ganancioso, 'e? 6 relutante

+ 6 ganancioso, + ? 6 relutante,

O que acontece quando temos


fonte: yyxxxyxx

fonte e o padrio seguintes?

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:

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
para o exame.

aspectos referentes a quantifcadores regex do qlrc 0s qtle discutimos aqut, rzasj,i abordamos mais do qae o rufciente 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
ef-.i-^ vulJrrY h v \r\ \.

// o compilador v isso como

uma

JAVA

277

/,/ seqr.i6ncia de escape invelida em \lava // o compilador fica feliz, e o regex ve um // ponto, e nao um metacaracter
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

Um problema semelhante pode ocorrer quando voce

? 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 = \b = \t =
E

linerted (que
backspace

uocd

poderi enczfrtrar no

exame)

tab

ndo precisard

oilras, que uocd poderi encontrar na Etpecifcagdo da Linguagen Jaua. Fora uma euentual apaipdo dc um v preocupar com seqi.i4ncias de ucape Jaaa no exame.

\n

dentro de

una String uoci

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


aprendeu um pouco de regex, usar as classes java.util.regex.Panern @attern) e java.util.regex.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: Depois que

vod

(Matcher)

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

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

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
exame,
uoc deueni

se asar regex classe

nber que a

appendReplacement

),

i para realiqar operagdes de busca e substitaipdo. Embora as operagdu de nbstitaipdo ndo caiam no Matcherfomece diuersos ndtodos qae realiqan operagdu de busca e de substituipio. Consulte os mitodos appendTail ( ) e O na API d.e Matcberpara nais detalbes.

replaceAll

regdes.Naida AclasseMatcherlhepermiteprocuraremzubconjuntosdosseusdados.fonteusandoseumconceitochamado 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:
imnnrliarra rrf il *.

class ScanIn { public static void main(String[] args)


q\/<|-am nrrlrJousrrL.vuu.vrfare\ nrinlf \\innl1f frlvue. ( . t\\. /,

System. out

flush

Lrv

Scanner
ql-ri

s = new Scanner(System.in)
.

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"


f rrPuu.

.i

nnrrts.

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

279

2bjetgs' (usando

o mtodo

arrays ort conjuntos. Estudaremos as duas classes da A?I que fornecem recursos de tokenizagio: String 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:
Se

"ab, cd5b, 6x,

24,,

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

iarzr

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
produz

"ab5 ccc 45 @" "\d"

count
>ab<

>ccc<
>@<

"\ \". Por causa disso, e dependendo

"\\\\d".)

(ObservagXo: lembre-se de que, para representar "\' em uma string, voc6 poderi ter de usar a seqii6ncia de escape do seu SO, o seu segundo argumento poder6 ter de ser "\ \ d" ou at6 mesmo

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


se usar

voc6 desejarl ver os tokens no ter criado os momento em que est1o sendo produzidos, e, possivelmente, interromper uma operaEio grande arquivo-. Se esse nrimero tokens de que p*.ir". Po, ex.mplo, .ro.6 pod"ri" buscar um nrimero de telefone em um seu nimero' 1ogo ,ro inicio do arquivo, voc6 gistaria de poder fin alivar o processo de tokenizaElo logo que obtiver

IJm inconveniente de

o m6todo

string. split ( ) 6 que freqiientemente

de tokenizagXo ap6s

"p"r...r Scannerfomece A dasse

uma ricaAPlpara redizar justamente isso'

oBSERVAQ6ESpeneoE)(AME
Pelofan /e
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

System. out.printJ.nO

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
etcape qae ndo existe.

de

A sintaxe correta d String s = "ab.cde.fg"; String[ ] tokens = s.split("\\.");


6 o Cadillac do processo de tokenizaqio. Quando precisar executar tarefas s6rias de tokeniza$o, use maravilhosa classe tem de tudo. Al6m das fung6es bisicas de tokenizagio fornecidas por

Tokenizando com Scanner


A
classe

java.util.Scanner
essa

Scanner-

String . split

( ) , a classe

Scanner oferece os seguintes recursos:

r r r

Scanners podem ser construidos usando-se arquivos, streams ou Strings como fontes.

AtokenizaEio|reahzadadentrodeumloop,paraquevocOpossafinalizaroprocessoaqualquermomento.
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 )

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
sio convenidos para os
os tokens depois de os obter, mas voc6 pode ver que os tokens de s2
seus respectivostipos primitivos-. lJm ponto fundamental 6 m6todos "q"i chamados hasNextXxx ( ) testam o valor do pr6ximo token, mas neo o obtm realmenti, nem se movem para o pr6ximo token nos dados-fonte. Todos os m6todos nextxxx ( ) realizam duas fung6es: obtdm o pr6ximo t6ken, e

q.tt

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

formatagio. VocA pode usar

formatO usaaclassejava.utif .Formatterpar^f.azerotrabalhopesadode 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) ) ;
se voc6

A string de formatagio pode conter tanto informag6es de strings literais dados de formatagio especificos de argumentos. A dica para determinar

nXo-associadas com argumentos quanto esti olhando para dados 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:

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:

* larg_index$] [flags] [width] [.precision] conversion char Os valores dentro de [ ] sio opcionais. Em outras palavras, os rlnicos elementos

arg-index
nessa posigio.

Um nrimero inteiro seguido diretamente por um

$, isso indica qual argumento dever6 ser exibido

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 parnteses width Este valor indica o ndmero minimo de caracteres a serem exibidos (se quiser ter colunas
organizadas e bonitas, voc6 usari este valor o tempo todo).

bem

precision
,r,t*..or,

Para o exame, voc6 s6 precisar6 disto ao formatar um nimero de ponto flutuante e, no caso desses precision indica o ndmero de digitos a serem exibidos depois do ponto decimal' que voc6 est6 formatando. Os que voc6 precisa conhecer:

conversion O tipo do argumento

I I f r I

b boolean c char d integer f floating point s string int i1 = -L23;


System.out.printf (">ts1$ (7d< \n" , rL) System.out.printf (">t0, 7d< \n", i2\ ;
;

Vejamos algumas dessas strings de formataglo na pr6tica:

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<

( para ajudar a demonstrar como funcionam as larguras minimas, os Q.,l6s adicionamos os literais ) e 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
;

in t.hread \\main" j ava util ception: d != java.lang.Double


Exception
.

. 11

legalFormatConversionEx-

Resumo para a certificagio


A coisa mais importante a se lembrar sobre Strings 6 que os ofietotString sio inalteriveis, mas x rcferncias 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.

Strings

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

283

Lembre-se de que os objetos do tipo File podem representar arquivos ou diret6rios, mas, at6 ou mkDir ( ) , ;inda n{o tericriado nada ,ro i.., disco rigido. As classes do java.io foram elaboradas para serem encadeadas. Raramente voce utilizar| um FileReadei ou File\Triter Pacote 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. que voc6 chamg

E/S de

arquivos

createNewFile ( )

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

String. split

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

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.

de dados para saida pode ser feita usando-se a classe Formatter, ou mais comumente usando-se os

Exercicios rdpidos
Aqui estio alguns dos pontos principais dos objetivos para certificagio
deste capitulo.

Usando String, StringBuffer e StringBuilder (Objetivo 3.1)

E E E
El

Os objetos String sio inalter6veis, por6m,


Se Se

as

variiveis de refer0ncia String nio.


seu programa.

voc6 criar uma nova String sem

atribuila, ela{icar| perdida para

voc redirecionar a referAncia a uma String para uma nova String, o objeto String anterior pode ser perdido.

Os m6todos String usam indices iniciados em zero, exceto para o segundo argumento de

substring (

classe String 6 f

inal - seus m6todos nio podem ser sobrescritas.

284 Copitulo 6: Strings,

E/S, FormotoE6o e Porsing

fl fl tr

ao pool. Quando uma String literal for encontrada pela VM, ela seri adicionada As Strings tpm um m6todo chamado length ( ) e os arrays tem um atributo chamado

lengLh.

A API

de StringBuffer 6 a mesma que a nova

API

de StringBuilder, exceto pelo fato de que os m6todos de

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

StringBuilder nXo s5o sincronizados Para seguranga de threads. Os m6todos de StringBuilder deverio rodar mais ripido do que os de StringBuffer.

tr E E
D

O m6todo equals

( ) de StringBuffer
encadeados

nio 6 sobrescrito;

ele

nlo compara valores.

Lembre-se de que m6todos

sio avaliados da esquerda para a direita.

M6todos String que voc6 deve memorizar: charAt O , concat O, equalslgnoreCase O length O, replace ( ) , substring ( ) , tolowerCase ( ) , toString ( ) , toUpperCase ( ) e trim ( ') .

MdtodosdeStringbufferquevocdevememorizar:appendO,

toString

deleteO,insertO, reverseO

().

E/S de Arquivos (Objetivo 3.2)

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 16los, mas normalmente elas devem ser encapsuladas.

fl E E E
O

As classes de java.io devem ser "encadeadas" ou "encapsuladas" decorador).

(esse 6

um uso comum do padrlo de projeto


se

E bastante comum "encapsular" um BufferedR mais alto (mais convenientes).


E,

eader em

um FileRead er, para

ter acesso a m6todos de nivel

bastante comum'encapsular" um BufferedVriter em um FilelW'riter, para se ter acesso a mdtodos de nivel mais alto (mais convenientes).
de Java 5 eles

PrintVriters podem ser usados para encapsular outros \ilflriters mas, a partir diretamente apartir de Files ou Strings. OsPrintrVritersdeJava5t6mnovos m6todos appendO, format ( )

podem ser criados

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

E tr E E E 0

precisam implementar a interface Serializable para que os seus objetos possam ser serializados. objetos, e o m6todo

O m6todo
Se

ObjectOutputstream.writeObjecL ( ) serializa Obj ectlnputstream. readObj ect ( ) os deserializa.


voc6 marcar uma vari6vel de instAncia com

transient.

ela

nio seri serializada. embora todo o resto do

estado do objeto seja.

VocA pode ampliar o processo automitico de serializagio de uma classe implementando os m6todos

writeObjectO ereadObjectO.Seofizer,aschamadasinseridasparadefaultWriteObjectO
defaultReadObject
Se

),respectivamente, cuidarlodapartedaserializa$oqueacontecenormalmente.
as suas subclasses

uma superclasse implementar Serializable, entio

tamb6m

implementam automaticarnente.

Se uma superclasse nio implementar Serializable, entio, quando um objeto constnrtor da superclasse sera executado.

da subclasse

for deseri alizado, o

JAVA

285

E E D tr fl D tr E

DatalnpudtreameDauOutputStream,naverdade,nlocaemnoenamgapaardoqueatiescritonosobjetivos&Stm.

Datas, Nrimeros e Moeda (Objetivo 3.4)


As classes que voc6 precisa entender slo java.util.Date, java.util.Calendar, java.text.DateFormar,

java.text.NumberFormat e java.util.Locale.

A maioria dos m6todos da classe Date foram depreciados.


Um Date 6 armazenado como um 1ong,
e refere-se ao

nrimero de milisegundos desde 1o. de janeiro de 1970.

Os objetos Date sio uma esp6cie de ponre entre as classes Calendar e Locale. 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.

Crie instincias de Calendar usando m6todos est6ticos de f6brica

(getrnstance ( )).

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).
InstAncias de DateFormat sio criadas usando-se m6todos estiticos de fibrica

E B E tr D E E

(getrnstance

getDatelnstanceO ) .
Existem diversos "estilos" de formatagio disponiveis na classe DateFormat.

Os estilos de DateFormat podem ser aplicados a diversos Locales para se criar uma s6rie de saidas para determinada data.

O m6todo DateFormat. f ormat ( )

6 usado para se

criar Strings contendo datas devidamente formatadas.

classe

Locale 6 usada em conjunto com DateFormat e NumberFormat.


e

Tanto objetos DateFormat quanto NumberFormat podem ser construidos com um Locale especifico

imutivel.
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
f,l Q

regex 6 uma abreviaEio de express6es regulares, que sio padr6es usados para se procurar por dados dentro de grandes fontes de dados. regex 6 uma sublinguagem existente em Java e em outras linguagens (como Perl). 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". Estude os metacaracteres
em seqiincia".

E fl E E
D D

\d, \s, \we.

(ponto).

regex fornece quantificadores que lhe permitem especificar conceitos como: "Procure por um ou mais digitos Estude os quantificadores gananciosos ?, 't e Lembre-se de que os metacaracteres e Strings

o devido escape deles. Por exemplo,

String s = "\\d";

nio trabalham bem juntos, a nio

ser que voc6 se lembre de f.azer

As

classes

Pattern e Matcher t6m as capacidades regex mais poderosas em Java.

VocAdeverientendero m6todo compile O dePatterne os m6todosmatcher( start ( ) e group( ) de Matcher.


Y oc|
nda precisar6

),patternO, findO,

J tr

entender os m6todos de substituigio de Matcher.


6a

Voc6 pode usar java.util.S canner patafazcr buscas regex simples, mas o objetivo original dessa classe

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 tr

A tokenizagio pode ser feita com

a classe Scanner

ou com

String. split ( ).

Os delimitadores sio caracteres rinicos, como virgulas, ou entAo complexas express6es regex.

286 Copftulo 6: Strings,

E/S, Formotogdo e Porsing

lhe permite tokenizar dados de dentro de um loop, o qual lhe permite interromper a operagio sempre que quiser.

classe Scanner

E I
D

classe Scanner lhe

permite tokenizar Strings, $reams ou arquivos.

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.
Existem dois m6todos novos em Java para formataglo de dados. Esses m6todos sio f ormat ( ) Eles se encontram na classe PrintStream, da qual o out de System. out 6 uma instlncia. Os m6todos f
e

print f O

ormat ( )

O A formataglo O O

printf ( ) tAm funcionalidades indAnticas. de dados com print.f ( ) (ou f ormat ( )) 6 realizada usando-se
e

stings deformatagdo que

sio

associadas com argumentos

primitivos ou strings.
as suas

O m6todo f ormat

( ) lhe

permite misturar literais com

strings de formatagXo.

Os valores para strings de formataglo que voc deve conhecer sio:

O Flags: -, +, 0, "," e ( E Convers6es: b, c, d, f E

es
bater com o tipo do seu argumento, ser6 langada uma excegio.

Se o seu caracter de conversSo nd,o

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

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.
F. r4r E langada uma excegio no tempo de execugio. r { t

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 B. A compilagio

sucesso.

falha devido apenas a um erro na linha 15.


apenas a um erro na linha 16. apenas a um

C. A compilaglo falha devido D. A compilaglo falha devido

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))); 5 += "=5 "; if(s1 == 7) if(s1 < new fnteger(7+1) ) s += "fly "; System. out . println ( s ) ;
j

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
n 3r I

das anteriores.

F. A compilagio

falha.
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) ; DateFormat df = new DateFormat ( ) t 5. 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.
n

1123631685981L
4r r r

I I 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! ^^6^"F^a cl-nraTf la\
.

a^n6rrf6rt\. vurrrPuus!\/,

void storelt(Computer c) { trY { ObjectOutputstream os = new Objectoutputstream(


new FileOutputstream( "nyFi1e" ) ) ;
os
.

writeObj ect

c);

JAVA

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

D. Exatamente um obieto

serializado. serializados.

E. Exatamente dois objetos sio

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

t)
f i I ^

(Exception x)
.

dir ] catch

(dir, "fi1e3" ) ; ("dir3". "fi1e3");

File dir ( "dir3" 1 ; = new File (dir, file);


.mkdj-rO;

r-re

= new File
nra:faFila/\ '

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

E. Uma mesma instAncia de NumberFormat pode ser usada para para criar nimeros formatados a partir de nrimeros.

criar objetos Number a panir de Strings

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

Todas

as

tr6s classes t6m um m6todo

length

()

Os objetos do tipo StringBuffer sio seguros em relagXo aos threads. Todas


as

trAs classes t6m m6todos

append ( ) sobrecarregados.
para todas
as tr,3s classes.

D. O " + " 6 um operador sobrecarregado

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

da

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. *; nio. *, utif. * i text. *; date.*;


12. Dado:
'imnnrf i:.':

new DateFormat

Locale.

LONG

DateFormat..getfnstance ( DateFormat.getDatelnstance (

Locale.GERMANy DateFormat..LONG DateFormat.GERMANY

util.reg,ex,' df.format(d));
in *.

d.format(df));

class Directories { static String [] dirs = 1"dirl", "dir2"]; public static void main(String [] args) { for (String d : dirs) {

iAVA

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
as

de c6digo devem ser inseridos? (N4arqG todas

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 ( ) D. String path = File.separator + d,. +" System.out.print(file.isFile()
13. Dado:
n'l ace Dnl i <h I

")

")
t')

")

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

. . fezba
falha.
i Ar I

F. A compilaglo

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

]
e

Qual opg5o, inserida independentemente na linha 4, compila

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 ^rr,brinf /++c z + \

$\.

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
)

293

Quais opg5es slo verdadeiras? (Marque todas as corretas)

A. A compilagdo B. Asaida610

f.alha.

09 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


sobrescreveria

G. Para alterar o processo padrio de des-serializagio, vocA

SpecialSerial.

ect ( ) de Specialserial. o m6todo def aultReadobj ect ( ) de

Respostas
esi 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
E

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

A, B, C, D, F e G estlo incorretas com


2.

no exposto acima. (Objetivo 3.5)

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


B esti correta. Buf f

base no

exposto acima. (Objetivo 3.3)

eredwriters somente podem ser constru(dos encapsulando-se um rVriter. As linhas 16, lTet9esteocorretasporqueBufferedWriter,Filewriter ePrintWriter estendemWriter.
base no

(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

exposto acima. (Objetivo 3.2)

4.

B, C e D estio corretas. Lembre-se de que o m6todo

true

equals ( ) para os wrappers


e

de integers somente

retornario

seosdoistiposprimitivoseosdoisvaloresforemiguais.ComC,6validof.azerunboxingeusar::.EmD,6
expresseo, fazer unboxing dele para comparagio com um

vilido criar um objeto wrapper com uma

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 tentar comparar dois tipos diferentes) (Objetivo 3. 1)

equals ( ) para

5. Eesticorreta.AclasseDateselocalizanopacotejava.uLil,demodoqueelaprecisaserimponada(import),eos objetos DateFonrnt devemsercriadosusandeseumm6todo static como DateFormat . getlnstance ( ) ou


T1=f 6E-^.m.|ueugr' vlrrqu . d6fTf-f LaI99 vsuuaLeIIrD ^TndFrnaa r I . t,/

A, B, C e D estio incorretas com

base

no exposto acima. (Objetivo 3.4)

6. A est6 correta. Uma instAncia


langamento de uma exceglo.

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

B, C, D e E estio incorretas com base no exposto acima. objetos teriam sido serializados. (Objetivo 3.3)
7.

Se

Keyboard implementasse Serializable, enteo dois

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

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.
Observag6es: as instrug6es

est6

incorreta, DateFormat

parse ( ) 6 usado para convener


de

uma String em um Date. (Objetivo 3.4)

9. A, C, F e G estio corretas. O caracter nio-nul1 ou nio-booleano.

conversio 8b (booleano) retorna

true

para qualquer argumento

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

i:rrr i :rzr

rrt- i I

* *

I avt-

class DateTVo { public static voj-d main(Strinq[] args) { Date d = new Date(1119280000000L); Dat.eFormat df = DateFormat.qetDatelnstance(
DateFormat. LONG, Locale.
System. out.println (df . format (d) ) ;
GERMANY) ;

ObservagSes: Lembre-se de que voc6 deve construir objetos tamb6m de que voc6 deve esp ecrticar umLocale paraum objeto m6todo getrnstance ( ) nio usa um Locale. (Objetivo 3.a)
12.

DateFormat usando m6todos esteticos. Lembre-se naterormat no momento do instanciamento. O


a

A e B estio corretas. Pelo fato

de voc6

e$ar chamando o programa

buscadeveriserfeita,niosecomegaocaminhocomumcaracterFile.separator.Om6todoexistsO aexist6nciadearquivosoudiret6rios;om6todoisFileO verificaapenasarquivos. IJmavezqueestamos


procurando por um arquivo, ambos os m6todos funcionam.

partir do diret6rio em cujos subdiret6rios diretos a verifica

C e D estio incorretas com


13.

base

no exposto acima. (Objetivo 3.2)

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
usando
esteo incorretas com base no exposto acima. (Objetivo 3.1)

14.CeDestlocorretas.Oespagoembranco6odelimitadorpadrio,eoloopwhileavangaatrav6sdaString

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 um objeto o 6. F 6 uma instrugio vilida.

static

transient

nio sio serializadas quando

A, B, D e E estio incorretas com

base no exposto acima. G este incorreta porque voc6 nio sobrescreve o m6todo 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 r I I I I t/
P&R
Projetos Usondo Coniuntos Sobrescrever equols( ) e hoshCode( ), Distinguir enlre e equols|

::

UsorVers6es Gen6ricos de Coniuntos Incluindo Set, List e Mop Usor Por6metros de Tipos, Escrever M6todos Gen6ricos Usor iovo.util poro Clossificor e Fozer
Buscos

Usor Comporoble e Comporotor Exercicios 16oidos


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

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.

objeto. Acosnrmese a isso.

Vod tem um

e$ado, um comportamento e um trabalho (ou pelo menos suas chances

Portanto, nesta seElo examinaremos apenas os m6todos hashcode ( ) e equals ) , nlo? Ceno, falaremos sobre ele agora mesmo porque s6 levar6 dois segtrndos.

OCapinrlogabordar6wait(

),noLify( )enotifyAll( ).Om6todofinalize( )foiabordadonoCapinrlo3. ( ) . oh, iso &ixa de fora tostring (

Tobelo

7-1 M6fodos do c/osse Obiect qbordodos no exorne


Descrigio
)

M6todo

boolean equals (object obj void fina]-ize( )

Decide se dois objetos sio significativamente equivalentes. Chamado pelo coletor de lixo quando este percebe que o objeto n1o pode ser referenciado. Retorna o valor

int

hashCode

int

do c6digo de hashing de um objeto, de modo

que

esse

pr.gu.*

objeto possa ser usado em classes Collection que o hashing, incluindo Hashtable, HashMap e HashSet.
desse

final- void notify(

Notifica um thread que estiver agtardando o bloqueio


objeto.
)

final void notifyAll ( final void wait ( String toString (


)

Notifica
desse

todot os

threads que estiverem aguardando o bloqueio

obieto.

notify ounotlfyAll

Faz com que o thread atual aguarde at6 que outro thread chame nesse obieto.

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 referncia 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 (h) ; System. out.println
;

A execugio
%

da classe HardToRead nos forneceri o interessante e significativo resultado,

java

HardToRead

HardToRead@a47e0
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

297

Talvez o fato de ter visto ese resultado o motive a sobrescrever o m6todo exemplo;

toString

em suas classes, por

public class BobTest { pubfic static void main (String[] args) 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.
pnipriw oQetw (e

: . Mas quando tiver que saber se os se duas referdncias slo id6nticas, use referAncias) sio iguais, use o m6todo equals( ). Para cada classe que escrever, voc6 teri que as 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.
Quando voc6 tiver que saber realmente

nio

O que significar6 a neo sobrescr:Sio de equals( )


H6 uma limitagio potencial escondida aqui:
a cbaue em ama tabela de hashing e

se voc6 nio sobrescrever o m6todo equals ( ) , ndo ?odeni usar o objeto como provavelmente neo obteri Sets precisos, de forma tal que nlo haja duplicatas conceituais.

O m6todo equals
sobrescreva

eguals

( ) de Object usa somente o operador : : p^racomparag6es, portanto, a menos que vocA ( ) , dois objetos s6 serlo considerados iguais re as duas ryferncias 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

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


Mnnf f irf rr:l

moofval-ue;
l {

moofValue = val;
)

public int getMoofValue ( ) return moofValue;


)

public boolean equafs(Object o) if ( (o instanceof Moof) && ( ( == this.moofValue)) { return crue; ) efse { return fafse;

(Moof

)o

) . getMoofValue

]
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

299

public boolean equals(Object o) { 2. if ( (o instanceof Moof) && ( ( (Moof)o).getMoofValueo == this.moofValue) ) { return truei 3. 4. ) else { return false; 5. 6. ) 7. j
1.
Em primeiro lugar, voc6 drue observar todas as regras da sobrescrigio; e na linha sobrescrigio v6lida do m6todo equals ( ) que herdamos de Object.
L estamos

realmente declarando uma

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


Em

se a

vari6vel

nXo referenciar algo que SEJA-UM objeto Moof.

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)
simplesmente convertendo
a

.getMoofValue( )comoumtodo,estamos

variAvel de refer6ncia de objeto, o, simultaneamente ) tentativa de chamarmos um 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) &&


== t.his, MoofValue)

((

(Moof)o).getMoofValue(

recurn Erue; ) else { return false;


]

Entio,

isso encerra

eguals

) ...

Calma...
dann vocA

Nlo tio r6pido. Se voc6 examinar


no m6todo equa
1

conhato especlficado
ser segridas se

) . Um nnran Java 6 um conjunto de regras qrc dnrm rer *eurdas, ou melhor, wd qtiserfomecer una intplenmh1do "mmta" coruo as ouhas ?essnar esfurao etpranda, Ou para colocar de outra forrna, se

a classe

Object na documentagio da APIJava, veri o que chamamos de um

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
eqwal-s

l-.embre-sedequeosmdtodosequals(
sobrucrigdo udlida do mdtodo

),hashCode( )rLoString(
)

) tiotodospilblicu.Ocddigoaseguirndoseriauma

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 a I

E reflexiztotPara qualquer valor de referAncia de x, x. equals


E sinitrico: Para qualquer valor de referAncia

y. equals (x) retornar true.

( ) deve retornar true. de x e y, x. equals (y) deve retornar true se, e somerue se,
(y)
retornar

E transitizso:Para qualquer valor de referAncia de x, y e z, se x. equal-s tamb6m retornar true, enteo, x. equals (z) deve retornar true.

true e y. equals

(z

) E consistenteiP^ra I

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.

Paraqualquervalorderefer6nciadex

E voc6 ainda nem chegou 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 ( ) .

queniosejanull,x.equals(nu11) deveretornarfalse. perto de estar seguro. Nlo examinamos o m6todo hashCode ( ) , mas eguals ( )

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
resultani do mumo aidigo;

por diante, e somando os valores num6ricos de todas paraver um exemplo, consulte aFigaraT-1,.

as letras

do nome. (Jm

nome espedfn semprc

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

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
Alex
Bob

Algoritmo A(f) +

do

C6digo de

C6digo de
L(12) + E(s) +X(24) B(2)+o(15)+B(2) D(4) +l(e) + R( 18) + K( | l) F(6) + RilS)+ E(s) + (D)

=42

= le
= 47 = 33

Dirk
Fred

Conjunto
Baldes com os

C6digos de Hashing

l-Dl T_] f xl l=_l t4tl 'Bob" "Fred" ::i';i:

T*\l

Llr]

Figuro

7-l

lJm exernp/o de codigo de hoshing simplificodo

oBSERVAQ6ES

pene O EXAME
raro ter mafu
de uma entrada em

En

casos reais de hashing, n6o d

un deptitito. Norma/nente, a recuperagdo adeqaada barcada en hashing

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

O exemplo

vi

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 ^'.1-li^ fe i-f

{
-.

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


)

Ji

qu9 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 muno @ropiado! Por exerrpk, o aidigo ndo estaria uiolando 0 cnnhatz.

elas iguais oa ndo, ainda seni

un

mdtodo utllido

atd

public int hashCodeo {return 1492;


Dois ofietos com um ua/or

tgua/ a

dexiguala/2
todos ot objetos

eoouhvcom um uakriguala-920.

8 terdo o mesmo aidtgo de hathing. Pordn, 0 metmr aconteceria con dofu nbjetls dferenter, um com o aalor EsemdtolahashCode ( ) rimaitoinefciente; lenbre+e disso,porqaefardcomque

depiitl

usandrt

s/an innidos no mesmo depdsito, mas, meJmr assim, o objeto podeni ser encontrado depois que o conlanto uascu/har no inico 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.

( ) que usario alguma combinagio de ^ (XOR) exclusivo envolvendo vari6veis 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").
Normalmente, voce ver6 m6todos hashCode
as

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 tambores) o contrato de hashCode ( ) :

classe

Object, apresentamos para voct. (rutar de

Sempre que for chamado no mesmo objeto mais de vmavez durante a execueeo de um aplicativo Java, o m6todo ) 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.

hashCode

Se

hashCode

dois objetos forem iguais de acordo com o m6todo equals (obj ect ) , entio, a chamada do m6todo ( ) nos dos dois objetos deve produzir como resultado o mesmo inteiro.

JAVA

303

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

Obrigat6rio

Nio 6 obrigat6rio
==

(mas

x.equals (y) == true x.hashCode( )


rr hach(-nAa /
I

x.hashCode( )
rz .A4ssrrvvsv hr chl^nr{o J / \
\ |

==

x.equals(y) == true
Sem requisitos

de

hashCode

x. hashCode y. hashCode

( (

\
)

r-

x.equals(y) == false

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,
1611r7n rrrr6.

mas ndo

correto

i else { return false;

Aqui

est6 o que poderia ser

feito em um c6digo como o do exemplo anterior:


a suas

I I I I I

Fornecimento de algum estado para o objeto (atribuigXo de valores Insergio do objeto em um HashMap, sendo o objeto a chave.

variiveis de instAncia).

Salvar o objeto em um arquivo usando a serializagio sem alterar nada em seu estado.

Recuperar o objeto no arquivo por meio da desserializagio.

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 ( ) tamb6m falhhii j6 que x ser6 usado como um dos indicadores da um c6digo diferente e o m6todo "q,tais igualdade dos objetos.
]

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

utadot

para

se

implemennr adequadamente

pmjeto, inclaindo

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

A estrutura

conjuntos do pacote java.util est6 repleh de interfaces

Mas o que fazer com um coniunto?


H6 algumas operag6es bisicas que normalmente sio
em conjuntos:

a I I I I
No

Adiaonar

objetos

ao

conjunto.

Remouer objetos

do conjunto.

Saberse am objeto (oagntpo de objetos) est6

no conjunto.

Renperarum

objeto

no conjunto (sem remov6Jo).

Iterarpelo conjunto, examinando cada elemento (o

um ap6s o outro.

Interfaces e classes-chave da estrutura de coniuntos


exame, voc6 ter6 que saber qual conjunto selecionar comesa com um grupo de interfaces, mas tamb6m forn teri que conhecer no exame (e na vida) sio as sete descr

n base em um reouisito declarado. A API de coniuntos virias classes .orr.r.t"r. As principais interfaces q.te voc6
a segurr:

Col-f

ection

Ll-st
Queue
As principais classes concretas de implementagio que outras, mas o exame nio as abor& especificamente): mapas

Sorted Set Sorted Map


ter6 que conhecer no exame sio as treze a seguir

ft6

coniuntos

istas
rr-r-T !!aylfDL i ^l

Filas D-.i ^-.i f frrArrarra uJ Yevuv

Utilitirios
.ClleCtiOnS

HashMap

HashSet

Hashtable
TreeMap

LinkedHashSet

Arrays

TreeSet

Linkedlist

LinkedHashl.{ap
Nem todos
os
conlantos passam no

coniuntos da estrutura implementam realrnente a interface Collection. Em outras palavras, nem todos os tute E-(JM se @licado o C)tktrioo. Especificamente, nenhuma das classes e interfaces relacionadas a maPas

JAVA

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

<<interfuce>> Queue

<<interhce>>
SortedSet

t *T:*]

F-"-.,"'E

['."y1 tr'.til

[-";f f-:"{l F..@-;1


<<interface>> SortedMap

r"**il r'.",ffi;l [-;ili


implementa

i,.*,',,1

Figuro 7-2 A hierorquio de inlerfoces e c/qsses de conjunlos

I r I

conjunto, que representa qualqaerumadas estruturas de dados nas quais os objetos sio armazenados
iterag6es.

e Passam

Por

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

(C'

virios m6todos utilit6rios oBSERVAQ6ES E

maiusculo e com 's' no final), que, na verdade, 6. a clastejava.util.Collections, a qual armazena static para serem usados com os collections.

pene O EXAME

move ( ), contains ( ), size ( ) r iterator(


Os conjuntos v6m em quatros vers6es b6sicas:

tome cuidado. I--embre-se de que Collections d ma classe, con mitodos utilitdrios ruuhof,lcil nnfandir "Collections" cum "Co//ection" utdtims, enquantr Collection d una interface com as declaragdes dos mitodos comans i maioria dos conjuntos inclusiae add( ),

re-

).

Listas
Coniuntos

Listas de itens (classes que implementam List). Itens exclusivos (classes que implementam Sed. Itens com uma identificagio exclusiva (classes que implementam Map). Itens arranjados na ordem em que serio processados.

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


Uma

Nio.ordenada (Unordered)

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

Eq WA | ]

E@

Valores

Gancho

,/

Chave

\snformado{ 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

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.

Quando um conjunto 6 ordenado, significa que vocA podeiterar em seus elementos em uma ordem 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.
especifica (nio aleat6ria). Um conjunto Hashtable
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?

Ordenado

Classificado Um conjunto

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 vem antes de b, ou 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 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.

bar

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
as

307

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.

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.

Arraylist

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

i exclusividade - ele nio permite duplicatas. O m6todo equals ( ) determinari (situagio na qual s6 um poder6 ficar no conjunto). As tr6s implementag6es de Set serio dois objetos sio id6nticos descritas nas se96es seguintes.
Set d6 relevAncia

se

HashSet Hashset

6 um conjunto Set nio-classificado e nlo-ordenado. Ele usa o c6digo de hashing do objeto que esti ) melhor seri o.desempenho sendo inserido; portanto, quanto mais eficiente for sua implementagio de hashCode 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
Ao
ndtodt padrAl Ob

pene O EXAME

usar Hashset ou I;inkedHashset, os objetos que

ec

hashCode
d.e

uocd

adicionar a

eles deaerio sobrescrezer uoci

hashCode

) . Se ndo o fTgrem, o

pennitir,i qae nilhplot objetos que


ndo

poderia considerar como "stgnficatiuamente igaais"

sejan adicionados ao seu conjanto

"tluplicatas

pennitidas".

Treeset
preta
(e

TreeSet 6 um dos dois conjuntos classificados (o outro 6 TreeMap). Ele usa uma estrutura de irvore vermelha e voc6 sabe disso), e garante que os elementos fiquem em seqiiAncia ascendente, de acordo com sua orden natural. 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 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.

.o-

HashMap
conjunto Map

HashMap fornece um conjunto Map nio-classificado e nio-ordenado. Quando voc6 precisar de um 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.

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.

Hashtable

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 remover elementos, pode-se esperar uma iteragio mais r6pida com LinkedHashMap.

TreeMap

Agora voc6 j6 deve ter adivinhado que TreeMap


ordem natural dos

um conjunto Map

clcxstfcado.

ji

sabe que isso

elementos". Como TreeSet, TreeMap permitir| que voc6 introduza suas 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.

significa "classificado pela

A Interface
A fungio

Queue

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

PriorityQueue

oBSERVAq6TS pena o EXAME


Vocd pode necessdrio

elininarfacilmente algarnas retplstas re am coryiunto de pares none/ ualor, jd que

reconhecer que,

por exentplo, um co{anto M@ nio pode


inteface,
esco/ha uma inteface

ser

classe escolhida

quandofor
11

M4 i arua interface,

e ndo ama c/asse conneta de inrplenentagdo.

rvdapda do exame
classe que a

explicita qaando

iro

impnrta,

putantq

se lhe solicitarem que selecione ama

ea ueqde uma

inplemente. O inuerso tambdm

uerdadtiro

se lhe solicitarem

para selecionar uma clase

de implementagio, ndo esco/ba

un

tipo de interface.

A Tabela 7-2
Arrays
e os

Conjuntos v6m logo

resume 11 das 13 classes concretas relativas a conjuntos que voc6 precisari conhecer para o exame. (Os a seguir!)

Iobelo
Classe

7-2

C/osses concretos de imp/ernentocdo de infe#oces de coniunfos

Mapa

Conjunto

Lista

Ordenado

Classificado

Hash-l.{ap

Nio Nio
X
Classificado

Nlo Nio
ordem natura/ ouregras de comparagio personalizadas N"ao

TreeMap

Por

LinkedHashMap X

Porordem
de

insergio ou
acesso N*ao

ultimo

HashSet

N"ao

TreeSet

Classificado

Por

ordem

natara/

ou regras de comparagio personalizadas

LinkedHashSet

Por ordem
de insergio

Nio

JAVA

309

Arraylist
Vector

X X X

Por indice Por indice Por indice


Classificado

Nlo Nlo Nio


Por ordem de
"coisas a fazer"

Linkedlist
Dri nri
+ lef

r;f'lrrarro Ysvsv

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 que manhim a ordem natural das chauet J,l que a chaue 6 uma String, a ordem nataral seni uma rcqiiencia/, precisarenos de un TruMap 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
ea um
conuertendo o
do

pacotelaua.utilpara umuer
eru uma

cddigo qae manipule uma lista

clarifmndo-a, realiqandn nela urua buva bindria, ou

conuertendo-a

arEl. (Jnrfungdes do pacotelauauti/pma

esmuer nid,igo qae manipub

un arrEt clasifcando-0, realiqando nelc uma

burca bindria oa
e arrqys.

arE

Ahm diso, reconhecer

lista. (Jsar at intufacesjaua.util.Comparator elaua.kng.Conparablz para inflaenciar a classifcag1o dt l$as o efeito da "ordrnapdo natural" das classes atr@perprinitiuas e dejaua.kng.Stringsobre a classficagdo.

J6 demos uma olhada te6rica nas elas funcionam na pr6tica.

principais interfaces e classes da Estrutura dos Conjuntos,

vamos ver agora como

Fundamentos de Arraylist
A
6

classe java.util.Arraylist 6 uma das mais freqiientemente usadas de todas as classes da Estrutura dos Conjuntos. EIa como um array anabolizado. Algumas das vantagens que Arraylist tem em relagio aos arrays sio:

I I

capaz de crescer dinamicamente.

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.)
De virias maneiras,
capaz de

Arraylist.<String> 6 semelhante a String ] , no sentido de que declara um container zen^r apenas Strings, mas que 6 mais poderoso do que um String J . Vejamos alguns dos recursos ^rm que um Arraylist possui:

imnarf rrr(yvru n"l-'-l ysv4+v i a

ir.': r:f Jsvs.surr. al ac<

il

*.

rl6ctArr^\rT.i

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

add

"string"

);

add/c\.

test.add(s+s); System. out.println System. out.println System. out . println test . remove ( "hi " ) ; System. out.println

(test. size ( ) ) ; (test. contains (42l, | ; ( test . contains ( "hihi " ) ) ; (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 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.

= new ArrayI,ist (l ; / / decfaraqdo pr6-.Tava 5 myfnts.add(new Integer(42)l; / / era preciso encapsular um


A partir
de Java 5,

List mylnts

int

podemos usar

mylnts.add(42)

; / / o autoboxing cuida disso!


a

Neste riltimo exemplo, ainda estamos adicionando um objeto rnteger o que acontece 6 que o autoboxing reaJizao encapsulamento para n6s.

myrnts

(e

nio um

int

primitivQ;

mas

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
ct- rrf f

//

#1-

rAA I ***,\rn6nr16r,, ----"-.

);
\

stuff
qfrrff

add ( "Boulder" ) ;
arirl /\\Iai
1

/ \

-r,, ^aa \ Aspell 5 LU! r . dUU /\\^^r.^hrr\

,l ;

JAVA

3I I

stuf f . add ( "Te1luride"

;
;

System.out.println("unsorted .. + stuff) Collections. sort (Etuff) t System.out.println("sorted " + stuff) ;


) Isso

l/

#2

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;Fp!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 + l


/ / I ftaff^Te 6 caflar --rl

"

+ leadActor + \\\n"

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
de automaqio de casas, queremos criar uma instAncia de D\rDrnf o Dara cadalinha de dados oue dvdinf o. txt. Para cada instAncia, faremos parsing dr linhr de dados (embra-sle 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:

No nosso aplicativo
tivermos lido
a

panir doarquivo

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

p^rao AirayList, ele chamou

tostring )
(
;

toString ( ) de DVDInfo,.portanto,
para cada uma das instAncias.)

quando chamamos

println

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


erro di
aqui? N6s sabemos que a classe Collections possui um m6todo sorL ( ) , e mesmo assim este entender que Coliections NAO remum m6todo sort ( ) capazde trabalhar com um dvdlist. Isso significa que deve hiver algo errado com o argumento que estamos passando (ava:-nfo).

O que est6 acontecendo


a

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^ de String? instAncias 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
Se vocA

Collections. sort

A Interface Comparable
A interface Comparable
para classificar

e arrays de objetos, respectivamente..Para implementar Comparable, a classe precisa implementar apenas um m6todo, compareTo ( ) . Eis uma chamada de compareTo ( ) :

Lists

6 usada pelos m6todos

Cof

lections. sort O e java.utils.Arrays. sort o


;

int x = thisObject.compareTo
O m6todo compareTo ( ) retorna um

(anotherObject)

int

com

as segu.intes caracteristicas:

I negativo Se thisobject < anotherobject I zero SethisObject == anotherObject I positivo Se thisObject > anotherObject
O m6todo
Como voc tem a opgio de implementaicompareTo ) crit6rios que desejaipara classificar as instAncias das suas classes'
(

sort ( ) usa compareTo ( ) para determinar como o List

ou o array de objetos deve ser classificado. para as suas pr6prias classes, poderi usar quaisquer
e usar a

Voltando ao nosso exemplo anterior para a classe DVDInfo, podemos optar pela solugio mais ficil implementaEio da classe String de compareTo ( ) :

cfass DVDfnfo implements Conparable<D\IDlnfo>


/ / a6di ao exi sfente ^"1-1 i^
yuvrrv f rlu

// +r
//
+2

inf

nnmn:r6rlr^tf)\iT)Tnfn v vvrrwu!

d\

{
()

return title.coqrareTo(d.getTitle

])
DVDInfo implementa Comparable de uma forma tal que objetos DVDInfo objetos DVDInfo. Na linha 2, impllmentamos compareTo ( ) ao.compararmos os podem ser comparados ourros titulos dos dois objetos DVDInfo. IJmaurzque sabemos que os tirulos sio Strings, e que String imo_lementa Compirable, 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:
Na linha 1, n6s declaramos que
a a classe

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

3I3

= return tit1e.

DVDInfo d

(DVDInfo)o;
compareTo (d.

gretTitle

));

]]
vilido, mas vocA.pode ver que nio s6 6 complicado como tamb6m arriscado, porque vocA precisa fazer uma conversio, e precisa verificar se a conversio nio vai falhar antes de tenti-la.
Isso ainda 6

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,
Qfrinn a|-rinn (t-rinn

a nossa classe

DVDInfo deveri

se

parecer com a seguinte:


{

cl-ass DVDInfo implements Comparable<DVDTnfo>


Iit-la. don16. 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

, , , ,
l

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

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

Copitulo 7: Gen6ricos e Con juntos

compare
g6nero.

().

Eis uma pequena classe que pode ser usada para classificar um List de instAncias de DVDInfo, por

import java.utiJ-.*; class Genresort implements Comparator<DVDlnfo> { public int compare(DVDInfo one, DVDfnfo two) t return one. getcenre ( ) .compareTo (two. getcenre ( ) ) ;
)

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:

O m6todo Comparator. compare ( ) retorna um


(

int

imnnrf 'imnnrt-

iarrr i:rr:

rrfil 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 vuvfru nnnrrl vvrs "^.iz{ afaT.i aal\ \ / Yv c|- I I .
.

println (dvdlist ) ; Collections. sort (dvdlist) ; System. out . println (dvdlist ) ;


System. out

/ a saida, conforme lida a parti-r do arquivo / a saida, classificada por titulo

Genresort gs = new GenreSort ( ) Collections. sort (dvd1ist, ers) ;


System. out
.

println ( dvdlist
I\ I

);

/ a saida, cfassificada por g6nero

]
vgv+4vwvfgyvyg4l4

nrrl.rlin

rrnid

nnnrr'lat-6T.icl-

/ 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^\/ r eJ
rrsr

Ri l

, , , ,
l

Lost in Translation comedy Murray, Bill 200L sci-fi ?? Donnie Darko sci-fi Gyll-enhall, Jake Star Wars sci-fi Ford, Harrison

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

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 negativo se obj One

< objTwo

O mesmo que Comparable

zerose objOne == oj)l'rwo positivo se ob j One > objTwo

Vod
cujas

precisa modifi car

a classe

Voc cria uma classe separada


daquela cujas instlncias deseja classificar.

irstincias

deseja classificar.

56 pode ser criada uma seqii6ncia de classificagio.

Podem sercriadas muitas seqiiAncias Elaborada para ser implementada com o obietivo de classificar instAncias de outras classes.

&

classificaglo.

Implementada freqtientemente na API por:


String, $?rapper classes, Date, Calendar...

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 com base na ordem natural. .fazem de primitivos usando um Comparator.

Nio

se engane

com uma questio do exame que ten6 classificar

vm array

Finalmente, lembre-se de que os m6todos


e_st6ticos, e

sort ( ) tanto para a classe Collections quanto para a classe Arrays sio que eles alteram os objetos que esteo chssificando, emvez de retornar um objeio classificado de iorma
pene O EXAME

diferente.

oBSERVAQoTS

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

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 I r

As buscas sio realizadas usando-se o m6todo


As buscas bem-sucedidas retornam o indice

binarySearch

()

int do elemento sendo procurado. 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.

Se

nessa mesma

o conjunto/array em que voc6 deseja-procurar tiver sido classificado na ordem natural, a busca deve ser feita ordem. (Isso 6 feito ao NAO se enviar um Comparator como argumento para o m6todo

3l6

Copiiulo 7: Gen6ricos e coniunlos

binarySearch

( ) .)

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) , for(String s : sa) System.out.print(s + " ");
q1r<fam nrrf nrinjlnl\r\nnno ='\

,,

Ot

+Arrays.binarySearch(sa,"one"));
System.out.println("now reverse sort") ; ReSortComparator rs = new Resortcomparator0; Arrays . sort ( sa, rs ) ; for(String s : sa) System.out.print(s + " ")'
q\/qfam nrrinrinlln{"\nonc = "

//

#2

+3

+Arrays.binarySearch(sa,"one"));
Qrr<l-om rf r ue.rL. ^rrf vqL
,

//
/

#4

^-i-ts]h/\^FA P! IIf L If I \

vrlE

Arrays.binarySearch(sa,"one".rs)) ;

#5

I t

static cl-ass ReSortComparator


implementsComparator<String> { public int compare(String a, String b) {

// //

#6

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

Linha2 Procura
Linha

pela localizagio do elemento

*um", que 6 1.

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


usamos para classificar

binarySearch ( ) o Comparator

que

o arr^y,

e,

por isso, recebemos uma resposta incorreta (indefinida).


a

Linha 5 Nova busca, passando o Comparator Linha 6 Definimos o Comparator;


6

binarySearctr

( ) . Desta

vez obtemos a resposta correta,2.

permitido que

esta seja uma classe

interna.

JAVA

5 3I7

LinhaT Ao trocar o uso dos argumentos


oBSERVAQ6TS
Ao

na chamada a

compareTo

),

obtemos uma classificagio invertida.

pene O EXAME

reto/uer quesldes sobre busca e classifcap1o, os dois errot mais cotzuns tdo:

l.

2. Usar um Comparator

Procurar em tlm an"El ou conjunto que ndo tenha sido c/assficado. 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 m6todos toArray ( ), e a classe Arrays poszui um m6todo chamado aslist ( ) .
e Set

possuem

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

outro

O , o array e o List ficam unidos 6 atualizado automaticamente. Veiamos:

asl,ist

como

se fossem

um s6. Quando voc6 atualiza um deles, o

String[] sa = {"one"
List slist = Arrays.aslist(sa); System.out.println("size " + s],ist.sizeO System.out.println( "idx2 " + sl-ist .geL(2)
qT,iqtqal- /? "qiv.\

/
)
;

/ cria

um

List

|;

sa[1] = "five";
fnrlQfrind c . <al

// modifica List // modifica o array

System.out.print(s + " "); System.out.println("\nsf [1] " + slist.get


Isso

(1) ) ;

produz

sj-ze

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(]; Integerll taz = new Integer[3]; ia2 = iL. toArray (ia2) ;
Usando Lists

/ /

tri

rrm

*--*r =rrarr
:rr:\/

Al _JlecE.

/ /

rri

rrn

Tnf

6ft6r

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

sendo feito o loop. Chamar

hasNext ( ) NAO move

houver pelo menos mais um elemento no conjunto em que esta o foco para o pr6ximo elemento do conjunto.

I object next ( )
imnnrti:rra

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:


rri-il *.

cfass
yuvrfv ^"1-'1

Dogr {
ia efrinn n:ma.

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(); while (i3.hasNextO ) {


Dog d2 =
System.
)

ll cria un Lteragor
/

i3.nex!O; out. println (d2 . name) ;

| ndo 6 preciso converter

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

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


receber6 uma saida como esra:

// lnsira este c6digo

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 porque tentou inserir uma entradaduplicada (uma String com o valor a) no Set.
Se

inserir esta linha de c6digo,

Set s = new TreeSet0;


vocA receber6 algo assim:

// insira este c6digo

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 questio
6 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 questio deverio sobrescrever os m6todos hashCode O e equals O . @em, voc6s6 das chaves pari o ^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 return false; i
1

public int
)

hashcode

(return

name.lengTthO

; l

class Cat {
enum

Pets

{DOG, CAT, HORSE

al

acc

ManrFact

public static void main(String[] args)

Mapcobject, Object> m = new Hashlvlap<object, Object>O;

m.put("k1", m.put ("k2" ,

new

Dog("aiko")); // adiciona algruns pares de chave / va]-or


,

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 ) ) ; / / System. out.println (m. size (l ) ; / / #6
]
o que produz algo como isto:
Dog@1c
DOG

#5

JAVA

32I

CAT key

Dog key
nul-l5

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

A quana

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


public int hashCodeO {return 4;
}

// //

+1,

#2

Hora de mais um teste r6pido: os dois hashcodes acima sio v6lidos? panir de um Map? Qual deles ser6 o mais r6pido?
As respostas para

Ser6 que eles

terio

sucesso em

obter objetos

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

q1/<|-6m
e LvfrL

^rr|vsv

. yr

nrirt4rf

e+

lnlm

nat. ld'l\\.

obteremos algo como:


DogB4
DOG

CAT key

Dog key

nul1
5

nu11
usada para ser encontrado. Pelo fato de a variivel Dog . name ser 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

O Dog que havia sido encontrado anteriormente nlo pode mais

MapTest.main

()

d1.name = "magnolia";

System.out.println(m.get(d1 ));
d1.name =
dl- . name

//
/

#L

"clover"; / /
#2

System.out.println(m.get(new Dog("clover") ) );

= "arttrur" ; 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


o objeto dentro dagaveta

2. Usar o m6todo equals O paraachar

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.
a algumas paginas, a Tabela 7-5

Daqui
exame.

resumir6 os m6todos

& Map com

os quais vocA

deveri estar familiarizado para o

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> { public int compare(Integer one, fnteger two) return two - one;
)

/
{

ordem inversa
rrnl-rnvina

/ /

public static void main(Strj-ng[] args) int[] ia = {1,5,3,1,6,9,8 };


eriorityQueue<fnteger> pq1 = new PriorityQueue<Integer>
fnrf inlna1 v nffar . i:\ /v\
.

dados n5o-ordenados ordem naturalfil:

();

/ usa a
aarranz:

//

for(int x : ia)
System.out.print(pq1 .poll() + " ");
System. out
.

// revisa a fila
(

println

"");

PQsort pqs = new PQsort ( ) ; Prj-orityQueue<Integ'er> pq2 = new PriorityQueue<Integer> ( 10, pqs ) ; for(int x : ia) // carrega a fila
na? nffar 1v\

obL6m um Comparator

// usa o Comparator

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

323

Esse c6digo

produz algo como:

1356789
sj-ze peek
7
9

size

7
9

poll

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 A Tabela 74 apresentaum resumo dos m6todos que voc6 tamb6m precisa conhecer. (Observagio: A sintaxe t
ser6 explicada mais adiante neste

exame.

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
C-onvene um ar:ry em um List (e vincula um ao outro).

static List aslist (f t

static int binarySearch (Object[ ],k"y) static int binarysearch (primiLive [ ] , key) static int binarySearch (T[ ], key, Comparator) static boolean equals (Object[ ], Objectt I ) static boolean equals (primitive[ ], primitive[ public staticvoid sort (Object[ ] ) public static void sort (primitive [ ] public staticvoid
)

Procuram em urn array classificado por um dado valor, retornam um indice ou ponto de insergio. Procura um valor em um array classificado com Comparator. Comparam dois arrap para determinar se os seus conteridos sio iguais. Classificam os elementos de um arrav por ordem natural.
Classifica os elementos de um array usando um

Eor! (T[ ], Comparator)


]
)

Comparator. Criam uma String que possui o conterido de um array

public static String tostring (Object[ ] ) public static String toString (primitive [

324 Copitulo 7: Gen6ricos

e Coniuntos

Principois M6todos em iovo.util.Collections

DescriE6es
Procuram em um List "classificado" por um valor, retornam um indice ou ponto de inserglo.

static int binarySearch (List, key) static int binarysearch (List, key, Comparator) static void reverse (List) static Comparator reverseOrder ( ) static Comparator reverseOrder (Comparator) static void Eort (List) static void sort (List, Comparator)

Inverte a ordem dos elementos em um List.


Retornam um C-omparator que classifica o inverso da atual seqiiAncia de classificaglo do conjunto. Classificam um List ou pela ordem natural ou por um Comparator.

Visio Geral dos Mtitodos para List, Set, Map e Queue


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.

No

Tobelo 7-5 Principois M6todos em Lisl, Set e Mop

Principois M6todos do Inter{oce

List

Set

Mop

DescriE6o
Adicionam um elemento. Para Lists, opcionalmente adicionam o elemento em um ponto indice.
Procuram em um conjunto por um objeto (ou, opcionalmente, por Maps com urna chave), retornam o resultado como um valor booleano. ObtAm um objeto de um conjuntq atrav6s de um indice ou uma chave-

boolean add (element) boolean add (index. element) boofean contains (object) boolean containsKey (object key) bool-ean containeValue (obj ect value)

object get (index) object get (key) int indexOf (object) Iterator iterator
(
)

Obt6m alocalizagio de um objeto em um List.


Obt6m um Iterator panr um List ou Set.
Retorna um Set contendo as chaves de um lvlap.

Set keyset,

Dut (key, value)


remove ( index) remove ( obj ect remove (key)
i-r rrrL ^i-^/\ srze t,
)

Miciona um par de chave


X

valor a um ldap.

Removem um elemento atrav6.s de um indice, do valor do elemento ou de uma chave. Retorna o nrimero de elementos de um coniunto. Retornam um arraycontendo os elementos do conluruo.

x
(1

ObjectI I toArray r[ ] toArray (Tt I )

peekO

Para o exame, os m6todos de PriorityQueue que vocA precisa entender sio of f er O (que 6 semelhante a add O ), (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 ordenado natura/:

JAVA

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

>FF<

>f < >ff<


naitiscalu
sdo colocadas antes das

Se uoc6 se /embrarque os espaEot sdo cobcados antes dos caracteres e qae at lehas

minilsculr, utani bempara

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
Reconhecer as kmitagdes da

API

dos Conluntos, en particular as tnterfans Set,

API

nda-gendica dos Co$untos e como refatorar cddigo

List e Map para usar as uersdes gendicas.

e as clatses de implenentagio.

nitodns

6.4 Desenuoluer aidigo qae use @mpriadanente os parhmehts de tipo en declaragdes de clasnsf intufacu, uaridueis dz insti.ncias, argamentos de e 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 i -f !f Du mvT i cf ILLJIrDL nar.r Irgw Arra\rT..i n!!qt!f <1- l\ /l ,. ru

);

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.

Nio

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 nioseguros (significando nio-gen6ricos).
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

O exame Java 5 aborda conjuntos tanto no estilo pr6-Java 5 (nio-gen6rico) quanto no estilo Java 5,

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.

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

= new

ArraylistO; //
/ /

impossivel- declarar um tipo


iv a1 a anazan^ Qf rihdc

cf ad.l / \E'rad " \, i ---Dog ( ) ) ;


;

mylist.add(new

myl-ist. add (new fnteger (42) \


Um conjunto nio-gen6rico 6

/ e armazena Dogts tamb6m // eAnLegers...


de objeto! Um conjunto nio-gen6rico armazena

alegremente qualquer coisa que

capaz_de armazonar qualquer tipo 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 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!"

int

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

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.

Perfeito.

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,


/
agora podemos usar simplesmente

quando ndo que receberi.amos uma

/ era garantido

String

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!
/ / 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 referncia de tipo especifico.

JAVA

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 return dogs;


)

inserir

dogs

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:

O compilador o impedir6

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


6

(A conversio neste exemplo aplica-se ao que vem do m6todo seL ( ) de Set; n6s nio estamos conveftendo o que 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 idntico 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.
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.

Ah,

328 Copitulo 7; Gen6ricos

e Coniunlos

Gen6ricos e C6digos Antigos


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 ^F mi'r rttyll>L !I>L


.i

^r

LrrarzT,i IIsw - *ar.r dt!4J!f


-

c{- 1\ oL \ /

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


iarr: rrf i l *.

um

conjunto gen6rico

'imnnrf

public class Testlegacy { public static void main(String[] args) { List<Integer> myl,ist = new Arraylist<Integer>
|

)'
aenanifinn
esyve

// |

.^n"irlnl-^
vv.LJ

da

fLfyvinn

mylisr.add(4); myl,ist.add(6); Adder adder = new eddero; int total = adder.addall(myl,ist); // passado para System. out.println (tota1 ) ;
]
Eis a classe antiga, nio-gen6rica, que queremos usar:
'imnnrf i:rr: rrt- i'l *.

um argumento sem

tipo

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

329

while (it.hasNextO ) { int i = ((Integer) it.next total += i;


)

))

intValue(

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.

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 mtodo antigo poderia ter falhado caso a lista que foi passada contivesse qualquer coisa que nio fosse um Integer (o que teria causado uma ClassCastException).
Umavez que o m6todo
Mas, imagine agora que voc6 chame um m6todo antigo que Ser6 que vai funcionar?

nio

apenas leia

um valor, mas

adicione algo ao

Arraylistl

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:


a\ \ . I I I / / |// / nAa Pvv rrma n:cc:da al-rinnffry n: rfs lic+-:

void insert(List list)


1 i cf :rt^ /rat.r \rrsw cfrih^/\/t/ oulfrrv \

<anAa

]
Ser6,

que isso vai funcionar? Sim, infelizmente funciona! Isso compila e executa. Nenhuma exceglo de tempo de 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 sem tipo especifico, e faga deus-sabe-o-qu6 com ele. m6todo de ,tma classe antiga que usa rr-

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,

"rgorn"nto

(simplesmente Quando voc6 chamou o m6todo addall ( ) em um exempl_o anterior, ele nio inseriu nada nalista 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".

das quutdes do exame, sd d preciso

uber w compi/a ou w a conpikgdo falha

auisos do conpzlador nio

fardo

diferenga

Na maioia 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
se

vr

que a que$do inc/aa uma resposta que mencione auisos,


com sacesso!A nnpila.{Ao com

mtia,

mesmo qae wc6


d

niba

que a compi/agdo os
de

pmdu{ri,

ainda asim
se

trata

dz

una compilagdo

auins

NUI'JCA

considerada como

unafalba

nnpihEdo.
d

Mais urua aeqnldigo

uir um cddigo que uoc| sabe qae

iri

compi/ar com auisos, o nidigo para

I\{AO

escolha "a corrpilag1ofalha" como a retposta.

quutdo

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

pnda{ni
"auisos".

am ayiso (oa o que mc pode

palura

faryr con

EIJMII,{AR

os auisos), a peryunta (ou a rcspwtQ

induinl explcitamente a

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 Depois que o trabalho do compilador termina, aJVM vA o que ele sempre viu antes deJava 5 e dos gen6ricos:

33I

Lj-st mylisL = new Arraylist


O compilador at6 mesmo insere conjunto prdava 5.

O;
para voc6

as convers6es

aquelas que voc6 tinha de fazer para retirar coisas de um

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

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 compilador o trata como
lista.
se fosse

do compilador nio 6 muito descritivo, mas a segunda observagio sugere que voc6 recompile com

poderio fazer algo perigoso. Neste exemplo, uma vez que o argumento da lista nio foi declarado com um tipo, o
um c6digo antigo e assume que nio h6 risco
a

-Xlint

unchecked, o compilador lhe mostra exatamente guais m6todos


respeito do que o m6todo colocar6 na

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 nlo vai falhar em tempo de execugio at6 que outras palavras, o ato de adicionar uma String a uma lista ( Integer voc6 tente tratar essa String-que-voc6-pensa-ser-um-Integer como um Integer.

No

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
aParecendo no exame.

essas

332 Copftulo 7: Gen6ricos

e Coniuntos

oBSERVAQ6TS
Ao uur

pene O EXAME
eEedfn)

caidado comproblemas de unboxingl Se uocd declarar am conjanto ndo-gendico, o mitodo 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. conjuntot anlgos (sen tipo

get ( )

SEMPRE retomard una

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

/ 6 preciso converter
(

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

Em outras palavras, podemos atribuir um Arraylist a uma refer6ncia List, porque List 6 um supeftipo de 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; //


List<Numlcer> numbers = new Arraylist<Integer>O;

NAo!
NAOI

//

// lembre-se de que Integfer 6 um subtipo


Mas estes esteo corretos:

de Number

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 onde 6 permitido que voc6 faEa isto,

333

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
I

o que significa que ramb6m 6 permitido que voce faga isto

Object[] myArray = new'JButton[3] ; // slm


mas

nio isro:
NAOI

List<Object> lisL = new Arraylist<JButton>O; //

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 System. out.println ( "Cat checkup" ) ;
] ]

Cat

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

334 Copftulo 7: Gen6ricos

e Coniunlos o

a.checkup?; // n6o importa com qual subtipo de animal // 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 System. out . println ( "Dog checkup" ) ;
) )

Dog

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

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 bem com arrays simples.

firncione

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

Obviamente,

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

j ava

: 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

polimorfismo comarrays,ondeomesmo cenArio


1..

funciona da maneira como voce esperaria. Assim, n6s temos duas quest6es na verdade: Por que isso nXo funciona?

(enimalt J podesereferiraDog[ ],Cat[ ] ouBirdI

tio

familiarizados com o uso de

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

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 [ ]
)
se isso for verdadeiro, e voc6 puder colocar Dogs em um Arraylist ( Animal > , enteo por que voc6 usar o mesmo tipo de cenirio de m6todos? Por que nlo 6 possivel fazer isto?

Entio,

nio pode

public void
)

(Arraylist<Animal> animals) { animal-s.add(new DoSO ) ; / / permitido em alguns casos...


addAnimal

JAVA

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 nlo6possivelpassarumArraylist(Dog) aumargumentodeArraylist<Animal)?Naverdade,oproblemaE

A pergunta permanece - por que isso 6 inv6lido? E por que

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 um conjunto (array ou Arraylist) de um subtipo para um m6todo que use um 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

A razio pela qual 6 perigoso

passar

analisar alguns cen6rios. O primeiro 6 simples:


^,,Lr PuvffL j^ -,^ji vvfu ^^/) lvv\ {

Doq[] dogs = {new DoSO, new DogO};


:rlAlnim:l/d^dc\. \svvv, , ,// , <an nrnhla-^ ----ltta, ^-_-l^ crrvf4 ^ u n^-r uv:| t I 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 do tipo Animal, enteo ele nio tem como perceber o problema. p,rssou vm
^rray
ESSE 6 o cen6rio que estamos

que o compilador permite que isso funcione com arrays, mas

tentando impedir, independentemente de se 6 um array ou um Arraylist. A diferenga nio com coniuntos gen6ricos.

para um m6todo que use um pela qual o compilador nio lhe permitir6 passar um Arraylist ( Dog 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 mas que esti agora sendo referenciado a partir do em um List que fo.a originalrnente declarado como Cat

A razlo

),

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.

NAO hi uma excegio equivalente para gen6ricos, por-causa do apagamento dos tipos! Em outras palavras, em mas NAO sabe o tipo de um conjunto. Todas as informag6es de tempo de execugXo aJVM SABE o tipo dos ^rr^ys, tipoi gen6ricos sio removidas dtrante i compilaSo, de forma que, no momento em que ela chega )JVM, simplesmente nlo
Mas

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


Dog ( ) ) ;

animals. add (new

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
{

NAO ir6 compilar:

),

mas sem modificar o m6todo

addAnimal

(),

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
1 . Li s

AnimalDoctorGeneric
List<Dog>

j ava : 4 9 : addAnimal- ( j ava . ut i

t<Animal>

in AnimalDoctorceneric cannot be applied to (java.util.


)

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

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

assinatura do m6todo se modificaria de

public void
Para

addAnimal (ListcAnimal> animals)

public void addAnimal(List<? extends Animal> animals) Ao usar < ? extends Animal>, estamos dizendo: "Eu posso receber um conjunto
Assim, 6 claro que o m6todo
esse

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

que seja um subtipo de List e

addAnimal ( )

acima nXo vai compilar nem mesmo com a notagio do coringa, porque

m6todo ADICIONA algo.

public void

(List<? extends Animal> animals) { animal-s.add(new DosO) ; // NAol Nao se pode adicionar
addAnimal

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 adicione nada, passarl a funcionar. Mas eqpere

nio

no exame, com

- ainda tem mais. @ a prop6sito, tudo o que abordamos nesta sedo sobre ggn6ricos provavelmente ser6 te*ado 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" nio

Parece estranho porque vocA nunca usaria isso em uma declaraglo de classe, porque Serializable 6 uma interface,

uma classe. Mas a sintaxe 6 essa, entio memorize-a! Mais uma vez
subclasses.

- s6 existe llMA
.

essa palavra-chave 6

palavra-chave coringa que representa tanto implementag6es de interfaces qlranto extends. Por6m, quando a vir, pense em "E-LIM", no sentido de dgo que passa no

teste de

instanceof
a

Entretanto, hi outro cenirio ern que voc6 pode usar um coringa E aindaadicionar ao conjunto, mas de uma forma
segura

palavra-chave

super.
Dog>

Imagine, por exemplo, que voc6 tenha declarado o m6todo desta forma:

public void addAnimal(List<? super


]

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

vilido adicionar um Dog

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

}
6?

EXISTE uma diferenga (e aindanio estamos dizendo que existe), qual

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 iarr: r'ri1 *.

o seguinte ir6 funcionar:

imnnrf

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

34]

nio. causa problemas, mas


coringa (sem

a classe Bar nio compilar6, porque elarealizaum add ( ) em um m6todo que super). E se modificarmos o m6todo dotnsert ( ) para isto:

usar um

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 E narla mus pode substituir < Obiect > .

Integer

para um m6todo capaz de usar APENAS um List

Object >

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.
A prop6sito,
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 quais irio compilar:

as seguintes

instrug6es e descubra

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 As tr6s que nio

t,2

e 5.

irio compilar sio


6

llnstrugiot:List<?> foo = new Arraylist<? extends Animal>O;


Problema: nio
possivel usar a notagAo com coringa na cnagio do objeto. Assim, new

Arraylist<? extends

Animal> O nio compilari.

I l

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

lnstruglo:

List<? super Animal> dT,ist = new ArraylistcDog>


6

O;

Problema:

Nlo

possivel atribuir um Dog a

classe. Somente

Animal

ou

<? super Animal>.

Obiect

O Dog est6'baixo" demais na hierarquia da

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

a resposta que vocA esta


6.

obviamente ji conhece: a API lhe declaragio API para a interface java.util.List:

diri quando um tipo parametrizado for esperado. Por

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 "Elemento",e6usadoquandoomodelo6umconjunto.Aoutraconvengioprincipal 6T(significa"tipo"),usado

public interface List<E> O <E> 6 um marcador parao tipo quevoc6 passar6.


O E, a prop6sito,

para, bem, para as coisas que

NAO forem conjuntos.


()
?

Agora que voc6 ji

viu

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,
este c6digo:

i itso o que wc|podni adicionar a ela. Assim,

imagine

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

List<Animal>

list

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 =
) nrrhlin Ol-!iadt- u aal-Ponl-al vvJ ev yeur\srf uq! /\ / \ I t

maxNumi
;

this. rentalPool = rentalPool

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

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 ] alca I ral-rrrnPant-:1 lnI
.

System. /

out.println

..Cannot add a non-Car,, ) ;


uma exceqao

/ provavelmente langa

)))
Mas quanto mais vocA olha, mais vocA percebe que:
1.

Voc6 ex6fazendo
sobrecarga)

do arg-umento de
2. VocA realmente

pr6pria verificagio de tipo no m6todo returnRental ( ) . Nio 6 possivel modificar o tipo returnRental ( ) para usar um Car, uma vez que se trara de uma sobrescrigio (e nio uma do m6todo & classe Rental. (Sobrecarregar acabaria com a sua flexibilidade polim6rfica com Rental).
a sua

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>

private List<T> rentalPool-

/ // // //
/

"'t" significa o parAmetro do tipo Use o tipo da classe como o tipo de List

private int maxNum; public RentalGeneric ( int maxl\trum, l,ist<T> rentalPool)


this.maxNum =
)

// o construtor usa um / / List do tipo da classe

maxNum;
;

this. rentalPool = rentalPool

public T getRental0 { // bloqueia aL6 que haja algo disponivel return rentalPool. get (0) ;
)

// estamos alugando

urn T

public void returnRental (T returnedThing)


rentalPool . add ( returnedfhing)
;

// e o locador // retorna um T

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

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>


rF anTncf an-o
-

//

aama o tino como um

da elasse

rF f I srl.drrqaeLL-t :nArr:rrAfTsr tJ

/ //
/
{
/ /

tipo de vari6vel de instAncia como um tipo de array


lln f in^ do ue
qrY4rrelrev

TestGenerics (T anlnstance)
)

rama

:rrrrmanl-n

this. anlnstance = anlnstancei


T nat_rFl\ \, YeLr
I / J aama rrh l- ind e4tsv .la
ev

rol-drno

return anfnstance;
J

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 Voc6 pode usar mais de um tipo parametrizado em uma 6nica definigio de classe:
^,'Lll^ 1;uurre ^r^^^ urdb> rr^^ u>eTwO<T, X> {

345

T one; X two;
UseTwo(T
thiq

one, X two)
= ^na. LWU;

nna

rLl ^ r-,^ LITI-.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
Strino theT = ft^roq acf.F/I.
=

new UseTwo<String,
/ / ralnrna

Integer> ( "foo" , 42)


rrma efrih-

int thex = twos.getx(l; // reLorna Integrer, faz unboxing para


1

um

intt

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


T animal;

/ use "T"

em vez

/ / .16 \\?"

public st.atic void main(SLring[] args)

AnimalHolder<Dog> dogHolder = new Animal-Holder<Dog> ( ) ;

AnimalHofder<Integer> x = new AnimalHolder<Tnteger> ( ) .


)
)

// //

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

/ Loma um objeto de umn I / |-ipo desconhecido e usa


nFrA ranfaqanl-ar r n v

um

finn Lrvv

-trl-st<'I'>

-L f

sE.

= new Arrayl,ist<T>

);

/ agora podemos criar / / 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


tempo todo:

de

Dp&

/n6todo

se

componaria como

se tivesse

tido

esta aparAncia o

public void makeArraylist(Dog t) { List<Dog> list = new Arraylist<Dog> list.add(t);


)

);

E, 6 claro,

se voce chamar o m6todo com um lnteger, o T ser6 substiruido por Integer (nio no bltecode, lembre-se descrevendo como ele aparenta se compott"r, e nlo como de fato acontece). estamos

tipo

A
de

coisa mais estranha a respeiro dos m6todos gen6ricos 6 que voc6 precisa declarar a vari6vel do tipo ANTES do

retorno do m6todo: um tiPo no argumento. VocA DEVE ser que ele seja especificado para a classe. Em CreateAnArraylist, a classe nio 6 h6 nenhum marcador de parAmetro de tipo que Possamos usar.

public <T> void makeArraylist (T t) O < T > antes de void simplesmente define o que T 6 antes que voc6 o,use como
declarar o tipo dessa forro", a

nio

gentrica,portanto, nio

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


oBSERVAQ6E,S
E

Number>

void makeArraylist(T t)

pene o EXAME
NAO
eshi onde aocd declaroa a uariduel
de

tentador uquuer qse o argumentt do nhodo

tipo como T, iw6 priciw


Parecer coteta,

t6-/a dutarado 0a c0m0 o k'po

pardnetro da

classe oa no

de pardwetro de tipo T. Para usar ama aaiduel de mitodo, antes do tipr de retuml. A linha abaixo podetl

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
Sim, irofunciona. O
cada um dot asos de

<X> X(X

x) t }
Asin,

qae

o nome do constnttor ndo tem nlagdo nenhama con a dularag1o de

re/ag6o nenhuma com o identifcador do argumento do consh'ntoy que tambim 6, claru,

X,

tipo <X>, qile' pzr sila ue7, ndo tem O conpi/ador convguefaryrpasing disso e hata

defonza independente.

ndo ocom nenbum conf/ito entre 0t fllmes das clares, dos narcadores dotpardmetms

de n'pos e dos identifcadores de uari,lueit

em aeqde uma uariduel de h'po

tJm dos enganos mais cumafis qte ospmgramadores conetem ao criarvm classes ou mitodos geniricos i asar am <T>, 1E), e assin por diante. Este cddigo pode parecer con'eto, mat ndo i:

4?t

na intaxe do coringa

public class NumberHolder<? extends


Enbora o ponto
d.e

Number>

}
ete

innrrogagdo funcione ao se declarar ama referincia

para uma uaitluel,

NAO

mitodos geniicos. Este aidigo ndo

i u,llido:

funciona para dularapdes de c/ases

public class NunberHolder<?> { z atlum; }


Mas
se uocl

// //

NAOI

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
Se esse assunto

347

ficou claro e filctl paravocA, excelente. Se foi... Complicado, saiba que a adigio dos gen6ricos 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. 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 mais do que dois dias para entender os gen6ricos. Isso sio s6 48 horas consecutivas.

".tF*

:*l

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.

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.

4 :.gYit,

ryvislmop

finalidade do operador_

:_(saber se duas vari6veis de referAncia apontam para o mesmo

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, equando 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 E
O

Sobrescreva toString o estado de szu objeto.

) para que System. out

println (

) ou ouuos

m6todos possam obter algo 6til, como

Use
Use

: :

para determinar se duas vari6veis de refer6ncia apontam para o mesmo objeto.

( ) para determinar se dois objetos sio significativamente equivalentes. 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
equals
apropriada.

D D

Quando sobrescrever

equals

),

compare os atributos significativos dos objetos.

Aspectos do contrato de

equals ( ) que foram realgados: 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 ( ) '

As classes HashMap, HashSet, Hashtable, LinkedHashMap e LinkedFlashSet usam hashing. sobrescriglo vilida de hashCode sobrescriglo

E Uma E Uma
D

( ) ter6 que se ater ao contrato. eficiente de hashCode ( ) distribuir6 chaves de forma igualit6ria em v6rios dep6sitos. ( ) retorne o mesmo
hashCode
valor para todas
as instAncias

Para reiterar: se dois objetos forem iguais, seus c6digos de hashing tamb6m devem ser.

B E vilido
seia

que um m6todo hashCode

(embora na pritica

muito ineficiente).
de hashCodeQ que foram realgados: chamadas a x.

E Aspectos do contrato E
Se

D E consistente: virias

(y)

retornarAo o mesmo inteiro'

x. equals (y) for true, x.hashCode ( ) == y.hashCod.e ( ) deve ser true 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.

TrAs significados para "conjunto":

E D E E

conjunto

representa a estrutura de dados na qual objetos sio armazenados;


e

Collection - java.util.Collection - Interface estendida por Set Collections

List;

m6todos utilit6rios esteticos de conjuntos. ^rmazen As quatro uersdesbasicx dos conjuntos sio as L)stas, Conluntos, MEar e Filas:

- uma classe que

E E E tr E
D D

Listas de itens: Ordenada,

repetigio

perruitida,

comum

indice,

Conjuntos de itens: Podem ou nio ser ordenados e/ou classificados


Mapas de itens com chaves: Podem ou

e a @etigdo ndo dpermitid4

nlo

ser ordenados e/ou classificados e a rqeilgdo de chaau ndo i pemitida.

Filas de itens a serem processados: Ordenados por FIFO ou Por prioridade.


classficada, ndo- clarifcada, ordenada e ndo-ordenada.

As quatro subvers6es bisicas dos conjuntos sio:

Ordenado significa

iteragio em um conjunto, obedecendo

uma ordem especifica nio-aleat6ria.


classficada

Classificado significa aiteragio em um conjunto, obedecendo uma ordem


ser alfab6tica, num6rica ou definida pelo programador.

estabelecida.

A classificagio pode

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

permitido;

E E tr

LinkedHashMap: iterag6es mais r6pidas; itera por ordem de insergio ou de rtltimo item acessado, permite uma chave nu1I e muitos valores nul1; TreeMap: Um mapa classificado. PriorityQueue: IJma lista de coisas a f.azer ordenada pela prioridade dos elementos.

JAVA

349

Usando Classes de Conjuntos (Objetivo 6.3)


E Os conjuntos s6 podem
D
Faga iterag6es

armazanar Objects, mas tipos primitivos podem ser usados com autoboxing.

com o loop
se

for

aprimorado, ou com um Iterator via hasNext


nao

o & next ( ).

D hasNext ( ) determina
(

existem mais elementos; o Iterator

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. Para ser vasculhado, um array ou List deve ser classificado primeiro.

0
tr

Classes Utilit6rias: Collections e arrays (Objetivo 6.5)


Ambas
essas classes de

java.util fornecem
(

tr Um
D Arrays

m6todo

sort
(

). classifica

usando um comparator ou usando a ordem natural Busca em

D Um m6todo binarySearch ( ).
.

um aftay oul-ist prdclassificado.

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.
que classifica ao contririo.

E Colf ections. reverseorder ( ) retorna um Comparator 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
(subclasse

< Animal
se

>

pode aceitar refer6ncias do dpo Dog, Cat ou qualquer outro subtipo de Animal

ou,

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 cts-.I -^ ^ uLtrrre - -- -r r-i=a.get(0); String s = (String)list.get'(0) ;
tr

// ndo6 preciso converter // convers6o obrigat6ria

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

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.
nXo existe no tempo de execudo

tr A informagio de tipos gen6ricos


tempo de exean$o.

compila$o. Misturar gen6ricos com c6digo antigo pode criar um c6digo compilado que poder6 langar uma exce$o no

ela s5 existe para a

seguranp em tempo de

350 Copitulo 7: Gen6ricos

e Coniunlos
aplicam-se somente ao tipo-base, e

D As atribuig6es polim6rficas

nio

ao parAmetro de tipo gen6rico. Voc6 pode usar

List<Animal> alist = new ArraylisL<Animal>O; Mas nio List<Animal> al,ist, = new ArraylistcDoS>O;

/ sim
n6'o

//

fl

A regra.de atribuigio polim6rfica


permitidos:

se

aplica sempre que uma atribuigio puder ser feita. Os seguintes nia sio

void foo(List<Animal> al,ist) { } //


List<Animal>

ndo pode usar um List<Dog>

baro t ]

//

ndo pode

retornar

um List<Dog>

Q A sintaxe dos coringas permite


argumento do m6todo:

que um m6todo gen6rico aceite subtipos (ou supenipos) do tipo declarado do

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

List<? extends

Dog>,oconjuntopodeseracessado,masniomodificado.

se usar um coringa, List<?>, qualquer tipo gen6rico pode ser atribuido e nXo para modificag6es.

refer6ncia, mas aPenas Para acesso,

QList<Object>refere-seapenasaumList<Object>,enquantoqueList<?>ouList<? 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

extends

tr O identificador de tipo dos gen6ricos pode ser usado em declarag6es de classes, m6todos 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.

variiveis:

VocA pode usar mais de um tipo parametrizado em uma declaragio:

public class
tr

UseTwo<T, X>

i i
nio definido
na classe:

VocA pode declarar um m6todo gen6rico usando um tipo

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 argumento do m6todo voc6 deve declarar o < T ) , o que acontece antes do tipo de retorno.
ndo estivsando

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
)

35I

Quais opg6es, inseridas em /

/ insira o c6digo aqui, irio compilar? (Marque todas as corretas)

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

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

();

for (List<Integer> row : table)


q\t<l-am ) ^rrinrinlln Irnt^rl
rr\.vYf /,

Quais instrug6es poderiam ser inseridas em / compile e rode? (Marque todas as corretas)

TNSIRA

DECLARACAO AQUI para permitir que esse c6digo

List<List<Integfer>> table = new List<List<Integer>> ( ) ; B. t,ist<f,ist<Integer>> table = new Arraylist<List<Integer>>


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

sobrescritos? (Marque todas as corret:N) A.Seom6todoequals( ) retornartrue,ooperador::decomparagiodehashCode( ) poderetornar

Quais das declarag6es abaixo s6o verdadeiras com relagao comparagdo de duas instincias da.mesma claslq, dado que os m6todos equals ) e halhcode ) foram apropriadamente

l.

true. B.Seom6todoequals( ) retornarfalse,ooperador- = decomparaglodehashCode( ) poderetornar


C.
Se

E.rue.
o operador
o operador

::
=

de comparagXo de
de comparaSo de

hashCode

true.
D.
E.
Se

( ) retornar true, o m6todo equals ( ) deve retornar

Se

o operador

true.

( ) retornar true, o m6todo equals ( ) pode retornar true. !: de comparagio de hashCode ( ) retornar true, o m6todo equals ( ) pode retornar
frashCode

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> q. add ( "Veronica" ) ; 1,2 . q.add("Wa1lace"); 13. q.add("Duncan"); 14. 15. showAll (q) ; 16. ]
L1
.

18. 19. 20 . 2L. 22.

public static void showAll


q.add(new Integer(42]']r;

(Queue

q)

while ( lq. isElmpty O ) System.out.print(q.removeO + " ");


]

Qual 6 o resultado? A. Veronica Wallace Duncan

B.Veronica Wallace Duncan


C. Duncan Wafface

42

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

353

set.add("1"); Iterator it = set. iterator while (it.hasNextO )


Svstem ) 6lllnrinjlif
.rfvr:u

navl-

l\
\

+ \\ $.|.
I I

Quais das seguintes afirmativas sio verdadeiras?

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.
A. O m6todo

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, ToDos t1 = new ToDos("Monday,,);

String>O;

t2 = new ToDos ( "Monday,, ) ; ToDos t3 = new ToDos ( "Tuesday" ) ; m.put (t1, "dolaundry" ) ; m.put (t2, "payBi11s" ) ;
ToDos
m nrrl- /f? qr/ql-am ) nrrjrr^la^nAff nrinl-lnlm i^,,\. 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 { private Map accountTotals = new HashMap0; 13. private int retirementFund; 14.
15.

354 Copftulo 7: Gen|ricos

e Coniuntos

16. L7. 18. L9. 20, 2L. 23' 24. 25. 26. j

public int getBalance(Strj-ng accountName) { Integer total = (Integer) accountTotals.qet(accountName); if (totaI == nul1) total = Integer.valueof (0) ; ret.urn total-. intValue ( ) ;
)

public void setBalance(string accounLName' int amount) t


accountTotals.put(accountName, Tnteger.valueOf(amount)
) );

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

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


D. Substituir
CI

linhas l7-20por

int tot.al = accountTotals.get if (total == null) total = 0; return total;


E. Substituir as linhas 17-20 por

(accountName)

Integer t.ot.a1 = accountTotals.gret if (total == nu1I) t.otal = 0; return total;


F. Substituir
as

(accountName) i

linhas 17-20 por

return accountTotals. get


G. Substituir alinha 24 por

(accountName)

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

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


corretas)

esse

c6digo compilasse? (Marque todas

as

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

System.out.println("Adding: " + o),' return super.add(o);


)

]
nla<q nri Parcnn 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? corretas)

M*q*

todas as

A.Adding
C.

Hans

B.addingr Lotte

Adding ,fane
3

total: E. total:
D.
n 4r r

F. O c6digo nio compila.


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

]
. Arrays e./ou j ava. util- . Collections voce poderia usar para converter as Quais m6todos de j ava. em um List e depois procurar no List pelo indice do elemento cujo vaTor 6 "f oo"? (Marque de um a tr& m6todos)

util

A.
B.

sort

()

asl,ist ( ) C. tor-ist ( )
()

D. search
E.

sortr,ist o

JAVA
F. G.

357

contains

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
t

DECLARACAO AQUT

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 compile e rode? (Ir4arque todas as corretas)

/,/

INSIRA A

DECLARACAO aQUr de forma que o programa

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 )

public st.atic Collection<E extends CharSequence> getlongwords ( Col- lection<E> coll_ ) D. public static List<Charsequence>
C.

getlongwords ( Col I ect ion<CharSequence>

co 1 1 )

E.public static List<? extends CharSequence> getlongwords (Collection<? extends CharSequence> F. st.atic public <E extends CharSequence> Collection<E>
getlongwords (Collection<E> co11 )
G,

co11)

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. 15. 16. 17.

map.add("two");

map.add("three"); map.add("four"); 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

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
B. 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
deseja usar esse

E> process(List<E> nums)

Um programador

m6todo da seguinte forma:


AQUT

// INSIRA AS DECLARAqOES output - process(input) ;

Quais pares de declarag6es poderiam ser colocados em / compilagio do c6digo? (Marque todas as corretas)

/ INSTRA As

DECLARACOUS aQur para permitir

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
Queue. corretas. O

m6todopoll

Oassocia-se comQueues. AclasseLinkedlistimplementaainterface

A esti incorreta porque a interface List


(Objaivo6.3)

nXo implementa Queue, e o instanciamento polim6rfico restringiria x a chamar apenas os m6todos declarados na interface List. B, C e E estio incorretas com base no exposto acima.

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

esquerda. (Objetivo 6.4)

JAVA

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

um aviso do compilador na linha 19 devido a uma atribuiglo nlo verificada, mas, fora isso, tudo 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.
e executa sem

Hi

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


m6todo sobrescrito

base no exposto acima.

(Objetivo 6.5)

7. CeDestiocorretas.SehashCodeO nioforsobrescrito,entaocadaentradair|paraoseupr6priodep6sito,eo
equals ( ) nlo
hashCode
()

for sobrescrito, entio o m6todo equals


base

ter6 efeito no que diz respeito a determinar a equivalAncia. Se ( ) sobrescrito veri t1 e t2 como duplicatas.

A, B, E e F estio incorretas com

no exposto acima. (Objetivo 6.2)

8.

B. E e G estio corretas.
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)

A esti

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


10.

6.5)

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 a classe falha porque o seu m6todo munch ( Sheep ) nio atende mais ao Sheep estener Plant, e
^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

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: uma interface e F, PriorityQueue nlo fornece acesso por indice. (Objetivo 6.2)
12.

C, List 6

( ) de Group - ele deveria ser add ( Person ) , uma vez que a Hashset<Person>. Assim, isso nlo compila. Teste ripido: o que aconteceria se voc6 consertasse essec6digo,modificandoadd(object) paraadd(Person)?Tenteexeantaroc6digoparaverseoresultadobate

F e*6correta. O problema aqui reside no m6todo add


classe estende

com o que voce esPerava.

360 Cooitulo 7: Gen6ricos

e Coniunios
base

A, B, C, D, E e G estio incorretas com


13.

no exposto acima. (Ob.ietivo 6.4)

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


esses

contains ( ) retorna um booleano, e nio um indice. C, D e E estio incorretas porque m6todos nio estao definidos na interface List. (Objetivo 6.5)
perto, mas esti errada porque o valor de retorno
6

14.

F esti correta. A
chega

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.

est6 correta. TreeSet assegura entradas sem repedgeo; al6m disso, se acessado,
afabdtica.

retomari elementos na ordem

natural, o que para Strings ignrfca

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 D 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 I I I a/
P&R
Closses inlernos Closses inlernos locois de m6todos Closses internos on6nimos Closses estdlicos oninhodos Exercicios rdpidos
Teste

individuol

362 Copitulo B: Closses internos


A
internas (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.
classes

desvantagens (pr6s e contras) das classes internas e o colocar|frenteaexemplos com 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.
Este capitulo examinar6 asvantagens
e

Entio, por que todo o espalhafato relacionado is classes internas? Antes de entramos no assunto, temos que lhe avisar voc6 ji nio souber) que as classes internas tOm gerado debates apaixonados do tipo amor e 6dio desde que foram
introduzidas na nerslo
1.1 da

(se

linguagem. Pelo menos dessa vez, tentaremos ser reseryados em nossas opini6es e apenas 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
apresenraremos os fatos

& maoeita q.te voc6 precisari

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.


Classes

I I I I

internas

Classes internas locais de m6todos


Classes internas

an6nimas

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

363

(indicando que q-uer que a mensagem que digitou sej a enviada para o servidor do bate-papo) , o c6digo do cliente de batepapo 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 ocpotter; conseg,rii isso fazenio 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.

.o-

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

prljetlzz dessa

forma.

Codificando uma classe interna "comum"


IJsamos o termo comilmpararepresentar classes internas que niosejam:

I I I

Estiticas
Locais de m6todo

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


alacc Mrrflrrt-ar

a I

segurr:

class Mylnner {
)

Muito f6cil. E se voc6 compilar

isso,

Sjavac Myouter.java
terminar6 com /oziarquivos de classe: MfOuter.dass MlOuter$Mykrner.class

classe

acessar o

interna continua sendo uma classe separada, portanto, um arquivo de classe 6 gerado. Entretanto, voc6 nio poder6 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


MrrArrtar I

as classes:

nlacc

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


perfeitamente vilido. Observe que a classe interna est6 realmente acessando um membro privado da esti 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.

O c6digo anterior

classe externa. Isso

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

Instanciando uma

nlaec

Mrzf)rrt.ar

private int x = 7; public voj_d makefnnerO


in caaOrrt-or1\
1

Mylnner j-n = new Mylnner ( ) ;


-

/ cria

uma

instdncia interna

a l a <<

Mr;Tnnar

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.) Uau! Esse 6 um grande quisermos criar uma instAncia da classe interna, 6 preciso ter 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!

Criando um obieto de classe interna fora do c6digo da instincia da classe externa


subtitulo, mas realmente explica o que tentaremos fazer.
Se

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

classe (supondo-se que a

mesmo, independente de o m6todo main ( ) estar dentro da classe MyOuter ou de algoma ouha outra classe tenha acesso a MyOuter, e ji que essa tem acesso padrXo, isso significa que o c6digo

JAVA
deve estar em uma classe do mesmo pacote de

365

MyOuter).

Caso goste de c6digos curtos, poder6 faz6-lo desta forma:

public static void main(String[1 args) MyOuter mo = new Myouter1; // vai comegar uma instAnciat I,Eouter.Mylilrer inner = ttro.new lrDrfnner ( ) t
1

anner-seeolrfer()

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

Voc6 pode considerar essa situagio como

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 exlafora daclasse externa:

Aqui

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
e

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
para instanciar, vocA precisa usar uma referAncia

classe externa,

new MyOuter(
se i6

.new

Mylnner( ); ou outerobjRef.new Uylnner( );

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
r I

A palavra-chave
c6digo

this static.

pode ser usada dentro do c6digo da instAncia. Melhor dizendo, nio pode ser usada dentro do

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.
6 a maneira de um objeto passar uma refer6ncia dele pr6prio para algum outro c6digo, como argumento de um m6todo:

A refer6ncia thi s

public void myMethodO mc.doStuff(this); //


]
Dentro

{
;

Mycl-ass mc = new MyClass O

passa uma

refer6ncia ao objeto executando myMethod

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 "ryferncia Lhis extema"?Embora normalmente o c6digo da classe interna nio precise de uma refer6ncia 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

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

Closses inlernos

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

asaidaseri:

Outer x is 7 Inner class ref Outer class ref


Poftanto,
as

is Myouter$MyInner@113708 is MyOuter@33f1d7
pr6pria ou para a instancia externa do c6digo
dessa classe, use
sAo as

regras para uma classe interna que aponte para si

seguintes:

I I

P ara re{erenciar a instAn cia da

pr6pria
"

classe interna , de dcnhv


ex'terna"

thi

Para apontar para a refer6ncia

thi s

NomeDaClasseExterna.

this

(instAncia da classe externa) de dentro do c6digo da classe interna, use

(exemplo,

MyOuter . this).
A
classe

Modificadores de membros aplicados a classes

internas

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

final abstract public private


protected

static - a excepio d qae sLatic strictfp

ttma uma classe aninhada

de niuel supeior, em ueqde uma classe intema.

Obietivo poro o certificoe6o


Classes internas locais de m6todo
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

O escopo

delinir uma classe interna dentro

de

um m6todo:

cl-ass Myouter2

private String x = "outer2";

JAVA

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

).Por6m, duttrodedoSLuff

( ),

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

/ /

) I

mi. seeout.er O ; / / fecha o m6todo doStuff

) da classe externa

// 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 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
escopo de uma
e, em seguida,

por tanto tempo quanto o objeto da

arriazrnada em uma vari6vel de instAncia. J6 que.as vari6veis locais nio t6m_ garantia de continuarem ativas 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
al:qc M\/Tnhar

String z = "local variable";


I

public void seeouter ( )


qlrqt- em orr1-

nr:int1n("Ogter

Svsfem-out-ni:int1n("Local

X iS " + x) ; variable z is " + z); // Ndo vai compilar!

368 Copitulo B:

Closses inlernos

\ j \

/ fecha o m6todo da classe interna / / fecha a definigdo da classe interna / / fecha o m6todo doStuff ( ) da classe externa
/

//fechaaclasseexterna
realmente

A compilagio do c6digo anterior

preocupari o compilador:

Myouter2.java:8: local variable z is accessed from within j-nner class;


needs to be declared final
q\/ql-am nttlnrinflnlNT,^.al rrariah1 a z iq \'+ zl.

Marcar a vari6vel Ioca|

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 vocpader,i aplicar a essa classe sio abstract e f inal - mas 6 claro que nunca os dois ao mesmo tempo como para qualquer outra classe ou m6todo.

oBSERVAQ6ES

pene O EXAME static c static

L.embre-se de que uma c/ase /oea/ du/arada em um mdtodo

terd acesn rlmente a membros da 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 ndo baueni a referdncia Lhis, portantl, a classe intema de um mdtodo s t a t i utd suleita as mesmas restipdes desse mdtodo. Em outras pa/arras, ndo tem ace$o a "uaidueis de

in$dncia".

hl-t

r. \,roleTtvo poro

r.f. o centttcocoo

Classes internas an6nimas


de uma classe dentro de outra classe encapsuladora (uma classe interna comum) e dentro 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. de

At6 agora examinamos a definigio

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


q\/cl-am nrr1vJvuutt.vsu.yrfllufrr\ nrirts

t
ln / rtnana^r^r, yvvuvrll \ /,

cl-ass Food

Popcorrr D = nevt eopcorn() {

public void popfl { System. out.println

"anonlmous popcorn,' ) ;

JAVA

369

I;
)

Examinemos o que ocorreu no c6digo anterior:

r I I

Definimos duas

classes,

Popcorn e Food.

Popcorn tem um m6todo, pop

Food tem uma variivel de instAncia, declarada com o tipo Popcorn. Isso 6 tudo quanto m6todos.

i Food.

Essa classe

nattem

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 n v _ = nar^r rruYv Ddn^nrn/l rvyvvrrl\/ { L

3. 4. 6. j;
Linha2
formato:

public void popo


System.

{
(

out.printl-n

"anonlzmous popcorn" ) ;

A linha 2

comega como uma declaragio de vari6vel de instAncia do tipo Popcorn. Mas, em vez de ter este

Popcorn

p = new Popcorn (\ ; / / repare no ponto-e-virgula ao final linha2, onde normalmente


estaria um ponto-e-virgula

h6 uma chave no final da

Popcornp = new Popcorn(\


Voc6 pode ler a linha 2 como:

{ // _uma chave emvez

do ponto-e-virgula

"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

Em seguida, a linha 3 6, na verdade,

faz? Sobrescreveu o m6todo

pop

( ) da superclasse

interna an6nima:

sobresmuer am ou mais mtitodos

primeira instrugio dentro da definigio da nova classe. E o que ela Popcorn. Aqui este o ponto crucial da criagio de uma classe da saperclasse (ou implementar m6todos de uma interface, mas
a

guardaremos isso para mais tarde).

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
Linha
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
? zt Dnnnnrn rvvuvlr]
P

ponto-e-uirgula
\ {

de

fechamento. Portanto,

uocd

pode uer am cridigo

conl

este n0 exame:

iar^r rrefv

rvyevlrr\/

Dnnnnrnf

^,,1-1
Puvrfe

4.

vvr ^ -.^; d pop ( ) i SysLem.out.println("anonymous popcorn")

.i

6. ) // Fllta o ponto-e-virgiula aecesgdrio 7. Foo f = new FooO;

p,ara

finalizar a instrugto en 2!!

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

O polimorfismo entra em cena quando

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 rr vvv v! fr

publ-ic void pop0


System.

{ )
;

out.println ( "popcorn"

cLass Food
^,,1-1 Puvffu
.i

{ {

PoPcorn P = new PopcornO

^ ,,^r,{ sizzle ( ) System. out.println


vvrs

t
(

"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 rra v crmlln uJ f L'!vr l

symbol : method slzzle ll

location: class p,sizzle);

Popcorn

que 6 a maneira de o compilador dizer: "NXo consigo encontrar o m6todo seguido de: "Consiga uma pista".

sizzle ( ) na classe Popcorn",

JAVA

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
instanciar uma inteface,

emqueCookable 6umainterfanemvezdeumtipodeclassenioabstract.Porque,pensebem,

uoc6niopode

emboraparega que 6 isso que o c6drgo est|fazendo. Mas 6 claro que ele nio est6 instanciando um 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.

linha a tegair ndo

u,llida,

r = newRunnabl-el); // impossivel instanciar a interface enqaantl a qae re encontra abaixo d udlida, porque estui instanciando ua implementador da inteface Runnable
Runnable
iruplenentaqdo

(una

classe de

aninina): em

Runnable

r = new Runnable O { / / chave public void runo { }

vez de ponto-e-virqula

);

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 um pouco confixo com relaglo is classes an6nimas, deve reler as seg6es anteriores. Se elas nio estiverem muito claras,
Se vocA

372 Copitulo B:

Closses internos

gostariamos de nos responsabilizar completamente pela confusio. Por6m, ficaremos felizes em compartilhar.
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).

Certo,

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
an6nima, dentro seu c6digo:

do argumenlo.

)daclasseBar.SendoumprogramadorJavaastuto,voc6simplesmentedefiniriumaclasseinterna Exatamente, logo onde voc6 menos esperaria encontrar uma classe. E aqui est6 o formato de

1. class MyWonderfulClass { 2. void goO {


3.
A

Barb=newBarO; b.doStuff(new FooO


n,,1-r1 ia

{ o {
/ \f^^f\r/

5.
6

r,^.i^

+^^f

q\tqfpm

arrt. nrinfln

j // final-izaom6todofoof 7. j) ; / / finaliza as instruq6es def, arg' e end da classe interna 8, j // finalizago(l 9. L0. j // final-iza a classe
11.

12. 13. 14. 15. L6.


Toda

interface Foo void foof ( ) ;


]

class Bar { void doStuff(Foo f) {

1,7. \
a agio comega na linha 4. Estamos chamando doStuf ) 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 ) . EntXo,6 o que faremos. Escreveremos

f(

f(

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-evirgula. Esiude essa sinta*ei YocE ueri classes internai an6nimas no exame e teri que ser muito cuidadoso com a

JAVA

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 {


)

nesse caso,

classe propriamente dita nio 6 realmente "est6tica"l nio existem classes est6ticas. O modificador informa que a classe aninhada 6. um membro utitico da classe extema.Isso significa que ela pode ser acessada,
sem ter

static,

como qualquer outro membro estAtico,

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,
nl:qq

tem este formato:


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 n.go( ); 82b2= new82( ); // acessa a classe interna b2.goB2( );
)

cl_asses

O que produz

hi

r]i2

374 Copitulo B:

Closses inlernos

oBSERVAq6ES pene O EXAME


Assim como aru mdtodo estdtico n6o terz
aninhada ndo tem acetso
acesso

is

aai,iueis de instdncjas

e m,itodos

ir

uaritlueis de instincias e aos mdtodos

ndo-sLaLic

ndo-sEatic da c/asse, uma clasrc estdtica 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.
as classes internas locais de m6todo - classes definidas dentro de um m6todo. Vimos que o c6digo 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.

A seguir examinamos
de uma classe

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
bloco de c6digo.

de outra classe, mas fora de qualquer m6todo ou

outro

E A classe interna 6 um membro individual da classe encapsuladora


enquanto

(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 abstract e f inal ao mesmo tempo - lembre-se de que abstract significari que ela deve ter subclasses,

final

quer dizer que ela nXo pode ter subclasses).

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 E

Para instanciar uma classe interna, voc6 precisa ter uma refer6ncia

instAncia da classe externa.

A partir do c6digo da classe encapsuladora, vocA pode instanciar


como vemos abaixo,

a classe interna usando somente o nome dela,

Myfnner mi = new MyTnner ( ) ;

JAVA

375

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 referncia i classe extern4 como no c6digo abaixo:

Myouter mo = new MyOutero; Myouter.Myfnner inner = mo.new MylnnerO; A partir de um c6digo dentro da classe interna, a palavra-chave
instAncia da classe interna- Para apontar para a refer|ncia
classe externa a qual essa
classe externa
MrzOrri- ar

instincii interna como na linha abaixo:


c.

this pode armazenar uma refer6ncia i this .*t.rrr" (em outras palavras, a instAncia da esti associada) anteceda a palavra-charr. i5i" com o nome da

thi

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 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.
Os rinicos modificadores que voc6 pode aplicar a uma classe interna local de m6todo sio f inal (nunca os dois ao mesmo rempo, no entanto).

abstracL

Classes internas an6nimas E As classes internas an6nimas nio t6m nome,


implementador da interface nomeada.

e seu

tipo deve ser uma subclasse do tipo nomeado ou um

D Uma

pontoe-virgula em Java.

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

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

de m6todo.

Classes aninhadas esteticas


D As classes
aninhadas estiticas sio classes internas marcadas com o modificador
6

static.

E
tr

Tecnicamente, uma classe aninhada est6tica nio aninhada de nivel superior.

uma classe interna, mas, em vez disso,6 considerada uma classe

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.

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


a

estitica nlo pode acessar membros nioest6ticos da classe extern4 ji que nio tem uma refer6ncia implicita 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 apresse. Relaxe.
se

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
todas as corretas)

classe aninhada estetica? (Marque

A
B.

Voc6 precisa ter uma referdncia ) instAncia da classe encapsuladora para instanci6-la. Ela nio tem acesso a membros
Suas

nlo-sLatic

da classe encapsuladora.

C
D. E.

variiveis

m6todos devem ser


se

static.
e a classe

Se a classe

externa

chamar

Mlouter,
)
;

aninhada

se

chamar

Myrnner,

ela pode ser instanciada usando

new

Myouter.Myfnner(

Ela deve estender a classe encapsuladora.

3. Dado: public interface Runnable { void run( );

}
as

O que cria a instAncia de uma classe interna an6nima? Qr4arque todas

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 B. Boo f C Boo f D. gar f E, Boo f

= new eoo(24) { };

= new Bar( ) { }; = new Boo( ) {Stri-ng s; }; = new Boo(String s) { }; = new Boo.Bar(String s) { };

JAVA

377

5. Dado o c6digo a seguir, 1. class Foo { 2. class Bar{

4. class Test { 5. publj_c static void main (String [] args) 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 C
D.

Ela deve ser marcada com f

i-nal.

B. Elapode ser marcada


Elapode ser marcada
Ela pode ser marcada

abstract. compublic. com stat.ic.


com

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. Ela pode estender somente uma classe ou implementar apenas uma interface. Pode implementar virias interfaces, independente de tamb6m estender uma classe. Pode implementar virias interfaces,
se

C
D.

E.

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 { publ j-c bool-ean equa]s (Obj ect obj ) t 4. return true; 5. 6. ) 7. ] System.out.println(o.equals("Fred") ) ; 8.
q]

10.)
qual ser6, o resultado?

A. Uma excegio ocorreri no tempo B. true

de execugio.

L. ralse
D. A compilagio falhari por
causa de um erro na linha 3.
causa de

E. A compilaglo f.alhari por F. A compilagXo falhari por


G. A compilagio falharipor
|

um erro na linha 4.

causa de um erro na linha 8.


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 { public String name; 4. public Horse(String s) { 5. 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 B. zipppo

de tempo de execugio ocorrer6 na linha 10.

C. A compilagio f.alhar| por D. A compilaglo falhari por

causa de um erro na linha 3. causa de um erro na linha 9.

E. A compilagdo

falhar6 por causa de um erro na linha 10.

F. A compilaglo falharipor
I

causa de um erro na linha 11.

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

de execugio ocorrer6 na linha 10.

C. A compilagdo falharipor

causa de um erro na linha 3. causa de um erro na linha 9.


causa de

D. A compilagio falhari por E. A compilagd,o f.alhar|por

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

uma classe aninhada est6tica, portanto, deve ser instanciada com o uso do nome do escopo
6

completo que

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 or m.mbros nio-static da classe (da mesma forma que um m6todo encapsuladori e, porranto, nio podi

stalic

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

3.

A resposta A
4. B e

est6 incorreta porque

nlo sobrescreve o m6todo run


a sintaxe

),

portanto, viola

as regras da

implementagio de interfaces. B, C e D usam

incorreta.

est6 correta porque as classes internas an6nimas nio slo diferentes de nenhuma outra quando se trata de polimoifismo. Isso significa que vocA sempre poder6 declarar uma vari6vel de referniia 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.

C. A resposta B

classe

passa um tipo int para o constnrtor de Boo, e nio hi um construtor Boo. D est6 errada porque viola as regras do polimorfismo; voc6 nio pode referenciar 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.

A resposta A esti incorreta porque


coincidente

na

classe

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
for usada (ponanto,6 improv6vel necessidade da criagio de uma subclasse da classe interna se a classe seja ritil). E est6 correta porque uma classe interna local de m6todo que 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

abstract

abstract

A resposta A

seja
esse

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.
a sintaxe de uma classe interna an6nima s6 permite um tipo nomeado depois de.new, tipo tem que ser apenas uma interface (caso no qual a classe an6nima implementari essa interface) ou vma inica classe (situag5o em que a classe an6nima estender6 essa classe).
e

est6

incorreta porque uma classe interna local de m6todo nio precisa ser declarada como f

inal

(embora

7. C esth correta porque


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


instrugio que nio termina at6
As respostas m6todo
10.
a

com um ponto-e-virgula. Lembre-se de que a linha 3 6 uma linha 7 e, como instrugio, precisaria de um ponto-e-virgulicomo fechamento!

$ B, C, D, E e F estio incorretas com base nal6gica do programa descrita acima. Se o ponto-evirgula fosse adicionado i linha 7, entio a resposta B estaria correta - o programa exibiria true, o retbrno do
equals (
)

sobrescrito pela subclasle an6nima de

obj ect.

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 referncia 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 (nioabstract) 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 I I I r'
P&R
Inicior Threods Reconhecer Estodos e TronsiE6es de Threods Usor o Bloqueio de Objetos poro Evitor o Acesso Simult6neo
Escrever C6digo que Use woii0,

notifyfl ou noiifyAll0
Exercicios 16pidos
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 I

Uma instAncia da classe java.lang.Thread; 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 nouothread, uma nova pilha se m6todo da pilha - o m6todo na parte inferior dela. Por6m, logo que voc6 criar 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.
seja muito cuidadoso com a interpretagdo de algum comportamento com o qual voc6 se deparar em 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.

Poftanto,

/./ma

AO TRABALHO
Nio
comela o erro
de

proletar reil pragrama baseado em ama implementagio especifca

da

JL/M.

Camo

uocd aprenderd

posteionnente,

JW|IS

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

As perguntas do exame sobre threads estio entre as mais dificeis. Na verdade, para a maioria das pessoas elas sla

JAVA

385

mais dificeis, e com qrxttro objaivos sobre threads voc6 terd que responder udriarpergontassobre eles. Se ainda 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

realmente

nio estiver familiawado com


@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
os threads, o que de java-lang.Thread

inclui zua cia$o,inicio

e pausa-

No

exame,

vod

Vod encontra.ri m6todos na classe Thread para gerenciar 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 ) 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.

nn(

VocO pode definir e instanciar um thread de uma das duas maneiras:

I I

Estender a classe java.lang.Thread

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, possivel fazer isso estendendo a classe Thread ou implementando a interface Runnable. Examinaremos as duas situag6es nesta segXo.
6

Estendendo java.lang.Thread
A maneira mais simples
de definir que um c6digo deve ser executado em um thread separado 6:

I I

Estender a classe Thread;


sobrescrever o m6todo
6 este:

run

O formato

386

Copftulo 9: Threods

cl-ass MyThread extends Thread public void run ( ) {

System.out.println( "Tmportant job running in MyThread"


]

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.

A limitagio

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-:hlinh rrtnnino in MvThrcad")


.

public void run(Strj-nq s)


Qa,cf6m ^,1f hrinflh/\\cts'.i-^

{
ir"n i. " + S);

].
]
Masesteja
classe Tbread espera um

a)ertaparaisso:omitodarun(String s) MbrecarregadoserdignoradopelaclasseTbreadamenosqueuoc6ochane.A milodo run ( ) um argumentos, e executari esse mdtodo para uoci ert una pi/lta de chamadas sQarada dEois que
a

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 do c6digo de onde voc6 fez a chamada, como acontece com qualquer outra chamada a

m6todo normal.
I

mplementando java.lang.Runnable
de estender a classe que quiser, al6m de
6 esse:

A implement aElo dalntertace Runnable lhe proporcionari uma maneira comportamento que serA executado por um thread separado. O formato

definir o

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

Portanto, examinaremo
fancionarrealmente.

s agoraa inttancia(alde sua classe

ser processado por um thread de execugio. habilitada para threads e, em seguida, veremos como fazer a coisa

Instanciando um thread
Nio run
Se

se esquega de que

) estar em uma subclasse de Thread ou em uma classe de objeto Thread parafazer t:udo funcionar.
voc6 estendesse a classe Thread,
a

todo thread de execuglo comega como uma instAncia

&

classe de

implementagio

Thread. Independente de seu m6todo Runnable, voc6 ainda precisar6 de um

instanciagio seria muito simples (veremos mais alguns construtores sobrecarregados

daquiapouco):

MyThread t = new UyThreadQ


Se

voc6 implementar Runnable,

instanciagio serl um pouco menos simples. Para ter um c6digo executado por um thread,

uocdaindaprecinrideanainttdnciade-I'hread.Contudo,emvezdeinserirothreadeatarefu(oc6digodom6todorun( 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

))em

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

387

Thread t = new Thread (r) ; / / passe seu Runnable a Thread


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

VocA s6 pode passar uma instAncia de Runnable para os virios objetos Thread, de modo que a mesma instAncia torne o destino de miltiplos threads, como vemos a seguir:

se

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

Fornecer o mesmo destino para vlrios threads significa que mriltiplos threads de execugio estario executando mesma tarefa (e que a mesma tarefa seri feita diversas veies).

OBSERVAQ6TS

pene O EXAME
run

A pnipria classe Tbread inplementa Rtnnable (afna/, ela tern am adtodo poderia passar am Thread a 0ulr0 clnstrutzr de Tbread:

) qae estiuamos sobrescreuendo). I:sa signfica que

uocd

Thread

t = new Thread(new

MyThread(

) );
uocd sd

Isso d am pouco estranho,

nas adlido. Neste caso, na uerdade,


usa

precisa de um Rttnnable, e criar oatro Thread d an exagerl.

Al6m do constnrtor sem argumentos e do que


a ser

executado),

hi outros construtores sobrecarregados


)

uma instAncia de Runnable (o destino, a instAncia que cont6m o trabalho na classe Thread. Os construtores relevantes para n6s seo:

I I I I

Thread(

Thread(Runnable target) Thread(Runnable target, String name)

Thread(String

name)

VocA ter6 que conhecer todos eles no exame! Posteriormente, discutiremos alguns dos outros construtores da lista anterior.
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.

Entio, voc6

Quando um thread tiver sido instanciado, por6m, nio iniciado (em outras palavras, o m6todo ) nio foi chamado na instAncia de Thread), diz-se que ele est6 no estado novo. Nesse est6gio, o thread ainda nio 6 conside rado atiuo.

start (

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

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:

Um novo thread de execucio

ser6 iniciado (com uma nova pilha de chamadas).

388

Copitulo 9: Threoos

I r

O thread

passar6 do estado novo Para o estado exuutduel.

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 instAncia de Thread ( ) e nXo de Runnable.

start ( ) em uma

OBSERVAQ6ES

aidigo que cbame o mdtodo rwn ) em uma c/asse Rannable (oa mesmo em ama ) serd executado em uru thread sQarado! Chamar instincia tle Thread), isso i pefeitanente udlida. Mas ndo stgntfca que o m,itodo run um milatlo ) 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:
nouo thread chamard. Portanto, se uoft se deparar com

pene EXAME Nno h,i natla especial na mitodo run ( ) da lingaagen laua. Cono main (
un

sinrylesmente

o nome (e a assinatara) do mdtado que o

run (

Runnable

r = new Runnabfeo ; r.runO; / / V61ido, mas ndo inicia

um

thread separado
definigio, instanciagXo
e

O exemplo abaixo demonstra o que abordamos

at6 agora:

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 . O exemplo a seguir instancia um que cada objeto Runnable exiba o nome do thread que executar seu m6todo run ) 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
nrthl ic ql-^l- id \z^id main (strind \ruLfrrv Il arfta\ LJ q!vr/
;

389

Ir

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

seguir:

? java
Run

NameThread

NameRunnable runninq

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
podemos at6 obter o nome do thread que est6 executando nosso c6digo principal,

Thread.currentThread( ),

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 inicializaeio de um thread.

-main

()

(novamente, quem adivinhou?). AFigurag-1 mostra oprocesso de

Iniciando e executando mais de um thread


JA

brincamos o bastante; passemos para a execugio real de aiiosthreads (mais de dois, na verdade). J6 temos dois threads, ( ) 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 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.

porqn" o m6todo main

390

Coo(tulo 9: Threoqs

class NameRunnable implements Runnable public void runO t for (int x = 1; x < 3; x++) {
rJruvaLt.vuL.v!

q\rct-am

nrrj.

nrinl.

lnl"Rrrn r\urr \

krv
vJ

\'

+ Thread. currentThread ( ) . getName ( ) ) ;

+ " , x is " + x);

public class
nrrlrl in

ManyNames {
rrnirl m:in /j- rino
\ v e! r44Y

c|.at'ir

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


^n6 cl-arl-ll. I\
.

l-r^rn cf :rl|,hr^a

ar^r|.l\.

l) comega main0 pub) ic static


/

void main{SL:ing

I args)

r1

/ execuca
attm aAAl.d--"

*_ryI_-i
Pilha

/ / al

f--* *-.*--*

//em maino
methodl(r;
,r

2) mainQ chama methodl()

I executa

''--. __-i**''i methodl

ii

/ mais c6digro

i-..-'.."'-*J j

j
i

rtain
A

Pilha

void nethodl{} { Runnah)l-e r : new MyRunnabLeO;


Thread t - new Thread{r);

i-----l

t.sLartO; --.--__, I I faz mais alguma coisa


)

I-a{: Il;r B
pilha
(thread 3)

r**h"Ji I -l

t)

Pilha A (main thread)

methodlf comega um novo thread

Figuro 9-1 A execugio


desse c6digo

lniciolizoEdo de um threod

produzid

o seguinte:

Z java

ManyNames
Y r_S 1

Rrrn fr\/ F-re.l

JAVA

39I

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 Run

by Ricky, x is

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.

as coisas acontecem em uma ordem previsivel. Mas as ag5es de diferentes threads podem se misnrar formas 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

Dentro de cada thread,


de

eventualmente comegamos

ver alguma oscila$o:

public void runo { for (int x = L; x <= 400; x++) System.out .println ( "Run by " * ", X is " + x);
J

t
(

+ Thread. currentThread ( ) . getName

A execuglo do c6digo anterior, com cadathreadprocessando o m6todo run de szuloop 400 vezes, comegou bem, mas depois se tornou nio linear. Aqui esd apenas um trecho da saida de linha de comando da execuEio desse c6digo. Paratornar maisfacildistinguircadathread coloquei emit6lico asaidaqueincluiFred, eemnegrito adeLucy, deixando adeRicky
inakerada:

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 aumentando um de cada vez, como esperado:

nio

Rttn bl Fred, x is 345 Ran Ran


b1 Fred, b1 Fred,

x is 345

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
Se o tread se tomar inatiuo, jamais podenl ser reiniciado!

voc6 tiver uma referAncia a um Thread, e chamar ) mais uma vez, isso ) , ele 6 iniciado. Se chamar 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 ) . Apenas um novo thread pode ser iniciado, e apenas u mavez. Um thread que estiver rodando ou inativo nlo pode ser reinicializado.

start (

start (

tart (

At6 agora, vimos tr6s estados dos tread:


este

nouo, executduel e inatiuo.

Examinaremos outros estados antes de terminarmos

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:

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
inflaenciar

nio

controlarrnot

o agendador de treads (nXo podemos, por exemplo, informar que um tread especifico
a seguir nos

seri executado), )s vezes, 6 possivel influenciilo. Os m6todos

fornecerlo algumas ferramentas para

o agendador. Somente nio confunda influ6ncia com controle.

oBSERVAQAO
tread
e

pene EXAME
exa
e

Espere porpergunlas n0

que aua/iardo sea conbecimento do que

oa ndo garantido! Voc|precisa ser capaTde olhar o aidigo de am


se isso

determinar

se

a saida serd realmente exibida de ama maneira esbecifrca ou

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,

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.

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

start (

atiut

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.

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

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 referncia 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
na classe Thread, que perrnite
a

-podecausarconfusio.H6umm6todo,suspend( ),

outro sualuspenslo; mas esse m6todo {oi reprovado e nio estari 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
um tread informar
a

de que um tread no estado bloqueado

ainda| considerado atiw.

I Inativo

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

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

necesdrio um cientista espacial para lhe dizer que

se

um tread est6 inativo, ele nio

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 I I
Suspensio

Suspensio
Espera

Bloqueio, porque precisa de um objeto bloqueado

( ) 6 um mdtodo static da classe Thread. use-o em seu c6drgo para "desacelerar umtread entrar no modo de suspensio antes de retornar ao e$ado executivel (no qual ainda ter6 que aguardar para ser o ffead executado). Quando um tread 6 suspenso, vai para algum local e nio retornaao estado execut6vel at6 que seja
O m6todo sleep
forgandoo
a

despenado.

Entio, por que voc6 iria querer um tread

por achar que o treadex|percorrendo seu c6digo muito dar opomrnidades a outros, j6 que uma execuglo adequadamente agendada 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.
suspenso? Bem,
a

rapidamente. Ou precisar forgar seus treads

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

395

Observe que.o m6todo

sleep ( )pode lanear

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 como no c6digo anterior.

uma excegio verificada InterruptedException (cuja possibilidade

tryliatch,

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. q|- :rlI l .

^no l-r^rn l-hrao

qi-arl-/\.

A execu$o

desse

c6digo exibiriFred, Lurye Rickyse alternando de maneiraadequada

t java ManyNames Run by Fred Run by Lucy


by Fred Run by Lucy Run by Ricky Run by Fred
Run Run
Pr

by Lucy
P

rn h\/

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

pene EXAME Sd porque o miitodo sleep ( ) do thread expirou e drpoit desperloa,


OBSERVAQAO
nio pode, por exenplo, confar no mdtodo
executado iouamente logo

n6o signtfca qae retomari ao estado de exuapdo! L,erabre-se de que

) ser,l o periodo quando um thread d despertado simplesmente retorna a0 estado executduel. Portanto, o tempo especifcado em sl-eep 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
) sl-eep ) nno un tinerpfeitanma prcciso. Embom em naias @litatiws usm sl-eep ndo d amagarantia de que o thread comeganl a ser nmotimerselasr.{uimtenmteadequada,mdprvcisasaberqaeotenpoespafuadanestemdtodo

q*i

ptriodo ixpirar

eo

tiread dupertar.
se engane

NXo

se esquega de

que s l eep

)6

um m6todo estitico, portanto, nio

achando que um tread pode colocar

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


) de

interface Runnable.

2. Sobrescreva o m6todo

run

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

Thread. sleep

( ) para f.azer uma pausa. lJm mimero do tipo long representar6

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 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 Selecionar a execugio de um tread mantendo-o assim at6 que seja bloqueado ou conclua seu m6todo o tempo dos treads do pool para dar a todos uma opoftunidade igual de execugio.

5
(

397
);

run

T dividir

Configurando a prioridade de um tread O tread receberi uma prioridade padrio que


execugio que o criou. Por exemplo, no c6digo

ser6 igual a do tread de

public class TestThreads { pubfic static void main (String [] args) MyThread t = newMyThreado;
J

O tread referenciado por insAnciadeMyThread

teri a mesma prioridade do tread main

(),

ji

que esse esti executando o c6digo que cria a

VocAtamb6mpodeconfiguraraprioridadedeumtreaddiretamentechamandoom6todosetpriority(
instAncia de Thread. como vemos abaixo:

)emuma

FooRunnable

r
'',;

= new FooRunnableO
ta
)

Thread

t
O

= new Thread(r);
rrr

t- <of Dvi nri


.*-.'-J

t.start

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 o intervalo das prioridades dos treads:

static

inal),

as quais

definem

Thread.MIN_PRIORITY (1)
Thread.NORM_PRIORITY
(

5)
)

Thread. MAX_PRIORITY ( 110

O mdtodo yield(
pr6tica. O que

fim de permitir que outrostreadscomanermaprioridadetenhamsuaoportunidadedeserprocessados.Portanto,afinalidade6usaryield( parapromoverum agendamento sofisticado de opornrnidades entre treads de prioridades iguais. Na verdade, o m6todo
) fuuefazer

yield (

Mas o que o m6todo

static Thread. yield ( ) tem a ver com tudo isso? Nio


o tread sendo executado para o estado

muito, na
)

|retornar

executivel,

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(


estado

)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

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

Uma chamada

yield ( join(

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.

Uma chamadaa

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

( ) do thread for concluido (6bvio). Com uma chamada a wait ( ) em um obieto (nio chamamos wait ( ) em um tbread, como veremos
Se

o m6todo

run

em

breve).

Quando um thread nio consegui r o bkq*eio do objeto cujo c6digo do m6todo estiver tentando executar.

O agendador do thread pode decidir

passar

o thread
6

que outro thread tenha a chance de rodar. essas trocas da maneira que desejar. Saida

Nio

atual do estado executado paru execut|vel, para permitir preciso nenhum motivo - o agendador do thread pode fazer

Principais eventos no c6digo do thread

A is running
n A ^ a a A A P R A R A A E ! R A n A R R R R R R R R A A A A I A l!r {D ic ic ic ic ic ic ic ic ie ic i+r ic ic i< ic ic ic ic ic ic ie ic ic ic ic ie ic ie ic ! urlrrlrv --.-'*i-rurllrug rrrnninn nrnnina rrrnnina rilnhihd rrrnrina nrnnind nrnninn vrrnninn rrrnninn rrrnhinn *,--i-r s4rf rrg rrlnhi-d rrrnrinn -,rrnina nrnhiaft nrnninc rirnnind rrrnninn firnhind rrrnnina rr:nnina rrrnninn rrrnni rrrnai n:nnina rrrnnira nrnninc rrrnnina .1,hnin^

Thread b = new Thread(aRunnable);


b.

start

Ot
Pilha

r'/Os Threads v6m e voltam

A esti

f-*--t r*-_:l t1 ti
;l

sendo executaca

I
//A-iilnfa-sc B //de ao finaf

il

aosturQ

i"l il
LI

a"ottero

Pilha

A estii

""';lo;u
Pilha B

rt
executaoa

Pilha B esti senoo

ldood'e4l

//Thread B finaliza !! //Thread A inicia novamencer


Pilha

i___,1
A

dostuf0

Pilha Aunida

'a ---,Ji
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 prob/emas referentes a dcesso simultineo.
utt @rlpriadr
do bloqaeio de objetos para proteger uaidueis

utiticat

ou de instdncias de

JAVA

399

Voc consegue imaginar o problema que pode ocorrer quando dois threads diferentes com acesso ) mesma 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.

instincia de uma

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. da quantidade que voc6 quiser retirar:
^l ufa-D-^^ l^^^,,-! 6LLUUIrL r I

A conta simplesmente rcrL o saldo reduzido

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.

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.

O que aconteceri

A l6gica do c6digo
1.

de nosso exemplo ser6 a seguinte:


a refer6ncia a apenas

O objeto Runnable cont6m

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 I

Faremos uma retirada (se houver o bastante na conta);

Exibiremos uma declaraglo de fazer uma retirada).


seguinte:

se

a conta exceder o :aldo (o que

nunca deve ocorrer, j6 que verificaremos o saldo

antes

5. O m6todo

makewithdrawal (
se

) da classe de

teste (representando o comportamento de Fred ou Lucy) faz o

I
T

Verifica o saldo para saber


Se

hi

o bastante para

^retk^d^;
a

houver o ba$ante, exibiri o nome de quem estiver fazendo

retirada;

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 I

quando sair da suspensio, concluirl a retirada e exibiri que ela foi feita;
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
* i arra
1 l'rad

saida (numerada):

n: --**------rnger A--^rrnt.
ic aninf^ rrithArrt.r

JAVA

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 13. Not enough in account for Fred to 14. Lucy completes the withdrawal 15. account i-s overdrawn! 16. Not enough in account for Lucy to 17. account is overdrawnl 18. Not enough in account for Lucy to 19. account is overdrawnl
Embora a

withdraw withdraw

0 0

withdraw -10
withdraw -10

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

primeira rdrada. A

alterou depois da ihima vez qtre foi verificado. E agora Fred est6 verficando o saldo nouamente, antes de Lury concluir sua 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 ^ valor igual a 10. Na linha 10, Lucy verificou novamente e viu que o saldo era 1.0, poftanto ela sabe que pode fazer
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
B acessari Obleto I

somente

Thread

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

elas sempre sejam executadas

a rcr.trada - nunca fiquem separadas. Precisamos que Temos que garantir que as duas aapas da retbada - wrfiatr o saldo e 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

jty

E como voc6 protegeria os dados? E preciso fazer duas coisas:

I I

Marcar as vari6veis com

private;
as

sincronizar o c6digo que altera

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 .

makeWithdrawal ( ) com slmchronized, como vemos abaixo: private synchronized void makeWithdrawal(int amt) { if (acct.getBalanceO >= amt) {

Podemos resolver todos os problemas de Fred e Lucy adicionando uma palavra ao c6digo. Marcaremos o m6todo

System.out.println(Thread. currentThread( ) .getName ( ) " is going to withdraw"),'

trY

{
;

Thread.sleep(500) acct.wj-thdraw(amt);
System.

) catch(InterruptedException ex) { 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 Not enough in account for Fred to withdraw

0 0

JAVA

403

Not enough in account for Lucv to withdraw Not enough j-n account for Fred to withdraw Not enough in account for Lucy to withdraw

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

Como

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

56 os ndtodos podem ser

slmchronized,

as

variiveis, nio.

Cada objeto possui apenas anbloqueio.

Nen todot ot mdtodos

de ama classe deuem ser

sincroniqados.IJma classe pode ter tanto m6todos sincronizados quanto

nio-slmchroni zed.
estiverem usando

slmchronized em uma classe, e ambos os threads 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).
Se

dois threads estiverem prestes a executar um m6todo


a

mesma instAncia

&

classe para chamar o

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 I

St

o,

thread enhar em suspensdo, e/e mantdm os vus b/oqueiot -

nio ot /ibera.

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 li

Voed Pode

sincroniqar um bloco de cddigo em ueqde am nitodo.

que a sincronizagio prejudica a concorrncia, 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 Psvrrv q1m^rF6cf I
(

out.println "not slmchronized" ) ; slmchronized(this) { System, out . println ( " slmchronized" ) ;


System.
(

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


que os m6todos

chronized public synchronized void dostuff O { System. out.println ( "slmchronized" ) ;


]
6 equivalente a isto:

(ttris), como no c6digo acima. (Jma vez que 6 a mesma instAncia em bloqueiam, isso significa que voc6 pode sempre substituir um m6todo slmpor um nio-slmchr onized, que contenha um bloco slmchronized. Em outras palavras, isto: slmchronized

public void doStuff ( ) { slmchronized (this ) { System. out . println


] Ambos

("

slmchronized" ) ;

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 esa classe. E essa instincia de java.lang.Class cujo Java possui uma insrAncia correspondente de,iava.lang.Class 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 em uma classe chamada MyClass, o c6digo equivalente 6 o seguinte:
^'lh] PulrIL ;^ rf-f;^.int>LdUfL Irru zcd(MttCl noft-nrrnf VEuevurrL\/ aqq l\ nlacq\
J

slmchronized.

Se o

m6todo for definido

srmchrnni

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

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 em seguida, a exibigio passar6 para a pr6xima letra. IJsaremos um objeto StringBuffer.

e,

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
objeto StringBuffer no argumento.

um

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

No entanto,

Ao

se

considerar o impedimento, 6 importante prestar atengio a quais objetos estio sendo usados para o bloqueio.

r I I

Threads qtre chamam m6todos que nio sejam 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.

static

Threads que chamam m6todos static slmchroni zed da mesma classe sempre bloqueario uns aos outros - todos eles bloqueiam na mesma instAncia de Class.

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 niostatic bloqueia na instincia this - essas ag6es nXo interferem umas com as outras de forma nenhuma.
voc6 precisa observar exatamente qual obieto foi usado para o blogueio. (O que slmchronized?) Threads que sincronizem no mesmo objeto bloqueario umas )s outras. Threads que sincronizem em objetos diferentes nio o fard.o.
est6 dentro dos par6nteses, depois da palavra
9-1 lista os m6todos relacionados a threads e se o thread abre

lPara blocos slmchronized,

A Tabela
Tobelo

mio

de seus bloqueios como resultado da chamada.

9-l

Metodos e o sfofus do b/oqueio

Abrem mlo do bloqueio


wd,r \- \
)

Mantm o bloqueio

Classe que define o mdtodo

notify ( ) (Embora
dessa chamada.

o thread provavelmente saia do c6digo sincronizado depois

j ava. lang. Obj ect

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 os nossos dados. Geralmente, sempre que mais de um thread estiver outros t" hor" "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 e nio-static, caso eles contenham dados que possam ser precisa se preocupar com campos

itatic

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 simultAneo. Mas um ihread que esteja trabalhando com uma a mesma instAncia serio impedidos de ter.m "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 h6

um campo

uma boa chance de elas nio funcionarem da maneira que voc6 deseja. Se voc6 tem um m6todo static acessando 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

slmchronizedeumquenioseja srlcromzanainstAnciaatual(this).Lembre-sedequeumm6todostatic 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.

9:ampg

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
deue

slmchroni-zed.
deue

O acetso a campos utdticos


rerfeito apartir

nrfeito apartir

de ndtodos que ndo

s/an

dc mdtodw stat.ic slmchroni zed. O acesso a campos ndo-esL6ticos sLatic slmchronized. Por exemplo:

public class Thing


nrirra|-a nri cl-aFi^ rzaf o i ht

{
<i:l-iaFia]A.
.1 .

inf

n^nql- af i .E i al

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

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


else

(0)

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

O m6todo

Collections. synchronizedlist

Namelist destaf.orma

public static void main(StringlJ args; 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

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
Thread

get

(0 ) , elas ocorrem nesta ordem:

t1 executa names . size ( ), que retorna 1. Thread t1 executanames . remove (0 ) , que retornaozlzmandias.
Threadt2 executanames. size ( ),queretorna Thread L2 nio chama remove ( o ) .
A saidaaqui
6

0.

Ozlzmandias

nu11
Entretanto,
se

executarmos o programa novamente, poderi acontecer algo diferente:

Thread L1 executanames .

t2 executanames Thread t1 executa names


Thread

sizeO, que retorna 1. . size ( ), que retorna 1.


.

remove

(0),

que retorna

Ozymandias.
como aquela retornada por synchronizedlistQ, cada m6todo
essas duas

Threadt2 executanames.remove(0),quelangaumaexcegloporquealistaagoraest^vazia.
O que voc6 precisa perceber aqui 6 que, em uma
nada impede que
classe "segura"

individualestisinCronizado.Assim,narnes.sizeO est6slmchronized,enames.remove(0)tamb6m.Mas
outro thread
faga alguma

outra coisa na lista no espago entre

chamadas. E 6 ai que podem

ocorrerproblemas.

Hiumasolugio aqui: nlo confie


vocAmesmo:
imnnrr i=rz: ,rfil *.

em

Collections . slmchronizedlist

( ) . Emvez disso,

sincronize o c6digo

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 primeiro finalize a sua operagXo com o m6todo removeFirst ( ) .
de esperar at6 que

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
seja breve e o libere (concluindo o m6todo

4O9

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 { private static class Resource { 2. public int value; 3. 4. ) private Resource resourceA = new Resource 5.
5nrirrate
ReSO111.Ce

();

reSOUrCeB = new Resorrrce():


aqui_

7. B. 9. 10.

pubLic int read() { slmchronized(resourceA) { // Pode haver impasse slmchronized(resourceB) { 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 1-'7 . slmchroni zed resourceA) { 18. resourceA.value = a; 19. resourceB.value = b; 20. ) 21. )
(

impasse aqui

))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 16 e 17 (ou nas

exemplo simples 6 f6cil de corrigir; apenas troque a ordem do bloqueio do thread de leitura ou de gravaEio nas linhas 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.
entre si para comunicar - entre outras coisas

O fltimo item que precisamos examinar 6 como os threads podem interagir 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 ;Ora,'nlo vou perder-meu tempo proiurando-correspond6nciai a cada dois segundos. Vou ficar nenhuma dizerr 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
Os ndtodos

lembrar

(e

memorizar para o exame) sobre waitlnotify 6 esse:


de

waiL
an

),

noti f y ( ) e noti fyA11 ( ) deuen ser chamados


or,t

dentn dr um contexto sincmniTado! O thread nio

pode chamar

mdtodo

aait

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
a

formatos

6 6timo porque o usuirio nio poder|fazer nada enquanto definir. Precisamos melhorar a situa$o.

miquina estiver ocupada

houver outros

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.

Uma solugio simples

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.
um sinal (uma notificagio) desse objeio. Um 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):

Lembre-sedequeosm6todoswait( )

enotify(

) slom6todosdeinstAnciadeObiect.Damesmamaneiraque

todo objeto poisui um bloqueio, pode haver uma lista

de threads aguardando

JAVA

411

1. 2. 3. 4.
5.

class ThreadA { public static void main(String [] args) ThreadB b = new ThreadBo; b.start0;
slmchronized (b) i

. '7.
6

try

8. 9. 10. 1l-. 42. l-3. L4.


l_5.

System.out.println("Waiting for b to complete.


b.wair O ; ] catch (InterruptedBxception e) i)

System.out.println(..Total is: .. + b.total);


)
) )

16. I7 .
1_8.

class ThreadB extends Thread { int total;

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

Observe na linha 6 que o c6digo

sincronizado com o objeto b; isso porque, para chamarwait

precisa.do.bloque-iodeb.Paraqueumthreadchamewait(

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:

)ounbtity[

) no objero, ThreadA

),.1.t.-queseroproprietiriodo

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


swahrorizarl(th) Esse q\ I rrvuflJ\/r r nnfifrr/\

fy

( ) seja chamado em anotherObj


1
J

ect.

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 bloqueio de um ob.iito em um bloco de c6digo especifico.

se

um thread possui o

p;jgr.; i"tlri"mpid" di -.rrrr"


exceglo:

Observe nas linhas 7-10 que

hi um bloco

maneiraqnl.

trylcatctr encapsulando o m6todo wait ( ) . Um thread em esPera n- thread em suspenslo, portanto, voca ter6 que manipular a

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
rrvsu

t
L

I oarecE.lons;

etc.

E imponarrte que o thread do usuirio nlo altere as etapas da m6quina enquanto o thread do hardware ,rsando, portanio, essa leitura e gravagS,o devem ser sincronizadas.

as

estiver

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

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

it(

| 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

I\o

) for chanado em um objeto, o thread que e$iaer executando use aidigo abinl mdo de tea bloqueio

entanto, quando chamado

noLify (

no t

i fy (

foi

nio signtfca que o bloqueio

se

tornani disponiuel

nesse

mlmentl.

Usando notifyAll( esPerando

) quando houver a possibilidade de muitos threads

estarem

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

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

nrrl-r'l i c Raarlor

/l-: l nrrl

^f ^r

^il

^l

c = cafc,.
)

6.
7.

8. publ-ic void runO


crmnhrnni
1-0 . 11

zaAlr\ I

j-rrr
eJ

Qrr<fpm 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; public void run0 { slmchronized (this ) { for(int i=0;i<100;i++) total += i;
]

29,

30. 31 . 32. 33. 34. 35. 36. 3'7. 38.


Esse

notifyAll
)

O;

)
)
(

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
Isso funciona
e

Reader/Calculator) tinham um mesmo problema. Em

ambos,haviapelomenosumthreadchamandowaitO,eoutrothreadchamandonotifyO

ounotifyAllO.

notifyO

muito bem, desde que os threads na espera rcnham comegado


a

esperar antes de o outro thread executar

ounoLifyAllO.Masoqueacontecese,porexemplo,oCdculatorrodarprimeiroechamarnotifyo
esperar?

antes de os Readers terem comeEado

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|-lonovamenteficario 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
e os Readers na espera

anterior damiquina cortadora de tecidos:

class Operator extends Thread {


Machine machine;

// public void runO { while (true) {

assume que

isso seja inicializado

Shape shape = getshapeFromUserO;

Machinefnstructions -iob

JAVA

415

calculateNewlnstructionsFor
machine. add,fob ( j ob)
;

shape ) ;

o loop para sempre, obtendo mais formatos dos usuirios, calorlando novas instn46es para esses enviando-os para a miquina. Mas agon al6grca para no t i fy ( ) foi movida para dentro do m6todo add,Job ( ) dadasseMachine:

O operador continuar6
e

formatos

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

public void run0


urhila ttrrra\ I crmnhrnnizod
/ /

/'inhc\ al- 6 mra

I no l o

/ / aqnara veyvre

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

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
porque
6

possivel que um thread tenha acidentalmente enviado um

noti fy

condigio i sHrpty ( ) sempre que for reativado, ( ) incorretamente.

podeserreativadomesmoquenenhumc6di.gotenhachamadonotifyO ounotifyAllO.@elomenosnenhum i6Ag" de que voc tenha conhecimento. Als vezes aJW poderi chamar notify ( ) po1 raz6es que s6 ele sabe,_ou

Existe tamb6m uma situaglo possivel, chamada de reativagio espontenea, que pode existir em algumas situag6es - um thread

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.
Se estiver vazia, esperamos; se

Na classe Machine, o que e$avamos esperando era que a lista de trabalhos nio estivesse vazia.

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


).ATabela9-2

O:ndtodoswaiL( ),notify(

sdonitodotnmentedejaua.lang.Objut,endodejaua.lang.Tltreadou
e os de

jaua.lang.Rannable. Certfique-se de saber que mritodos sdo defnidu em Tbread, quais sdo en Objut

plftantqesseificil).DosrzitodosprincipaisdeThread,ceftifique-sedesaberquaissdosLaLic

quaisndosdo-join( )estart(

-s1eep( )eyield(

Runnable (sonente ran( ),

)-

listaosmdtodotprincipafuqueuocdprecisaniconltecernoexame,czmosnitodos

static

exibidw em itdlico.

Tobelo 9-2 M6lodos principois dos threods


Classe Obiect

ClasseThread

Interface Runnable

wait0
notdyQ

staft0 jeld(
tlttp(

run0

) )

notifyAll0

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 alguns
dos pontos principais de cada objetivo para a certificagio deste Capinrlo. Tire uma c6pia embaixo de seutravesseiro para completar a absorgio.
e

durma com eles

Criando, instanciando e iniciando novos threads (Objetivo 4.1)

0 B

Os threads podem ser criados pela extensio de Thread e a sobrescrigio do m6todo

public void run (

).

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

417
de

Voc6 pode chamar start ( ) em um objeto Thread somente uma vez. Se start vmavez em um objeto Thread, uma excegio RuntimeException seri langada.
E

)for chamado mais

u
tr

vilido criar muitos objetos Threadusando

o mesmo objeto Runnable como destino. )sejacharrudo.

D QuandoumobjaoThreadforcriado,eleniosetomarawntlmaddemug'wxiq:eseum6todostart(
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 E D tr tr

Uma vez que um novo thread for iniciado, ele sempre entrari no estado execut6vel.

O agendador

de threads pode

alternar um thread entre os estados execut6vel

e de

execugio.

Para uma m6quina tipica, de apenas um processador, s6 um thread pode ser executado estar no estado execut6vel.

por vez, embora muitos possam

Nio hi Nio

garantia de que

ordem na qual os threads foram iniciados determinarl

ordem na qual serio executados.

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, ) funciona bem o suficiente para encorajar os seus threads a

yield (

trabalharem bem juntos.)

E
D

Umthreadsendoexecutadopodeentraremumestadobloqueado/deesperaporumachamadaawait(

oujoin(

),s1eep(
de

).
espera, porque

Um thread sendo executado pode entrar em um estado bloqueado/de


umtrecho
de c6digo

nio p6de obter o bloqueio

sincronizado.

E tr E E
D

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

Um thread inativo nio pode

ser iniciado novamente.

Sleep, yield e join (Objetivo 4.2)


A suspensio 6 usada para retardar thread entrar em suspensio.
a

execugio por um periodo de tempo

nenhum bloqueio seri liberado quando um

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.
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. O m6todo
e 10 (alto), embora
) 6 usado em objetos Thread para dar aos threads um n(vel de prioridade entre 1 Saixo) prioridades nio sejam garantidas e nem todos osJVMs usem um intervalo de prioridades de 1 a 10 - alguns niveis podem ser tratados como efetivamente iguais.
as

fl E
O

setpriority (

Se

nio for configurada explicitamente,

prioridade de um thread seri

mesma do thread que o criou.

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

tr

O mais pr6ximo que teremos

prioridade alta.

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

do

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

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

Todosostrsm6todos-wait(
que tenha o bloqueio desse objeto.

)/notify( )/notifyall(

conteno sincronizado! O thread ter6 que chamar

wait ( ) /notify ( ) em um objeto

) -devemserchamadosdedentrodeum
especifico, e seri necessirio

Threads em impasse (ObjetiYo 4.4)

I
D

O impasse ocorre quando removidos dos objetos.

execugio do thread

interrompida porque o c6digo

est6 esperando que os

bloqueios sejam

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

inadequado.

Nio

tente cri6lo.

Teste individual
Asperguntas

dificil, nio

se

a seguir o ajudarXo a avaliar sua compreensXo sobre o material apresentado nese capinrlo. Se inicialmente achar 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 Quais dos seguintes sio resultados possiveis? (lr4arque todas


as

419

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

----.19f nalne;
arc lQf rina n:mol t
L

nrrLrl i c T.of

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.

seguintadefinig6esdem&odospoderiamseradicionadas lclasselenenparase obteressa-garanrid (Marquetodas asco-rretas)

Quaisdas

A public B. public C public D. public E. public E public G public

void runo { writel;; i synchronized void runO { writeO; } static slmchronized void runO { wriLeO; } void run0 { stmchronized(this) { writeO; } } void runO { stmchronized(Letters.class) { writeO; } i void runO { slmchronized(System.out) { writeo; } } 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 B. public C public D. public E. public

class class class class class

MyRunnable extend.s Runnable{public void runo {}} MyRunnable extend.s object{public void. runo{}} MyRunnable implements Runnable{public void runO{}} MyRunnable implements Runnabl-e{void runO {}} MyRunnable implements Runnabfe{public void startO{}}

420

Copitulo 9: Threods

4. Dado: 2. class MyThread extends thread { public static voj-d main(String [] args) 3. 4. MyThread t = new MyThread|; 5. t.srarto; 6. System.out.print("one. "); 't . t. start O ; 8. System.out.prj-nt("two. "); 9. ) public void runo { 10. 11. System.out.print("Thread "); 72. ) l-3. )
Qual6 o resultado
desse c6digo?

A
B.

Acompilagofalha.
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. 4. 5. 6.
t1

public static void main(String [] args) MyThread t = new l'tyThreado; Thread x = new Thread(t); x.startO;

8.

public voi-d run O { . 10. for(int i=0;i<3;++i) { 11. System.out.print(i + ".."); 1.2. )
9

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

public static void main(String [] args) printAll (args) ;

JAVA

421

s.
; 8. 9. 10. 11. L2.
1?
I

public stati-c void printAll(Strins[] for(int !=Q;i<1j-nes.length;i++){ System.out.printl-n(1ines Ii] ) ;


]
]

lines)

Thread.currentThreadO.sleep(1000);

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
Elt

6 executado em

um objeto

r nread.

C. Seri exibida D.
Esse c6digo

currentThread ( )
nio

cada String das /inbat ser6 compilado.

do array, sem garantias de que haveri uma pausa porque


esse

pode nio recuperar

thread.

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 B. public public C public public D. public public E. public public H public public

void set(int a, int b) {this.a=a;this.b=b} synchronized int read(int a, int b) {return a+b} slmchronized void set(int a, int b) {this.a=a;this.b=b} int read(int a, int b) {synchronized(a) {return a+b}} void set(int a, int b) {slmchronized(a) {this.a=a;this.b=b}} int read(int a, int b) {s}mchronized(a) {return a+b} } void set(int a, int b) {slmchronized(b) {this.a=a;this.b=bi} synchronized(this) int read(int a, int b) {return a+b} slmchronized(this) void set (int a, int b) {this .a=a; this.b=b} int read(int a, int b) {slmchronized(this) {return a+b} } 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( );

notifyAll ( ); C isfnterrupted( r;
B. D. slmchronized( );
!.

E.

4rf

int-arrrrni-/ ue!rqvu

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

executar esse programa?

,{, SuacompilagXofalhar6porqueaexcegaorllegalMonitorstateExceptiondewait(
nalinhaT.

)nio6manipulada

B. 1.23

c13
D.L
E
2

E. Notempodeexecuglo,elelangar6umaexcegiolllegalMonitor StateExceptionquandotentarentrarno
estado de espera.
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
PelaCPI-llr
esse

m6todo for chamado, quando o thread A

se

tornar6 candidato

conseguir outra chance de ser executado

A
B.

Depois que o thread A for notificado, ou ap6s dois segundos. Depois que o bloqueio de B for liberado, ou ap6s dois segundos. Dois segundos ap6s o thread A ser notificado.
segundos ap6s o bloqueio de B ser liberado.

C
I

D. Dois

l. Quais das declarag6es abaixo sio verdadeiras? (Marque todas 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.

as corretas)

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.

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

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


C. Sincronizando D. Sincronizando

StringBuffer tornar6

essa classe segura.

E. Sincronizando

Ios ( ) . apenas o m6todo getContents ( ). log ( ) e getContents ( ).


apenas o m6todo

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
C

Exibexefinaliza.

B. Exibex enuncafinaliza.
ExibexY efinalizaquaseimediatamente.
atraso de 10 segundos entre

D. Exibe xY comum

Y.

E. ExibeXY comumatrasode 10000segundosentreX eY.

E
G
n

Oc6digoniocompila.
4t

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 D usrrr. rJ nrrf vsL
r nri v!

f !rurl!

nfl

n l $ fnn" \

); t.start
)
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 thread2. start

O O

; ;

JAVA

425
as

Quais dos seguintes pares de chamadas a m6todos nunca poderiam ser executadas ao mesmo tempo? (l4arque todas corretas)

A.x.a0 B. x.ao C. x.ao D. x. a O E. x.bo F. x.bo G.x.bo H.x.bO


|

threadl, and x.ao em threadl , and x.b0 em thread.l , and y.ao em threadl , and y. b O em threadl , and x.ao em threadl-, and x.bo em Lhreadl, and y.ao em Lhread.l , and y.bo
em

em thread2 em thread2 em thread2 em thread2 em thread2 em thread2 em thread2 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 { publ-ic void run ( ) { 5. 6. f.doStuffo; t. ] B. )); 9. Thread g = new ThreadO { public void runo { 10. 11. f.doStuffo;
1

'>

1,4. t. start ( ) ; g. start O ; l-5 . 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


C. O c6digo nlo seri compilado por

causa de um erro na linha 7 da classe Foo. 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) laurel = new Thread0 { public void run0 { System. out.println ( "A" ) ; try {
hardy.sleep(1000); ) catch (Exception e)
System.
{
(

out.println
. v!

"B" ) ;
:

i
q\rcfam rf e uqrr. nrrlvuu

nrint-ln rarLrlr

I irf-")

);
hardy = new rhread0 { public void run0 i
vJpeurrr.vuu.Pif.rL4

q\rcfam

nrrl-

nrint-ln

l"Tl/)

trY

laurel.wait ( ) ; ] catch (Exception e) t System. out . println ( "8" ) ;


)
q\rcl_am vtruelri.vuL.vr ^rrtnrin|In INF"')
:

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

Oc6digonSocompila.

JAVA

427

Respostas do teste individual


1.

C
e

Gromit-1

est6 correta. Ambos os threads exibirio duas mensagens cada. wallace-1 deve vir antes de wallace-2, deve vir antes de Gromit-2. Fora isso, as mensagens Wallace e Gromit podem vir em
base

qualquer ordem.

A, B, D, E, F e G estlo incorretas com


2.

no exposto acima. (Objetivo 4.1)

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 esti incorreta porque
classe tenha as interfaces

interface Runnable com um m6todo


e

run ( ) v6lido.

um m6todo

public void rin ( ) vilido, ela nio implementa


run ( )

sio implementadas,

nlo

estendidas. B esti incorreta porque embora a


6

incorreta porque o m6todo

run ( ), e nlo start

deve ser ( ) . (Objetivo 4.1)

publ ic.

a interface Runnable. D est6 E esti incorreta porque o m6todo a ser implementado

4.

se tenta usar o m6todo start ( ) pela segunda vez em um mesmo objeto Thread, o 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

B esti correta. Quando


m6todo

acima. (Objetivo4.1)

J.

D esti correta. O thread MyThread seri iniciado e executar6 um loop tr6s


A

vezes (de 0 a 2).

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

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)
)
deve declarar que langar6 a excegio

( ) deve ser inserido em um bloco try,/catch

ou o m6todo

printAll

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

this

A resposta A
pelo m6todo

est6 incorreta porque

read

( ) pertengam ao mesmo

nio foi sincronizada; portanto, ni,o h6 garantias de que os valores somados par. C e D estio erradas; somente objetos podem ser usados na

sincronizagio. E falha; nio 6 possivel selecionar outros objetos (nem mesmo quando um m6todo for declarado com slmchronized. (Objetivo 4.3)

thi

s) para executar a sincro ruzergio

& A, B e F estio corretas. Eles estio todos relacionados ) lista

de threads em espera

no objeto especificado.

AsrepostasCrE"GeHestioincorretas. Osm6todos
instAncia
9.

isrnterrupted( ) e interrupt ( ) slom6todosde eyield( ) siom6todosstatic deThread.Dest6erradaporque &Thread.Osm6todossleep( ) synchroni z ed 6 uma palavra<have e a estrutura slmchroni z ed ( ) faz parte da linguagem Java. (Objetivo 4.2) 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.


6

A resposta A

est6

incorreta;

rllegalMonitorstateException
jl
que esse programa

erradas, 3 nunca ser6 exibido,

ficari em um estado continuo

uma excegio nXo-verifica&. B e C estio 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 A

se

torne candidato

a ser executado

novamente'

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(


ser chamado em um contexto sincronizado.

))devesemPre

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.

estit,

classe nioestar6 segura a

correta. Sincronizar os m6todos priblicos 6 suficiente paru tornar a classe segura, en6o F 6 falsa. Esta 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

Illega1Thread.StateException.
a espera fosse

colocada dentro de

t antesde chamar t.waitO, entio elelangauma O m6todo est6 sincronizado, mas nio em L, entlo a excegio ser6langada. um bloco slmchronized (t ) , entAo a resposta correta seriaD.
base na

Se

A, B, C, D, E e F estio incorretas com


14.

l6gica exposta acima. (Objetivo a.2)

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

H nio

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
m6todo fosse sincronizado, o c6digo seria executado sem langar uma excegio.

t(

) . Se

o
a

As respostas A, B, C e D estio incorretas porque o c6digo ser6 compilado sem erros. F esti errada porque
excegXo ser6 langada antes que haja alguma saida. (Objetivo 4.4)
17 .

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 ( ) - mas hardy nio sincronizou em 1aure1, de modo que chamar laurel .wait ( ) causa imediatamente uma 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.

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

B, G e H estio incorretas com base no exposto acima. (Objetivo 4.4)

JAVA

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

class Ins)mc extends Thread { StringBuffer letter; public Inslmc(StringBuffer letter) this.letter = letter;
)
{

4. 5. 6.
'7.

8. 9. 10. 11-. ]-2. l-3. 1,4. l-5. 16. 1,7. l-8.


1q l

public void runo { slmchronized(letLer) { for(int i = 1;i<=100;++i) SysLem.out.print(letter);


)

System.out.println( ) ; // Incrementa a letra em StringBuffer: char temp = letter.charAt(0);


++tempt

letter.setCharAt(0, temp);
)

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
I I a/
P&R

Deierminor o Comoortomento em Tempo de ExecuE6o de Closses e Linhos de Comondo


Usor Closses de Arquivos JAR Usor Closspoths poro Compilor

C6digo
Exercicios r6pidos
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

clmpnrtanentl espnadn en tempo dc exuugdo.

l:;::r::t

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

At6. agora neste livro, n6s provavelmente j5, falamos sobre chamat os comandos agora iremos dar uma olhada mais aprofundada neles.

j avac e j ava

um milhio de vezes;

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
Digamos que voc6 tenha a seguinte estrutura de diret6rios:

significadestino).

myProj
I

ect
| --cdllFFA

I
I

-- MyClass. java

- classes
I

t-O sguinte comandqernitidonodiretoriomyProj ect,iticompilarMyClass . j ava ecolocaroarquivolvblass . cLass resultanre nodiretorio classes. (Obsena$o:istoassumequeMlClassniotenhaumainstrugopadcage;filarernos sobrepacoteseminstantes.)

JAVA5 433
^/l ftrrDT^'i 6^i

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
|

|
Se

voc6 estivesse

- (Myclass . class vem para c6) 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

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.
Esse comando poderia ser

De forma um tanto surpreendente, o comando


precisa! Suponha que temos o seguinte:

j avac

pode, em alguns casos, lhe ajudar ao ciar os diret6rios de que ele

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

/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. javac -d
.
. 6 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:

A ultima coisa sobre - d que voc6 precisar6 saber para o exame

java:5: error while writing MyClass: classes/MyClass.class such file or directory)

(No

Iniciando Aplicativos com iava


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.
O comando Eis avisio geral:

java [opc6es] class [argumentosl Aspartes [opg6es] e [argumentos] docomandojava java


-DmyProp=myvalue MyClass

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:

1 e

Deixando os detalhes para depois, esse comando pode ser lido como "crie umapropriedade de sistema chamada myProp 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,
seguinte c6digo:

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

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

chamado desta forma:

java

-DcmdProp=cmdval TestProps

Voc6 receber6 algo como isto:

os.name=Mac OS
mYProP=myvalug

j ava. specif ication.vendor=Sun Microsystems Inc.

user. language=en

JAVA

435

java.version=1.5.0
cmdProp=cmdVal

02

retic6ncias (. . .) representam diversos outros pares de nome = valor. (O nome e o valor sio, ds vezes, chamados de Duas propriedades norne = valor foram adicionadas is propriedades do sistema: myProp=myValue foi adicionada atavds do mEtodo setProperty, e cmdProp=cmdVal foi adicionada arraves

""0.;;e propriedade, respectivamente) chave


da

opgio -D
a

na linha de comando.
- D, se o seu

Ao usar
forma:

opgio

valor contiver espagos em branco, entlo todo o valor deve ser colocado entre aspas, desta

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.

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

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

depois chamado da seguinte forma

java

CmdArgs

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
pode ser declarado usando-se
a sinta:<e dos

e,apartirdoJava5,ometodo

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

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. 4. 5. 6. 7.
O ptimeiro lugar onde eles procuram
6

No caso de as listas de

busca conterem dois ou mais arquivos com o mesmo nome, o ptimeiro arquivo encontrado ser6 usado. nos diret6rios que contem as classes que v6m com oJ2SE.

O segundo lugar onde procuram


classes.

nos diret6rios definidos por classpaths.

Classpaths significam "caminhos de busca de classes". Eles sdo listas de diret6rios nos quais podem ser encontradas

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

maioria das quutdu do exame relacionadas a caminbos asani

serdo declarados usando-se banas inaertidas

(\)

e o caracter

nenbum conhecimento esputJtin sobre the//s para o exa///e.

conuengdes do Unix. Se uocdfor usadio do l%indowq os seus diretrjrios rcparador serd o ponto-e-uirgala 0. M^, nluamente, uod NAO precisani ter

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
Esse classpath

/ com/ foo / acct

/com/foo : .

6 idntico 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
i mn^rf

com.
d^fi

foo.MyClass;
f^^ * .

/,/ qualquer

uma das importaq6es

funcionarS

public class Another void go O {


^^com.

MyClass m1 = new MyClass O ;


I ^^ rr- -dl roo.lvlyulass m2 = new com. foo.MyClass O ; m1.hi O ;

// nome-c6digo / / nome completo

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 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; u.doX("argt", "arg2" ) i com.wickedlysmart.Date d =
new com.wickedlysmart.Date O ; d. getMonth ( "Oct" ;
,

nome simples

//

nome completo

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:

Um subdiret6rio chamado com (o chamaremos de diret6rio "ruz do pacote")

438

Cooftulo

l0:

Desenvolvimento

I I
1.

Um subdiret6rio dentro de com chamado Dois arquivos em

wickedlysmart

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:

O caminho at6 o diret5do deve ser absoluto; em outras palavras,


do pacote).

partit da ruz (at2|lz do sistema de arquivos,

e neo a

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 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:
6 uma

(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

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 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 nio tem um subdiret6rio chamada dirB. Em outras

dirB

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)


diretdrios @mpiada para esa
sucest0.

7.5 Dado o nome comp/etamente qualifcado cl.asse. Dada

de

ama

classe

distribuida dentro

ua exenplo

de aidigo e um clasEatb, deterzinar se o clarpatb

oufora de un arquiao JAk, canstruir a estr*tara de perrnitinl que o aidigo compile con

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
arquivar dados.
a

arquivos ZIP) e para

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
I

l--Dates.class
|

(pacote myApp.utits;)

-Conversions. clags

il

|-

-engl-ne
j
|

-r.a.. class

(pacote

myApp. engine,'

--minmax.class

Vocpode 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
precise descompactar o arquivoJAR Embora voc

alquvoJARpodedo seracessadasatrav6sdedasspathseusadaspor j ava e j avac.Tirdoissopodeacontecersemquevocd jamais nio precise saber como criar arquivosJAR para o exame, r'amos passar para o diretotio
e em seguida cnat

ws,

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

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

myApp/ engine /minmax

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

diret6rio myApp

utiIs,

f . j ava precisasse

usar classes do

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!


implesnente

Esrcspacotes sdo totalnente indtpendentet entre

$; a tinica coiv qae nrrpatilban


. * I na esperanga
de

o mesmo

direnirio "raiq", mas ndo sdo o mesnl paclte.

niltiplos pacotet

A tituk d.e infomagdq uoci n6o pode usar import, j ava lembre+e, uma inshvgdo inlprrt xd i capa<dz inportar un rinico pacote.

importar

Usando ..lirelllblext com Arquivos fAR


Quando voc6 instalaJava, cnada uma enorme anote de diret6rios contendo coisas relacion adas comJava, incluindo os arquivosJAR que contm as classes que vm com oJ2SE. Como dissemos anteriormente, j ava e j avac tm 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.
preciso mencionar esses subdiret6rios em uma instugio classpath - a procura nesse diret6rio 6 uma fungio interna A Sun recomenda, no entanto, que voce somente use esse recurso para testes e desenvolvimento internos, e nio pata software que pretenda distribuir.
6

Nio

deJava.

oBSERVAQoBS pene O EXAME


para classpaths hngu. O cksspath de alguns arquiuos JAk no J2SE dun tipo ao se defnir aru clatrpath. Se uoei uir algo como 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
E possiuel criar aaridueis
de ambiente

queforne(am //m

nome-cridigo

pode rcr bastante extenso, defonna qae

comum ilsar ilm nome-aidigo

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 importpara interagir com (atrauis do ace$o ou da herangQ o aidigo do exempl0.
est6ticas para este capinrlo.
de pacotes e

in$rapdet

Observag6o: No Capinrlo 1, n6s abordamos a maior parte do que estd definido neste obietq mas deixamos as importag6es

lmportag6es Est6ticas
N6s vimos usando instug6es import ao longo de todo o livro. No fim das contas, o finico valor que as instrug6es import tm 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

i
Depois das importag6es est6ticas:

import stat.ic java. lang. System.out; import static java. 1ang. Integer. *;
.i hl'1^'1 rU^ I/UUf LrdDD ^'l --^ r^^n.qf rf i nTmnnrt ICDLOLdLIUTTTLIJUT L I I {

// t // 2

public static void main(String[] args) out.printl-n (MAX VALUE) ; out . prj-ntln (toHexst.ring (42) ) ;
)

//

l t
Ambas as classes produzem 2747 483647
a

mesma saida:

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

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

A sintaxe deve ser

import sEaLic; static import est6incorreto. 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.

Epossivelfazerwma'tmportagdoest6ticaemrefernciasaobjetosstatic,constaotes(embre-sequeelassio

static

final-).

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-..rtoJriopara o elemento 1 e assim por diante. argumento vai
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,


em seus Pfogfamas.

as

importag6es est6ticas. Esse 6 um recurso aPenas

deconvenincia,quereduzanecessidadedesedigitarnomeslongospa:amernbtosstatic

dasclassesquevoc6usar

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.
o-ruz do pacote i6

E
fl tr

Aopgio
exisa.

- d pode criat, automatjcamente, classes de destino dependentes do pacote, caso o diret6ri

Use aopgdo -Demconjuntocomocomando exemplo,

java

quandoquisetdefinirumapropriedadedesistema.

As propriedades de sistema consistem de pares de nome = valor que devem ser anexados diretamente ap6s -D, por

j ava -Dmyproperty=myvalus.

tr

Os argumentos de linha de comando sio sempre tratados como Strings.

O argumento de linha de comando java nfmero elemento 1, e assim por diante.

16

colocado no elemento 0 do array; o argumento 2 colocado no

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 vm 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
O

Pode-se declarat um classpath na linha de comandq e ele substirui o classpath padrio.

Um mesmo classpath pode definir muitos locais de busca diferentes. Em classpaths do Unix, sio usadas batas (/)
usadas barras invertidas

0 E
D
El

p^x

sepzu:^r

os diret6rios que compSem um caminho. No rVindows, sio

(\).

Em Unix, sio usados dois-pontos (:) panseparar os caminhos dentro de um classpath. No Windows, sio usados
pontos-e-virgulas (r.

Em um classpath, para especificar o diret6rio atual como local de busca, use um ponto Em um classpath , uma vez encontrada uma classe, busca 6 importante.
a busca 6

(.)

interrompida, de modo que a ordem dos locais de

Pacotes e a Procura (Objetivo 7.5)

E E D

Quando uma classe Uma instrugdo

colocada dentro de um pacote, deve ser usado o seu nome totaLnente qualificado.

import

fornece um nome-c6digo para o nome totalmente qualificado de uma classe.

Para que uma classe possa ser localizada, o seu nome estrurura do diret6rio onde ela reside.

toalmente qualificado deve ter um relacionamento intimo com a

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.

Parafazer testes, voc6 pode colocar arquivosJAR de diret6riosJava na sua mdquina.

em - . . /

jre/l-ib/

ext,que fica em algum lugar dento

da drvore

lmportag6es Estiticas (Objetivo 7. | ) B Voc6 deve comegar uma instrugio de importagdo estitica desta forma: import static E Vocpodeusarimportagdesestiticasparaciaratalhosparamembrosstatic (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.*; class Needy3 { public static void main(Srringll args) xcom.Useful u = new xcom.UsefulO; System.out.println(u. increment (5) ) ;
)

// linha
{

l"

// Iin}ra

Quais afirmativas sio verdadeiras? (I\4atque todas as cortetas)

Asaida60.

B. Asaida65.

444

Copitulo

l0:

Desenvolvimento

C. Asafda66. D. Acompilagtrofdha.

E.

O c6digo compila se a linha 1 fot removida. O c6digo compila sealinha2formodificadapara

Useful u = new UsefulO; 2. Dada


or9
a seguinte

estrutura de diret6rios:

| -- Robot.cl-ass
I

I -- .*
|
I

-- Pet.class

-- 'hv
|

-- oos.class
|
1

E o seguinte arquivo-fonte:
^1 ^-^ urdss ^"--^1 ^-^ rYryvrdsE

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

445

class _ { static public void main(String. . . _A_V_)


Cf rin^ vut^rr: < Y N/.

or

int

x=0

++x

g += _A_V_[xl;

" _A_v_.length;

out.println($);
) )

linha de comando:

java_-A
Qual 6 o resultado?

A- -A B. A. C. -1. D. -A.
E. _-A.

E
G.

Acompilagdofalha.
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
i arr: n Il
'i elra e

depois chamat

B. Definir

o diret6rio arual como xcom e depois chamar

javac -classpath javac -classpath


D. Definir

B.java
e

C. Definit o diret6rio atual como test


o diret6rio atual como

depois chamar

xcom/B. java

test e depois chamat javac -classpath xcom B.iava


chamar

E. Definir o diret6rio arual como Eest e depois 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*
B.

25 30 36

c.
E

D. Acompilagdofalha.
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 / todas as coretas)

/ insira o c6digo aqui,

permitir6 que todos os trs arquivos compilem? @larque

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

chamada de linha de comando:

java -Daaa=ccc TestProps


O que 6 sempre verdadeiro? (trIarque todas
as

correas)

.d
B. D. E.

O valot da propriedade aaa 6 aaa

O valor da prcpriedade aaa 6 bbb.

C. O valor dapropriedade aaa 6 ccc.


O valor daptopriedade bbb 6 aaa. O valor dapropriedade bbb 6 ccc.

A chamadando frnalizat6 sem erros.

10. Se existirem tr6s vers5es de MyClass.iava em um sistema de arquivos:


Avetsio 1em Aversio
Aversio
2
3

/foo/bar
foo/bar /baz

em /

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

O resultado nlo

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 dtvore de diret6rios J2SE.

j ava, mas nio com o comando j avac,


extdentroda

C. Parapoderemserusadospor java,osarquivosJAR deuemsercolocadosnosubditet6rio / jrellibl

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) { -,,L1 vq!f,ru ^r^r:^ String s = new Kit O .gluelt (args [1] , args [2J ) ; System. out.println (s) ;

)
)

a seguinte

estrutura de subdiret6rios:

t--

|
I

--useK].f'.cIass
com

l--Kr-t.uar.lar
Se o

ditet6rio atual for test, e o arquivo pkg/Kit . cl-ass estiver em produzirS,a saida bc? O4arque todas as corretas)

Kit,far. j ar, qual linha de comando

A. java B. java C. java D. java E java F. java G. java FI. java

UseKit b c UseKit a b

-cl-asspath com UseKit b c -classpath com:. UseKit b c -classpat,h com/Kit,Jar. jar UseKit b c -classpaLh com/KitJar.jar UseKit a b c -classpath com/Kit,far.jar:. UseKit b c

-classpath com,/KitJar.jar:. UseKit a b

Respostas do Teste Individual


'l'.
D est6 cotreta. O m6todo A
e

increment ( ) deve ser matcado


(

com public para ser acessado fora do pacote. Se incre-

mentQ fosse public, C, E e F estariam corretas.

B sio saidas incorretas, mesmo se increment

) for publ i c. (Objetivo 7.1)

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

B, D

F estlo incorretas com base no exposto acima. (Objetivo 7.1)

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

estio incorretas com base no exposto acima. (Obiewo7,2)

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

6.

est6 corteta. Para importar membros estAticos,


e

instrugZo import deve comegar com: import static.

A, B, C
7.

E estio incorretas com base no exposto acima. (Obietivo 7.1)


6

A est6 cotreta. -D nio


sem espagos.

um flagde compi-lagio,

eo

parnome = valor associado com -D precisavirlogo depois de -D,

B, C
8.

estao incorretas com base no exposro acima. (Objetivo 7.2)

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

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


6 definido na linha de comando. Se aaa nio tivesse nenhum valor ouando foi chamado, entio aaztena sido definido como bbb.

C est6 cotteta. O valor de aaa

get Property
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
11.

E estio incorretas com base no exposto acima. (Objetivo 7.5)

AeDesteocoffetas. B esti incorreta porque


localizados em . . . /

tambdm pode usar arquivosJAR. C est6 incorreta porqueJARs podem estar mas eles tambEm podem ser acessados se residirem em outros locais. E esti incorreta, os arquivosJARmantm estruturas de diret6rios. (Obietivo 7.5)

jre / Iib / ext,

j avac

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

,it!,i

Ap6ndice A

Sobre os stqulvos

dlsponlvels poro donwlosd

..

:":

ij: "

452 Ap6ndice A
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.

Os

Requisitos do sistema
O software requer o \X/indows 98 ou superior, o Internet Explorer 5.0 ou superior instalagio completa.
e 20

MB de espago no disco rigdo pan

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, referncias 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 tegressivaatzero 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 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 ao

contefdo t6cnico do livro elet6nico ou do MasterBxam, visite o site www.osborne.com ou mande uma mensagem (em ingls) 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