java - scjp 5 - portugues

480
Elogios ao Guia de estudos para programador e desenuoluedor em Jaua 2 certif cado pela S an@ "Kathy Sierra 6 uma das poucas pessoas no mundo que consegue fazer coisas complicadas parecerem murto simple;. E como se isso nio fosse suficiente, ela consegue fazer com que assuntos mon6tonos paregam interessantes. Sempre fico ansioso para ler o que Kathy escreve - ela 6 uma de minhas autoras favoritas". - Paul IYheaton, Chefe de Aconpanbamento da JauaRanch.com "Quem melhor para escrever um guia de estudos sobre Java do que Kathy Si_err.a, que reina soberana quando se trata de treLamento emlava? Kathy Sierr-a conseguiu novamente - aqui est6 um guia de estudos que j6 poder6 lhe garantir a cenifica$o!" - Jamu Cabeta, Engenheiro de Sistenaq SCI "O que mais aprecio em Kathy 6 seu esforEo p arafaznr comque todosnos lembremos de que estamos ensinando pessoas . nio aoenas fa"endo uma palestra sobre Tava. Seu entusiasmo e vontade em oferecer um treinamento da mais alta ffi;#i. frffi;; #.##T; i; ;;;, ;;; .. rreza nio encontra paralelo na sunEd. s.* a""iar, h6 centenas de I alunos que se beneficiaram de terem assistido a suas aulas" . - i ,1 - Victor Peters, fandador da Next Snp Education e Inslrutor Certifcado Jaua pela Sun q "Quero agradecer a Kathy pelo EXCELENTE guia de esudos. O livro 6 bem.escrito,.informa especificamente o que voc6 aJq. ri'U.r.ro.*"-..."d,conceito 6 explicaio de maneiraclaracom autilizagio deum exemplo davidareal' Da **Jira orr. foi escrito, voc6 se sentir6 em uma sala de aula como se algu6m estivesse realmente lhe ensinando os conceitos diiil;;; "ilde maneiraformal e fria. As perguntas no final dos capftulos tamb€m slo MUTIo boas e estou certo de que aju&rio os candidatos a passarem no tesi. Fique alerta para esse livro incrivelmente astuto". - Atfred RaouJ Desenuoluedor de Solugdu na IYeb i O exame de certificagio da Sun cerramente nio foi como um passeio no parque' mas o material de Kathy permitiu nio s6 que eu Passasse no exame, mas que passasse bem!" - Mary lqhetsel, Etpecial^ta S1nior em Tecnologla, Integragdo e Estrategla de Aplicagdes, Tbc St. Paal Corapaniet "Ben demonstra uma aptidio comprovada e fantistica de transformar com-plexidade em simplicidade ao oferecer um percurso dirigido no aprendizado do que 6 necessirio para o exame da certificaqXo". - Thomas Bende6 Presidente, Gold Hi// Sofnaare Desing, Inc' "por sua habilidade em expressar claramente conceitos complexos aos que assistem a seus treinamentos' todos os alunos cons€guem se tornar especialistas no que Ben tem a ensinar". - DauidNdgq Diretor Geral, Ndge Astociatet "Achei este livro exrremamente 6til para ajudar o candidato a passar no exame. Ele foi muito bem escrito, com a qtrantidade ideal de come"."ri"r b.*-ftJ-oi ^Cit p"At*r. .or' qrr. .'oo.? se esquega de que est6 estudando Para um teste tio dificil' ALTAMENTE RECOMENDADO!" -Nico/e Y. McCallough *Nunca me diveni tanto lendo um livro r6cnico quanto no caso deste aqui... Hoje de manhi, fiz o exame SCJP e consegu,i ecertar 980/o(60 de 61). Esse sucesso nio teria sido possivel sem este livro!" -Yaie Nagornl ,,EvfizoSCJp 1.4 emJulho de 2004 e consegui 957o (58/.6l).Kathy e Ben t6m um estilo incrivel de escrever' e literdmente-grav"ra- ot.o.t..itos principais na minha cabega." -Bhsshen P. Madan (Kansas, Estadot Uildos) (

Upload: marcos-lordelo

Post on 05-Aug-2015

1.049 views

Category:

Documents


8 download

TRANSCRIPT

Page 1: Java - Scjp 5 - Portugues

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

"Kathy Sierra 6 uma das poucas pessoas no mundo que consegue fazer coisas complicadas parecerem murto simple;. E

como se isso nio fosse suficiente, ela consegue fazer com que assuntos mon6tonos paregam interessantes. Sempre fico

ansioso para ler o que Kathy escreve - ela 6 uma de minhas autoras favoritas".

- Paul IYheaton, Chefe de Aconpanbamento da JauaRanch.com

"Quem melhor para escrever um guia de estudos sobre Java do que Kathy Si_err.a, que reina soberana quando se trata de

treLamento emlava? Kathy Sierr-a conseguiu novamente - aqui est6 um guia de estudos que j6 poder6 lhe garantir a

cenifica$o!"

- Jamu Cabeta, Engenheiro de Sistenaq SCI

"O que mais aprecio em Kathy 6 seu esforEo p arafaznr comque todosnos lembremos de que estamos ensinando pessoas

. nio aoenas fa"endo uma palestra sobre Tava. Seu entusiasmo e vontade em oferecer um treinamento da mais alta

ffi;#i. frffi;; #.##T; i; ;;;, ;;; .. rreza nio encontra paralelo na sunEd. s.* a""iar, h6 centenas de I

alunos que se beneficiaram de terem assistido a suas aulas" . - i,1

- Victor Peters, fandador da Next Snp Education e Inslrutor Certifcado Jaua pela Sun q

"Quero agradecer a Kathy pelo EXCELENTE guia de esudos. O livro 6 bem.escrito,.informa especificamente o que voc6

aJq. ri'U.r.ro.*"-..."d,conceito 6 explicaio de maneiraclaracom autilizagio deum exemplo davidareal' Da

**Jira orr. foi escrito, voc6 se sentir6 em uma sala de aula como se algu6m estivesse realmente lhe ensinando os conceitos

diiil;;; "ilde

maneiraformal e fria. As perguntas no final dos capftulos tamb€m slo MUTIo boas e estou certo de

que aju&rio os candidatos a passarem no tesi. Fique alerta para esse livro incrivelmente astuto".

- Atfred RaouJ Desenuoluedor de Solugdu na IYeb i

O exame de certificagio da Sun cerramente nio foi como um passeio no parque' mas o material de Kathy permitiu nio s6

que eu Passasse no exame, mas que passasse bem!"

- Mary lqhetsel, Etpecial^ta S1nior em Tecnologla, Integragdo e Estrategla de Aplicagdes, Tbc St. Paal Corapaniet

"Ben demonstra uma aptidio comprovada e fantistica de transformar com-plexidade em simplicidade ao oferecer um

percurso dirigido no aprendizado do que 6 necessirio para o exame da certificaqXo".

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

"por sua habilidade em expressar claramente conceitos complexos aos que assistem a seus treinamentos' todos os alunos

cons€guem se tornar especialistas no que Ben tem a ensinar".

- DauidNdgq Diretor Geral, Ndge Astociatet

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

ideal de come"."ri"r b.*-ftJ-oi ^Cit

p"At*r. .or' qrr. .'oo.? se esquega de que est6 estudando Para um teste tio dificil'

ALTAMENTE RECOMENDADO!"-Nico/e Y. McCallough

*Nunca me diveni tanto lendo um livro r6cnico quanto no caso deste aqui... Hoje de manhi, fiz o exame SCJP e consegu,i

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

-Yaie Nagornl

,,EvfizoSCJp 1.4 emJulho de 2004 e consegui 957o (58/.6l).Kathy e Ben t6m um estilo incrivel de escrever' e

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

-Bhsshen P. Madan (Kansas, Estadot Uildos)

(

Page 2: Java - Scjp 5 - Portugues

"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 trabalhomagnifico ao apresentar os fatos imponantei qe

"oc6 pricisar6 sabei para o exame, ao mesmo rempo deixaram de lado

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 insightsobre a verdadeira natureza do que vocA.encontrari no exame. Ao contririo de muitos outros guias de cenificagio. Esti aqui6 uma leitura p razerosa. Neste livro, at6 os mais enfadonhos objetivos da Sun sio combinadoi com um revigo.*t. bo.ri-humor."

-Vad Fogel (Onlaia, Canadi.l

Page 3: Java - Scjp 5 - Portugues

Ceftificagdo Sun@ paraProgramador fAVA 5

Guia de Estudo(tuame 310-055)

lGthy Sierra

Bert Bates

Page 4: Java - Scjp 5 - Portugues

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 escritoda 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 assumemresponsabilidade pelos resultados e usos da informagdo fornecida. Recomendamos aos leitores testar a informagdo bem como tomartodos os cuidados necess6rios (como o backup), antes da efetiva fiilizagdo. Este livro n6o contdm CD-ROM, disquete ou qualqueroutramidia.

Produgiio Editorial: Editora Alta BooksCoordenagflo Editorial: Fernanda SilveiraThadugiio: Marcelo SoaresRevis6o: Fernanda SilveiraRevisEo T6cnica: Leonardo Rota-RossiColaboragflo T6cnica: Gabriel Fairbanks, Leonardo Gangemi eAnderson XavierDiagramagiio : Aldenir Gil

Erratas e atualizag6es: Sempre nos esforgamos para entregar a voc6 leitor um livro livre de erros t6cnicos ou de conteido, por6m nemsempre isto 6 conseguido, seja por motivo de alteragilo de software, interpretagdo ou mesmo quando alguns deslizes constam naversdo original de alguns livros que traduzimos. Sendo assim, criamos em nosso site www.altabooks.com.br a seg6o Erratas, onderelataremos, 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 responsabilidadede seus proprietiirios. A Editora informa n6o esfar associada a nenhum produto e/ou fomecedor apresentado no livro. No decorrerda obra, imagens, nomes de produtos e fabricantes podem ter sido utilizados e desde j5 a Editora informa que o uso 6 apenasilustrativo 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 detentoresdo direito autoral da obra, bem como a c6pia ilegal do original. Esta pratica generalizada nos estabelecimentos de ensinoprovocam 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 ailltima. Essa publicaqdo pode ser usada como auxllio na prepqraqdo dos alunos para o exame de certificagdo da Sun emJava 2. Nem a Sun Microsystems ou a McGraw-Hill/Osborne garqntem que o uso dessa publicagdo assegurard sucesso noexame em questdo. Sun, Sun Microsystems e o logotipo da Sun sdo marcas registradas da Sun Microsystems.Inc. nos EstadosUnidos e em outros paises. Java e todas as marcas relacionadas sdo marcas registradas da Sun Microsystems Inc. nosEstados Unidos e em outros paises. A McGraw-Hill/Osborne ndo tem ligaqdo com a Sun Microsystems, Inc.

Rua Viriva Claudio,29l - JacaftRio de Janeiro - RJ. CEP: 20970-031

TeI: 21 3278-8069/ Fax: 21 3277-1253ww.altabooks.com.br

e-mail: [email protected]

ESeitrrRl*|Ewu{w.osborne.Eorn

Page 5: Java - Scjp 5 - Portugues

JAVA 5 V

ParaaComtrnida&Java

Page 6: Java - Scjp 5 - Portugues

Sum6riocapirulo | - DEclAnag6es E coNTRoLE DE AcEsSo.................................... I

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

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

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

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

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

Outros Modificodores de Closses (N6o-re{erentes o Acesso) a

Exercicio l- | Criando uma Superclasse Abstrata e uma Subclasse Concreta .....' | 0

Objetivo paraaCertificag6o............ .......... llDeclarar lnterfaces (Objetivos l. I e 1.2 do Exame) ............. .'........ I I

Objetivo para a Certifi cagio ............Declarar Membros de Classes (Objetivos 1.3 e 1.4) ............ ........... 14

Membros Protecl e Defoult ....... 19

Deiolhes de Protect ................. nDetolhes de Deioult....Vori6veis Locois e Modificodores de Acesso ..................... 23

Argumentos Finol ...........M6todos AbsM6todos Synchronized ..'.......... 27

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

Declorondo Primitivos e Iniervolos de PrimitivosDeclorondoVori6veis de Refer6ncio ............. 30

Voridveis de Instdncios ...........' 30

Vori6veis Locois (Automotic/Stock/Method) ......... ........-.... 3lDeclorog6es de Arroys ..........'.. 33

t4

Page 7: Java - Scjp 5 - Portugues

JAVA 5 VII

Voridveis e M6todos Stotic.........'.. ................ 35

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

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

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

Objetivo para a CertificagioHeranga, E-Um, Tem-Um (Obletivo 5.5 do Exame) .....52

Relacionamentos E-Uy e TEM-UM ............55

Objetivo para a Certifica9io.............. ........58Polimorfismo (Obietivo 5.2 do Exame) .......58

Objetivo para a Certi{ica9io............ ..........60Subscrevendo / Sobrecarregando (Obfetivos 1.5 e 5.4 do Exame) ................... 60

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

Sobrecorgos v6lidos ................ &Chomqndo m6todos sobrecorregodos ............. ................ 65Polimorfismo em m6todos sobrecorreqodo e subscrilo ....... &

Objetivo para a Certificagio ............ ,.............68Conversio de Vari6veis de Refer6ncia (Objetivo 5.2 do Exame) ....68

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

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

Objetivo para a certificag6o .............Tipos de retorno v5lidos (obfetivo 1.5 do exame) ........74

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

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

Objetivo para a certificag6o ............. .........77Construtores e instanciaEio (Objetivos I .6 e 5.4 do exame) .........77

Aspeclos bdsicos do construtor .................... 77Codeiqdeconslrulores................. ..............77Regros dos construtores .............. ................ 78

ldentifcando se um construComo voc6 pode ter o certezo de que um conslrutor podr6o ser6 criodo? ................ 79

O que oconlecer6 se o conslruiuor do superclosse tiver orgumentos?........... ..........80

74

Page 8: Java - Scjp 5 - Portugues

vlll

Objetivo para a Certificagio

Vori6veis e m6todos stotic .......... ................. 85

Acessondo vori6veis e m6todos stotic ........... ................... 85

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

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

Pilha e Heap - Uma Revisio .... 102

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

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

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

Literois

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

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

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

Usando umavari6vel ou elemento de array que nlo tenha sido

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

Voridveis de instdncio primitivos ................. 1.l3

Vori6veis de insi6ncio de refer6ncio o obietos ..........-....... I 13

Vori6veis de instdncio de orroy ................... I 14

Tipos primitivos e obielos locois (de pilho, outom6ticos) ...................... I l5

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

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

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

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

Objetivo para a certificagio ...122DedaraEio, construgao e inicializaEio de arrays (objetivo 1.3 do exame) ..... |-22

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

Construindo orroys unidimensionois ...........123Construindo orroys multidimensionqis .........124

Page 9: Java - Scjp 5 - Portugues

JAVA 5 IXlniciolizondo elementos em um loop ........... ...................126Declorondo, construindo e inciolizondo em umo linho .......... .............126Construindo e iniciolizondo um orrov on6nimo ...........127AtribuiEoes v6lidos poro os elemenlos do orroy . .............128Arroys de tipos primitivos ............... ............ l2BArroys de referGncio o obietos ....................129AtribuiE6es de vori6veis de refer6ncio de orroys unidimensionois .............. ...............

.|30

Atribuigoes de vori6veis de re{er6ncio de orroys multidimensionois ............ .............. '130

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

Objetivo para a certificagio .............Usando classes wrapper (Objetivo 3. I do exame)

Osconstrutoreswrqpper .........133Os m6todos volueOf0 ... ... ............. ]34

Usando os utilitidos de conversio das classes wrapper .............. | 34

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

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

Boxing, ::, e equolsfl .......... 137Onde Pode ser Usodo o Boxing .................. l3B

Objetivo para a Certifica96o............ ........ | 39Sobrecarregando (Objetivos 1.5 e 5.4 do Exame) ...... 139

Sobrecorregondo do Moneiro Di{icil- Correspond6ncio de M6todosSobrecorgo com Boxing e Vor-orgsAmpliondo Vori6veis de Refer6ncioSobrecorgo no CombinoE6o de AmplioE6o com BoxingSobrecorgo em CombinoE6o com Vor-orgs

do exame) .... 143

Vis6o total do gerenciamento da mem6ria e da coleta de lixo ............... ............ 143

Quondo o coletorde lixo 6 execulodo? ............ ..............144Como o coletor de lixo funciono? ..144

Escrevendo um c6digo que torne os objetos explicitamente qualificados

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

Objetivo para a certificageo ..........Operadores Java (Objetivo 7.6 do exame) .................. 162

Operodores deAtribuiE6o ......162Operodores de Atribuigdo Compostos .........162

t33133

r39r40141

141

142

Objetivo para a certificagioColeta de lixo (Objetivo 7.4

Page 10: Java - Scjp 5 - Portugues

x

lguoldode de tipos pdmilivos ...........'..'..-..'164lguoldode de vori6veis de referGncio ..."...... 165

lguoldode poro Enums r65Operodorde comporog6o inslonceo{ .......... 166

Erro de CompiloE6o de instqnceof ................. ...............-167

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

Operodor de concotenoE6o de stringsAcr6scimo e decr6scimo ......... ]70Ooerodor condicionol. ..........'171Operodores L6gicos ...............172Operodores Bitwise (N6o Coem no Exome!) ...................172OperodoresL6gicosdeAbrevioE6o................ .....'........'172Operodores l6gicos (que n6o s6o de obrevioE6o) ...........174Operodores L6gicos ^ e !........... ..............174

Resumo para a certificagio

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

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

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

Breokeopossogemcompletoemblocosswitch......... .....190A instruE6o cose defoult .........192

Exercicio 5- | Criando

Objetivo para a certificagio ... 193

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

O LoopforBdsico .................,l95LoopforBdsico: Declorog6oeiniciolizoE6o................ .....|95Loop for Bdsico: Express6o condicionol (booleono) .........

.|95

LoopforBdsico: Express6ode iterog6o.. ......196LoooforB6sico:Corocleristicosdolooofor.............. ......196O Loop forAprimorodo (poro Arroys) .........197

Objetivo para a certificagioManipulando exce96es (objetivos 2.4 e 2.5 do exame) ................. 20 |

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

Page 11: Java - Scjp 5 - Portugues

JAVA 5 XI

Objetivo para a Certifica9io.............. ......214Erros e ExceE6es Comuns (Objetivo 2.6 do Exame) ...................214

De Onde V6m os ExceE6es .....214Exceg6es LonEodos pelo JVM .....................214ExceE6es LonEodos Progromolicomente ......... .................215Um Resumo dos ExceE6es e Erros poro o Exome .............215

Objetivo para a certificagio ...216Ti'abalhando com o mecanismo de assertivas(Objetivo 2.3 do exame) ..........216

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

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

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

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

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

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

Strings s6o obietos inolter6veis ...................238Fatos importantes relacionados aos objetos String e a mem6ria .......................24 |

Criondo novos slrings ............242M6todos importon'les do closse String......... ..............242

StringBufferx StringBuilder ......244Usondo StringBuffere StringBuilder .............245

M6todos importantes das classes StringBuffer e StringBuilder ......245

Objetivo para a Certificagio.. 246NavegaEio de Arquivos e E/S (Objetivo 3.2 do Exame) ...............246

Criondo Arquivos com o Closse File ............. .................247Usondo FileWriter e FileReoder ..................249Combinondo Closses de E/S ......................250Trobolhondo com Arquivos e Direi6rios .......252

Objetivo para a Certifica9io.............. ......254SerializagSo (Objetivo 3.3 do Exame) ........254

Page 12: Java - Scjp 5 - Portugues

xilTrobolhondo com ObiectOutputStreom e ObiectlnputStreom ................255Gr6ficos de Obietos ...............256Usondo wrileObiect e reodObieci ............... 258

Como o HeronEo Afeto o Seriolizog6o .........260A SeriolizoEoo n6o 6 poro Est6ticos ................ ...............262

para a Certificasio..............Nrimeros e Moeda (Objetivo 3.4 do Exame) ...263

TrabalhandoOrquestrondo Closses Relocionodos o Dotos e Nimeros .... ...............263

A Closse Colendor .................265A Closse DoleFormol .............266

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

Objetivo para a Certificagio............ ........27 |

Parsing, Tokenizag6 e Formatagao (Objective 3.5 do Exame) .......271

Buscqs Usondo Melocorocreres ......................., ,,,,.........'273Buscos Usondo Quqnti{icooores ................O Ponto Pr6-definido .............275Quonti{icodores Gononciosos.............. ......275Quondo Metocorocleres e Strings Colidem .....................276

Locaf izando Dados atrav6s da Correspond6ncia de Padr6es... ....277

Tokens e Delimitodores ................ ..............279Tokenizondo com String.splitfl ......... ......279Tokenizondo com Sconner ..............280

cApiTuLo7-GENfRlcosEcoNfuNToso.........o...o.ooo......o.o...................oo........zgs

Objetivo para a certificagio ............. .......296Subscrevendo hashCode( ) e equals( ) (objetivo 6.2 do exame) ...296

O que significor6 o n6o subscriEdo de equolsfl ... ....... . ...............297lmplemenlondo um m6fodo equols( ) .. ...............298O conlroto de equols( ) ................. ............300

Entendendo os c6digos de hoshing ............300lmplementondo hoshCodefl ................ ......30'lO conlroto de hoshCodefl ... ........302

Objetivo para a certificag6o ............. .......304Conjuntos (Objetivo 6. I do exame) .......... 304

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

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

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

ObjetivoDatas,

Page 13: Java - Scjp 5 - Portugues

JAVA 5 XIII

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

Clossificondo Coleg6es ....... . . . 3l OA Interfoce Comporoble ................... 312Clossificondo com Comporotor .............. ....3j3ClossificondocomoClosseArroys........ .....315Fozendo Buscos em Arroys e em Coniuntos .............. ......315ConverJendo Arroys em Listos e de Voltq em Arroys ..........3j7

Usondo o Cfosse PriorityQueue ................... ..................322Vis6o Gerql dos M6iodos poro Arroys e Coniuntos. .....32gVisSo Gerql dos M6todos poro Lisl, Set, Mop e Queue...... ..............324

Objetivo para a Certificagio ..........32sTipos Gen6ricos (Objetivos 6.3 e 6.4 do Exame) .........325

Criondo o suo Pr6prio Closse Gen6rico ......342Criondo M6todos Gen6ricos ......................345

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

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

lnslonciondo umo closse interno ................3UReferenciando a instincia interna ou externa de dentro da classe interna ...........365

Objetivo para a certificagio ...366Classes internas locais de m6todo .............366

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

ObjetivoClasses

Para a ceftificagao .............internas an6nimas ........369

Objetivo para a certificagio ...373Classes est6ticas aninhadas ....... 323

................ 368

Page 14: Java - Scjp 5 - Portugues

xtv

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

Objetivo para a certificagSo ............. .......384Definindo, instanciando e iniciando threads(Obletivo 4. I do exame) .......... 384

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

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

Criando

Objetivo para a certificagio ............. .398Sincronizando o c6digo (Objetivo 4.3 do exame) ....... 398

O oue ocontecer6 se um threod n6o puder obter o bloqueio? """"'405Ent6o, Quondo Eu Preciso Sincronizor? ..."' 405

Closses Seguros em ReloEdo o Threods """' 407

Objetivo para a certificagio .............lnteragio entre os threads (Objetivo 4.4 do exame) "409

Usando notifyAll( ) quando houver a possibilidade de muitos threads estarem esperando ...'.4 | 3

Usondo woit( ) em um Loop " " 414

Exercicio 9-l: Criondo um threod e coloconoo-o em suspensfio..........'... """""""'428Exercicio 9-2: Sincronizondo um bloco de c6digo ..""""' 429

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

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

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

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

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

Declorondo e Usondo Closspoths """""""' 436

Pocoleseo Procuro """""""'436

Page 15: Java - Scjp 5 - Portugues

JAVA 5 )ryCominhos Relotivos e Absolutos ...... ....438

Objetivo para a Certifi cagio .............. 439Arquivos JAR (Objetivo 7.5) .....439

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

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

APENDICE A..o..o.......o............................................................................................... 45 |Requisitos do sistema ...............452

lnstalando e executando o MasterExam ....452

Suporte t6cnico ......452

Page 16: Java - Scjp 5 - Portugues

xvl

Sobre os Colaboradores

Sobre

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 recordistasdevendassobreJavaji receberam v6rios prAmios da revista Sofrware Development Magazine, e ela 6 tamb6m membrofundador do programa

Java Champions da Sun.

Bert Bates tem sido desenvolvedor-lider de virios exames de certificagio da Sun, incluindo o SCJP paraJava 5. Ele tamb6m6 moderador de um f6rum emJavaranch.com, e tem desenvolvido softwares por mais de 20 anos. Bert 6 co-autordediversos livros recordistas de vindas sobreJava, e 6 membrofundador do programaJava Champions da Sun.

a Equipe de Revisio T6cnica

Johannes deJong tem sido o lider das nossas equipes de revislo t6cnica por muito, muito tempo. (Ele tem mais paci6ncia

do que qualquer pessoa qrre conhecemos.) Neste livro, ele liderou a maior equipe que j6 formamos. Nossos sinceros

"gmd..i-entot "or t"goitttes volunt6rioi, que foram inteligentes, trabalhadores, pacientes e muito, muito detdhistas!

Rob Ross, Nicholas Cheung, Jane Griscti, Ilja Preuss, Vincent Brabant, Kudret Serin, Bill Seipel Jing Yr' GinuJacobGeorge, Radiy4 LuLrrr-MazaAnshu Mishia, Anandhi Navaneethakrishnan, Didier Varon, Mary McCartney, Harsha

Pherwani, Abhishek Misra e Suman Das.

Sobre o LearnKeyO karnKey fornece conrerido de aprendizado que respeita o ritmo do aluno, e apresenta solug6es de distribuigio de

muldmidia para aprimorar habilidades pessoais e produiirridade empresarial. O_ LearnKey apresenta a maior biblioteca de

conterido di treinamento multimidia existent., "'q.r"l

fottt.." "o, "irrrro,

rlm dinAmico aprendizado, rico em diversas

midias, como videoclips, 6udio, grificos totalmenfe animados e ilustrag6es animadas. O site do LearnKey na web 6

www.kamKey.aorrl

Os Astros da Revisio T6cnicaNio sabemos quem trabalhou mais, mas podemos contar as edig6es feitas por cada revisor (e o fizemos!) - entio, na ordem

de mais edig6es feitas, n6s orgulhosamente apresentamos os nossos superastros.

Em primeiro lugar, as 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).

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!

Page 17: Java - Scjp 5 - Portugues

JAVA 5 )O/II

AgradecimentosKathy e Bert gostariam de agradecer as pessoas a seguir:

r Topas 1s egssoas incrivelmente esforgadas da Osborne: Tim Green, Jim Kussow, Jody McKenzie e Jennifer Housh por

toda.a ajuda e por serem tXo compreensivas e pacientes - bem, certo, nem tio pacientes assim - mas muitoprofissionais e o grupo mais agrad6vel de pessoas com quem sepoderiaesperartrabalhar.

I Os nossos anjos Solveig Haugland e Midori Batten, por virem nos salvar quando realmente esr6vamos em apuros!

r Akuns dos profissionais de software e amigos que nos ajudaram nos dias iniciais: Tom Bender, Peter Loerincs, CraigMatthews, Dave Gustafson, konard Coyne, Mbrgan Poner e Mike Kavenaugh.

r Acima de tudo, a maravilhosa e talentosa equipe de cenificagio da Sun Educational Services, principalmente o Gerentedo Progtama de Cenificagio, Steve ('Gooie') Moore e a pessoa mais persistente que ji conhecemos quando se trata decondrsio, Evelyn Cartagena (paraMnspelo rec6m-nascido, Evelyn).

-

r Nossos melhores amigos e especialistas emJava, Bryan Basham, Kathy Collina e SimonRoberts.

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

r O chefe doJavaranch Trail, Paul \(heaton, por manter a melhor comunidadeJava da Internet.

I Todos os outros instrutores antigos e atuais de Java da Sun Ed por aju&rem a torn ar o aprendizado dessa linguagemum1 expel6nciadivenida, _incluindo (para nomear apenas alguns) : Alan Petersen, Jean Tordella, Georgianna MJa$ier,Antho-ny Orapallo, Jacqueline Jones, James Cubeta, Teri Cubaa, Rob '$7eingruber,

John Nyquist, AsJk Perumaiiar,Steve Steltin_g,\a;reZaffery, KimberlyBobrow, Keith Ratliffe o conhecedordeJavamais dedicado einspiradordoplaneta,,JariPaukku.

r Darren e Mary, obrigado por nos manter sios e por nos ajudar com os nossos novos amigos peludos, Andi e Kara.

r Finalmente, Eric e Beth Freeman pelo incentivo continuo.

Page 18: Java - Scjp 5 - Portugues

)o/il1

PreficioO principal objaivo deste liwo 6 ajud6-lo a se preparar e passar no exame de cenificagio SCJP da Sun Microrystems referente

aJava 5. A boanoticia 6 que o exame tende a "borda.

t6picos que a maioria dos desenvolvedoresJava encontrarlo nos seus

tiabalhos. A noticia desafiadora 6 que o exame Java 5 tem escopo bem mais amplo do que o seu antecessor, o exame Java1.4. Os novos objetivos passam poi muitas das-APIs mais utiliiadas emJava. A palavri-chave aqui 6 "passam por". Aintengio dos criadores io ex"*. foi qn

" "provagXo representasse a certeza de que o candidato ente nde osfundanenns de

APIs, tais como aquelas usadas para E/S diarquivos e express6es regulares. Este livro segue o miximo psssivel tanto o

escopo quanto a profundidade do exame real. Pbr exemplo, ap6s ler este livro voc6 provavelmente nXo vai acordar no outro

di" *-b ,rtn go* d. ,.gr*, mas, se estudar o material, e sair-se bem nos testes individuais, voc6 ter6 um entendimento

bisico de regei e se sairilemno exame. Depois de terminareste livro, voc|tericeneza de que estudoutodos os objetivos

estabelecidos pela Sun para o exame.

N este livroEste livro foi organizado de maneira a otimizar o seu aprendizado dos t6picos abodados pelo exame SClPJava- f . Sempre

que possivel, n6-s organizamos os capitulos seguindo os objetivos da Sun, mas em.alguns casos misturamos objetivos ou

os repeumos parcialirente p"r" "prrs"nt"t

os t-6picos em uma ordem mais adequada para o esnrdo do material.

Em cada capitulo

N6s criamos um conjunto de blocos constituintes dos capitulos que chamario sua atengio.para itens importantes,

reforgarXo pontos deiestaque e fornecerXo dicas riteis para a hora do exame. Veja o que voc6 encontrar6 em cada capinrlo:

I Cada capitulo comegar6 com os Obietivos da Certificag5o - 9-guq vocA precisa saber para passar na seglo do exame que

tratar do t6pico refeiente ao capinrlo. Os objetivos serio identificados dentro do capinrlo por seus cabegdhos, portanto'

voc6 sempre saber6 qual6 o objetivo quando o vir!

I A notas Observag6es para o exame chamario a atengio para informag6es e possiveis armadilhas relacionadas ao

exame. LJma vez que eit6vamos na equipe que criou o exame, sabemos pelo que voc6 vai passar!

I As notas Ao trabalho descreverXo aspectos priticos de t6picos da certificagXo que podem nio aparecer no exame, mas

que serlo riteis no mundo real.

I Os exercicios priticos foram incluidos no decorrer dos capitulos. Eles o ajudario a aprimorar as aptid6es,que

possivelmenteirXo enfocadas no exame. NXo se limite a leios exercicios! Eles fornecem a pritica na execugio com a

qual voc6 teri que estar familiarizado. Aprender fazendo 6 uma maneira eficaz de aumentar sua capacidade.

I A segXo Nas salas de aula descrever6 as quest6es que surgem com mais freqiiAncia em cenirios de treinamento em salas

de aula. Essas barras laterais lhe darXo uma perspe&iva vfiosa sobre t6picoJ relativos i cenificagio e aos produtos. Elas

ressaltario alguns dos problemas mais comunJe confusos que os alunos encontram quando fazem um curso deJava.

P&R

O Resumo para a Certificagio 6 uma revisio sucinta do capitulo e uma reiteraglo dos pontos importantesrelacionados ao exame.

O Exercicio Mpido no finalde cada capitulo 6 umalistade verificaEio com os principais pontos do capitulo. Pode ser

usado para uma revisio de ultima hora.

O Teste Individual oferece perguntas que simulam os t6picos, a estrutu ra e a naltezadas perguntas encontradas no

exame de certificagio. As resposras a essas perguruas, assim como suas explicag6es, podem ser encontradas no final de

cada capitulo. Aoiaznr oTeie Individual, depois da concluslo de cada capinrlo, vod reforgar6 o que aprendeu nele ao

mesmo tempo em que se fam liarizarS, coma estrutura das perguntas do exame.

I

I

I

Page 19: Java - Scjp 5 - Portugues

JAVA 5 XIX

lntrodu96o

Organizagio

Este livro foi organizado de maneiraa servircomo um estudo aprofundado sobre o exame de Programador Cenificadopela Sun na PlataformaJava 5 tanto para profissionais experientes na linguagem quanto para os que estiverem nos est6giosiniciais de vi#ncia com as tecnologias Java. Cada capinrlo aborda um dos aspectos principais do exame, com Anfase emperguntas como "por que" e'!olo" pJggramar na linguager-nJava. O livro tamb6m inclui um estudo detalhado dos itensessenciais para obter uma avaliagio positiva no projeto enviado para o exame de DesenvolvedorJava Certificado pela Sun.

O que esse livro n6o 6

Neste livro voc6 nio encontrar6 um guia para iniciantes no aprendizado de Java. Todas as suas piginas sio dedicadassomente 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. Noentanto, nio pressupomos nenhum nivel de conhecimento anterior dos t6picos individuais abordados. Em outraspalavras, em todos os t6picos discutidos (direcionados exclusivamente pelos objetivos reais do exame), paftimos dasuposigio de que voc6 ainda nio os conhece. Portanto, o consideramos iniciante nos t6picos indivi duais, mas ndo nalinguagemJava.

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 examenio 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 maisinformados e completos do que seriam sem o estudo dirigido para o exame.

No site

Para obter mais informag6es sobre os arquivos para download, consrlte o Apdndice A.

Algumas sugest6es

Quando tiver terminado de ler este livro, reserve algum te mpo parafazer uma revisio completa. Seria bom se voc6retornasse ao livro v6rias vezes e fizesse uso de todos os m6todos que ele oferece para revisar o material:

L RebiatodososExerciciotRtipidotoupegaaalgu|mparalhefazcrasperguntas.Voc6tamb6mpodeusarosexercicioscomouma maneira de fazer uma revisio ripida antes do exame. Ou criar alguns cart6es pedag6gicos em fichas 3x5 contendo omaterial dos Exercicios R6pidos.

Z Reteia todat as notas da segdo Alerta no Exame. Lembre-se de que essas observag6es foram escritas por autores que ajudarama criar o exame. Eles sabem com o que voc6 se deparar6 - e com o que dwe tomar cuidado.

3. Refapa wTestet Indiuidaais.Fazer os testes logo ap6s ter lido o capitulo 6 uma boa id6ia, porque as perguntas ajudario areforgar o que voc6 acabou de aprender. No entanto, uma ideia melhor ainda 6 voltar posteriormente e responder todasas perguntas do livro de uma s6 vez. Imagine.que est6 fazendo o exame real. (Quando percorrer as perguntas pelaprimeira vez, anote suas respostas em.um.pedago. de papel separado. Dessa forma, voc6 poderi responder as perguntasquantas vezes precisar at6 que se sinta familiarizado com o material).

4. Faga ot exercicios.Voc6 fez os exercicios quando leu cada capitulo? Se nlo os fez, faga-os agora! Esses exercicios foramelaborados 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 tiverentendido, releia essa se$o do capinrlo.

Introdugio ao material do livro

O exameparaProgramadorJavaCertificado pelaSun (SCJP, Sun CertifiedJavaProgrammer) 6consideradoumdos maisdificeis (se nXo for a mais dificil) do segmento de inform6tica e podemos dizer a panir de nossa experiAncia que boa partedos 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 paraconcluir nosso projeto atual, dados os prazos impraticiveis, geralmente associados. Mas esse exame tentarA avaliar seuconhecimento totd da linguagemJava e nio apenas 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 qrrcconhece pode funcionarde formaumpouco diferente do que imagina. Nio 6 o bastante conseguirque seuc6digo funcionecorretamente;voc|prccisacompreender os fundamentos bisicos de maneiraprofunda e com abrang6ncia suficiente para

Page 20: Java - Scjp 5 - Portugues

xxabordar 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 eleavaliar6 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 temsido considerado a cenificaglo que mais se popularizou no universo da inform6tica e a quantidade de candidatos que o fazcontinua a crescer a cada ano. Passar nesse exame provar6 tr& itens importantes para um empregador atual ou futuro: quevoc6 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 tenhapassado, 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 boavantagem inicial. Para demonstrar efetivamente sua habilidade no desenvolvimento (em vez de apenas seu conhecimento dalinguagem) , voc6 deve corsiderar o Exame de Desenvolvedor, do qual receberi atarela decriar um programa, do inicio ao

fim, e envi6-lo para um avaliador que o examinar6 e lhe dari uma nota.

Programa de certificagio da Sun

Atualmente, h6 oito exames de cenificagio emJava. Os exames de Associado,ProgramadoreDesenuoluedoresteo associados coma Java Standard Edition. Os exames de Componentet IYeb, Ca@onentes de Negocin, Smigos IYeb e Proletista Empresarial estl.oassociados 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 AplicativosM6veis sio exclusivamente de mriltipla escolha e do tipo arrastar-e-soltar, e sXo feitos em um centro de testes, enquanto osexames de Desenvolvedor e de Projetista envolvem o envio de um projeto.

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

Associado Java Certificado pela Sun (SCJA)

O exame de Associado foi elaborado para candidatos que acabaram de iniciar uma carreira em desenvolvimento &aplicativos ou em ger6ncia de projetos de software usando tecnologiasJava. Este exame testa conhecimento bisico deconceitos de programagio orientada a objetos, os fundamentos de LIML, os fundamentos da linguagem de programagioJava e o conhecimento geral de plataformas e tecnologiasJava. E$e exame nio tem nenhum pr6requisito.

O exame de programador (CX-3 10.035)

ProgramadorJava Certificado pela Sun paraJava 5 (SCJP)

O exame de Programador foi projaado paratestar seu conhecimento na propria linguagem de programagio Java. Ele requerum conhecimento aprofundado da sintaxe da linguagem, dos conceitos principais e de uma pequena quantidade deinterfaces de programagXo de aplicativos (APIs, Application Programming Interfaces). Este exame tamb6m testa oconhecimento intermediirio de conceitos de projetos orientados a objetos. Nio avaliarinenhuma questio relacionada aoprojeto 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 umprograma 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 avaliarsua 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 quest5esdissenativas 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 acompanhamentocomquest6esdissertativas, elaborado, principalmente, paravalidareverificar sef.oram eletquem o projetaram e construiram.

Page 21: Java - Scjp 5 - Portugues

JAVA 5 XXI

O exame de Desenvolvedor de componentes da Web (CX-3 10-08 l)Desenvolvedor de Componentes da \ilfleb Cenificado pela Sun na PlataformaJava EE (SC\7CD)

O exame de desenvolvedor da \fleb tem como alvo as pessoas que estiverem usando o JSP $ava Server Pages) e o servlet datecnologiaJavap.ar3criaraplicativos\fleb. Ele foi baseado nas eipecificag6es do Servlet i ao jSn a.fUa"rna'JavaEnterpriseEdition fava EE). Parafazrr esteexame, 6 necessirio que o candidato seja um ProgramadoiJava Cenificado pela Sun.

^

O exame de Desenvolvedor de Componentes de Neg6cios (CX-3 l0-090)Desenvolvedor & Componentes de Neg6cios Certificado pela Sun na Pl ataformaJavaEE (SCBCD)

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

O exame de Desenvolvedor de Servigos Web (CX-3 lO-220)Desenvolvedor de Servigos \feb Certficado pela Sun na PlataformaJava EE (SCDIWS)

O exame de servigos web tem como alvo os candidatos que estejam criando aplicativos com tecnologiasJava EE eJava \7ebServices Developer Pack. Para fazer este exame, 6 necessi.rio que o candidato seja um ProgramadorJaia Clrtificado pela Sun.

o exame de Projetista (cX-3 | 0-05 | , cx-3 | 0-300A, cx-3 | 0-06 | )Projetista Empresarial Cenificadopara a Tecnolo 1gr_J2EE (SCEA)

Essa certificagXo se destina a projetistas empresariais e, ponanto, nio requer que o candidato passe no exame deProgramador. O exame de Projetista tem tr6s panes: uma prova de mriliipla escolha baseadaim conhecimentos, umprojeto de arquitetura e um teste de acompanhamento com quest6es dissertativas. VocA precisa passar na prova de multiplaescolha antes de se registrar e receber a tarefa do projeto.

O exame M6vel (CX-3 | 0-0 | l)Desenvolvedor & Aplicativos M6veis Certi{icado pela Sun paraJava ME (SCMAD)

O exame de. dese1,volv9d91{e aplicativos m6veis 6 para candidatos que esejam criando aplicativos para telefones celularesou 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 ProgramadorEm um mundo ideal, vocA seria avaliado-p-or seu conhecimento efetivo em um assunto e nio simplesmente pelas respostasgu9. d9y a.varias perguntas de um e*ame. Mas a vida nXo 6 perfeita e nem 6 pritico avaliar o conhecimento de v6rias p.iro".individualmenre.

Na maioria de seus exames de cenificaglo, a Sun avalia os candidatos usando um servigo de teste baseado em computador eoperado pela SyJvan Promet'ic. Esse servigo 6 bem popular na indfstria e usado por v6rios programas de cenificag?o deoutros fornecedores, incluindo o CNE da Novell e b MCSE da Microsoft. Gragas a grande luaitidade & filiais daSylvanPrometric, os exames podem ser administrados em todo o mundo, geralmente na riesm" cidade do candidato.

Geralmente, os exames da Sylvan Prometric apresentam um funcionamento semelhante para todos os fornecedores. Noentanto, h6 um fato imponante a se conheceriobre os exames da Sun: eles usam o formaio tradicional de te*e da SylvanPrometric e nio o adotado recentemente. Isso d6 ao candidato uma vantagem, j6 que o formato tradicional permiteque asrepostas 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 alteret'tlila rePorta qaando achar que pode ter interpretado mal ou se enganado na primeira kitura que feq de ama perganta. O neruositmo pode

faler com que uoci encontre ama ugunda rerpotta para cada perganta deixando a cotrcta de lado.

Para desencorajar.a simples memorvaglo,os exames da Sun apresentam um conjunto potencialmente disinto de perguruaspara candidatos diferentes. Na elaboragio do exame, centenas de perguntas sio compiladas e aprimoradas pot t.tt"doi.tbeta. Desse co{gnto volumoso, sio extraidx as perguntas referentei a cada objetivo que, posteriormente, sio reunidas emv6rias vers6es diferentes do exame.

Page 22: Java - Scjp 5 - Portugues

xxtlCada exame da Sun tem uma quantidade especifica de perguntas (o exame de Programado r conr6:mT2 Perguntas) e umaduragio para o teste (175 min.ttos p"t" o r*ame de Programador). Normalmente, otempo destinado ao teste 6 generoso' Orcmpo 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 seriimpresso automaticamente na mesa do inspetor para que voc6 possa arquiv6Jo. A nota do teste 6 transmitidaeletronicamente para a Sun.

oBSERVAQ6ESpeneTE)(AME

puando uocd n sentir confurc ao retponderpergantas de nilltipla escolha, use seu rascunho para anotar as duat ou h€s respostas que

conddera as mais pttadaeit e, em seguida, vtblinbe a @osta qw acha que possiuelmente i a corwta. Aqai utui un exemplo de como fcani seu

rascanho qaando uocljd tiuerpercorido 0 terte t/ma ueg

2l.BouC

)3.AouC

Iso uri exlrenamente titil paa uocl marcar a petgilflta e darpmsseguinenta Posteriorrzente, podeni retomar e resgatar inediatamente naraciocinio de 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,

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 informaquanras respostas t6m que ser selecion-adas. As perguntas do Teste Individual, encontrado no final de cada capitulo, t6mquase o meimo formato, redagXo e nivel de dificuldade das perguntas do exame real, com duas exceg6es:

r Sempre que possivel, as nossiu quest6es NAO lhe dirio quantas respostas corretas existem (diremos "marque todas as

corretas"). Faremos isso para lhe ajudar a dominar o material. Alguns alunos experientes com testes poderiam eliminar.r t 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 noenamereal!

I O exame real normalmente numera as linhas de c6digo de cada questio. N6s normalmente nlo as numeramos - a

principal razio 6 para termos espago para adicionar comentirios onde necessirio. No exame real, quando uma listagem

de c6&go comegar pelo 1, isso indicique se trata de um arquivofonte inteiro. Se a listagem comegar por um nfmeromaiordo 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-SoltarEmbora 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 tipoarrastar+soltar,

As quest6es arrastar+soltar normalmente consistem de tr6s comPonentes:

I Um cenirio Uma pequena descrigXo da tarefa que voc6 deverireaJizar.

I Uma tarefa parcidmente redizada Uma listagem de c6digo, uma tabela ou uma irvore de diret6rios. A tarefaparcialmente realizxla conter6 espagos em bran6, indicadoJcom caixas (normalmente amarelas). Essas caixas devefroser preenchidas para se complet ar atarefa.

I Um conjunto de fragmentos r€presentando respostas possiveis VocA clica nos fragmentos (normalmente caixas

azuis) e os arrasta para o espago em branco correto. O cenario da questio lhe diri se voc6 pode reutilizar fragmentos.

A maioria das quest6es de arrastare.sohar teri cerca de 4 a L0 espagos em branco para serem preenchidos, e normalmentemais fragmenros do que o necess6rio (alguns fragmentos sio deixados sem utilizagio). As quest5es de arrastar-e-soltarfreqiientemente sio as mais complexas do exame, e o ntlmero de possiveis combinag6es de respostas as tornam quase

impossiveis de "chutar".

Page 23: Java - Scjp 5 - Portugues

JAVA 5 XXIII

oBSERVAe6rspeneonl<eME

No que n ,trto fu questdes de arrastar-e-soltar, h,l um grande problena com o software de teste em muitos dos centros Pmmetric em todo o

mundo. Em geral, o nfhaare lbe penzite reuisar at questdes que jd respondeu qilantas aerys quiw.

No caso das qautdu de arrastar-e-so/tar, entretanto, maitos candidatos tim relatado qae, se eles pedirem para reuer a questdo, o nfwaruaPaga a rerpo$a anteioreil CUIDADO! Ati qae ese problena s/a nrrigido, recomendamos qae aocd mantenba uma lista de quait quutdet

sdo de anastar-e-so/ta6 para que ndo reuise rma sem qaerer. Outra boa iddia d anotar as rerpostat duse tiPl de qilesfil, de modo qile se iltua

for @agada, nrificil drgitar noaanente a rerporta.

Isso nos rerlete a ouho problema que os candidatos tdm re/atado. O cenhx de teste deueia lhefornecer o ruateria/ necesnirio para que uoei

pora traba/har nas questdes por escrito. En 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.

Dicas para a hora do exame

H5,72 pergontas no exame 31G055 $ava 5). VocA ter6 que acertar pelo menos 43 delas para passar - acima de 59 por cento.O tempo para conclusio do exame ser6 de quase tr€s horas. Essas informag6es estio zujeitas a alterag6es. Confirme sempre

com a Sun emwww.suned.sun.com, antes deprestar o exame.

. VocA pode responder as perguntas em qualquer ordem e tamb6m pode volt ar paramarcol suas respostas depois que tiverpercoirido otlste. Nio hi penalidades para as respostas erradas, ponanto, 6 melhor marcar uma resposta do que deixar uma

Perguntaem branco,

Uma estrat6gia adequada ao fazer o exame 6 percorr€Jo uma vez e responder todas as perguntas que souber de imediato.F.m seguida, voc6 poder6 voltar e responder as outras. Responder uma pergunta pode fazer com que se lembre comoresponder a anterior.

Seja muito cuidadoso com os exemplos de c6digos. Primeiro, procure erros na sintaxe, conte as chaves, sinais de ponto evirgula e par6nteses e ceftifique-se se h6 a mesma quantidade desses simbolos na abeftura e no fechamento. Procure erros nacolocagio 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 podeesperar apreender tudo que precisa siber em uma revisio ripida feita em uma inica sessio de estudo. Trata-se de um campoque vai sindo m.lhor corttpreendido com o tempo, atrarr6s do estrrdo de um assunto e posterior aplicagXo doConhecimento. 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 sucedidoserio bastante altas.

E "lt"-.trt.

r.comendivel que voc6 use can6es pedag6gicos ao se preparar para o exame de Programador . O caniopedag6gico 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 virandoo cartio para ver se acertou. Ou pedir a outra pessoa que o ajude, segurando o cartio com o lado da pergunta virado paravoc6 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. Noentanto, 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 maisparticipativa 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 (tipoaqueles com m6dia 987o), eles sempre relatam que escreveram muito c6digo como pane do estudo.

Page 24: Java - Scjp 5 - Portugues

xxtv

Agendando seu exame

Os exames slo contratados na propria Strn, mas sio agendados diretamente com a Sylvan Prometric. Para locais fora dosEstados Unidos, o nimero de contato de onde voc6 estiver poder6 ser encontrado no site Web da Sylvan, que fica noenderego http :/ /www.2tex.com. Os representantes da Sylvan poderio agendar seu exame, mas nio terio informag6essobre osprogramas de cenificagXo. Perguntas sobre a certificaglo devem ser dirigidaspara o depanamento de TreinamentoInternacional da Sun. Esses representantes estio suficientemente familiarizados com os exames para encontri-los pornome, mas ser6 melhor se voc6 tiver o nrimero do exame especifico ) mio quando falar com eles. Afinal, voc6 nlo iria gostarse 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. Nomomento do agendamento, os operadores procurario centros de teste em sua irea. Por conveniOncia, eles tamb6m poderioinformar em que centros de teste voc6 j6 esteve.

Quando voc6 se registrar no exame, o n{rmero de sua identificag1o ser6 solicitado. Esse nrimero ser6 usado no envio dosresultados 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 pelaprimeira vez tamb6m serio usadas pela Sun para enviar os certificados e outros materiais relacionados. Nos EstadosUnidos, geralmente o n{rmero de seu seguro social 6 usado como nrimero de identificagio. No entanto, a Sylvan pode lhefomecer um nirmero exclusivo de identificacio.

Chegando no local do exame

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

Chegue cedo no exame; isso lhe dar6 tempo para relaxar e revisar os fatos essenciais. Aproveite a opornrnidade pa ra reversuas notas. Se estiver cansado de estudar, talvez possa comegar seu exame alguns minutos antes. Por outro lado, niorecomendo 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 precisofornecer dois tipos de identificagio. Os tipos aceitos sio identificag6es emitidas pelo governo (por exemplo, passaporteou habilitagio de motorista), cart6es de cr6dito e crach6s de empresas. Sua fotografia deve consrar em uma dasidentificag6es. Eles s6 estario se certificando se voc6 nio enviou, em seu lugar, seu vizinho brilhante emJava, a quempagou para fazer o exame.

Al6m de um c6rebro repleto de informag6es, vod nio precisar6levar nada mais para o exame. Na verdade, seu c6rebro ser6tudo que poder6 levar! Todos os testes devem ser feitos com os livros fechados, o que significa que voc6 nio precisa levarnenhum material de consulta. Tamb6m nXo poderi levar nenhuma nota ao sair da sala do exame. O inspetor do teste lheforneceri papel e caneta. Alguns centros & teste podem fornecer uma pequena prancheta em vez disso. Recomendamos quevoc6 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 salado exame e talvez ainda possam ser ouvidos se tocarem fora da sala. Bolsas, livros e outros materiais devem ser deixadoscom 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 ontmero do exame esteo corretos. Se for a primeira vez que voc6 estiver fazendo um teste da Sun, poder6 selecionar umtutorial 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 seunivel de experiAncia em Java. O tempo que voc6 gastar n a pesquisa nio ser6 retirado do tempo propriamente dito do seuteste - nem voc6 ter6 mais tempo se responder a pesquisa rapidamente. Lembre-se tamb6m de que as quest6es no seuexarne 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 voc6se mova para baixo ou para cima entre as perguntas. No canto superior direito da tela, contadores mostrario a quantidadede perguntas e o tempo remanescentes. O mais importante 6 que haver6 uma caixa de selegio chamada Mark no cantosuperior esquerdo da tela - essa ser6 uma ferramenta importantissima, como explicaremos na segio seguinte.

Page 25: Java - Scjp 5 - Portugues

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 conclusiodo 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 aspecrospossam distraiJo. Aqui estlo algumas dicas paraf.azer o exzLme mais eficientemente.

Avalie o desafio

Primeiro, d6 uma passada r6pida por todas as perguntas do exame. Elimine as f6ceis, respondendo.as imediatamente. Leiarapidamente.cada pergunta, observando seu tipoi assunto. Como diretriz, tente gastar^menos do que 25 por cento de seutempo nessa leitura.

Essa etaPa permitil6 q.ue vogQ ryalie o escopo e a complexidade do exame, lhe ajudando a dererminar como conrrolar seutempo' Tamb6m dari uma id6ia de onde encontrar possiveis respostas para algumas das perguntar. As ,r.zes,

" redagio Je

umapergunta pode darpistas ou trazer a sua mem6iia outrapergurua.

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

Em segundo lugar- rwise todg o teste, empregando a percepglo que obteve na primeira leitura. Por exemplo, se o testeinteiro parecer dificil, voc6 saberi que nio poder6 gastar mais de circa de ,r- *irr.rto .- cada pergunta. Dirrij, o ..*po e*pequenos blocos - Por exemplo, "Preciso responder L0 perguntas a cada 20 minutos".

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

Em terceiro lugar, leia todas as perguntas que voc6 marcou para revisar, usando o botlo Review Marked da tela de revisio dePerguntas. Essa etapa inclui uma segunda leitura de todas as perguntas cujas respostas foram dadas sem cerreza, assimcomo responder as que exigem maistempo e que ,rocA posteigori at6 agora. Responda como achar melhor esse conjunto deperguntas ate que as tenha responctldo por completo.

Se voc6 estiver mais seguro para responder uma pergunta que marcou, desmarquea agora. Do contririo, deixe-a marcada.V6 trabalhando nas perguntas que exigirem mais tempo, principalmente as qrr. n ..tiit"rcm de c6lculos manuais.Desmarque-as quando estiver satisfeito com a resposia.

-

Ao final dessa etapa, voc6 ter6 respondido todas as pergpntas do_teste, apesar de nlo te r ceneza em alzumas das respostas.Se ficar sem tempo na pr6xima etipa nio perder6 pbntos pela falta de uma pergunta. Estar6 bem se aiida tiver 1O-2b porcento de tempo remanescente.

Revise suas respostas

Agora voc6 est6tranqiiilo! Respondeu a todas as perguntas e estA pronto par afazer smaverificaglo apurada. Faga outraleitura (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 queincluirem a opgio "N5o 6cotttpil"t".Eseja alenapara pistas de riliirnahora. VocO j6 eiti bem familiarizado com quasetodas as perguntas a essa altura e pode encontrar algumas pistas que nio tinha visto antes.

O grande final

Quando estiverconfiante de todas as respostas, termine o exame enviando-o para avaliagio. Depois, do que parecerio os LOsegundos mais longos de sua vida, o software do teste retornar6 sua nota. Geialmente, ela 6 exibida em um gr6fico debarras, que mostra a nota minima exigida, a nota obtida e um indicador PASS/FAIL.

Se voc6 estiver curioso, poder6 ver sua m6dia de pontos nesse momento. Nio serio apresentadas as repostas a pergunrasespecificas; em vez disso, 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?.

Quando voc6 sair do local do exame, ter6 que deixar seu rascunho para tris ou entreg6Jo ao inspetor. (Alguns centros deteste registram o nfmero de folhas que sio fornecidas, para tetem certezade que tod-as serio devolvidas). Em troca, vocpreceber6uma c6pia do relat6rio do teste.

Esse relat6rio terl a marca do centro de testes gravada e voc6 deve guardiJo em um local seguro. Normalmente, osresultados sio transmitidos automaticamente para a Sun, mm podi r.r q.te voc6 precise doielat6rio emitido para provarque Passou no exame.

Page 26: Java - Scjp 5 - Portugues

x)o/r

Em algumas semanas, a Sun lhe enviar6 um pacote pelo correio contendo um bonito cenificado, um alfinete de lapela e

uma carta. Tamb6m podem lhe enviar instrug6es di como contratar o tabalho artistico para criaSo de um logotipo que

voc6 poderiusar em cart6es de visitapessoais.

Fazendo novamente o teste

Se voc6 nio passar no exame, nio perca a esperanga. Tente aproveitar o que ganhou com a experiAncia e preParese Pararcntar,ro1r"rn.rrr..'Considere.se um po.tco -"is informado. Voc€ conhece o fbrmato do teste um Pouco melhor e o relat6rio

mostrari que ireas vod precisa fortalecer.

Se fizer o teste mais uma vez sem demora, provavelmente voc€ se lembrari de virias das Perguntas que pode ter errado.

Isso o ajudari a concentrar seus estudos na area certa'

Paraconcluir,lembrese que as ceftificag6es daSun sXo vdiosas, pois sio dificeis deobter. Afinal, se qudquerpesoa

conseguisse, que valor teria? No final das contas, 6 necessirio uma atitude adequada e muito esnrdo, mas voc6 pode faz&lol

Page 27: Java - Scjp 5 - Portugues

I

"'

DeclaraE6es eControle deAcesso

Oblerlvos pqru oGerrlflcqf6o:

I Decloror Closses e Interfoces

I Desenvolver Inlerfoces e Closses

Abstroct

I Usor Primitivos, Arroys, Enums eldentificodores Legois

I Usor M6todos Stotic, NomeoEdoJovoBeons e Vor-Args

I Exercicios R6pidos

P&R Teste lndividuol

Page 28: Java - Scjp 5 - Portugues

2 Copitulo 1 : DecloroE6es e Conirole de Acesso

N6s partiremos do principio de que, uma vez que esti planejando obter a cettificagio, voc€ i6 sabe o bisico deJava. Caso seja

completamente iniciante na linguagem, este capinrlo - e o restante do livro - ser6 confusq entio, certifique-se de que voc6sabe pelo menos o b6sico da linguagem antes de mergulhar neste livro. Dito isso, comegaremos com uma revisio pararefrescar a sua mem6ria sobreJava, caso tenha estado afastado da Jinguagem por algum tempo. i

Revisio de favaUm programa emJava € principalmente uma colegdo de objetos falando com outros obf etos por meio da invocagio dos

.

m6todos uns dos outros. Cada objeto 6 de um tipo, e esse tipo 6 definido por uma classe ou uma interface. A maioria dos

programas emJava usa uma colegio de objetos de muitos tipos diferentes.

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

I ObietoNomomentodaexecugio,quandoaM6quinaVirtualJavaflavaVirtualMachine,ouJVlvf eflcontt^^p^l^.rra-chave new, ela usa a classe aproprtadapara criar um objeto que seri uma instAncia dessa classe. Esse obieto ter6 o seu

pr6prio estado e ter6 acesso a todos os comportamentos definidos pela sua classe.

I Estado (vari6veis de instdncias) Cada objeto (instdncia de uma classe) ter6 o seu conjunto rinico de vari6veis de

instAncias conforme definido na classe. Coletivamente, os valotes atribuidos is variiveis de instincias de um obietocompdem o estado do objeto.

I Comportamento (m6todos) Quando um programador cria uma classe, ele cria m6todos para essa classe. E nosm6todos 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-chaveTodos 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,Javatemum coniunto de palavras-chaves internas. Essas palavras-chave nio podem ser usadas como identificadores. Mais adianteneste capitulo, veremos os detalhes sobte essas regras e conveng6es de nomeagio, e sobre as palavtas-chaveJava.

HerangaFundamental pataJava e outras linguagens orientadas a objetos 6 o conceito de hetanga, que permite ao c6digo definido emuma classe ser reutilizado em outras classes. EmJava, voc6 pode definir uma supetclasse geral (mais abstract), e depoisestend,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 umasuperclasse recebe automaticarnente as vari6veis de instAncias acessiveis e os m6todos definidos pela superclasse, mas 6

tamb6m livre para substituir m6todos da superclasse para definir comportamentos mais especificos.

Por exemplo, :uma npercIasse Carro poderia definir m6todos gerais comuns a todos os autom6veis, mas uma JrlklasseFerrari poderia substituir o m6todo acelerar ( ) .

InterfacesUm poderoso companheiro da heranga 6 o uso das interfaces. Ainterface 6 uma esp6cie de superclasse 100% abstricEque define os m6todos que uma subclasse deve suportat, mas ndo como esse suporte deve ser implementado. Fm odtraspilavras,umainterfaceAnimal poderiadeclanr que todas as classes de implementagio de Animal devem ter um m6todocomer ( ) ,mas ainterfaceAnimalnlo fornecenenhumal6gicaparaom6todo comer ( ) .Isso significaque ftcaacargodas 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 ClassesComo veremos mais adiante no livro, 6 uma boa id6ia manter a coesio das suas classes. Isso significa que cada classe deve tetum 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 criadaspor outros (tais como as classesJava API da Sun).Jwa orgatizaas classes em pacotes, e usa declaragdes import pan daraos programadores uma forma consistente de gerenciat anomeagdo das classes de que precisam e o acesso a elas. O exameaborda v6rios conceitos relacionados aos pacotes e ao acesso a classes; exploraremos os detalhes neste e em outros capitulos.

Page 29: Java - Scjp 5 - Portugues

JAVA 5 3

Al_r r. ^

..t.\Joleilvo poro o Lentttcocoo

ldentificadores e favaBeans (Objetivos 1.3 e 1.4)l.J Detenuoluer cddigo que dulare, inicialiqe e ase primitiuos, atraJs, enumr e objetos como uaridueis stat ic, de instdncias e locais. Ahndisto, usar identifcadoret legais para nomes de uaridaeis.

l.4Desenuoluercddigoquedularemdtodosstatic en1o-sLaLic'e,seapropriado,usarnomesdemdtodosqueobedegamaospadrdude nomeagdo JauaBeans. 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, issosignifica que as seg6es a seguir abordario pelo menos parte desses objetivos. Alguns objetivos serio abordados emv6rios capitulos diferentes, de modo que voc€ ver6 o mesmo obietivo em mais de um lugar do livro. Por exemplo, estasegio cobre declarag6es, identificadores e nomeagioJavaBeans, mas o uso do que voc€ vai declant ser6.abordado emcapitulos posteriores.

Assim, comegaremos com os identificadotesJava. Os tr6s aspectos dos identificadoresJava que abordaremos aqui sio:

I Identificadores Legais As regras que o compilador usa para determinar se um dado nome 6legal.

I Conveng6es de C6digo Java da Sun As recomendag6es da Sun para nomeagio de classes, vari6veis e m6todos.Normalmente n6s obedecemos a esses padr5es em todo o livro, exceto quando estivermos tentando lhe mostrar comoseria uma questio dificil do exame. Nio lhe ser6o feitas perguntas sobre as Conveng6es de C6digoJava, masrecomendamos enfaticamente que os programadores as usem.

I Padr6es de NomeagdoJavaBeans Os requisitos de nomeagio da especificagioJavaBeans. Nio 6 preciso estudar aespecificagioJavaBeans pata o exarne, mas voc6 precisa saber algumas regras b6sicas de nomeagSoJ"rrrB.*, q.r.abordaremos neste capitulo.

Tecnicamente, os identificadores legais devem ser compostos apenas de caracteres Unicode, nrimeros, simbolos de moedas ecaracteres de conexio (como underscores). O exame nio mergulha nos detalhes de quais falras do coniunto de caracteresUnicode qualificam como letras e digitos. Assim, por exemplo, vocd n6o precisar{ saber que os drgrtos em Tibetano v6o de\u0420 at6 \u0f29. Eis aqui as regras que voc6 precisa saber:

I Osidentificadoresdevemcomegarcomumaletra,umcifrio($)ouumcaracterdeconexdo,comoounderscore(_).Osidentificadores nio podem comegar com um nfmerol

I DePois do primeiro c^r^cter,os identificadores podem conter qualquer combinagio de letras, caracteres de moedas,caracteres de conexio ou nfmeros.

I Na pr6tica, nio h6limite para o nrimero de caracteres que um identificador pode conter.

I Nio se pode usar uma palavta-chaveJava como identificador. A Tabela 1-1 lista todas as palavras-chave Java. incluindouma novidade da versio 5.0, enum.

I Os identificadores emJava si.o case-sensitive; foo e Foo sio dois identificadores diferentes.

Seguem alguns exemplos de identificadores legais e ilegais; primeirq identificadores legais:

I nf a .

int gc,'

int 2 w;

int _$;int eis_um_nome_bastant.e_detalhado3ara_um_identif icador ;

Os seguintes sdo ilegais (agora voc€ ji sabe o por qud):

int :Jr;

i ht -A .

int e#;

I nr I .

anE. /9,.

ldentificadores Legais

Page 30: Java - Scjp 5 - Portugues

4 Copftulo 1 : Declorog6es e Conlrole de Acesso

Tobelo 1-l Listo Completo de Polovros-Chove Jovo (ossert odicionodo em 1 .4, enum odicionodo em 1 .5)

abstract boolean break byte case catch

char class const ^^nl_ i nlra default do

double else extends final finally float

for :Jvuv if implements import instanceof

int interface long nati-ve package

hri rt^l-a protected public return short staEic

strictfp super switch synchronized this throw

throws trans]-enE Ery void voLatile while

asserE enum

Conveng6es de C6digo lava da Sun

Pelas estimativas da Sun, ao longo da vida ftil 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

com um coniunto de padr6es e programiJo aiudaadiminuir o esforgo envolvido em testar, fazer amanutengio e

melhorar qualquer c6digo. A Sun criou um con,unto de padr6es de programagdopanJavaepublicou esses padr6es em um

documento inteligentemente chamado de "Convengdes de C6digoJ ava",o qualvoc6 pode encontrar em iava.sun.com.Trata-se de um 6timo documento, curto e f6cil de ler, que recomendamos enfaticamente.

Dito isso, vocd ver6 que muitas das quest6es do exame nio seguem as conveng6es de c6digo, devido is limitag6es do

programa de provas que 6 usado para minisftar o exame internacionalmente. Uma das boas coisas sobte as certificag6es da

Sun 6 que os exames sio administrados uniformemente em todo o mundo. Para se conseguir isso, as listagens de c6.ligos

que voc€ ver6 no exame real freqiientemerite sio bem bagungadas, e nlo seguem os padr6es de c6digo da Sun. Panprepat|-lo pam o exame, n6s freqtientemente iremos apresentar listagens de ssdigos com uma aPar€ncia igualmente bagungada,

usando apenas dois espagos depatdgnfo em vez dos quatro espagos do padrio Sun'

N6s tamb6m bagungaremos nossas chaves de forma artificial, e, em alguns casos, colocatemos v6rias declatag6es na mesma

linha... oh nio! Por exemplo:

1. class Wombat implements Runnable {

2, private int i;3. public synchronized void runO i4. if (i*5 l= 0) { i++; i5. for(int x=0; x<5; x++, i++)

6. { if (x > 1) Thread.yield0 ; }

7. System.out.print (i + " ") ;

8)g. public st.atic void main(string[] args) t -l-0. Wombat n = new wombat O ;

11. for(int x=100; x>0; --x) { new Thread(n).startO; }

L2. ) )

Considere-se avisado - voc€ ver6 v6rias listagens de c6digos, quest6es simuladas e quest6es de exames reais que serio

doentias e incompreensiveis dessa maneira. Ningu6m quer que voc6 escreva seu c6digo desse ieito. Nem o seu empregador,

nem os s..,s colegas de trabalho, nem n6s, nem a Sun e nem a equipe de elaboragdo do exame! Esse tipo de c6digo foi

criado apenas para que conceitos complexos pudessem ser testados usando-se uma ferramenta de provas universal. O rinico

padrio que 6 seguido tanto quanto possivel no exame rcaL6. o dos padr6es de nomeagio. Eis os padr6es de nomeagio

recomendados pela Sun, e que usamos no exame e na maior parte do livro:

I Classes e interfaces A primeira letra deve ser maifscula e, se v6rias palavras forem escritas iuntas para formar o nome, a

primeira leta d e cadapalavrainterna deve ser mairiscula (um formato chamado em inglBs de "camelCase'). Para classes,

os nomes devem normalrnente ser substantivos. Por exemplo:

Dog / /Cachorro

Page 31: Java - Scjp 5 - Portugues

JAVA 5 5

Account / /ContaPrint.Wrj-ter / / Impressora

Para interfaces, os nomes devem normalmente ser adletivos, como:

Runnable //Execut6velSerializable / / Seria]-:-z5ivel

I M6todos A primeira letra deve set minriscula, e depois as regras camelCase normais devem ser usadas. Al6m disso, osnomes devem normaknente ser pares de verbo-substantivo. Por exemplo:

getBalance / /obterBalangodoCalculat ion / / fazerC6lculosetCustomerName / /de f inirNomeDoCl iente

I VariSveis Como nos m6todos, o formato camelCase deve ser usado, comegando com uma letra minriscula. A Sunrecomenda usar nomes curtos e significativos, o que nos parece uma boa id6ia. Alguns exemplos:

buttonWidth / / LarguraDoBotSo

accountBal ance / / balanqoDaConta

myString //minhaStringI ConstantesAsconstantesJavasdocriadasmarcando-sevariiveiscomostatic efinal.Elasdevemsernomeadasusando-se leftas maifsculas com cafacteres underscore como seoaradores:

MIN_HEIGHT / /ALTURA_MINIMA

Padr6es favaBeansA especificagioJavaBeans foiciadapanajudar os desenvolvedores a criarem componentesJava que possamser facilmenteusados 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 usarcomponentes 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 depoder acessi-los atrav6s de uma ferramenta de desenvolvimento de forma tal que nio precise escrever todo o seu c6digo dozero. Ao usar regras de nomeagio, a especificagdoJavaBeans ajuda a garantir que as ferramentas podetio reconhecer e usarcomponentes criados por diferentes desenvolvedores. AAPIJavaBeans 6 um tanto complexa, mas voce s6 precisar6 estudaralguns fundamentos para o exame.

Primeiramente,JavaBeans sio classesJava que tem propriedades. Para os nossos prop6sitos, pense nas propriedades comovati6veis de instdncias private. Umavez que sdo private, a rinica maneira pela qual podem ser acessadas de fota dasua classe 6 atav€s de m6todos da classe. Os m6todos que modificam o valor de uma propriedade sio chamados m6todostetter, 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:

t

Regras de Nomeagao de Propriedades favaBeanI Se a propriedade r'do fot booleana, o prefixo do m6todo getter deve ser get. Por exemplq getsize ( ) 6 umnome 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 dosgetters e setters, e nZo-atrav6s de quaisquer vari6veis da sua classe. O que vocd ir6 retornat a partir de gets i ze ( )

fica a seu critdrio.

I Se a ptopriedade for booLeana, o prefixo do m6todo getter 6 ou get ou is. Por exemplo, tantogetSt.opped ( ) quanto isstopped ( ) sio nomesJavaBeans vilidos pataum^ propdedade booleana.

I O ptefixo do m6todo setter deve ser set. Por exemplo, setsize ( ) 6 o nomeJavzBeanv|Idopar^lmapropriedade chzmada s i z e.

I Pa:,a ter o nome completo de um m6todo getter ou settef, passe a primeira letra do nome da propriedade paramairiscula e depois anexe o prefixo apropriado (get, is ou set).I As assinaturas de m6todos setter devem ser marcadas como public, com um tipo de retorno void e umargumento que represente o tipo da propriedade.

I As assinaturas de mdtodos getter devem ser marcadas como pubL ic, nio usar argumentos e ter um tipo deretorno que bata com o tipo do argumento do mdtodo s et ter pan a ptopiedade em questao.

Em segundo lugar, a especificagiloJavaBean tem suporte a euentos, os quais permitem aos componentes notificarem uns aosoutros quando algo acontece. O modelo de eventos geralmente 6 usado em aplicag6es GUI quando urn evenro, como urnclique do mouse, 6 comunicado para muitos outros objetos que possam ter cgisas a fazet qtando ocore um clique do

Page 32: Java - Scjp 5 - Portugues

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

void setCustomerName (String s)

public void modifyMyValue(int v)

public void addXlistener{MyListener m)

I Os nomes de m6todos listeners usados para"reg|strar" um listener com ulna fonte de eventos devem usar o prefixoadd, segu.ido do tipo do listener. Por exemplo, addActionlistener ( ) 6 um nome v6fido para um m6todo que

uma fonte de eventos dever6 permitir a outros registrarem para eventos Act ion.

I Nomes de mdtodos listeners usados para remover ("desregistrar") um listener devem usar o prefixo remove, seguido

do tipo do listenel (usando-se as mesmas regras que o m6todo add de registro).

I O tipo de listener a ser adicionado ou removido deve ser passado como o argumento para o m6todo.

Alguns exemplos de assinaturas de mdtodos JavaBean vdl-idas:

public void setMyValue(int v)

public int getMyValue ( )

nrrlrl i a lrnnl aan i cM\/ql-.1-rrc | )ysv4+v

public void addMylistener (MyListener m)

public void removeMylistener (MyListener m)

Alguns exemplos de assinaturas de m6todosJavaBezn inuilidar

/ / nrcai sa sFr nrrl-r1ict t ylvvlve

/ / n6.o se pode usar 'modify'/ / crra da l- inn d. l-iStenefI I eLLv

oB SERYAQoBS pene O EXAME

O objetiuo sd diqque uoci precisa saber os identifcadoru legais para nzmes de uaridueis, mas as regras s6o ar nermas para TODOS os

componentes Jaua. Assim, lenbre-rc d.e que un identifcador legalpara ilma aariduel tanbdn d legalpara un nitodo ou uma classe.

Entretanto, uocd deue distinguir entre os identifcadores legais e as conuengdes de norueagdo, tais como o: padrdet JauaBeafls, q//e indican cono

um determinado componente Jaua deue ser nomeado. En outras palauras, uocd deue ser capaqde reconheeer qae um dado identifcador d legal

mesml qile e/e ndo se conforme a padrdes de nomeapdo. Se a qaestdo do exame estiuer lhe perguntando sobre conuengdes de nomeapdo - e ndo

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

Obietivo poro o Certificogdo

Declarar Classes (Objetivo l. I do Exame)/.1 Desenuoluernidigo que dulare classes (incluindo claset absLracL e todas atformas de classu aninhadat), intefaces e enilm!, e

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

Ao escreve c6digo emJava, voc€ est6 escrevendo classes ou interfaces. Dentro dessas classes, como voc€ sabe, eistemvariiveis 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 doc6dig: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 nivelextremo 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

::;:....O" rer ceftezzabsoluta de que domina totalmente todos os assuntos dos objetivos desta segZo antes de fazet 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:

I

Page 33: Java - Scjp 5 - Portugues

.,! r

JAVA 5 7

I 56 pode haver uma classe publ i c em cada arquivo de c6digo-fonte.

r Os comentirios podem aparecer no inicio ou no fim de qualquer linha no arquivo do c6digo-fonte; eles sioindependentes de quaisquer regras de posicionamento diicutidas aqui.

f lsiaul,er-Jpa-clas,sepubli-cemumarquiv.o-o..-el^"rg"*odevesere.mesmodaclassepubfic.porexemplo, 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, antesde 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 niohouver uma declatagdo package, entio a(s) declaragzo(5es) impoit deie(m) estar na(s) primeirals; Iinha(s) do arquivodo c6digo-fonte. Se n6o houvet declaragSes package nem import, a declatagiodu.t"i.. d.rr..sti na primeira linha doarquivo do c6digo-fonte.

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

I Um arquivo pode ter mais de uma classe nio-public.I Arquivos que nio tenham classes pub 1 i c podem ter um nome que nio seja o mesmo de nenhuma das classes do arquivo.No Capitulo 10' discutitemos mais de talhes sobre as regras envolvidas com a dec langdoe o uso de importag6es, pacotes eum recurso novo doJava 5, importag6es estAticas.

\,p

".\\(

Declarag6es e Modificadores de Classes

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

class Myclass { }

Esse.c6digo iri compilat sem ptoblemas, mas yqgepqdelamb€lq adeio.nar rao-digga4tr-es antes da de cla.r-ag,oda classe. Osmodificaderes ee dividemsnc duas..patsgp_r-ias :

r _!t_"-aiq..aores de ac€sso: public,prolecLe4 pLivate.I M-odificadoresquen6ose.r,eferemaacesso(incluindo strictfp, f inal eabstract).Examinaremos os modificadores de acesso ptimeiro para que voc6 aprenda como restringir ou permitir acesso a uma classeque criar' 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){oguq v-o-c€ oblim qual-{o ndo usa nenhunraostr€l-modi-fic4do{qs de acesso. E,m'outras palavras, gggp13rr., m6todo ..'Vgrpy..el{g inst{gci4 quevo-g6 {eclatar tem um controle Jieacisrq -d.pqndentemente d;voc€ indi} um explicitamente ou0.69' Embora tgd-g! 9-9^qF4trq gontrole; fg acesso (o que significa todos os tr€s modificadores) foncion emparaa maroria dasdeclarag5es de m6todos e de variiveis, uma classipode.ser declarada.apenaS,.co5n,gcesso pubt"ic ou d,ef ault; os outrosdois niveis de controle de acesso nio se aplicam paia classes, como voc6 ver6 adiante.

AO TRABALHO

Jaua d uma linguagen cenlrada n\Epa.rote|; os derenuoluedoret asrumiram qae,para uma boa organiqagdo e controle do escopo de nomes,uocdpreferiria colocar todat as suas clasres empacotes. Eles estauam certoi, e iocd deuefaryr i:i neino. Inagine o seguintepesadelo: trdsdiferentet progmnadorer' na flrerma efitprestT, mas traba//tando em diferentes partu de in prolen, escreuen ,oin o* una clasrc chamadaUtlities' Se essas trfu classes lJtilities ndo ,iuerem sido deltyadas in nenhin pacot, ,^pbrito, e utiuerem no clasrpath, uoci ndo terdnenhana maneira de diler ao compilador ou a lwtL qual

/as trds estd tentand) referencior. A Sun recomenda qae os desenuolaedoretusem n1mes de doninio reuerso, anexados colr o nlme da diuisdo e f oa doprojeto. Porexeupl0, ft 0 ltvne do siu doninioforgeeksanonltmous'cLm' e estiaer traba/hando no aidigo do clienlepara oprograna TwelaePoiitOStEt, aoc6 daria ao Jeil pacote ,/m //,mecamo com'geeksan0nlm0us.rteps.client. Isso modifcaria o oori do su) classe pnra ,o*.grr/"roronlroa1sEt.c/ient.(Jtilities. Aindaastim, uocd poderia ter klisdes de nomer dentro da rila emprera, se ndo inuentai os uus pidprios ujor*^ de' nomeagdo, margarantidamente ndo hausnl colisdes nm clasu duenuolaidas.fo* d: saa empreM lassinlido qrr)/o, ngn* a conuengdo de nomeagdo daSury se e/as ndo o17(erem, bem, coisas bastante desagradriuiis poden aconticer).

'

Acesso a Classeso que significa acessar uma classe? Q-uando dizemos qug o g{dig-o-de uma classe.(a classe A) tem acesso a ou-tra-Gla-csE-E),if gl-stgilfisa-Su-eaclAS!94-p-oi9g:9r-r1!tl.dlsp.g',rniq9coie4q;*

I Criar uma instdncia da classe B.

Page 34: Java - Scjp 5 - Portugues

8 Copftulo 1 : DecloroE6es e Controle de Acesso

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

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

l-.i.a pritica, acesso signific a uisibilidadp. Se. a c-lasse A nio puder uera classeB,o nivel de acesso dos m(lodos e variiveis dentro

da classe B n6o farS,dtfercnga; a classe A nio ter6 como acessar esses m6todos e vari6veis.

ASr.SgD_ =faprll-Upaclagge-comaqggq-gdefaul-t naotemnenhummodificadorprecedendo-a{radeclaragio! Esse6o

iontrole de acesso que vo.e oUte- quando nio digrta um modificador na declaragdo daclzsse. Pense no acesso defaul-tcomo 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,aclasse 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 { iAgora 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 panconsertar isso. Voc6 poderia colocar ambas as classes no mesmo pacote, ou poderia declarar Beverage como publ ic, como

descrito na seg6o seguinte.

Quando v_oc_e yrgm? ques.t6o com lp"gga complexa,.certifique-se de olhar os modificadores de acesso primeiro. Dessa

,forma, se descobrir uma violagio de acesso (por exemplo, uma classe do pacote A tentando acessar uma classe de f aul- tdo pacote B), yoc6 saber6 que o c6digo nao vai compilat, entio nio precisa nem se dar ao trabalho de tentar entender a

I6gica. Afin"i,i;;ai; -as o que fLrr ro ..rr,.-po "o

fazer aptova.Simplesmente marque a resposta 'A compilagio

falha'e passe para a questao seguinte.

.{ge.sqg Pirblico Uma declaragio de classe com ^p^lavr^-chave

publ i c dd alo-das as classes, de todos os pacotes, acesso.d

-.l"sS.e pfbliC?. Em outras palavras, lg/a.s as classesdo p_-ni;qersoJava QU) tdm acesso a uma classe priblica. No entanto, ndo

se esquega, de que, gg.ruLa-ela.s;g,pgbLq1.qqe estlyer terrta.ndo usar estiver em um pacote diferente do da classe que este

screrrendq vocgggd.U_ree!ca!--6 1r-nper!al?-@s€p'$!9.

No exemplo da segio anterior, talvez ndo queiramos colocar a subclasse no mesmo pacote que a superclasse. Para fazet o

c6digo funciona4precisamos adtcionar apalavra-chave pu-b1 ic na frente da declaragdo da superclasse @everage), da

seguinte forma:

n: nlz:na narf .

public cfass eeverage { }

Isso modifica a classe Beverage para que ela se torne visivel a todas as classes em todos os Pacotes. Essa classe agora pode set

instanciada a partir de todas as outras classes, e qualquer classe est6 agora livre para subclassific6la (estender a partir dela) - a

ndo ser que a classe esteja marcada tamb6m com o modificador f inal .J5. falarcn:.os sobre isso.

Outros Modificadores de Classes (Nio-referentes a Acesso)Voc€podemodificarumadeclzraglodeclasseusandoaspalavras-chavefinal"ab.sEract,oustricF€.D.!sse;.modiicadores exi*sfen-rm-adigio-a.qualqueffontrolede acesso existent€naslasse, entiovoc6 poderia, por eremplq declarar

U€Q(!.classecomopublic efina]*ao.mesrf,rotempo.Nlar:r.dqd.semprequevocepodemisturarmodificadoresndo-

{F.fgtgqtesaacesso.Voc€podeusarstrictfp emcombinagiocomfinal,porexemplo,masniodevenunca,iamais,m tc rvmaclassecomof inal- eabstract aomesmotempo.Voc6ver6porquenasduaspr6ximassegSes.

Voc6 nio precisard saber como strictfp funciona, entio nos concentfafemos apenas em modificar uma classe como

final- ouabstract.Paraoexame,voc6s6precisasaberquestrictfp 6umapalavra-chavegguepodeserusadapara.nodifijarumaclasseouunm6tgdo*.m4snuocamavan|vel.Marcarumaclassecomostrictfp significaquequa-lquet

c6digo de m6todo na classe se conformar6 is regras do pa&io IEEET54pzrzpontos flutuantes. Sem esse modificador, os

Page 35: Java - Scjp 5 - Portugues

JAVA 5 9

pontos flutuantes usados nos m6todos poderio se comportar de forma variante conforme aplataforna.Se ndo declarat aclassecomostrictfp,aindaassimvoc6poder6obterumcomportamentostrictfp param6todosespecificos,declarando o m6todo como strictfp. Se voc6 nio conhece o pa&io IEEE 754,agotanio6 o momento pam aprend6-lo.Voc€ tem assuntos mais importantes para se preocupar.

ClassesFinaisQuandousadanadeclaragilodeumaclasse,ap.flV3;3;9bave-final significaqueaclasseemquestdonaogg[gper subcla,ssificada' Em outras palavtas, ne*gblqggclr-g1a.ss-eppd-ejas.rar,s aslenJef @erdar de) uma clasie f ina1, e

9gdWe1l9111aivade faz€-lolhe dard um erlo de compilag{q

Entio por que voc€ sequer m arcaiauma classe como f inal ? Afinal de contas, isso n6o viola to da a nogd.ode herangapresente nas linguagens orientadas a obietos? !,oc€ s6-5!pv_g marc4r gp.qa.c,lasse como f ina] . seprecisar de uma garantia4lselu-ta dequ.g.ngghurlr dos m6todos dessa classe jamais vai ser substituido. Caso ieo c6digo seja profundamentedependentedaimplementagiodecetosm6todos,usarfinal lhedar6asegur"ogad.qoe-ningu6mpoder;,modtficatairslegrent?g5g .qem vo_qQ. s_4!e1.

V?.i n1i.U]ique rr.rtls-gb:-q9g-4?s bibliotecas fuodamentaisJava s6o f ina1. !og*9,1emplo, a classe String"nio pode sersubclassificada. 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 (eassim colocar as suas novas instancias da subclasse String onde esperam-se instAncias de java.lang.Strin $, a civiltzagfuo ticomoaconhecemosenttaiaemcolapso.$ssim,usefinal paraseguranga,masapenasqo".rdotivercertezadequeasuaclasse f inal de fato j6 disse tudo o que precisa ser dito nos seus m6todos. Marcaiuma.larr".orno f inal- significa, naEI?a-94 que a su,a classe nunca ser6 aprimorada, ou mesmo modificada para uso mais especifico, por outro programador.

IJ-q1!-e1e{c!o de se ter.classe$nao--f;pa1 6 neste cgn6rio: imagine que voc6 encontrou um problema com um m6todo em9$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 emtg-,{1s31og;r-s10es em gue a superclasse original for esperada. No entanto, se a classe for f inal, entao nao h6 nada que voc6pcissa fazer.

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

nadLrd6 ^arf.Fsv.leJv 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 subcl_ass final classes: cl_ass

cert.Beverage class Tea e:itends Beveraqe{

1 errorNapr6tica,voc€quasenunczciars"wrnacJ.asse f inal.As classes f inal acabamcomumbeneficio fundamentaldaprogramagio OO - a extensibilidade. Assim, a n6o set que voc6 tenha uma s6ria preocupagio de seguranga, assuma quealgum 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 classepoderia 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. Temoscefteza de que o dono de um Boxster lhe diria que o caffo dele 6. capaz de fazer coisas que o Subaru apenas ,.sonha emfazer". Observe a seguinte classe abstract:

abstract class Car {

nri rr:f a dnrrl.l*_*-,e prlce;

Page 36: Java - Scjp 5 - Portugues

'l 0 Copftulo I : Decloroc6es e Controle de Acesso

privaLe String model,'

private String year;

public abstract voj-d

public abstract void

public abstract void/ / Co1 odrrc o resfo do/ / vv+vYqv

)

O c6digo acima iti compilar sem problemas. Entretanto, se voce tentar instanciar um Car em outro corpo de c6digo,

receber6 eros de compilagio como o seguinte:

AnotherClass.java:7: class Car is an abstract

class. It can't be instantiated.

Car x = new CarO,'

1 errorRepare que os metodos matcados com abstract terminam componto-e-virgula, emvez de chaveg'

Pro.Clr_19-lyeptQes 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 alQstracLclntamirra !o4a_a.!q!ma: Vocd pode,:ro entaoto, coloc-ar m6todos nio-abstract em uma classe abs-F-.ract' Por

.*.-plo, rro.6 poderia ter m6todos com implementag6es que nio devem mudar de acordo com o tipo deCx,tais como

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

que as subclasses concretas herdam funcionalidad.r, . preiiii- implementar apenas os m6todos que definem

comportamentos especificos da subclasse.

(A prop6sito, se voc6 achou que usamos a expressio raison d'etre fora de contexto, anteriotmente, nio nos mande e-mail'

Queremos ver uoc6 colocarumra expressio dessas em um livro de certificagio PM Progr madores')

programar com tipos de classes abstract (incluhdo interfaces, que serio discutidas mais adiante neste capitulo) permite

q..e voc6 tire vantagem do polimorfismo, e lhe d6 o maior grau possivel de flexibilidade e extensibilidade. Voc6 aprender6

mais sobre polimorfismo no Capitulo 2.

Nig €pqssiv€l mar:catrtm^classe como abstract e f inaf ao mesmo tempo. Elas t6m significados quase opostos'

Uf"C -.laeSe-abgLract-'p:ecisa-ser subclassificada, enquanto que uma classe f inaf nlo deve ser subclassificada. Se voc€

"it"..rrfombinagiodemodificadoresabstract efinal,usadosparaumadeclatzglodeclasseoum6todo,oc6digo

nio ir6 compi-lar.

Exercfcio 1 - 1

goFast ( ) ;

goupH]--Ll- (/;

impressNei.ghbors O ;

c6digo importante e s6rio aqui

Criando uma Superclasse Abstract e uma Subclasse Concreta

Osegu.inteexerciciotestarioseuconhecimentodeclassespublic,default,finaf eabstract.Crieumasuoerclasse abstracg chamada Fruit e urna subclasse concreta chamada Apple. A superclasse deve pertencer a um pacote

chamado food e a subclasse pode pertencer ao pacote def ault (significando que ela ndo ser6 colocada em um pacote

expLicitamente). Torne a superclasse pubf ice d€ i subclasse acesso def ault.

1. Crie a superclasse da segrrinte maneuzl.

n:nlraa fnnd.

nrrhtic ehsl-recf class pruit{ /* insira qualquer c5digo que desejav */Ivuvr+v

2. Ciea subclasse em um arquivo separado, da segrinte maneira:

import food.Fruit;

Page 37: Java - Scjp 5 - Portugues

JAVAS IIclass Apple extends Fruit{ ,/* insira qualquer c6digo que desejar */}

3. crie um diret6rio chamado food dentro do diret6rio configurado no seu class path.4' Tente compilat os dois arquivos. Se quiser usar a classe Apple, certifique-se de colocar o arquivo Fruit.class nosubdiret6rio food.

Al .Obietivo poro o CertificoE6o

Declarar Interfaces (objetivos l.l e 1.2 do Exame)1'l Desenuolaer aidigo qae declare clases (incluindo clasus abttract e todas asformas de c/asses aninhadat), intefans e enum!, e inclua o uso4rEiado de dukmgdet package e inport (incluindo impo,tapdet utriticas).

1'2' Desenaolaer aidigo qae declare uma nttrfott Desenuoluer aidigo que inplenente ou estenda uma ou mais interfaces. Desenuoluer c;digoqae dec/are uma classe abstract. Desenuoluer cddigo que ettenda nri ,l^n abttract

Declarando uma interface

Quando voc6 criar uma inte rfzce, estat6' definindo um contrato com o que a classe pode fazer, sem mencionar nada sobrecomo a classe o fad.Umalnterface 6 um conffato. Voc6 poderia escrevei uma interiace Bounceable, por exemplo, queestabeleceria: "Essa 6 uma interf"ceboon.eable. Qualquertipo de classe que @plementar .rru irt.riu.. precisa concordar eme;19r;y_q-r-9p6$go do_sm6todosbounce ( ) e setBounceFactor ( ) ".

Se uma interface Bounceable (Saltitante) for definida, qualquer classe que quiser ser ttatada como algo sal.ntante podet6simplesmente implementar essa interface e fornecer oi6digo de seosiois m6todos.

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

interface Bounceable

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

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

Figuro 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 m6todosabstract com a forma,

abstract void bounceo; // Termina com ponto-e-virgu1a, em vez de chavesMas, enquanto uma classe abstract pode definir tanto m6todos abstract quanto ndo-abstract, r*najnferfacpgggg.dt ter m€todos abstr-aqt. outro ponto em que as interfaces diferem das classes abstract 6 que elas

interface Bounceable

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

Ii

O que vocddeclara

Oqueocompiladorv6.

O que a classeprecisa fazer(todos osmdtodos pre-cisam serimplementa-dos e defini-dos comop{rblicos)

Page 38: Java - Scjp 5 - Portugues

12 Copftulo 1 : DecloroE6es e Controle de Acesso

/ apresentam muito pouca flexibilidade em como os m6todos e vari6veis definidos na interface s6o declarados. As regras s5o

restritas:

I Todososm6todosdeinterfacesioimpliciamentepublic eabstract.Emoutraspalavras'vocenaoprecisadigitar

realmente os modificadores publ ic ou abstract, na declaragio do m6todo, mas mesmo assim ele sempre ser6

PubIic eabstract.

,. I Todasasvariaveisdefinidasemumainterfacedevemserpublic, static e f inal -emoutraspalavras,as' intetfaces s6 podem se declarar constantes e neo vari6veis de instAncia.

; I Osm6todosdeinterfacesn6opodemser static'

a Jaque os m6todos de interface sio abstract, nio podem ser marcados como f inal, native, strictfp ou

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

I Uma interface pode estender uma ou mais interfaces diferentes.

I f Uma interface nio pode estender nada que nio seja outra interface.

1 I Uma interface nio pode implementar outra intetface ou classe.

\ f Uma interface deve ser declarada c om apalavn-chave interf ace.

I r Os tipos de interface podem ser usados polimorficamente (consulte o Capitulo 2paramais detalhes)'

A linha a seguir 6 uma declaragio de interface v6lida:

public abstract interface RoIlable { }

Digitat o modificador abstract 6 considerado redundante; as interfaces serio implicitamente abstract caso voce

.ligite ou n6o abstract. 56 6 preciso saber que essas duas declarag6es sio vilidas e funcionalmente id6nticas:

public abstract interface Rol1ab1e { }

public interface Ro1lable { }

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

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

Public interface aounceable {

public abstract void bounce ( ) ;

cublic abstract void setBounceFactor(int bf) ;

ipor6m, digitar os modificadores public e abstract nos m6todos 6 redundante, i6 que todos os m6todos de

interface slo implicitamente publ ic e abst,ract. Dada essa regta, vocd pode ver que o c6digo a seguir 6 exatamente

equivalente a interface antenor:

public interface Bounceable {

void bounceO ; / / sem modificadores

void setBounceFactor (int bf) ; / / sem modificadores

]

Voc€precisalembrarquetodesosrn6todosdeinterfaces6opublic eabstract independentedoqueestivetoa

definigio daintetface.

procure m6todos de interface declarados com qualquercombinaglo que envolvapublic ou abstract, ou sem

modificadores. por exemplo, as cinco declarag6ls de m6todo a seguir, se declaradas dentro de uma interface, serio vilidas e

id€nticas!

void bounce O ;

.,, public void bounce O ;

abstract void bounce O ;

: Fubf ic abstract void bounce O ,'

abstract public void bounce O ;

As declarag6es de m6todos de interface abaixo nio serio compiladas:

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

/ /abstract j6 est6 imPlicito

Page 39: Java - Scjp 5 - Portugues

i static void bounce ( ) tI

I private void bounce O ,.

{I protected void bounce ( ) ;I

Declarando constantes de interface

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

"s.--!S?.cq_tls!.4ol9.

Ao colocar as constantes diretamente n ainterface,qualquer classe que impleme ntar aintefiace ter6 acesso direto isconstantes, como se as tivesse herdado.

Yo4-ef9gi.tilg lembrar de- uma reg,ra fundamental para constantes de interfaces. Elas devem sempte se1

nrrhlin et=f i^ +inal.

Isso parece simples, certo? Afinal, as constantes de interfaces nio sio diferentes de quaisquer outras constantes acessiveispublicamente, entio, obviamente elas precisam set declaradas como public, sLatic e f inal-. Mas, antes de pular orestante desta discussio, pense nas implicag6es:.pelo.f3r!o dg_ a.s.constantes de interfaces serem definidas em umaint-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 deinterfacessiosemprepublic eabstract,independentementedevoc6indicarissoounionoc6digo.qualgrefv"*gttf"d€ggde."9!9'-9.1F'4 tnre{-faqe-deJe sskgsg*4ltaBe-tlle 6 - uma constante publ i c . veja t. -'o.e .onr.grre percebero problema com o seguinte c6digo (assuma que sdo dois arquivos separados):

interface Foo {

int BAR = 42,.

void go O ;

)

class Zap implements Foo {

public void goO {

EAK = ZI'

lVocd 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, osaidigos a seguir sio todos iddnticos:

public int x = 1; // varece nao-static e n50-fina1, mas n50 6,ant x = 1; // parece defaul-t, ndo-final e ndo-static, mas ndo 6!statii i-nt x = 1; // Neo mostra final ou publicfinal int x = 1; // Ndo mostra static ou public6,,L] i^ ^r-!l^ l1luuaru >L4Lru ant x = 1; // Nao mostra final

^,,Ltl^ 4t*^1 r-yuuras larrdr rrrt x = 1,. / / Nao most.ra staticstatic final int x = 1 // Nd,o mostra publicpublic static final int x = 1; // o que voc6 recebe implicitamente

pualquer combinapio dos motlficadores necessriios (poriru in4licitos) d udlida, como tambdm o i o nlo artliqasio de modficadores! Noexame' espere encontrar perguntas as quais ndo podeni responder coretamenle, a ntenos qae saiba, por exempl0, qae y.f a.u,,!!!,t!!,! dg-innface .ffinal enanrapodenireceberumualordarlasseqaeaestiuerimp/emenlando(oadeqaa/qaeroarrarlasse).

JAVA 5 13

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

Page 40: Java - Scjp 5 - Portugues

14 Copitulo 1 : Declorogoes e Conirole de Acesso

Obietivo poro o CertificoEdo

Declarar Membros de Classes (Obietivos 1.3 e 1.4)

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

disso, usaridentificadoru legaispara nomes de uaridueis.

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

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

J6 vimos o que significa usar um modificadot em um a declangdo de classe, e agora veremos o que significa modificar uma

declatagdo de um m6todo ou uma vari6vel.

Os m6todos e as vari6veis de inst6ncias (nioJocais) sio conhecidos coletivamente como membros. Voc6 pode modificar

um membro que tenha tanto modificadores de acesso como modificadotes que nio se referem a acesso, e vocd tem mais

modificadorei para escolher (e combinar) do que quando est6 declarando uma classe.

Modificadores de Acesso

Pelo fato de os m€todos e vari6veis normalmente receberem controle de acesso exatamente da mesmas forma, abordaremos

ambos nesta segio.

Enquantoumaclasrcs6podeusardoisdosquatroniveisdecontoledeacesso(default oupublic),osmembros

podem usar todos os quatro:

r publicI protectI defaultI 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,excetopolumadiferengaqueser6mencionada posteriormente.

E crucial que voc6 saiba tudo sobre o controle de acesso par o exzme. Haver6 uma boa quantidade de Perguntas pataas

qoais voc6 dever6 usar o seu conhecimento sobre controle de acesso. Algumas quest6es testam v6rios conceitos de controle

de acesso ao mesmo tempo, enrio o desconhecimento de uma pequena parte que seja do assunto poder6lhe custar uma

questio inteira.

O que signific a o fatode o c6digo 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

classe B est6 visivel para a classe A. Quando uma classe nZo tem acesso a ouffo membro, o compilador vai brigar com voc6

por tentar acessar algo que voc6 nio deveria nem saber que existe!

Voc6 precisa entender duas quest6es difetentes telativas ao acesso:

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

I Se uma subclasse pode berdarwm membro da sua superclasse

O primeiro tipo de acesso ocorre quando um m6todo de uma classe tenta acessar um m6todo ou uma vari6vel de outra

.1"..., lrsr.rdo o operador ponto (.) para invocar um m6todo ou obter uma vari|veL Por exemplo:

class Zoo {

public String coolt"tethod ( ) ireturn "Wow babv";

)

class Moo {

nrrl.r'lin rrnid rrqpZ- ,'.___ *-_-\zoo(,) t

Zoo z = new ZooO;

/ / se a linha anterior compilar, Moo terS acesso

Page 41: Java - Scjp 5 - Portugues

JAVA 5 15

// d classe zoo

/ / Mas'.. . ser6 que tem acesso a coolMethodO ?

System.out.println("A Zoo says, " + z.coolMethod() );/ / A linha anterior funciona porque Moo pode acessar o

/ / mAraAn nrrl-r'] i a

lO segundo tipo de acesso refere-se a quais membros de uma supetclasse (se 6 que existem) uma subclasse pode acessaraftav€s da heranga. Nio estamos querendo saber se a subclasse pode, digamos, invocar um m6todo para uma instincia dasupetclasse (o que seria aPenas um exemplo do primeiro tipo de acesso). Em vez disso, queremos saber se a subclasse podeberdarum membro da sua superclasse. Lembre-se de que se uma subclasse herdaum membro, 6 exatamente como se a

subclasse tive sse declarado o membro ela mesma. Em outras palavras, se uma subclasse herdaummembro, efltao ela tem

esse membro.

class Zoo {

nrrhl i n (f ri na nnnl Morhnrl / \ IuvvrrrLuarvs \ / t

return "Wow baby";

l

class Moo extends Zoo {

public void useMyCoo1MethodO {

/ / Ser6, que uma instAncia de Moo herda coolMethod ( ) ?

System.out.println("Moo says, " + this.coolMethodO );/ / A J-inha anterior funciona porque Moo pode acessar o

/ / m6todo public

// Ser6. que uma instAncia de Moo pode invocar coolMethodQ em

/ / wma instAncia de zoo?

Zoo z = new ZooO;

System.out.pri.ntln("Zoo says. rr + z.coolMethodO );// coolMeuhodO 6 public. entao Moo pode invocd-Io em

/ / uma refer6ncia a zoo

)

)

A Figura 1,-2 faz a comparagdo entre uma classe herdando um membro de outra classe, e acessando um membro de outraclasse usando uma refer€ncia de uma inst6ncia dessa classe.

Muito do controle de acesso (ambos os tipos) se concentra em se as duas classes envolvidas estao no mesmo pacote ou em

Pacotes diferentes. N6o se esquega, no entanto, q,te se apnipria classe A nio puder ser acessada pela classe B, ent6o nenhummembro da classe A poderi, ser acessado pela classe B.

Vocd precisa saber o efeito de diferentes combinag6es de acesso a classes e membros (por exemplo uma classe padrao comuma vari6vel pubJ- ic). Para descobrir issq primeiramente observe o nivel de acesso da classe. Se a pr6pria classe nio forvisivel a outra, entio nenhum dos seus membros ser6 visivel, nem mesmo se forem declarados publ ie. Depois deconfirmar que a classe est6 visivel, 6 uma boa id6ia observar os niveis de acesso nos membros individuais.

Membros PublicQuando um m€todo - ou vatiivel-membro - 6 declarado publ i c, isso significa que todas as outras classes,independentemente do pacote ao qual pertengam, podem acessar o membro em questao (assumindo-se que a pr6pria classeesteia visivel).

Page 42: Java - Scjp 5 - Portugues

goFast (

dostuff (

goFast (

)

Convertible

doThings( ) {Sportscar sc = new Sportscar( ) tsc.goFas!( );)

16 Copftulo 1 : Declorog6es e Conlrole de Acesso

Driver

doDriverSEuff ( ) {Sportscar car = new Sportscar( ) tcar.goFast( );

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

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

Tr€s formas de acessar um m6todo:

(D)Invocando um m6todo declarado na mesma classe

(R) Invocando um m6todo usando uma referdncia da classe

(I) Invocando um m6todo herdado

Observe o seguinte arquivo-fonte:

package book;

import cert.*; // tmporta todas as

class Goo {

public static void main (String IJ

Sludge o = new SludgeO;

o.testIt O ;

)

i

classe do pacote certo

args) {

Agora observe o segundo arquivo:

narkanp acrl.

public class Sludge {

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

1)

Como vocd pode ver, Goo e Sludge estao em pacotes diferentes. Entretanto, Goo pode invocar o metodo em Sludge sem

problemas, porque t^nto a classe Sludge quanto o seu metodo test.It ( ) est6o marcados como public.Pan uma subclasse, se um membro da sua superclasse for declatado pub 1 i c, a subclasse herda esse membto,independentemente de se ambas as classes estarem no mesmo pacote ou nio:

Page 43: Java - Scjp 5 - Portugues

JAVA 5 17

n:^Lrd6 ^arf.

public class Roo {

public String doRooThings O {

/ / imagine o c6digo divertido que entra aquirafrrrn \fr1n/.

)

A classe Roo declara o membto doRooThings ( ) como publ i c. Assim, se criarmos uma subclasse de Roo, qualquerc6digo presente nessa subclasse Roo poderi chzmar o seu pr6prio m6todo doRooThings ( ) herdado.

package notcert; / / NEo 6 o pacote em que Roo se encontra

import cert . Roo;

class CIoo extends Roo {

public void testcloo ( ) {

System. out . println (doRooThings ( ) ) ;

l

]

Repare no c6digo anteriot que o m6todo doRooThings ( ) 6 invocado sem a necessidade de prefixi-lo com umareferdncia. Lembre-se de que se voc€ vir um mdtodo invocado (ou uma vad6.vel acessada) sem o operador ponto (.), issosigrrifica que o m6todo ou a vari6vel pertence i classe onde voc6 l'ru esse c6digo. Tamb6m significa que o m6todo ou avai6velest6 sendo implicitamente acessado(a) usando-se arefer€ncia this. Assim, no c6digo anteior,acharnadaadoRooThings ( ) na classe Cloo poderia tet sido escrita como thi s . doRooThings ( ) . A refer6ncia thi s semprese refere ao objeto sendo executado atualmente - em outras palavras, ao objeto que esteja rodando o c6digo quando voc6v6 a refer€ncia thi s. Pelo fzto de a rcfetdncia thi s ser impiicita, voc6 n6o precisa prefixar o seu c6digo de acesso a ela, masse 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 chamardoRooThings ( ) 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

I

Membros PrivateMembros marcados como private ndo podem ser acessados por c6digo em nenhuma ouffa classe que nio aquela na qual

o membro private foi declarado. Vamos fazer uma pequena modificagio na classe Roo apresentada em um exemploantedot.

package cert;public class Roo {

private String doRooThings ( ) {

/ / Imagine o c6digo divertido que entra aqui , mas apenas

/ / a c]-asse Roo sabe dissoratlrrn rrfrlnrr.

)

O m6todo doRooThings ( ) agora 6 private, entao nenhuma outra classe pode us6-lo. Se tentarmos invocar om6todo a partir de qualquer outra classe, teremos problemas:

Page 44: Java - Scjp 5 - Portugues

1 I Copitulo 1 : DecloroE6es e Controle de Acesso

package notcert;i mn^rf

^6rf D^^.+rrryv! e

cl-ass useAr{oo t

public void testlt o

Roo r - new RooO;qvcfam

^,,f nrintln

I)

.I

)

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

cannot find symbol

symbol : method doRooThings ( )

E como se o m6todo doRooThings ( ) nio existisse, e, no que diz respeito a qualquer c6digo fora da classe Roo, isso 6

verdade. Um membro private 6 invisivel para qualquet c6digo fora da pr6pria classe do membro.

E se uma subclasse tentasse herdar um membro private da sua supetclasse? Quando um membro 6 declaradoprivate, uma subclasse nio pode herdar dele. Pata o exame, voc6 precisa entender que uma subclasse nio pode ver, usare nem sequer pensar nos membros private da sua superclasse. Voc6 pode, no entanto, declarar um m€todocortespondenie na subclasse. Mas, nio importa asuaapai€.nci^,t Ao se irqta de um mdtodo substitutolEsimplesmente um m6todo que por acaso tem o mesmo nome que o m6todo private (de cuia existdncia voc6 nio devesequer saber) da superclasse. As regtas de substituigio ndo se aplicam, de forma que voc6 pode fazer esse m6todo "rec6m-declarado-que-por-um-mero-acaso-6-o-mesmo" declarar novas exceg6es, ou modificar o tipo de retorno, ou qualquer otrtracoisa que voc6 queira fazer com ele.

nanlrana rarf .

public class Roo {

private String doRooThings ( ) {

// Imagine o c6digo divertj-do que entra aqui, mas nenhuma

/ / orttra classe saber6 dissoreturn "fun" -

.lO m6todo doRooThings ( ) agora est6 fora do alcance de todas as subclasses, at6 mesmo aquelas que esteiam no

mesmo pacote que a superclasse:

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

class Cloo extends Roo { / / fuao bem aj-nda, a superclasse Roo 6 prlblicapublic void testClooO {

System. out.prj-ntl-n (doRooThings O ) ; / / Erro de compilaqdo !

lSe 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

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

em ueqde acerd-/a diretamente. Os ndtodos de acesso conpatiueis con JauaBeans t€m aforna get<noneDaPropriedade) ou, para booleanos,

is<noneDaPropriedade> e set<nomeDaPropriedade>, efornecem um lugar onde uocd pode uerifcar e f oa ua/idar antes de retomar ou

tt

// Ate aqui, tudo bem; a classe Roo 6 prlblica(r.doRooThingsO ) i // Erro de compilaqdol

Page 45: Java - Scjp 5 - Portugues

JAVA 5 19

modficar um ualar.

Sem usaprotepdo, a uari,iuel weight ('pesa') de an objeto Cat, por exempl0, poderia ur defnida nmo tlm nilmem negatiuo caso o cddigo

in@npiado tenba acesso direto i uaiduel publ ic, coml em somecat . weight = -20. Mas un mdtodo dz acesto, setweight(int wt), podeia uerifcar se o nilmem d @ropiado. (Ok, tudo isso d especulagdo, mat estamos partindo do prina?io de qae un peso negatiuo

poderia ser in@ropriado para am gato. Ou ndo.) O Capitalo 2 divutinl esta prutu(Ao de dadot (enc@ulanento) com mais detalhes.

E possivel um m6todo private ser substituido por uma subclasse? Essa 6 uma pergunta interessanre, mas a resposta,tecnicamente, 6 nio. Uma vez qve a subclasse, como vimos, nio pode herdar um m6todo private, ela, portanto, naopode substituir o m6todo - a substituigio depende da heranga. Abordaremos as implicag6es disso com mais detalhes maisadiante 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 deum mesmo ou de diferentes Dacores.

O efeito do controle de acesso privado

Subclasse

Driver

doErrivy'sruff( ){Spo9(sCar car = new Sportscar( );c9r'.gd(ast( );

co\eZliUfe con = nehr convert.ible( );

r'ffit"tt l'

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 DefaultOsniveisdeconuoledeacessoprotect edefault sioquaseid€nricos,mascomumadiferengafundamental.Ummembro de f aul t s6 pode ser acessado se a classe que o estiver acessando pertencer ao mesmo pacote, enquanto que ummembro protect pode ser acessado (atrav6s da heranga) por uma subclasse rnesmo se e subclasse estiuer em urnpacote diferente.

Observe as duas classes seguintes:

nanl::ao narf i f i z--- *--*JaEfon,.

public class OtherClass {

SportsCar

goFast ( ) {...}dosEuff ( ) {goFast ( ) ,

]

Convertible

Page 46: Java - Scjp 5 - Portugues

20 Copftulo 1 : DecloroE6es e Controle de Acesso

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

/ / indica acesso padrao

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

)

Em um outro arquivo de c6digo-fonte voce tem o seguinte:

package somethingElse ;

imnarf aarf i f i nrf i nr ntharr-l rae.+LLrFv! e

class AccessClass {

static public void main(Stringtl args) {

Othercl-ass o = new OtherClassO;o. testIt O ;

j'Como pode ver, o mdtodo testlt ( ) do ptimeiro arquivo tem acessopddr1o (ot seja, de niveldopacote). Repare tambemque a classe OtherClass se encontra em um pacote diferente de AccessClass. Serl que AccessClass poder6 usar o m6todot e s t f t O ? Vai causar um erro de compilagdo? Ser6 que o Daniel vai se cas ar colr, aFrancesca? Nio perca os pr6ximoscapitulos.

No method matching testlt O found in class

certification. Othercfass. o. testlt ( ) ,'

Pelosresultadosacima,voc€podeverqueAccessClassniopodeusarom6todotestlt O deOtherClassporquetest.It O temacessopadtio,eAccessClassnioest6nomesmopacotequeOtherClass.Assim,Accessclassn6opodev6-la, o compilador reclama, e n6s nao temos nem id6ia de quem sejam Daniel e Ftancesca.

Os comportamentos def ault e protect diferem apenas quando falamos sobre subclasses. Se a palavra-chaveprotected fotusadaparadefinirummembro,qualquersubclassedaclasseque fazadeclangdopodeacess6-lo atrauisda

heranga. N6o faz diferenga se a superclasse e a subclasse estao em pacotes diferentes, o membro da superclasse protectainda 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 nioser que a subclasse esteia no mesmo pacote que a superclasse.

Enquanto que o acesso padrio nio estende nenhum considetagdo especial is subclasses (ou voc6 est6 no pacote ou nioesti), 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 Pensarem protect, pense em?acnte + kids.IJma classe com um membro protect esti marcando esse membro como tendoacesso de nivel do pacote pata todas as classes, mas com uma excegio especial para subclasses fora do pacote.

Mas o que significa uma subclasse de fora do pacote ter acesso a um membro (parent) da supetclasse? Significa que a subclasse

herda o membro. Nio significa, no entanto, que a subclasse de fora do pacote possa acessar o membro usando uma refer6ncia a

umainstinciadasuperclasse.Emoutfaspalavfas,protecL =henn7a,Protect niosignificaqueasubclassepossatrataro membro protect da superclasse como se ele fosse publ ic. Assim, se a subclasse de fota do pacote obtiver umarefer6ncia i superclasse (cdando, por exemplq uma instAncia da superclasse em algum lugar no c6digo da subclasse), a subclassenio pode usar o opetador ponto na refet€ncia i superclasse para acessar o membro protec. Para uma subclasse de fora dopacote, um membro protect poderia da mesma forma ser def aul-t (ou mesmo privado), quando a subclasse est6

usandoumarefer€nciaisuperclasse.Asubclasses6podeveromembroprotect atrav6sdaheranga.

Est6 confuso? N6s tamb6m. Agriente firme e tudo ficar6 claro com a s6rie de exemplos segrintes. (E ndo se Preocupe, na

verdade, nio estamos confusos. Estamos apenas tentando fazt-lo se sentir melhot caso voc6 esteia confuso. Sabe, tipo niotem problema se voc€ estiver achando que nada faz sentido, e ndo 4 culpa sua. Ou serd que 6? <insira isada mal€vola aqui>)

Detalhes de protectVamos dar uma olhada em uma vari6vel de instincia protect 0embre-se de que uma vari6vel de instdncia 6 ummembro) de uma superclasse.

package certif ication ;

public class Parent {

protected int x = 9; // acesso protectI

O c6digo acima declara a vari6vel x como protected. Isso ^totn acersiael a todas as outfas classes dentm do Pacote

certification, bem como herdduelpor gttaisquer subclasses defora do pzcote. Agora vamos criar uma subclasse em um pacote

Page 47: Java - Scjp 5 - Portugues

JAVA 5 21

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

package other; / / Pacote diferenteimnnri- carfi fiaal-inn Drranf.

class Child extends Parent {

public void tesrlr ( ) {

System. out . printl-n ( "x i_s \ + x) ; Sem problema; Childherda x

)

O c6digo acima compila sem problemas. Repare, no entanto, que a classe Child estd acessando a vari6vel protect atrav6sdahetanga. Lembre-se, sempre que falarmos de uma subclasse ter acesso a um membro de uma superclasse, podetiamosestar falando de a subclasse herdar o membro, e nio simplesmente acess6-lo atrav6s de uma referdncia a uma ins tdtcia dasupetclasse (que 6 a forma como qualquer ouua nio-subclasse o acessaria). Repare no que acontece se a subclasse Child (forado pacote da superclasse) tentar acessar uma variivel protect usando uma referencia i classe Parent.

package other,.

import certif ication. Parent ;

class Child extends Parent {

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

System. out . printl-n ( "x is

Parent P = new Parento;

System. out.println ( "X in

" + x) i // Sem prdblema; Child/ / herda x

// Podemos acessar x usando

// a refer6ncia a p?

parent is " + p.x); // Erro de compilaqSol

l

O compilador alegtemente nos mostra qual 6 o problema:

9'i:rr=n -d nl- ho- /alai I .l i --'-u . vurrLr/ Lrlf fu. Jqva

other/Child.java:9: x has protected access in certification.ParentSvsl-em otrt nrinf ln($X in naranf iq rt r n v\.yqlgllur9-y.^l'

^,u ;;:.*belecemos que um membro p ro t e c t tem, essencialmente, acesso de nivel do pacote ou padrio a todas as classes,

exceto as subclasses.J6 vimos que as subclasses de fota do pacote podem herdar um membro prot.ect. Finalmente, j6vimosque as subclasses de forado pacotenao Podem usarumafefer6nciadi superclasse paraacessarum membropratecl. Perauma subclnsse deforq do pacotq o membro protect stf pode ser acessado otraaes da heranqa.

Ainda h6 mais uma questZo que nao consideramos... Q"ul 6 a apar€ncia de um membro protect para outras classes quetentem usar a subclasse de fora do pacote para obter o membro protect da superclasse que foi herdado pela subclasse?Por exemplo, usando as nossas classes Parent/Child anteriores, o que acontece se uma outra classe - digamos, Neighbor -do mesmo pacote que Child (subclasse) tiver uma refer€ncia a uma instincia de Child e queira acessar a vari6vel-membrox?Em outras palavns, como esse membro protect se comporta depois que a subclasse o herdou? Ele mant6m o seustatus de protect, de forma tal que as classes no pacote de Child possam v6Jo?

Nio! Depois que a subclasse de fora do pacote herda o membro protect, ele (conforme herdado pela subclasse) torna-seprivate para qualquer c6digo de fotada subclasse, com a excegio das subclasses dessa subclasse. Assim, se a classeNeighbor instanciat um obieto Child, entdo mesmo se Neighbot estiver no mesmo pacote que Child, Neighbor nlo teriacesso i vari6vel x herdada (mas protect) por Child. Resumo da hist6ria: quando uma subclasse de fora do pacote herdaum membto protect, esse membro torna-se essencialmente private dentro da subclasse, de forma tal que apenas a

subclasseeassuassubclassespodemacess6lo.AFigural-4ilustraoefeitodoacessoprotect sobreclassesesubclassesno mesmo ou em diferentes pacotes.

Carambal Com isso terminamos protected, o modificador mais incompreendido emJava. Novamente, ele s5 6 usadoem casos muito especiais, mas pode ter certezade que aparecer6 no exame. Agora que j6 abordamos o modificadorpro-tected, passaremos para o acesso padrio, uma molezacomparado a protect.ed.

Page 48: Java - Scjp 5 - Portugues

22 Cqpitulo 1 : Declorog6es e Controle de Acesso

Detalhes de DefaultVamos comegar com o comportamento padrd.o de um membro de uma superclasse. Modificaremos o membro x de Parent

panrorn6-lo def ault.package certif ication;public class Parent {

int x = 9; / / Aus€ncia de modificadores de acesso

/ / indica acesso padrSo (de pacote)

)

Repare que nio colocamos um modificador de acesso na ftentedavai|vel x. Lembre-se de que, se voc€ nio di.grtar ummodificador 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

convergible

Pacote B

Chave:

Pacote A

l--D'i'"'_lT^^t,I er," g t.

goFast( )t ]

Convertible

Convertible f c;;ctb;l[H-elf *1"". *l

E-tr-ll

Onde goFast 6Declarado namesma classe.

dofhings ( ) {Sportscar sc = new Sportscar( ),sc.goFast( );

l

lnvocando goFast$ usando-se uma Refer-6ncia A classe na qual goFastQ foideclarada.

r------------1I dot'tore( )( fI sorast( );IIt I.L-.r-F:'=*[Invocando

goFast$ usando.se uma Refer6nciad classe na qualgoFast$ foideclarada.

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 : xSystem.out.println("Variable x is " + x) t

1 errorO compilador nos d6 o mesmo erro de quando um membro 6 declarado como private. A subclasse Child (em umpacote diferente do da superclasse Parent) ndo 6 capaz de ver nem usar o membro padrio x da superclasse! Agora, e quantoao acesso padrio para duas classes do mesmo pacote?

package certif ication ;

public cl-ass Parent{

Page 49: Java - Scjp 5 - Portugues

JAVA 5 23

int x = 9; // acesso padrao

)

E, na segunda classe, voc6 tem o segrinte:

package certif ication ;

class Child extends parent{

static public void main(StringlJ args) {

Child sc = new Chi_IdO;

sc. testIt O ,.

i)

public void testrr O {

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

)

)

O c6digo-fonte acima compila sem problemas, e a classe Child roda e exibe o valor e x. Basta se lembrar de que os membrospadrio ficam visiveis par:-as subclasses apenas se elas estiverem no mesmo pacote que a superclasse.

Variiveis Locais e Modificadores de AcessoOs 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 comc6digo como o seguinte:

class Foo {

void doSruff O {

private int x = 7;

this.doMore(x);

]

Pode ter certeza de que qualquer vari6vel local declarada com um modificador de acesso fieo vai compilar. Na verdade. s6existe 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 deacesso e visibilidade; 6 uma boa id6ia passar algum tempo estudando-a. Em seguida, vamos passar para os outrosmodificadores (nio-referentes a acesso) que voc€ pode apltcar a declarag6es de membros.

Tqbelo I -2 Determinondo o Acesso o Membros de Closses

Visibilidade Pubtc Protect Default Private

A partir da mesma classe Sim Sim Sim Sim

A partir de qualquer classe do mesmo pacote Sim Sim Sim Nio

A partir de uma subclasse do mesmo pacote Sim Sim Sim N6o

A partir de uma subclasse de fora do mesmo pacote Sim Sim, atrauis Nio Nioda heranga

A partir de qualquer classe que nio sejauma subclasse e esteia fora do pacote

Sim Nio N6o Nio

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 umavariivel de instdncia) aparar de outra classe. Isso ainda nio inclui uma s€rie de outros modificadores que vocd pode usar emdeclarag6es de membtos. Dois deles j6 lhe sio fami-liares - f inal e abstract -, porque n6s os aplicamos a

Page 50: Java - Scjp 5 - Portugues

24 Coollulo I : Decloroc6es e Conirole de Acesso

declaraE6es de classes anteriormente neste capitulo. Mas ainda temos de dar uma ripida olhada em trans ient, syn-chroni zed, nat ive, strictf p, e depois uma longa olhada no grande modificadot - stat ic.

Veremos primeiro os modificadores aplcados a m6todos, seguidos pelos modificadores aplicados a vari6veis de instAncias'

Fecharembs esta segao com uma olhad" .- .orno stat ic funciona quando aplicado a vari6veis e m6todos.

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

de um objeto String), vocd nio poder6 substituir a matorizdos m6todos nas bibliotecas de classes fundamentais. Essa

restrigio quanto a soUstitoigao propicia boa seguranga, mas voc6 deve us6-la com muito cuidado. Impedir que uma

subclasse iubstitua um metodo invatida muitos dos beneficios da orientagao a obietos, incluindo a estensibilidade atravds

do polimorfismo. Uma declaragio de m6todo f inal tipica se pareceria com isto:

class SuperClass{

public fj-na1 void showSamPle O {

System. out . println ( "One thing . " ) ;

)

E v6lido esrender SuperClass, umavez qwe a classe ndo esti marcada como f inal-, mas nio podemos substituit o mdtodo

f inaf showsample ( ) , como o seguinte c6digo est|tentando f^zetl

class SubClass extends SuperClassi

public void showSampleO { // Tentando substituir om6todo

/ / f:-na:-- da suPerclasse

System. out . println ( "Another thing . " ) ;

)

Se tentar compilar o c6digo acima, voc6 receberi uma mensagem como esta:

?javac FinalTest.javaFinalTest.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 FinalOs argumentos de m6todos sio as declarag6es de varidveis que aparecem entre par€nteses na declatagio de um m6todo. Uma

declaragdo de m6todo tipica, com multiplos afgumentos, se Parece com o seguinte:

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

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

f ileNumber e recordNuniber seguem todas as regras aplicadas avari6veis locais. Isso significa que elas tamb6m

podem ter o modificador f inal-:public Record getRecord(int fileNumber, final int recNumber) { }

Nesteexemplo,avartfivelrecordNumber 6declaradacomofinal,oquesignificaobviamentequeelanlopoder6sermodificada 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 AbstractUm m6todo abstract 6 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,

Page 51: Java - Scjp 5 - Portugues

JAVA 5 25

emvez disso, com ponto-e-virgula. Em outras palavras, eIa ndo tem uru corpo de ndtodo. Voc6 marca um m6todo comoabstract quandoquerforgarassubclassesaforneceraimplementagloemquestao.Porexemplo,seescreverumaclasseabstract Car com um m6todo goupHi 11 ( ) , voc6 poderia desejar forgai todos os subtipos de Car adefinir o seupr6pdo comportamento de goupHill ( ) , especifico dquele tipo determinado de carro.

public abstract void showSample O ;

Repare que o m6todo abstract termina com ponto-e-virgula emvezde chaves. E, inv,i,lido ter um rinico m6todoabstract. que seja em uma classe que n6o seia declarada explicitamente como abstractl Observe a seguinteclasseinvilida:

publi-c class I1lega1C1ass{

public abstract void dolt O ;

)

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

f11ega1Class. java: 1 : class Il1ega1C1ass must. be declaredabstract.It does not define void doftO from cl_ass I11ega1C1ass.public cLass I11ega1Class{

1 errorvoc6 pode, no entanto, ter uma classe abstract sem nenhum m6todo abstract.compilar sem problemas:

publi-c abstract cl_ass LegalClass {

void goodMethodO {

/ / insira um monte de c6digos reais de implementagdo aqui)

1J

O seguinte exemplo ir6

No exemplo anterior, goodMet.hod ( ) nio 6 abstract. Tr€s dicas diferentes lhe dizem que nio se trata cle umm6todo abstract:I O m6todo nio est6 marcado como abstract.I A declaragio do m6todo inclui chaves, em vez de terminar com ponto-e-virgula. Em outras palavras, o m6todo tem um

corpo de m6todo.

I O m6todo inclui c6digo de implementagio.

Qualquer classe que estenda uma classe abstract deve implementar todos os m6todos abstract da superclasse. anio ser que a subclasse tambdn seia abst.ract. A tegra 6 a seguinte:

Aprimeirasubclasseconcretadeumaclasseabatraet deveimplernentattoda.sosm6todosabst,ract dasupetclasse.

Concretosignificaapenasnio-abstract,entao,sevoc€tiverumaclasseabstract estendendooutraclasseab-stract, a subclasse abst.ract nio precisa fornecerimplementag6es para os m6todos abstract herdados. Maiscedo ou mais tatde, no entanto, algu6m vai ctiat uma subclaise nio-abstract (em outras palavras, uma classe que podeserinstanciada), e essa subclasse teri de implementar todos os m6todos abstract de cima para baixo na 6rvore de-heranga. O seguinte exemplo demonstra umaLrvorede heranga com duas classes abstract e uma concreta:

public abstract class Vehicle {

private String type;public absrract void goUpHitl O ; / / M6tod.o abst.ractpublic String gerType O { / / M6rodo neo-absrract

return t)4)et

lpublic abstract class Car extends Vehicle {

public abstract void goUpHill O ; / / X:-naa abstractnrrhl i a rrni r{ dan--TLi -^^ / \ Iyqvrf v vvrq uvvqr rrrrrrgD \ / t

/ / C6digo especial para o carro entra aqui

Page 52: Java - Scjp 5 - Portugues

26 Copitulo I : Declorocoes e Controle deAcesso

I)

ll

public class Mj-ni extends Car ipublic void goUpHilI ( ) t

/ / c6digo especifico para o Mini subir ladeiras

i

]

Entio, quantos m€todos tem a classe Mini? Tr6s. Ela herda os m6todos getType O e doCarrhings O , porque eles

sio pfblicos e concretos (nio-abstract). Mas, pelo fato de goupHill ( ) ser abst.ract na superclasse Vehicle, e

nunca ser implementado na classe Car (permanecendo abstract, portanto), isso significa que a classe Mini - como a

primeiraclasseconcretaabaixodeVehicle-precisaimplementatom6todogoupHill O.Emoutraspalavras,aclasseMini nio pode deixar a implementagio do m6todo abstract pa:.aapr6xjrr'a classe abaixo dela na 6rvote dehetanga,

mas a classe Car pode, porque Car, como Vehicle,6 abstract. A Figura 1-5 ilustra os efeitos do modificador ab-stract sobre subclasses conctetas e abstratas.

Os m6todos abstract devem set implementados por umasubclasse 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 m6todosabstract da superclasse. A classe AcmeRover 6 nio-abs t rac t, entao ela precisa implementar o mdtodo ab -stract declarado na sua superclasse, SUV e precisaimplementar tamb6m turn ( ) , que nio foi implementado porSL]V

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

Ptocure por classes concretas que nio fornegam implementag6es pata m6todos abstracL da superclasse. O seguinte

c6digo nio vai compilar:

public abstract class A {

abstract void foo ( ) ;

)

classBextendsA{void foo(int r) { }

iA classe B nio vai compilar porque ela ndo implementa o m6todo abstract herdado f oo O . Embora o m6todo

f oo ( int I ) da classe B parega ser uma implementagio do m6todo abstract da superclasse, na verdade €

simplesmente um m6todo sobrecarregado (um m6todo que usa o mesmo identificador, mas diferentes argumentos)' enteo

ele nio atende ao requisito de implementagdo do m6todo absLract da superclasse. Veremos as diferengas enresubstituigio e sobrecarga com mais detalhes no Capitulo 2.

Um m6todo nio pode nunca, jamais, ser marcado como abstract e f inal ao mesmo tempo, nem como ab-stracL e private ao mesmo tempo. Pense um pouco - os m6todos abstract precisam ser implementados (o

absttact Car

startEngine( )

abstract gaFor'ward( )abstract reverse( )

stop( )abstract turn(int whichWay)

absEracE SW

startEngine( ) // opcionalrd( | // requerido

reverse( ) // requeridoturn ( int rdhichway) //requerido

enable4wd( )goForward( )

reverse ( )

abst.ract gooffRoad( )

// rttrn{\ nin imnlamenEado/ I vsLLL .lJrtyrvttt.

enable4wd( \ // oPclonaLgoOffRoad( ) // requeridoturn (int, whichWay) //requerido

Page 53: Java - Scjp 5 - Portugues

JAVA 5 27

que na pr6tica significa serem substituidos por uma subclasse), enquanto que m6todos f inal e private ndo podemjamais ser substituidos por uma subclasse. Ou, dizendo de outra forma, uma designagio abstract significa que asuperclasse nlo sabe nada sobre como as subclasses devem se comportar no m6todo Lm questio, enquanro que umadesignagio f ina l- significa que a superclasse sabe tudo sob.r como todas as subclasses lpor -"1, afastadas qr.re estejam na6rvore de heranga) devem se comPortarno m6todo em quest6o. Os modificadores abst;act e f inal- siopraticamente 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 comoabstract.Finalmente,voc6precisasaberqueomodificadorabstract niopodenuncasercombinadocomomodificadorstat ic. Abordaremos os m6todos stat ic mais adiante .r.rt. obl.ti-ro, mas, por zgora,bastalembrar que o seguinteseria inv6lido:

abstract static void doStuff ( ) ;

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

MyClass.java:2: i1lega1 combi-nation of modifiers: abstract and<f ^l- i ^

abstract static void doStuff O;

M6todos SynchronizedA palavra-chave s)mchroni zed indica que um mdtodo s6 pode ser acessado por um thread de cada vez. N6sdiscutiremos isso i exaustio no Capin lo 9, mas, por agora, tud; o que nos intereisa 6 saber que o modificador synchro_nized s6podeseraplicadoamdtodos-ndoavari6viis,nemclasses,apenasam6todos.Umadeclarag6osynchronizedtipica se parece com a seguinte:

public synchronized Record retrieveUserlnfo(int id) { }

Voc6 precisa saber tambdm que o modificador synchroni zed. pode ser acompanhado por qualquer um dos quatroniveis de controle de acesso (o que significa que ele pode ser usado juntamente com qualqueiu-" d", t C, palavras-chavemodificadoras de acesso).

M6todos NativosO modificador native indica que o m6todo est6 seodo implementado conforme aplataformz,freqtientemente e C.Voc6 n6o precisa saber como usar m6todos nativos pano etim.,basta saber qu. tr-ii.re € um modificador (e, ponantquma palavra-chave reservada) e-que nat j-ve s6 pode ser aplicado a mdtodos - ndo a classes, nem avai6veo,

"p..rui a

m6todos. Repare que o corPo de um m6todo nativo deve ser ponto-e-virgula O (como m6todos abstraci), indicandoque a implementagao foi omitida.

M6todos StrictfpVimos anteriormente o uso de strictfp como modificadot de classe, mas, mesmo que voc6 nio declare uma classecomo str j-ct f p, ainda assim voc€ poderi declarar um m6todo individual como strictf p. Lembre-se de questrictfp forgaospontosflutuantes(equaisqueroperagoescompontoflutuante)aaderirem aopadriolEil,ET54.Com strictf p,6 possivel prever como os seus pontos flufuantes se comportarao,independentemente daplatafotmasubjacente na qual aJ\M esti rodando. O inconveniente disso 6 que, se aplitaformasubjacente for capazde srrportar 11mamaior 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 nioptecisasabernadasobrestrictfp al6mdasuautilidade,dofatodequepodemodificarumad,eclangdodeclasseoudem6todo, 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 deonde voc€ pesquisar, poderd ver essa caPacidade ser chamada de "listas de argumentos de extJnsio v ariivel';,,,argumentosvari6veis", "vat-args","vatatgs" ou o nosso favorito (saido do departamento de obscuridad e),"patdmetrocom nfmerovari6vel 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 desteLivro.

I argumentos Aquilo que voc6 especifica entre pardnteses quando est6 inuocantlowm m6todo:

dostuff("a", 2l; // estamos invocando dostuff, entdo a & 2 sao argumenrosI patdmettos Aquilo na assinatura dom6todo indica o que o m6todo deve receber quando forinvocado:

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

Page 54: Java - Scjp 5 - Portugues

28 Copftulo 1 : Declorog6es e Conlrole de Acesso

// pardmexros: String e int

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

pamvar-args:

I Tipo var-atg Quando declara um pardmeftovar-arg, vocd deve especificar o tipo do(s) argumento(s) que esse

p"ia-.t.o do seu m6todo pode recebet. @ode ser um tipo primitivo ou um tipo de obieto.)

I Sintaxe b4sica Para declarar um mdtodo usando um parAmetro vat-arg, voc€ escreve depois do tipo um sinal de

retic€ncias (...), um espagq e depois o nome do array que ir6armazenar os parimetros recebidos.

I Outfos pardmetros E v6lido tef outfos parametros em um m6todo que use um vaf-afg.

I Lirnites dos var-args O var-arg deve ser o riltimo parametro na assinatura do metodo, e voc€ s6 pode ter um var-arg

por m6todo.

Vejamos algumas declarag6es com var-argvdlidas e invilidas:

Vdlidas:

void doStuff (int... x) { }

void doStuff2 (char c, int

void doStuff3 (Animal-... animal)

Invdlidas:

void doStuff4(int x...) { }

void doStuffs(int . x, char...void doStuff6 (String. . . s, byte

espera de 0 a muitos intscomo parAmetros

t ) / / es9era Primeiramente um char,

// e depois de o a muitos ints

{ } tt de 0 a muitos Animals

/ / sin1caxe incorretay) { } //mais deumvar-argb) { i / / var-arg tem de vir por rlltimo

x)

Declarag6es de Construtores

Foo2O { }

private Foo2 (byte

Foo2 (int x) { iFnal/inf v inl-

EmJava, os obietos sio construidos. Sempre que voc€ cria um novo obieto, pelo menos um construtor 6 invocado. Toda

classe tem um construtor, e, se voc6 nio criar um explicitamente, o compilador vai criar um para voc€. Existem toneladas de

regtas relativas aos construtores, e iremos deixar a discussio detalhada para o Capinrlo 2.Por agota,vamos nos concentrar

flas regras b6sicas de declaragio. Eis um exemplo simples:

class r.oo t

protected FooO { }

protected void Foo O { }

)

/ / este 6 o construtor de Foo

A primeira coisa a se reparar 6 que os construtores se parecem um bocado com m6todos. Uma diferenga fundamental 6 que

11rrl .orrrtr.rtor n6o poie nonca, i"mais, ter um tipo de retorno.., Nunca! As declarag6es de construtores podem ter, no

entanto, todos os modificadores de acesso normais, e podem usar argumentos (incluindo var-args), da mesma forma como

os m6todos. A outra REGRA IMPORTANTE a se entender sobre os constmtores 6 que eles devem ter o mesmo nome

que a classe no qual sio declarados. Os construtores nio podem ser matcados como s t at i c (afinal eles sio associados

com instanciaminto de objetos), nio podem ser marcados como f inaL nem abstract (porque ndo podem ser

substituidos), Eis algumas declarag6es de construtores v6lidos e invalidos:

cJ-ass Eooz I

/ / consLrutores vSlidos

este 6 um m6todo com um P6ssimo nome,

^^-6h rrilidayvr err,

b){}

v) t)

Page 55: Java - Scjp 5 - Portugues

JAVA 5 29

/ / constTutores invSLidos

void Foo2 O { } / / 6 um m6t.odo, ndo um consrrur.orFooO { \ / / n5o 6 nem m6todo nem conscruuorFoo2 (short s) ,. / / se parece com um m6todo abscraccstatic Foo2(float f) { } // ndo pode ser staticfinal Foo2 (long x) { } / / ndo pode ser fj_naIabstract Foo2 (char c) { I t t ndo pode ser abstractFoo2(int.. x, int t) { } tt sintaxe var-arg lncorreEa

Declarag6es de Variiveis

ryi

Existem dois tipos de vari6veis emJava:

I Primitivos Um primitivo pode ser de oito tipos diferentes: char, boolean, byte , short , int ,long, double ou f l-oat. IJmavez declarado, o seu tipo primitivo nio pode nunca ser modificado, embota namaioria dos casos o seu valor possa se modificar.

I Vari6veis de refet€ncia As vari6veis de referdncia sio usadas para se referir (ou acessar) um objeto. Uma variavel dereferdncia 6 declarada como sendo de um tipo especifico, e esse tipo nio pode nunca ser modificado. Uma vari6vel derefer€ncia pode ser usada para referit-se a qualquer objeto do tipo declarado , ou de tm subtipo do ipodeclarado (umtipo compativel). Falaremos muito mais sobre o uso de uma vari6vel de referCncia para referir-se a tlm subtipo noCapitulo 2, onde discutiremos o polimorfismo.

Declarando Primitivos e Interralos de PrimitivosVari6veis primitivas podem set declaradas como vari6veis de classe (stat ic), varidveis de instincias, parimetros dem6todos 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, apresenraremosapenas alguns exemplos de declaragSes de vari6veis primitivas:

byte b,'

boof ean myBooleanprimit ive ;

l nf v / / decl-ara tr6s primi_tivos j_nt

Em vers6es anteriores do exame, voc€ precisava saber como calcular intervalos para todos os primitivos J ava. Para o exameatual, voc€ pode pular alguns detalhes, mas ainda 6 impotante entender que, para os tipos intiiros, a seqtidncia 6 (do menotpara o maior) byte, short, int e long, e que doubles sio maiores do que floats.

Voc€ tamb6m precisar6 saber que os tipos num6ricos (tanto inteiros quaflto de ponto flutuante) sio todos assinalados, ecomo 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 quepodem ser negativos ou positivos. O bit mais i esquerda (o digito mais significativo) 6 usado para representar o sinal, emque 1 significa negativo e 0 sigmfica positivo, como mostrado na Figura 1-6. O resto dos bits ..p..r..rturn o valor. usando anotaqao de base 2.

I/

sinal

\ I

00100r.1

t__=\bit fe valores

111110100000011

bitde sinal: 0 - positivo 1 = negativo

bits de valores:

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

short: 1 5 bits podem representar 21 s ou 327 68

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

Figuro 1-6 O bit de sinol de um byte

short

bit de

Page 56: Java - Scjp 5 - Portugues

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

f6rmula -2&it" -r) pa112- calcular o intervalo negativo, e usamos -l&its

- t) - 1 pata o intervalo positivo. Novamente, se voc€

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

Tobelo l-3 Intervolos de Primitivos Num6ricos

Tipo Bits Bytes Intervalo Minimo Intervalo Miximo

b)'t' 21 -1

short t6 )15 a15 1

5Z1nt.r3r )3r 1

long oz+ 163 a63 IL _L

float JZ n/d n/d

double n/d n/d

O intervalo para nimeros de ponto flutuante 6 complicado de determinar, mas felizmente voc6 nZo precisa sab6-los para o

exame (embora 6 esperado que voc6 saiba que um double ^rmazen^

64 bits, e um float armazena32).

Para tipos booleanos nlohdum intervalo; um booleano s6 pode ser true ou false. Se algu6m lhe perguntar a

profundidade de bits de um tipo booleano, olhe bem nos olhos da pessoa e diga "depen de da mdqutna vktual" . F,la

ficar6 impressionada.

O tipo char (um caracter) cont6m um s6 caracter Unicode de 16 bits. Embora o coniunto ASCII estendido conhecido como

ISO Latin-1 precise de apenas 8 bits Q56 carzcteres diferentes), 6 necess6rio um intervalo maior pata rePresent^t car^ctetes

encontrados em linguas diferentes do ingl6s. Os caracteres Unicode, na verdade, sdo representados por ndmeros inteiros de

16 bits nio-assinalados, o que significa 216 tipos possiveis, que vio de 0 a 65535 Q\ -1. No Capitulo 3, voc6 aprender6 que,

pelo fato de um char ser na verdade um tipo de nrimero inteiro, ele pode ser atribuido a qualquer tipo de nfmero grande o

suficiente p^tz ^rm^zenar

65535 (o que significa qualquer coisa maior do que um tipo short. Embora tanto chars quanto

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 Refer6nciaVari6veis de refet€ncia podem ser declaradas como variiveis s t at i c, vari6veis de instincias, parAmetros de m6todos ou

vari6veis locais. Voc6 pode declarar uma ou mais vari6veis de referCncia, do mesmo tipo, em uma mesma linha. No Capitulo

3, discutiremos as virias maneiras pelas quais elas podem setirnciahzadas, mas por agot^^presefltaremos apenas alguns

exemplos de declarag6es de vari6veis de refer€ncia:

Object o;

Dog myNewDogRe f erenceVariable ;

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

Variiveis de lnstinciasAs 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

oz+

/ / ouLros c6digos aqui, incluindo os metodos de acesso para campos privados

Page 57: Java - Scjp 5 - Portugues

JAVA 5 3I

A classe Employee antetior diz que cada instAncia de employee saber6 qual 6 o seu pr6prio nome, titulo e gerente. Emouras 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, existemdisting6es sutis, mas ocasionalmente importantes enfte os termos, contudo, elas nio sio usadas no exame.)

Parao exame,voc6 ptecisa saber que as varidveis de inst6ncias

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

I Podem sermarcadas como f inalI Podem sermatcadzscomo transientI Nio podem sermarcadas como absLract.I N6opodem sermarcadas como sinchroni-zedI Nio podem sermatcadas como strictfpI Niopodem sermarcadas como nativeI Nio podem set marcadas como stat. ic, porque isso as transformatia emvati|veis de classe.

J6 abordamos os efeitos de se aplicar controle de acesso a vari6veis de instincias (funciona da mesma maneira que param6todos membros). Um pouco adiante neste capin:lo, veremos o que significa aplicar o modificador f inal oo t.ran-sient zumavari|ve.Tdeinstincia.Primeiro,daremosumar6pidaolhadanadiferengaentrevari6veisdeinstAnciasevariiveis locais. A FiguraT-7 compara amaneirapelaqual os modificadores podem set aplicados a m6todos em contrastecom varidveis.

Vari6veis locais Varidveis (nioJocais) M€todos

final finaLnrrhf i ^yuvf+e

protectedprivatest.at. ict

transientvolatile

tinaLnrrl.r'l'i aysvrre

hr^|-a-l-aAFr vevv ues

nrirr.f-a

D LdLIU

abstractsynchronized

c|-ri al-fn

native

iguro l-7 ComporoEdo de modificodores pqro vori6veis x m6fodos

Variiveis Locais (Automatic/Stack/Method)Varidveis locais sio aquelas declaradas dentro de um m€todo. Isso significa qu e avai|velnd.o 6 apenas inrciahzzda dentro dom6todo, mas tamb6m declarada dentto dele. Assim como a vari6vel local iticjaasua vida denffo do m6todo, ela tamb6m 6destruida quando o m6todo finaLzz. As vari6veis locais frcam sempre na pilha, e nio no heap (Falaremos mais sobre a pilhae o heap no Capinrlo 3). Embora o valor da vanivel possa ser pass ado para, digamos, outro m6todo que enrao ^r^^"in ovalor 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 objetopropriamente dito ainda ser6 criado no heap. Nio existe um objeto de pilha, apenas umavari6vel de pilha. Voc6frlqiientemente ouvird programadores usarem a expressio "objeto local", o que eles realmente querem dizer 6 "variivel derefer6ncia declarada localmente". Assim, se ouvir um programador usar essa expressio, vocd sabir6 que ele 6 simplesmentepreguigoso demais parausar o termo tdcnico mais preciso. Voc6 pode dizer a ele que n6s afirmamos is so - a nio ser que elesaiba onde nos moramos.

As declarag6es de varidveis locais nio podem usar a maioria dos modificadores que podem ser aplicados a vari6veis deinstincias, tais como public (ou os outros modificadores de acesso), transient, vo1ati1e, abstract oustatic, mas, como vimos anteriormente, as vari6veis locais podem ser marcadas como f ina1. E, como voc€ aprender6no- Capitulo 3 (mas aqui vai um adianto), antes que uma vari6vel local possa ser usada,ela precisa ser inicialiTada.o- ,r-valor. Por exemplo:

Page 58: Java - Scjp 5 - Portugues

32 Copitulo I : Decloroc6es e Controle de Acesso

class Testserver {

public void loglnO {

int count = 10;l)

llNa maioria dos casos, voc€ vai iticiahzat umavariivel local na mesma linha em que a declarar, embora voc6 possa ainda terde rcintciall2|-la depois, no m6todo. A chave 6 se lembrar de que uma vari6vel local precisa s er iniciabzada antes de voc6tentar 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 dom€todo logln ( ) . Novamente, nio queremos dizer com isso que o valor de count n6o possa ser passado pan fon dom6todo para comegar uma nova vida. Mas a vari6vel que armazena esse valor, count, nio pode ser acessada depois de om6todo frnaltzar, como o seguinte c6digo inv6lido demonstra:

class Testserver {

public void logInO {

int. count = 10;

)

nrrl.r"l in rrnid dnenmafhina/int i \'...-', t

count = i; // Ndo vai compilarl Nao 6 possivel acessar count

// de fora do m6todo loginoI)

),4E possivel declarar uma.vari6vel local com o mesmo nome que uma vari6vel de instincia. Isso 6 conhecido comosonbreamento, 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

iO c6digo acimaproduz a seguinte saida:

loca1 variable count is 10

instance variable count is 9

Mas por que razdovoc6.iiaquerer fazer isso?

Normalmente, voc6 n6o vai. Mas uma das raz6es mais comuns € pan dzr a um parAmetro o mesmo nome que a vai6vel de

instAncia i qual o parimetro ser6 atribuido. O seguinte c6digo (incotreto) est6 tentando definir o valor de uma vari6vel de

instAncia usando um parAmetro:

class Foo {

int size = 27;

Page 59: Java - Scjp 5 - Portugues

JAVA 5 33

hrr'|.\'l i ^

r'^.i A raf qi to (inf <.i zo\ IIJu!fre vvfu Deuer-s\frrL ofzs/ I

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

)

]

Entio vocd decidiu que - para melhor Iegibilidade - voc€ qu er dx ^o

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

class Foo {

int size = 2'7 ;

public void setsize(int size) {

this. size = size ; / / L}ris. size significa a vari6vel de instAncia/ / do objeto atual , slze. O valor de size

// d, direita 6 o parametro

lll

Declarag6es de ArraysEmJava, os arrays sio objetos qve

^rmazen m mriltiplas vari6veis do mesmo tipo, ou varilveis que sio todas subclasses do

mesmo tipo. Os attays podem arm^zeflar owprimitivos ou referdncias a obf etos, mas o pr6prio anay serS,sempre umobieto no heap, mesmo se o array for declarado paraarmzrzerrar elementos primitivos. Em outras palavras, nio existe umarray primitivo, mas vocd pode criar um array de primidvos.

Para o exame, voc6 precisa saber ffes coisas:

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

I Como criar um objeto array (construir)

I Como preencher o array com elementos (inicializar)

Para este obietivo, voc6 s6 ptecisar6 saber como declarar um array; n6s abordaremos a construgio e airttciilrzagdode artays noCapitulo 3.

AO TRABALHO

Os analt sdo efcientes, mat muitat uerys uoci det/ard usar am dos tipos Collecion fu j ava . ut i 7 (incluindo HashlvIap,ArrayList e TreeSet). At classes Collection oferecen maneiras na*fuxzueis de acessar am objeto (para inurgdo, apaganentl,/eitara e assim por diante) e, ao contniio dos ara1s, podem se expandir ou contrair dinamicamente i medida que uoci adiciona ou remoaeelementos. Existe un tipo Collection para ltma amp/a gama de necessidadu. Vocd precisa de una classifcagdo nipida? De /4n grupt de objetotsen dup/icatas? De uma maneira dn acessar um par de nome-ualor? O Capituk 7 os aborda com nais detalbes.

Os arrays sio declarados informando-se o tipo de elementos que o alray iri arrnazefl r (um objeto ou um primitivo),seguido por colchetes em um dos lados do identificador.

Derlaranclo um Arral de Pinitiuot

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

int key I J ; / / colchetes depois do nome (v61ido, mas menos legivel)

Declarando am Aray de Refer1ncias a Obietos

Thread [ ] threads;

Thread threads [ ];

/ / Pccnmond:dn

// val-i-do, mas menos leglvel

AO TRABALHO

Ao declarar ama referincia a anq,\ uoci deue sempre co/ocar o: colchetet do aralt imediatamente depois do tipo du/arado, em ueqde depois doidentfrcador (nome da uariduel). Dusaforma, qualqaer um qae leia o aidigo sabertlfaci/menh qaq por exenpl0, ke1 i uma referlncia a umobjXo de arrEt int, e ndo um pimitiuo int.

Page 60: Java - Scjp 5 - Portugues

34 Copiiulo 1 : Declorog6es e Controle de Acesso

Podemos tamb6m declarar arrays multidimensionais, que, na verdade, s6o arrays de arrays. Isso pode ser feito da seguintemaneira:

String[ J t ] [ ] occupantName;

String I J ManagerName [ ];O primeiro exemplo 6 um array ridimensional (um array de arrays de anzys), e o segundo 6 bidimensional. Repare nosegundo exemplo, o quzltnz um par de colchetes antes do nome da vari6vel e um par depois. Isso 6 perfeitamente v6lidopara o compilador, provando mais uma vez que o fato de ser vdlido nio necessariamente indica que 6 bom.

OBSERVAQ6BS pene O EXAME

Nanca d adlido inclair o tamanho do arral na saa declaragdo. Sim, n6s sabertos que uocd podefaryr isso em algumat outras linguagens, que ia raqdo pela qual uoci podeni uer uma questdo ou duas que ineluam aidigo parecido com o seguinte:

int [5] scores;

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

fa1 dtferenga.

No Capitulo 3, passaremos um bom tempo discutindo arrays, como os trnciahzar e usar, e como lidar com arrays

multidimensionais... Fique l-igado!

Variiveis FinalDeclararumavari6velcom^palaw^-ch^vefinal impossibilitaareutilizagiodessavari6veldepoisdeelatersidoiniciahzada 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 xvai permanecer como 10 para sempre. Isso 6 bem simples para primitivos, mas o que significa terwmavai|vel de referdncia

aobjeto f inal?Umavari6veldereferdnciamarcadacomo f inal- nSopode jamaisserrearibuidaparareferir-seaumobjeto diferente. Os dados dentro do objeto podem ser modificados, mas a varidvel de refer€ncia n6o pode set modificada.Em outras palavras, uma referdncia f inal- ainda lhe permite modificar o estado do objeto ao qual se refere, mas voc6 niopode modificar avairdveldercfer€nciaparafaz€-laserefeir a um obieto difetente. Decore isto: nio existem objetos f inal,apenas referdncias f inal. Explicaremos isso com mais detalhes no Capinrlo 3.

Agora jd estudamos como o modificador f inaL pode ser aplicado a classes, m6todos e vad6veis. A Figura 1-8 mostra as

principais caracteristicas e diferengas das virias aplicag6es de final.

classe a clasrc f j-nal- ndo

mdtodo o nrltodo f inal nio

classe Roo

fi"al i"t sir. =42;

,roi-ffi"rrgsize (

a uariduelf inal niopode receber um valornovo, depois de ter sidocriado o m6todo inicial (a

auibuigio inicial de um

classe final Foo

cfasse Bazfinrl rrnirl an/ \vvru Jv \ /

classe Bat estende Ba

rinaffid so ( )

variivel

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

Page 61: Java - Scjp 5 - Portugues

JAVA 5 35

Vari6veis TransientSe marcar uma vari6vel de instdncia como transient, voc6 estar6 dizendo dJ\M para ignorar ess avaiilvelquando vocetentat 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 deinstincias) em um tipo especial de stream de E/S. Com a serializagio vocd pode salvar um objeto em um arquivo, ou at6enviilo affav6s de uma conexio para ser "re-inflado" (deseridtzado) do outro lado, em outraJ\M. A serializagio foiadicionada ao exame na vetsioJava 5, e falaremos dela com mais detalhes no Capitulo 6.

Vari6veis VolatileOmodificadorvolatile diziJVMqueumthreadqueacesseavari6veldevesemprereconci-liarasuac6piaprivateda vari6vel com a c6pia master ptesente na mem6ia. Como 6 que 6? Nio se preocupe com isso. Para o exame,tudo o quevoc6precisasabersobrevolatile 6que,assimcomotransient,essemodificadors6podeseraplicadoavari6veisde instAncias. Nio se engane, a id6ia de multiplos threads acessando uma vari6vel de instAncia € assustadora, e 6 muitoimportante que todo progtamadorJava a entenda. Mas, como ver6 no Capinrlo 9, voc6 provavelmente usar6 asincronizagio, 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 StaticOmodificadorstatic 6usadoparacizrvai|veisem6todosqueirioexistirindependentementedequaisquerinstdnciascriadasparaaclasse.Emouftaspalavras,osmembrosstatic existemantesmesmodevoc6criarumanovainstinciadeuma classe, ehaver| apenas uma c6pia do membro stat ic, independentemente do nrimero de instdncias dessa classe.Em outras palavras, todas as instAncias de uma dada classe compartilham o mesmo valor para qualquervait6vel stat ic.Falaremos de membros static com mais detalhes no pr6ximo capitulo.

O que voc6 pode marcar como static:I M6todos

I Vari6veis

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

I Blocos de inicializagdo

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

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

I Classes (a nio ser que esteiam aninhadas)

I Interfaces

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

M6todos de classes internas e vari6veis de instincias

Vari6veis locais

Declarando Enums

A partit da versio 5.0,Java lhe permite restringir uma vari6vel para ter um de apenas uns poucos valores prd-definidos - em outraspalawas, 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 delanchonetes, voc6 poderia desejar reduzir os tamanhos de caf6s possiveis a BIG ("gande"), HUGE ("enorme') e OVER-WHELMING ('absurdo'). Se voc6 deixar a possibilidade que um pedido de tamanho LARGE ("grande') seja feito, issopoderia causar um erro. Entram em agdo os enums. Com a simples declatagio a seguir, vocd poder6 garantir que ocompilador o impedir6 de atribuir qualquer coisa a um Coffeesize que nio seja BTG, HUGE ou OVERWHELMING:

enum CoffeeSize { erc, HUGE, oVERwHELMING };Dai em diante, a rinica maneira de se obter um Co f f e e s i z e ser6 com um a declaragdo parecida com esta:

CoffeeSi-ze cs = CoffeeSize,BIG;

Nio 6 obrigatdrio que as constantes enums estejam escritas totalmente em mairisculas, mas, tomando emprestado daconvengio de c6digos da Sun que detetmina que as constantes tenham os seus nomes em mairisculas,6 uma boa id6iafaz€Jo aqui.

II

Page 62: Java - Scjp 5 - Portugues

36 Copftulo I : Decloroc6es e Controle de Acesso

Os componentes b6sicos de um enum sio as suas constantes (ou seja, BIG, HUGE e OVERWHELMING), emboravoc€v6 ver logo adtante que pode haver muito mais em um enum. Os enums podem ser declarados como as suas pr6priasclasses separadas, ou como membros de classes, mas nlo podem ser declarados dentro de um m6todo!

Declarando um enum fora de uma classe:

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

/ / private nem protect

class Coffee {

CoffeeSize size;lJ

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 somentecomomodificadorpublic ouodefault,assimcomoumaclassenio-interna.Eisumexemplodedeclaragiodeerrum dentro de uma classe:

^lc-Lass uorreez {

enum coffeesize {erc, uuce, oVERWHELMTNG }

CoffeeSize size;I)

public class CoffeeTest2 {

public static void main(Stringtl args) {

Coffee2 drink = new Coffee2 O ;

drink. size = Coffee2 . CoffeeSize . BIG; ,z/ incluindo classes

/ / nome requerido

)

lJ

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

O seguinte exemplo NAO 6 v6lido:

public class CoffeeTestl ipublic static void main(Stringtl argts) {

enum coffeesize { erc, HUGE, oVERWHELMTNG } // ERRADo! Nao se

/ / pode declarar enums

// em m6todos

Coffee drink = new Coffee O ;

drink. size = CoffeeSize.BIG;

)

I)

Panfazer as coisas ficarem mais confusas pzravoc€,os elaboradores da linguagem Java frzeram opcional a colocagdo de

Page 63: Java - Scjp 5 - Portugues

JAVA 5 37

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

public cl-ass CoffeeTestl- i

enum coffeesize { erc, HUGE, OVERWHELMTNG I; / / .- o ponto-e-virgula| / < ^^^: ^-^-// e opcrona_L aqu]-

public statj.c void main(StringtJ args) {

Coffee drink = new Coffee O ;

drink. si_ze = CoffeeSize.BIG;

)

)

P"lT,o que 6criado quando voc6 cria um enum? O mais importante a se lembrar 6 que enums nlo sio Strings nemints! CadaumdostiposenumeradosdeCoffeeSize 6naverdadeumainstinciadeCoffeeSize.Emou-traspalavras, BIG 6 do tipo Cof f eeSize. Pense em um enum como um tipo de classe, que 6 parecido (mas nioexatamente) com isto:

,// exemplo conceitual- de como voc6

/ / pode entender os enums

class CoffeeSize {

public static final CoffeeSize BTG =

new Cof f eeSize (..BIG,' , 0) ;

public static flnal CoffeeSize HUGE =

new CoffeeSize ('.HUGE,,, I) ;

public static final CoffeeSize OVERWHELMTNG =

new CoffeeSize (.'OVERWHELMfNG,,, 2 ) ;public CoffeeSize(String enumName, int index) {

// mais coisas aquiI)

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 tipoCof 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 osenumssdodeclaradosfazdiferengz.Voc€podepensarnosenums deCoffeeSj-ze iomofazendopatedieumarraydo tipo Cof f eeSi ze, e, como ver6 em um capitulo postedor, voc6 pode iterar atrav6s dos valor de um enuminvocando o m€todo val-ues ( ) em qualquer tipo de enum. Q.,Tio se preocupe com isso neste capitulo.)

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

Voc6poderia criar algtm tipo de tabela de busca, usando alguma outra estrutura de dados, mas isso seria um design ruim ededificilmanutengio.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 momentoem que os enums forem inicializados, passando um valor ao construtor do enum. Isso precisa ser explicado com umpouco mais de detalhes, mas, primeiramente observe o seguinte 6fdigo:

enum CoffeeSize {

Page 64: Java - Scjp 5 - Portugues

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;

)

private int ounces; / /

publj-c int getounces O iral- rrrn nrrndac.

i

/ / atrtbu]. o valor a

t | .._^ ----r:-re1 de instancia/ / uttt4 vd!r4!

uma vari6vel de instdncia que o valorde cada enum tem

)

acJ_ass colIee t

CoffeeSize size; cada instAncia de Coffee tem um

enum CoffeeSize

public static void main(StringIJ args) {

Coffee drinkl = new Coffee O ;

drinkl . slze = CoffeeSize.BIG;

Coffee drink2 = new Coffee O ;

drink2 . size = CoffeeSize.OVERWHELMING;

System. out . println (drinkl- . size . getounces ( ) ) ;

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

8

16

exibe

exibe

]

Os principais pontos a se lembrar sobre os constflrtores de enums sio:

f NUNCA 6 possivel invocar um construtor de enum diretamente. Esse construtor 6 invocado automaticamente! com

os argumentos que vocd define ap6s o valor da constante. Por exemplo, BIG ( I ) invoca o construtor Cof f eeSizeque usa um int, passando o int literal 8 ao construtor. (I',los bastidores, 6 claro, voc6 pode imag1nar que BIGtamb6m 6 passado ao construtor, mas nio precisamos saber - nem nos importarmos com - os detalhes.)

I Vocd pode definir mais de um argumento para o construtor, e pode sobrecarregat os construtores do enum, assim

como pode sobrecarregar um construtor normal de classes. Discutiremos os construtores com muito mais detalhes noCapitulo 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 umconstrutor em Cof f eeSize que usa tanto um int quanto uma string.

E, finalmente, voc6 pode definir algo realmente estranho em um enum, que se pafece com uma classe intema an6nima

(sobre a qual falaremos no Capinrlo 8). E o chamado corpo de classe especifico da constate, e voce pdoe us6Jo quando

precisar que determinada constante substitua um metodo definido no enum.

Imagine este cen6rio: voc6 quer que os enums tenham dois m6todos - um para ongas e um para c6digo de registro (uma

String). Agora imagine que a muorja dos tamanhos dos caf6s usa o mesmo c6digo, "8", mas o tamanho OVERWHELM-

ING usa o tipo "A'. Voc6 pode definir um m6todo getlidcode ( ) no enum Cof f eesize que retorne "8", mas

..rr. ."ro rro.6 precisa de uma forma de substinriJo para OVERWHELMING. Voc6 nio quer colocar um c6digo if / thende dificil manutengio no m6todo getlidcode ( ) , entio a melhor saida poderia ser fazer com que a constante OVER-WHELMING de alguma forma substitua o m6todo getlidCode O .

Isso parece esttanho, mas voc6 precisa entender as regras bisicas de declaragio:

Page 65: Java - Scjp 5 - Portugues

JAVA 5 39(-nffcaQ i za I

BIG(8),

HUGE (r_0) ,

OVERWHELMING ( 16 )

public String

t // ininie rrmt t,

/ / o "corpo"getlidcode O {

bloco de c6digo que definapara esta constante

// substitua o m6todo

/ / definido em Coffeesizereturn rrA";

)

); // .- o ponto-e-virgulaCoffeeSize (int ounces) {

this.ounces = ounces;

)

private j-nt OUnCeS;

public int get.Ounces O {

reEurn ounces;

)

public String get.LidCode ( )

6 OBRIGAT6RIO quando h6 um corpo

{ // este m6t.odo 6 subsriruido| / ^^1/ / pe!a consranre OVERWHELMING

rafrrrh !rQrr.

)

)

/ / o va\or padrao que queremos retornar/ / para as constantes CoffeeSize

Ap6s absorver o material d,este capitulo, voc€ dever6 estar familiarizado com algumas das nuances da linguagemJava. Voc6poder6 talvez se sentir confuso sobre por que teve a id6ia de fazer este exame. Iiso 6 normal a esta altura. Caio esteiaouvindo a si mesmo dizendo "onde eu estava com a cabega?",basta se deitar e descansar at6 que isso passe. N6sgostariamos de poder dizer que fica mais f6cil, que este foi o capitulo mais dificil e que daqui em diante fica tudo menoscomplicado...

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

Haverd muitas quest6es indiretamente relativas a palavras-chave, entao, certifique-se de que sabe identificar quais siopalawas-chave reais e quais ndo sio.

Embora as convengoes de nomeagio como o uso de camelCase nao caiam diretamente no exatne, ainda assim voc6 ter6 deentender 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 dec6digo-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 viucomo os modificadores de acesso @ub1ic, protected e private) definem o controle de acesso de uma classe ouum membro.

Voc€ aprendeu que as classe,s abstract podem conter tanto m6todos abstract quanto nio-abstract., mas quese um s6 m6todo for marcado como abstract, entao a classe deve ser marcada como abstract. Nio se esquega deque uma subclasse concreta (nio-abstract) de uma classe abstract deve fornecerimplementagdes para t;dos osm6todos abstract da superclasse, mas que uma classe abstract nio precisa implerientar os m6todos ab-stract da sua superclasse . Uma subclasse abstract pode "passar a boli" paraapiimeira subclasse concreta.

Examinamos a implementagio de interfaces. Lembre-se de que as interfaces podem estender uma outra interface (oumesmo multiplas interfaces), e que qualquer classe que implemente uma interface deve implementar todos os m€iodos detodas as interfaces da drvore de heranga da interface que a classe est6 implementando.

Page 66: Java - Scjp 5 - Portugues

40 Copftulo I : Decloroc6es e Controle de Acesso

Tamb6m vimos os outros modificadores, incluindo static, f inal-, abstract, synchronized e assim pordiante. Voc6 aprendeu como alguns modificadores nunca podem ser combinados em uma declangdo,pot exemplo,misfurar abstract com f inal- ou pri-vate.Tenha em mente que nio existem obietos f inal ernJzva. Uma variivel de refer6ncia marcada como f inal- nuncapoder6 ser modificada, mas o objeto a que se refere pode ser modificado.

Voc6 viu que f inal aplicado a m6todos significa que uma subclasse nio os poder6 substituir, e, quando aplicado a umaclasse, 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 zetoa muiros argumentos do tipo declarado), mas que voc€ s6 pode ter um var - arg por m6todo, e ele deve ser o ultimoparAmetro 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 tamb6mcontef 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 umavairivel de instincia apartu da classe onde reside, porque ele nio tem uma referdncia explicita a nenhuma instenciaparticular 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 comom6todos, 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 voc6estiver 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 RipidoLembre-se de que quando falamos de classes neste capihio, estamos nos referindo a classes n6o-internas, ou classes de nivel

mais alto. Dedicaremos todo o Capitulo 8 is classes internas.

ldentificadores (Objetivo | .3)E Os identificadores podem comegar com uma letra, um underscore, ou um caracter monet6rio.

E Depois do primeiro car^cter,os identificadores podem incluir tamb6m digitos.

E Os identificadores podem ter qudquer extensio.

D Os mEtodosJavaBeans devem ser nomeados usando-se camelCase e, dependendo do prop6sito do m6todo, devem

comegar com set ("define'), get ("obt6m'), i s("6'), add("adiciona") ou remove.

Regras de declaragSo (Objetivo l.l)E Um arquivo de c6digo-fonte s6 pode ter uma classe priblica.

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

D O arquivo s6 pode ter uma instrugio de pacote,por€m,v6izs de importaqdo.

E A instrugeo de pacote (se houver) deve ficar na primeira linha (fora os comentarios) do arquivo de c6digo-fonte.

E A instruq6o de importaqio (se houver) deve vir depois do pacote e antes da declaragio de classe.

O Se nao houver instrugio de pacote, as instrug5es de importagio terZo que ser as primeiras (fora os comentArios) do

arquivo de c6digo-fonte.

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

E O arquivo pode ter mais de uma classe nio priblica.

Page 67: Java - Scjp 5 - Portugues

JAVA 5 4I

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

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

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

E Criar uma instdncia de outra classe

E Estender (ou criar subclasses) outra classe

E Acessar m6todos e vari6veis de outra classe

Modificadores de classe (n6o referentes a acesso) (Objetivo 1.2)E As classes tamb6m podem ser alteradas com f ina1, abstract ou strictfp.E Uma classe nio pode ser f inal- e abstract.E Uma classe f inal- n6o pode ter subclasses.

E Uma classe abstract nio pode serinstanciada.

E Uma classe com somente um m6todo abstract significa que a classe inteira deve ser abstract.E Uma classe abstract pode ter m6todos abstracts ou ndo.

E Aprimeiraclasseconcretaaestenderumaclasseabstract ter6queimplementartodososm6todosabstracts.

lmplementagio de interfaces (Objetivo 1.2)D Asinterfacessiocontratosquedefinemoqueaclassepod,er6.fazer,masndodtzemnadasobreamaneirapelaqualela

deverS,faz€-Io.

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

E A interface 6 como uma classe 100%o abstract, e ser6 implicitamente abstract caso voc6.ligite ou nio omodificadot abs t rac t na declaragd.o.

E Uma interface s6 pode ter m6todos abstracts, nenhum m6todo concreto 6 permitido.

El Osm6todosdasinterfacessio,porpadrio,public eabstracts -adeclaragioexplicitadessesmodificadores6opcional.

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 doque coostar na declarag6o da interface.

E Deve manter a assinatura (sio permitidos retornos covariantes) e o tipo de retorno exatos dos m6todos queimplementa (mas nio precisa declarar as exceg6es da interface).

E Umaclassequeestiverimplementandoumainterfacepodeelapt6priaserabstract.

E Umaclassedeimplementagioabstract nloprecisaimplementarosm6todosdainterface(masaprimeirasubclasseconcreta pfecisa).

E A classe s6 pode estender uma classe (sem heranga multipla), por6m, pode implementar v6rias.

E As interfaces podem estender uma ou mais interfaces.

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

E Quando ftzer o exame,vetifique se as declaragSes de interface e classe sio v6lidas antes de verificar outrasl6gcas do c6digo.

Page 68: Java - Scjp 5 - Portugues

42 Copftulo I : Decloroc6es e Controle de Acesso

Modificadores de acesso a membros (Obietivos 1.3 e 1.4)E Os m6todos e as vari6veis de inst6ncia (nio locais) sdo conhecidos como "membros".

fl Os membros podem usar todos os quatro niveis de acesso: public, protected, def aul-t, private.

E O acesso aos membros se d6 de duas formas:

D O c6digo de uma classe pode acessar um membto de outra classe

f,l Uma subclasse pode herdar um membro de sua superclasse.

E Se uma classe ndo puder ser acessada, seus membros tamb€m ndo poderio.

E A visibilidade da classe deve ser determinada antes da dos membros.

D Os membros pub 1 i c podem ser acessados por todas as outras classes, mesmo de pacotes diferentes.

D Se um membro da superclasse for publ i c, a subclasse o herdat6 - independente do pacote.

fl Os membros acessados sem o operador ponto (.) t6m que pertencer i mesma classe.

D tnis sempre referenciarS.o objeto que estiver sendo executado no momento.

fl tnis.aMethod( ) 6omesmoquesimplesmentechamaraMethod( ).

E Os membros private s6 podem ser acessados por um c6digo da mesma classe.

D Os membros private n6o ficam visiveis p^r^ as subclasses, portanto, nZo podem ser herdados.

E Os membros def ault e protect s6 diferem quando subclasses estio envolvidas.

B Os membros def ault s6 podem ser acessados por outras classes do mesmo pacote.

E Os membros protect podem ser acessados por outras classes do mesrno pacote, al6m de pot subclasses,

independente do pacote.

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

E Por subclasses externas ao pacote, o membro protect s6 pode ser acessado affavEs da heranga: uma subclasse

externa ao pacote nio pode acessar um membro protect usando a refer6noa a uma instAncia da superclasse (em

outras palavras,ahetangzb o rinico mecanismo para uma subclasse externa ao pacote acessaf urn membro protectde sua superclasse).

D Um membro protect herdado por uma subclasse de outo pacote nio pode ser acessado por nenhuma outra

classe do pacote da subclasse, exceto Pelas pr6prias subclasses dessa.

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

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

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

Outros modificadores - membros (Objetivo 1.3)

E Os m6todos f inal nio podem ser sobrecarregados em uma subclasse.

E Os m6todos absgract foram declarados, com runa assinarura, um tipo de retorno e uma cl6usula throws opcional,mas nio foram implementados.

E Os m6todos abs t rac t terminam com urn ponto-e-virguIa, e ndo chaves.

E H6 tr6s maneiras de identificar um m6todo n6o abstract :

E O m6todo ndo 6 marcado como abstract.E O m6todo possui chaves.

E O mdtodo possui um c6digo entre as chaves.

E Aprimeiraclassenio-abstrata(concreta)aestenderumaclasseabstract deveimplementartodososmdtodosab-stract dessa.

D O modificador synchroni zed s6 6 aplicado a m6todos e a blocos de c6digo.

O Osmdtodos synchronized podemterqualquercontroledeacessoetamb6mseremmarcadoscomo f inal.

E Os mdtodos abstract devem ser implementados por rxna subclasse, porantq tem de ser herdados. Por essarzzdo:

E Os m6todos absuract ndo podem ser private.

E Os m6todos absLract nio oodem ser f inal.

Page 69: Java - Scjp 5 - Portugues

JAVA 5 43

E O modificador nat ive s6 6 aplicado a m6todos.

D Omodificadot strictfp s6 6apJicado aclasses em6todos.

M6todos com Argumentos Vari6veis (var-args) (Objetivo 1.4)E A partir de Java 5,os m6todos podem declarar um p ardmetro que aceita de zero avdriosargumentos, 6 o chamado

m6todo var-arg.

O Um parimetrov^r-zrgedeclarado com a sintaxe tipo... nome; por exemplo:

doStuff (int... x) { }

E Um m6todo var-arg s6 pode ter um parim etro var'zlrg.

E Em m6todos com parimetos normais e um var-arg, o var-arg deve vir por ultimo.

Declarag5es de Vari6veis (Objetivo 1.3)fl As vari6veis de instincia podem:

E Ter qualquet tipo de contole de acesso

E Seremmarcadas como finaL ou transl-entD Asvari6veisdeinstAncianiopodemserdeclaradascomabstract, sychronized, nativeoustrictfp.D E valido declatar uma v ari|vellocalcom o mesmo nome de uma vari6vel de instincia; isso 6 chamado de

"sombreamento".

E As variiveis f inal apresentam as seguintes propriedades:

E Nao podem ser reinicializadas, uma vez que tiverem um valor atribujdo.

E As vari6veis de refer6ncia f inal- ndo podem referenciar um objeto diferente se j6 tiverem um objeto atribuido aelas,

E Asvaridveisderefer6nciafinal devemseriniciahzadasantesqueaexecugiodoconstrutorsejaconcluida.

E N6o existem obietos f inal-. Uma refer€ncia a obf eto marcadacomo f inal- n5o significa que o obieto propriamentedito 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 doattay.Por exemplo, se Horse estender Admal,entd,o um objeto Horse pode ser colocado em um arav di Animal.

Vari6veis e m6todos static (Objetivo 1.4)D Nio sio associados a nenhuma instincia especifica da classe.

E Nio6necessiriaaexistdnciadainstinciadeumaclassepataqueosmembrosstatic destasejamusados.

D 56 haveri um a c6pia da vaidvel ou classe s tat i c e todas as instdncias a compartilhario.

E Os m6todos static nio tdm acesso direto a membros nio-static

Enums (Objetivo 1.3)E Um enum especifica uma lista de valores constantes que podem ser atribuidos a um determinado bpo.

D Um ertum ndo 6 uma String nem um int; o tipo constante de um enum 6 o tipo do pr6prio enum . por exemplo,INVERNq PRIMAVER T, VERAO e OUTONO sio do tipo enum Estagio.

Q Um enum pode ser declarado fora ou dentro de uma classe, rnas ndoem um m6todo.

E Umenum declarzdoforadeuma classeadopodesermarcadocomstatic, f inal , absLract, pro-tected ou private.

Page 70: Java - Scjp 5 - Portugues

44 Copitulo I : Decloroc6es e Controle de Acesso

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

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

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

E Os construtores enum nuncapodem ser chamados diretamente no c6digo.Eles sio sempre chamados

automaticamente quando um enum 6. irttcidtzado.

" r':f *:j ilt il:i;l:*io

deum enum 6 opcionar Ambos sio v6ridos:

Teste IndividualAs 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 c6digof. 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? (Marquetodasas €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 ; }

3. Qual das seguintes afirmativas 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

^t ^a^^

Page 71: Java - Scjp 5 - Portugues

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

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

B. int 123;

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

F. int *divide;G. int central_sales_region_Summer_200S_gross_sa1es ;

5. Quais nomes de m6todos obedecem ao padreo favaBeans? (Marquetodas as corretas)A. addSize

B. getcustC. deleteRepD. isColoradoE. putDimensions

6. Dado o c6digo:l-. cl-ass voop {

2. public static voi_d main(String tJ args) {

3. doStuff (1) ;

4, doStuff (7,2) ;Fl

l

5. / / insira c6digo aqui

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

A. static void doStuff(int... doArgs) { }

B. static void doStuff (int [ ] doArgs) { }

C. static void doStuff(inr doArgs...) { }

D. static void doStuff(int... doArgs, int y) t iE. static void doStuff(int x, int... doArgs) { }

7. Quais das seguintes opg6es sao declarag6es v6lidas? (Marque todas as corretas.)A. short x [ ];B.shorttly;C. short[5] x2;D. short z2 [5] ;

E. short t I z I I t l;F, short t I y2 = [s] ;

Page 72: Java - Scjp 5 - Portugues

46 Copitulo 1 : DecloroE6es e Controle de Acesso

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

3. String sound;

4- Animals(String s) { sound = ", }

6. class TestEnum {

7. static Animals a;

8. public static void main(StringtJ args) {

9. System.out.println(a.DoG.sound + r\ * + a.FISH.sound) ;

r-0. )

11. )

Qual 6 o resultado?

A. woof burbleB. Multiplos erros de compilagio

C. A compilagio falha devido a um erro na linha 2

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

E. A compilag6o falha devido a um ero naltnha 4

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

9. Dado o c6digo:r. enum A t A ]

2. class E2 {

3. enum B t iJ l4. voidcO {

s. enumo{o}b. l

7. j

Quais das aEtrmaivas sio verdadeiras? (I\{arque todas as corretas.)

A. O c6digo compila.

B. Se apenas a linha 1 for temovida, o c6digo compila.

C. Se apenas ahnha3 for removida, o c6digo compila.

D. Se apenas a linha 5 for removida, o c6digo compila.

E. Se as linhas 1 e 3 forem removidas, o c6digo compi,la.

F. Se as linhas 1,3 e 5 forem removidas, o c6digo compila.

Respostas do Teste Individual1. C e D estio coffetas. C esti correta porque uma classe abstract nio precisa implementar nenhum dos m6todos

da sua interface. D esti correta porque o m6todo est6 implementado coretamente.

A est6 incoreta porque as interfaces nio implementam nada. B est6 incorreta porque as classes nio estendem interfaces.

E est6 incorreta porque os m6todos de interfaces sio implicitamente publ ic, entao os m6todos sendo

implementados precisam ser publ i c (Objetivo 1.1)

2. B est6 correta. As classes abstract nio precisam ter nenhum m6todo abstract.A est6 incorreta porque os m6todos abstract devem ser marcados como tais. C est6 incoreta porque n5o 6

possivel ter um m6todo abstract sem que a classe seja abstract. D est6 incorreta Porque apalzvra-chave

abst.ract deve vir antes do nome da classe. (Obietivo 1.1)

Page 73: Java - Scjp 5 - Portugues

JAVA 5 47

3. C estd correta.

A est6 incorreta porque as classes implementam interfaces, mas nio as estendem. B est6 incorreta porque as interfacess6 "herdam de" ouffas interfaces. D est6 incorreta com base nas regras anteriores. (Objetivo 1.2)

4. A, C e G slo identificadores v6lidos.

B est6 incorreta porque um identificador nio pode comegar com um digito. D, E e F estao incorretas porque osidentificadores devem comegar com $ ou uma letra. (Obietivo 1.3)

5. B e D usam os prefixos v6lidos get e is.A, C e E estao incoffetas potque add, delete e put nio sio nomes de prefixosJavaBeans padr6es. (Obietivo 1.4)

6. Ae E usam sintaxe vat-atgv6Jrdz.

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

7. A B e E sdo declaragSes de arrays corretas; E 6 um array tridimensional.

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

8. A estd correta; enums podem ter consffutores e vari6veis.

B, C, D, E e F estio incorretas; todas essas linhas usam sintaxe correta. (Objetivo 1.3)

9. D e F estio corretas. A linha 5 6 a rinica que nio vai compilar, porque os enums nio podem ser locais a um m6todo.

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

Page 74: Java - Scjp 5 - Portugues

48 Copitulo I : Decloroc6es e Controle de Acesso

Page 75: Java - Scjp 5 - Portugues

OrientaEio aobjetos

Obierivos pqrq qcertificog6o

I Decloror Interfoces

I Decloror, Iniciolizor e Usor Membrosde Closses

I Usoro Sobrecorgo eo SobrescriE6o

I Desenvolver Consirulores

I Descrever o Encopsulomento, oAcoplomenlo e o Coes6o

I Usoro Polimorfismo

I Relocionor Modificodores e HeronEo

I Usor Conslrutores de Superclosses eConlrutores Sobreco rregodos

I Usor ReloE6et 6-UU e TEM-UM

l/ Exercfcios r6pidos

P&R Teste individuol

Page 76: Java - Scjp 5 - Portugues

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 precisosonhor com hierorquios de heronEo, o poder do polimo#ismo lem de fluir otrov6s dos suos veios, o coesoo e o ocoplomentofroco precisom se tornor t6o noturois poro voc6 quonto ondor, e o composiE6o preciso se lornor o seu feiioo com orroz. Eslecopftulo 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 deorientoE6o o obietos fornecidos por Jovo, portonto, comeeoremos pelo inicio.

nl . r. ..1.\.roleTtvo poro o centttcocoo

Beneficios do encapsulamento (Objetivo 5. I do exame)5./ Dercnaoluer aldigo que implemente encapsulamento igido, acoplanento Jraco e alta coetdo em classes, e desreaer os benefcios.

Suponhamos que voc6 escrevesse o c6digo de uma classe e virios programadores de sua empresa escrevessem programasque a usassem. Agora imaginemos que nio tivesse gostado da maneira como a classe se comportou, porque algumas desuas variiveis de instAncia estavam sendo configuradas (por outros programadores em seus c6digos) com valores que voc6nlo previu. O c6digo deles resultou em erros no seu c6digo (relaxe, isso 6 apenas uma hip6tese...). Bem, trata-se de umprogramaJava, portanto, voc6 deve simplesmente langar uma versSo mais recente da classe, que eles poderio substituir emseus programas sem alterar nada no c6digo que criaram.

Esse cenario ressalta duas das promessas/beneficios da OO: flexibilidade e f6cil manutengXo. Mas os beneficios nlo surgemautomaticamente. VocA tem quefaryralgo.Precisa escrever suas classes e c6digos de man eka que di sapore i flexibilidade e

f6cil manutengio. Portanto, e reJava der suporte a OO? Ela nlo projetar6 szu c6digo para voc6. Por exemplo, imagine se

voc6 criasse sua classe com variiveis de instAncia publ ic e os programadores citados acima as configurassem diretamente,como o c6digo aseguirdemonstra:

public class BadOO ipublic int size;public int weight;

ipublic 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 surgiremquando algu6m alterar a vari6vel s i z e para um valor inadequado? Sua rinica opgio 6 voltar ao script, escrever o c6digo de

umm6tododeajusteparasize (umm6todosetsize(int a),porexemplo)e,emseguida,protegeressavari6velcom, digamos, um modificador de acesso private. Por6m, logo que voc6 fizer essa alt eragdo em seu c6digo, innnonper,l o dos

outros!

A capacidade de fazrr alterag6es no c6digo de implementagio seminterromper o c6digo das outras pessoas que o estiveremusando, 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 outrosc6digos chamarem - em outras palavras, a API de sea cridigo. Com a ocultagio dos detalhes da implementaglo, vocApoder6 trabalhar novamente o c6digo de seu m6todo (podendo tamb6m alterar a maneira como as vari6veis serXo

usadas por sua classe) sem forgar uma alteragio nos c6digos que chamarem o m6todo modificado.

Se voc6 quiser obter f6cil manutengio, flexibilidade e extensibilidade (e 6 claro que voc6 quer), seu projeto deveincluir o encapsulamento. Como fazer isso?

I Mantenha suas variiveis de instAncia protegidas (com um modificador de acesso, geralmente privat.e).

I Crie m6todos de acesso public, e exija que o c6digo chamador use esses m6todos, emvez de acessar

diretamente a vari|vel de instAncia.

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

get<someProperty>.

Page 77: Java - Scjp 5 - Portugues

JAVA 5 5I

A Figura 2-1 ilustra o conceito do encapsulamento, forgando os chamadores do c6digo a usar m6todos em vez depoderem acessar as variiveis diretamente.

Chamamos os m6todos de acesso de capturadores e confgaradores. embora algumas pessoas prefiram os termos maispomposos acusadorcs e modifcadorcs. (Pessoalmente, nio gostamos dapalavra modfiear.) Independente da maneira comovoc6 os chamar, eles serio os m6todos que as outras pessoas terio que usar para icessar suas varilveis de instincia. Slo deapar6ncia simples, e 6 provivel que voc6 ji os tenha usado:

A Classe A nio 6 capaz de acessar os dados de vari6veis deinstAncias da Classe B sem ser atrav6s de m6todoscapturadores e configuradores. Os dados sio marcados como

privados; apenas os m6todos acessadores sio p0blicos.

Figuro 2-l A noturezo do encopsulqmenfo

public class Box {

// protege a variS.vel de inst.Ancia; somente uma instAncia/ / a parEir de Box pode acessar .' dprivate int size;

// Fornece capturadores e configuradores priblicospublic int getsizeO {

recurn st-ze;

]

public void setsize(int newSize) {

size = newSize;

)

iEspereumminuto...quantodoc6digoanterior6ritil?Elenemmesmoexecutaalgumavalidagioouprocessamento! Quebeneficio pode haver em ter m6todos capturadores e configuradores que neo adicionem uma funcionalidade extra? Aquesteo 6 a seguinte, uocd pode mudar de idiia depoit e adicionar mais alguma codificagio a seus m6todos seminterromper a API. Mesmo se achar que nao precisari realmente de validagio ou processamento dos dados, umbom projeto de OO Preconiza o planejamento para o futuro. A fim de ficar seguro, exija um cddigo chamador que acerenus mdtodos em ueqde pennitir o acesso direto is uaridueis de insthnria. Sempre. Assim, poder6 trabalhar de novo as

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

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

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

Qretsize ( )

setSize ( )

getName ( )

setName ( )

getcolor ( )

set.Color ( )

Page 78: Java - Scjp 5 - Portugues

52 Copitulo 2: Orientog6o o obietos

implementag6es de seus m6todos posteriormente, sem correr o risco de ter que enfrentar a fiiria dos diversosprogramadores que sabem onde voc6 mora.

oBSERVAQ6ES pene O EXAME

Cuidado con cridigos que parepm abordar o cumpnftamentl de um mtitodo, ponim, com o pmblena real sendo afalta de encapsulamento.

Examine o exerQ/o a seguiry e uela se clltsegtle detcobir o qae eshi acontecendo:

class Foo {

n,rl-r"l in ihf r6ft - 9.

public int right = 3;

public void setleft(int IeftNum) ileft = leftNum;

right = leftNum/3;

)

// muitos c6digos de teste complexos aqui

)

Agora considere essaperganta: O ua/or da direita serd umpre ilm terp do ua/or da esquerda? Sua reposta senl sim, ati que perceba que os

usudiot da classe Foo ndo precisam usar o mitodo setl,ef t ( ) ! Eles poden simplesnente ir direto ds uaridaeis de instincia e alteri-

/as com qualqur ualor int aleahirio.

Obietivo poro o Certificog6o

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

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

A heranga esti por toda pane emJava. E seguro dizer que 6 quase (quase?) impossivel escrever at6 mesmo pequenos

programas em java sem usar a heranga. Para explorar esse t6pico, iremos usar o operador instanceof , o qualdiscutiremos com muito mais detalhes no Capitulo 4. Por agora, basta lembrar de que instanceof retorna tnre se a

vari6vel de referAncia testada for do tipo ao qual est6 sendo comparada. Este c6digo:

class Test {

public static void main (String [ ] args) {

TesL t1 = new Test ( );Test t2 = new Test ( );if ( !tl.equals (t2) )

System.out.println ( "they' re not equal" ) ;if (t1 instanceof Object)

System.out.println ( "t1's an Object" ) ;

)

)

Produz esta saida:

they're not equal

t1's an Object

De onde saiu esse m6todo equals? A varilvel de referAncia t1 6 do tipo Test, e nio existe nenhum m6todoequals na classe Test. Ou existe? O segundo teste if pergunta se E1 6 uma instAncia da classe Object, e pelofato de ela ser (falaremos mais sobre isso em breve), o teste i f tem sucesso.

Page 79: Java - Scjp 5 - Portugues

JAVA 5 53

E ptt um minuto... como t1 pode ser uma instAncia do tipo Object, se acabamos de dizer que ela era do tipoTest? Tenho cerreza de que voc6 esti muito na nossa frente aqui, mas o que ocorre 6 que toda classe em Java 6uma subclasse de Object, (exceto, 6 claro, a pr6pria classe Object). Em outras palavras, toda classe que voc€ venhaa 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 herdaritodos os m6todos da classe Obiect.

Por qu6? Examinemos esse m6todo equals, por exemplo. Os criadores de Java presumiram corretamente queseria bastante comum os programadores Java quererem comparar instAncias das iuas classes para verificar se sioiguais. Se a classe Object nio tivesse um m6todo equals, voc6 teria de escrever o seu pr6prio; voc6 e todos osoutros pr,ogramadoresJava. Esse m6todo equals ji foi herdado bilh6es de vezes. (Para ser exaro, equals foisobrescrito 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 6imponante entender que as duas raz6es mais comuns para se usar a heranga sio:

I Para promover a reutilizagilo de c6digos

r Para usar o polimorfismo

Vamos comegar com a reutilizagio.Uma abordagem de projetos comum 6 criar uma verslo um ranto gen6rica deuma classe, com a intengio de criar subclasses mais especializadas que herdem dela. Por exemplo:

class GameShape {

public void displayShape ( ) {

System. out.println ( "displ_aying shape,, ) ;

]// maiq c6dia

]

class PlayerPiece extends cameshape {

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

/ / ma:-s c6digo

)

public class Testshapes {

public static void main (String[1 args; {

PlayerPiece shape = new playerpiece ( ) ;

shape. displayShape ( ) ;

shape . movePiece ( ) ;

]

)

Tem como saida:

displaying shape

moving game piece

Repare que a classe -p.layllspiece herda o m6todo display ( ) gen6rico da classe menos especializadaGameShape, e tamb6m adiciona o seu-pr6prio_m6todo, movePiece ( ) . A reutilizagio de c6digo atrav6s daheranga.significa que.os m6todos com funcionalidade gen6rica (como display ( ) ) - que podeiia- se aplicar auma s6rie de tipos diferentes de formas em um jogg

_ nio precisam ser reimplementadoi. Isio significa que todasas 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 componenresespecializados de um jogo online, por exemplo.

Mas disso voce ji sabia. Voc€ ji passou pela dor de enconrrar c6digo duplicado ao f.azer uma modificaqeo em umlugar e ter de rastrear todos os outros pontos em que exista o mesmo c6digo (ou um muito semelhante).

Page 80: Java - Scjp 5 - Portugues

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 tenhauma classe Gamelauncher que queira fazer tm loop atrav6s de diferentes tipos de objetos GameShape, echamar display ( ) em cada um deles. No momento em que est6 escrevendo essa classe, voc6 nio conhece todosos tipos possiveis de subclasses de GameShape que ainda serlo escritos por outros programadores. E voc6 comcerteza 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 GameShapecomo se fosse uma GameShape. Em outras palavras, voc6 pode escrever c6digo na sua classe Gamelauncherque diga, "nio me importa que tipo de objeto voc6"6, desde que herde de.(estenda) GameShape. E, no que me dizrespeito, 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 cridiagvvv4Y

1J

class PlayerPiece extends GameShape {

public void movePieceO (

System.out.println ( "moving game piece" ) ;

)

// mais crldio6vvs4Y

)

class TilePiece extends GameShape {

n"l.'l in rzniA na|-aAi:nanf 1\ Iyulfre vvfs Yeu^sJqeslru\/ 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

PlayerPiece player =

TilePiece tile = new

doghapes (player) ;doshaDes (tile) t

(String[] args) {

new PlayerPieceO;tilePiece ( ) ;

)

public static void do9hapes(Gan€shaDe shape)

shape . displayShape ( ) ;

)

i

Gera a saida:

displaying shape

displaying shape

Page 81: Java - Scjp 5 - Portugues

JAVA 5 55

O ponto principal 6 que o m6todo doShapes ( ) 6 declarado com um argumento GameShape, mas pode receberqualquer subtipo (neste exemplo, uma subclasse) de GameShape. O m6todo pode entio chamar qualquer m6todo deGameShape, 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 - significaqu-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 importandoo que seja o objeto. Isso significa que voc6 nio pode usar uma vari6vel GameShape para chamar, digamos, om6todo getAdjacent ( ), nem mesmo se o objeto passado for do tipo TilePiece. (Veremos isionovamente quando falarmos sobre as interfaces.)

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

E-umNa OO, o conceito E-UU 6 baseado na heranga de classes ou implementagio de inrerfaces. O termo E-UM 6r.rmamaneira de dizer, "esse item d un tipo desse outro'.?or exemplo, um Mustang 6 um tipo de cavalo, portanto, naterminologia da OO poderiamos dlzer, "Musta"g f-UIvt Cavalo". Subaru E-UU Carro. Broccoli f-'l-IM Vegetal(!io muito atraente, mas mesmo assim conta). O relacionamento E-UM 6 expresso emJava por meio das piavras-chave extends (para heranga de classes) e implements (para implementagio de interface$:

public class Car {

/ / C6digo de Car aqui

]

public class Subaru extends Car {

/ / Coisas importantes de Subaru aq"ui

/ / Nd,o se esqueqa que Subaru herda membros acessjveis de Car,/ / o qte pode incluir tanto m6todos quanto vari6vers

]

Ocarro(Car)6umtipodeveiculoffehiclQ,pofianto,aArvoredeveterinicio apartirdaclasseVehiclecomoveremosabaixo:

public class Vehicle { ... }

public class Car extends Vehicle { ... }

public cl-ass Subaru extends Car { ... }

Na terminologia da OO, vod pode dizer o seguinte:

Vehicle 6 a zuperclasse de Car.

Car 6 a subclasse de Vehicle.

Car 6 a superclasse de Subaru.

Subaru 6 a subclasse de Vehicle.

CarherdadeVehicle

Subaruherdade Car

Subaru herda de Vehicle.

Subaru 6 derivado de Car.

Car 6 derivado de Vehicle.

Subaru 6 derivado de Vehicle.

Subaru 6 um subtipo de Car.

Subaru 6 um subtipo de Vehicle.

Voltando ao nosso relacionamento E-uM, as declaraE6es a seguir sio verdadeiras:

Page 82: Java - Scjp 5 - Portugues

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 irvorede heranga. Se a expressio (Foo instanceof ear) 6 true, enteo a classe Foo E-UM Bar, mesmo se Foo nioestender diretamenie Bar, mas, emvez disso, estender alguma outra classe que seja uma subclasse de gar. AFigura 2-2 ilustra a 6wore de heranga de Vehicle, Car e Subaru. A seta se rnove da subclasse para a superclasse. Emoutras 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-UMOs relacionamentos TEM-UM sXo baseados na utilizagio , em vez de na heranga. Em outras palavras, classe ATEM-UM B ocorreri se o aldrgo da classe A apresentar una referdncia a uma in$dncia da classe B. Por exemplo, voc6 pode

dizer o seguinte,

Um Cavalo ftIorse) f-UnA Animal. Um Cavalo TEM-UMA R6dea (Flalter).

E o c6digo teria o formato a seguir:

public class animal { }

public class Horse extends Animal- {

nri rraf e Hel ter mVHalter;

)

No c6digo anterior, a classe 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{..9relacionado a ela ni pr6pria classe Horse. A Figura 2-3 ilustra o relacionamento TEM-IIM entre Horse e Halter.

Os relacionamenros TEM-UM permitirio que vocA projete classes que sigam as boas Priticas da OO sem que

sejam necess6rias classes monoliticas que eiecutem milhares de coisas diferentes. As classes (e, Portanto, os objetos

instanciados a paftir delas) devem ser especialistas. Como diz o nosso amigo.Andrew, 'as classes especializadas

de fato podem "jnd,

r a redvzir bugs". Qiuanto mais especializada. a classe, mais prov6vel que possa ser reutilizada

.* 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 halttie(Rope r) """

Halter

tt"(""p" r)

A classe Horse tem um Halter, porque Horse declara

uma variivel de instincia do tipo Halter. Quando oc6digo 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

Page 83: Java - Scjp 5 - Portugues

JAVA 5 57

Os usu6rios da classe Horse (isto 6, um c6digo que chamar m6todos em uma instAncia de Horse), achardo queessa 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 delegariessa tarefa para sua classe Halter chamando myHalter . tie ( rope ) . O cen6rio que acabou de ser descritoter6 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 executaria taref.a. Para que se d6 dessa forma, a classe Horse ocultar6 de seus usu6rios detalhes da implementaQio. Osusu6rios de Horse solicitario a esse objeto que execute tarefas (nesse caso,

^marrar a si mesmo) .

".lasseHorse o far| ou, como nesse exemplo, solicitarA a outrem parafaz6-lo. No entanto, para o chamador semprepareceri qli;e 0 pniprio objeto Horse feqtado. Os usu6rios de Horse nio precisario nem mesmo saber que ha algochamado classe Halter.

Na sala de aula

Projeto orientado a obietosOs relacionamentos f-Ulrt e TEM-UM sio apenas a ponta do iceberg quando se rrara de projeto orientado aobjetos.. Muito.s livros e.teses de graduaEio t6m sido dedicados a esse t6pico. A, razilo pari a Anfase no projetoapropnado 6 simples: dinheiro. O custo de distribuigio de um aplicativo tem sido estimado como 10 vezis maiscaro para programas mal projetados. Tendo visto os resultados de projetos fracos, posso assegurar que essaesrrmauva nio 6 irreal.

At6 os melhores projetistas que usam o modelo orientado a objetos cometem er.os. E dificil visualizar osrelacionamentos entre centenas, ou at6 milhares, de classes. Quando os erros sio descobertos durante a fase deimplementagXo_(criagio do c6digo) de um projeto, a quantidade de c6digo a ser reescrita is vezes pode fazer comque 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 semter 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 antesque a codificaglo comece. Outra inovagio recente no projeto orientado a objetos est6 relacionada aos padr6es deprojeto. Os projetistas perceberam que muitos projetoi orientados a objetos sio aplicados de maneiraionsisrentede um projeto para outro, e que seria ritil aplicar os mesmos projetos porque isso reduziria a possibilidade deintrodugio de novos erros. Assim, os projetistas usu6rios do modelo orieniado a objetos comig"ram acompanilhar esses projetos entre si. Atualmente, hi muitos catilogos desses padr6es de projetos tanto na Internetquanto em livros.

Embora para passar no_exame de certificaglo em Java voc6 nio precise compreender o projeto orientado a objetoscom esse nivel de detalhes, essas informag6es auxiliares o ajudario a entender melhor porqn. os criadores do testeoptaram por incluir o encapsulamento e os relacionamentos d um e tem a?n no exame.

I Jonathan Meeks, Programador Certificado em Java pela Sun

Page 84: Java - Scjp 5 - Portugues

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 do polimorfsno. Alin disso, deterrtinar quando a conuersdo senl necerdria e

reconhecer quando os erros sdo de nnpikgdo e quando sdo de tenpo de exuugdo n0 que re refere i conuersdo de referdncias de objxo:.

kmbre-se de que qualquer objetoJava que possa passar em mais de um teste E-UM pode ser considerado polim6rfico.Fora os objetos do tipo Object, todotos objetosJava sio polim6rficos, no sentido de que eles passam no teste E-IIM feitoem relaSo ao seu proprio tipo e em relagio ) classe Object.

Lembrese de que a rinica maneira de acessar um objeto 6 atrav6s de uma vari6vel de refer6ncia, e h6 algumas coisas

imponantes a memorizar sobre as refer6ncias:

I Uma vari6vel de refer6ncia s6 pode ser de um tipo e, uma vez declarado, esse tipo nunca pode ser modificado (embora oobjeto que referencie posa se modificar).

r Uma referOncia 6 uma variivel, de forma que pode ser reatribuida para outros objetos (a nio ser que a refer6ncia seja

declaradacomo f inal).r O tipo de uma variivel de refer6ncia determina os m6todos que podem ser chamados no objeto o qual a vari6vel est6

referenciando.

r Uma vari6vel de refer6ncia pode apontar para qualquer objeto do mesmo tipo que a refer6ncia declarada, ou - isto 6

muito importante - pode se referir a qualquer subtipo do tipo declarado!

I Uma variivel de referAncia pode ser declara& como um tipo de classe ou um tipo de interface. Se a vari6vel for declarada

como um tipo de interface,ila pode referenciar qualquer objeto de qualqu er classe que impbmente a interface.

Anteriormente, n6s criamos uma classe GameShape que foi estendida por duas outras classes, PlayerPiece e

Tilepiece. Agora, imagine quevoc6 deseje animar algumas das formas no quadro do jogo. Masnem todasasformas

podem ser animadas, entio, o que voc6 faz com a heranga da classe?

Poderiamos criar uma classe com um m6todo animate ( ) , e fazer somente algumas das subclasses de GameShapeherdar dela? Se pudermos, entlo poderiamos fazer PlayerPiece, por exemplo,estender tanto a classe GameShapequanro 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 outraspalavras, se PlayerPiece for uma classe, nlo 6 possivel dizer algo como:

class PlayerPiece extends GameShape, Arrimatable t // Niot// mais c6dica

]

IJma classe nio pode estendermais do que uma classe. Isso significa um parent por classe. lJma classe pode ter mriltiplosancestrais,no.itttatrto,,r-avezqueiclasseBpoderiaestenderaclasseA,aclasseCpoderiaestenderaclas_seBeassimpordiante. Entio, qualquer classe poderia ter mriltiplas classes acima de si na 6rvore de heranga, mas isso nio 6 o mesmo que

dizer que uma classe estende diretamente duas classes.

AOTRABALHO

Algurzas ltngaagens (cono C++) permitem qae ana classe e$enda nais do que uma classe. Essa capacidade d conhecida como "heranga

ntiltipla". A raTdo pela qual os criadoru de Jaua decidiram ndo permitir a beranga nilltipla d qae ela pode acabar bagungando o c,idigo.

Basicaaente, o prob/ena i qae se uma clasv estender dttas oatras c/astes, e ambat as superc/asses tiuerem, digamoq um mitodo

doStuf f ( ) , qaal uersdo de doStuf f ( ) a subclasse herdaria? Essa quut1o poderia leaar a un ceniio conhecido como o 'Diananteda Morte", por causa daforrna do diagmna dt clasm qae pode ser criado en pmjetot com heranga nilltipk. O dianante iformado qaando

tantoaclasseBquantrac/asseCestendemA,etantoBquantoCherdamummitododeA.Seac/asseDestendertantoBquantoC,etanto 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 formaspodem ser animadas, mas isso nlo 6 verdadeiro porque apenas algumas das subclasses de GameShape poderio rodarcom sucesso o m6todo animate ( ) .

Entdo o que mais voc6 poderia fazer? VocA j6 sabe a resposta - criar uma interface, Animatable, e fazer com que

apenas ai subclasses di cameshape q.rc possam sei animadas implementem essa interface. Eis o seu c6digo:

Page 85: Java - Scjp 5 - Portugues

JAVA 5 59

public interface Animatable {

public void animate ( ) ;

)

E eis a classe PlayerPiece modificada para implementar a interface:

class PlayerPiece extends Gameshape implements Animatable

publi-c void movePiece ( ) {

System.ouL.println( "moving game piece" ) ;

)

public void animateo {

qlrcf 6m nrrl. nrifif l- /\r-- jfr-F.l*-rJeuerLrr vqu.y!rarufll \ AIlrlL@LfIrV,

)

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

,,\;

Agora n6s temos uma classe PlayerPiece que passa no teste E-LIM tanto para a classe GaneShape quanto para a

interface Animatable. Isso significa que um PlayerPiece pode ser tratado polimorficamente com uma das quatroseguintes opg6es a qualquer momento, dependendo do tipo declarado da variivel de refer€ncia:

r Um obj ect (uma vez que qualquer objeto herda de Obj ect)I Um GameShape (umavez que PlayerPiece estende GameShape)

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

I Um Animatabl e (uma vez que Pl ayerP i ece implementa Animat.abl e)

As seguintes sio todas declarag6es legais. Observe com cuidado:

PlayerPiece player = new PlayerPiece ( ) ;

^Li ^^+ ^ - *1 --.,uDJecE. o = prayer;

Gameshape shape - player;Animatable mover - player;

56existeumobjetoaqui-umainstAnciadotipoPlayerPiece -mashiquatrotiposdiferentesdevari6veisdereferdncia, todasreferindo,se a um objeto na *&n6.i". teste rapido: quais das variiveis'de refer6ncia acima podem chamar om6todo 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 dareferAncia, independentemente do tipo do obj eto.Eitlo,observando os quatro tipos de refer6ncias novamente - obj ect,GameShape, PlayerPiece e Animatable - quais desses quatro tipos conhecem o m6todo display ( ) ?

VocA adivinhou - as classes GameShape e PlayerPiece, como 6 de conhecimento do compilador, t6m um m6tododisplay ( ) , entio qualquer um desses 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 tipodeclarado6 elayereiece e,umavezque PlayerPiece e$endeGameshape,issosignificaque etayerpieceherdou 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 refer6nciadeclarada como do tipo animatable? Apenas o m6todo animate O . E claro que o interessante aqui 6 que qualquerclasse, de qualquer irvore de heranga, pode tamb6m implementar Animatatle; enteo isso significa qn., s.voc6tiver 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 queimplemente Animatabl-e. E voc6 pode usar esse parAmetro (do tipo Animatable) para chamar o m6todoanimate ( ) ,.mtr nio o m6todo display ( ) (que pode nem existir) ou qualquer outro que nio seja conhecidopelo compilador com base no tipo da refer6ncia. O compilador sempre sabe, nb entanto, que voc6 pode chamar osm6todos 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 derefer6ncia declarado, a JVN[, em tempo de execugio, sabe o que o objeto iealmente 6. E isso significa que, mesmoque 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 sobrescrevaesse m6todo! A Jyry o!se_rv1 o objeto real do outro lado da refer6ncia, "v6' que ele sobrescreveu o m6todo do tipoda vari|vel de refer|ncia declarada, e chama o m6todo da classe verdadeira do objeto. Mas uma coisa a se ter enimente:

As chamadas de m6todos polim6rficos se aplicam somente a nitodos de in$6ncias. VocA sempre pode se referir a umobjeto com um tipo de va?iivel de refer6ncia mais geral (uma superclasse ou interface), -"r, .- tempo de

Page 86: Java - Scjp 5 - Portugues

60 Copitulo 2: Orientogdo o obietos

execuglo, "s

ONTCAS coisas que sio selecionadas dinamicamente com base no pr6prio objeto (em vez de no tipoda referincia) sio os m6todos de instincias. Nio m6todos uttiticos. Nio uaridueis. Apenai m6todos de instAnciassobrescritas 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 m6todosestiticos e m6todos de instincias, falaremos sobre eles em seguida.

Obletivo poro o CertificoE6o

Sobrescrevendo/ Sobrecarregando (Obietivos 1.5 e 5.4 doExame)

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

5.4 Dado am cendio, desenuoluer cddigo qae declare ef ou chame mdtodos sobrescritos ou sobrecarregados, e devnuoluer cddigo que declare ef ou

chame conshatores de superc/asses, cznstfl.rtzre! sobrescritos oa sobrecatregados.

M6todos Sobrescritos

Sempre que vocd tiver uma classe que herde o m6todo de uma superclasse, poderi sobrescrever esse m6todo (a

menos que, como aprendeu anteriormente, ele tenha sido marcado com f inal). O beneficio chave dasobrescrigio 6 o recurso de definir um comportamento que seja especifico de determinado tipo de subclasse. Oexemplo a seguir demonstra a subclasse Horse penencente i classe Animal sobrescrevendo a versio do m6todoeat( )dessaclasse.

public cl-ass animal {

public void eat ( ) t

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

)

]

class Horse extends Animal {

public void eat ( ) {

q\/qj- Fm nrrf nrintln (.'Horse eaf i-^ 1-'r.' ^^f c =-4 hOrSe tfeats");rf ousrL'.vuL.P! \ frvrrE gqLrrlY rrsJ r veev, errv

]

)

Para os m6todos abstract que voc6 herdar de uma superclasse, nio hi escolha. E preciso implementar om6todo 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 m6todosabst.ract da superclasse. Portanto, voc6 deve considerar os ndtodos abstract como aqueles ot quair ser,iforpado a

sobrescreuer.

O criador da classe Animal pode ter decidido que para fins de polimorfismo, todos os subtipos de Animalprecisario de um m6todo eit ( ) definido de maneira .rp..ifi." e.exclusiva. Coq o polimorfismo, quandoalgu6m tiver uma referAncia a Animal que aponte nio para uma instAncia de Animal, mas para a instAncia de umasu-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 om6todo 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 dopolimorfismo 6 apresentado abaixo:

pubJ-j-c cl-ass TestAnimals {

public static void main (String [] args) t

Animal a = new Animal0;Animal b = new lrorEe () t / / Refer6ncia Animal, rnas 6 tut objeto Horse

a.eat\\; // Executa a versdo Animaf de eatob.eat (\; / / Executa a versSo Horse de eato

Page 87: Java - Scjp 5 - Portugues

JAVA 5 6I

]

class animal {

public void eat ( ) t

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

)

class Horse extends Animal {

public void eato {

System.out.println("Horse eating hay, oats, and horse treats"),'ipublic void buck0 { }

)

No c6digo anterior, a classe de teste usa uma refer6ncia a Animal para chamar o m6todo em um objeto Horse.Lembre-se de que o compilador s6 permitir6 que os m6todos da classe Animal sejam chamados quando a

referAncia a um objeto Animal for usada. O c6digo a seguir nio seria vilido dado o c6digo anterior:

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

| / A cl'aes'e Aninral nio possui asse m6todo

O compilador s6 verificari o tipo da referdncia e nio o da instdncia. O polimorfismo permitir6 que voc6 use arefer6ncia a um supeftipo mais abstrato (incluindo uma interface) para acessar um de seus subtipos (inclusiveos implementadores da interface).

O m6todo novo ndopodertl ter um modficador de acesso mais restritiuo do que o m6todo que foi sobrescrito (por exemplo,voc6 nio pode sobrescrever um m6todo marcado com public f.azendo com que ele se torne protected).Pense bem: se a classe Animal apresentar um m6todo eat ( ) public e algu6m tiver uma referAncia a Animal(em outras palavras, uma referencia declarada com o tipo Animal), essa pessoa presumiri ser seguro chamareat ( ) na refer€ncia a Animal independente da instAncia real para a qual a refer6ncia estiver apontando. Se

fosse permitido que uma subclasse se infiltrasse e alterasse o modificador de acesso no m6todo novo, enteo,repentinamente no tempo de execuglo - quando a JVM chamar a verseo real do m6todo no objeto ftIorse) em vezda versio do tipo da referincia (Animal) - o programa seria interrompido (sem mencionar o stress emocional sofridopor quem foi traido pela subclasse embusteira). Alteremos o exemplo de polimorfismo que vimos anteriormente:

public class TestAnimals {

public static void main (String [] args) {

Animal a = newAnimalo;Animal b = new Horse() i / | Refer6ncia Animal, nag 5 urn objeto Horse

a.eat); // Executa a versao Animal de eatob.eatO; // Executa a versdo Horse de eato

]

]

cl-ass Animal {

public void eat ( ) {

System.out.println( "Generic Animal Eat.ing Generically" ) ;

]

]

class Horse extends Animal {

priwate void eat ( ) {

System.out.printl-n( "Horse eating hay, oats,+"and horse treats");

)

)

Se esse c6digo pudesse ser compilado (o que nio acontecer6) o descrito a seguir falharia no tempo de execugio:

Page 88: Java - Scjp 5 - Portugues

62 Copitulo 2: Orientogdo o obietos

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

/ / aL6 aqui. tudo bem

// Falha no tsnpo de execug3,ol

A vari6vel b 6 do tipo enimal, que possui um m6todo eat ( ) public. Contudo, lembre-se de que no tempo deexecugio,alinguagemJavausaachanadaaumnitodovirtaalparaselecionardinamicamenteaverseo realdom6todoqueser6executado, com base na instAnciareal.IJmarefer6ncia aAnimal sempre poderiapontatparauma instincia de Horse, porqueHorse 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 Animalou simplesmente herd6los, qualquer pessoa com uma refer6ncia de Animal ) instAncia de Horse poder6 chamartodos os m6todos disponiveis em Animal. Por essa razio, o m6todo novo deve seguir o contraro da superclasse.

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

I A llsta de argumentot deae coincidir exatamente com a do m6todo sobrescrito. Se nXo coincidirem, voc6 poder6 acabarcom um m6todo sobrecarregado que nio queria usar.

I O tipo dz retomo deae ser o mesmo, ou um subtipo, do tipo de retorno declarado no m6todo sobrescrito original dasuperclasse (Falaremos mais sobre isso daqui a algumas piginas, quando discutirmos os retornos covariantes).

I O nfuel de acesso n6o deue ser nais rutritiuo que o do m6todo sobrescrito.

I O niuel de acesso pode ser menos restitiao que o do m6todo sobrescrito.

I Os m6todos de instAncias somente podem ser sobrescritos se forem herdados pela subclasse. lJma subclassedentro. do mesmo pacote que a superclasse da instincia 6 capaz de sobrescrever qualquer m6todo desuperclasse que nio seja marcado com private ou f inal. Uma subclasse de um pacote diferente somentepode sobrescrever os m6todos nio-f inal marcados com public ou protecteA (uma vez que osm6todos protect.ed sio herdados pela subclasse).

I O m6todo sobrescritor PODE langar qualquer excegio (de tempo de execugio) nio-verificada,independentemente de o m6todo sobrescrito declarar ou nio a excegio. (Mais sobre isso no Capitulo 5.)

I O m6todo novo ndo deae langar excegdes ueifcadas flnuas 0a mais abrangentes que as declaradas pelo m6todo sobrescrito.Por exemplo, um m6todo que declare uma excegio FileNotFoundException nio poder6 ser sobrescritoPor um m6todo que declare uma excegio SQlException, Except.ion ou qualquer outra excegio que nioseja de tempo de execugio, a menos que ela seja uma subclasse de FileNotFoundException.

I O ndtodo noao podeni langar excegdes nais restritiuas oil nefilr abrangentes. 56 por que o m6todo sobrescrito "se arriscou',nio quer dizer que a excegio da nova subclasse deva contemplar os mesmos riscos. Conclusio: O m6todonovo nio precisa declarar nenhuma excegio que nunca langar6, independente do que o m6todo sobrescritotenha declarado.

I Voc6 n6o pode sobresmuer um mdtodo marcado com f :-na]-.

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

I Se u, mdtoda ndo puder rcr lterdado, uocd ndo poderi sobrewaiJo. Lembre-se de que a sobrescrigio implica que voc6 estireimplementando um m6todo herdado! Por exemplo, o c6digo a seguir nio 6 vllido, e mesmo se voc6 adicionasse umm6todo eat ( ) a Horse, ele nio seria uma sobrescriqXo do m6todo eat ( ) de Animal:

public class TestAnimals {

public static void main (String [] args) iHorse h = new Horse0;h.eat l); / / Nio 6 w61ido, Dorque Horse nio herdou eat()

)

]

^1 -^^ n-l--rL!d>D rurltrdf t

private void eat ( ) t

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

)

class Horse extends aninal { }

Page 89: Java - Scjp 5 - Portugues

JAVA 5 63

chamando a versio da superclasse de um m6todo sobrescritoGeralmente, 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 dasuperclasse p-a.ra. o m6todo e' em seguida, volte aqui e tirmine com o c6digo adicional d. mirrh" subclasse para

1y 3€t$g"lf !:"* ressaltar qry :,.t?o

6 preciso que a versio da superclassZ t.1" .".."r.J"";;;;i;;dt;;'d" -suDclasse)' t tacrl tazer lsso no codrgo usando a palavra-chave super, como vemos a seguir:

public class Animal {

public void ear O { }

ntthlin rznid nrint-Vnrrrcalf /\ /rvstpsr! \ / t

/ / C6digo ritil de exibiqdo aqui

]

class Horse ext.ends Animal {

nrrl-r'lic rrnid nr.infv^rrra6lf /\ /wvfu yrfrrurvq!osr! \/ I

/ / Aproweita-se do c6digo de Animal, depoj-s adici-ona mais c6dioosuper.printYourself O,. // Chama a supercfasse

/ / c6digo (Animal)

/,/ Depois volta e realiza// outros serviqos de exibiqio/ / especificos de Horse aqui

l

Observagio: IJsar super para chamar um m6todo sobrescrito somenre se aplica a m6todos de instAncias. (Lembre-se de que m6todos static nio podem ser sobrescritos.)

oBSERVAq6ES pane o EXAME

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

class Animal ipublic void eat ( ) throws Exception {

/ / Ianea uma Exceqd.o

)

class Dog2 ext.ends Animal {

public void eatO { //sem Exceq6es }

public static void main(String [] args) tAnimala=newDog2O;Dog2 d = new Dog2O;

d.eatO;// ok

a.eatO; ll erro de coogilagao -I / Exceg6,o n6o relatada

)

)

Este aldigo ndo coapilanl deuido i exce\zo dularada no mdtodo eat ( ) de Aninal. Isso ocom mesmo qtle, em tempo de exuugdo, 0 mit4doeaL ( ) asado sela a uertdo de Dog a qual ndo dulara a excegdo.

Page 90: Java - Scjp 5 - Portugues

64 Copitulo 2: OrientoE6o o obietos

Exemplos de sobrescritas de m6todo v6lidas e nao-vilidasExaminemos a sobrescrita do m6todo eat ( ) de Animal:

public class Animal {

public void eat O { }

)

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

classe Animal.

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

C6digo de subscrigio invSlido Problema no c6digo

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

public void eat ( ) throws lOException { }Declara uma excegio verificada nio declarada

pela versio da superclasse

public void eat ( string food) { }IJrru sobrecarga vilida, e nio uma subscrigiq

poque a lista de a{gumentos foi aherada

publicStringeat( ) { }

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 se pergtrntando o que os m6todos sobrecarregados estio fazendo em um capido sobre OO, mas os

incluimos "q.ri

p.lt fa:to de uma das coisas com as quais os deienvolvedoresJava novatos mais se confundem serem

justamente as sutis diferengas entre m6todos sobrecamgados e sobrescitos.

Os m6todos sobrecarregados permitirio que voc6 reutilize o mesmo nome de m6todo em uma classe, mas com

;g";;; dif.rentes (e Spciori"l*..rr., .or.r um tipo de retorno diferente). A sobrecarga de um m6todo geralmente

,ifnifi." q.r..,o.6.rt"ri r"ndo um pouco mais condescendente com as Pessoas que chamarem seus m6todos, po^rque razr

..iaig" *]"*r ,^^tirf.^d{idar coirrtipos de argumentos diferentes eri vezdeiorgar o rhamadorafaznr convers6es antes de

chamar seu m6todo. As regras sio simples:

I Os m6todos sobrecarregados deuem alterar a lista de argumentos.

I Os m6todos sobrecarre gados poden alterar o tipo de retorno.

I Os m6todos sobrecarreg ados podem alterar o modificador de acesso.

I Os m6todos sobrecarregado s 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 Adefinirum m6todo doStuf f (int i), a subclasse B poderia definirum m6todo doStuf f (String s)sem sobrescrever a versio da superclasse que usa um int. Assim, dois m6todos com o mesmo nome, mas em

diferentes classes, ainda podem'r.r corrsid.rados como sobrecarregados, caso a subclasse herde uma versio do

m6todo e depois decl^ri outr^versio sobrecarregada na sua definigio de classe.

Sobrecargas vilidasExaminemos um m6todo que queremos sobrecarregar:

nrrhlic rrnid chanaesizc(inf size. String name, float pattern) { }.Puvfrv vvrs vlrgrrYe

Os m6todo a seguir sio sobrecargas u,itidas do m6todo changeSize ( ) :

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

n,,1.r1 .in ini ^h:ndaqizotini- qize f I^al- naftern) I ItrruurI9 frrL urrqrtverr!= \rlru

public void changeSize(float pattern, String name)

throws rOException { }

Page 91: Java - Scjp 5 - Portugues

JAVA 5 65

oBsERvAe6ns pene o ExAME

Tome caidado 41ando tiuer qae reconbecer se um mitodo d nbrecarregado em ueTde sobrucrito. Voc€ pode aer am mdtodo qae parega uio/aruma regra da nbrucrigdo, mar qae na uerdade senl uma sobrecarga u,i/ida, como ueruos a seguir:

public class Foo {

nrrhl i c rrni rl rlnqtrrf f / i nr rr ctsrivuvrrL vvru u---e r, evL-ng S) { }

public void moreThings(int x) { }

]

class Bar extends Foo {

nrrl.r'lin rznid r{nQl-rrff f inr!! \ frfu

i

VocdpodefcartentadoaconsideraralOExcepLioncomooproblema,a0uerqueomdtodosobrevritodoStuff()ndodeclarouum1 excegdo e ao saber que a excegdofoi uerifcadapelo compilador. Mas o mitodo doStuf f ( ) ndofoi defotma alguma substcrito! Asubclasse Bar o sobrepds, altemando a lista de argumentlr, portanto a excepdo lOExcept.i on i adequada.

-

Chamando m6todos sobrecarregadosRepare.que ha muito mais a ser dito sobre como o compilador sabe qual m6todo chamar, mas o restante ser6abordado no^Capjtu1o.3, quando virmos o boxing e os var-args - ambos t6m impacto significativo sobre asobrecarga. (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 emque voc6 o estiver chamando. Por exemplo, a classe Horse pode ter-tres m6todos com o ;esmo nbme, por6-,com listas de argumentos diferentes, o que significa que o m6todo foi sobrecarregado.

A decisio sobre qual dos m6todos coincidentes chamar ser6 baseada nos argumenros. Se voc6 chamar o m6todocom um argumento String, a versAo sobrecarregada que usar uma String ser6 chamada. Se chamar um m6todo como mesmo nome' mas Passar Para ele um tipo f 1oat, a versio sobrecarregada que usar um tipo f loat ser6executada. Se chamar um m6todo com o mesmo nome, mas passar para el=e um-objeto roo e nio houver umaversio.sobrecarregada que use esse objeto, enteo, o compi]xdel aviJar6 que nio est6 conseguindo encontrar umacoincid6ncia. A seguir temos exemplos de chamadas a m6todos sobrecarregados:

class Adder {

public int addThem(int x, int y) {

return x + v;)

// Sobrecarrega o m6todo addThem para adi-cionar doubles em vez de intspublic double addThem(double x, double y) {

return x + y;

)

)

/ / A partir de outra classe, chama o m6todo addThemopublic c1ass TestAdder {

public stat.ic void main (String [] args) {

Adder a = new Adder0;

y, float s) throws rOException { }

int c = 3;

int result. = a.addThem(b,c) ; ll euaL addTtren 6 chanado?double doubleResult = a.addThem(22.5,89.36) ; // euaL addlltrern?

]

No c6digo TestAdder anterior, a primeira chamada a a. ad.dThem (b, c) passa dois tipos int para om6todo, portanto, a primeira versio de addThem ( ) - a versio sobrecarregada que usa doii argumen^tos de tipoint -ser6chamada.Asegundachamadafeitaaa.addThem (22.5, 89.361 passadoistiposdouble-para o m6todo,.portanto, a segunda verseo de addThem ( ) - a versio sobrecarregadl que usa dois argumentosdouble - ser6 chamada.

Page 92: Java - Scjp 5 - Portugues

66 Copitulo 2: Orientoqdo o obietos

Chamar m6todos sobrecarregados que usem refer6ncias a objetos_ em vez de tipos primitivos 6 um pouco mais

inr.r.rr"rri.. Oig"r"ot qrr. v&e tive'sse um m6todo sobre.a.i.g"do em qu9 -uma

versio usasse um objeto Animal e

a outra;"b,;?;H;rr'. 1r"b"i"rt. Je Animal). Se voc6 p"tt"t"o- objeto Horse na chamada do m6todo, chamarh

a versio sobrecarregada que usa esse objeto. Ou pelo menos 6 o que Parece i primeira vista:

class animal { }

class Horse extends animal { }

class UseAnimals {public void doStuff(Animal a) t

s\/qt-Fm orri- nrint-ln("Tn the Animal version");uJ e uer( .

]

public void doStuff (Horse h) {

svsl-cm orrf nri nf l n ( "Tn fhe Horse version" ) ;vJrevlrr! vse.y!4^re+

]public static void main (String [] args) {

UseAnimals ua = new UseAnimals ( ) ;

Animal animalObj = new animal ( ) ;

Horse horseobj = new HorseO;

ua.doStuff (animalObj ) ;

ua.doStuff (horseObj ) ;

)

)

A saida seri a que voc6 espera:

in the Ani-mal versionin the Horse version

Mas, e se voce usar uma referOncia de Animal a um objeto Horse?

Aninal aninalRefToHorse = new Horse();

ua. doStuf f ( animalRefToHorse ) ;

Qual das vers6es sobrecarregadas seri chamada? Voc€ pode estar querendo responder: "A ,9ge usa qm objetoliorr., jL que 6 esse objeto que est6 sendo passado parJo m6todo no tempo de execugio". Mas nio 6 assim que

funciona. O c6digo anterior na verdade exibiria:

in the Animal version

Ainda que o objeto real no tempo de execugXo seja um objeto llgrse e."q" Sli*ll, a opgio por qual m6todo

sobrecamgado chamar (em outras palavras, a assinatura do m6todo) nio 6 decidida dinamicamente no tempo de

execugi6. Apenas lembre-se de q.te o tipo da referdncia (e ndo o tipo d9 objeto) d(emiry 4!al ndto(o sobrecamgado.unl chamado!

Resumindo,^o m6todo sobresnito a chamar (em outras palavris, de qual classe da 6rvore de heranga)- 6 decidido.no

tempo de exuipao com base no tipo do objeto, mas qual versio sobreearegado do m6todo chamar 6 baseado no tipo da

referdnciapassado no rempo de tonp;kgi. Se voc6 chamar um m€todo passando a ele uma referdncia Animal a umoblrto Horr., o compilador s6 saberi do Animal, portanto, ele escolhe a. verslo sobrecarregada do m6todo que

,rr" rr* Animal. Nio impona, em tempo de execugio, que na verdade seja um Horse sendo passado.

Polimorfismo em m6todos sobrecarregado e sobrescritoComo 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 opolimorfismo 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" ),'

Page 93: Java - Scjp 5 - Portugues

JAVA 5 67)

public class Horse extends Animal {

public void eat0 {

System. out.println ( ..Horse eating hay .. ) ;

)

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

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

)

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

Iobelo 2-2 Chomodos

oBSERVAQ6ES pene O EXAME

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

public class Foo {

void doStuff0 { }

]

class Bar extends Foo {

void doStuff (String s) { }

)

A elasseBar tem dois mdtodot doStuf f ( ): a uersdo sem argamentls qae herdou deFoo (e ndo sobresmuel e a nbrecamgadadoStuf f (String s) defnida na classe Bar. O aidigo con uma refer€ncia ao objeto Foo pode chamar somente a aersdo semargilnentLr' mN 0 que ten a refer€ncia a am objeto Bar pode chamar qua/.quer uma das uersdes sobrecamgadas.

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

Iobelo 2-3 Diferengo enlre m6fodos sobrecoregodos e sobrescrifos.

M€todo sobrecarregado M6todo sobrescrito

o rn6fodos e sobrescrifos

C6digo de chamada de m6todo Resultado

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

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

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

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.

Horse he = new Horse ( )Hone eating Apples O m6todo eat(String s) sobrecarregado 6 chamado.

Animal a2 = newAnimal ( )

a2,eaX ("treats");Erro do compilador! O compilador percebeu qtre a classe Animal nio possuium m6todo eat( ) que use uma String.

Animal ah2 = new Horse ( ) ;

ah2 . eat ( " carrots " ) ;

Erro do compilador! O compilador conrinuou examinando somenre o tipo darefer6nciae viu que Animal nio tem um m6todo ea( )qtre use uma srring. Ocompilador nlo se preocupou com o fato de quetalvez o objeto real no tempode e:<ecugio seja um objeto Hone.

lista de argumentos Deve ser alterada Nio deve ser alterada

tipo de retorno Pode ser alterado Nio deve ser alterado

Exceg6es Podem ser alteradas Podem ser reduzidas ou eliminadas.

Page 94: Java - Scjp 5 - Portugues

68 Copftulo 2: Orientog6o o obietos

Nio devem ser langadas exceg6es

verificadas novas ou mais abrangentes

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

ser menos restritivo)

Chamadas O tipo da refer6ncia determinaqtre verslo sobrecarregada(baseada nos tipos deargumentos deilarados) serisel-ecionada. O m6todo real a ser

chamado ain&ter6umachama&virnral no tempo de

excecu$o, a coincidAncia de

argumentos ji teri sido definida,s6 faltando a classe real onde om6todo reside.

O tipo do objeto (em otttras palavras, o

ti1o da inrfincia real na memtiia)

ser6 selecionado. Isso ocorrer6 a todoinstante.

Sobrescrito

Tree

showleaves ( )

Oak

showleaves ( )

Sobrecarregado

Tree

setFeatures (String name)

Oak

setFeatures (String name, int leafSize)setFeaLures (int leafSize)

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

O objetivo atual (5.4) aborda tanro a.sobre carga de m6todos quanto de construtores, por6m, a iltima ser6 abordada

na proxlma segao, na qual tamb6m discutirernos os outros t6picos-relacionados a construtores que aParecerio no

."".n.. A figuia 5-4 ilustra a maneira como m6todos sobrecarregados e sobrescritos sio tratados em

relacionamentos de classes.

Obietivo poro o Certificogdo

Conversio de Variiveis de Refer6ncia (Objetivo 5.2 do Exame)

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

saber dferenciar enor de conrpilagdo de erms de tempo de execapdo relacionados i conuersio de refer4ndas a objetos.

J6 vimos que 6 possivel e comum usar tipos gen6ricos de variiveis de ref_9r6ncia pa?:.ap2+tar.para,tipos de objetos

mais especifi.oi. kto forma a base do poli*orfir-o. Por exemplo, esta linha de c6digo lhe deveri Parecer natural

a esta altura:

Animaf animal = new DogO;

Mas o que acontece quando voc6 deseja usar a variivel de refer€ncia do animal a fim de chamar um m6todo que -

apenas a classe oog possui? VocA sabe que esti se referindo a um Dog, e deseja fazer algo que 6 especifico.a Dog?

No c6digo seguinti, f.*or rr* array deanimals e, sempre que. acharmos um Dog no array, queremo^s fazer

algo espe"cific6 d. pog. Vamos coniordar por agora que todo o c6digo est6 correto, exceto pelo fato de nioestarmos ceftos sobre a linha que chama o m6todo playDead.

class Animal {

void makeNoise ( ) {System.out.println( "generic noise") ; }

)

class Dogr extends Animal {

Page 95: Java - Scjp 5 - Portugues

JAVA 5 69

void makeNoiseO {System.out.println(..bark,,) ; }

void playDead ( ) i System. out.println ( ', roll over,, ) ; )

]

class CastTest2 {

public static void main(String IJ args; {

Anima] tl a = inew Animal O , new DoSO , new Animal O );for(Animal animal : a) {

animal.makeNoise ( ) ;

if (animal instanceof Dogr) {

animal .playDead(li // lentou realizar um coq)orta.m€nto de D,og?

J

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

cannot. find slzmbol

O compilador est6 dizendo: 'Ei, a classe Animal nio tem um m6todo playDead ( ) ". Vamos modificar o bloco

conwertendo a variSvel de refer6ncia

de c6digo if:if (animal instanceof Dos) {

oog d. = (Dog) anirnal; //d.playDeadO;

]

O novo e melhorado bloco de c6digo cont6m uma conversio, que neste caso 6 is vezes chamada de conuersdo

redutora, porque estamos convertendo para baixo na Lrvore de heranga, de uma classe mais geral para uma maisespecifica. Agora, o compilador frcarS, feliz. Antes de tentarmos chamar playDead, n6s convertemos a variiveldo animal para o tipo Dog. O que estamos dizendo ao compilador 6 "sabemos que ela na verdade se refere a umobjeto 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 paratermos certeza.

E i-pon"ttt. saber que o compilador ser6 forgado a confrar em n6s quando fazemos uma conversio redutora,mesmo quando fazemos besteira:

class Animal i )

class Dog extends Animal { }

al aac T\aaToct I

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

Animal animal = new Animal ( ) ;

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

J

Isso pode ser enlouquecedor! O c6digo compila! Mas quando tentamos executAlo, recebemos uma excegeo parecidacom esta:

j ava. 1ang. ClassCastExceptionPor que nio podemos confiar que o compilador vai nos a.judar aqui? Ser6 que ele nio consegue ver que animal 6do tipo Animaf ? Tudo o que o compilador pode fazer 6. verificar se os dois tipos esrio na mesma iwore deheranga, de forma que, dependendo se houve ou nio algum c6digo antes da conversio, 6 possivel que animalseja do tipo Dog. O compilador precisa permitir coisas que possivelmente vio funcionar no mominro daexecugio. 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

Page 96: Java - Scjp 5 - Portugues

70 Copitulo 2: Orientoglo o obietos

Nesse caso, voc6 receberi um erro parecido com este:

class DogTest {nrrlr]in c{-:fia

Dog d = new

Anina1 a1 =

Ani.mal a2 s

)

)

inconvertible tlpesAo contr6rio da conversio redutora, a conversio generalizadora (convefter para cima na irvore. de heranga, de umtipo 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 m6todosque ilode chamar, ao contririo da conversio redutora, o que implica que, mais tarde, voc6 poder6 desejar chamarum m6todo mais espec{fco. Por exemplo:

^t ^^^ n-i*-1 r )Ll45> rurrrllal I J

class Dog extends Animal { }

void main(St.ring [] args) {

Dogo;d; / / converslo generalizadora ok sem nenhunr converEio e:rglicita(Animal) dt ll cornwergio generalizadora ok co umr conversio otrllicit,a

Ambas as convers6es acima irio compilar e rodar sem exceg6es, porque um Dog n-UVt Animal, o que significaque qualquer coisa que um Animal possa fazer, um Dog tamb6m poder6. Um Dog pode f.azer mais, 6 claro, mas-aquestao 6: qualquer um que tenha uma referAncia a Animal pode chamar, com seguranga, os m6todos de Animalem uma instincia de Dog. Os m6rodos de Animal podem ter sido sobrescritos na classe Dog, mas tudo que nosimporta agora 6 que um Dog sempre pode tazer, no m(nimo, tudo o que um Animal puder. O compilador e a JVMtamb6m sabem disso, entlo a conversio generalizadora implicita 6 sempre v6lida para atribuir um objeto de umsubtipo a uma referencia de uma das classes (ou interfaces) do seu supertipo. Se Dog implementar Pet, e Petdefinir beFriend.ly ( ) , entio um Dog pode se converter implicitament. .tn n.tiPrt, mas o 6nico m6todo deDog que voc6 poder6 chamar enteo ser6 beFriendly ( ) , que Dog foi forgado a implementar porque Dogimplementa a interface Pet.

Mais uma coisa... Se Dog implementa Pet, entXo se Beagle estender Dog, mas Beagle nio fuclarar que estiimplementando Pet, Beagle ainda ser6 um Pet! Beagle 6 um Pet simplesmente porque estende Dog, e Dog jltcuidou dos seus pr6prios comportamentos Pet, e os de todos os seus descendentes. A classe Beagle sempre podesobrescrever quaisquer m6todos que herdar de Dog, incluindo m6todos que Dog implementou para satisfazer ocontrato 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 superclassesde 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, entioBeagle E-IIM Pet, e ji atendeu is suas obrigag6es de Pet de implementar o m6todo beFrien-dly ( ) , uma vez queele [erda esse m6todo. O compilador 6 espirio o suficiente pira dizer, "Eu j6 sei que Beagle 6 UM Pet, mas niotem problema em tornar isso mais 6bvio".

Assim, nio se deixe enganar por um c6digo que mostre uma classe concreta que declare estar implementandouma 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 deheranla jitiver forneiido implementag6es concretas (ou seja, nio-abstract) doi m6todos, e tiver declarado queela (a superclasse) est6 implementando a interface, enteo a subclasse nXo tem obrigagio nenhuma dereimplementar (sobrescrever) esses m6todos.

oBSERVAQoES pene O EXAME

Os niadorcs do exame irdo lhe diryr que foran forgadot a eo/ocar toneladas de aldigos em pequeills espapos 'por causa do sistema do exane".

Embora isso t/a potencialmente uerdadeiro, eles TAMBEM gwtam de ser obvums. O aidigo ngainte:

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

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

Ani-ma1 a = new DogO;

( (Dog) a) .doDogStuff ( ) ;

Neste caso, o conpiladorprecisa de todos esses par€nteses, caso contniio pentari que eshi recebendo ama infuwgdo innmpleta.

Page 97: Java - Scjp 5 - Portugues

JAVA 5 71

etivo poro o CertificoEdo

lmplementando uma Interface (Objetivo 1.2 do exame)1.2 Desenuolaer cddigo qae declare uma interface...

Quando voc€ implementar uma interface, estari concordando em aderir ao conrraro definido nela. Isso significaque estari concordando em fornecer implementas6es v6lidas de cada m6todo definido na inrerface e que {ualquerpessoa que.souber como sio os m6todos da interface (nio a maneira como sio implementados, *"r .&.to irod6mser 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 serexecutado por um thread especifico), ter6 que fornecer o m6todo public void run ( I . Oo conlririo, ocoitado do thread_ poderia ser informado para executar o c6digo de seu objeto Runnable e - surpresa - iriadescobrirqueo objetoniopossui o m6todo run( ) !(Momentoemque, othreadseriainterrompidoeaJVMencerrado em uma finalizagi"o espetacular, por6m, horrivel). Felizmenle, a linguagem Java impedlr6 que isse danoocorra pela execugio de uma verificagio do compilador em cada classe que tentaiimplementar uma interface. Sea classe informar que esti implementando uma interface, 6 melhor que tinha uma implementagio de cada m6tododa interface (com algumas exceg6es que examinaremos em breve).

Assumindo-se que temos uma interface Bounceable, com dois m6todos: bounce ( ) e setBouneeFactor ( ) , aseguinte classe ir6 compilar:

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

public void bounce O { }

public void setBounceFactor(int. bf) t ]

)

Cefto, sabemos o que voc6 esti pensando: "Essa deve ser a pior classe da hist6ria das classes de implementagio". Noentanto, ela ser6 compilada. E executada. O contrato di interface garante que uma classe tenha o m6todo (emoutras 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-Ocompilador nunca lhe dir6, "Desculpe, mas voc6 nlo quer mesmo inserir nada entre essas chaves? ATENQAO: jique 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 umaclasse estendendo uma classe abstract. Para ser uma classe de implemintagio v6lida, uma classe deimplementagio nio abstract deve fazer o seguinte:

I Fornecer implementag6es concretas (nio abstract) de todos os m6todos da interface declarada.

r Seguir todas as regras de sobrecarga vilidas.

I Nio declarar exceg6es existentes em m6todos de implementagio que nio sejam as declaradas pelo m6todo dainterface, ou subclasses que nio sejam as declaradas por esse m6todo.

I Manter a assinatura e o mesmo tipo de retorno do m6todo da interface (por6m, nXo sendo preciso declarar asexceg6es existentes na declaragio do m6todo da interface).

Mas.espere_, hi mais! Uma_classe de implementagio pode ser ela pr6pria abstract! Por exemplo, o c6digo aseguir 6 v6lido para uma classe Ball que implemente a interface Bounceable:

abstract class Ball implements Bounceable { }

Notou algo faltando? Nio fornecemos os m6todos de implementagio. E isso esti certo. Se a classe deimplementagio for abstract, ela pode simplesmente passar atarefa para sua primeira subclasse concreta. Porexemplo, se a classe BeachBall estender Ball e nio for abstract, entXo, reri que fornecer todos os m6todos deBounceable:

class eeachBall extends Ball {

/ / F;rnbora nao o digamos na declaragd.o de classe acima,

// BeachBall implement.a Bounceable, uma vez que a superclasse abstract de

/ / BeachBall (8a11) implementa Bounceable

public void bounceO t

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

]

Page 98: Java - Scjp 5 - Portugues

72 Copftvlo 2: OrientoEdo o objetos

public void setBounceFactor(int bf) {

/ / c6digo bounce especifico de BeachBall aqui para definir um fator de bounce

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

/ / ser implementados aqui tamb6m.

)

Procure m6todos que informem implementar uma interface, mas nXo fornegam-as implementag6es de m6todocorreras. 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 dormirsempre, 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 sub-classei define quem e o que 6 a classe, enquanto I implementagio define uma fungio que ela.poderi desempenharou algo que poderi usar, apesar do quanto possa ser diferente de outra classe que estiver implementando a mesmainterface (por6m, apartir de uma 6wore de heranga diferente). Por exemplo, uma pessoa estenderia HumanBeing(embora isso possa ser discutivel para alguns). Mas tamb6m poderia implementar programmer, snowboarder,employee, parent ou personcrazyenoughtotakethisexam.

2. A pr6pria inter{ace pode estende r outra interf.ace, mas nunca implementar algo.

O c6digo abaixo 6 perfeitamente v6lido:

public interface Bounceable errtends rdoveable { }

O que isso significa? A primeira classe concreta (nio abstract) de implementagio de Bouceable deveimplementar todos os m6todos dessa interface, al6m de todos os m6todos de Moveable! A subinterface, como a

chimamos, simplesmente adicionari mais requisitos ao contrato da superinterface. VocA veri esse conceitoaplicado em muitas 6reas da linguagem Java, principalmente no J2EE, onde geralmente temos que construirnossas pr6prias interfaces para estender uma das suas.

No entanto, agoarde, porque 6 agora que comega a ficar estranho. Uma interface pode estender mais de umainterface! Pense bem por um momento. Voc6 sabe que quando se trata de classes, o que vemos abilxo nio 6 vlilido:

frublic cLass PrograrEner extends Eqrloyee, Geek { , | | I,rrvlLj-Aol

Como mencionamos anteriormente, uma classe nio pode estender virias outras em Java. No entanto, umainterface pode estender virias interfaces.

inlerf,ace BounceabLe extends Dloveable, spherical {

void bounce O ;

void setBounceFactor(int bf ) ;

)

interface Moveable {void moveft O ;

)

interface Spherical {

void doSphericalThing( ) ;

)

Ball 6 necess6ria na implementagio de Bounceable, al6m de todos os m6todos das interfaces que Bounceableestende (incluindo qualquer interface que essas interfaces estendam, e assim por diante, at6 que vocb alcance oinicio 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) { }

Page 99: Java - Scjp 5 - Portugues

JAVA 5 73

publ-ic void movelt O { }

public void doSphericalThingO { }

// Implementa os m6todos de Moveable

// Implementa os m6todos de Spherical]

Se a classe Ball n5o conseguir implementar nenhum dos m6todos de Bounceable, Moveable ou Spherical, ocompilador 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 qualquerum, 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 bouncepublic 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 naoimplemenLou

public void moveTt ( ) { ... }

public void doSphericalThingO { ... }

/ / SoccerBall pode decidir sobrescrever os m6todos de Bounceable

// implementados por Ballpublic void bounce ( ) { ... }

I

interface Bounceable

void bounce( );void setBounceFacEor(int bf) ;

^I

class Tire implements Bounceable

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

abstract Ball implements Bounceabl-e

/*ndo serSo implementadosem Ball quaisquer m6todosde Bounceable */void beSpherical( ){}

class BeachBall exEends Ball

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

/*beSpherical n5o 6 abstract entaoBeachBall ndo 6 solicitado paraimplementar isso */

// oK

// Ndo! Ndo 6 trtossiveL impTementar uma cLasse

Devido oo foto de BeochBoll ser o primeiro closse concreio poro implemenlor Bounceoble, elo devefornecer 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 referidoporo implemenlor lodos.

A Figuro 2-5 comporo o uso vdlido e o n6o volido de exlens6es e implementoq6es, tonto poroclosses quonlo poro inferfoces.

oBSERVAQ6ES pene O EXAME

Procure utiliqagdes ndo udlidas de exten$u e inplenentapdes. As linhas a seguir mostram exemplos de dulamgdu udlidas e ndo udlidat de

intet'aces e clastes:

class foo { }

ala<< R:r imnlamanfc E'^^ f J

Page 100: Java - Scjp 5 - Portugues

74 Copftvlo 2: OrientoE6o o objetos

interface eaz { }

interface Fi { iinterface 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 uma/ / interface// 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

class Toon extends Foo, Button { }

cl-ass Zoom implements Fi, Fee { }

interface Vroom extends fi, Fee { }

MemoiTe isto e pmcare abusos cometidos nas petgilntar qae estiuerem n0 exame. IndEendente do que as perguntas parEam aualiar, o

pmbhna real pode ser a declaragdo da classe ou interface. 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

pa ft fl teret nre m i n ue n tadot ?).

Declarag6es de tipos de retorno

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 quepode 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 param6todos sobrecarregados e sobrescritos, porque j6 abordamos isso neste capitulo. Entraremos um pouco em uma6rea nova, no entanto, quando examinarmos os tipos de retorno polim6rficos e as regras para o que 6 ou niov 6lido re torn ar realmente.

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

Tipos de retorno de m6todos sobrecarregadosLembre-se de que a sobrecarga de m6todos nXo significa muito mais do que a reutilizagdo de nomes. O m6todosobrecarregado 6 completamente diferente de qualquer outro m6todo com o mesmo nome. Portanto, se umm6todo for herdado, mas sobrecarregado em uma classe, voc6 nio estar6 sujeito is restrig6es da sobrescrigio, o quesignifica 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 umm6todo sobrecarregado:

publj-c class Foo{

void go0 { }

)

public class Bar extends Foo {

String go(int x) {

return nu11;

Page 101: Java - Scjp 5 - Portugues

JAVA 5 75

O_bserve que a versio da classe Bar para o m6todo usa um tipo de retorno diferente. Isso 6 perfeitamenteadequado' Contanto que voc6 tenhi alterado a lista de argumentos, esrari sobrecarregando'o m6todo, porranto, otipo de retorno nio precisar6 coincidir com o da versio da superclasse. O que voc6 n?o pode fazer 6 isto:

public class Foo{

void go0 { }

]public class Bar ext,ends Foo {

String go0 { // Inv6lidol Ndo 6 possivel modificar apenas o tipo de rerornoreturn null;

)

A Sobrescrigio e os Tipos de Retorno; e Retornos Covariantes

9y4o uma.subclasse quiser alterar a implementagio de um m6todo herdado (uma sobrescrigio), ter6 quedefinir um m6todo qrre coincida exatanente com a verslo herdada. Ou, a partir do Java 5, voc6 tem a possi-bilidadede modificar otipo de retorno no m6todo sobrescritor, desde que o novo tipo de i.totno seja um subiipo do tipode retorno declarado do m6todo sobrescrito (da superclasse).

Vejamos um retorno covariante em agXo:

public class Foo{

void so0 { }

)

public class Bar extends Foo {

String goO { // sobrescrlgdo v6.1i-da em ,Java 1.5return nu11;

)

]

Com oJava 5, esse c6digo compilari sern problemas. Se voc6 tentasse compil6Jo usando um compilador 1.4 oucom o flag source, desta forma:

javac -source 1.4 Beta.javareceberia um erro de compilagio parecido com este:

attempting t.o use incompatible return type(Falaremos mais sobre os flags do compilador no Capitulo 10.)

Outras regras slo aplicadas i sobrecarga, inclusive as dos modificadores de acesso e exceg6es declaradas, mas elasnio sio relevantes para a discussio sobre o tipo de retorno.

No exame, voc6 ter6 que saber que os m6todos sobrecarregzdos podem ter o tipo de retorno alterado, mas os m6todosque estiverem sobrerreuendo outros sri poden fa$-/o dentro dot linitu dos retnftilr couariantes. 56 por ter conhecimento dissovoce 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

Page 102: Java - Scjp 5 - Portugues

76 Copitulo 2: Orientoq6o o obletos

implicitamente conveftido para o tipo de retorno declarado.

public int foo ( ) {

char c = 'c';return c; / / char 6 compativel com int

)

4. Em um m6todo com tipo de rerorno primitivo, voc6 pode retornar qualquer valor ou vari|vel que Possa ser

explicitamente convertido parao tipo de retomo declarado.

public int foo ( ) {

float f = 32.5f;return (i-nt) f;

]

5. Y oc€ ndo deve retornar nada de um m6todo com tipo de retorno void.

public void bar ( ) {

return "this is it"; /,/ rnv6lido! !

]

6. Em um m6todo que tenha como tipo de retorno a refer6ncia a um objeto, voce pode retornar qualquer tipo de

objeto que possa ser implicitamente convenido paraotipo de retorno declarado.

public Animal- getAnimal ( ) {

return new Horse (\ ; / / Assuma que Horse estenda Animal

)

public Object. getObjectO {

int[] nums = {I,2,3};reLurn nums; // Retorna um array int, que ainda 6 um objeto

]

public interface chewable { }

public class Gum implements Chewable { }

public class TestChewable {

/ / M6Lodo com um tipo de retorno da interfaceChewable getChewable {

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

)

oBSERVAQ6ES pRne O EXAME

Procure mdtodos qae dtclarem cono tipo de retomo una clasn abs trac t ou anta interface, e rzemoriry que qaa/quer objeto qae passar

no teste E-UM (erz outras pa/awar, qu/e tiaer como ruultadn lrae no teste com o operador ins t.anceo f ) podeni rcr retomado desse

mdtodo - por exemplo:

public abstract class Animal { }

public class Bear extends animal { }

public class Test {

public Animal go ( ) {

return new Bear (\ ; / / OK, Bear $a!-um/' Animal

]

]

Esse aldigo ini compilar, o ualor de retorno i um subtipo.

Page 103: Java - Scjp 5 - Portugues

JAVA 5 77

Obietivo poro o certifico€6o

Construtores e instanciagio (Objetivos 1.6 e 5.4 do exame)1.6 Dado um conjanto de claset e saperc/asses, desenuo/uer constmtzrer para uma oa mais das c/asses. Dada uma dukragdo de c/asse,

deterwinar se serri criado am clnrtutzrpadrdo e, em caso afrrtatiuo, determinar o comportamento dcsse construtor. Dada uma listagem dtc/asse aninhada ou ndo, escreuer aidigo para instanciar a c/asse.

5.4 Dado um nndrio, desenuo/ueraidigo que declare efou chame nitodos sobrescritos ou sobrecanegados, e cddigo qae dec/are efou cbane

cznJtratlres de superc/assu, con$rutoret sobrescritot ou sobrecanegados.

Os objetos sio construidos. Voc| ndo pode criar am nouo o[eto sem chamar am clnstratzn Na verdade, nio pode criar umnovo 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, parasermos 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. Temosmuito que discutir aqui - examinaremos como os construtores sXo codificados, qaem os codifica e como funcionamno tempo de execugXo. Portanto, pegue seu capacete e um martelo e executemos a construgio de alguns objetos.

Apectos bisicos do construtorToda classe, incluindo as classet abstract, precisa ter um constnrtor. Memorize isso. Mas s6 porque uma classe

precisa ter um constnrtor, nio significa qlre a prugramadorterthaque digit6-lo. lJm construtor tem o formato a

segurr:

class Foo {

roo0 ( | ll o constrirtor para a claEse foo

)

Notou o que est6 faltando? I'{do htl tipo de retomolLembre-se de que um construtor nio possui tipo de retorno, e seunome deve coincidir exatamente com o nome da classe. Normalmente, os construtores sio usados para inicializaro estado de variiveis de instAncia. como descrito abaixo:

class Foo {

int size;Qlri nd nama.

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

this.name = name;

this.size = size;

J

No c6digo do exemplo anterior, a classe Foo n5o possui um construtor sem argumentos. Isso significa que oc6digo a seguir ndo seri compilado,

Foo f = new Foo O ; / / Ndo vai compilar, nao h5 um construtor correspondente

mas a linha a seguir ser6 compilada,

Foo f = new Foo("Fred", 43); // Sem problemas. os argumentos correspondem ao

//construtor de Foo.

Portanto, 6 muito comum (e desejivel) que uma classe tenha um construtor sem argumentos, independente dequantos outros construtores sobrecarregados existam nela (sim, os construtores podem ser sobrecarregados). Voc6nno conseguiri fazer com que isso funcione sempre em suas classes; ocasionalmenrc terh uma classe em que niofar6 sentido criar uma instAncia sem fornecer informag6es para o constnrtor. IJm objeto j ava. awt.Color, porexemplo, nio pode ser criado com uma chamada a um construtor sem argumentos, porque isso seria o mesmo quedizer iJVM: "Crie um novo objeto Color para mim e nio vou me preocupar com a cor real que ele ter6,...Vocd

escolhe". Voc6 realmente quer que a JVM tome as decis6es est6dcas no seu lugar?

Cadeia de construtoresSabemos que os construtores serXo chamados no tempo de execugio quando voc6 digitar new em algum tipo declasse como vemos abaixo:

Horseh=newHorseo;

Page 104: Java - Scjp 5 - Portugues

78 Copitulo 2: OrientoEdo o obietos

Mas o que ocorreri realmente quando voc6 digitar new Horse ( ) ? (Assuma que Horse estende Animal e queAnimal estende Object.)

1. O construtor de Horse ser6 chamado. Todo constnrtor chama o construtor da sua superclasse com umachamada (implicita) a super ( ) , a nlo ser que o construtor chame um construtor sobrecarregado damesma classe (falaremos mais sobre isso em instantes).

2. O construtor de Animal seri chamado (Animal 6 a superclasse de Horse).

3. O construtor de Object ser| chamado (Object 6 a superclasse final de todas as classes, portanto, a classeAnimal estenderi Object ainda que voc6 nio digite realmente "extends Object" em sua declaraEio. Estariimplicito). Nesse ponto estaremos no inicio da pilha.

4. As vari6veis de instAncia de Object receberio seus valores explicitos. Por explicitos, queremos dizer osvalores que slo atribuidos no momento em que as varilveis sio declaradas, como "int x = 27", onde"27" 6 o valor explicito (e nio um vaTor padrio) davariSvel de instAncia.

5. A execuEio do construtor de Object ser6 concluida.

6. As variiveis de instAncia de Animal receberio seus valores explicitos (se houver).

7. A execuglo do construtor de Animal ser6 concluida.

8. As vari6veis de instAncia de Horse receberio seus valores explicitos (se houver).

9. A execugio do construtor de Horse seri concluida.

A Figura 2-6 mostra como os construtores funcionam na pilha de chamadas.

4. Object o

3. Animal O calls super ( )

2. Horse ( ) calls super ( )

l. main ( ) calls new Horse ( )

Figuro 2-6 Construtores no pi/ho de chomodos

Regras dos construtoresA lista

" j.g"lf re^sume as

.regras que voc6 teri que conhecer para faze.r o exame (e para compreender o restantecesta segao). v oce preasara se lembrar-se delas, portanto, estude-as mars de uma vez.

r Os construtores podem usar qualquer modificador de acesso, inclusive private (um construtor privatesignificaque somente o c6digo que estiner dentro da pr6pria classe poderi inJtanciar um objeto desse tipo, ionanto, sea classe do construtor private tor permitir que uma instincia dela seja usada, deve fornecer uma varilvel ou m6todostatic que conceda acesso a uma iistAncia ciiada dentro da classe).

I O nome do construtor deve coincidir com o da classe.

I Os construtores nio devem ter um tipo de retorno.

r E valido (mas inritil) ter um m6todo com o mesmo nome da classe, por6m, isso nio o tornar6 um construtor. Sehouver um tipo de retorno, seri um m6todo em vez de um construtbr. Na verdade, voc6 poderia ter um m6todo e umconstrutor com o mesmo nome - o nome da classe - dentro da mesma classe, e isso nlo 6 um problema paraJava.Cuidado para nlo achar que um m6todo 6 um constnrtor e vice-versa - pro*i. ,.*pre um tipb de retorno.

r Se voc6 nlo inserir um construtor no c6digo de sua classe, um constnrtor padrio seri gerado automaticamentepelo compilador.

I O construtor padrio ser| sempreum construtor sem argumentos.

I Se voc6 quiser um construtor sem argumentos e tiver inserido algum(n$ outro(s) no c6digo de sua classe, ocompilador nio fornecer6 esse constirtor (ou qualquer outro). Ein outras palavias, se uori"tiaerinseido amclnthatlr 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 pelocompilador.

Se voc6 inserir um construtor (emvez de ficar esperando pelo construtor padrio gerado pelo compilador) e ndodigitarachamadaasuper( )ouathis( ),icon?iladirinseini,automaticamente,irztachanadarsuper(') senargt/mentos, como a primeira instrugdo do constrvtor.

Uma chamada a super ( ) pode ser sem argumentos ou incluir os argumentos passados para o construtor dazuperclasse.

IJm construtor sem argumentos nio ser6 necessariamente o constnrtor padrio (ou seja, o fornecido pelocompilador), apesar de ele nunca ter argumentos. O coushzrtorpadrio i o que o nntpikdorfomecelEmborio

T

Page 105: Java - Scjp 5 - Portugues

JAVA 5 79

construtor padrio nuncatenha argumentos, voc6 pode inserir seu pftipit construtor sem argumentos.t

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

I Apenas vari6veis e m6todos static p9{eqr s9r acessados como pafte da chamada a super ( ) ou this () . (Exemplo: super (Animal . NAME )) 6 v6lido, porque NAME 6 declarada como uma variivel static.

I As classes abstract t6m construtores e eles sio chamado s serupre que uma subclasse concreta 6 instanciada.r As interfaces ndo t6m construtores. Elas nio fazem pane da irvore de heranga de um objeto.r A $i1 maneira pela qual um constmtoS pode ser chamado 6 dentro de outro construtor. Em outras palavras,

voc€ nio pode escrever um c6digo que chame efetivamente um construtor como vemos abaixo:

class Horse {Horse0{}//construtor

rroid dnQirr+Fl\ I

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

]

ldentificando se um construtor padrio seri criadoO 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 ( )

{Bpr3,chegamos no ponto exato. O compilador gerarS,tmconstnrtor padrXo para a classe anterior, porque nio foicelrnroo nennum construtor para ela.

Certo, e quanto a esta classe?

rlaqq IJ^rc6 f 1

void Horse( ) { }

iPode paruer que o compilador nlo crrari um construtor, porque ji existe um na classe Horse. Existe mesmo?\-rDserve novamente a classe Horse anterior.

Oque hi de errado com o constnrtor Horse( )?.Ele nio 6 de forma alguma um consrrutor! E simplesmente umm6todo que por acaso tem o mesmo nome da classe. Lembre-se de que o tipo de retorno 6 uma fista certa de queestamos olhando para um m6todo, e nio um constnrtor.

Como voce pode ter a certeza de que um construtor padrio seri criado?Isso ocorreri quando aocd ndo criar nenhum construtor em sua classe.

Como voc6 poder6 reconhecer o construtor?

Da forma a seguir:

I O construtor padrXo te ri o mesmo modfirador dt acesso da classe,

I Ele ndo terd atgumentor.

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

Page 106: Java - Scjp 5 - Portugues

80 Copitulo 2: OrientoE6o o obietos

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

Tobelo 24 Codigo do construto r gerodo pelo compilodor

C6digo do closse(digitodo por voc6)

C6digo do construlor gerodo Pelocom pilodor

cfass Foo { }

class Foo {roo( ) {

Eulrer ( ) ;)

)

cfass Foo { }FooO {}

]

class Foo {Foo( ) {

Euper( ),)

]

nrr].'linalaceFnn {l

class Foo {public roo() {

super( );)

]

class Foo { }I,OO(Srrngs) tJ

)

class Foo {F^^/qfrinn q\ I

auper( );]

)

class Foo { }!oo(Scrfngsl tj

super ( ) ;]

]

Nenhum , o compilador nao precisa inserir

class Foo { )voidFooO {}

]

cfass Foo {void Foo O {}

roo() (super( );

)](void Foo O 6 um m6todo, nao um construtor.

O que acontecer6 se o construtor da superclasse tiver argumentos?Os construtores podem ter argumentos da mesma forma que os m6todos, e se voce tentar chamar um m6todo que

use, digamos, um tipo int, mas nio passar nadaPara ele, o compilador reclamari:

cfass Bar {

class UseBar {

public static void main (String [] arqs) t

Barb=newBarO;b.takelnt () t / / Tenta chamar wn n6todo takelnto sem argJumentos

)

O compilado r avrsarique voc6 nio pode chamar takeInt ( ) sem passar um tipo int. E 9laro. qg9-o- .

compil;dor aprecia urrenigma ocasional, portanto, a mensagem que exibir6 em algumas vers6es da JVM (pode

variar com a verseo) nio seri tio clara:

UseBar.java:7: takelnt(int) in Bar cannot be applied to o

b. takelnt O ;

Mas voc6 a entender6. A conclusio 6 que deve haver uma corresponden cia para o m6todo. Por correspondAncia,

queremos dizer que os tipos dos argumentos devem poder aceitar.os valores ou varilveis que voce estiver

passando e na oraem em que forempassados. O que nos conduz de volta aos constnrtores (e voc6 Pensou que

nunca chegariamos neles), que funcionam exatamente da mesma maneira.

Page 107: Java - Scjp 5 - Portugues

JAVA 5 8IAssim, se o construtor de sua superclasse (isto 6, o constnrtor de sua superclasse,/parent imediata) tiverargumentos, 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 (asubclasse) Porque precisard de um local para inserir a clianado ao nnstrutor da s'upockss, cvm 0r atgamentus @ropiadot.O c6digo a seguir 6 um exemplo do problema:

^l ^^^ ^61*-lLfq-r rulrrrrqa 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, oproblema ser6 o.fato de nlo haver uma corrispondAncia para o q.ri.rt"*os tentando chamar com super ( )um construtor de Animal sem argumentos.

Outra maneira de colocar isso 6 que se sua superclasse ndo tiaer am consttator tem argllmentus, entio, em tua tubc/asse uoc6 niopodenl usar o conshvtorpadrdofomecidipek nrpilador. E simples assim. Ji que o coirpilador s6 pode inserir a chamada aum construtor super ( j sem arg,rmerrios, voc6 nio conseg,riri rr.* -.r-o compilar;lg" .;;; ; lafii.

"-- -

segurr:

class Clot.hing iClothing(String s) { }

)

class TShirt extends Clothing { }

IJma.tentativa de compilar esse c6digo nos traria o mesmo erro que obtivemos quando inserimos um construtorna subclasse com uma chamada i versio sem argumentos de super ( ) :

Clothing. java: 4: cannot resolve symbol<rmlrnl . .^ncf rrr^f ar ll nrlr.i na / \r1f1r9 \ /

focation: class Clothingclass TShirt extends Clothing { }

Na verdade, o c6digo anterior de cloching e TShirt 6 implicitamente o mesmo mostrado a seguir, no qualfornecemos um construtor para TShirt que 6 id6ntico ,o .onrt*tb, padrlo fornecido pelo compilador:

"

class Clothing {

Clothang(String s) t )

]

class Tshirt extends Clothino {

t t constrl.,,tor identico ao construtor cadrdo,/ / f ornaai dn nal n anmni I ^^^-

Tshirt ( ) {

supero; // Ndo vai funcionar!j / / Chama um construtor sem argumentos Clothing( )

j / / mas esse construtor ndo existelUm. riltimo ponto relacionado. a toda essa po.lAmica sobre o construtor padrio (e que provavelmente 6 muitoobvro' mas. temos que mostre-lo ou nos sentiremos culpados por anos), 6 que ar constratores nunca sdo herdados. EIesnlo sio m6todos. Nio podem ser sobrescritos (porque nio sio m6todos, e s6 os m6todos podem ser sobrescritos).

Page 108: Java - Scjp 5 - Portugues

82 Copitulo 2: Orientog6o o obietos

Poftanro, o(s) tipo(s) de construtor(e$ que sua superclasse_tiver, de maneira alguma determinar6 o tipo de

consrnrtor iia.ao q,r. rro.6 "bte.i.'Algrn",

prr*"t acreditam que o construtor padrio de alguma forma

coincidiri ** o "o'rrrt*to,

da supercLsse, trot "rru*entos

que ter6 (lembre de que o conshtttorpadrd.o i sempre am

constrator sem argunento) ou nos "rgrr*.ntot

usados na chamadi ) super ( ) fornecida pelo compilador.

Por6m, embora os constnrtores nio possam ser sobrescritos, voc6 j6 viu que eles podem ser sobrecarregados, e

normalmente o sio.

Construtores sobrecarregados

Sobrecarregar um consrruror significa inserir v6rias vers6es dele, cada uma tendo uma lista de argumentos

diferente, como nos exemplos a seguir:

class Foo {

roo0 { }

Foo(String s) { }

)

A classe Foo anterior possui dois construtores sobrecarregados, o que usa.uma string e outro sem argumentos. Jique nio h6 um c6digo na versXo sem argumentos, na verdade, essa classe 6 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.

A sobrecarga de um construtor normalmente 6 usada para fornecer maneiras alternativas de os clientes

instanciareir objetos de uma classe. Por exemplo, se o-cliente souber o nome d9 ".- animal, poderi pass6-1o para

um construtor de Animal que use strings. Mas se ele nio souber o nome, poderi chamar o constnrtor que nio usa

argumentos, e este fornecei6 n* tto-. padrlo. Veja como funciona:

1. public class enimal {

2. String name;

3. Animal(String name) {

4. this.name = name;

s. )

7. Animal O {

8. this (makeRandomName O ) ;

10.

11. Etatic String makeRandomNameo {1,2. int x = (int) (Math.random(1 * 5);1-3. String name = new Stringi] {"Fluffy", "Fido"'

"Rover", "Spike",

"Gigi"] [x] ;

L4. return name;

15. )

]-6.

17. public static void main (String [] args) i18. 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

Page 109: Java - Scjp 5 - Portugues

JAVA 5 83Zeus

I java Animal

FluffyZeus

t java Animal

Rover

I java Animal-

FluffyZeus

Muita coisa aconteceu no c6digo anterior. A Flgur_a 2-7 mostra a pilha de chamadas de construtores quando umconstnrtor 6 sobrecarregado. Examine a pilha de chamadas e, em seguida, percorreremos o c6digo desde o inicio.r Linha 2 Declara avari|vel de instAncia de String nana

r Linhas3 a5 Insereoconstrutorqueusastringseoatribuiavari6vel deinstincianane.

r r,inha T P ^qy;que fica divertido. Suponhamos que cada animal precise de um nome, mas o cliente (o c6digo

chamador) pode nio saber qual deve ser usado, porta.rto, voc6 attuir6 um nome aleat6rio. O construtor seirargumentos gerarS, vm nome chamando o m6todo makeRandomName( ).

4. object ( )

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

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

l.main( ) chama new Animal( )

Figuro 2-7 - Construfores sobrecorregodos no pilho de chomodos

r Linha 8 O construtor- sem argumentos chamar6 o constnrtor que o sobrec arrega e usa strings, da mesmamaneira que seria chamado se o c6digo-cliente estivesse executando o comando new para instinciar umobjeto, passando para ele uma string relacionada ao nome. A chamada sobrecarregada nsa a palavra-chavetJris, empregando-a como se fosse o nome de um m6todo, this ( ) . Portanto, a linha 8 esi6 simplesmentechamando o constrtrtor da linha 3, passando para ele uma string selecionada aleatoriament , emviz de umnome escolhido pelo c6digo-cliente.

r Linha 11 Observe que o m6todo makeRandomName ( ) foi marcado com static! Isso porque voc6, ndopode chamar um m6todo de instAncia (em outras palavras, nio-static) ou acessar uma vari6vel ie instAncia,at6 que o constnrtor da superclasse tenha sido exicuta do. E ji que esse construtor seri chamado a partir doconstrutor da linha 3, emvez de usar o da linha 7, alinha 8 s6 poderi empregar um m6todo static paragerar o nome. Se quis6ssemos que todos os animais sem nomes especificidos pelo chamador tivessem omesmo nome padrXo, digamos, 'Fred", enteo, a linha 8 poderia apresentar thls ( "Fred" ); em vez dechamar um m6todo que retorne uma string com o nome escolhido aleatoriamente.

r Linha 12 A linha 12 nio tem nada a ver com construtores, mas j6 que estamos todos aqui para aprender... Elagera um nfmero aleat6rio entre O e 4.

r Linha 13 Sabemos que 6 uma sintaxe estranha. Estamos criando um novo objeto String (apenas uma instinciade 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 Stringrec6m-criado.

4. Atribuimos a string recuperada no array i variivel de instAncia declarada, nama Poderiamos rer tornadoa 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 totalmenterelacionado ao cerne da questio) f.az pane do espirito do exame. Nlb fique

"rsustlado (ceno, fique assusrado, mas

entAo apenas diga para si mesmo: "Calma", e d€ prosseguimento).

r Linha 18 Estamos chamando a versio sem argumentos do construtor (fazendo com que um nome aleat6rioda lista seja selecionado e passado para o outro construtor).

Page 110: Java - Scjp 5 - Portugues

84 Copitulo 2: Orientog6o o objetos

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

O ponto chave a exrrair desse exemplo de c6digo esta na finha 8. Emvez de chamar super ( ) , estamos

chimando this ( ) que nmpre tWtf* una chinad.a a uatro cunstrator da mesma classe. Certo, mas o que aconteceri

depoisdachamada a this ( )i CJo outarde o construtor super ( ) ser6 chamado, nXo 6? L6gico..Uma.

cfr"-"d" a this ( ) significa apenas que vocA esti retardando o inevit6vel. Algum construtor' em algum local,

ter6 que Iazer a chamada a super ( ) .

Regra chave: a primeira linha de um construtor deve ser uma chamada a super ( ) ou a thig ( ).

Sem exceg6es. Se voc6 nXo tiver nenhuma dessas chamadas em seu construtor, o compilador inserir6 a chamada

semargumenrosasuper( ).Emoutraspalavras,seoconstrutorA( )tiverumachamadaathis( ),ocompiLdor saberi que ndo seri esse construtor que chamari super ( ) .

A regra anterior quer dizer que um construtor nunca pode ter tanto uma chamada a super ( ) quanto a this (

I . J6 que essas chamad"r p.eiim* ser a primeira instrug-Xo de um construtor, voc6. nio.pode usar de maneira

vilida as duas no -.r-o ^.onrtrutor.

Issb tamb6m significa que o compilador nio inserir6 uma chamada a su-per ( ) em um construtor que possua uma chamada a uhis ( ) .

Pergunta a se considerar: O que vocA acha que acontecerisetentar compilar o c6digo a seguir?

class A {

AO{this("foo");

)

A(String s) {

this O ;

)

)

Seu compilador pode nio captar o problema (isso variari dependendo do compiladgl ml1 a maioria nXo

perceberi o pro6lema). Ele presumir6 que voc€ sabe o que esti fazendo. Conseguiu identificar a falha?-Dado. que o'.onrt*to, d. .t-" superclaise deve seriempre chamado, onde a chamada a super ( ) seria inserida? Lembre-se

de que o compilador nio vai inserir rr- .onit*tor padrio se voc6 i6tiver um ou mais construtores em sua classe.

Mesmo assim, ele aindainsere uma chamada a super ( ) em algum construtor que nlo tenha explicitamente uma

chamada ao construtor da superclasse - a menos que o construtor_ ji tenhauma chamada a this ( )' Ponanto, no

c6digo anterior, onde srrpei ( ) pode ser inserido? Os rinicos dois construtores da classe t6m chamadas a

thi; ( ), evoc6 obter6e*at"metrte o mesmo que conseguiria se digitasse o c6digo do m6todo aseguir:

public void goo t

doStuff ( ) ;

)

public void doStuff ( ) {

go(),.

)

AgoravocE consegue enxergar o problema? E claro que sim. Apithafoi exndida!Elaficou maior e maior, a!6 qu9 .

siirplesment. r. ibtin e o i6dig" do m6todo foi deiramado, esvaindo-se parafora daJVM e.caindo no chio. Dois.orrit-tor.r robrecarregados chinando this, sio dois construtores chamando um ao outro. Repetidamente, resultando em

* java AException 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 "ttr "p6tt"r

um constnrtor e, em seguida, fazendo 9om qge outros construtores o chamassem, voc6 nio teriaque escrerrei e fazer a manutengio de v6rias vers6es do c6digo desse construtor imponante. Basicamente, os

.b.rrt*to.., que nio fossem ,.iarr"rrt., chamariam esse outro constnrtor sobrecarregado, passando para ele os

dados que precisasse (dados que o c6digo-cliente nio forneceu).

Os construtores e a instanciagio se tornarXo ainda mais interessantes (agora que vocA achou que estava livre) _

quando chegarmos )s classes internas, mas sabemos q-ue voc6 s6 poder6 suportar tanta diversXo em outro capitulo,ponanro, esramos guardando o resto da discussio sobre instanciagio de classes internas para o Capitulo 8.

Page 111: Java - Scjp 5 - Portugues

JAVA 5 85

Obletivo poro o CertificoEdo

Static (Objetivo 1.3 do Exame)

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

Variiveis e m6todos stat:c

O modificador static tem um impacto de forma profunda sobre.o comportamento de um m6todo ou variivel que otrataremos como um conceito inteiramente separado dos outros modificadoies. Para compreender a manerra como ummembrostatic funciona,examinaremosp-rimeiro arazioparausarum. Imaginequeioc6tivesseumaclasseutilit6riacom um m6todo que sempre fosse executido da mesma mineira; sua rinica"fungio seria retornar, digamos, umnrimero 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., davariivel deinsA.ncia) de um objeto. Portanto, por que, entio, voc6 precisa de um objeto, j6 que o m6todo nuncaser6 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 instAnciascriadas

_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 reinicializadacom um valor padrlo a cada nova instAncia.

$ lesposta tanto parao cenlrio do m6todo utilitirio, sempre executado da mesma forma, quanro para a contagemininterrupta do total de instAncias 6 usar o modificador static. As variiveis e m6todos marcados co"m staticPertencem i classe, emvez de a qualquer instAncia especifica. Na verdade, vocA pode usar um m6todo ou variivelstatic sem ter absolutamente nenhuna in$incia dessa classe. 56 precisa ter a classe disponivel para poder chamar umm6todo static ou acessar uma variivel static. As variiveis static tamt6tn poi.- ier acessadas sem tera instincia de uma classe. Mas se houver instAncias, avari|vel static dessa classe ier6 companilhada por todasas instAncias da classe; s6 haveri uma c6pia.

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

class Frog {

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

frogfcount += 1; / / Modifica o valor do const.rutor)

public static void main (String [] args) {

new Frog'O;

new Frog( ) ;

new FrogO;System.out.println("Frog count is now .. + frogCount);

]

)

No c6digo anterior, a vari|vel static frogCount 6 configurada com zero, quando a classe Frog 6 carregada pelapriqgira vez pela JVM , antes que qualqaer instdncia de Frog rc1a a)aat (A prop6sito, ioc€. nilo precisard rellmente " 'inicializar uma vari6vel static com zero; as variiveis est6ticas iecebem ot -"r*or-rralores padrlo que asvarilveis de instAncia). Sempre que uma instAncia de Frog for criada, o construror ser6 executado e arrmlentari ovalor da vari6vel est6tica f rogCount. Quando esse c6digo for executado, tr6s instAncias de Frog serio criadasemmain( ) e o resultadoser6:

Frog count is now 3

Agora imagine o que aconteceria se frogCount fosse uma variivel de instAncia (em outras palavras, ndofosse unidc):

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

class Frog {

i nf f rnaanrrhf - n.

nrrhlin E'r^ft/\ /! +vv \ / L

fr^d/l^rrnf r- 1.rrvvvvsrrL , - r,

1)

// DecTara e inicializa a vari6vel de instAncia

/ / Nlodifica o valor do construtor

Page 112: Java - Scjp 5 - Portugues

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

"trti. nio saberia nada sobre elas. O mesmo se aplica a m6todos de instAncia; um m6todo static nio pode

chamar diretamente um m6todo nio staLic. Considere static : classe, nlo stat.ic : instlncia. Tornar om6todo chag{9 pelaJVM-(main ( ..)) static significa que aJVM nio teri que criar uma instAncia de sua classe

apenas para iniciar a execugio do c6digo.

oBSERVAQ6ES pene O EXAME

[Jm dos enos maisfreqiientet cometidos porprogramadoru laua iniciantet d tenlar acessar una uarihuel de in$6ncia (o qae ignfrca una

aaiiaelndostatic) apartirdomitodomain( ) (quendotennenhamainfomag1osobrein$incias,prrtantz,ndopodeaeessaraaaiduel). O aidigo a rcgair i um exenpk de acesso inudlido de ama aaidael ndo sLaLic a partir dt um mitodo s tat i c.'

class Foo {

int x = 3;

public static void main (String [] args) t

System.out.println("x j-s " + x) ;

)

]

E bon qae aoc6 saiba qae use aidigo nunca uri compilado, porque n6o 6 possiuel acessar uma uariiuel n6o sEaLic (de instdnciQ a patirde um mitodo static. Apenas inagine o compilador diqpndo 'Ei, ndo tenbo iddia de que uaiduel x do objeto Foo aocd ettui tentando

exibir!" I-,embre-rc de qae t4 a cksse que execata o mitodomain ( | e ndo uma instdncia da classe. E claro que aparte corrplicada no

exane seni qae a perglnta ndo pareceni tdo 6bria quanto o c1digo anterior. O problena sobre o qual uocd estari sendo aualiado - acesiar tlma

uariduel ndo sLatic a paftir de am mitodo static - senl. canuflado no aidigo qle pareceni aaa/iar oatra qautdo, Por exempk, seria

mais prouduel que o cddigo acina aparecese naforwa:

class Foo {

int x = 3;

fl-oatY=4.3f;public static void main (String 1l args) {

for (int z = x; 7 < ++xi z-, Y = Y + z\ {

/ / c6digo complicado de looping e branching

)

)

Portanto, efiquantr uoc6 ertiaesse tentando acompanbar a hgica, o problena real seia qile x e y ndo poden ser ttsados dentro de main (

),porquesdoaaridaeisdeinstdnciaendostaticlOmetnose@/icaa0acervdemdtodosndosLaLic apanirdcummdtodo

static. Aregrai,omitodo static deumaclassendopodeacessarilmnembro-mitodoouaariiuel-ndouhitico(deinstdncia) de

nta pnlpria classe.

Acessando yari6yeis e m6todos staticJriquevoc€nioprecisaterumainstinciaparachamarumm&odostatic ouacessarumavai|velstatic,entio,iomo chamar6 ou usar6 um membro st;tic? Qual 6 a sintaxe? Sabemos que para um m6todo de instAncia comum, voc6usaria o operador ponto na refer6ncia a uma instAncia:

nl:ce Frnn I

int frogSize = 0;

nrrhlia in{- aat-FranQizaI\ Ivgvf!v+fr9Yv9rrvVv*!v\,

return frogSize,'

Page 113: Java - Scjp 5 - Portugues

JAVA 5 87

public Frog(int s) {

frogSize = s;

)

public static void main (String [] args) {

Frog f = new Frog(25);System.out.println(f.getFrogsizeO); / / Acessa o m6todo da instAncia usando f

)

No c6digo anterior, criamos uma instAncia de Frog, a atribuimos a variavel de refer6ncia f e, em seguida, usamosessa referenciapara chamar um m6todo na instdnciaFrogque acabartos rriar.Emoutras palavras, o m6toiogetFrogsize ( ) 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. Dorouepode 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 staticpublic 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

)

class Dog extends Animal- {

static void dostuffO { // 6 uma redefinigd.o,

l

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

Frogf=newFrog0;int frogs = f.getFrogCount()t // Acessa o m6todo est6tico getFrogCount usando f

No c6digo anterior, instanciamos um objeto Frog, atribuimos esse novo objeto a variivel de refer0ncia f e, emseguida, usamos a referAncia I para charnar um m6todo static! Mas mesmo que tenhamos usado uma instAnciaespecifica de Frog.para acessar o m6todo static,-as^regras nio.foram alteradas. Isso 6 simplesmente um truque desintaxe para permitir que voc6 ase rrma uariduel de refer6ncia de objeto (mas nXo o objeto que ila referencia) pariacessar uma variivel ou m6todo static, mas o membro stat.icainda nio tem conhetimento da instAnciaespecifica usada para cham6lo. No exemplo, o compilador sabe que a refer6ncia f 6 do tipo Frog e, porranro, om6todo static da classe Frog 6 executado sem conhecer ou se preocupar com a instAncia na outri exremi&de darefer6ncia f. Em outras palavras, o compilador s6 se preocupari com o fato de a referdncia f ser declarada com otipo Frog. A Figura 2-8 ilustra os efeitos do modificador stat.ic sobre m6todos e variiveis.

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

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

class Animal {

static void doStuff O {

System.out.print ( "a " ) ;

Page 114: Java - Scjp 5 - Portugues

88 Copftulo 2: Orientogdo o objetos

/ / nd'o uma sobrescrj-qdo

System.out.print ( "d " ) ;

)

public static void main(string [] args) {

Animal tl a = {new Animal O , new DoSO ' new Animal O };for(int x = 0,' x < a.length; x++)

alxl.dosuuf,f Ot | / cli;ama o m6todo static

)

)

Executar esse c6digo produz a seguinte saida:

Lembre, a sintaxe a [x] .doStuf f ( ) 6 apenas um atalho (o truque da sintaxe)... O compilador usar6' emvezdisso,algocomoAnimal .doStuff O.Reparequenlousamosaquioloop for apimoradoloJava1.5(abordaJo no Capitulo 5), embora pud6ssemos t6lo feito. Espere ver uma mistura de estilos de programaglo e

pr6ticas deJava 1.4 eJava 5 no exame.

classe Foo

int size = 42;slatic void doMore( ){

int x = sVe;]

classe Bar

void go ( );stat,ic. void doMore ( ) {

fft );J

classe Baz

sEatic int count;static void woo( ){ }static void doMore( ){

woo( );i nF v - ^^irnF

.

)

O m6todo static neo 6 capaz de

acessar uma variivel de inst6ncia

(nio-static)

O m6todo static ndo 6 capaz

de acessar um m6todo nio-

static

O m6todo static 6 copoz deacessar 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

modo que o que e$;mos discutindo neste capitulo 6 do ponto de,vista do exame, que nio 6 de forma nenhuma a

verdade absoluta sobre esses dois principios OO de projetos. Pode nio ser exatamente a forma como voc6 os

aprendeu, mas 6 o que vocA precisa entinder para responder as quest6es. Haveri bem poucas quest6es sobre

acoplamento e coesio no exame real.

Page 115: Java - Scjp 5 - Portugues

JAVA 5 89

RXt l?k t6picos, acoplamento e coesio, t6m a ver c.om a qualidade de um projeto oo. Em geral, o bom projetooo pede acoplamentofraco 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 sior Facilidade de criagio

I Facilidade de manurengio

r Facilidade de melhorias

AcoplamentoVamos comegar f.azendo uma tentativa de definigio do_ acoplamento. Acoplamento 6 o grau em que uma classeconheceoutraclasse.Seorinicoconhecimentoque.aclasseAtemsobreaclasseB6oqieaclasseBexp6satrav6sdasua 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

".oplr*.nro."r..'as classes 6 mais forte... E isso nlo 6 bom. Em outras palavras, se A sabe mais do que deveria sobre a maneira pelaqual B foi implementada, entio A e B t6m acoplamenio forte.

lJsandocste segundo cenirio, imagine o que acontece quando a classe B 6 aprimorada. E bem possivel que odesenvolvedor que esteja aprimorando.a classe B ne* saib" da exist6ncia da classe A, afinal po. qrr. dev'eria? Odesenvolvedor da classe B deve panir do principio que quaisquer melhorias que nio danifiqfuem a interface daclasse deverlo ser seguras, entio.ele pode modificar

"lg,rm" pirte da classe que nlo se refira ) interface, o que

entio f.az a classe A ser danificada.

Opiorcasopossivel6ahorrivelsituagioemqueaclasseAsabedecoisasnio-relativas)APlsobreaclasseB,eaclasse B sabe de coisas nio-referentes i API sobre a classe A... Isso 6 MUITO RUIM. Se qualquer uma das claisesfor modificada, 6 possivel que a outra seja danificada. Vejamos um exemplo 6bvio de ..opl"-.rrto fone, queresultou de um encapsulamento mal feito:

class DoTaxes {

float rate;float doColorado O {

SalesTaxRates str = new SalesTaxRates ( ) ;

rate = str.salesRatei // oh nio// isi.o deveria ser uma chamada a m6t.odo:

/ / raLe = str.qetSalesRate (..CO', ) ;

/ / faz coi-sas com rate)

)

class SalesTaxRates {

guJrlic float salesRate; / / deveria ser privatepubJ.ic float adjustedSalesRat-e; / / 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 quetodas.as interag6es entre objetos em um_sistema OO usassem as APIs, ou seia, os contratos, das respectivas'classesdos objetos. Teoricamente, se todas as classes de uma aplicagio tiverem APis bem elaboradas, entXo deveria serpossivel que todas as interag6es interclasses as usassemtxclusivamente. Como discutimos anteriormente nestecapitulo, 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 emexemplos realmente 6bvios de acoplamento forte; nio lhe ser6 pedido que faga julgamentos sutis sobre o assunto.

CoesioEnquanto que o acoplamento tem a ver com a forma como as classes interagem umas com as ouuas, a coesio se refere a comouma determinada classe foi elaborada. O termo coudo 6. usado para indicar o grau em que uma classe tem um rinico e

Page 116: Java - Scjp 5 - Portugues

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. Outrobeneficio'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 oseguinte projeto desde o comego:

class BudgetReport {

Options getReportingOptionsO { }

void generateBudgetReport(Options o) { }

]

cl-ass Connect.ToRDBMS {

DBconnectj-on getRDBMSO { }

l

class PrintStuff t

PrintOptions getPrintoptionsO { l

)

class Fil-eSaver {

SaveOptions getFileSaveoptionsO { }

)

Este projeto 6 muito mais coeso. Em vez de uma classe que faz tudo, dividimos o sistema em quatro classes principais, ca&tr-" iom .rm papel bastante especifico, ort clero. Uma vei que n6s construimos essas classes esp eirafizadas e reuttlrzl.veis,serl muito rnaii f6cil .t..err.i um novo relat6rio, vmavez que j6 temos a classe para a conexio ao banco de dados,

a classe para impressXo e a classe que salva os arquivos, e isso significa que elas podem ser reutilizadas Por outrasclasses que possam querer imprimir um relat6rio.

Resumo para a certificagioN6s 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 instAnciasprivadas e com getters e setters priblicos.

Em seguida, abordamos a imponAncia da heranga, para que voc6 pudesse entender a sobrescrigio, a sobrecarga ,opolimorfismo, a conversio de refer}ncia,os tipos de retorno e os constnrtores'

Abordamos E-UM e TEM-IIM. n-UVt 6 implementado usando-se a heranga, e TEM-UM 6 implementado usando-se

variiveis de instAncias para se referirem a outros objetos.

O polimorfismo veio em seguida. Embora o tipo de uma variivel de refer0ncia nio possa ser modificado, ele pode ser

*rdo p".* r. .eferir a um o6jeto cujo tipo seja um subtipo do seu pr6prio. Aprendemos como determinar quais m6todos

sio invociveis para determinada variivel de referOncia.

Page 117: Java - Scjp 5 - Portugues

JAVA 5 9IExaminamos. a diferenga entre m6todos sobrescritos e sobrecarregados, aprendendo que o m6todo sobrescritoocorre quando umasubclasse herda o m6todo da superclasse, e, entio, o reimpleme ni^ p^r^adicionar umcomPortamento mais especializado. Aprendemos que no tempo de execugio, a JVM chamar6 a versio dasubclasse 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, endosobrescritos, j6 que, na verdade , niolrd nada asobrescrever).

Vimos que os m6todos novos devem manter a mesma lista de argumentos e tipo de retorno (ou, do Java 5 emdiante,, eles podem retornar um.subtipo do tipo de retorno decllrado do m6todo sobrescrito da srp.rclasr.f dom6todo sobrescrito e que o modificador de acesso nio pode ser mais restritivo. O m6todo nono t"-b6* nio podelangar 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 sintaxesuper.doSomething( ) ;.Os m6todos sobrecarregados permitem que voc6 reutilize o mesmo nome de m6todo em uma classe, mas comargumentos diferentes (e op.cionalmente, um tipo deretorno diferente). Enquanto os m6todos q,a,e sobrcsTeuemoutros ndo devem alterar a lista de argumentos, os m6todos sobruanegaiot preiso, faz|-lo. Por6m, diferente dosm6todos novos, os sobrecarregados podem variar o tipo de retorno; o modificador de acesso e as exceg6esdeclaradas da maneira desejada.

Aprendemos o funcionamento da conversio (em geral redutora), das vari6veis de referdncia, quando ela 6necess6ria e cemo usar o operador insLanceof .

A implementagio de interfaces veio em seguida. As interfaces descrevem um contrato que a classe implementadoradeve 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 interfacespodem estender outra interface.

Tamb6m examinamos os tipos de retorno dos m6todos, e vimos que voc6 pode declarar o tipo de retorno quequiser (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 mesrrrotipo de retorno do m6todo sobrescrito da superclasse. Vimos que enquanto os m6todos novos ndodevem alterar otipo 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 implicitamenteconvertido no tipo-de retorno declarado. Portanto, pbr eiemplo, short pode ier ietornado quando o tipo deretorno declarado for um int. E uma referAncia a Horse pode ser retornada quando o tipo de-retorno declaradofor 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, ocompiladorinserir6um. O construtorgeradopelo compilidor6 chamado de consrrutorpadrio, e6 sempreumcon$rurorsem argumentos com uma chamada sem argumentos a super ( ) . O construtor padrionunca seri gerldo se houver ums6 construtor que seja na sua classe (independentemente dos argumentos que ele r.rse), entio, se voc6 lrecisar de mais de umconstnrtor na sua classe e_quiser usar um sem argumentos, ter6 de escrevA-lo voc6 mesmo. Tamb6m vimos que osconstnrtores 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 temtipos de retorno.

N6s vimos como todos os construtores da 6rvore de heranga de um objeto serio sempre chamados quando oo.bjel^g 6 instanciado usando-se new. Tamb6m vimos que os construtores podem ser sobrecarregados, o quesignifica definir construtores com listas de argumentoi dife.etrt.r. Um construtor pode chamaioutro dimesmaclasse com a palavra-chave this O , como se o constnrtor fosse um m6todo chamado this O . Vimos que todoconstrutor 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, demodo que s6 existe uma c6pia de cada membro static. lJm erro comum 6tentar referenciar uma variivel deinstancia a partir de um m6todo static. IJse o nome da classe com o operador ponto para acessar membrosstatic.N6s discutimos dois conceitos da programagio orientada a objetos, que sio o acoplamento e a coesio. Oacoplamento fraco,6 o estado desejivel para duas ou mais classes que-interajam rrriras.orn as outras atrav6s daszuas_respectivas APIs. O acoplamento fone 6 o estado indesej6vel para duas ou mais classes que conhegamdetalhes internos sobre outra classe, detalhes nio revelados na API da classe. A alta coesio 6b estado desei6velpara 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 r6pidosAqui estXo alguns dos pontos-chave de cada objetivo para certificagio deste capitulo.

Page 118: Java - Scjp 5 - Portugues

92 Copitulo 2: OrientoE6o o obietos

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

E O encapsulamento aluda a ocultar a implementagio por tris de uma interface (ou API)'

tr O c6digo encapsulado fornece dois recursos:

E As vari6veis de instAncia sXo mantidas protegidas (geralmente com o modificador private).

E Os m6todos capturadores e configuradores fornecem acesso a variiveis de insdncia.

E O relacionamento E-Uvt se refere ) heranga.

E O relacionamento n-UU 6 representado pela palavra-chave extends.

E "E-UM", "herda de" e "6 um subtipo de" sio todas express6es equivalentes.

tr TEM-UM significa que a instincia de uma classe 'tem uma" refer6ncia I instAncia de outra classe, ou a outrainstAncia da mesma classe.

Heranga (Objetivo 5.5)D A heranga 6 um mecanismo que permite que uma classe seja uma subclasse de outra, e, dessa forma, herdar

variiveis e m6todos da superclasse.

D A heranga 6 um conceiro fundamental, que est6 por tr6s do E-UM, do polimorfismo, da sobrescrigio, da

sobrecarga e da conversio.

fl Todas as classes (exceto obj ect) sio subclasses do tipo obj ect, e, portanto, herdam os m6todos de ob-i:ats

Polimorfismo (Objetivo 5.2)E Polimorfismo significa "muitas formas".

U Uma vari|vel de refer6ncia 6 sempre de um s6 tipo imutivel, mas ela pode referir-se a um objeto do subtipo.

E Um mesmo objeto pode ser referido por vari6veis de instAncias de muitos tipos diferentes - desde que elas

sejam do mesmo tipo ou de um supenipo do objeto.

E O tipo da variivel de refer6ncia (nio o tipo do objeto) determina quais m6todos poderlo ser chamados!

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

Sobrescrig6o e sobrecarga (Objetivos 1.5 e 5'4)E Os m6todos podem ser sobrescritos ou sobrecarregados; os construtores podem ser sobrecarregados, mas nio

sobrescritos.

D Os m6todos abstrac L deuerz ser sobrescritos pela primeira subclasse concreta (nio abstract).O No que diz respeito ao m6todo sobrescritos, o m6todo novo:

E Deve ter a mesma lista de argumentos;

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

tr Nio deve ter um modificador de acesso mais restritivo;

O Pode ter um modificador de acesso menos restritivo;

tr Nio pode langar exceg6es verificadas novas ou mais abrangentes;

tr Pode langar exceg6es verificadas mais restritivas ou menos abrangentes, ou qualquer excegio nioverificada.

E Os m6todos f inal nio podem ser sobrescritos.

tr 56 os m6todos herdados podem ser sobrescritos, e lembre-se de que os m6todos private nio sio herdados.

E Uma subclasse usar6 super. overridenMethodName ( )para chamar a versio da superclasse de umm6todo sobrescrito.

EJ Sobrecarga significa reutllizar o mesmo nome de m6todo, mas com argumentos diferentes.

fl Os m6todos sobrecarregados:

D Devem ter listas de argumentos diferentes;

fl Podem ter tipos de retorno diferentes, contanto que as listas de argumentos tamb6m sejam diferentes;

El Podem ter modificadores de acesso diferentes;

E Podem lancar exceQ6es diferentes.

Page 119: Java - Scjp 5 - Portugues

JAVA 5 93

E os m6todos de uma superclasse podem ser sobrecarregados em uma subclasse.

tr O polimorfismo 6 aplicivel i sobrescrigio e nio )sobrecarga.

Q O tipo de objeto (e nio o tipo da vari6vel de refer€ncia) determina qual m6todo sobrescrito seri usado no ternpocte execugao.

tr O tipo de refer6ncia determina qual m6todo sobrecarregado ser6 usado no tempo de compilaglo.

Conversio de Vari6veis de Refer6ncia (Objetivo 5.2)E Existem dois tipos de conversio de variiveis de refer6ncia: a conversio redurora e a ampliadora.

E Conversio redutora: se voc6 tiver uma vari|vel de referAncia que aponte para um objeto de um subtipo, poder6atribui-la a uma vari6vel de refer6ncia do subtipo. Voc€ precisa f^ie, u iconversio explicita p"." iso, I oresultado 6 que voc6 pode acessar os membros-do subtipb com essa nova vari6vel de referAncia.

0 Conversio ampliadora: voc6 pode atribuir uma vari6vel de referAncia a uma varibvel de referAncia de umsupenipo explicita.ou implicitamente. Essa 6 uma operagio inerentemenre segura porque a atribuigiorestringe as capacidades de acesso da nova variivel.

lmplementando uma Interface (Objetivo 1.2)fl Quando voc6 implementauma interface, est6 cumprindo o seu contraro.

tr Voc6-implementa uma interface ao sobrescrever apropriada e concretamente todos os m6todos definidos pelainterface.

E Uma mesma classe pode implementar muitas interfaces.

Tipos de Retorno (Objetivo 1.5)fl Os m6todos sobrecarregados podem modificar os tipos de retornol os m6todos sobrescritos nio podem, exceto

no caso de retornos covariantes.

E Os tipos de retorno de referAncias de objetos podem aceitar nul-L como valor de retorno

D Um array 4 um tipo de retorno vilido para declarar e para retornar como um valor.

E Para m6todos com tipos de retorno primitivos, pode ser retornado qualquer valor que possa ser converridoimplicitamente para o tipo de retorno.

tr Nada pode ser retornado a partir de um void, mas voc€ pode decidir nXo retornar. E permitido que voc6 usesimplesmente return, em qualquer m6todo com um tipo de retorno void, para inierrornper um m6todo antes dasua finalizagio. Mas nio 6 possivel retornar nada a panir de um m6todo com um tipo de retorno nio-void.

tr M6todos com um tipo de retorno que 6 uma referOncia a um objeto podem retornar um subtipo.

E M6todos com um tipo de retorno que 6 uma interface podem retornar qualquer implementador.

Construtores e Instanciamento (Objetivos 1.6 e 5.4)E Nio se pode criar um objeto sem que seja chamado um constnrror.

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

E Toda classe, mesmo as classes abstract, tem pelo menos um construtor.

D Os construtores devem ter o mesmo nome da classe.

E Os constnrtores nio t6m um tipo de retorno. Se houuer,entio, seri simplesmente um m6todo com o mesmo nomeda classe e nio um construtor,

E A execugio do construtor ocorrer6 da maneira a seguir:

E O construtor chamari o construtor de sua superclasse, que chamar6 o construtor de sua superclasse, e assim pordiante, at6 alcangar o consrrutor de Objea.

E O construtor de Object seri executado, retornando em seguida ao construtor chamador, que ser6 processado at6 suaconclusio, e por sua vez retornar6 ao construtor que o chamou; dando prosseguimento a essa

-eqii6nCia at6 a execugio

do construtorda instAncia que estiver sendo criada.

E Os construtores podem usar qualquer modificador de acesso (at6 mesmo private!).E O compilador criar6 um co nfirutor padraose voc6 nio criar nenhum construtor em sua classe.

E O construt or padrdo 6 wconstrutor sem argumentos com uma chamada tamb6m sem argumentos a super ( ) .

E A primeira instrugio de todo construtor deve ser uma chamada a thi s ( ) (um construtor sobrecarregado) ousuper ( ).

Page 120: Java - Scjp 5 - Portugues

94 Copitulo 2: Orientogdo o obietos

tr O compilador adicionarS,umachamada a super ( ) , a menos que voc€ i|tenhainserido uma chamada a

this( ) ouasuper( ).

D Os membros de instAncia s6 podem ser acessados dqoir de o construtor da superclasse ser executado'

E As classes abstract possuem constnrtores que sio chamados quando uma subclasse concreta 6 instanciada.

D As interfaces nio t6m constnrtores.

B Se sua 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'

D Os construtores nunca sio herdados, portanto, nXo podem ser sobrescritos.

tr Um constnrtor s6 pode ser chamado diretamente por outro constnrtor (usando uma chamada a super ( ) ou

rhis ( )).

E Quest6es relacionadas com chamadas a this ( ) :

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

O A lista de argumentos determina que construtor sobrecarregado ser6 chamado.

B Os construtores podem chamar outros construtores que podem chamar-ainda ourros eassim por diante;mas, cedo ou iarde, 6 melhor que un deles chame super ( ) ou a pilha excederi o limite.

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

nunca os dois.

Est6ticos (Objetivo 1.3)D Use m6todos static para implementar comportamentos que nio sejam afetados pelo estado de quaisquer

instincias.

E Use variiveis static paraarmazonar dados que sejam especificos ) classe, em vez de i instAncia - s6 existiri umac6pia de uma vari6vel 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

"om o op.t"dor na verdade 6 um truque sint6tico, e o compilador substituiri a variivel de referAncia pelo

nome da classe, por exemplo:

d.doStuff O ;

se torna:Dog.doStuff ( ) ;

E M6todos static nlo podem ser sobrescritos, mas podem ser redefinidos.

Acoplamento e Coesio (Objetivo 5.1)D O acoplamento refere-se ao nivel em que uma classe conhece ou usa membros de uma outra classe.

fl O acoplamento fraco 6 o estado desejivel para classes bem encapsuladas, que minimizam as referAncias umas is outras e

limitam a extensio do uso da API.

E O acoplamento forte 6 o estado indesejivel de se ter classes que desobedecem is regras do acoplamento fraco.

D A coesio refere-se ao nivel em que uma classe tem um rinico e bem definido papel ou responsabilidade.

E A alta coesio 6 o estado desej6vel de uma classe cujos membros dio suporte a um rinico e bem definido papel ouresponsabilidade.

D A baixa coesio 6 o estado indesejivel de uma classe cujos membros dlo suporte av6rios pap6is ou responsabilidades

nio-focados.

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

Page 121: Java - Scjp 5 - Portugues

JAVA 5 95

D. Os relacionamento Tem-Um sempre dependem do polimorfismo.

E. Os relacionamento Tem-Um sempre t6m acoplamento forte.

2. Dado:class Clidders {

public final void flipperO { System.out.println("Clidder"l; }

]

public class Clidlets extends Clidders {

public void flipperO {

System. out.println ( "Flip a Clidlet" ) ;

super. flipper O ;

]

public static void main(String [] args) {

new Clidlets O . flipper ( ) ;

]

]

Qual6 o resultado?

A Flip a ClidletB. rlip a ClidderC rfip a Clidder

Flip a ClidletD. 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) { }

Page 122: Java - Scjp 5 - Portugues

96 Copitulo 2: Orientogoo o obietos

4. Dado: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 baixoacoplamento. (Marque duas),4. Os atributos da classe sio todos privados.

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

C O objeto cont6m apenas um pequeno nrimero de vari6veis.

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

E. Avari6veldereferAncia6declaradaparaumtipodeinterface,enioumaclasse.Aintertacef.orneceumpequenonimerode m6todos.

F 14. t IE E 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?

,{. ClidletB. ClidderC clidder

ClidletD. Clidlet

ClidderE. AcompilaSofalha

Page 123: Java - Scjp 5 - Portugues

JAVA 5 97

7. Usando os fragmentos abaixo, complete o seguinte c6digo de forma que ele com-pile. ObseruagSo, talvez nio seja preciso preencher todos os espagos em branco.C6digo:

class AgedP {

public AgedP(int x) {

]

ipublic class Kinder extends AgedP {

public Kinder(int x) {

o;j

)

Fragmentos: Use cada um dos seguintes fragmentos quantas vezes for preciso, ou deixe sem uso:

AgedP this

( ) t

8. Dado:1. class Plant {

2. String getNameO { return "p1ant"; }

3. Plant getTlpeO { return this; }

4. )

5. cl-ass Fl-ower extends Plant i6. // insira o c6digo agui

8. class Tulip extends Flower { }

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

,{. Flower getTlpe| { return this; }

B. String getTlpeO { return "this"; }

C.Plant getTypeO { return this; }

D. tulip getTlpe0 { return new Tulip0; }

9. Dado:1. class Zing {

2. protected Hmpf h;

^ ^1 ^^^ rr'^^- --.f anr{c 7i nn I }+ t ufa-D vvuvP YJ---^-

E nl:cc umnf I )

Quais opg6es slo verdadeiras? (Marque todas as corretas)

A. Woop 6-umFlmpf etem-umZing.

B. zingr 6-umWoop etem-umHmpf.

C. Hmpf tem-umWoop eWoop 6-umZingr.

D. Woop tem-umFlmpf eWoop 6-umZing.

Page 124: Java - Scjp 5 - Portugues

98 Copiiulo 2: Orientog6o o obletos

E. zing tem-umFlmpf eZing 6-umWoop.

10. Dado:1. class Programmer {

2. Progranmer debugrO { return this; }

3. )

4. class SCJP extends Programmer {

5. // jtnsira o c6digo aqui

6. )

Qual op91o, inserida na linha 5, iri compilar? (Marque todas as corretas)

A. Programmer debug ( ) { return this,' }

B. SC.fP debugfo { return this; }

C.object debugr0 { return this; }

D. i-nt debug ( ) { return 1; }

E. int debug(int x) { return l-; }

F.Object debug(int x) { return this; }

I l. Dado:class Uber {staticinty=);Uber(int x) { thiso; y = y * 2; }

Ubero { y++; i)

class Minor extends Uber iMinor0 { super(y) ; y = y + 3; }

public static void main(String [] arqs) {

na\^t Mi nnr 1\ .

System. out.println (y) ;

])Qual6 o resultado?

4.68.7c.8D.9E. A compilagio falha.

F. SerS langada uma exceglo.

12. Quais afirmativas sao verdadeiras? (Marque todas as corretas)A A coesio 6 o principio da programagio OO mais intimamente associado com o ato de esconder os detalhes da

implementa$o.

B. A coesio 6 o principio da programagio OO mais intimamente associado com o ato de certificar-se de que as classes s6

conhecerlo outras classes atrav6s da" suas APIs.

C A coesXo 6 o principio daprogramaglo OO mais intimamente associado com o ato de certificar-se de que a classe foielaborada com um rinico e bem-focado prop6sito.

D. A coesio 6 o principio daprogramagio OO mais intimamente associado com o ato de se permitir que um mesmoobjeto seja visto como tendo muitos tipos.

Page 125: Java - Scjp 5 - Portugues

JAVA 5 99

13. Dado:1. class DoS { }

2. cl-ass Beagle extends DoS { }

3.

4. class Kennel {

5. public static void main(String [] arfs) {

6. Beagrle b1 = new Beagle ( ) ;

7. Dog dogl = new DogO;

8 . Dog dog2 = b1-;

9. // insira o c6digo aqui

10. ) )

Qual opgio, inserida na linha 9, ir6 compilar? (Marque todas as corretas)

A. Beagle b2 = (Beagle) dogl;B. Beagle b3 = (Beagle) dog2;

C. Beagle b4 = dog2;

D. Nenhuma das instrug6es acima irl compilar.

14. Dado o seguinte c6digo,l-. class X { void do1 O { } }

2. c]ass Y extends X { void do20 { } }

?

4. class Chrome {

5. public static void main(String [] args) {

6. X x1 = new XO;

7. X x2 = new yO;

8. Y yl = new YO;

9. // inslra o c6digo aqui

10. ) )

Qual opgXo, inserida na linha 9, ir6 compilar? (tr4arque todas as corretas)

A. x2.do2O;B. (Y) x2.do2O;C. ((Y)x2).do2O;D. Nenhuma das instrug6es acima ir6 compilar.

Respostas1 Best6correta.

A e D descrevem outros t6picos relativos ) programagXo OO. C est6 incorreta porque uma classe pode ter uma instAnciade 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 m6todotwiddle ( ) .

A esti incorreta porque m6todos abstract nlo t6m corpo.

Page 126: Java - Scjp 5 - Portugues

100 Copitulo 2: OrientoEdo o obietos

C estA incorreta porque as classes implementam interfaces, mas nio as estendem.

D est6 incorrera porque sobrecarregar um m6todo nio 6 o mesmo que o implementar. (Objetivo 5.4)

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 compiladorsomente se a classe nio tiver nenhum construtor definido explicitamente.

A, B, C e D estio incorretas com 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 acoplamentolimitado. Se o acesso 6 feito atrav6s de uma referAnia do tipo interface, pode-se argumentar que existem aindamenos oponunidades para o acoplamento , umavez que o pr6prio tipo da classe nio se encontra visivel. Dizerque modificag6es em uma parte de um programa provavelmente nio causario conseqiiOncia em outra, 6

realmente a ess€ncia do acoplamento fraco. Nlo existem variiveis an6nimas. Referir-se apenas a um pequenonrimero 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 devemnormalmente ser private, mas isso descreve o encapsulamento e nXo o baixo acoplamento. E claro que umbom encapsulamento tende a reduzir o acoplamento, como conseqii6ncia.

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

A esti correta. Embora um m6todo f inal nio possa ser sobrescritos, neste caso o m6todo 6 private, e,

portanto, escondido. O efeito 6 que um novo e acessivel m6todo f lipper 6 criado. Assim, nXo ocorrepolimorfismo neste exemplo; o m6todo chamado 6 simplesmente o da classe-child, e neo ocorre nenhum erro.

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

Como nio existe um tile descan6vel para avari|vel x e os par6nteses (no constnrtor Kinder) j6 estio no seu lugar e

estio vazios, nio 6 possivel criar uma chamada ao construtor da superclasse que usa um argumento. Poftanto, a

rinica possibilidade restante 6 criar uma chamada ao construtor sem argumentos da superclasse. Isso 6 feito assim:super ( ) ;. A linha nio pode ser deixada em branco, uma vez que os par6nteses j6 estio no lugar. Al6m disso, umavez que o construtor da superclasse chamado 6 a verslo sem argumentos, esse construtor precisa ser criado. Elenio seri criado pelo compilador porque jl existe um outro construtor. (Objetivo 5.4)

A, C e D estio corretas. A e D sloexemplosde retornos covariantes, ouseja, Flower e Tulip sio ambossubtipos de Plant.

B est6 incorreta, String nlo 6 um subtipo de Plant. (Objetivo 1.5)

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

A, B, C e E estlo incorretas com base no exposto acima. (Objetivo 5.5)

l0.A,B,EeFestiocorretas.AeBsioexemplosdesobrescrigXo;especificamente,B6umexemplodesobrescrigio usando-se um retorno covariante. E e F sio exemplos de sobrecarga.

C e D estio incorretas. Sio de sobrescrigio inv6lidas, porque os seus tipos de retorno sio incompativeis. E siosobrecargas invilidas porque os seus argumentos nio se modificaram. (Objetivo 5.4)

lL Dest6correta.OconstnrtordeMinorfazumacharnadaoplicitaaoconstrutorcomumargunentodelJber,quefazumadramadaenplicia(trLis) aoconstrutorsemargumentosdeubeqqueporsuavezincrementayedepoisretomaparaoconstrutorcomumargurnentqoq'.ulmuhiplicay'r2edepoisretomaparaoconstrutordeMinor,queadicioru3 ay.

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

12. A resposta C est6correta.

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

13. A e B estio corretas. Entretanto, no tempo de execugio, A langari uma ClasscastException porque doglrefere-se a um objeto Dog, o qual nio necessariamente s ericapaz de realtzar tarefx deBeagle.

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

14. C est6 correta. Para poder chamar o m6todo do2 de v, voc6 precisa converter x2 para que ele se torne do tipo Y. Ainstrugio B parece ser uma conversio correta, mas, sem o segundo conjunto de pardnteses, o compiladorpensari que setrata de uma instrugXo incompleta.

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

4.

5.

6.

Page 127: Java - Scjp 5 - Portugues

AtribuiE6es

Obiefivos pqrq qcertificqe6o

I Usor Membros de Closses

I Desenvolver C6digos Wropper e deAutoboxing

I Determinor os Efeitos de se PossorVqri6veis o M6todos

r Reconhecer Quondo os Obietos se

Tornom Quolificodos ooro o Coletode Lixo

I Argumentos de linho de comondoporo o m6todo Moin

t Exerc(cios r6pidos

P&R Teste individuol

Page 128: Java - Scjp 5 - Portugues

102 Copftulo 3: AtribuiE6es

Pilha e Heap - Uma RevisioPara a maioria das pessoas, entender os fundamentos sobre a pilha e o heap facilita bastante a comPreensio de t6picos

como a passage* d. "rg.r*.ntos,

o polimorfismo, threads, exceg6es e coleta de lixo. Nesta segio, nos limitaremos a uma

visio geral, mas expan&remos esseJt6picos virias vezes ao longo do livro.

No gerd, as virias partes (m6todos, variiveis e 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,

vari6veis locais e objetos:

I As vari6veis de instAncias e os objetos residem no heap.

r Asvarilveislocaisresidem napilha.

Vejamos um programa emJava, e como os seus diversos pedagos sio criados e mapeados na pilha e no heap:

l-. class Collar { l

2.

3. class Dog {

4. Co11ar c; // vari6vel de

5. String name; / / vari6vel- de

6.

7. public static void main(String

B.

9. Dog d;

l-0. d = new DogO;

i-1. d.so(d);1.2. ]

13. void go(Dog dog) { // vari6veLL4. c=newCollaro;1-5 . dog. setName ( "Fido" ) ;16. )

I7. void setName(String dogName) {

18. name = dogName;

19. / / faz mais coisas

20. )

21.. j

Local: dog

/ / variSvel local: dogrName

A Figura 3-1 mostra o estado da pilha e do heap depois que o programa atinge a linha 19. Em seguida, apresentamos

alguns pontos principais:

instAnciainstAncia

[] arss) {

/ / vari1vel 1oca1: d

objeto String

Vari6veis deinstAncias- name

pbleto co11ar

setName O dogName

go O dog

main ( )

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

Page 129: Java - Scjp 5 - Portugues

JAVA 5 IO3

I LinhaT-main ( ) 6colocadonapilha.

r Linha 9 - a variivel de referAncia d 6 criada na pilha, mas ainda nio existe um objeto Dog.

r Linha 10 - um novo objeto oog 6 criado, e 6 atribuido i variivel de referAncia d.

I Linha 1 1 - uma c6pia & vari6vel de referAncia d 6 passada para o m6todo go ( ) .

r Linha 13 - o m6todo go ( ) 6 colocado na pilha, com o parimetro dog como umavariivel local.

r Linha 14 - um novo objeto co11ar 6 criado no heap, e atribuido ) vari6vel de instAncia de Dog.

r Linha17-setName() 6adicionadoipilha,comoparAmetrodogName comoasuavari6vellocal.

r Linha 18 - a variivel de instincia name agora tamb6m se re{ere ao objero String.I Repare que duas vari6veis locais difermtesreferem-se ao mesmo objeto oo9r.

I Repare que uma vari6vel local e uma variivel de instAncia referem-se ambas ) mesma String aiko.I Depois que a Linha 19 fnal:.aa, setName ( ) termina e 6 removido da pilha. Nesse ponto, avari6vel local dogNametamb6m desaparece, embora o objeto String ao qual ela se referia ainda esteja no heap.

Obietivo poro o certificog6o

Literais, Atribuig6es e Variiveis (Objetivos 1.3 e 7.6 do Exame)| .3 Desenuo/uer aldigo que dukre, inicialiry e use primitiuos, affaJg enums e objetos romo aaiiaeis static, de in$1ncias e locais. Ahm disn,asar identifeadores udlidos para nonet de uariiueis.

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

Valores literais de todos os tipos primitivos

Um literal primitivo 6 simplesmente a representagio do c6digo-fonte dos tipos de dados primitivos - em outras palavras,um inteiro, umnrlmero de ponto flutuante, umbooleano oucaractere quevoc0 digite enquanto escreveumc6digo. Aseguir, temos exemplos de literais primitivos:

-b' // char literal42 // inE literalfalse // booTean literal2546789.343 // double literal

Literais inteirosHi tr6s maneiras de representar nrimeros inteiros na linguagemJava: decimal (base 10), octal (base 8) e hexadecimal (base

16). A maioria das perguntas do exame que envolve literais inteiros usa representag6es decimais, mas vale a pena estudarpara 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 apenaspordversao.

Literais decimais Os inteiros decimais nio precisam de explicagio; voc6 os tem empregado desde a primeira s6rie escolarou at6 antes disso. Hi chances de que os esteja usando, j6 que voc6 nio preenche seus cheques em notagio hexadecimal. (Se

exiuerfaqgndoisso, nlo se preocupe, h6 um grupo de Nerds An6nimos (NA) pronto para ajudar). Na linguagemJavao elessio representados da maneira tradicional, sem prefixo de nenhum tipo, como descrito a seguir:

int length = 343;

Literais octais Os inteiros octais usam somente digitos de 0 a7 .Emlava, o inteiro 6 representado na forma octal com ainclusio de um zero na frente do nrimero. como vemos abaixo:

class Octal {

public static void main(String [] args) t

int six = 06i // Igual ao 6 decimalint seven = 07; / / Igual ao 7 decimal

int eight = 010; // IguaI ao 8 decimal

int nine = 011; / / Igual- ao 9 decimal

Page 130: Java - Scjp 5 - Portugues

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 nosnrimeros octaii), voltamos ao ponto de partida,ewznro 6, adicionado ao inicio do nrimero. Voc6 pode ter at62t digitosem um n6mero oaal, nio incluindo o zero inicial. Se executarmos o programa anterior, ele exibiri o seguinte:

Octal 010 = 8

Literais hexadecimais Os nrimeros hexadecim is (hexnaabreviatura) slo construidos com o uso de 16 simbolosdistintos. J6 que nunca foram inventados simbolos num6ricos unit6rios para os algarismos que vlo de 10 a L5, usamos

caracteres alfab6ticos para representar esses digitos. A contagem de 0 a 15 na representagio hexadecimal ficaria assim:

0L23456'789abcdefA 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 prefixoOxou 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. 'TantoOXCAFE quanto 0xcafe siov6lidos.

Todos esses literais inteiros (octal, decimal e hexadecimal) sio definidos como int por padrXo, mas tamb6m podem ser

especificados como long com a inclusio de um sufixo L ou 1 depois do nrimero:

long jo = 110599L;

long so = 0xFFFFI; // Observe a letra '1' minriscula

Literais de ponto flutuanteOs nrimeros de ponto flutuante slo definidos com um nimero, um simbolo decimal e os outros n{meros querepresentam afra$o.

double d = 11301-874.9881-024:

No exemplo anterior, o nime ro I1,3QI87 4.9881024 6 o valor literal. Os literais de ponto flutuante sio definidos comodouble (64 bits) por p adrio, ponanto, se vocA quiser atribuir um literal de ponto flutuante a.umavariSvel do tipof loat (32 bits), tenl que anexar o sufixo F ou f ao nimero. Se nio o fizer, o compilador reclamar6 de uma possivelfalta de precisio, porque voc6 estari tentando inserir o nrtmero em um "contAiner" (potencialmente) menos preciso. Osufixo F fornece uma maneira de voc6 informar ao compilador: "Ei, sei o que estou fazendo e correrei o risco, muitoobrigado".

float f = 23.467890; // zrro de compilador, possivel perda da precisdoffoat 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 ocompoftamentopadrio.

double d = 110599.995011D; // opcional, n5o 6 obrigat6riodouble 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

Page 131: Java - Scjp 5 - Portugues

JAVA5 IO5

Literais booleanosOs literais booleanos sio a representaglo do c6digo-fonte para valores boolean. Um valor boolean s6 pode serdefinido como true ou f alse. Embora em C (e algumas outras linguagens) seja comum o uso de nrimeros pararePresentart.rue oufalse,isondofuncionaniemJaua.Novamente,repitacomigo,Javanio6C++".

boolean t = true; // V6l-ido

bool-ean f = 0; // Erro do compilador!

Procure perguntas que usem nrimeros onde os booleanos seriam obrigat6rios. Voc6pode veruma avaliagio deinstrugio i f que use um nimero, como na linha a seguir:

int x = 1; if (x) { } // Erro do compilador!

Literais de caracteresO 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 podeatribuir 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; //literalhexadecimalchar b -- 982; // literal inteirochar c = (char) 70000; // A conversS.o 6 necess6ria; 70000 est6 fora do intervalo charchar d = (char) -98; // Absurdo, mas v61ido

E as descritas abaixo nlo sio vilidas e produzirlo erros de compilador:

char e = -29; // Possivel perda de precisSo; precisa de uma conversSo

char f = 70000 // Possivel perda de precisSo; precisa de uma conversSo

VocA tamb6m pode usar um c6digo de escape se quiser representar um caractere que nio possa ser digitado como um literal,incluindo os caracteres de alimentaglo de linha, nova linha, tabulagio horizontal, backspace e aspas simples e duplas.

char c = '\"'; // Aspas duplas

char d = '\n'; // Nova linhaAgora que voc6 est6 familiarizado com os tipos de dados primitivos e seus intervalos, precisa ser capaz de identificar o tipode dado apropriado a ser usado em uma situagio especifica. A seguir serio apresentados alguns exemplos de quantidadesno mundo real. Tente selecionar o tipo primitivo que melhor represente a quantidade.

Valores literais para stringsUm literal de strng| arepresentagio do c6digo-fonte para o valor de um objeto String. Por exemplo, abaixo vemos umexemplo com duas maneiras de representar um literal de string:

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 oarray, que examinaremos mais adiante neste capinrlo.

Thread t = ??? / / qtal vafor literal poderia ir aquil

Operadores de atribuigioAtribuir um valor a uma variivel parece bem simples; simplesmente insira o valor i direita do s tnd, : para atribuilo )variivel que estar6 i esquerda. Bem, certo, mas nio espere ser avaliado com algo do tipo:

x=6;NXo, voc6 nio ser6 avaliado com atribuig6e s que selarnfchinha (termo t6cnico). No entanto, ser6 avaliado em atribuig5esmais ambiguas que envolvam conversio e express6es complexas. Examinaremos atribuig6es primitivas e de vari6veis de

Page 132: Java - Scjp 5 - Portugues

106 Copftulo 3: AtribuiE6es

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

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

O mais imponante a lembrar 6 que um inteiro literal (como 7) 6 sempre implicitamente um tipo int. Se voltarmos aoCapitulol,vocAlembrar6queotipoint 6umvalorde32bits.Niohaveriproblemasevoceestiveratribuindoumvalora uma vari6vel int. ou long, mas, e se estiver arribuindo a uma variivel uyte? Afinal, um dep6sito do tamanho dotipo fote nlo pode armazenar tantos bits quanto um dep6sito com o tamanho do tipo int. Aqui, as coisas comegam a

ficar estranhas. O c6digo a seguir 6 v6lido,

byLe b = 27;

mas somente porque o compilador compafiaautomaticanenrao valor literal para o tamanho de um tipo byte. Em outraspalavras, o compilador executa a conuersdo. O c6digo anterior 6 id6ntico ao seguinte:

k,,F^ h - /L,-r^\ 'vrus ! - \!rus/ 27; // Converte explicitamente o valor literal inteiro para um tipo byte

Parece que o compiladorlhe deuumachance e permitiu quevod tomasse um atdho com atribuig6es avari6veis inteirasmenorel que um tipo int. (fudo que estamos dizendo sobre o tipo byte se aplica igualmente a char e short, jique os dois sio menores do que um tipo int). A prop6sito, ainda nio entramos realmente na parte estranha.

Sabemos que um inteiro literal 6 sempre um tipo int, mas o que 6 mais importante 6 que o resultado de uma expresseo

que envolva qualquer item do tamanho de um tipo int, ou menor, ser6 sempre um tipo int. Em outras palavras, some

dois tipos byce e vocd ter6 um tipo int - mesmo se esses tipos byte forem muito pequenos. Multiplique um tipoint por um short e ter6 um tipo int. Divida um tipo short por um byte e ter6... Um tipo int. Certo, agorachegamos )pane estranha. Veja isto:

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

um bytebyte c = B;

byted=b+ct/ / Sem problemas, 8 cabe em

/ / xeo deveria ter problemas, a soma dos dols bytes

/ / cabe em um tipo de byte

referAncia. Mas antes de comegarmos, retomaremos um pouco para examinar uma variAvel por dentro. O que i umavariivel? 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 bitsp"r" o tipo noolean, mas nlo achamos isso importante). Um tip o futte devalor igual a 6, por exemplo, significa que opadrXo de bits davariivel (o dep6sito de tipos @t) 6 igual a 000001.1.0, representando os 8 bits.

Portanro, o valor de um avariLvelprinitiw6 evidente, mas o que estaria dentro de um dep6sito de objea? Sevoc|escrever:

Buttonb=newButtono;o que estar6 dentro do dep6sitg Bgaon blseria,o.objeto Button? N;o/Uma vari6vel referenciando um objeto seria

exaramenre rs so - ono ,oidatl de refeftncia. O dep6sito de bits de uma vari6vel de refer6ncia cont6m bits que representamuma 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.ggQeaitoecifuo danentiria. Ou ovalornull. Se umvalor nio tiversido atribuido avariivel de referAncia ou tiver sido atribuidoexpiicitamente um valor nu11, a vari6vel armazenarL bits que representario - voc6 adivinhou - o valor nul1. VocA pode

hButton 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 terminaremoscom as atribuig6es avari6veis de refer6ncia.

Atribuig6es primitivasO sinal de igualdade ( = ) 6 usado para a atribuSno de umvalor a uma variivel e foi chamado adequadament e de Eeradar dz

atribuigdo.Naverdade, h6 12 operadores de atribuigio, mas apenas os cinco mais freqiientemente usados caem no exame, e

eles serio abordados no Capitulo 4.

Vodpode atribuirumavarilvel primitivausando umvalorliteral ou o resultado deumaexpressio. Examine o c6digo asegur:

Aultimalinha nio seri compilada!Voc6 veri o erro aseguir:

Page 133: Java - Scjp 5 - Portugues

JAVA5 IO7

TestBytes.java:5: possible loss of precisionfound : intramli 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 caberem 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 primitivosA nnuersdopermitirl que vocA transforme valor-es primitivos de um tipo em outro. Examinamos a converslo de tiposprimitivos anteriormente neste capinrlo, na seglo de atribuig6es, mas agora, a discutiremos com mais detalhes. A conversiode objetos foi abordada no Capitulo 2.

As convers6es podemser implicitar ou explicitat.Uma conuersdo inpliatasignifica que.voc6 nio precisa escrever um c6digo paraelE a conversao ocorTera automatrcamente. I\onnalmente, unVI conversao lmplrclta ocorre quancto lazemos umatransformagio que envolva anpl)agno.Em outras palavras, quando inserimos'um item menor (digamos, um tipo byte) emumcontein-ermaior(comoumtipoint).Lembradaqueleserrosdecompilador"possintiloss of freci-'sion" que vimos na secio de atribuiE6es? Eles ocorrem quando tentamos inserir um item maior (digamos, um tipolong) emumcont6ineimenor (comoumtipo sho.rt). Atransformaglo "valormaioremumcontdinermenor"6conhecida como compactaglo e requer uma c onversio.explhita,em que voc6 esari informando ao compilador que conhece operigo e aceita toda a r?:sponsabilidade. primeiro, exarunaremos uma conversio implicita:

int a = 100;

long b = a; / / Conversdo implicita, um valor int sempre cabe em um long(Jma conversio explicitatem o formato a seguir:

float a = 100.001f;

int b = (int)a; // ConversSo explicita, um tipo de float pode perder informag6es comoum tipo de j-nt

Os valores inteiros podem ser atribuidos a uma variivel double sem a conversio explicita, porque qualquer valor inteiropode ser inserido ein um tipo double de 64 bits. A linha a seguir demonstra isso:

double d = 100L; // ConversSo implfcitaNa instrucio anterior. um tiDo double 6 inicializado com um valor do dpo lonq (como indicado pelo L depois dovalor num6rico). Nenhuma ionversio 6 necessiria nesse caso porque um tipo dgu5le po{e ar.mqzenir todas aiinformag6es que um tipo l ong poderia conter. Se, no entanio, q-uisermos atribuir um valor do tipo doubl e a um tiporntefo, estafemos tentancto uma conversao Por compactagao e o comPilactor sabera drsso:

^1 ^^^ ^-^Ll-^ rUIdDD LqDLTITIJ \

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.javaCasting.java:3: Incompatible tlpe for declaration. Explicit castneeded to convert doub]e to int.

int x = 3957.229; // nd.o 6 v51ido

1 errorNo c6digo anterior, um valor de ponto flutuante este sendo atribuido a uma vari6vel inteira. Ji que um inteiro nioconsegri armazer,tar casas decimais, um erro ocorrer6. Para fazer isso ftmcionar, converterem6s o ndmero de pontoilutuante emum lntero:

class Casting ipublic static voj-d main(String [] args) {

int x = (int)3957.229; // conversSo v5lidaSystem.out.println("int x = " + x);

Page 134: Java - Scjp 5 - Portugues

108 Copftulo 3: AtribuiE6es

)

Quando voc6 converter um nrimero de ponto flutuante em um tipo inteiro, o valor perder6 todos os digitos depois do- I ' r ^ r r I r. a 1 . , ,l

POntO decmal. A execugao do coctrgo antenor proctuara a sarch a seguf:

Bjava Castingint x = 3957

Tamb6m podemos converter um tipo de nrimero maior, como long, em um menor, como b1te. Observe o c6digo abaixo:

nla<c l-acfina I

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

long 1 = 56L;

byte b = (byte)1;

System.out.println("The byte is " + b);

)

O c6digo anterior seri compilado e executado adequadamente. Mas, o que aconteceria se o valor long fosse muor que t27(o maior nrimero que um byte pode armazenar)? Alteremos o c6digo para descobrir:

ala<c l-acf ira I

public static void main(String [] args) {

long 1 = 130L;

byte b = (byte)1;

System.out.println("The byte is " + b);

]

O c6digo ser6 compilado adequadamente, e quando o executarmos, obteremos o resultado a seguir:

O; --.- ^-^r l --tJovd ud>Lf119

The byte is -126

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

Exercicio 3- |

Convertendo tipos primitivos

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

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

2.Atribuaotipo float aumtiposhort: short s = (short) f;Atribuindo nirmeros de ponto flutuante Os nrimeros de ponto flutuante apresentam um compoftamento de

atribuigio um pouco diferente dos tipos inteiros. Primeiro, voc€ precisa saber que todo lberal depontoflutuante d

implicitanenteantipodouble @abit)endoantipofloat.Portanto,oliteral 2.3,porexemplo,6consideradoumtipodouble. Se voc6 tentar atribuir um double a um f loat, o compilador saberi que nio h6 espago suficiente nocont6iner do tipo float de 32 bits paraarmaenar aprecisXo do tipo double de 64 bits, e ele lhe informarl isso. Oc6digo 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 ocompilador nio permitir6 isso. Para atribuir um literal de ponto flwuante a uma variivel f 1oat, voc6 precisa converter ovalor 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:

Page 135: Java - Scjp 5 - Portugues

JAVAs 109

Atribuindo um literal que seia muito grende para avariivel Tamb6m veremos um erro do compilador se renrarmosatribuir um valor literal que ele saiba que E muito grande para caber em uma va/riryel.

byte a = 1,28; // byte s6 pode armazenar at6 o nirmero \27

O c6digo anterior renrltard nesse effo:

llact- R\rl- aq i:rr: . q. h^6ri 1-.1 ^ l aa- ^f. f : possroJ_e -Loss or preclsaon

Found : intrequired: 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 deordem superior que nio se enquadrarem. Em outras palavras, ele perder6todos os bits ) esquerda dos que voce estiverconveftenoo.

Examinemos o que aconteceri no c6digo anterior. Nele, 128 6 o pa&io de bits 10000000. Esse pa&io usa exatamente 8

bits para representar o nfmero 128. Mas j6 que o literaJ,I2S 6umtipo int, na verdade, obteremos 32 bits, estando onrimero 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 esquerdarepresenta esse sinal (e nio pane do valor da vari6vel). Ponanto, terminamos com um ntimero negativo (o nrimero 1 queusamos para representar llS,agorarrepresentao bit do sinal negativo). Nio se esquega: para descobrir ovalor de umnrimero negativo usando a notagio biniria complementar, inverta todos os bits e, em seguida, adicione 1. Ao inverter osoito zeros ficaremos com 011111 1 1 e adicionando L a esse resultado obteremos 10000000 ou novamente 128! E quandoaplicarmos 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. Umaconverseo nada mais 6 do que sua maneira de dizer ao compilador, "Confie em mim. Sou um profissional. Assumo totalresponsabilidade por qualquer coisa estranha que possa vir a ocorrer quando esses bits superiores forem eliminados".

Isso nos leva aos operadores compostos de atribuigXo. O c6digo a seguir seri compilado,

byte b = 3;

e equivalente a:

byte b = 3;

b = (byte) (b + '1 l;

// Sem problemas - adiciona 7 a b (o resultado 6 10)

/ / 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. Naverdade, * =, - : r'r : e / : usario todos uma conversio implicita.

Atribuindo uma vari6vel primitiva a outra vari6vel primitiva Quando voc6 atribuir uma vari6vel primitiva aoutra, 0conteildo da aari,iuel da direita seni copiado, por exemplo,

int a = 6;

intb=a;O c6digo anterior pode ser lido como: "Atribui o padrio de bits do ntmero 6 I variivel int a. Em seguida, copia opadrio de bits de a e insere a c6pia na variivel b.

Portanto, as duas vari6veis, agora, contem o padrio de bits do nrimero 6, mas nio apresentam outro relacionamento.IJsamos a vari6vel , somente para copiar seu conterido. Nesse momento, as duas vari6veis possuem conteridos id6nticos(emoutraspalavras,uakresid€nticos),massealterarmososconteidosdea oub,aoutravari6velnloser6afetada".

Examine o exemplo abaixo:

class Val-ueTest {

public static void main (String ll args) {

int a = 1-0; // Atribui-se um valor a a

Page 136: Java - Scjp 5 - Portugues

I l0 Copfiulo 3: Atribuig6es

System.out.println("a = " + a);intb=a;

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

)

A saida desse programa serA:

tjava ValueTest

a=10a = 1-0 after change to b

Observe que o valor de a permaneceu igual a 10. O ponto chave a lembrar 6 que mesmo depois que voc6 atribuir a a b, as

duas variiveis nio referenciario o mesmo local da mem6ria. As vari6veis a e b nio companilham apenas um valor; elas

t|m aipiasid|nricas.

Atribuig6es de vari6veis de refer6nciaVocO pode atributum objeto rec6m-criado aumavariivel de refer€ncia de objeto da maneira abaixo:

Button b = new Button0;A linha anterior executa tr6s operag6es essenciais:

I Cria uma vari6vel de refer6ncia chamada b, do tipo Button.

I Criaumnovo obieto Button namem6ria.

r Atribui o objeto zutcon rec6mcriado ) vaiivelde referlnciab

Voc6 tamb6m pode atribuir o valor nul1 a uma vari6vel de refer€ncia de objeto, o que significa simplesmente que avari6vel nio referenciar6 nenhum obieto:

Button c = null;A linha anterior cria um espago para a vari 6vel de rcfer1neiaButton (o dep6sito de bits para um valor de refer6ncia) , mas niogera realmente um objeto Buuon.

Como discutimos no Capinrlo anterior, voc6 tamb6m pode usar uma vari6vel de referdncia para referenciar qualquer objetoque seja uma zubclasse do tipo declarado para a vari6vel, como descrito a seguir:

public class Foo {

nrrlrlin rzniA AnFnncfrrff /\ Ivglrfv vveLBLL\/ r

)

ipublj-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 queum objeto Bar , com cfrtez4pode fazer o mesmo que Foo, portanto, qualquer pessoa que tiver uma refer6ncia a Foo poder6chamar m6todos Foo, mesmo se o objeto na verdade for um objeto Bar.

No c6digo anterior, vimos que Foo possui um m6todo doFooStuf f ( ) , que algu6m com uma refer6ncia a essa classe

poder6 tentar chamar. Se o objeto referenciado pela variivel Foo for realmente um objeto Foo, nXo haverl problemas. Mastamb6mniohaver6problemasseeleforumobjetoBar,jiqueBarherdouom6tododoFooStuff ( ).Voc6niopode

Page 137: Java - Scjp 5 - Portugues

Escopo Vari6velDepois 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 demodo geral, mas ele tamb6m tem um papel imponante no exame. Comecemos examinando um arquivo de classe:

fazer isso funcionar de maneira inversa, no entanto. Se algu6m tiverdoBarStuf f ( ) , mas se o objeto referenciado na verdade for um

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

JAVA 5 'I1I

uma refer6ncia aBar, poderi chamarobjeto Foo, ele nio saber6 como responder.

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 as vari6veis em todos os programas Java, as deste programa (s, x, x2, x3, y e z) t6m todas umescoPo:

I s 6 umavariivelstatic.I x 6umavariiveldeinstAncia.

I y 6 uma vari6vel local Qs vezes chamada de vari6vel "local de m6todo").

I z E.umavariiveldebloco.

I x2 |umavarilvel de bloco init, um tipo de variivel local.

I x3 6 uma variivel de construror, um tipo de vari6vel local.

Para o prop6sito de explicagio do escopo das vari6veis, podemos dizer que existem quatro escopos bisicos:

I Asvari6veisstatic t6moescopomaislongo;elassiocriadasquandoaclasse6carregada,eduramportodootempo em que a classe permanecer carregada naJVM.

r As vari6veis de instAncia sio o segundo tipo mais longevo; elas sio criadas quando uma nova instAncia 6criada, e existem at6 que a instAncia seja removida.

I As vari6veis locais v0m em seguida; elas existem durante todo o tempo em que o seu m6todo permanecer na pilha.Como veremos em breve, no entanto, as variiveis locais podem estar vivas e ainda assim estar "fora de escopo".

I As vari6veis de bloco s6 existem durante o tempo em que o bloco de c6digo esti sendo executado.

Os erros de escopo t6m muitos tamanhos e formas. IJm engano comum acontece quando umavarihvel| sonbreadaedoisescopos interferem um com o outro. Veremos o sombreamento com detalhes daqui a dgumas p6ginas. A razio maiscomum Para acontecerem erros de escopo 6 quando vod tenta acessarumavariivel que nio est6no escopo. Vejamos tr6sexemplos comuns desse tipo de erro:

r Tentaracessarumavari6veldeinstAnciaapartirdeumcontexto static (normalmenteapartirdemain ( ) ).class ScopeErrors {

i-nt x = 5;

public static void main(Stringll args) 1

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

]

I Tentar acessar uma vari6vel local a partir de um m6todo aninhado.

Quando um m6todo, por exemplo go ( ) , chama outro m6todo, por exemplo so2 O, 9o2 ( ) nio ter6 acesso isvari6veis locais de go ( ) . Enquanto so2 ( ) esr6 rodando, as vari6veis locaii de go O ainda estXo atiuar, mas estio foradeescopo.Quando go2O f:urralua'.6removido&pilhaego () continuaasuaexecugio.Nesseponto,todasasvarilveis

Page 138: Java - Scjp 5 - Portugues

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 ScopeErrorsOis.go();

)

rrniA an/\ Iwvls Yv \ / L

int Y = 5'

902();

Y++ i

]

vvrv vv! \, L

y++;

)

// depois que go2O finaliza, y volta ao escopo

t/ ^<^ ^^-^il- ,,;'lnaal : nn/\/ / Ltav LUrttIJf Jqr y E rvuqt q vv \ /

]

I Tentar usar uma vari6vel de bloco depois que o bloco de c6digo jA terminou de executar.

E bastaote co-n- declarar e usar uma variivel dentro de um bloco de c6digo, mas cuidado para neo tentar usar a vari6veldepois que o bloco finalizou:

void so3 O {

for(int z=0; z<5; z++l {

boolean test = false;if(z == 3) {

test = true;break;

]

)

System. out.print (test ) ;

]

// 'test' 6 uma ex-vari6vel,t | ^1 ^ -=^ ^-.1 ^ts^ -,ila]-s. . .

Nos dois ultimos exemplos, o compilador dir6 algo como:

cannot find symbol

Essa 6 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 o E)GME

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

Usando uma vari6vel ou elemento de array que neo tenha sidoinicializado e atribuido

A linguagemJavanos fornece aop$o de inicializarumavari6veldeclarada oudeix6-lasem serinicializa<la. Quandotentarmosusmalaiive[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 oucon$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.

Page 139: Java - Scjp 5 - Portugues

JAVA5 I13

Variiveis de instincia de tipo primitivo e de objetoAs umidueis de instdncia (tarnb|mchamadas de vari6veis membros) sio vari6veis definidas no nivel da classe. Isso significa quea declaragio da variivel rrio 6feita dentro de um m6todo, construtor ou qualquer outro bloco incializador. As vari-6veis deinstAncia sio incializadas com um valor padrio sempre que uma nova instAniia 6 criada, embora possam receber um valorexplicito depois de os superconstrutorei do objeto ierem fin ahzado o seu trabalho. A Tabela 3-i lista os valores padrio paraos tipos primitivo e de objeto.

Vari6veis de instincia primitivasNo exemplo a seguir, ointeiro year 6 definido como um membro da classe, pois esti dentro das chaves iniciais dessaclasse e nio nas chaves de um m6todo:

public class BirthDate {

int year,' / / Yari6vel de instdnciapublic 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 primitivasrelacionadas a nfmeros.

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

Tipo de variivel Valorpadrio

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

byte, short, int, long

float, double 0.0

boolean €-f ^^!4Abe

char '\u0000'

AOTRABALHO

Voc6 deue inicialiqar todas as suat uariiueis, nesnl se estiuer atribaindo a elas o ualor padrdo. Sea cr6digo fcanl nais fricit de ser lido; ospmgramadores qtre precisarem faryr a manutengdo en sea aidigo (dEois qae uoc6 ganbar na loteria e mudar para o Taiti) fcardo gratos.

Vari6veis de instincia de refer6ncia a obietosQuando comparadas com as vari6veis primitivas nio inicializadas,uvari|veis de referdncia de obieto nio inicializadasrepresentam uma hist6ria completamente diferente. Examinemos o c6digo abaixo:

public class Book {

private String title; / / vari6,ve1 de referGncia de instAncianrrtrl ic (t-rina nal-rFit- l6/\ IYsurf urs \ / I

return t.it1e;1

public static void main(String [] args) {

Book b = new Booko;System.out.println("The title is .. + b.getTitleO );

]

Page 140: Java - Scjp 5 - Portugues

I I4 Copitulo 3: AtribuiE6es

Esse c6digo seri compilado adequadamente. Quando o executarmos, o resultado seri:

The title is nu1l

A variivel title nio foi explicitamente inicializada com a atribuigio de uma string, portanto, o valor da

variivel de instAncia ser6 nuII. Lembre-se de que nu11 nio 6 o mesmo que uma stringvazia (""). IJm valornu1l significa que a variivel de referdncia nao foi atribuida a nenhum objeto da pilha. Sendo assim, a alteragioabaixo no c6digo da classe Book apresentari problemast

public class Book {

private String title; / /public String getTitle ( )

ratrrrn |. if16.

]

J

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

Exception in thread "main" java. lang.NullPointerExceptionat 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 {

public static void main(StringBookb=neweook0;String s = b.getTitle0; //String t = s.tolowercaseO;

)

private String title, / /public String getTitle( )

r6t-11rh t i t- l a '

)

vari6vel de refer6ncia de instAncia

{

[] args) {

Ser6 compilado e executado

// Exceqdo de tempo de execuqSol

vari6vel de refer6ncia de instAncia

{

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 valornul-1. No c6digo anterior, por exemplo, examinamos a declaraglo da variivel de instAncia title, vimos que niohouve 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 arrayO 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 siovariiveis de instAncia. Conclusio: Os elementos do analt receberio iemPre sempre nnpre uakret padrdo, independente de onde o

pnlpio aral for dularado oa in$anciado.

Quando inicializarmos um array, os elementos de refer6ncia ao objeto serio iguais a nuI1, se nio foreminicializados 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:

Page 141: Java - Scjp 5 - Portugues

JAVA5 I15

public class BirthDays istatic int [] year = new int[100];public static void main(String [] args)

f or ( int i.=0; j-<l-00 ; i++ )

Syst.em.out.println("year[" + i + "] = + rrarrIi]\.' Jve+ L1J

' I

)

)

Quando o c6digo anterior for executado, a saida indicari que todos os 100 inteiros do array sio iguais azero.

Tipos primitiyos e obietos locais (de pilha, autom6ticos)As vari6veis locais sio definidas dentro de um m6todo, o que tamb6m inclui os parAmetros desse m6todo.

OBSERVAQ6ES pene O EJGME

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

Tipos primitivos locaisNo simulador de viagem no tempo a seguir, o inteiro year 6 definido como uma vari6vel autom6tica, porque esr6 dentrodas chaves de um m6todo.

public class TimeTravel {

public static void maj-n(String [] args) tint 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 nXonecessariamentenamesmalinhadec6digo).AlinguagemJavaniofome,aalsvariiveislocais,umvalorpadrio; wcdtenlqueinfuiali4i-las explicianntecom um valor, como no exemplo anterior. Se tentar usar um tipo primitivo nlo inicializado emseu 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- errorPara corrigir seu c6digo, precisamos fornecer um valor para o inteiro year. Neste exemplo atualizado, ele foi declarado emuma linha separada, o que 6 perfeitamente vilido:

public class TimeTravel {

public static void main(String [] arqs) {

int year; / / DecLarada, mas n5o inicializadaint 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)

Page 142: Java - Scjp 5 - Portugues

1 16 Copitulo 3: AtribuiE6es

System.out.print.ln("Welcome to the year " + year);

]

Observe no exemplo anterior que declaramos um inteiro chamado day que nio 6 inicializado e mesmo assim oc6digo foi compilado e executaao adequadam.nt.. E v6lido declarar uma variivel local sern inicializ|-la, contantoque ela nlo seja usada, mas convenhamos, se voc6 a declarou, provavelmente tinha umarazaa para isso. (Emboratenhamos ouvido falar de programadores que declaram variiveis locais aleatoriamente s6 por diversio, para ver se

elas conseguem descobrir como e porque estio sendo usadas).

AO TRABALHO

O compilador ndo podeni irforrnar sempre se uma uaiduel localfoi inidaliqada antes do uto. Por exempl0, n uoci inicialiqti-la dentro de um

bloco condicional ldgico (en outras palauras, am bloco de aidtgo que pode ndo ser executado, como o bloco de uma instrugdo if , ou }oopf or rcm un ualor literal true ou f a l- s e como altematiua), o conpi/ador saberd que a inicialiTgjdo talueq nio ocorra e podeni produ{rum 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]

x ='J;

)

inf ar -

v'LLLv t - ^t

J

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

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

Por causa do problena do conpilador ndo poder infomar com cerieqa, em algamat situagdes uoci ter,i que inicialiTar saa uaiduelfora do bloco

condiriona/, cpenat para deixar o conpilador satisfeito, Voci sabe porque isso d importante seji uiu o adesiuo de pdra-cboqae: "puando o

compilador n1o eshi mtisfeito, ninguin ufli".

Refer6ncias de Objetos locaisTamb6m 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 arefer6ncianio 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. ReferAnciasdeclaradas localmente n5o poderio apresentar bons resultados quando um valor nullfor procurado antes do uso, a menosquevoc6 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.

l= nu11l { //suponhamos que voc) soubesse que este resuitado seja<amore Erue

/ / o compilador ndo poderd informar se esta instrugdo ser1. executada

// o compilador ter5 problemas agui

1 errorrf (date == nu11)

Page 143: Java - Scjp 5 - Portugues

JAVA 5 117

As refer6ncias de vari6veis de instAncia recebem sempre um valor padrio igual a nu1l, at6 serem inicializadasexplicitamente- 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 queest, 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 locala seguir ser6 compilada apropriadamente:

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

Arrays locaisExatamente como em qualquerorrtra refer6ncia aobjeto, deve-se atribuirumvaloris refer€ncias de arrays declandasdentro deum m619d9 ante; que sejamusadas.Isso significa apenas que voc6 precisadeclarar e constnriro

"o"y.Irio.ntanto, nio ser6

necessirio.inicializar explicitamente os elementos de um array.J6dissemos iso antes, mas 6 imponante o srficiente para queseja repetido: Elementos de arrE recebem seas ualorespadrio (0, fa1se, nu11, ' \u0000 ' e asimpordiante) indepentte;tu d0;ffqterida &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 dentrode 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 outraCom relagio as vari6veis primitivas, aatribuigig de gma variivel a outra significa que o conterido (padr6es de bits) de umavari6vel seri copiado em outra variivel. As vari6veis de refer6ncia de objeto-funcionam ex"t"*.nte-cla m.sma maneira. Oconterido de uma vari6vel de referAncia 6 um pa&lo de bits, portanto, se voc6 atribuir a vari6vel de referAncia a ) variivel derefer6ncia b, o padrlo de bits de a seri copiado e a nova c6pia seri inserida em b. Se atribuirmos a instAncia existente de umobjeto auma novavariivel de referOncia, entio, duasvari6veis de refer6nciaarmazenarioo mesmo padrio de bits -umpadrlo de bits referenciando um objeto especifico da mem6ria. Examine o c6digo a seguir:

i **^*! I ---- -- -- f)i mon<.i nn .rlrryvr u J4vq. dwL

class ReferenceTest {

// com nul-]"

public static void main (String [] args) {

Dimension a = new Dimension(5,10);SvStCm ottf nrinFlh/\\- 1-'^i^Lf - \\ + a hoiahf \eJeuerlr.vqury!rlrurrr\ q.rrsIVIIu - _, 4.rrurVrrL/,

Dimension b = a,-

vi4re+Y11u -

Jv,

Srrsl-cm 6ttf nr.irf'lh/\r- L^.i-L+ - tr +: hoinlrt ruJuuerLLtvuu.y!frlLrrr\ a.rrcr9lrL - , q.rrsfvrrL I

"after change to b" ) ;

public static void main(String [] args) {

String x = "\Tava";af ri naeulfrrv ! - ^t

]

No exemplo anterior, um objeto Dimension a 6 declarado e inicializado com uma largura igual a 5 e altura igual a 10. Aseguir, 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 quetanto a quantob estio referenciando. Para concluir, a propriedade de altura 6 alterada com o uso da referOncia a b. Agora,Pense Por um minuto: Isso tamb6m irimudar apropriedade de altura de a? Vejamos qual ser6 o resultado:

Bjava ReferenceTest

a.height. = 10

a.height = 30 after change to b

Por essa saida, podemos concluir que as duas vari6veis referenciama mesmainstAncia do objeto Dimension. Quandofizemos a alteragio em b, a propriedade de altura tamb6m foi alterada em aEncontramos uma exceglo ) maneira como as refer€ncias a objetos sXo atribuidas no objeto String. EmJava, esses objetosrecebem-tratamento especial. Em primeiro lugar, os o\etor.stringtdo inalteniueir,vocA nlo pode alter:ar o ,ralor de um objetoString. Mas is so parece ser realmente possivel. Examine o c6digo a seguir:

class Strinqs {

,// Atribui- valor a x// Agora, y e x referenciam o mesmo objeto String

Svstem orrf nri nl- l n 1"\/ qtri nn = \\ + \/l '\ J ru!+lry - ' J I t

Page 144: Java - Scjp 5 - Portugues

I '18 Copftulo 3: AtribuiE6es

x = x + " Bean"i / / Agora, o objeto foi alterado com o uso da

/ /referlncia a x

System.out.println("y string = " + y);

)

VocA pode achar que o objeto String y armaz.enar| os caracteres Java Bean depois que a variivel x for alterada, porqueas strings sXo objetos. Examinemos qual seri a saida:

9'i:rr: cf ri nft

Y Strr-ng = ,Java

Y string = ,Java

Como vocA pode ver, mesmo se y for uma vari6vel de refer6ncia ao mesmo objeto que x referencia, quando alterarmos x isso

nio dterari l Com qualquer outro tipo de objeto, onde dtras refer6ncias apontem para o mesmo objeto, se uma delas forusada para aher6Jo, as duas saberio da aheragio, porque ainda haveri somente um obj eto. Mas sempre qnf4tmot alteraldes dc

qaaQaer tipo em urua String, o I,/M ataaliqani a uai,iuel d.e refer€nciaparafa(-k @ontarpara am objeto dtfermte. O objeto diterentepoderiserumnovo objeto ounio, masdefinitivamente serlumobjetodiferente. ArazAopelaqudniopodemos dizercomceneza se foi criado um novo objao reside no pool de corstantes Strings, que abordaremos no Capinrlo 6.

VocA precisa memorizar o que ocorre quando usamos umavari6vel de refer6ncia Stringpara aheraruma$ring:

r [Jma nova string 6 criada, deixando o objeto String original intocado.

I A referAncia usada para alterar o objeto String (ou em vez disso, para criar um novo objeto String pela alteragio de umac6pia do original) seri atribuida ao novo objeto String.

Poftanto, quando vod escrever,

1. Strind s = *Fred";

2. String t = s, // Agora, t e s referenciam o mesmo objeto String3. 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 tquanto s referenciarXo o mesmo objeto Stiing. Mas quando a linha 3 for executadao em vez de alterar o objeto referengia{9

por t (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 realmentereferenciado e tanto t quanto s o referenciario. O comportamento das strings 6 extremamente importante no exame, de

modo que o abordaremos com muito mais detalhes no Capitulo 6.

Obietivo poro o Certificog6o

Passando variiveis para m6todos (Obietivo 7.3 do exame)7.3 Detenninar o efeito nbre as refer€ncias dc olxos e sobre os ualoru pimitiuos quando eles sdo passados a mdtodot que realilam atribuipdes

oa niltras operagdu de nodtftagdo nos parimetros.

Os m6todos podem ser declarados para usar refer6ncias primitivas e/ou de objetos. Voc6 teri que saber como (o9 se) a

valiavel do chanadorpoderi ser afetada pelo m6to do chanadt. A drlerenga entre variiveis primitivas e de refer6ncia de obieto,

quando passadas para m6todos, 6 grande e importante. Para compreender esta segio, voc6 teri que estar familiaizado comasegXo 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 [email protected] de que uma vari6vel de refer6ncia cont6m bits que representam (para o VM subjacente) umarn*rit" d.

".essar um objeto na mim6ria (no heap). O mais imponante que voc€ precisa lembrar 6 que nio estari

passando nem mesmo a variivel de refer6ncia real, mas, emvez disso, uma c6pia dos bits dessa vari|vel, P.ortanto'qnando passar uma variivel de refer€ncia, estar6 passando wa alpia dos bits que representam como um objetoeipecifico 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:

Page 145: Java - Scjp 5 - Portugues

JAVA 5 I'I9f . 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. i10. void modify(Dimension din) {

1-1. dim.height = dim.height + 1;

1,2. System.out.println("dim = " + dim.height) ;

l-3. )

14.j

Quando executarmos essa classe, poderemos ver que o m6todo modi fy ( ) realmenre conseguiu alterar o objetoDimension originat (e rinico) ciado nahrta4.

C : \ Java Pro j ec ts \Re f erence> j ava Ref erenceTes tRaf^r6 mndi€rz/\ r{ haia}rf - 1A\/ srrlsrvrrL - fv

dim = 11

After modifyO d.height = 11

Observe que a paftir do momento em que o objeto Dimension da linha 4 for passado para o m6todo modi fy ( ) ,qudquer alteragXo que ocorrer dentro do m6todo estari sendo feita no objao cuja refer6ncia foi passada. No exemploanterior, tanto a variivel de refer6ncia d quanto d.im apontam para o mesmo objeto.

A linguagem faya usa a semantica de passagem por valor?

Se alinguagemJavapassaobjetos usando avariivel de refer6ncia, isso significa queempregaaparsagempnrrcfefinciano queda resryito a objetos? N5o exatamente, embora seja comum ouvirmos falar e vermos em livros que ela fazisso. Naverdade, elapassanlpor aakr todas xvariiveis que forem executadas dentro do mesmo VM. Passar por valor significa passarpor valor da uai,luel. E isso quer di zer, pa$arpnr aipia da uaiiuel (eis apalavra "c6pia" novamente) !

Nio. faz diferenga se voce est6 passando vari6veis primitivas ou de refer6ncia, sempre estari passando uma c6pia dos bits davari6vel. Portanto, no que diz respeito a uma variivel primitiva, vocO estari passando uma c6pia dos bits qrr. i.pr.s.nt"m ovalor. Por exemplo, se vocd passar uma vari6vel int de valor 3, estari passando um a adpia dosbitsque representam 3.Assim, o m6todo chamado obteri sua propria c6pia do valor, para fazer com ela o que quiser.

E se voc6 estiver passando uma vari6vel de refer6ncia de objeto, estari pas sando wa aipiados bits que represenram arefer6ncia a um objeto. Assim o m6todo chamado obter6 sua propria c6pia da variivel & refer6ncia e far6 com ela o quequiser. Mas j6 que duas variiveis de refer6ncia id6nticas referenciam exatamente o mesmo objeto, se o m6todo chamadodteraro objeto (chamando m6todos de configuragio, porexemplo), o chamadorperceber|,qteo o$eaque suavariivelorigind referenciou tamb6m ter6 sido aherado. Na pr6xima segfo, examinaremos iomo o cenirio se ahera quando falamossobre tipos primitivos.

A conclusio sobre a passagem por valor 6 a seguinte: o m6todo chamado nlo pode alterar a uairlaeldo chamador, emborano que diz resp eito avariiveis de reter|ncia deobjeto, o m6to do chamado pdc aherar o objao que avari|velreferencia. Quala diferengaentre alterar l variivel e alterar o objao? Quanto )s referAncias a objetos, significa que o m6todo chamado niopode reatribuir avariivel de referAncia original do chamador e fazer com que ela referencie um objeto diferente ou ovdornu1l. Porexemplo, no c6digo abaixo,

void bar( ) t

Foof=newFooO;doStuff ( f) ;

)

void dostuff (Foo g) {

Page 146: Java - Scjp 5 - Portugues

'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 sidocriados, um referenciado pela vari6vel local f e outro pela vari6vel local (vari6vel de argumento) 9r. J6 que om6todo doStuf f ( ) possui uma c6pia davari|vel de referAncia, tem uma maneira de acessar o ob)eto Foooriginal,porexemplo parachamar om6todo setName ( ). Por6m, doStuf f ( ) ndotemc0m0acessarauariduelde

referlncia f. Assim, doStuf f ( ) pode alterar o que f estiverreferenciando, mas nio o conterido real (padrio debit$ deste. Em outras palavras, dostuf f ( ) pode modificar o estado do objeto a que f se refere, mas nio podefazer com que f se refta a um objeto diferente!

Passando vari6veis primitiyasExaminemos o que acontece quando uma vari6vel primitiva 6 passada para um m6todo:

class ReferenceTest {

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

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

System.out.println("Before modifyO a = " + a);rF mnr{ i frz /r*..,.-*--f \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 a 6 passada para um m6todo chamado modify ( ) , que a aumentari emuma unidade. A saida resultante teri este formaro:

Refnremndifvll a=lrllvgf !J \ ,

number = 2

Aftermodifvl) a=1Observe que a nio se alterou depois que foi passada para o m6todo. Lembre-se de que somente uma alpia de afoi passada para o m6todo. Quando uma vari6vel primitiva 6 passada para um m6todo, ela 6 pasadapor ualor, o quesignifica "passar por c6pia dos bits davari|vel,.

Na sala de aula

O mundo sombrio das variiveisNo momento em que vod pensou que havia decifrado tudo, viu um trecho de c6digo com variiveis que nlo estavam se componando da maneiraque, na sua opiniio, deveriam estar. VocA pode ter encgntradg

-um c6digo

.com variiveis sombreadas. E possivel sombrear uma variSvel de v6rias

manerras; examinaremos apenas a que mais provavelmente the confundir6 - omltaruma uarihnl fu iutdncia sombreanda-a com ama uarirhnl locaL

O sombreamento envolve redeclarar uma vari6vel que j6 tenha sido declarada em algum outro local. O efeito do sombreamento 6 a ocuha$o&variAveldeclaradaanteriormente, detalmodo quepossaparccerqlrevod estiusando avariiveloculta, mas o queestar6realmenteusandoser| avai|vel de sombreamento. VocA pode encontrar raz6es para sombrear uma variAvel intencionalmente, mas normalmenteocorre por acaso, causando erros dificeis de detectar. No exame, vocA pode esperar perguntas nas quais o sombreamento teri umapanicipagio.

VocA pode sombrear uma variivel de instAncia declarando uma variivel local com o mesmo nome, diretamente ou comoparte de um argumento, como vemos abaixo:

class Foo {

Page 147: Java - Scjp 5 - Portugues

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

Sjava Foo

size = 7

size in chandcTr- is 207

size after changelt is 7

Tudo fica mais interessante quando a vari6vel sombreada 6 a referOncia a um objeto, em vez de um tipo primitivo:

class Bar {

int barNum = 28;

]

class Foo {

Bar myBar = new Bar ( ) ;

void changelt(Bar myBar) {

myBar.barNum = 99;

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

myBar = new BarO;

myBar.barNum = 420;

System.out.println("myBar.barNrm in changelt is now " + myBar.barNum);

]

public static void main (String [] arqs) {

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

changelt (f.myBar) ;

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

]

O c6digo anterior exibir6 isto:

f.myBar.barNum is 28

myBar.barNum in changelt is 99

Page 148: Java - Scjp 5 - Portugues

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 myBarfor atribuido um novo objeto Bar, que em seguida modificaremos alterando seu valor barNum, avariivel de instAncia myear origi-nal de Foo permanecerl intocada.

Al . ,.1.\-/oleTrvo po ro o cenrTrcocoo

Declaragio, construsio e inicializagdo de arrays(Objetivo I.3 do exame)

1.3 Desenuoluercddigo qae dulare, inicialiry e unpimitiuos, affEtq ertramt e obletos como aaidueis esfliticag de instincias e /orais.Akndisso, usar ident'ficadores uilidos para nomes de aaridaeis.

EmJava, os arrays sio objetos que armazenam diversas variiveis do mesmo tipo. Eles podem conter variiveis de refer6nciaprimitivas ou de objeto, mas o array propriamente dito sempre ser6 um objeto da pilha, mesmo se for declarado paraarmazenarelementos primitivos. Emoutraspalavras, nXo exise algo comoumarrayprimitivo,mxvoc|podccriarum arrayde elementos primitivos. Para esse objetivo, vocd teri que conhecertr6s itens:

I Como criarumavariivel de nfunciade xray (declaraio)

r Como criar um ofrxo de array (consrugXo)

I Comoprymcheroarraycomelementos (inicializagXo)

H6v6rias maneiras diferentes de executar cadauma dessas tarefas e voc6 teri que conhecertodas para o exame.

AOTRABALHO

Ot aralt fio efcientes, mas na rzaioria das sitaagdu seri melhor uocd asar ilrt dos tipot Collection da claxe jaua.util (incluindo HathMap,ArrEList e TreeSet). As classes de co@unto oferuem mandras maisflexiueis de acessar un o\eto (para insergdo, exclusdo, leitura e assim

por diante) e diferente dos an'a1s, poderdo rcr expandidat ou mnhaidas dinamieamente quando uocd adicionar ou remouer elementos (na

uerdade e/as s6o arrals gerencidueiq jd que os usam em sua estruturQ. 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 plr nomef ualor? Una lista

encadeada? O Capitalo 7 os abordani com mais detalhes.

Declarando um array

Os arrays sio declarados atrav6s da descriglo do tipo de elemento que armazenario, os quais podem ser um objeto ou umtipo primitivo, seguido de colchetes ) esquerda ou direita do identificador.

Declarando um array de tipos primitivosint[] key; // Colchetes anLes do nome (recomendado)

int key []; /,/ Colchet.es depois do nome (v61ido, mas menos legivel)

Declarando um array que referencie objetos

Threadl] threads; // Recomendado

Thread threads []; // v6Lido, mas menos legivel

Quando declanr avanivelde refer6ncia de um affry, insira sempre os colchetes do array imediammente ap6s o tipodeclarado, em vez de depois do identificador (nome da variivel). Dessa forma, qualquer pessoa que ler o c6digo pod."6perceber 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 arraysarmazenados. Isso pode ser feito da maneira a seguir:

Stringtl tl tl occupantName,' // recomendado

String[] ManagerName []; // feio, mas v61ido

Page 149: Java - Scjp 5 - Portugues

JAVAs I23

O primeiro.exemplo 6um_array tridimensional (um aray com outros arrays tamMm alrrrra?.Enrerrdo arrays) e o segundo 6um-array bidime-rsional. Observe que no segtndo exemplo, temos um colchete antes do nome davariivei eum delois. Isso 6perfeitamente 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 emalgumas outras linguagens, e 6 por isso que poder6 se deparar com uma ou duas perguntas que incluam um c6digosemelhante ao seguinte:

int[5] scores;

O c6digo anterior nio conseguir6 passar pelg compilador. Lcmbre-se de.que a JVM nio alocarS.espago at6 quevoc6 instancie realmente o objeto de array. E ai que o tamanho importari.

Construindo um array

Construir vm array significa criar o objeto de array na pilha (onde todos os objetos residem) - em outras palavras,trarapalavra-chavenew comotipo doarray.Paracrnrumobjeto dearray,aJavateriquesaberquant;espagoalocar na pilha, ponanto, voc6 precisa especificar o tamanho do array na hora da const^glo. Esse tama.rho seriigud a quantidade de elementos que o array armazenar|.

Construindo arrays unidimensionaisA maneira mais-simples de construir um array 6 usar a palavra-chave new seguida pelo tipo do array, comcolchetes. especi{icando quantos elementos desse tipo o array armazenarS. A seguiriemos um exemplo daconstrugio de um array de tipo int:

int[] testscores; / / Declara o array de tipo inttestscores = new int[4]; //constr6i um array e o atribui a vari6vel testscores

O c6digo anterior insere um novo objeto na pilha - um objeto de array contendo quatro elementos - com cadaelemento contendo um tipo int de valor padrio igual a 0. Considere esse c6digo como se ele dissesse aocomPjlaior: "Crie na pilha um objeto de array que armazenar6 quatro tipos inJ primitivos e atribua-o i vari|velde refer6ncia declarada anteriormente chamada Lestscore=. E ..tq.t".rt o fizer isso, aproveite paraconfigurarcada elemento int com zero. Obrigado". (O compilador aprecia boas maneiras). A Figura 3-2 mostra como oarray testscores aparecer| na pilha, depois da construglo.

varidvel derefer€ncia doarray int[ ]

Valores

Indices

Figuro 3-2 - Um orroy unidimensiono/ no pilho

Voc6 tamb6m pode declarar e construir lma arc^y em uma instrugio como vemos abaixo:

int[] testscores = new int[4];Essa instrugXo individual produz o mesmo resultado das duas instrug6es anteriores. os arrays de tipo de objetopodem 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. NioestamoscriandoumainstdnciadeThread,mas,emvezdisso,umrinico objetodearEThread.Depois&inclusXodasinstrug6es anteriores, aindanio haver6, realmente, objetos Thread!

oBSERVAQAO pene O EXAME

Contidere cuidadoumente qilantts objetos estardo napilha, dtpois que uma instrugdo ou bloco do aidigofor exuutado, No exame seriesperado que uoci taiba, por exenpk, qae o aidigo anteriorpmduq@enas m objxo (o aral atribuido a uaiiuel de refer€ncia cbamada

FFT;T;I0123

Page 150: Java - Scjp 5 - Portugues

124 Copitulo 3: AtribuiE6es

thread). O ilnico objeto referenciadopor threafu contim cinco uaridaeis de referinciaTbread, mas nenbum objetoTbreadfoi criado ou

atribaido a essas uaridueis de referincia.

Lembre-se de que os arrays devem senpreterum tamanho atribuido no momento em_que forem construidos. A

JVM precisa do tamanho a fim de alo."r o espago apropriado na pilha para o novo objeto de array. Nunca 6

considerado vilido, por exemplo, fazer o seguinte:

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

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

oBSERVAQAO pene O EXAME

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

pilha;'. Essas pilanas tanbdm inplicam qae 0 cunstrutor do objeto senl executado, como resultado d.o aidigo de nnstragdo/triaydo/-instanciagdo.

itodeno, di7,er con cirteqa, ltor exenplo, qae qua/.quer aidigo que use a palawa-chaue r,ew (se for exuutado eon sucesso) fanlcom 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. Oc6digo a seguir declara e constr6i um array bidimensional de tipo int:

inttl[] ratings = new j-ntt3l tl;Observe que apenas os primeiros colchetes possuem um tamanho. Isso 6 aceitivel em Java, i6 que a JVM precisa

saber somente o tamanho do obieto atribuido avariivel ratings.

A figura demonstra o resultado do seguinte c6digo:

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

objeto do array int[ ]

array 2-D int[ ] [ ]

vari6vel de refer6ncia (doarray 2-D) de int[ ] [ ]

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

Page 151: Java - Scjp 5 - Portugues

JAVA 5 I25

Inicializando um array

lniciel i"x1' qn array significa inserir itens n ele. Os iterc (Srorque, sim, esse /um rermo t6cnico) do array sio seus elemenros,osquaispoderioservaloresprimitivos(2,'x',fa1se eoutros)ouobjetoscitadospelasvariiveisderefer€niradoarray.Se voc6 tiver um array de objetos (e nXo de tipos primitivos), na verdade , ele nilo armaTenar,ios objetos, exatamente comonenhuma outra vari6vel que nio seja primitiva, nunca cont6m realmente o ofiea, mas, em vez disso, armazenavma r{er€nciaa ele. Por6m, nos referimos a arrays como, por exemplo, "um array de cinco strinp", embora isso, na realidade, signifique,"um array de crnco refer€nciat a objetos String". Portanto, a grande pergunta p"srJa ser s. essas refer6ncias estio riesm^o ounlo 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 tentarusar essa referOncia nu11, digamos, aplicando o operador ponto para chamar um m6todo com ela, receber6 a detestivelexceglo Nu1 1 PointerExcept i on .

Os elementos individuais do array podem ser acessados com um ntmero de indice. O nrimero de indice sempre comega nozero' Portanto' Para um array de dez objetos os nrtmeros de indice irio de 0 a 9. Suponha que cri6ssemos um .lrray com tr6sAnimais como descrito a seguir:

Animal [] pets = new Animal[3];Temos_um objeto de array na pilha, com tr6s refer6ncias nu11 do tipo Animal, mas ainda nio temos nenhum objetoAnimal. A pr6xima etapa ser6 criar alguns objetos Animal e atribuir a eles posig6es de indice no array relerenciado porpeES:

pets[0] = new Animalo;Pets [1] = new animal ( ) ;

Pets [2] = new Animal O ;

Esse c6digo insere tr6s novos objetos Animal napilha e os atribui atrAs posig6es (elementos) de indice do arraypets.

OBSERVAQ6ESPARAOE)(AME

Procure aidigos qae tentem acetsar um indice de arralfora do intervalo. Por exerup/0, re am affal tiaer trls e/enentot, a tentatiua de acessar oelemento pl knpani a excegdo ArraylndexOutOfBoundsExcept ion, pois em ltm affal de tu€s elementos, os ualores atllidospara os indices serdo 0, I e 2, Voci tambin pode uer a tentatiua de utiliqagdo de um nilmero negatiuo clmo am indice do anE. A seguir,temos exenplot de tentatiuat ud/idas e inud/idas de acesso ao affaJ. Certfique-w de reconhecer quando elas causam exagdes de tempo deexuagdo e ndo erms de nmpilador! puase todas as petgtlntas do exame listam tanto exngdu de tempo de execugdo quanto envs decompilador como re spostas possiueis.

int[] x = new int[5];x[4] = 2; / / OX, o riltimo elemento est6 no indice 4

x[5] = 3; // Exceqd.o de tempo de execuqSo. Nao h5. nenhum elemento no indice 5!

int [] z = new int[2];int Y = -3'zlyl = 4; / / ExceqSo de tempo de execugSo. y 6 um nfmero negativo

F las poden ser dfrceis de loca/iqar em um kop complexo, mas ese seri o momentr mais prouiuel em que suryirdo problemas con os indieesdos anals de perguntas do exame.

Um array bidimensional (um array preenchido com outros arrays) pode ser inicializado da maneira a seguir:

inttl tl scores = new int[3] [];/ / Declara e cria um array contendo tr6s refer6ncias a arravs intscores[0] = new int[4];/ / o primeiro elemento do array scores estii em um array int de quatro elementos intscores[1] = new int[6];/ / o segundo elemento do array scores est6 em um array int de seis elementos rntscores[2] = new int[1];/ / o terceiro elemento do array scores est6 em um array int de um el-emento int

Page 152: Java - Scjp 5 - Portugues

126 Copftulo 3: AtribuiE6es

Inicializando elementos em um loopOs 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. Porexemplo, se o tarnanho de um array for igual a 4, os valores dos indice irio de 0 a 3. Geralmente' vemos os

elementos do array incializados em um loop conforme descrito abaixo:

Dog[] myDogs = new Dogt6l; // cria um array de 6 referQncias a Dogi

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

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

)

A variivel length nos informa quantos elementos o array cont6m, mas n6o se esses elementos foraminicializados. Como veremos no Cipitulo 5, a partir do Java 5 n6s poderiamos ter escrito o loop f or sem usar a

vari6vel length:for(Dog d : myDogs)

d = newDog( );

Declarando, construindo e incializando em uma linhaVocA 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 primeiroser6 usado para declarar, criar e inicializar, usando uma instrugeo como a seguinte:

f. int x = 9;

2. ing[] dots = {6,x,8};A linha2 do c6digo anterior executa qlrdro operag6es:

I Declara uma vari6vel de refer6ncia ao array int chamada dots.

I Cria um array int de tamanho igual a tr6s (tr6s elementos).

I Atribui aos elementos os valores 6,9 e 8.

I Atribui o novo objeto de array ) vari6vel de refer6ncia dots.

O tamanho (extensio do array) 6 determinado pela quantidade de itens separados por virgulas entre as chaves. O c6digo 6

funcionalmente equivalente ao mais longo descrito a seguir:

int[] dots;dots = new int[3];intx=9;dots[0] = 6;

dots[1] = x;

dots[2] = B;

Issotraz apergunta: "Por que algu6musaria aformamais longa?" Uma razXo vem )mente. VocA pode nio saber- nomomeruo em q.r. .rr", o ,ir"y --os ,ralores que serlo atribuidos aos elementos. 56 esse atalho de array vale o prego deste

livro (bem, isso combinado com amaravilhosa apresentagio).

Com refer6ncias a objetos em vez de tipos primitivos, ele funcionar6 da mesma maneira:

Dog PUPPY = new Dog("Frodo");

Dog[] myDogs = {PuPtry, new Dog("Clover"), new oog("Aiko")};

O c6digo anterior cria o array Dog, referenciado pela variivel myDogts, com um tamanho de tr6s elementos. Ele atribui oobjeto Dog criado anteriormente (atribuido ) vari6vel de referAncia puppy) ao primeiro elemento do array e tamb6m cria

dois novoJobjetos Dog ("clover" e "Aiko") atribuindo as duas instAncias rec6m-criadas aos dois riltimos elementos

&variivel de referAnciaDog, do arraymyDogs. AFigura 34 mostrao resultado.

Vodtamb6mpode usarasintaxe de atalho com arrays mukidimensionais, como nalinhaabaixo:

inttl [] scores = {{5,2,4,1}, {9,2}, t3,4}};O c6digo anterior cria um total de quatro objetos na pilha- Primeiro, um array contendo arrays int 6 construido (o

objao {ue ser6 atribuido ) variivel de refer€ncia scores). O array scores tem um tamanho igual a tr€s, derivado da

q"."tid.d" de itens (separados por virgula) entre as chaves externas. Cada um dos tr& elementos doarray scores 6 uma

v,iriivel que faz refeiOncia a um-array in{ portanto, os tr6s arrays int foram constnldos e atribuidos aos ffes elementos

do affay scores.

Page 153: Java - Scjp 5 - Portugues

JAVA 5 I27

vori6vel dere{er6ncio do orroy oog [ ]

A figuro demonstro o resuhodo do c6digo seguinfe:

Dog PtrBtrY = new Dog("Frodo');OoSt I myDegs * ipuppy, nsw Dsq('Clover,lr rsr. Oog{'Aiko"}};Quofro obielos s6o criodos:

1 objeto Dog referenciodo por puppy e por myDogs ( 0 )

i orroyde Dog [ ] re{erenciodo pornyDogs

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

Figuro 3-4 - Declorqndo, construindo

e iniciqlizondo um arroy de obletos

O tamanho de cada um dos tr6s arrays int 6 derivado da quantidade de itens dentro das chaves internascorresPondentes. Por exemplo, o primeiro array tem um tamanho igual a quatro, o segundo array 6 igual a dois e oterceiro tamb6m 6 igual a dois. At6 agora, temos quatro objetos: um array contendo arrays int (cadi elemenro 6 umareferAncia a umar:rey int) e tr6s arrays int (cada elemento dos tr& arrays int 6 um valor int). Para concluir, os tr6sarrays int foram inicializados com os valores int reais das chaves internas. Portanto, o primeiro array int cont6mos valores 5, 2 ,4 e7 . O c6drso a seguir mostra os valores de alguns dos elementos desse ariay bidimensional:

scores t}l / / um array de quatro intsscores 1Ll / / Lrm array de 2 intsscores t2l / / um array de 2 intsscoresl0l t1l // o valor int igual a 2

scores t2l l1l / / o va]-or int igual a 4

AFigura3-5 mostrao resultadodadeclaragio, consruglo einicializagXo deum arraybidimensionalemumainstruso.

Construindo e inicializando um array an6nimoO sggundo atalho 6 cham ado de aalao ac an'a1 andnimo epode ser usado para construir e inicializar um array e, em seguida,atribui o arrayaumavari6veldeclarada anteriormente, que fagarefer6nciaaoutro aftay:

i nf I l l-6cl- q-^ra<- --- -i,'

testscores = new int [ ] {4 ,7 ,2} ;

O c6digo anterior criouum array int com tr6s elementos, inicializou os tr6s com os valores 4, 7 e 2, e, em segu^ida,atribuiu o novo array i variivel de refer6ncia testscore s do array int declarado anteriormente. Chamamosessa operagio de criagio le array an6nimo, porque com essa sintaxe, voc€ nem mesmo precisa atribuir algumvalor ao novo array. Voc6 pode estar pensando, "Qual a vantagem do array, se ele nXo for atribuido a umivari6velde refer6ncia?" Ele pode_ser usado na criagio de um array just-in-tine a ser empregado, por exemplo, comoargumento de um m6todo que use lm arr^y como parAmetro. O c6digo abaiio demonstra um argumento de array,u$-rn-ume:

public class Foof {

void takesAnArray(int [] someArray) {

/ / usa o array como pardmetro

)

public static void main (String [] args) {

Page 154: Java - Scjp 5 - Portugues

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 do array Cat

objeto Cat

objeto do array Cat

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

D) de cat[ ] [

A figura demonstra o resultado do seguinte c6digo:

cat[ ][ ] myCats = {tnewCat("Fluffy"}, newcat('zeus")},{new Cat("Bilbo"), new Cat("Legolas"), new Cat("BerE") }}

56o criados oito obietos:I obieio orroy 2-D Cat t I t l

2 obietos orroy de Cat [ ]

5 obietos cat

Figuro 3-5 - Um orroy bidimensiono/ no pilho

OBSERVAQ6ESpeneoE)(AME

Itmbre-se de ndo especifcar am tarnanho quando usar a intaxe da criagdo de arral an6nimo. O tamanho d deiuado da quantidade de itens

(separadot por uiryu/a) existentes entre as cbauer. Preste bastante atengdo na intaxe de arals usada nas pergantar do exame (e bauer,i

ntuitas). Vocd pode aer xtrta czmo essa

nar^r f\lrioal-f ?l Inrr'l'l naur nl-rian|- /l row Oh'iccl- {)}:trrufrr rlvvv vvJvvL\r,

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

Atribuig6es vilidas para os elementos do arrayO 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 tiposprimitivos podem ser atribuidos aos elementos do array. E a variivel de referAncia do array? Que tipo de objeto de arraypode 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 primitivosOs arrays primitivos aceitam qualquer valor que possa ser atribuido implicitamente ao tipo de array declarado. Por exemplo,vm arlay inL armazenar6 qualquer valor que seja permitido para uma vari6vel int de 32 bits. Portanto, o c6digo a seguir6v61ido:

int[] weightlist = new int[5];

Page 155: Java - Scjp 5 - Portugues

JAVA5 I29

byte b = 4;

char c = 'c';short s = 7;

weightlisttOl = b' // OK, byte 6 menor do que intweightlisttll = c' // OK, char 6 menor do que intweightlist[2] = si // OK, short 6 menor do que int

Arrays de refer6ncia a objetosSe o tipo declaradopuaoarray forumaclasse, voc6poder6inserirnele objetos de qualquersubclasse do tipo declarado. Porexemplo, se Subaru for uma subclasse de Car, voc6 poderi inserir tanto objetos Subaru quanto objetos Car no array, comovemos 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 itemque possa ser atribuido a uma variivel de refer6ncia Car poderi ser concedido de maneira v6lida a um elemento do array Car.

Se o array for declarado como um tipo de interface, seus elementos poderAo fazer refer|ncia a qualquer instAncia das classesque implementem a interface declarada. O c6digo a seguir demonstra o uso de uma interface como tip o de auay:

interface Sporty {

void beSporty( ) ;

]

class Ferrari extends Car implements Sporty {

nrrhlia rznid l-raannrtrr/\ tv v+\4 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 SportysportyThings [1] = new Racingplats ( ) ;

/ / OIr., RacingFlats implementa SportysportyThinSs[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

Page 156: Java - Scjp 5 - Portugues

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

infIl <nlafc.

int[] dats = new int[4];char[] letters = new char[5];splats = dats; / / Ox, dats se refere a um array intsplats = 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 atribuidaexplicitamente 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 quevoc6 pode inserir um objeto Honda em um array Car (porque Honda esten& a classe Car), pode atribuir um aray detipoHondaaumavariivel de refer€nciado array Carcomo descrito abaixo:

Car [ ] cars,.

Hondal] cuteCars = new Honda[S];

cars = cutecars; / / OK, poi-s Honda 6 um tipo de Car

Beerl] beers = new Beer [99];cars = beers; // llAo nsrA conReTo. pois Beer nao 6 um tipo de Car

Apliqueotest.ti-l,tgUnnOparalhe ajudaradistinguiro que6vilidodo quenio 6. HondaII-MEMBROdo grupo Car,portanto, um arrayHondapodeseratribuido aum array Car. A assertivaBeerE-MEMBRO do grupo Carnio est6correta;Beer ndo estendea classe Car (para nio mencionar o fato de que nio tem sentido l6gico, a menos que voc6 j6 tenha bebidobastante).

oBSERVAQoESPARAOE)(AME

Vocd ndo pode inuerter at atribai{6e! udlidas. Un anal Car nio pode ser atibuido ao anal Honda. Nem todo carro i da marca Honda,portanto, te uoc6 tiuesse dtclarado 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 .

A regras de atribui$o de arrays se aplicam tanto a interfaces quanto a classes. IJm array declarado como um tipo de interfacepode 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 Boximplementar Foldable, o c6digo a seguir ser6 v6lido:

Foldable [ ] foldingThings;Box[] boxThings = new eox[3];foldingThings = boxThings;

/ / oK, Box implementa Fo1dab1e, portanto. Box f-MeMeRo de Foldable

Atribuig6es de vari6veis de refer6ncia de arrays multidimensionaisQuando voc6 atribuir um array a uma vari6vel de refer€ncia de array declarada anteriormente, 0 affal teri que estar

na metma dimeudo da uaiduel de refeftncia a qual estiuer sendo atribuido. Por exemplo , um array bidimensional de arrays intndo pode ser atribuido a uma vari6vel de refer6ncia de um array inL comum, como vemos abaixo:

int[] blots;inttl tl squeegees = new intt3l tl;blots = squeegees; // NAo ti v:furoo, squeegees 6 um array bidimensional de arrays intint[] bl-ocks = new int[6];blots = blocks; / / OK, blocks 6 um array int

Page 157: Java - Scjp 5 - Portugues

JAVA 5 I3IPreste.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&nonas linhCI a seguir:

int[] tl books = new inr[3] [];int[] numbers = new intt6l;int aNumber = 'l ibooks[0] = aNumber; //NA.o 6 vdlroo, espera-se um array r-nt. em vez de um valor intbooks[0] = nunbers, //vALrDo, numbers 6 um array int

A Figura 3-6 mostra um exemplo de atribuig6es v6lidas e invilidas para refer6ncias a um array.

Blocos de Inicializageo

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 dey".ldrye.- t"fap quando aclasse€ garregadapeQprimelavez (umbloco deitticializ"gio esrfuico) ouquandoumainsdncia6 criada (um bloco de inicializagio de instAncia). Vejamoi um exemplot

class SmallInit {

sLatic int x;int y;

\lari{vel de refer€ncia ao AfiayCat[ ]A YariAvel de ref€rencia ao anaySOMENTE pode se referir a uma.ray Cat l-D

Variavel de referencia aoArayCatllll2-DA variavel d6 refer€ncia 2-DSOMENTE pode s€ referir aum array Cat 2-O

Figuro 3-6 AtribuigOes de oroys volidos e inv6lidos

i Cat obj6to

-n o .loato -

uh a.r.y Cat t-Dr a 8m pdo .. t.f.stE . u

o .loato d. u dj.ro e .rr.ycahtl Il2-D8mrbd...r.l.rlr I u E!.y Cat l-D

cat obj€to cataluffy

A mycats = myCats [0]; I

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

B mycats = myCats [0] tOl ; | ----------*

Atribuig6es Inv6lidas de Refer6ncias de Arrays | "*,r,

v61.ido

/ / Nl,o 6 possivel atribuir um objeto ndo-array a I Inv6lidouma refer€ncia a array 1-D

D myCats [0] [1] = morecats'

/ / N5o 6 possivel atribuir um objeto array a umarefer6ncia n5o-array// q€ats [0] [1] s6 pode se referir a um objeto Cat

/ / N5o 6 possivel atribuir um objeto ndo-array a Iuma refer6ncia a array 2-D

Ic mycats [1] = mycats [1] l2l; | ---"-"--'--">

Page 158: Java - Scjp 5 - Portugues

132 Copitulo 3: AtribuiE6es

Como voc6 pode ver, a sintaxe dos blocos de inicializaglo 6 bem complexa. Eles nXo t6m nomes, nio usam-

argumentos . ,rio ,.iorrram nada. 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

superconstnrtores tenham rodado.

VocA pode ter muitos blocos de inicializagio em uma classe. E impottattte notar que' ao contr6rio de m6todos ou

constnrtores , a ordem em qae 0s blocos de inicialiqagdo 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?

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

{ Slzstem.orri-nri nl- ln("1st insl-a.nce init"); }I efrullr!vuu.yt4.Ae+

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

staf ir: { Svst^* arrts nvj-r1-/""nd Static init"); }t slpusrrrrvuu.y!rrru+rr\ 4rr

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

new InitO;new Init(7) t

]

]

Para descobrir a resposta, lembrese destas regras:

I Os blocos deiriciahzagiro rodam na ordem em que aParecem.

r Osblocosde'tncialuagXoest6ticosrodamumavez,quandoaclasre.6.carregadapelaprlmeiravez.

I Os blocos de inicializagio de instincias rodam sempre que uma instl.ncia de classe 6 criada.

I Os blocos de inicializagio de instAncias rodam depois da chamada que o construtor faz a super ( ) .

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

1st static init2nd static init1st instance init2nd instance inicnn-arff a6nql.

1st i-nstance init2nd instance init1-arg const

Como voc6 pode ver, os blocos de rnicia\izaglo de instAncias rodaram duas vezes. Esses tipos de blocos sio usados

como um lugar para se colocar c6digos que todos os constnrtores de uma classe devam compartilhar. Dessa

forma, o c6digo nio precisa ser duplicado em todos os construtores.

Finalmente, se voc0 cometer um erro no seu bloco de inicializagio estatico, a JVM pode langar umExc ept i onlnlnini ta1 i z at i onError. Veiamos um exemplo,

class hitError {

static int [] x = new i-nt[4];

static { xt4l = 5; } // indice de array inv6.1ido!

public static voj-d main(String [] args) { }

Page 159: Java - Scjp 5 - Portugues

JAVA5 I33

J

que produz algo como:

Exception in thread *main" j ava. 1ang. Exceptionrnrnitial_izerErrorCaused by: java. lang.ArraylndexOutOfBoundsException: 4

at InitError. <clinit> (Tnit.Error. iava: 3 )

OBSERVAQ6ESpeneoEJ(AME

Porconuengdo, os b/ocos de inicialiqagdo nonzalmente aParecempertt do inicio do arquiuo da c/asre, en algum lugarpefto rlot construtores.Entretanto, utamosfalandn do exame SCJP aqui. Itfdo se surpreenda se acharum bloco de inicialiqg4do esconditlointre alguns ndtodos,di$argado de um en'o de nmpilapao prlnta para acontecer!

nl . r. ..f.\,roleTtvo poro o cefitttcocoo

Usando classes wrapper (Obietivo 3.1 do exame)J.I Desenuoluer aidigo que ase ar classes wr@perprinitiuas (tais como Boolean, Character, Doable, Integer, etc.), ef ou autoboxing e

unboxing. Discutir as dzferenpas entre as classes Sting, StingBuilder e StringBffin

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

r Fornecer um mecanismo para "empacotar" valores primitivos em um objeto de modo que possam serincluidos em atividades reservadas a obietos, como ier adicionados a coniuntos on retornadbs de um m6todoque 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 costumavamfazer mantalmente agora sio feitas de forma autom6tica.

I Fornecer um conjunto de fung6es utilitirias para tipos primitivos. A maioria dessas fung6es esti relacionadacom v6rias convers6es: de-tipos primitivosem.objetbs Siring e vice-versa, de tipos primitivos e objetos Stringpara bases (ou radicais) diferentes - como binirias, octais e hexadecimais, e viie-virsa.

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

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

Os construtores wrapperTodas as classes wrapper exceto Character fornecem dois construtores: um que usa como argumento o tipoprimitivo que esta sendo criado e outro que usa uma representagio em String do tipo sendo Jonstruido. Pbrexemplo,

fntegfer i1 = new Integer(42);hteger i2 = new Integer (,.42,, 1 ;

ou

new Float (3.IAf\ ;

new Float ( "3 .14f" ) ;

Criando obietos wrapper

Fl-oat f1

E roaL 12

Page 160: Java - Scjp 5 - Portugues

134 Copitulo 3: AtribuiE6es

Tobelo 3-2 C/osses wrapper e os orgurnenios de seus conslrulores

Tipo primitivo Classe wrapper Argumentos do construtor

Boolean Boolean booleano ou String

Byte Byte byte ou String

Char Character char

Double Double double ou String

Float Float float ou String

Int Int.eger int ou String

Long Long long ou String

Short Short short ou String

A classe Character fornece s6 um construtor, que usa o tipo char como argumento. Por exemplo,

Character c1 = new Character('c');Os construtores da classe wrapper Boolean usam um valor booleano true ou f a1se, ou uma String que nlodiferenciamaiusculasdeminisculascomovalortrue oufalse.AntesdeJava5,umobjetoBooleanniopodiaserusado como expressio em um te$e booleano - por exemplo,

Boolean b = new Boolean("fa1se") ;

i f /h\ // ndo compila com Java 1.4 ou anterior

ApartirdeJava5,umobjeto Boo:.earropodcserusadoemumtestebooleano,porqueocompiladorir6,f.aznrautomaticamente o unboxing do objeto para um boolean. Iremos nos concentrar nas fun96es de autoboxing deJava 5

na pr6xima seglo - entio fique alena!

Os m6todos valueOf( )Os dois (bem, geralmente dois) m6todos estiticos valueof ( ) fornecidos na maioria das classes wrapper lheproporcionario outra abordagem paraacriaglode objetos wrapper. Os dois m6todos usam uma Stringpara representar oiipo apropriado de seu primeiro argumento, sendo que o segundo m6todo (quando fornecido) usa um argumentoa&cional, int radix, que indica em que base (como 6in6ria, octal ou hexadecimal) o primeiro argumento foi representado.

Por exemplo,

Integer i2 = Integer.valueOf("101011". 2); / / converte 1-0101-1 em 43 e

/ / atrlbui o val-or 43 ao

/ / nbi'ero Tnfcacr i2t I vv)Yvv

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

Usando os utilit6rios de converseo das classes wrapper

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

m<Value( )Quando voc6 precisar converter o valor de um objeto wrapper num6rico em um tipo primitivo, use um dos

muitos m6todos xxxValue ( ) . Todos os m6todos dessa familia sio m6todos sem argumentos. Como voc6 podever 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 primitivonum6rico. Por exemplo,

Page 161: Java - Scjp 5 - Portugues

JAVAs 135

Integer i2 = new Integer(42);byte b = i2.byteValue0;

short s = i2.shortValueo;

double d = i2.doubleVa1ueO;

Float f2 = new Float(3.14f);short s = f2.shortvalue0t

System. out.println (s ) ;

Iobelo 3-3 M6todos wrapper comuns de conversdo

/ / cria um novo objeto wrarx)er

// conwerte o valor de i2's em um

/ / nrimi t- i rrn ].xrf a

/ / vm outro m6todo xxxValue/ / Aa Taraaar/ , sv 4A4vvYe!

/ / mais um m6todo xxxValue/ / Aa 'rnranar

/ / cria um novo objeto wrapper

// converxe o valor de i2's em um

// primitivo short// o resultado 6 3 (truncado, nao

// arredondado)

M6todos=staticn=excegeoNFE Boolean Byt€ Character Double Float Integer Iong Short

ByeVdue

doubleValue

FloatVdue

IntValue

IongVahre

ShortMue

ParseX:o<42

ParseX:o< 4z (com a base)

valueOf. s,n

valueOf s,n (com abase)

Tosfting

toStringi(primitivQ x

toString s (primitivo, base)

Resumindo, as assinaturas essengiais dos m6todos wrapper de conversio sio:primitivexorValue$ -paraconverterumtilfrapperparaumprimitiveprimitive parsdGo<(String) - para converter um String para um primitive\(lrappervahrcOf(String) -paraconvefterumStringparaum\ilfrapper

pansexuO e valueOf( )Os seis m6todos parsexxx ( ) (um de cada tipo wrapper num6rico) estio intimamente relacionados com o m6todova]ueof ( ) que existe em todas as classes wrapper num6ricas. Tanto parsexxx ( ) quanto valueof ( ) usamuma String como argumento, langamuma excegio NuberFonnatException se o argumento Stringnio estiver noformato apropriado e podem convener objetos String de diferentes bases (radicais), quando o tipo primitivo subjacente forqualquer um dos quatro tipos inteiros (consulte a Tabela 3-3). A diferenga entre os dois m6todos 6 que:

I parseXxx( ) retornaotipoprimitivonomeado.

I ValueOf ( ) retorna um objeto wrapper rec6m<riado do tipo que chamou o m6todo.

Alguns exemplos desses m6todos em agio:

Page 162: Java - Scjp 5 - Portugues

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

Os exemplos abaixo envolvem o uso da base como argumento (nesse caso, biniria):

/ / converte um Strinq em um primitivo

// o resul_tado 6 "d4 = 3.14"

/ / cria um objeto Double

// o resultado 6

/ / S:uring bin6ria para um primitivo// o resultado 6 "L2 = 42'

/ / Strrng bin6ria para objeto Longl

// o reswLtado 6 "L3 value = 42"

long L2 = Long.parselong("101010", 2);System.out.println("L2 = " + L2) ;

Long L3 = Long.vafueOf("101010",

System.out.println("L3 value = "

2t;+ L3);

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 m6todotoString( ). Oobjetivodom6todo toString( ) 6permitirquevoc6obtenhaalguma representagdosrgnficatiua

de determinado objeto. Por exemplo, se voce tiver um conjunto de v6rios tipos de objetos, poderi percorrA-lo e

exibir alguma forma de representagio significativa de cada objeto usando toString ( ) , que com cefteza podeser encontrado em todas as classes. Discutiremos mais o m6todo toString ( ) no capitulo sobre Conjuntos,mas, por enquanto, enfocaremos como esse m6todo est6 relacionado com as classes wrapper que, como sabemos,

sio marcadas com f ina1. Todas as classes wrapper possuem a versio de uma in$6ncia de toString ( ) sem

atgamentls e ndo-sLaLic. Esse m6todo retorna uma String com o valor do tipo primitivo encapsulado no objeto.Por exemplo,

Double d = new Doubl-e("3.14");

System.out.println("d= " +d.tostring0 l; // o resuLtado6 "d= 3.14"

Todas as classes wrapper num6ricas fornecem um m6todo static toString ( ) sobrecarregado que usa otipo num6rico primitivo apropriado (oouble. toString ( ) usa um double, Long. toString ( ) usa umlong, 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 convert6Jopara 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 umarepresentagio 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 octalSystem.out.println("254 in octal = "+ s4); // o resul-tado 6 "254 in octal = 376"

Estudar a Tabela 3-3 6. a melhor maneira de se preparar para esta segio do teste. Se voc6 conseguir entender bem as

diferengasentre xxxvalue( ),parseXxx( ) evalueOf ( ),devesesairbemnessapartedoexame.

AutoboxingIntroduzido 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 ouso de classes wrapper. Antigamente, no mundo pr6-Java 5, se voc6 quisesse criar um w rapper, abriJo, usiJo e depoisfech6lo novamente, vocA poderia fazer algo como:

Integer Y = new Integer(5671;int x = y.intValueO;x++,'

/ / cria/ / abre

/ / rrca aql-a

Page 163: Java - Scjp 5 - Portugues

JAVA 5 I37

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:

Y=568E sim, voc6 leu corretamente. O c6digo parece estar usando o operador de p6s-incremento em uma vari6vel de referdncia aobjeto! Mas isso 6 simplesmente uma conveniAncia. Nos bastidores, o compilador faz o unboxing e a reatribuigio paravoc6. Anteriormente, n6s mencionamos que os objetos wrapper sio imut6veis... Este exemplo parece contradizer isso.Com certeza parece que o valor de y mudou de 567 para 568. Mas o que realmente aconteceu foi que um segundo objetowrapper foi criado, e o seu valor foi definido como 568. Se pelo menos n6s pud6ssemos acessar aquele primeiro objetowrapper, poderiamos provar isso...

/ / cri-a um wrapper

/ / atribui uma segunda vari5vel/ / de refer6ncia AO wrapper

/ / verifica se elas estao se

/ / referindo ao mesmo objeto

// abre, usa, fecha novarnente

/ / exibe os valores/ / verifica se elas estao se

/ / refcri ndn : ntrietos diferentesO que produz a saida:

Erue

567 568

falseAssim, nos bastidores, quando o compilador chegou i linha y++; ele teve de substitui-la por algo como isto:

int x2 = y.intValue0 ; / / abre

x2++;

y = new Integer(x2);Como suspeit6vamos, precisa haver uma chamada a new em algum lugar do c6digo.

Boxing, ==r€equalsQAcabamos de usar : : parafaznr uma pequena exploragio dos wrappers. Vamos dar uma olhada com mais detalhes emcomo os wrappers trabalham com : : , ! : e equal s O . Falaremos muito mais sobre o m6todo equal s O emcapitulos posteriores. Por agora, tudo o que temos de saber 6 que a intengio do m6todo equals ( ) 6 determinar se duasinstAncias de uma dada classe slo "significativamente equivalentes". Essa definigSo 6 subjetiva de prop6sito; fica a cargo docriador da classe determinar o que significa "equivalente" para os objetos da classe em questio. Os desenvolvedores da APIdecidiram que, para todas as classes wrapper, dois objetos sio iguais se forem do mesmo tipo e tiverem o mesmo valor.Nio deve ser surpreen&nte que

Integer i1 = 1000;

Integler i2 = 1000;

if (i1 != i2) System.out.println("different objects") ;

if (i1. eguals (i2) ) System. out.println( "meaningfully egual" ) ;

y = new fnteger(x),'Svstem orrl- nrinf lnI"rr = " + it.vgu.yt4rrUJlr\f_

/ / fecha novamente

/ / exibe

/ / cria/ / abre, incrementa,

/ / fecha novamente

/ / exlbe

Vamos tentar o seguinte:

Integer Y = 567;T- | ^-^erllLeljer

^ - y,

System. out.println (y==x) ;

Y++ i

System.out.println(x + * " + y);System. out.println (y==x) ;

// usa

/ / fecha novamente

Page 164: Java - Scjp 5 - Portugues

138 Copfiulo 3: AtribuiE6es

Produza a saida:

different objectsmeaningfully equal

SXo apenas dois objetos wrapper que, por acaso, tAm o mesmo valor. Pelo fato de eles terem o mesmo valor int, om6todo equals ( ) os consi&ra iomb sendo "significativamente equivalentes", e, portanto, retorna true. E quanto a

isoaqui:

Integer i3 = 10;

Integer i4 = L0;

if (i3 == i4) System.out.println("same object") ;

if (i3.equa1s (i4) ) System.out.print.ln( "meaningfullv equa1" ) ;

Este exemplo produz a saida:

same objectmeaningfully equal

Ugh! O maodo equals ( ) parece estar funcionando, mas o que aconteceu com : : s ! : ? Por que razio ! : est6 nos

diiendoqueil- ei2 sXoobjetosdiferentes,quando:: est6dizendoquei3 ei4 sioomesmoobjeto?Para. .

economizar mem6ria, duas instAncas dos seguintes objetos wrapper serio sempls : : quando os seus valores primitivosforemo mesmo:

I Boolean

I Byter character de\u0000at6\u007f (7f 6I27 emdecimal)

I Short ernteger de-I28a&127

Onde Pode ser Usado o BoxingConforme discutimos anteriormente,6 bastantecomumusarv/rappers emcombinagio comconjuntos. Sempre que quiserque 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 possausarumprimirivo 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) {

Boolean ifSo = true;Short s = 300;

if (ifso) t

// encapsula o int que recebeu

// encapsula o literal// encapsula o primitivo

/ / abrindo

System. out . println ( ++s ) ;

ireturn !ifSo;

/ / abre, incrementa, encapsula novamente

/ / abre, reLorna o inverso

J

oBSERVAQoES pene O DC{ME

I-*mbre-se de qae as uaiiueis de refer€ncia wr@perpodem serrrwJ_l-,. Isso signfica que uoci precita tomar euidado com algum nidigo que

parega e$arrealiqando operagdu seguras conprinitiuos, nat queplssan lanprumaNullPointerException.'

class Boxing2 {

static Integer x;

Page 165: Java - Scjp 5 - Portugues

JAVA5 I39

public static void main(String [] arqs) {

evves!! \^/ |

)

static void doStuff(int z) {

inX z2 = 5:

System.out.println(22 + zl ;

JJ

Ette aidigo conpila unproblemas, mat aJI/M knga umaNullPointerException quando tenta ehamardoSXuf f (?<),

Pzrqae x nio se refere a um oQeto Integec pnftantl, ndo hi nenbum ualor para abir.

Obietivo poro o CertificoE6o

Sobrecarregando (Objetivos 1.5 e 5.4 do Exame)1,5 Dado um exemplo de aidtgo, deterwinar se um mitodo eshi sobresmuendo oa sobncamgando comtanente ouho mitodo, e identifcaraalores de retomo udlidot (incluindo retnrnls coaaiades) para o mitodo en questdo.

5.4 Dado un ceniio, dueruolueraidigo que dulan ef or ebame mdtodat sobrescritos ou sobrecamgados...

Sobrecarregando da Maneira Dificil - Correspond€ncia de M6todosEmbora ji tenhamos abordado algumas regras para a sobrecarga de m6todos no Capitulo 2, neste capitulo n6sadicioaaremos alguns itens ) nossa caixa & ferramentasJava. Nesta segio, daremos uma olhada em ti6s fatores que podemdifi cultar um pouco a sobrecarga:

r Ampliago

I Autoboxing

f Var-arp

Quando umaclassetem m6todos sobrecarregados, umadastarefas do compilador6 determinar qual m6todo usarsempreque encontrarumachamadaao m6todo sobrecaregado. Vejamos umexemplo que nlo usanenhumrecurso novo deJava5:

class EasyOver {

static void go(int x) { System.out.print("int "); }

sLatic void go(long x) { System.out.print("1ong "); }

static void go(double x) { System.out.printl"double "); }

public static void main(String [] args) tbyte 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

Page 166: Java - Scjp 5 - Portugues

140 Cop(tulo 3: Atribuig6es

Isso provavelmente nlo serl nenhuma surpresa; as chamadas que usam byte e os arguryentos shon sioimplicitamente ampliados para bater com a versio do m6todo go ( ) que usa um int. E claro que a chamada

.o* long usa a rierslo tong de go ( ) e, finalmente, a chamada que usa um f l-oat 6 convertida para bater

com o m6todo que usa um double.

Em qualquer caso, quando uma correspond6ncia exata nio puder se encontrada, a JVM usa o m6todo com omenor argumento que seja mais amplo do que o parAmetro.

VocA pode verificar que, se houver apenas uma versio do m6todo go ( ) , e ele usar um double, essa versio se r|usaAaparatodas as quatro chamadas a go ( ) .

Sobrecarga com Boxing e Var-argsVamos 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"); }

static void go(int x, int y) { System.out.println("int,int");}static void go(byte... x) { System.out.println("byte... "); }

public static void main(String[] args) {

byte b = 5;

qo{b,b); // qual go0 ser5 chamado?

)

Como voc6 provavelmente adivinhou, a saida 6

int, intPorque, mais uma vez, mesmo que cada chamada requeira algum tipo de conversio, o compilador escolher6 o estilo antigoem vez do estilo novo, mantendo os c6digos existentes mais robustos. At6 aqui, vimos que:

r A ampliagio 6 preferida em vez do boxing

r A ampliagio 6 preferida em vez dos var-args

Neste ponto, as mentes curiosas querem saber: o boxing 6 preferido em relaglo aos var-args?

class BoxOrVararg {static void gro (Byte x, Byte y)

{ System.out.println("Byte, Byte") ; }

static void go(byte... x) { System.out.println("byte... "); }

public static void main(String [] args) {

int i = 5;

9o (i) ; / / q)al go O ser6 chamado?

]

]

Como vimos anteriormente, se a tnica versio de go ( ) fosse a que usa um Integer, o recurso de boxing de Java 5

permitiria que go ( ) fosse chamado com sucesso. Da mesma forma, se apenas a verseo long existisse, o comPilador a

usaria para lidar com a cham adaago ( ) . A questXo 6, dado que ambos os m6todos existem, qual deles ser6 usado? Emoutras palavras, seri que o compilador pensa que ampliar um parAmetro primitivo 6 melhor do que realizar uma operaEiode autoboxing? A resposta 6 que o compila dor preferirlaampliagio, entio a saida seri:

long

Os elaboradores deJava 5 decidiram que a regra mais imponante deveria ser que os c6digos pr6existentes devem continuarfuncionando 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 prevera saida do seguinte c6digo:

class Addvarargs {

Page 167: Java - Scjp 5 - Portugues

JAVA 5 I4I

)

E a saida 6

Byte, Byte

IJma boa maneira de memori zar essa regra t.perceber que o m6todo var-args 6 mais "solto" que o outro m6todo, nosentido de que ele pode lidar com chamadas contendo qualquer nrimero de parAmetros int. Um m6todo var-args funcionamais como um m6todo de captura total, em termos & quais chamadas ele pode lidar; e, como veremos no Capitul o 5,fazmais sentido que recursos de captura total sejam usados c omo vm illtimo recurso.

Ampliando Vari6veis de Refer6nciaJi vimos que 6 vilido ampliar um primitivo. E possivel ampliar uma variivel de refer6ncia e, em caso positivo, o que issosignificaria? Voltemos o nosso raciocinio para a nossa atribuigio polim6rfica favorita:

Animal_ a = new DogO;

Mantendo esse mesmo raciocinio, uma chamada poderia ser:

cl-ass enimal {statj-c void eatO { } iclass Dog3 extends Animal {

public static void main(String[] args) iDog3d=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 paraum Animal, e a chamada tem sucesso. A principal questlo aqui 6 que a ampliagio da refer6ncia depende da heranga" emoutras 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) {

public static voidbyte b = 5;

qo (b, b) ;

)

Dog4d=newDog4O;d. test (new Integer (5) ) ;

]

void test (Long x) { }

main(StrinS [] args) {

// qoaT go$ ser6 chamado?

,/,/ impossivel ampliar um Inteqer| / ^^-^ ..* T ^6-/ / IJAL q UrL !V1r9

]

I--embre-sedequenenhartadasclasseswr@perpodeseamp/iardeumaparaoutralByLes ndoseampliamparashorts,Shortsndo se ampliamparaLongs, etc.

Sobrecarga na Combinagio de Ampliagio com BoxingJi vimos as regras que se aplicam quando o compilador consegpe estabelecer uma correspond6ncia entre chama& e m6todorealizando uma tinica convenio. Vejamos agora o que acontece quando 6 preciso fazer mais de uma conversio. Neste caso, ocompiladorter6 de ampliar e depois fazer autoboxing do parAmetro para que haja uma correspond6ncia:

Page 168: Java - Scjp 5 - Portugues

142 Copitulo 3: AtribuiE6es

class WidenAndBox {

sLatic void go(Long x) { System.out.println("Long"); }

public static void main(String [] args) {

byte b = 5,'

go (b) ; / / preclsa ampliar e depois fazet boxing - inv6lido

)

Isso 6 &mais para o compilador:

WidenAndBox. java: 5 : gto ( java. lang.Long) in WidenAndBox cannot be

applied to (byter

Mas o 6 estranho que o compiladorPODE fazerumaoperagio de boxingseguidaporumaopera$o de ampliagio para

criar uma corresponddncia entre chamada e m6todo. Este exemplo podera lhe deixar confuso:

class goxAndWiden {

static void go(Object o) {

Byte b2 = (Byte) o; / / ok - 6 um objeto Byteqrrqf6m nrrt- nriniln /Lr?\ .sJ p Lvlr!. vqu.}/t frrufLL \p- t,

)

public static void main(String [] args) t

byte b = 5;

go(b); // este byte pode ser transformado em um Object?

)

)

Esse exemplo compila (!), e produz a saida:

5

Uau! Eis o que aconteceu nos bastidores quando o compilador, e depois aJVM, chegou i linha que chama om6todo go O :

1. O byte b foi encapsulado com boxing em um Byte.

2. A refer€ncia Byte foi ampliada para se tornar um Object (uma vez que Byte estende Object).

3. O m6todo go ( ) recebeu uma refer6ncia Object que, na verdade, aponta para um objeto Byte.

4. O m6todo so ( ) convefteu a referOncia Object de volta para uma refer6ncia Byte (embre-se, nunca houveum objeto do tipo Object neste cenirio, apenas um objeto do tipo Byte!).

5. O m6todo so ( ) exibiu o valor de Byte.

Porque o compiladorniotentouusaral6gicaboxingdepois-amplia$o quando tentoulidarcom aclasseWidenAndBox? Pense nisso... Se ele tentasse fazer boxing primeiro, byte seria convertido em um Byte. E ai estariamos devolta i situagio & tentar ampliar um Byte para um Long e, 6 claro, o teste E-UM falha.

Sobrecarga em Combinagio com Var-argsO que acontece setentarmos combinarvar-argp oucom a ampliagio ou com o boxingemum cenirio de buscapelacorrespond6ncia de um m6todo? Vejamos:

class Vararg {

static void wide-vararq(1ong. . . x)

{ System.out.println("1ong. . . " ) ; }

static void box_vararg(Integer. . . x)

{ System.out.println( "fnteger. . . " ) ; }

public static void main(String [] args) t

wide-varars(5,5); // precisa ser ampliado e usa var-argsbox_vararg(5,5) ; / / preclsa ser encapsul-ado com boxing e usa var-args

Page 169: Java - Scjp 5 - Portugues

JAVA 5 '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 regraspara m6todos sobrecarregados que usem ampliaglo, boxing e var-args:

r A ampliagio de primitivos usa o "menor" argumento possivel do m6todo.

I Usados individualmente, boxing e var-args sio compativeis com a sobrecarga.

r NAO 6 possivel ampliar de um tipo wrapper para outro. @-tnt frlha.;

r NAO 6 possivel ampliar e depois fazer boxing. (Jm int nlo pode se tornar um Long)

I E possivel fazer boxing e depois ampliar. (Um int pode se tornar um Object, via Integer.) E possivel combinar var-args com ampliagio ou com boxing.

Existem aspectos mais complexos relativos i sobrecarga, mas, tirando algumas poucas regras referentes aos gen6ricos (queabordaremos no Capinrlo /), isso 6 tudo o que voc6 percisarl saber para o exame. Caramba!

Obietivo poro o certificoEdo

Coleta de lixo (Objetivo 7.4 do exame)T.4Dadoumexemplodealdigo,reconheceropontoemqueumoletosetornaqualifcadoparaacoletadelixo,edeterminaroquedeoquendoigmantido pek $stema de colcta de lixo. Reeonhuer 0 cnnpnftamentr de Slsten.gc e dafnaliryg1o.

Visio total do gerenciamento da mem6ria e da coleta de lixoEsta 6 a seglo pela qual voc6 estava esperando! Finalmente chegou a hora de nos aprofundarmos no interessante universodo gerenciamento da mem6riae coleta de lixo.

O gerenciamento da mem6ria 6 um elemento crucial em muitos tipos de aplicativos. Considere um programa que leiagrandes quantidades de dados, digamos, em algum local de uma rede e, em seguida, os grave em um banco de dados naunida& 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 armazenoutemporariamente precisaria eliminar os dados antigos ou ser excluido e recriado antes do processamento do pr6ximo lote.Essaopera$opodeserexecutadavAiuvezns,eemlinguagenscomoCouC+ +,queniooferecemacoletaautom6ticadelixo; 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 pequenasperdas sXo chamadas de uaTamentot de memriia, e depois de virias iterag6es podem tornar inacessivel uma quantidadesuficiente de mem6ria para finalmente causar a interrupgio dos programas. A criagio de um c6digo que execute ogerenciamento manual da mem6ria de maneira limpa e completa 6 uma tarefa complicada e nio trivial, e emboraas estimativas variem, 6 discutivel se esse gerenciamento manual pode dobrar o esforgo de desenvolvimento de umprograma complexo.

O coletorde lixo dalinguagemJavaforneceumasolugio automhticaparaogerenciamento damem6ria. Namaioriadoscasos ele o livrari de ter que adicionar alguma l6gica de gerenciamento da mem6ria em seu aplicativo. A &wantagem dacoleta de lixo autom6tica 6 que voc6 nlo poder6 controlar exatamente quando ela ser6 ou nio executada.

Vis6o geral do coletor de lixo em favaVamos examinar o que queremos dizer sobre coleta de lixo no universoJava. Aqui, a 30 mil p6s de altura, coleta de lixo 6 otermo usado para descrever o gerenciamento automitico da mem6ria em Java. Sempre que o programa de um software forexecutado (emJav4 C, C + + , Lisp, Ruby, e assim por diante), ele usar6 a mem6ria de v6rias maneiras diferentes. Nioentraremos nos aspectos blsicos da ci€ncia da computaglo aqui, mas 6 normal a mem6ria ser usada para criar uma pilh4 umheap, em pools constantes de maiusculas e minusculas da linguagemJava, e em 6reas de m6todos. Heap 6 aparte damem6ria onde residem os objetosJava, sendo o rtnico local da mem6ria que de alguma forma estari envolvido noprocesso de colaade lixo.

Un heap i irzplesaente am he@. No exane rcni inportantu saber que uocd pode chaad-lo de be@, de heap de cokta de lixo, de

Page 170: Java - Scjp 5 - Portugues

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 disponivelquanto 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 emum ciclo constante de criagio dos objetos que precisa (o que ocupa espago no heap) e, em seguida, descartando-osquando 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 excluirida 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 voc6pode solicitar )LJVM para executar o coletor de lixo, mas nio haveri garantia, em nenhuma circunstAncia, de queele o far|. Quando a decisio 6 s6 dele, normalmente a JVM executa o coletor de lixo ao perceber que a mem6riaest6 ficando sem espago. A experiAncia mostra que quando um programalava f.az uma solicitagio de coleta delixo, a JVM geralmente a atende rapidamente, mas ado bd garuntias. Exatamente quando pensamos que poderemoscontar 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 niogarante 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 tlrnarealmente qaalifcado para a coleta de lixo. Para responder essa questeo integralmente temos que nos adiantar um pouco efalar sobre threads - consulte o Capitulo 9 para obter informag6es detalhadas sobre eles. Resumidamente, todoprograma 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 m6todomain ( ) no final da pilha. No entanto, como aprenderemos em detalhes no Capitulo 9, hl muitas raz6esrealmente importantes para iniciar threads adicionais a paftir de seu primeiro thread. Al6m de ter sua pr6priapilha de execugio, cada thread possui seu pr6prio ciclo de vida. Por enquanto, tudo que precisamos saber 6 que osthreads podem estar ativos ou nio. Com essas informag6es auxiliares jf podemos dizlr cbm bastante clareza queum objeto utui qualficado para a coleta de lixo qaando nenhum tbread atiuo pode acessd-/0. (Observagio: devido ao cariter vago dopool de constantes Strings, o exame concentra as suas quest6es sobre coleta de lixo em objetos nio-Strings, enteo anossa 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 umobjeto que nlo pode ser alcangado por nenhum thread ativo o considera qualificado para a exclusio, e pode at6exclui-lo em algum momento. Ou tamb6m pode nio exclui-lo nunca. Quando falamos sobre alcanparum objeto, naverdade estamos falando sobre ter uma variivel de refer€ncia ahangiuel que aponte para o objeto em questao. Se

nosso programa Java tiver uma variivel de refer6ncia que aponte para um objeto, e se ela estiver disponivel paraum 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 objetosda mem6ria quando eles nio forem usados. No entanto, se voc6 tiver muitos objetos ativos (objetos referenciados poroutros objetos ativos), o sistema poder6 ficar sem mem6ria disponivel. A coleta de lixo nio pode assegurar que hajamem6ria suficiente, somente que a mem6ria disponivel ser6 gerenciada tio eficientemente quanto possivel.

Escrevendo um c6digo que torne os objetos explicitamente qualificadosPara a coleta

Na seglo anterior, aprendemos as teorias existentes por trAs da coleta de lixo Java. Nesta segio, mostraremos como tornar osobjetos qualificados para a coleta de lixo usando um c6digo real. Tamb6m discutiremos como 6 possivel tentar forgar acoleta de lixo se ela for necessiria e como voc6 pode executar uma limpeza adicional nos objetos antes que eles sejamremovidos da mem6ria.

Anulando uma refer6nciaComo discutimos anteriormente, um objeto se torna qualificado para a coleta de lixo quando nlo h6 mais referAncias a eleque possam ser alcangadas. E claro que se nlo houver refer6ncias alcang6veis, nio imponari o destino do objeto. No que nosdiz respeito, ele ficar6 apenas flutuando no espago, sem ser utilizado ou acessado, nio sendo mais necessirio.

A primeira maneira de remover a refer6ncia a um objeto 6 configurar com nulf avari|vel de refer6ncia queestiver apontando para ele. Examine o c6digo a seguir:

Page 171: Java - Scjp 5 - Portugues

JAVA 5 I45

1. public class GarbageTruck {2. public static void main(String [] args) {

3 . StringBuffer sb = new StringBuffer ( "hello" ) ;

4. System.out.println(sb) ;

5. // O objetoStringBuffer nao esta qualificado para coleta6. sb = nul1;'7. / / Agora o objetostringBuffer est.6 qualificado para coletaB. )

9. ]

A variivel de refer6ncia sb foi atribuida ao objeto StringBuffer de valor hell-o na terceira linha. Para torn6-loqualificado (ptara a coleta), configuramos a variivel de refer6ncia sb com null, o que remover| a inicarefer6ncia ao objeto StringBuf f er que existia. IJma vez executada a linha 6, nosso objeto StringBuf f erhe11o estar6 condenado, qualificado para a coleta de lixo.

Reatribuindo uma vari6vel de referGnciaTamb6m podemos desassociar uma varilvel de referdncia de um objeto configurando-a para referenciar outroobjeto. 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 nri nl- lr 1<1 \vJ s ev.'r.

// Neste ponto, o StringBuffer "hell-o" nao est5 qualificados1 = s2; // Redireciona s1 para refer6ncia ao objeto "goodbye"

/ / Agora o StringBuffer "hel1o" est5 qualificado para coleta

)

iOs objetos criados em um m6todo tamb6m precisam ser considerados. Quando um m6todo for chamado, qualquervari6vel 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 retornadodo m6todo, sua refer6ncia pode ser atribuida a uma variivel do m6todo que o chamou; assim, ele nio estariqualificado para a coleta. Examine o c6digo abaixo:

import j ava. util . Date t

nrrhl i n al :cc fl:rl-r:naE'ani-nrrz I

public static void main(String [] args) {

Date d = getDateo

doComplicatedstuff ( ) ;

System.out.println("d = " + d) ;

)

n"k] .i^ -f-f.i^ nrl6 d6l-n:f6/\ tPUUIIL DUaUfL uqus YeLUqre\/ L

Date d2 = new lateo;StringBuffer now = new StringBuffer (d2.toStringO );qircl- am ^11|- nri n|- l n lnar^rl .efrevrrr!vuu.vrflrvf

return d2;

]

]

No exemplo anterior, criamos um m6todo chamado getDate ( ) que retorna um objeto Date. Esse m6todo criadois objetos: um objeto Date e uma StringBuffer contendo as informag6es sobre a data.li que o m6todo retorna oobjeto Date, ele nio esterS, qualificado para a coleta mesmo depois que o m6todo for concluido. O objetoStringBuffer, no entanto, estar6 qualificado, ainda que nio tenhamos configurado explicitamente a variivel nowcom null-.

Page 172: Java - Scjp 5 - Portugues

146 Copftulo 3: Atribuig6es

lsolando uma referenciaH6 outra maneira por meio da qual os objetos podem se tornar qualificados para a coleta de lixo, netmo rc ainda

tiaervm referincias u,ilidas! Consideramos esse cenirio como ilbat de isolamento.

Um exemplo simples seria uma classe que tivesse uma vari6vel de instAncia que fosse a variivel de refer6ncia de outrainstAncia & 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 referdnciav61ida, nio haveri como algum thread ativo acessar um deles. Quando o coletor de lixo for executado, ele descobrir6 esasilhas de objetos e as remover6. Como voc6 pode imaginar, as ilhas podem se tornar bem grandes, contendo teoricamentecentenas de objetos. Examine o c6digo a seguir:

public class lsland {

Island i;public static void main(String [] arqs) {

fsland i2 = new IslandoIsland i3 = new fslandoIsland i4 = new Islando

IZ .I

lJ.a

i4.i

:A -

i3; // i2 refere-se a i3i4; // i3 refere-se a i4i2; // i4 refere-se a i2

nrrl l .

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, i3e 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-7para refor7ar os conceitos de objetos sem referOncias e ilbas de inlanento.

Forgando a coleta de lixoA 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, provavelmenteir6 tentar minimizar as chances de um atraso causado pela coleta de lixo. Mas deve se lembrar que os m6todosfornecidos pelaJava sio solicitagdes e nio demandas; a miquina virtual fari o que puder para executar o que voc6solicitar, 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 todosos objetos nXo utilizador r.iao reimente removidos da mem6ria. li essencial que voc6 compieenda esse c-onceitopara 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 Runtimefornece um mecanismo de comunicagio direta com a m6quina virtual. Para capturar a instAncia de Runtime, voc6pode 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 oobjeto Singleton para voc6. A maneira mais simples de solicitar a coleta de lixo Qembre-se: 6 apenas umasolicitaEio) 6 atrav6s de:

Qa'cf6m n- I I

Page 173: Java - Scjp 5 - Portugues

JAVA 5 I47

Teoricamente, depois de chamar System. cg ( ) , voc6 ter6 tanto espago livre na mem6ria quanto possivel.Dissemos teoicamente porque essa rotina nem sempre funciona assim. Primeiro, a JVM que voc6 estiver usandopode nXo tAJa implementado; a especificagio da linguagem permite que essa rotin^ nilo tenha absolutamentenenhumafungio.

pubLic class IslandIsland n;public static void

Island i2 = newls1and i3 = newTsland i4 = newl-l.n = t-Ji3.n = i4i4.n =i2i2 = nul1;i3 = null;i4 = nu11;

(

main(St.ring [] args) {IslandO;IslandO:Island():

public class LosE {public static void rnain(Strinq {} args) {

Lost x = new tost O:x = nul1;docomplexstuff ( ) :

)

5.

7.

8.q

l_0.

System. out.println ( "Tota1 JVM memory:

System.out.println( "Before Memory = "Date d = nul1;for(int i = 0;i<10000;i++) {

d = new Date0;d = nul1;

+ rt.totalMemoryO );rt.freeMemoryO );

11.

1,2.

13.

L4.

)

System. out.println ( "After Memory = r' + rt. freeMemory ( ) ) ;

rt.gc(\; // uma alternativa a System.gco

System.out.println("After GC Memory = " * rt.freeMemoryO );

m@,

doCourlexstuff O; til @

ma

-}lndicava uma

referGncia ativa

.@.,lndica uma

referCncia apagada t

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 substanciallogo 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 niopode confiar em system. gc ( ) para liberar um espago suficiente na mem6ria de modo que nXo precise se preocuparcom a execugeo da coleta de lixo. O exame da certifica$o estari interessado em um comportamento garantido, neo numprov6vel.

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 namem6ria 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 doespago livre na mem6ria deve indicar se ele foi executado. Examinemos o programa:

f . import java.util.Date;2. public class Checkcc {3. public static void main(String [] args) {

4. Runtime rt. = Runt.ime. getRuntime ( ) ;

Page 174: Java - Scjp 5 - Portugues

148 Copitulo 3: AtribuiE6es

15. )

1-6. ]

Agora, executaremos o programa e verificaremos os resultados:

Total J\,rM memory: 1048568

Before Memory = 703008

Aft.er Memory = 458048

After cC Memory = 8L8212

Como podemos ver, o VM realmente decidiu coletar (isto 6, excluir) os objetos qualificados. No exemplo anterior,sugerimos I JVM que executasse a coleta de lixo com 458.048 bytes de mem6ria restantes e ele atendeu nossa

solicitaglo. Esse programa s6 tinha o thread de um usuirio sendo executado, portanto, nio havia nada maisacontecendo 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 utilizadosserlo removidos da mem6ria. A rinica coisa garantida 6 que se voce estiver ficando com muito pouco espago namem6ria, o coletor de lixo ser6 executado antes que uma exceglo outofMemoryException seja langada.

Exercfcio 3-2

Experimente modificar o programa CheckGC colocando as linhas 13 e 14 dentro de um loop. VocA poder6 ver quenem toda a mem6ria 6 liberada com uma passada de GC.

Fazendo uma limpeza antes da coleta do lixo - o m6todo finalize( )A linguagemJava fornece um mecanismo para que algum c6digo seja executado imediatamente antes que um objeto seja

excluidopelocoletordelixo.Essec6digoficar6emumm6todochamado finalize( ) quetodasasclassesherdamdaclasse 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 hicomo contar com ele; enteo, neo insira nenhum c6digo essencial nesse m6todo. Na verdade, recomendamos que

voc6 nlo sobrescreva de forma alguma f inalize ( ).

Cuidados relacionados com finalize( )Hi alguns conceitos relacionados com f inalize ( ) que voc6 precisa lembrar:

I Para qualquer objeto, f inalize ( ) seri chamado apenas umavez (no maximo) pelo coletor de lixo.

r Chamar f inalize ( ) pode resultar em salvar um objeto da exclusio.

Examinaremos essas declarag6es com mais detalhes. Em primeiro lugar, lembre-se que f inalize ( ) 6 umm6todo e qualquer c6digo que voc6 puder inserir em um m6todo conum poderi inserir em f inalize ( ) . Porexemplo, no m6todo f inalize ( ) voc6 poderia escrever um c6digo que retornasse uma refer6ncia ao objetoem questio para outro objeto, duqualficando efetivamente o objeto para a coleta de lixo. Se em algum momentoposterior esse mesmo objeto se tornar novamente qualificado para a coleta de lixo, o coletor ainda poderiprocessar e exclui-lo. No entanto, ele lembrar6 que f inalize ( ) jLf.oi execttado paraesse objeto, e nio processar6o m6todo mais uma vez-

Resumo para a certificagioEste foi um megacapitulo! NXo se preocupe se vocA perceber que precisar6 revisar alguns destes t6picos quandochegar. em capitulos posteriores. Este aqui apresentou muitos conceitos b6sicos que lhe serio rlteis

POStenOrmente.

Comegamos o capitulo revisando a pilha e o heap; lembre-se de que as variiveis locais residem na pilha, e as vari6veis de

instAncias residem, com os seus objetos, no heap.

Revisamos os literais v6Llidos para tipos primitivos e Strings, e depois discutimos os fundamentos da atribuigio de valores a

tipos primitivos e a vari6veis de refer6ncia, al6m das regras para conversXo de primitivos.

Em seguida, discutimos o conceito de escopo, ou "por quanto tempo esta vari6vel viver6?" Lembre-se dos quatro escoposbisicos, do maior para o menor tempo de vida: static, instance, local, block.

Page 175: Java - Scjp 5 - Portugues

JAVA 5 I49

Abordamos as implicag5es de se usar variiveis nio-inicializadas, e a imponincia do fato de que as vari6veis locaisdeaem receber um valor explicitamente. Falamos sobre alguns dos aspectos complicados de se atribuir uma variivelde referAncia a outra, e alguns dos detalhes sobre a passagem de variiveis para m6todos, incluindo uma discussiodo "sombreamento".

O t6pico seguinte foi a criagio de arrays, no qual falamos sobre declarar, construir e inicializar arrays uni e multidimensionais.Falamos sobre arrays an6nimos e sobre arrays de referOncias.

Em seguida, revisamos os blocos de inicializagio est6ticos e de instAncias, qual a apar6ncia deles e quando eles sio chamados.

Caramba!

Continuamos o capitulo com uma discussio das classes wrapper, usadas para se criar objetos imut6veis que armazenem umtipo 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, taiscomo 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 dem6todos 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. Aprendemoique, no fim das contas, a JVM far| a coleta de lixo quando ele quiser. VocA (o programador) pode pedir que sejafeita uma coleta, mas nio pode forgiJa. Falamos sobre a coleta de lixo aplicar-se apenas a objetos que estioqualificados, e que qualificados significa "inacessiveis para qualquer thread ativo". Finalmente, discutimos oraramente rltil m6todo f inalize ( ), e o que vocA precisari saber sobre ele para o exame. No fim das contas, umcapitulo fascinante.

{ EXERCICIO RAPIDOEis alguns dos pontos principais deste capitulo.

Pilha e HeapE Asvariiveis locais (vari6veis de m6todo$ residem napilha.

E Os objetos e as suas variiveis de instincias residem no heap.

Literais e Conversio de Tipos Primitivos (Objetivo 1.3)D Osliteraisintegerpodemserdecimais,octais(p.ex.013) ouhexadecimais(p.ex.Ox3d).

D Os literais para longs terminam com L ou 1.

D Os literais float terminam com F ou f , e os literais double terminam com um digito, com D ou com d.

E Os literais booleanos sio true e f alse.fl Os literais para chars sio um 6nico caracrer dentro de aspas simples: 'd'.

Escopo (Objetivos 1.3 e 7.6)E O escopo refere-se ao tempo de vida de uma vari6vel.

E Existem quatro escopos bisicos:

E As variiveis estiticas vivem basicamente pelo mesmo tempo que as suas classes.

0 As vari6veis de instAncia vivem pelo mesmo tempo que os seus objetos.

fl As vari6veis locais vivem pelo mesmo tempo que os seus m6todos na pilha; entretanto, se o m6todo chamar outrom6todo, elas ficam temporariamente indisponiveis.

D As vari6veis de bloco (p.ex. em um f or ou em um if) vivem at6 a conclusio do bloco.

Atribuig6es B6sicas (Objetivos 1.3 e 7.6)tr Os literais de integers sio implicitamente ints.E As express6es integer sempre geram um resultado com o tamanho de int, nunca menor.

B Os nrimeros de ponto flutuante sio implicitamente doubles (64 bit$.

Page 176: Java - Scjp 5 - Portugues

150 Copftulo 3: AtribuiE6es

E Diminuir um tipo primitivo causa o corte do.s bits de ordem mais alta.

D Atribuig&s compostas (p.ex. + =) realizamumaconversio autom6tica.

El Uma vari6vel de refer6ncia armazena os bits que sio usados para se referir a um objeto.

E As varilveis de refer6ncia podem referir-se a subclasses do tipo declarado, mas nio a superclasses.

E Aosecriarumnovoobjeto,p.ex.,Button b = new ButtonO;,tr6scoisasacontecem:

E Cria-se umavari6vel de refer6ncia chamada b, do tipo Button

B Cria-seumnovo obietoButton

tr Atribui-se o objeto Button )variivel de refer6nciab

Usando uma yari6vel ou elemento de array que nao tenha sido inicializado ou atribuido(Objetivos 1.3 e 7.6)D Quando um array de objetos for instanciado, os objetos do array nio serio instanciados automaticamente, mas todas as

refer6ncias receberio o valor padrio nul1.

tr Quando um array de tipos primitivos for instanciado, todos os elementos receberio seus valores padrio.

tr As vari6veis de insAncia serio sempre inicializxlas com um valor padrlo.

E As vari6veis locais/autom6ticas/de m&odo nunca recebem um valor padrio. Se voc6 tentar usar uma antes de inicializ6-la, receberiumerro do compilador.

Passando vari6veis para os m6todos (Obietivo 7.3)D Os m6todos podem usar tipos primitivos e/ou referAncias a objetos como argumentos.

D Os argumentos dos m6todos sio sempre c6pias.

D Os argumentos dos m6todos nunca sio objetos reais (podem ser refer€ncias a objetos)

0 Um argumento primitivo 6 uma c6pia totalmente desvinculada do tipo primitivo original.

tr Um argumento de refer6ncia 6 outra c6pia de uma refer6ncia ao objeto original.

E O sombreamento ocoffe quando duas vari6veis com diferentes escopos companilham o mesmo nome. Isso leva a bugsdificeis de encontrar, e a quest6es do exame dificeis de responder.

Declaragio, construgio e inicializagilo de arrays (Obi. 1.3)O Os arrays podem conter tipos primitivos ou objetos, mas o array propriamente dito sempre ser|umobjeto.

D Quando vocd declarar um array, os colchetes poderio ficar i esquerda ou i direita do nome.

tr Nio 6 considerado vilido incluir o tamanho de um array na declaraSo.

E Voc6.precisa incluir o tamanho de um array quando o construir (usando new) a menos que esteja criando um arrayanorumo.

E Os elementos de um array de objetos nio sio criados automaticamente, embora os elementos de arrays primitivosrecebam valores padrto.

fl Voc€ receber6 uma excegio NullPointerException se tentar usar o elemento de um array de objetos e esse elemento nioreferenciar um objao reai.

fl Os arrays sio indexados comegando pelo zero.

0 ArraylndexOutOfBoundsException ocorre se vod usar um valor de indice invilido.

B Os arrays possuem umavariivel length, cujo valor 6 a quanti&de de elementos do array.

tr O ultimo indice que voc6 poder6 acessar seri sempre uma trnida& menor do que o tamanho do array.

E Os arrays multidimensionais sio apenas arrays compostos por outros arrays.

E As dimens6es de um array multidimensional podem ter tamanhos diferentes.

E Um array de tipos prirnitivos aceitar6 qualquer valor que possa ser promovido implicitamente ao tipo declarado para oarray. Por exemplo, uma vari6vel q6e pode ser inserida em um array int.

E Um array de objetos pode conter qualquer objeto que passe no teste E MEMBRO (ou instanceof) aplicado ao tipodeclarado para o array. Por exemplo, se Horse estender a classe Animal, entio o objeto Horse poderi ser inserido em umarraydeanimais.

E Se vod atribuir um array a uma referAnc ia de array ji declarada, o array ter6 que estar na mesma dimensXo & refer6ncia ao

Page 177: Java - Scjp 5 - Portugues

JAVA 5 'I5I

qual for atribuido.

D Voc6 pode atribuir um arruy de um tipo a uma refer|ncia de array j6 declarada de um de seus supertipos. Porexemplo, um array Honda pode ser atribuido a um array declarado como tipo Car (supondo-se que Hondaestenda 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 ossupercon$rutores e antes de ser executado o c6digo do construtor.

I Se existirem v6rios blocos init em uma classes, eles seguem as regras indicadas acima, e rodam na ordem em queaparecem no arquivo-fonte.

Usando wrappers (Objetivo 3.1)E As classes wrapper e$io correlacionadas aos tipos primitivos.

E Os wrappers t6m duas fung6es principais:

0 Encapsular tipos primitivos para que possam ser manipulados como objetos;

E fornecer m6todos utilit6rios para tipos primirivos (geralmente convers6es).

U Os construtores wrapper podem usar uma String ou um tipo primitivo, exceto para Character, que s6 podeusar um tipo char.

E As tr€s familias de m6todos mais importantes seo:

E xxxValue ( ) Niousaargumentos, retornaumtipoprimitivo;

D parseXxx ( ) Usa uma String, retorna um tipo primitivo, 6 static e langa a exceEio NFE;

E valueof ( )UsaumaString, retornaumobjeto encapsulado,6 static elangaaexcegioNFE.

D O argumento do radical referencia bases (normalmente) diferentes de 10; a base biniria tem radic a72, oed,: 8 e hex :16.

Boxing (Objetivo 3.1)tr A partir deJava 5, o recurso de boxing lhe permite converter tipos primitivos em wrappers ou convener wrappers em

uPos Prurutrvos automatrcamente.

D Usar : - com wrappers 6 complicado; v/rappers com os mesmos valores baixos (normalmente os menoresque I27) serio : :, rnzs yalores maiores nlo serio ::.

Sobrecarga Avangada (Objetivos 1.5 e 5.4)D A ampliagio de primitivos usa o "menor" argumento de m6todo possivel.

0 Usados individualmente, o boxing e os var-args sio compativeis com a sobrecarga.

Cl Y ocl ndo pofu ampliar de um tipo wrapper para outro. @-Ulf faUra.;

D Voc6 ndo pode ampliar e depois fazer boxing. (Um int nlo pode se tornar um Long.)

O Voc6 pode fazer boingedepois ampliar. (Um int pode se tornar um Object, atrav6s de um Inreger.)

tr Vod pode combinar var-args com a ampliagio ou com o boxing.

Coleta de lixo (Objetivo 7.4)E EmJava, a coleta de lixo fornece um nivel de gerenciamento automatico da mem6ria.

tr A finalidade da coleta de lixo 6 excluir objetos que nio possam ser alcangados.

J 56 a II'/M decide exatamente quando executar o coletor de lixo; voc6 (o programador) s6 pode recomendar queseja feita essa operagio.

E VocA nio tem como conhecer o algoritmo da coleta de lixo.

D Os objetos devem ser co niderados qulifuaiasantes que possam ser coletados como lixo.

E Um objeto est6 qualificado para a coleta quando nenhum thread ativo consegue alcangiJo.

E Para alcangar um objeto, vod precisa ter uma refer6ncia alcanSvel e ativa a esse objeto.

0 Os aplicativos Java podem ficar sem espago na mem6ria.

tr Ilhas de objetos podem ser coletadas como lixo, ainda que refiram-se umas ls outras.

Page 178: Java - Scjp 5 - Portugues

152 Copftulo 3: Atribuig6es

tr Solicite a colea de lixo com System. gc ( ) ; (recomendado).

E AclasseObjectpossuiumm6todo finalize ( ).

tr Om6todofinalize( )temsuaexecugiogarantidaumavez,esumenre,/maae1antesdeocoletordelixoexcluirumobjeto.

E J6queocoletordelixoniotemexecugiogarantida, finalize ( ) podenuncaserexecxtado.

B Voc6 pode desqualificar um objeto para a coleta usando f inal ize ( ) .

Teste Individual

l. Dado:a'laq< Qcnnn {

static int throwero throws Exception { return 42; }

public static void main(String [] args) {

try {

int x = thrower0;

) catch (Exception e) ix++;

) finallY {

System.out.println("x = " + ++x) ;

]]]Qual6 o resultado?

A.x=42B.x=43C.x = 44

D. A compilagXo fdha.

E. O c6digo roda sem nenhuma saida.

2. Dado:class CardBoard {

Short sEory = 5,'

CardBoard go(CardBoard cb) icb = 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?

AOB. 1

Page 179: Java - Scjp 5 - Portugues

JAVAs I53

c.2D. A compilagio falha.

E. Nio 6 possivel saber.

- *r rF. 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,'; }

iclass oefender {

public st.atic void main(String [] args) {

System. out.println (new Alien ( ) . invade (7) ) ;

)

Qual6oreruhadol

,{. many

B. a few

C Acompilagofalha-

D A saida nio pode ser prevista.

E. E langda uma o<cegXo no tempo de execu$o.

4. Dado:1. class Dims {

2. public static void main(String[] args) {

3. inrtJU a= {{1,2,}, {3,4}};4. int[] b = (inttl) atll;5. Object 01 = a,

6. inttl tl a2 = (inrt] [] ) o1;

7. inttl b2 = (int[]) o1;

8. System.out.println(bt1l ) ;

10. ]

Qual6 o resuhado?

L2B.4C f langda uma exce$o em rempo de exeor$o.

D A compila$o falha devido a um erro na linha 4.

E. A compilaglo falha devido a um erro na linha 5.

E A compilagio falha devido a um erro na linha 6.

G A compilagXo falhadevido aum erro na linha 7.

5. Dado:class Eggs {

int doX(Long x, Long y) { return 1-; }

int dox(Iong. .. x) { return 2; }

int dox(Integer x, Integer y) { return 3; }

Page 180: Java - Scjp 5 - Portugues

1 54 Copitulo 3: AtribuiE6es

int doX(Number n, Number m) { return 4; }

public static void main(String[] args) {

new Eggs O .goO ;

]

void go0 {

short s ='7;System.out.print(dox(s,s) + " ");System. out.println (doX (1, I | ) ;

))Qual6 o resultado?

,d118.21,c31-D.4 r-

8.2 3

833G43

6. Dado:class Mixer {

Mi-xer O { }

Mixer (Mi-xer m) { ml- = m; }Mixer m1;

public static void main(string[] argrs) {

Mixer m2 = new Mixer0;Mixer m3 = new ytixer (m2 ) ; m3 . go ( ) ;

Mixer m4 = m3 .m1; m4. go ( ) ;

Mixer m5 = m2.m1; m5.goo;

)

void go() { System.out.print("hi "); }

)

Qual6 o resultado?

A" hiB. 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?

Page 181: Java - Scjp 5 - Portugues

JAVAs I55

A. A compilagio tem sucesso.

B. A compilagio falha devido a um erro apenas na linha 3.

C. A compilaglo falha devido a um erro apenas na linha 4.

D. A compilagio falha devido a um erro apenas na linha 5.

E. A compilagio falha devido a erros nas linhas 3 e 5.

F. A compilagio falha devido a erros nas linhas 3,4 e 5.

8. Dado:class Fizz {

int. x = 5;

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

ftnaL Ftzz f1 = new Ftzz];Ftzz f2 = new Fizz);ELZZ T5 = E'LZZSWIECN\TI,TZ) i

System.out.println((f1 == f3) + " " + (fl-.x == f3.x) );)

A. t.rue trueB. fal-se trueC true falseD. fa]se falseE. Acompila$ofalha.

- '4r | ryr.: E rangaoa uma excegao no tempo de execu$o.

9. Dado:class Knowing t

static final long tooth = 343L;

^F-ts.i^ 1^h^ ^^Tf

tlnnn fnnfh\ I- L4UIU f Vrr\j Uvf u \ rvrry uvvutl/ t

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

hFl n I f^^th \ .eJ u uvrrr. vuu . Pr rrruf

]

)

Qual6 o resultado?

A. 343 340 340

B. 343 340 342

c 343 34L 342

D. 343 341, 340

E. 343 341, 343

E Acompilagofalha.ari'tt.\r E rangact:I uma excegao no tempo de execugio.

Page 182: Java - Scjp 5 - Portugues

156 Copilulo 3: AtribuiE6es

| 0. Quais das afirmativas abaixo s6o verdadeiras? (Marque todas as corretas)A. A chamada ao m6todo f inalize O de um objeto 6 sempre a fltima coisa a acontecer antes de um objeto ser

coletado como lixo.

B. Quando uma variivel da pilha sai de escopo, ela se torna qualificadapara coleta de lixo.

C. Algumas variiveis de refer6ncia residem na pilha, e algumas residem no heap.

D. Apenas objetos que nio tenham variiveis de refer0ncia apontando para eles podem ser qualificados para coletade lixo.

E. E possivel requisitar a coleta de lixo atrav6s de m6todos das classes j ava . 1ang. Runtime ouj ava. 1ang. System.

I l. Dado:1. class Convert {

2. public static void main(String[] args) {

3. Long xL = new Long(456l);4. long x1 = Long.valueOf("123");5. Long x2 = Long.valueOf("L23");6. long x3 = xl,,longValue$;7. Long x4 = xl,.longValue0;8. Long x5 = Long.parselong:("456");

9. long x6 = Long.parselong("123");10. )

l_1. ]

Qual ir6 compilar usandose laval,mx ndocompilari com Javat.4? (Marquetodas as corretas)

A. Linha4

B. Linha 5

C. Linha6

D. LinhaT

E. Linha 8

F. Linha9

12. Dado:1. class Eco {

2. public static void main(stringll args) {

3. Eco e1 = new EcoO;

4. Eco e2 = new EcoO;

5. Eco e3 = new EcoO;

6. e3.e = e2;'7. e1 .e = e3;

8. e2 = nuI1;9. e3 = nul1;

l-0. e2.e = e\;l-1. e1 = nu1l;L2. )

1-3. Eco et

t-4. )

Em que ponto hi apenas um objeto qualificado paracoletade lixo?

Page 183: Java - Scjp 5 - Portugues

JAVA 5 I57

A. Ap6s a execugio da linha 8.

B. Ap6s a execugio da linha 9.

C. Ap6s a execugXo da linha 10.

D. Ap6s a execugio da linha 11.

E. A compilagio falha

F. Nunca nesse programa.a 4t r - r i\r. .tr rangaoa uma excegio no tempo de execugio.

| 3. Dado:1. class Bigger {

2. public static void main(Stringl] args) {

3. // insira o c6digo aqui

4. )q1

5. class Better {

"l . 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, 1

{ q\rql- am 611l- nri hf f \\r? \\ \ . }t vtsLe!.r. t I J

static { System.out.prj-nt("r4 "); }

]

class Hawk extends Raptor {

public staLic void main(String[] args) iqa/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

Page 184: Java - Scjp 5 - Portugues

158 Copitulo 3: AtribuiE6es

D, 11- 14 pre b1 b2 13 r2 hawk

E. 11, 14 pre b2 bI 12 13 hawk

F. pre rL 14 b1 b2 13 12 hawk

G. pre r! 14 b2 bl- r2 13 hawk

H. A ordem da saida nio pode ser prevista.

I. A compilagio falha.

RespostasI D esti correta,avari|vel x s6 est6 no escopo dentro do bloco de c6digo try, mas nXo quando est6 dentro dos blocos

catch ou f inal1y. (Para o exame, acostume-se com esses fechamentos horriveis com ) ) ) .)

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

2. C est6 correta. Apenas um ob.ieto Cardnoard ( c 1 ) est6 qualificado, mas ele tem um objeto wrapper Shon quetamb6m est6 qualifi cado.

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

3. C est6 correta, a compilagdo falha. A declaragio dos var-args est A correta, mas invade usa um tipo shorL, de modo queo argumento 7 precisa ser convertido para esse tipo. Com a conversio, a resposta 6 B, 'a f el'/.

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

4. C est6 correta. Uma ClassCastExcept.ion 6langada na linha 7 porque o1 refere-se a um int [ ] [ ] , e nlo a umint t I . Se a linha 7 fosse removida, a saida seria 4.

A, B, D, E, F e G estio incorretas com base no exposto acima. (Objectivo 1.3)

5. G esti correta. Duas regras se aplicam i primeira chamada a doX ( ) . Nio 6 possivel ampliar e depois fazer boxing de

uma s6 vez, e os var-args sio sempre escolhidos por ultimo. Portanto, vocd nio pode ampliar shorts para ints nemlongs, a fim de fazer boxing deles para Integers ou Longs depois. Mas voc6 pode fazer boxing de shons paraShorts e depois ampli6-los para Numbers, e isso tem prioridade em relagio a usar um m6todo com var-args. Asegunda chamada usa um simples boxing de int para Integer.

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

6. F esti correta. A vari6vel de instAncia m1 do objeto m2 nunca 6inicializad4 enteo, quando m5 tentar us6-la,seri langada uma Nu1 1 PointerExcept ion.

A, B, C, D e E estio incorretas com base no exposto acima. (Ob.ietivo7.3)

7. A estl correta, todas essas declarag6es de arrays sio v6lidas. As linha 4 e 5 demostram que arrays podem serconvertidos.

B, C, D, E e F estio incorretas porque este c6digo compila. (Objetivo 1.3)

8. Aest6 correta. Asrefer€nciasfL,z ef3 apontamtodasparaamesmainstAncia deFizz. Omodificadorfinal assegura que uma vari|vel de refer6ncia nio poderi ser transferida para um objeto diferente, mas f inalnio impede que o estado do objeto se modifique.

B, C, D, E e F estio incorretas com base no exposto acima. (Objetivo7.3)

9. D esti correta. Existem tr0s variiveis long diferentes chamadas tooth. Lembre-se de que voc6 pode aplicaro modificador f inal a vari6veis locais, mas neste caso as duas vers6es de tooth marcadas com f inalnXo sio modificadas. O rinico tooth cujo valor se modifica 6 o que nio est6 marcado com f ina1. Esteprograma demonstra uma mA pritica conhecida como sombreamento.

A, B, C, E, F e G estio incorretas com base no exposto acima. (Objetivo 7.3)

10. C e E estio corretas. Quando um objeto tem uma vari6vel de refer6ncia, essa variivel reside dentro do objeto,no heap.

Page 185: Java - Scjp 5 - Portugues

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.Besr6 incorreta - a coleta de lixo nXo lida com variiveis de pilha. D est6 incorreta porque os objetos podemresidir em "ilhas de isolamento" e serem qualificadas para coleta de lixo. (Objetivo 7.4)

11. A, D e E estio corretas. Por causa dos tipos de retorno dos m6todos, essas chamadas requerem o autoboxing paracompilar.

B, C e F estio incorretas com base no exposto acima. (Objetivo 3.1)

12. Gest6correta. IJmerronalinhal0fazcomquesejalangadaumaNullPointerExcept.ion,porque e2 f.oidefinida como nulL na linha 8. Se a linha 10 fosse colocada entre as linha 7 e 8, entio F estaria correta, porque at6 quea ultima refer€ncia seja anulada, nenhum dos objetos estari qualificado, e, depois de anulada a ultima referAncia, todosos tr& estario qualificados.

A, B, C, D, E e F estlo incorretas com base no exposto acima. (Objetivo 7.4)

13. C e E apresentam sintaxe correta para se acessar um enum a paftir de outra classe.

A, B, D e F apresentam sintaxe incorreta. (Objetivo 1.3)

14. Desticorreta.Blocosinit static sloexecutadosnomomentoemqueaclasse6carregada,eosblocosinitde instAncias rodam logo ap6s a chamada a super ( ) em um constmtor. Quando existem diversos blocos ini t de

um mesmo tipo dentro de uma classe, eles rodam ordenadamente, de cimapara baixo.

A, B, C, E, F, G, H e I estio incorretas com base no exposto acima. Observagio: voc6 provavelmente nio ter6 nenhumaquestao no exame real com tantas opg6es assim! (Objetivo 1.3)

Page 186: Java - Scjp 5 - Portugues

160 Copftulo 3: Atribuiq6es

Page 187: Java - Scjp 5 - Portugues

,rffi

.:,. -

:. :.

,'

ffi,'':

.;

Operadores

I

Oblerlvos pqru ocerllflco96o

I Usondo Ooerodores

t Exercicios r6pidos

P&R Teste individuol

i.i

l:ri

,"

':,,

Page 188: Java - Scjp 5 - Portugues

'162 Copftulo 4: Operodores

Sevoc€tivervai6veis,k6alter6-las.Aumentariseuvalor,assomar6,deslocar6seusbits,asinverter6ecompataxdumas comas outras. Neste capinrlo, voc6 aprender6 como fazer tudo isso emJava. Adicionalmente, voce aprender6 como fazer coisasque provavelmente nurlca usar6 no mundo reil, mas que 6 quase certo de estafem no exame.

Obietivo poro o certificoqdo

Operadores fava (Objetivo 7.6 do exame)7.5 Escreuer aidigo que @lique czffetamente os operadores @rEiados, inc/uindo os de atibuigdo (linitadot a =, *=, -=), os operadoret

aritmdticos (linitados a i, -, +, /, 0k, ++, - -), os operadores de comparagdo (initadw a 1, 1=, ), )=, ==, !=), o operador insanceoJ

os operadores llgicos (linitados a &, l, n, !, &&, I l) e o operador condicional (?) para produ{r un resuhado duelado. Esreuer cddigo que

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, osoperandos silo itens i esquerda ou direita do operador). O resultado damuonadas operag6es 6 um valor booleano ounum6rico. E como voc6 j6szbe qweJaaa ndo d C**,ndo ftcar| suqpreso com o fato de seus operadores nio poderem sersobrecarregados. No entanto, h6 alguns operadores que j6 v6m sobrecarregados:

r O operador * pode ser usado para adicionar um primitivo num6rico a outro, ou para rea)tzar :uma operagdo deconcatenagio se um dos operandos for uma String.

I Os operadores &, I e ^ podem todos eles ser usados de duas maneiras diferentes, apesar de que, nesta verslo do exame,as suas funcionalidades pa:aopengdo com bits nio sio cobradas.

Fique alerta. A parte do exame referente aos operadores e atribuig5es normalmente 6 aquela em que os candidatosconseguem 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 causade uma instrugio de prd-incremento.

Operadores de AtribuigioAbordamos a maior parte da funcionalidade do operador de atribuig6o,"=",no Capinrlo 3. Para resumir:

I Ao se atribuir um valor a um primitivo, o tamanho faz drfetenga. Certifique-se de saber quand o uma corrvetsdo implicitair6 ocorrer, quando a conversio explicita 6 necessiria, e quando poderao ocoffer cortes.

I Lembre-se de que uma variivel de referdncia nio 6 um obf eto; 6 uma maneira de se chegar a um obieto (Sabemos quetodos os leitotes que sZo programadores de C++ estao loucos para nos ouvir dizer "6 um ponteiro", mas nio iremosfazer isso).

I Ao se atribuir um valor aumavai|vel de refer€ncia,o tipo faz diferenga. Lembre-se das regras para supertipos, subtipose arTays.

Em seguida, abordaremos mais alguns detalhes sobre os operadores de atribuigio que caem no exame e, quandochegarmos no Capitulo 7, veremos como o operador "=" trabafhacom Strings (que s6o imut6veis).

OBSERVAQ6BS penrt O EXAME

Ndo derperdice teupo preparando-se para tuipicos que ndo utqam mais no exanel Resumindo, o exame Jaua 5 difere do exame / .4 por eafastar dos bits e se @roxinar da APL Muitos tripicos da uersd.o 1 .4 relacionados a lperadzres flram remouidos do exame, de modo qile neste

capitulo uoc€ IIJAO uenl

I Operadores de mudanga de bit

I Operadores bitwise

I Complementosbindrios

I Assuntos referentes i divisio porzero

Ndo 6 que uns tdpicos ndo s/am importantes, d @enas qae e/es ndo caem mab n0 exane, e nosso objetiuo i nos concentranros no exame.

Operadores de Atribuigio CompostosNa 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 permitemque os digitadores preguigosos economizem algum trabalho de digrtagio. Eis v6rios exemplos de atribuig5es, primeiro semusar um operador composto,

Page 189: Java - Scjp 5 - Portugues

JAVA 5 163

Y = Y - 6;

x = x +2 * 5;

E agora com operadores compostos:

Y-=6;x+=2*5;

As duas ultimas atribuigSes d6o o mesmo resultado que as duas primeiras.

oB SERVA9oBS pene O EXAME

Versduantigasdoexameco/ocaaamumagrandeOnfatenaprueddnciadeoperadoresQono:pualrioresultadode:x=y+++++xfz). Tirando am conhecimento ba$ante bdsico nbre a preceddncia (qae + e f tin prued1ncia sobre * e -, por exemplo), uocd ndo precisard

estudarapreced1ncia de operadoru, exceto ofato de qae, ao asarilm operadorcorrposto, a expreudo no lado direito do = senPre senl aualiada

prineiro. Por exempl0, uoc6 podeia esperar qae

x*=2+5;

fosse aualiada duta forna:

x = (x * 2) + 5; // preced€ncia incorreta

uma ue<que a nuhiplicapdo tdn preced€nda sobre a adigdo. Pordrz, em ueTdisso, a exprer1o ti direita senQre 6 cokcada entrc paftnleses. Eaualiada destafonna:

x = x * (2 + 5);

Operadores de comparagao

O exame aborda seis operadores de comparagio ((, <=, ), )=, == e l-) Os operadores de comparagio sempre resultamem um valor booleano (true ou f alse). Esse valor booleano 6 usado com mais freqri6ncia em testes if , comovemos a seguir:

int x = 8;

r_r (x<v) 1

/ / faz al-go

\)

mas o valor resultante tamb6m pode ser atribuido diretamente a um tipo bool-eano primitivo:

class CompareTest {

public static void main(String [] args) t

booleanb=100>99;System.out.printl-n("The value of b is " + b) ;

]

Java tem quatro operadores de comparagio que podem ser usados para comparar qualquer combinagio de inteiros,nrimeros de ponto fluruante ou caracteres:

I > maior que

I >= maior ou igual a

I < menor que

t <= menot ou igual a

Examinemos algumas comparag6es v6lidas:

class GuessAnimal {

public static void main(String [] args) tString animal = "unknown",.

int weight = 7OO;

char sex = 'm' ;

doubl-e colorwavelength = 1.530;

Page 190: Java - Scjp 5 - Portugues

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 dec ractere com qualquer nrimero (embora nio seia um estilo de programagio adequado). A execugio da classe anterior exibfu6o seguinte:

The animal is a gray elephantMencionamos que os caracteres podem ser usados com operadores de comparagio. Quando compara um caractere comoutfo ou um caractete com um nrimerq a linguagemJava usa o valor Unicode do caractere como o valor num6rico e

compara os nrimeros.

Operadores de igualdade l

J^v^tem tamb6m dois operadores de comparagio (chamados de "operadores de igualdade') que compa:-arndois itenrsemelhantes e retofnam um valor booleano que representa o que 6 verdadeiro sobre os dois itens serem iguais. Essesoperadores sio

I == g"al (tamb6m conhecido como "igual a')

I != difetente (tamb6m conhecido como "diferente de")

Cada compatagio pode envolver dois nfmeros (incluindo o tipo char), dois valores booleanos ou duas vad6veis deteferdncia de objeto. Voc€ nio pode comparar tipos incompativeis, no entanto. O que significaria perguntar se um tipobooleano €igoal,aum tipo char? Ou se um objeto Button 6 igual

^!mafiay String? (Exatamente, neo tem

sentido,e6porissoquen6opodemos faz€-lo).H6guatrotiposdiferentesdeitensquepodemsertestados:

I Nrimeros

I Caractetes

I Tipos booleanos primitivos

I Vari6veis de referdncia de obleto

Por6m, o que o operador == examina realmente? O valor da vari6vel - em outras palavras, o padreo de bits.

lgualdade de tipos primitivosA maioria dos programadotes est6 familiarizada com a compangdo de valores primitivos. O c6digo a seguir mostta algunstestes de igualdade em vari6veis primitivas:

class ComparePrimitives {

public static void main(String, [] args) {

System.out.println("character 'a' == 'a'? " + ('a' == 'a'));System.out.println("character'a' =='b'? " + ('a' =='b'));system.out.println("5 != 6? 't + (5 t= 6)) ;

System. out.println ( "5. 0 == 5L? " + (5. 0 == 5L) ) ;

System.out.println("true == false? " + (true == false) );

I

Esse progtama ptoduzir6. a saida abaixo:

character 'a' == 'a'? truecharacter 'a' == 'b'? false5 l= 6? true5. 0 == 5IJ? Erue

true == false? falseComo podemos ver, se um nrimero de ponto flutuante for comparado com um inteko e os valores forem os mesmos, ooperador == tetotnard true como esperado.

Page 191: Java - Scjp 5 - Portugues

JAVA 5 165

oBsERvAgOBs pene o ExAME

Ndocorfudaodnal=conooperador=--em*maexpressdobooleana.Oc6digoaseguiriuilido:

l]-.booleanb=false;L2. if (b = Lrue) i System.out.println("b is true");l-3. i else { System.out.println(.,b is false,,) ; }

Olhecuidadovmente! Voc6podtfcartentadoapensarqaeauidarcni'b ts faIse", matexamineote$ebooleanodatinha2.Aaari,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$ituigdod0 inal = Pell nperador = = sdfxndona com uaridaeisbooLeanas, jd qile 0 terte if pode vrfeito apeltar em expresrdu booleanas.

Portanto, o aldigo abaixo ndo senl conpilada:

7.intx=1;8.if(x=o) i)

Jd qw x i um inteim (e ndo un booleano/, o resultado de (x = A) ser,i 0 (o resuhado da aaibtig1o) Os inteimt ndo pod.em vrtrvdos onde ttm aalor booleano i esperado, portanto, o aidigo da linba 8 ndofuncionanl a menlr qile sgja aherado de una ahibuigdo (=) pararm tette de tgualdade (= =) como uemot a segxir:

8. if (x == 0) i )

lgualdade de variiveis de refer6nciaComo vimos anteriormente, duas vari6veis de refer6ncia podem apontar para o mesmo objeto, como o o..6o 6. g6digoabaixo 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 como r6nrlo Exit). As vari6veis de refer6ncia podem ser testadas com o operador == para sabermos se estao referenciando umobieto em comum. kmbre-se de que o operadot == estar6 examinando os bits da vari6vel, portantq com relagio is vari6veisde referdncia, se os bits das duas variiveis forem id6nticos, elas estario referenciando o mesmo obieto. Examine o c6digoabaixo:

import java. awt. Button;class CompareReference {

*,,Lli^ ^r^el-1,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

Bt.. s$digo cria tr€s vari6veis de refer€ncia. As duas primeiras, a e b, sio objetosJButton diferentes, que por acaso tem omesmo nome. A terceira r,zri6vel de referdncia, c, 6 inicializadapatarcferenciar o mesmo objeto que a esta referenciando.

Quando esse prograrna for executado , a seida a seguir ser6 produzida:

Is reference a == b? falseIs 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, ondeabordaremos o m6todo equals ( ) (nio confundfu colr:;, o operadorde igualdade que examinamos aqui).

lgualdade para EnumsDepois que vocd declarou um enum, ele nio pode ser expandido. Em tempo de execugdo, nio 6 possivel criar novasconstantes enum. E claro que voc€ pode ter tantas vari6veis quanto quiser apontando para uma dada constante enum, deforma que 6 importante que se possa comparar duas vari6veis de refer6ncia enum para ver se sio "iguais", ou seja, se elas sereferem i mesma constante enum. Voc€ pode usar ou o operador == ou o m6todo equals ( ) para determinar se duasvari6veis est6o se referindo i mesma constante entrm:

Page 192: Java - Scjp 5 - Portugues

166 Copitulo 4: Operodores

class EnumEqual 1

anrrm (-nl ^- [ F--r-:E.rJ, }JLUE] // ; 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 }

)iO"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 instanceofO 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 obfetoreferenciado pela vari6vel i esquerda do operador passaria no teste E-MBMBRO do tipo de interface ou classe do ladodireto do operador (o Capinrlo 2 abordou os relacionamentos E-MEMBRO com detalhes). O exemplo abaixo:

public static void main (string IJ args) {

afrih^ c - nau' at-rina/trf^^r'\9u!f11: v9rrllY \ lvv / ,

4 + | ^ : F^+-h^6^f Cf r.i na\ If! \E frrDudrrus9r oLrrrrY,/ t

System.out.print ( "s is a String" ) ;

]

)

edbeisto:sisaStringMesmo se o objeto testado nio for realmente uma instanciagio do tipo de classe que estiver do lado direito do operador,instanceof ainda retornari verdadeiro se o obfeto puder ser atribuido a esse tipo.

O exemplo a seguir demonstra o teste em um obf eto com o uso de instanc eof ,p^r saber se ele 6 a instAncia de umdos seus subtipos, antes de se tentar urna conversio "redutora":

class A i )

cl-assBextendsA{public static void main (String IJ args) {

AmyA=newBO;m2 (myA) ;

]

public static void m2 (A

if (a instanceof B)

( (B) a) . doBstuff ( ) ;

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

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 operadorinstanceof junto ao tipo Obj ect, da seguinte forma,

a){

/ / convertendo uma refer6ncia/ / em ttma refer6neia B

A

Page 193: Java - Scjp 5 - Portugues

JAVA 5 167

Bb=newBO;if (b insranceof Object) {

System.out.print("b is definitely an Object,,) ;i

que edbit6:

b is definitely an Object

oBSERVA9oSS pARA O EXAME

Pron'm perguntas eom instanceof que testem u um objeto i a instincia de lma interface, qaando a classe do objxo for implenentadaindiretamente. Una implenentagdo indinta ocore quando ma das superc/astes do oQeto implementa una intetface, ,^ i pnlpio classe dainstitcia ndo ofaq- por exenplo,

interface roo { }

class A implements Foo { }

classBextendsAi )

Aa=newAO;Bb=newBO;

ot rerultados a seguir rcrdo aerdadeims:

a instanceof Foo

b instanceof A

b instanceof Foo // implementado indj-retamente

Un objeto seri considerado de un tipo de inhrface especifn (igfieando que pasuni no te$e lnsEanceof) se algama de suaswperclasnt implementar a inteface.

Al6m dissq 6 vilido testar se a refer6ncia de um objeto nu11 6 a instincia de uma classe. Isso sempre resultar6 emf aI se, € claro, Por exemplo:

class InstanceTest {

public static void main(String [1 args) tString a = null;boolean b = nul1 instanceof String;boolean c = a instanceof String;System.out.println(b + " " + c) ;

)

)

exibe isto: f al, se f al- se

Erro de Compilagio de instanceofNio 6 possivel usar o operador instanceof para testar em duas hierarquias de classes diferentes, Por exemplo, oseguinte c6digo ndo comptlatil:

class cat { }

class Dog {

public static void main(String tl args) {

Dogd=newDogO;System.out.println (d inst.anceof Cat) ;

)

)

A compilagio fdha - d iamais poder6 se referir a um Cat, ou a um subtipo de Cat.

Page 194: Java - Scjp 5 - Portugues

168 Copirulo 4: Operodores

oBSERVAQ6ES pene o EXAME

I-embre-v que os aralr sdo objetos, mesmo quando armaqenam tipos prinitiuos. Procure ddigot qae Po$am ter e$a @at€ncia na petganta:

int [] nums = new int [3] ''

if (nums inst.anceof object) { } tt o resultado 6 true

Um anal rcnl rcmpre uma instdncia de Object. paalquer aray

A Tabela 4-1 resume o uso de instanceof presumindo-se o seguinte:

interface face { }

class Bar implements Face{ }

class Foo extends Bar { }

Iobelo 4-1 Operondos e resultodos do uso do operodor instanceof

Primeiro opetando(refer€ncia sendo testada)

Opemndo de instanceoj(tipo que compararemoscom a tefer€ncia)

Resultado

null Qualquer tipo de interface ou classe false

instincia de Foo Foo, Bar, Face, Obiect

instincia de Bar Bar, Face, Object

instincia de Bar Foo false

Foo[ ] Foo, Bar, Face false

Foo[ ] Object

Foo[1] Foq Bar, Face, Object

Operadores aritm6ticos

Temos certeza de que vocd est6 familiaizado com os operadores aritrn6ticos b6sicos.

I + adiglo

I - subtragio

I x multiplicagio

I / divisio

EIes podem ser usados da maneira padrio:

int x = 5 * 3;

intY=x-4;system.out.println("x - 4 is " + y); // Exibir6 11

O Operador Resto (o/o)

Um operador com o qual vocd pode n6o estar familiaizado 6 o operador de rcstooh. O operador de resto divide ooperando 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

)

Page 195: Java - Scjp 5 - Portugues

JAVA 5 169

A execugSo da classe MathTest exibiri a linha a seguir:

The resul-t of 15 ? 4 is the remainder of 15 divj-ded by 4. The remainder is 3

(I-embre-se: As express6es sio avaliadas da esquerda p an ^

dlteita,por padrio. Voc6 pode modificar essa seqriencia, oupmceddncia, adicionando parenteses. Lembre-se tamb6m de que os opetadores *, / e %o tdm maior preced€ncia do que osoperadores * e -.)

Operador de concatenageo de stringsO sinal de adigdo tambdm pode ser usado para concatenar duas strings, como vimos anteriormente (e com certeza veremosde novo):

String animal = "Grey " + ..elephant,,,.

A concatenagZo de Strings se tornari interessante quando voc6 combinar nirmeros com obietos String. Vedfique o c6digo a seguit:

String a = "String";inl- l.r - ?.

i-nt c = 7,'

System. out.println (a + b + c) ,.

O operador * atuafi, como um sinal de adigZo quando somar as vari6veis int de b + c? Ou ftatara 3 e 7 comocaracteres e os concatenard individualmente? O resultado ser6 Stringl O ou St.ring3 7? Certo, voc€ teve temposuficiente para pensar sobre isso. Os valores int foram simplesmente tratados como caracteres e acrescentados i direitada string. Portanto, o resultado 6:

String3 7

De forma que poderiamos ler o c6digo anterior assrm:

"Comega com a String a, "String", e adiciona o caractere 3 (o valor de b) aela,pataproduzir uma nova string,"String3",adicionando,ent6o,ocaractereT (ovalordec)aoresultadoparaproduziroutastri.ng,"string3?",eexibi-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 deadigio, dado que os dois operandos sio valores int. O ponto chave aqui 6 que, dentro dos pardnteses, o operando daesquerda nio 6 uma String. Se fosse, o operador I execttaiaaconcatenag6o de Strings. O c6digo anterior pode serlido da seguinte forma:

"Soma os valores de b + c, em seguida, converte a soma em uma string e ^

corrc tena com a string davai|vela".

A regra a lembrar 6:

Se um dos operandosfor ama String, o operador I atuari c0m0 um operador de concatenagdo de SLrings, Se ot dois @erandotforem nilrterot, o operador * funcionani como o operador de adipio.

Em algumas situag6es voc6 poderi ter problemas para descobrir se, digamos, o operador da esquerda 6 ou nio umaString. No exame, nio espere que isso seja 6bvio. (I.{a verdade, i6 que mencionamos nisso, nunca espere que seja 6bvio).Examine o c6digo a seguir:

System.out.println (x.foo O + 7) ;

Voc6nioter6meiosdesabercomoooperador* est6sendousadoat6quedescubraoqueom6todo foo ( ) tetotnarilt,Se retornar uma SLring, entio,T seri concatenado a string retornada. Mas se f oo ( ) retornar um nfmero, ooperador* serdusadoparasomaro algarismo 7 comovalorretornadopor foo ( ).Finalmente, voc€ ptecisa sabet que 6 v6lido mistutar o operador aditivo composto (*=) com Strings, desta forma:

String s = \\A23"i

s += "45";s += 67;

System. out. printl_n (s) t

Umavez que nos dois casos o operador += foi usado, e o operando da esquerda era uma String, ambas as operagdes foramconcatenag6es, resultando em

L234567

Page 196: Java - Scjp 5 - Portugues

I Z0 Copitulo 4: Operodores

oBSERVAQoTSpeneTXAME

Se aocd ndo compreendtr eomo a couatenaj1o de Stringsfunciona, principalmente dentm de ma instrufio de saida, podeni realmente ser mal

sucedido tt7 examq mesmo y soaber o retto da reposta i pergunta! Ji que tantas petglntat indagam, "pual rcni o resultado?", uoc| ptvcisa

taber tdo s6 qual a saida do ctidigo que eftiuer rcndo mas tambdm c0m0 esse resultado rcni. exibido. Mesmo bauendo pelo menot

neia di{a d.e peryuntas que nriarAo diretamente seu conhecimento em strings, a eoncatenagdo de ftrings @ancenl em outras petguntas de

cada objetiuo. Faga um teste! Por exenpk, uoc6 pode aer uma linha como

int b = 2;

System.out.print.ln(*\r + b + 3);

qae exibiri

z5

mas se a inshtgdo de saidafor alterada para

System.out.println(b + 3) ;

entdo, o resultado serti 5.

Acr6scimo e decr6scimoA 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 i2. static int PIaYers = 0;

3. public static void main (String [] args) {

4. System.out.println("players online: " + players++);

5. System.out.println("The value of players is " + players);6. System.out.println("The value of players is now " + ++players);

7. )

8. )

Observe que na quarta linha do progtam ,o operador de incremento esta depois d^v^i6vel players. Isso significa que

estamos usando o operador p6s-fixado, o que far6 com que a variivel players seia aumentada em umavnidade, mat

sonente dEois que nu aabrfor uvdo na expresdo. Quando executarmos esse Programa, ele exibir6 o seguinte:

?java MathTest

players online: 0

The value of players is 1

The value of players is now 2

Observe que quando avai6vel6 exibida na tela, primeiro informa que o valor 6 igual a 0. J6 que usamos o operador de

incrementop/r-fxado,oacr6scimondoocouer6.at6omomento ap6savai6velplayers serusadanainstrugiodesaida.Entendeu? A paniculapris de p6s-fixado significa depois. Allnha seguinte, a de nri.mero 5, n6o aumenta o valor de play-ers ; apenas o exibe na tela, portanto, o valor rec6m-aumentado a ser exibido ser6 1. A linha 6 aphca o operador pre-fxado

a players, o que significa que o acr6scimo ocortetS. antesque o valor da van6velseiavsado (pMsigrtrfrcz antet). Portantq a

saida ser6igaal a2.

Espere por perguntas que combinem os operadores de incremento e diminuigio com outros operadores, como noexemplo abaixo:

irlLx=2;int Y = 3t

if ((Y -= x++) | (x < ++Y) ) {

System.out.println(<x = < + x + < y = < + y);

)

Page 197: Java - Scjp 5 - Portugues

JAVA 5 17]

Oc6digoanteriorexibirix = 3 y = 4

Voc6 pode ler o c6digo assim: "Se 3 for'rgoaIa2 OU menor do que 4..."

Aprimeiraexpresslocompar^x ey,eoresultado6false,potqueoacr6scimodex n6ooconer6antesqueotestedooperador == 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,demodo que a instrugZo de saida ser6 executada.

OBSERVAQ6ES pene O EXAME

Pmcare petgantas qlrc usen ot operadoret dc inmmento e dininligdo em uma aaridae/ f inal-,. Jd que as uaridaeis f i na I n6o podem seraheradas, os operadoret de inmmento e dininuQdo ndo poderdo ser asados com eks e qraQuer hntatiua defaTgr ilro wvltari em am ero docompilador. O aidigo a nguir ndo nni co@ilada,

finalintx=5;int y - x++,.

epmdt$ni o erm

Test.java:4: cannoL assign a value to final variable xint y = x++iVoc6 pode esperar uma violagio como essa camuflada em um trecho complexo de c6digo. Se identifici-la, saber6 que oc6rligo 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 osea conltecinento sobre o modificador f inal.

Operador condicionalOoperadorcondicional 6umoperadortemirio(temtr€soperandos)usadoparaavaliarexpress6esbooleanas demodosemelhante iinstrugio if, exceto por,emvezde executar um bloco de c6digo se o resultado do teste for true, atdbuirum valor i vari6vel. Em outras palavras, o objetivo do operador condicional 6 decidir qual dos dois valores atribuir a umavariivel. Ele 6 constnrfdo com os simbolos ? (ponto de interrogagio) e : (dois pontos). Os pardnteses sio opcionais. Suaestrutura 6 a seguinte:

x = (expressdo booleana) ? valor a atribuir se true: valor a atribuir se f al se

Examinemos um operador condicional no c6digo:

class Salary ipublic static void main(String IJ args) {

i-nt numOf Pets = 3;

String status = (numOfPets<4)?,,Pet limit not exceeded,,:,,too many pets,,;System.out.println(.'This pet status is '. + status) ,.

)

Voc6 poderia l.r o sfdigo anteriot assim:

"Configura numOf Pets igual a 3. A seguir, atdbui uma String avati|vel starus. Se numOf Pets for menor do que4, atibur6"Pet limit not exceeded"; do contr4rio, atibwrd"too many pets".O operador condicional comega com uma operagdo booleana, seguida de dois valores possiveis paraavai|veld,esquerdado 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 aninharoperadotes 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",.

Page 198: Java - Scjp 5 - Portugues

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 L6gicosOs 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 umou outro "ligado" ( | ), "" exatamente 116 "ligado" (^). A prop6sito, se rodarmos o c6digo anterior, teremos

015 1

Tendo dito tudo isso sobre operadores bitwise, o principal a se lembrar 6 isto:

OS OPERADORES BITWISE NAO CEPU NO EXAME!

Entio por que falamos deles? Se cair nas suas mios um livro antigo de preparagio para o exame, ou se encontrar alguns

.*"-.i simulados que ainda nio foram devidam ente atualizados, voc€ poder6 se deparar com quest6es envolvendo

operag5es bitwise. A nio ser que se sinta tio culpado a ponto de achar que merece esse tipo de punig6o, pode ignorar esse

tipo de questeo simulada.

Operadores L6gicos de AbreviagioHd cinco operadores l6gicos no exarne que sio usados para avaltar instrug6es que contenham mais de uma expressio

booleana. Desses cinco, os mais comumente usados sio os dois opetadotes l6gicos de abreriagAo. Sdo eles:

r && Edeabreviagio

I | | OU de abreviagio

Eles sio usados p^t iunt?Lrpequenas express6es boOleanaS a fim de formar express6es bool-eanaS maiotes' Os

operadores && e | | ava1am somente valores booleanos. Para uma expressio E (&&) ser verdadeira, ambos os

operandos ptecisam ser true - pot exemplo,

if ((2 < 3) && (3 < 4)) { }

A expressio anterior s6 6 true, porque tanto o operando um (2 < 3) quanto o operando dois (3 < 4) slo true.

O recurso de abreviagdo do operador && consiste no fato de ele ndo perder sea tempo em aua/iapder inilteis. O operador de

abrcviagdo && avalar|o lado esquerdo da operagio primeiro (operando um) e se esse operando tiver um resultado f a}se,ele nio examinar6 o iado direito da equagio (operando dois), ]6 que o operador saber6 que a expressio completa neo ser6

u! uc.

uI4>D lUYrUAf I

public static void main(String [] args) {

boolean b = true && fal-se,'s\/qram nrrt-.println("bool-ean b = " + b) ;

l

)

Quando executarmos o c6digo anterior, obteremos:

Page 199: Java - Scjp 5 - Portugues

JAVA 5 I73

boolean b = falseO 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 | | nioperder6 tempo examinando o lado direito da equaglo. No entanto, se o primeiro operando for f alse, o operador tera queavaliar o segundo operando para saber se o resultado da operagio OU ser6 L rue ou f a l- s e. Pteste bastante atengao noexemplo a seguit; voc6 veri algumas pefguntas como esta no exame:

1. class TestOR {

2. public static void main (String [] args) t

3. if ((isrrsmall(3)) ll (isrrsmall(7))) {

4. System.out.println("Rqsu1t is true");J

6. if ((isrrsmall(6)) ll (isrrsmall(9))) t

7. System.out.println("Rsgult is true");8. ]

e. )

10.

l-1. public static boolean isltSmall(int i) {

L2. if (i < s) t

13 . System. out .println ("i < 5" ) ,.

]-4. return true;r_5. J erse t

l-6. System.out.printLn("i >= 5");L7. return false;18. )

t-e. )

20. )

Qual ser6 o resultado?

? java TestOR

1<5

Result is truei>=5

Aqui est6 o que aconteceu quando o m6todo main ( ) foi executado:

1. Quando chegamos i linha 3, o pdmeiro operando da expressio | | (em ouuas palavras, o lado esquerdo da operagioI l) foi avaliado.

2 O m6todo isltsmall- (3 ) foichamado, exibiu "i < 5" eretornou uerdadeiro.

3. J6queoprimeiroopetandodaexpressio ll,dalinha3,6igalatrue,ooperador llnioavaliar6osegundooperando. Portanto, nunca veremos a frase "i >= 5", que teria sido exibida caso o segundo operando fosse avaliado(chamando isItSmall (7 ) ).

4. A linha 6 set6,avaladaagora, comegando pelo primeito operando da expressio | | .

5. Om6todo isItSmall (6) 6chamado,eibe "i >= 5"eretorna faIse.6. J6queoprimeiroopetandodaexpressio ll,dalinha6,6false,ooperador llnlopoder6ignorarosegundo

operando; ainda h6 uma chance da expressio ser 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 nuncaser6executada.

oBSERVAQ6ES pene O EXAME

Osoperadoret &&e ll sdfuncionamcomoperandosbooleanos. Oexamepodetentarengand-lo,usandointeiroscrtltesseroperadoret;

Page 200: Java - Scjp 5 - Portugues

174 Copitulo 4: Operodores

if (s && 6) t )

onde parece que estawts teutando usar am operador bit a bit E nos bits que representam os inteiros 5 e 6, mas o cfidigo lteln Tresmo

seni compilado.

Operadores l6gicos (que nio sio de abreviagio)Existem dois operadores l6gicos que fio sdo de abreiagdo.

I &Endo-abreviado

I I OU nio-abteviado

Esses operadores s6o usados em expressdes l6gicas, assim como os operadores && e | | ; por6m, j6 que ndo sdo osoperadores de abreviagio, aualiardo os dois ladw da exprusdo, semprclBles serio ineficientes. Por exemplo, mesmo se o primeirooperando (ado esquerdo) de uma expressio & for f al se, o segundo tamb6m seri avahado - ainda que agora tenha ntonado impossiuel o resultado serErue/E o operador I ser6 ineficiente na mesma medida; se o primeiro operando for true,ele a;nda dati prosseguimento e avahatS" o segundo operando, mumo quando souber q*e a expressdo seri Erue.

No exame, voc€ veri muitas perguntas usando tanto operadores l6gicos de abrciagdo quanto os que nio usam a abreviag6o.Voc€ ter6 que saber exatamente quais opetandos sefao avaliados e quais ndo serlo, jique o resultado variar|se o segundoopetando da expressio for ou n6o avaliado:

1nt z = 5;

if(++z r 5 (ll ++z > 6) z++i // z = 7 depois deste c6digo

contra:

int z = 5;

if (++z > 5 | ++z > 6) z++; // z -- 8 depois deste c6digo

OperadoresL6gicos ^ e!Os dois ultimos operadores l6gicos no exame s6o

I ^ OU exclusivo (XOR)

I !inversiobooleana

O operador ^ (OU exclusivo) avalia somente valores booleanos. O operador ^ relaciona-se com os operadores de nio-abreviagio que acabamos de revisar, no sentido de que sempre ava)ia ambot os operandos, o do lado direito e o do lado

esquerdo, em uma expressio. Pata uma expressio OU exclusivo ( ) set verdadeira, EXATAMENTE um operando precisa

ser Lrue - por exemplq

system.out.println("xor " + ( (2<3) ^ (4>3) ) );produz asuda; xor falseA expressio actma avaJia como f al se porque TANTO o primeiro operando (2 < 3) quanto o segundo (4 > 3) avdtamcomo crue.

O operador ! (inversio booleana) retorna o oposto do valor atual de um booleano:

if ( l (? == 5) ) { Sysfem.out.println("not equal") ; }

pode ser lido como "se nio for verdade que 7 == 5", e a instrugio produz esta saida:

not egual

Eis um ouuo exemplo usando booleanos:

boolean t = true;boolean f = false;System.out.prinLln("! " + (t & !f) + " " + f);

produz asuda:

! true falseNo exemplo anterior, repare que o teste & teve sucesso (exibindo true), e que o valot da variavel booleana f n6o se

modificou, de modo que ela exibiu f alse.

Se voc6 estudou este capinrlo atentamente, deve tet obtido uma compreensio s6lida sobre os operadoresJava, e dever6

saber o que significa igualdade, quando seu conhecimento sobre o operador == for avaliado. Recapitr:lemos os Pontos

Page 201: Java - Scjp 5 - Portugues

JAVA 5 I75

importantes do que voc€ aprendeu neste capitulo.

Os operadores l6gicos (&& e I l) s6 podem ser usados para avaliar duas express6es booleanas. A difetenga entre && e

& 6 que o operador && n6o se preocupari em testar o operando direito, caso o esquerdo for avaliado como f aI se, pois oresultado da expressio && nunca pode ser true. A diferenga entre | | e | 6 que o operador | | n6o testar6 o operandodireito se o esquerdo for avaliado como true, porque o resultado i|setkrcconhecido como true nesse momento.

O operador -- pode ser usado p^r comp^rar valores de tipos primitivos, mas tamb6m pode ser empregado para

determinar se duas variiveis de refer6ncia referenciam o mesmo objeto.

Ooperadorinstanceof 6usadoparadeterminarseoobjetosendoreferidoporumavari6velderefer€nciapassanoteste E-UM para um tipo especificado.

Ooperador* 6sobrecarregadopanteahzartatefasdeconcatenaglodeStrings,epodeconcatenartamb6mStringscom tipos primitivos, mas curdado - essa operagio pode ser complicada.

O operador condicional (tamb6m conhecido como "operador temirio') tem uma sintaxe incomum, com tres operandos -nio a confunda com uma instrugio assert complexa.

Os operadores ** s - - sereo usados em todo o exarne, e voc6 deve prcstzraatengdo a se eles s6o prefixados ou posfixadosi varidvel que esti sendo atuaJizada.

Prepare-se para muitas perguntas no exame envolvendo os t6picos deste capihrlo. Mesmo em perguntas que testarem seu

conhecimento referente a outro obfetivo, o c6digo freqiientemente estar6 usando operadores, atribuig6es, passagem deobjetos e tipos primitivos, e assim por diante.

,/ Exercfcios r6pidosAqui estlo alguns pontos-chave de cada segio deste capitulo.

Operadores de comparageo (Objetivo 7.6)E Os operadores de compangdo sempre resultam em um valor booleano (t.rue ou f alse).El H6 seis operadores de comparagao: ), )=, (, (=, == s l=. Os dois ultimos (-- .l-) sio, is vezes, chamados de

operadores de igualdade.

Q Quando compata car cteres, a linguagemJava usa o valot Unicode do caractet como o valor num6rico.

fl Operadores de igualdade

E Quatro tipos de itens podem ser testados: nirmeros, caracteres, booleanos, vari6veis de referdncia.E Hi dois operadores de igualdade: == s l=.

Q Ao comparar vai|veis de refer€ncia, == retotna true somente se ambas as refer€ncias apontatemparao mesmoobjeto.

Operador instanceof (Objetivo 7.6)E instanceof s6 6 usado com variiveis de refer6ncia e verifica se o obieto 6 de um tipo especifico.

EI O operador instanceof s6 pode ser usado par^testr objetos (ou valores nuI1) confrontando-os com tipos declasse que esteiam na mesma hieratquia da classe.

E Para intedaces, um obieto passa no teste instanceof se alguma de suas superclasses implementar a interface dolado direito do operador instanceof .

Operadores aritm6ticos (Objetivo 7.6)Cl H6 quatro operadores principais: adigio, subtragio, multiplicaglo e divislo.

E O operadot de testo (o/o) rctotnao resto de uma divis6o.

El As express6es sio avaliadas da esquerda p ata a dtreita,a n6o ser que voc€ adicione par6nteses, ou que alguns operadoresna expressio tenham maior preceddncia do que outros.

f,l Os operadores *, / e %o t6m maior preceddncia do que * e -.

Operador de concatenageo de strings (Objetivo 7.6)f,l Se um dos operandos fot uma String, o operador * concatenat6" os operandos.

B Se os dois operandos forem num6ricos, o operador * somatl os operandos.

Page 202: Java - Scjp 5 - Portugues

176 Copitulo 4: Operodores

Operadores de acr6scimo/decr6scimo (Objetivo 7.6)D O opetador pr€-fixado 1+ + e -_) seri executado antes do valor ser usado na expressio.

E O operador p6s-fixado 1++ e --) ser6 executado depois que o valor for usado na expressio.

E Em qualquer expressiq os dois operandos sio avaliados integralmente antes que o operador se ia aphcado.

O O valor das variiveis f inal nio pode ser aumentado ou diminuido.

Ternirio (operador condicional) (Objetivo 7.6)D Retorna um entre dois valotes baseando-se nos casos de uma expressi.o booleana ser true ou f alse.E Retotna o valor depois de ? se a expressio for t rueE Retorna o valor depois de : se a expressio for f a1se.

Operadores l6gicos (Objetivo7.6)E O exame aborda seis operadores l6gicos: &, l, ^, !, && e | | .

D Os operadores l6gicos trabalham com duas expressSes (exceto ! ) que devem resultar em valores booleanos.fl Os operadores && e & retornario Erue somente se os dois operandos forem uerdadeiros.

E Os operadores | | e I retornario true se um ou os dois operandos forem uerdadeims.

Q Os operadores && e | | sio conhecidos como operadores de abreviagio.

D O operador && ndo avahard o operando direito se o esquerdo for f a 1 se.

E O operador | | ndo avahat6ooperando direito se o esquerdo for true.fl Os operadores & e I sempre avallamos dois operandos.

Q O operador ^ (chamado de "XOR l6gico') retorna t rue se exatamente um operando for verdadeiro.

E O operador I (chamado de operador de "inversio'), retorna o valor contr6rio do operando booleano que o precede.

Teste individual

l. Dado:class uexy {

-,,L1 I ^ ^!-+i ^ -"roi-d main (Srring [] args) {

Integer i = 42;

String s = (i<40) ?"1ife": (i>50) ?"universe" t"everything";System. out.prinLln (s) ;

i)

Qual 6 o resultado?

A. nullB. lifeC. universeD. everythingE. Acompilagio falha.

E E langada uma excegio no tempo de execugio.

2. Dado:1. class Example {

2. public static void main(StringlJ args) {

3. Short s = 15;

Page 203: Java - Scjp 5 - Portugues

JAVA 5 I77

4. Boolean b;

5. // insira o c6digo aqui

o. l

7. \

Qual opgio, inserida indepentemente na linha 5, ir6 compilar? (I\zlarque todas as corretas)

A. b = (Number instanceof s) ;B. b = (s instanceof Short);C. b = s. instanceof (Short) ;

D. b = (s instanceof Number);

E. b = s. instanceof (Object) ;

E b = (s instanceof String);

3. Dado:1. cl-ass Comp2 i2. public st.atic void main(Stringtl args) t3. fl-oat f1 = 2.3f ;

4. floar n il f2 = {{.42.0f1 , {t.tt, 2.3tll , {2.6f., 2.tf}} ;

s. float tl t: = {z.tt} ;

6. Long x = 42Li

7. // insira o c6digo aqui

8. System.out.println("true");ol

)

10. iE os cinco seguintes fragmentos de c6digo:

F1. if (fr == 121

:tlC. <^r^I r.l\EZ. r!\!r == LZLZJLLJ)

F3. if (x == f2 iol tol )

F4 . if (f1 == f2 lr,rl )

Fs. if (f3 == f2 L2) )

O que 6 verdadeiro?

,{. Um deles compilari, apenas um ser6 true.B. Dois deles compilario, apenas um ser6 true.C. Dois deles compilario, dois serio true.D. Tr€s deles compilardo, apenas um ser6 true.E. Tt6s deles compilario, exatamente dois serio true.F. Tr€s deles compilareo, exatamente tres sereo true.

4. Dado:crass lorK t

public static void main(stringlJ args) t

if(args.length == 1 I args[1J.equals("test")) t

System. out.println ( "test case" ) ;

) else {

System.out.pri-ntln("production " + args [0J ) ;

)

)

)

Page 204: Java - Scjp 5 - Portugues

178 Copftulo 4: Operodores

E a chamada de linha de comando:

java Fork 1ive2

Qual 6 o tesultado?

A- test case

B. productionC. tesE case live2D. Acompilaglofalha.

E 6 hngada uma excegio no tempo de execugio.

5. Dado:class Foozit {

public static void main(String[] args)fnt.eger x = 0;

Integer y = 0;

for(Short z = 0; z < 5i z++)

if( (++x > 2) I | (++y > 2) )

x++ r.

System.out.println(x + s \ + y) ;

)

)

Qual 6 o resultado?

A-518,5 2

c.s3D.81882883G.102rL10 3

6. Dado:class Titanic {

public static void main(StringlJBoolean b1 = true;boolean b2 = false;boolean b3 = true;if ((br- & b2) | (bz e b3) & b3)

System. out .print (..alpha ., ) ,-

if ((b1 = false) | (b1 & b3) |

System.out.print ("beta *) ;)

)

Qual 6 o resultado?

,{.. bet,a

B. alphaC. alpha beta

args) {

(b1 | b2))

Page 205: Java - Scjp 5 - Portugues

JAVA 5 I79

D. Acompilagdofalha.

E Nio 6 produzida nenhuma saida.

E E langada uma excegao em tempo de execug6o.

7. Dado:class Feline {

public static void main(StringlJ args) {

Long x = 42L;

Long Y = 44Li

System.out.prlnt(\\ \\ + 7 + 2 +.. ..),'

System.out.print(fooO + x + 5 + ,' .,);

System.out.println(x + y + fooO);]static String foo O { return "foo"; }

)

Qual 6 o resultado?

A" 9 foo47 86foo8.9 foo47 4244foo

C. 9 foo425 86fooD.9 foo425 4244foo

E 72 foo47 86foon 72 foo47 4244foo

G. 72 foo425 86fooI+ 72 foo425 4244foo

I. Acompilagdofalha.

8. Coloque os fragmentos no c6digo para produzar a saida 33. Obseryagio: voc6 deveusar cada fragmento exatamente uma vez.

class Incr ipublic static void main(StringlJ args) {

Integer x = 7;

i-ntY=2;

System. out.println (x) ;

)

FRAGMENTOS:

Y v Y v

Y x x

*= *=

Page 206: Java - Scjp 5 - Portugues

I80 Copitulo 4: Operodores

9. Dado:1. class Maybe {2. public static void main(Stringtl args) {

3. boolean b1 = t.rue;

4. boolean b2 = false;5. system.out.print(!fatse ^ fatse) ;

6. system.out.print(* $ + (!b1 & 1bz = true)));7. system.out.println(' " + (b2 ^ b1)) ;

8. )

q]'. )

O que 6 verdadeiro?

,d A linha 5 produz 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.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-11B.L2c.21,D.2 2

E.41F.42G. Acompilagdofilha.

H. E langada uma excegao em tempo de execugio.

Respostas1. D est6 correta. Este 6 um ternirio aninhado dentro de um ternario com um pouco de unboxing funto. Ambas as

express5es tern6rias slo falsas.

A5 B, C, E e F estio incortetas com base no exposto acima. (Objetivo 7.6)

2. B e D usam cottetamente boxing e instanceof juntos.

A estd incorreta porque os operandos est6o invertidos. C e E usam sintaxe instanceof incorreta. F estl erradaporque Short nio est6 na mesma 6rvore de heranga que String. (Obietivo 7.6)

3. D est6 correta. Os fragmentos F2, F3 e F5 compilario, e apenas F3 6 true.

Page 207: Java - Scjp 5 - Portugues

JAVA 5 I8I4 B' C, E e F estio incorretas. F1 esti incorreta porque nio 6 possivel comparar um tipo primitivo com um anay.F4usa sintaxe incoffet^Par^^cessar um elemento de um array bidimensional. (Obietivo 7.6)

4. E est6 correta. Pelo falo {e a abteiragdo ( | | ) neo ter sido usada, ambos os operandos sio avaliados. Uma vez queargs[1] esta^l6mdoslimitesdoanayargs,6,langadaumaArraylndexQutOfBoundsExr':ention

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

5. E esti correta. Nas duas primeiras vezes em que o teste i f 6 execuadq tanto x como y sio incementadas uma vez (s6 sealcangax++ natercekaitetagno).Apartirdatercaraiteragdodoloop,y nuncamais6usadqporcausadooperadordeabrevia$o

4 B, C, D, F, G e H est6o incorretas com base no exposto acima. (Objetivo 7.6)

6. E est6 cotteta. No segrrndo teste i f , a expressio mais i esquerda 6 uma aribuigio, e nio uma comparagio. Depois queb1 foi definido como f al-se. os demais testes sdo todos f al-se.

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

7. G est6 correta. A concatenagio roda da esqu erdz pata z dtreita e, se algum dos operandos for uma S t r i ng, osopetandos s6o concatenados. Se ambos forem nrimeros, eles sdo adicionados um ao outro. O unboxing funciona emconi unto com a concatenagdo.

A B, C, D, E, F, H e I estio incorretas com base no exposto acima . (Objetivo 7.6)

8.

class Incr {

--,,h1 l^ ^r-rl^ -1,ularg ELdLru void main(String[] args) t

Integer x = 7;

int Y = 2,

x*=x;rr *- rr.r - r,

Y*=Yix_=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 !inverteovalorbooleano do operando. Na linha 6,b2 = true 6 uma atribuigio, e nio uma comparagdo, e n6o 6 avaliada potque& nlo serve d e abrcizgdo para ela.

B, C e E estao incorretas com base no exposto acima. (Obf etivo 7.6)

10. F est6 correta. O opendoroh (resto, tamb6m conhecido como m6dulo) retorna o resto de uma operagio de divis6o.

A B, C, D, E, G e H estAo incorretas com base no exposto zcin,:'a . (Objetivo 7.6)

Page 208: Java - Scjp 5 - Portugues

182 Copftulo 4: Operodores

Page 209: Java - Scjp 5 - Portugues

Controle de fluxo,excesoes eassertivas

Obierivos pqrq qcertificqe6o

I Usor InstruE6es if e switch

I Desenvolver Loops {or, do e while.Usor Instruq6es breok e continue

I Desenvolver C6digo com Assertivos

I Usor lnstruq6es try cotch e {inolly

I Descrever o Efeiio dos ExceE6es

I Reconheceros Excec6es mqis

Comuns

( Exercicios r6pidos

P&R Teste individuol

Page 210: Java - Scjp 5 - Portugues

.|84 Copitulo 5: Controle de fluxo, exceg6es e ossedivos

VocA consegr.re se 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'

As instrug6es i f e swi tch sio tipos de controles condicionais/de decisio.que permitirio aseu pro gramaagt de

ma.reira iif..enre 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

repetidamente ar6 que o res"hrao ae Agu-a condigio seja true. -As

exceg6es the proporcionario,uma maneira simples e

limpa de organizarts c6digos e de lidar com ot proble*as que poss-am surgir no tempo de execugio. Para concluir, o

*"i*ir*o"d" asserrivas, aJicionado a linguagem na versXo 1 .4, lhe fornecer6 um meio de executar verificag6es de depura$o

em condig6es que vod queira expor durante -o

desenvolvimento, quando nio quiser ou precisar gerar a sobrecarga no temPo

de execugXo associada i manipulagio de exceg6es.

Com essas ferramentas, vocA poder6 desenvolver um programa robuso, capaz de manipular qualquer.situaglo l6gica com

sofisticaglo. Espere virias pergunras no exame que incluam o controle de fltrxo como pane de seu c6digo' at6 mesmo

aquelas que nio estiverem avaliando especificamente seu conhecimento sobre esse asstrnto.

Obietivo poro o certificoc6o

Escrevendo o c6digo usando instrus6es if e switch(Objetivo 2. I do exame)

2./ Escreuer cfidigo qae inplenente ama instrugdo f ou switch; identifcar os tipos de atgunentr uti/idos para essas in.rtrapda.

As instrug6es i f e swi tch geralmente sio conhecida s como inshwpdes d.e decisd.o. Quando voc6 usar instrug6es de decisioem 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 i f 6 o seguinte:

if (expressdoBooleana) {

System.out.println( "conte\ido da instruqdo if" ) ;

)

A expresslo entre par6ntes es deaeter corrro resultado um valor booleano true ou f alse. Normalmente voc6 testarialgo para sabe r se 6, uerdadeiro e, em seguida, executar6 um bloco de c6digo (uma ou mais instrug6es) se o resultado formesmo uerdadeim e (opcionalmente) outro bloco de c6digo se nio o for. O c6digo a seguir demonstra uma instrugio i fvAlida:

if (x>3) {

System.out.println("x is greater than 3");) else {

System.out.println("x is not gfreater than 3");]

O bloco e1 se 6 opcio nal, portanto, vocA tamb6m poderia usar o seguinte:

if (x>3) {

]z L- a.

a=y+X;

Oc6digoanterioratribuir|ovalor2ay seotesteforbemsucedido(isto6,sex forrealmentemaiorque3),masasoutras duas linhas tamb6m serio executadas independente disso. At6 mesmo as chaves serio opcionais se voc6 s6 tiver umainstrugio 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

Page 211: Java - Scjp 5 - Portugues

JAVA 5 I85

Y=2iz += 8;

a-y+x,.A Sun considera como boa pr6tica colocar blocos dentro de chaves, mesmo que s6 haia uma instrugio no bloco. Sejacuidadoso com c6digos como esse, porque voc6 pode pensar que ele deve sei lido assim:

"Se xfor maior qrc 3, mtdo nnfgurc-1t eoa 2, qcom !8 e a comJlx".

Contudo, as duas riltimas linhas serio executadas de qualquer forma! Elas nio {azempane dofltxo condicional. VocA oacharia ainda mais confirso se estivesse recuado como vemos abaixo:

if (x>3)

Y=2;z += 8;

a=y+x;Podesernecessirioaninhar_insrug6es if-else(emboratamb6mnXosejarecomendadoporraz6esdelegibilidade,poftanto' testes i f aninhados devem ser mantidos em uma quantidade minima). Voc6 poder6 configurar uma instrugiofehe p.ara que teste v6rias condig6es. O exemplo abaixo usa duas condig6es de modo que r o primeiro teste for bemsucedido, 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)serreescritocomo:

if (price < 300) {

l.urrrDrnArra+ / \ .vsjrrvvseu\/,

] else if (price < 400) {

getApproval ( ) ;

) else {

dontBuyProduct ( ) ;

]

Existem algumas regras para o uso de eI se e de el s e i f :

I Voc6podeterumounenhumelse paraumdadoif,eeledevevirdepoisdequaisquerinstrug6eselse if.r Vocdpodeterdemuitosounenhumelse if paraumdadoif,eelesdevemvirantesdoelse (opcional).

I Depois que um else tem sucesso, nenhum dos demais else i f ou else ser6 testado.

O segqnte glemplo mostra um c6digo horrivelmente formatado para o mundo real. Como vocA provavelmente j6adivinhou,_6bastante prov6vel que encontre ese tipo de formatagio no exame. De qualque r f.orma,o codigo dernonstra ouso de mriltiplos e lse i f :

int x = 1;

if(x==3){}el-se if (x < 4) {System.out.println("<4"); }

else if (x < 2) {System.out.println("<2"); }

else { System.out.println("e1se") ; }

Page 212: Java - Scjp 5 - Portugues

186 Copitulo 5: Controle de fluxo, exceE6es e qssertivos

O exemplo produz estasaida:

<4

(R.epareque,mesmoqueosegundoelse sejaverdadeiro,aexecugionuncachegaaele.)

Emalgunscasos,voc6podeterdificuldadesemdescobrircomqualif oseuefse deveserpareado,comonesteexemplo:

if (exam.doneO )

if (exam.getScoreO < 0.61)q1/ctam nrrt- nrin1- lnlt\Tr\/ aa:in "):ujeevlrL.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 elsepertencerl ) initrugXo i f mais pr6ima a qual ela possivelmente pertenga (em outras palavras, i instrugio i f anteriormais 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 todosapropriadamente recuados. Alguns candidatos t€m at6 uma frase de efeito para a maneira como as perguntas sioapresentadas: tudo que puder ser feito de maneira mais confusa, assim seri.

Esteja preparado para perguntas que al6m de nio recuarem os c6digos apropriadamente, o fario intencionalmente de

maneira confusa: preste bastante atengio em distragSes como a do exemplo a seguir:

if (exam.done O )

if (exam.getscoreO < 0.61)

System. out.println ( "Try again. " ) ;

elseSystem.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 ifAs instrug6es i f s6 podem avaliar valores booleanos. Qualquer expressio que tenha como resultado um valorbooleano seriadequada,masalgumasdelaspodemsercomplexas.SuponhamosquedoStuff ( )retornetrue,

int Y = 5,'

int x = 2;

if (((x > 3) && (y < 2)) | aostuttt)) iq\rql-om nrrf nrinf lnl"rrrra/1.

Page 213: Java - Scjp 5 - Portugues

JAVA5 187

)

queodbiri

VocO pode ler o c6digo anterior assim: "Se tanto (x > 3) quanto (y < 2) forem t rr-re ou se o resultado de dostuf f ( )tor true, entio 'true" seri exibido. Portanto, basicamente, se apenas d.oStuf ( ) for true, ainda obteremos true.!or6ln,sedoStuff ( ) forfalso,(x>3)e(y<2)terloquesertrue paraquetruesejaexibido".Oc6digoanteriorficariundamais complexo se voc6 nio inserir um conjunto de par6ntese, .orrro lr.rrro,

"t"i*o,int y = 5'int x = 2;

if ((x > 3) && (y . 2) I aostutro ) {

System. out.println ( "true,, ) ;

]

Agora ele exibir6... Nada! Porque o c6digo anterior (com um conjunto de par6nteses a menos) far6 a avaliagio como seestivesse 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 && deabreviagio, a expressio ser6 avaliada como se houvesse par€nreses enfeixando ( lv.z I dostuf f ( )). Em outraspalavras, 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 i f 6 um valor booleano. Em algumas linguagens, O ==false,e1== t.rue.MasnioemJava! Oseguintec6digomostrainstrug6esif quepodemparecerv6lidas,masniosio, seguidas de substitutos v6lidos.

int- irrraTnf - 1.

'i nl- f: l qoTnf = O.

if (truelnt)if (truelnt == true)if (1)

if (falseInt == fal-se)

if (truelnt == 1)

if (falselnt == 0)

/ / inv6lido/ / inv5aido

/ / inv6lido/ / inv6Tido

/ / v6lido/ / v6Lido

oBSERVAQ6ESpeneOE)(AME

Um ero clmtlm qtle os programadoru cometea (e que pode ser dficil de identfimr) i atribair ama uari,iael booleana quando a intenpdo seriateshl-la. Cuidado com aldigot como o seguinte:

boolean boo = false:if (boo = true) { }

Vocd pode achar ama enlre trds coitas:

1., pae o aidigo rcni nnpikdo e executado adeqaadamente, mdr qae o teste if falhar,i porque boo 6 f also.2, pue o aidigo ndo senl nmpilado porque uoci est,l asando uma atibuigdo (: ), t, ueTde um teste de igualdade (: : ).

3. pae o aldigo senl conpilado e executado adzquadamente, e o teste if seni bem sandidn porque boo foi confgurado com Lrue (em

ueTde estar sendo aualiado se d uerdadeiro) n0 argunentl da insrap1o if!

Bem, a oppdo 3 estti correta. 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 f requeren expressdu boo/eanas, uocd precisa ter um conhecimento srilido tanto sobre os operadoret ldgicos qaanto sobre aintaxe e remdntica do teste if .

Page 214: Java - Scjp 5 - Portugues

188 Copftulo 5: Controle de fluxo, exceq6es e ossertivos

Instrug6es svvitch

lJma maneira de simular o uso de virias instrug6es if 6 com a instrugXo switch. Observe o c6digo do bloco else-i f e veja como pode ser confuso ter testes i f aninhados, mesmo com apenas alguns niveis:

int x = 3;

if (x == 1) {

System.out.println( "x equals 1" ) ;

]

else if(x == 2) {

System. out.println ( "x equals 2" ) ;

)

else if 1x == 3) {

System.out.println( "x equals 3" ) ;

)

el-se {

system.out.println("No idea what x is");)

Agora vejamos a mesma funcionalidade representada na estrutura de uma instrugio swi tch:

int x = 3;

switch (x) {

case 1:

System. out.println (

break;

case 2:

System. out . println (

break;

case 3:Q\rc|- 6m nrrF nrinr'ln /rJ p uelr r vuu . y! fIIurrr \

break;

default:System. out.println (

)

"x is equal to 1," \ ;

"x is equal to 2" ) ;

"x is equal to 3");

"Still no idea what x is" ) ;

ObservagXo: arazXo pelaqual essa instrugio switch emula os i f s aninhados listados anteriormente 6 devido )sinstrug6es break que foram colocadas dentro do switch. Em geral, as instrug6es break sio opcionais e, como veremosdaqui a algumas piginas, a inclusio ou excluslo delas causa grandes mudangas na forma como a instrugio swi tch serier<ecutada

Express6es vilidas para switch e case

A forma geral da instrugio switch 6

switch (express6o) {

case constantel: bloco de c6digo

case constante2: bloco de c6digo

default: bloco de c6diqo

iA expressio de um switch deve avaliar um char, byte, short, int ou, a panir do Java 5, um enum. Isso significaque, se voce nio estiver usando um enurg s6 vari6veis e valores que puderem ser promovidos automaticamente (emoutras palavras, implicitamente convertidos) a um tipo int serio aceitos. VocA nio conseguiri compilar se usar algum tipodiferente, incluindo os tipos num6ricos 1ong, f loat e double.

O rinico argumento que uma instrugXo case poder6 avaliar seri aquele que apresentar o mesmo tipo que a instruSo

Page 215: Java - Scjp 5 - Portugues

JAVA 5 I89swi tch pode u.ar, com uma restrigio adicional - e re/euante: o argumento de case tem que wr uma constante tlc tenpo de conpikgdo!Ele precisa ser resolvido no tempo de compilagio, portanto, isso quEr dizer q,r. vo.6 ipode usar uma variivi f inaiconstante com um valor literal. Nio 6 o suficiente ser f ina1, ela deve ser uma constante no tempo de compila$o. Pore><emplo:

f i-a] ihf . - 1.

final int b;

intx=0;switch (x) {

case a: // ok

case b: / / erro de compilagdo

Al6mdisso,ainstrugdoswiLgh sdpodeuerifcaraigualdade.Oquesignificaqueosoutrosoperadoresrelacionaiscomomaiorqae sio.considerados nio utiliz6veis em uma instruEio case. A seguir temos o exemplo de uma expressS.o vilida que usauma chamada de m6todo na instrugio swi t.ch. Observe que para esse c6digo ser v6fido, o m6todo que esti sendochamado na referdncia ao objeto deve rerornar um valor compitivel com umiipo int.

String s = "xyz";switch (s.lengthO ) {

case 1:

System.out.println( "length is one,') ;

break;

case 2:

System. out.println ( "length is two" ) ;

break;

case 3:

Syst.em. out.println ( "length is three" ) ;break;

default:System.out.println( "no match" ) ;

l

Oura regra que voc6 poderia nio esperar envolve a pergunta: "O que aconteceria se uma variivel menor do que um tipoint fosseusadanainstrugloswitch?"Examineoexemplodeinstrugioswitch aseguir:

bYte g = 2'switch(g) {

case 23:

case 128:

)

Esse c6digo nXo seri compilado. Embora o argumento da instruglo swi tch seja v6lido - um tipo bpe 6 convertidoimplicitamente em um tipo int. - o segundo argumento de case (128) 6 muito grande para um tipo byte e ocompilador sabe disso! Se vod tentar compilar o exemplo anterior ver6 um erro:

Test.java:6: possible foss of precisionfound : i-nt

required: bytecase 128:

Tamb6m nlo 6 vilido ter mais de uma instrugio case usando o rnesmo valor. Por exemplo, o bloco de c6digo a seguirnio ser6 compilado porque usa duas instrug6es case com o mesmo valor igual a 80:

int temp = 90;quri talr lr- amnl I

case B0 : System.out.println("80") ;

case 80 : System.out.print]n("80"); / / nd.o compila!

Page 216: Java - Scjp 5 - Portugues

190 Copftulo 5: Controle de fluxo, exceq6es e ossertivos

case 90: System.out.println("90") ;

default: System.out.println("default") ;

J

A tt't-c varoo se aprovenar cos recursos do boxing em uma expressao swi tch. O seguinte exemplo 6 vAlido:

switch(new Inteqer(4) ) {

case 4: System.out.println("boxing is OK");

]

oBSERVAQ6ESpeneOE)(AME

Procure alguma uiolagdo nas regras dos argumentos de swiLch, case. Por exenp/0, uocd pode enclntrar exempks que nio serian ttd/idos

como os tr* trecbos abaixo:

switch (x) {

case 0 {

)

switch (x) {

o: { }

1: { }

)

No exemplo, a inshag1o case usa uma cbaue e omite os dois pontos. O segundo exempk omite a pakwa-chaae case.

Break e a passagem completa em blocos switchFinalmente estamos prontos para discutir a instrugio break e mais detalhes sobre o controle de fluxo dentro de umainstrugio 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, e a pineira clnrtafite case que bater com a exprusdo swi tch serri o ponto

de enlrada da exuupio.

Em outras palavras, ap6s 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 seguinteexemplo usa um enum em uma instrugio case.

anrrm ('nlar IraA dra6n ].r'lrral

class SwitchEnum {

public static void main(String [] args) {

Color c = Col-or.gfreen;

switch(c) {

case red: System.out.print ("red ") ;

case gfreen: System.out.print("green ") ;

case blue: System.out.print ("b1ue ") ;

default: .qvstem-otrt nri nf ln( "done"),'

]

Neste exemplo, case green: teve uma correspondencia, entio aJVM executou esse bloco de c6digo e todos osblocos subseqiientes paru produztr a saida:

green blue done

Novamente, quando o programa encontrar apalavra<have break durante a execugAo de uma instrugAo swj-tch, oprocessamentopassar6imediatamentedoblocoswitch paraainstrugioposterioraele.Seapalavra-chaveforomitida,oprograma simplesmente continuar6 a executar os outros blocos case at6 que uma palavra break seja encontrada na

Page 217: Java - Scjp 5 - Portugues

JAVA 5 191

instrugio switch ou at6 que a instrugio termine. Observe o c6digo a seguir:

i-nt x = 1;

switch (x) {

case 1: System.out.println("x is one"),.

case 2: System.out.println(..x is two,,);

case 3 : System. out.println ( "x is three" ) ;

]

Syst.em. out.println ( "out of the switch" ) ;O c6digo exibiri o seguinte:

x l_s one

x is two

x is threeout of the switch

Essacombinagio ocorreuporque o-c6digo nioghegou aumainstrugXobreak; poryagtg, l execu{io simplesmentecontinuou a percorrer cada instrugio case at6 o final. Esse processamento na verdade 6 chamado de "passagemcompleta" por causa da maneira como a execugio passa de uma instrugio case para a seguinte, Con.riderv a in$ntg6o casesatifafllia sinplesrnente corzo seu ponto de entrada no bloco swiLch/Em outras palavras, voc| ndo deve consideri-la assim:"Encontre a instrugio case sadsfat6ria, execute apenas esse c6digo e saia da instrugio". Nio 6 dessa forma que funciona.Se vocA quiser mesmo o compoftamento de "interesse apenas no c6digo satisfat6rio", insira uma palavra break em cada

instrugio case como vemos abaixo:

int x = 1;

switch (x) {

case l-: {

System.out..println("x is one") ; break;

)

taea ). I

System. out.println ( "x is two" ) ,'

]

naca ?. I

System. out.printfn( "x is two" ) ;

)

break;

)

System.out.println( "out of the switch"),'A execugio do c6digo anterior, agora que adicionamos as instrug6es brealg exibirS

x is one

out of the switch

es6.Entramosnoblocoswitch nainstrugiocase l.JAqueelaapresentouumacorrespond6nciacomoargumentoswi tch ( ) , passamos para a instrugio println, atingimos a palavra break e saltamos para o fim da instrugXo swi tch.

Um exemplo interessante dessa l6gica da passagem completa 6 mostrado no c6digo abaixo:

int x = someNumberBetweenoneAndTen;

switch (x) {

case 2:

case 4:

case 6:

case B:

a:ca 1O. t

Page 218: Java - Scjp 5 - Portugues

192 Copitulo 5: Conirole de {luxo, exceg6es e ossertivos

System.out.println("x is an even nuricer") ; break;

)

Ainstrugloswitch exibir6"x is an even number"ounloexibir|nada,issodependerAdonrimeroestarentreum 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 instrugiocase 1 0 nio 6 necess6ria; o final da instrugio swi tch j6 ter6 sido atingido.

Observagio: pelo fato de a passagem completa ser pouco intuitiva, a Sun recomenda que voc6 adicione um coment6rio,como: / / pas sagem compl eta, quando usar essa l6gica em seus Programas.

A instrugio case defaultEse,usando oc6dtgoanterior,voc6quisesseexibir"x is an odd number"quandonenhumadasinstrug6escase(os nrimeros pares) fosse satisfat6ria? VocA nlo poderia inserir o resultado depois da instrugio switch ou como a riltimainstrugiocase dainstruEioswitch,porquenessasduassituag6esoresultadoexibidoseriasempre"x is an oddnumber". Para obter esse comportamento, use a palavra-chave default. (A prop6sito, se voc€ estiver se perguntandopor que h6 uma palavra-chave def ault ainda que nlo seja usado um modificador para o controle de acesso padrio,veriagora que ela 6 empregada com uma finalidade completamente diferente) A rinica alteragXo que precisaremo sfazpr ser|adicionar a instrugio case default ao c6digo anterior:

int x = someNumberBetweenoneAndTen;

switch (x) {

case 2:

case 4:

case 6:

case B:

case 10: {

System.out.println("x is an even number");

break;

)

default: System.out.println("x is an odd number");

)

OBSERVAQoESPARAOH(AME

A instrag1o case def auLE pode ndo uir nofnal da inshagdo switch. Procure-a em locait e$ranhos como aemos abaixo:

inL x = 2:

switch (x) tea<a 2, Qrrcfam arrf nr.i6f l-/\rarr\.r vJrLerrrtvuu.v!frruril\ z It

default. : System. out.println ( "default" ) ;

case 3 : System.out.println("3") ;

case 4: System.out.println( "4" ) ;

]

A exwugdo do aidtgo anterior exibini

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 nrihfln/\r/\., sJ-Lsrrrivuu.PrrrrLrLL\ L t,

Page 219: Java - Scjp 5 - Portugues

JAVA5 I93

default : System. out.printl-n ( "defaulL" ) ;

na<a ?. Qrrcl- am ^11t- nri nf 'l n / $?" I .vse r tsr 4aAe+

case 4 : System.out.println ( "4" ) ;

)

A exultpho do cddigo anteior exibini

default

Aregraalembrar,iqaeainstrugdodefault fancionaexatanentec0m0qtlalqilerzutrainstril(Aocase fiaparsagem

conpleta!

Exercfcio 5- 1

Criando uma instrugio switch-case

Tentecriarumainstrugioswitch-case usandoumvalorchar comoainstruEiocase. Incluaumcomportamentopadrio para o caso de nenhum dos valores char ser satisfat6rio.

I Cenifique-se de que umavariivel char seja declarada antes da instrugio switch.I Cada instrugio case deve ser seguida de uma instrugio break.

I O valor default pode ser inserido no fim, na metade ou no inicio.

Al . t. ..f.L/OleTrvo poro o centttcogoo

Loops e lteradores (Obietlvo 2.2 do exame)2.2 Escreueraidigo qrc implenente todas asforwas de loopt e iteradorcs, induindo o uso defor, do loopforEinorado (for+ach), do, while,

labels, break e nntinue; e explicar os ualores *tiliqadot pelas uaiiutit de cortador do loop darante e @6s a exuugdo desse.

OsloopsdalinguagemJavav6memtr6svers6es:while,doefor(e,apanirdoJava5,oloopfor temduasvariantes). 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 outraslinguagens, portanto, mesmo se for iniciante emJava, esses loops nio serio dificeis de aprender.

O loop whi 1e seri adequado em cenirios nos quais voc6 nXo souber quantas vezes o bloco ou instnrgio teri que serrepeti{o,masquiserqueiuaexecugiocontinueit6quealgumacondig{o*jauerdadeira.Ainstruglow}rile temoformatoasegur:

while (expressSo) {/ / faz al-go

iou

int x = 2;

while(x == 2) {

System. out.println (x) ,.

++X;

]

Nesse caso, como em todos os loops, a expressio (teste) ter6 que resultar em um valor booleano. O corpo do loopwhile rdser6executadoseaexpressfo(tam66mchamadade"condigio") resultaremumvalortrue. lJmavezqueentrarmos 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

Usando loops while

Page 220: Java - Scjp 5 - Portugues

194 Copitulo 5: Controle de {luxo, exceg6es e ossertivos

no loop, de modo que quando a condiglo for verificada noyamente seri avaliada como f alse e a execugeo doloop seri finalizada.

Qualquer variivel usada na expressio de um loop while deve ser declarada antes da expressio ser avalia&. Em outraspalavras, voc6 nio pode escrwer

while (int x = 2) { } / / inv5l-idoMas tamb6m por que voc6 faria isso? Em vez de testar a variivel, voc6 estaria declarando e incializandoa, portanto, ela teriasempre o mesmo valor. Nlo seria uma condigio de teste adequada!

O ponto chave a lembrar sobre o loop whi 1e 6 que ele pode nem mesmo ser exectrtado. Se a expressio do teste forfalse naprimeiravezqueoloopwhile forverificado,ocolpodoloopser6ignoradoeoprogramacomegareaserexecutado na primeira instrugio depois dele. Examine o exemplo a seguir:

i-nt x = B;

whife (x > 8) {

System. out.println ( "in the 1oop" ) ;

x=10;)

System.out..println( "past the 1oop" ) ;

A execuglo desse c6digo produziri

past the loop

Pelofatodeaexpressio(* > 8) avaliarcomo false,oc6digodentrodoloopwhile nuncaser|exeantado.

Usando loops do

O loop do 6 semelhante ao loop whi 1 e, exceto pelo fato de que a expressao nlo 6 avaliada at6. que o c6digo do loop dotenha sido executado. Ponanto, 6 garantido que o c6digo dentro de um loop do ser6 executado pelo menos uma vez. Oc6digo abaixo mostra um loop do em ageor

do{System. out. println ( "rnside loop" ) ;

] while(false);

AinstrugioSystem.out.println( )seriexibidaumavez,aindaqueaexprusdos/aaualiadacomofalse.Lembre-sede que o loop do serrpre execvt^o c6digo de seu conterido pelo menos umaaal. Nio esquega de observar o uso do ponto e

virgula no final da expressio while.

oBSERVAQ6ESpeneOE)(AME

Como nos tettes if , procure loops whil-e (e testes while de loops do -whi 1e) clm ilma expressdo que ndo resalte em umbooleano. Examine os exenplos abaixo de exprutduwhile uilidas e 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)/ / rr.<l .i A^ F^df ^ /{a i nrra l da^o/ / vaLLwt ue>Le uL rvqqrsqse

/ / var)-do

Usando loops forComoadventodoJava5,oloopfor adquiriuumasegundaestrutura.N6schamaremosoestiloantigodoloopforde "loop f or bisico", e chamaremos o novo estilo de "loop f or aprimorado" (embora o obj etivo2.2da Sun se refira a

ele como f or- each). Dependendo de qual docum enta&o vocA' usar (incluindo a da Sun), ver6 ambos os termos, juntocomfor-in.Ostermosfor-in,for-eache"for aprimorado"referem-setodosaomesmoconstrutorJava.

O loop f or b6sico 6 mais fleivel do que o aprimorado, mas o loop aprimorado foi criado para facilitar a programagio deiterag6es atrav6s de arrays e de conjuntos.

Page 221: Java - Scjp 5 - Portugues

JAVAs I95

O Loop for BisicoO loop for ser6 panicularmente ritil para o controle do fluxo quando voc€ ji souber quantas vezes teri que executar as

instru96es do bloco do loop. A declaraEio do loop f or possui tr6s partes principais, al6m do corpo do loop:

r Declara$oeinicializa$odevariiveis

I A expressio booleana (teste condicional)

I Aexpressiodeiteragio

Cada uma das tr6s partes da declaragio do loop f or 6 separada por um ponto e virgula. Os dois exemplos a seguirdemonstram o loop f or. O primeiro mostra as partes de um loop f or em forma de pseudoc6digo e o segundo exibe asintaxe 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 inicializagioA primeira parte da instrugio for permite que voc6 declare e inicialize nenhuma, uma ou diversas variiveis do mesmotipo dentro dos par6nteses ap6s a palavra-chave f or. Se voc6 declarar mais de uma variivel do mesmo tipo, terA que separi-las comvirgulas como nalinha abaixo:

for (intx = 10, Y = 3; Y > 3; y++) { }

A dularagdo e inicialiTagdo ocorrem antes de qualqaeroutra coisa em um loop for. E enquanto as outras duas partes - o testebooleano e a expressio de iteraglo - sio executadas a cada iteragXo do loop, a declaraSo e ancialbaSo ocorrem apenas umavez, logo no inicio. VocA tamb6m precisa saber qwe o ucopo das aaiiueis dularadat no loop f or terminajanto com o loop!Oc6digo abaixo demonstra isso:

for (int x = 1; x < 2; x++) {

System.out.println(x) ; // V6lido]

System.out.println(x); // InvaLido! x agora estii fora de escopo

/ / e nl.o pode ser acessado

Se voc6 tentarcompilar ese c6digo, obter6

Test. java: 19 : cannot regolve symbol

symbol : variable x

location: class Test

System. out.println (x) ;

Loop for B6sico: Expressio cond:cional (booleana)A pr6xima segio a ser executada ser6 a expressio condicional, que (como todos os outros testes condicionais) tenlqueresultar em um valor booleano. VocA pode ter somente uma expressio l6gica, por6m, ela pode ser muito complexa.Cuidado com c6digos que usem express6es l6gicas como esta:

for (int x = 0; (( ((x < 10) aa (y- - > 2)) | x

O c6digo anterior 6 v6lido, mas o seguint e ndo o 6:

for (int x = 0; (x > 5), (y < 2); x++) { }

O compilador lhe informari do problema:

Testlonq. Java:20: ';' expectedfor (int x = 0; (x > 5), (y.2) ; x++) { }

A regra a lembrar 6 esta: ,.a r)port, nrn*o exprerrao de teste.

-- ?\ \. vrr\ / \--

J | |

| / ^--^^^^^ a^

/ / avnraccAoq

Page 222: Java - Scjp 5 - Portugues

195 Copitulo 5: Controle de fluxo, exceg6es e ossertivos

Em outras palavras, voc6 nio pode usar v6rios testes separados por virgulas, ainda que as ounas dvas partes de umainstrugio for possam ter virias seg6es.

Loop for B6sico: Expressio de iteragiioAp6s cada execugio do colpo do loop for, a expressXo de iteragio ser6 processada. E tr.rr" p"rt. que voc€ poderi informaro que deseja que acontegaacadaiteragio do loop. Lembre-se de que ela semp re ocorreri depoisque o corpo do loop f or forexecutado! 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 docorpo do loop, a expressio de iteraglo ser6 processada, aumentando x em uma uni&de. A seguir, o teste condicional seriverificadoej6queoresultadoagoraserlfalse,aexecugiosaltar|parabaixodoloopfor edariprosseguimentoapaftirdd.

Tenha em mente que, fora uma saida forgada, as avaliag6es da expressio de iteragio e, posteriormente, daexpressio condicional, sio sempre as duas tltimas coisas a ocorrer em um loop for!

Exemplos de saidas forgadas incluem um break, um return, uma excegio, ou uma instrugio System. exit ( ) , todasfazem com que o loop seja encerrado repentinamente, sem executar a expressio de iteragSo. Examine o c6digo a seguir:

static boolean dostuff ( ) {

for (int x = 0; x < 3; x++) iSystem.out.println ( "in for loop" ) ;

return t.rue;

]

return true;

)

A execugio desse c6digo produzir6

in for loop

O resultado da instrugio ser6 exibido apenas umavez, porque a instruglo return far6 com que a execugXo saia nio s6 daiteragio atual do loop, mas de todo o m6todo. Portanto, a expresslo de iteragio nunca seri executada nesse caso. A Tabela 5-L lista as causas e resultados da finalizaglo repentina dos loops.

Tobelo 5-l Cousos do finolizoE6o ontecipodo do loop

C6digo do loop O queacontecer5

break A execu$o saltari imediatamente para a primeira instru$o ap6s o loopfor.

reE,urn A execucio retornari imediatamente ao m6todo chamador.

System. exit ( ) A execugio do programa ser6 completamente interrompida; o VMser6encerrado.

Loop for B6sico: Caracteristicas do loop forNenhuma das tr6s seg6es da declaragio do loop f or sio necess6rias! O exemplo a seguir 6 perfeitamente vilido (emboranio seja necessariamente uma boapritica):

for( ; ; ) {

System.out.println( "Inside an endless 1oop") ;

]

No exemplo anterior, todas as partes da declaragio foram deixadas de fora, portxoto, o c6digo agir6 como um loop infinito.No exame, ser6 importante saber que com a au$ncia das seg5es de declaragio elntcializagio, o loop agiri como um loopwhil-e. O exemplo abaixo demonstra como isso acontece:

Page 223: Java - Scjp 5 - Portugues

JAVA 5 I97

i-f i - n.

for (;i<10;) {

i++;

/ / faz algum outro trabalho

]

O exemplo abaixo demonstra um loop for com diversas variaveis. Umavirgula separa as variiveis e elas precisam ser domesmo tipo. Lembre-se de que as vari6veis declaradas na instruglo f or slo todas locais do loop, e nio po&m ser usadas

fora desse escopo.

for (int i = 0, j = 0; (i<l-0) && (j<10),- i++, j++) {

SysLem.out.println("i is " + i + " j is " +j) ;

)

PREPARAQAOPARAOE)HME

O ucopo das uaidueis terd unafungdo abrangente n0 exama Vocd ter,i que saber que ama uaidael declarada no loop f or ndo podeni ser

usadafora dele. Pordn, ama uariduel apenas inicialiTada na inthwgdo f or (rzat dularada anteriormente) pode ser usadafora do loop. Porexempk, o cddigo abaixo d uilido,

int x = 3;

for (x = 1_2; x < 20, x++l { }

System. out.prlntln (x) ;

efiquanto esse ndo d,

for (i-nt. x = 3; x < 20; x++) { }System.out.println(x) ;

A riltima coisa que deve ser ressaltada 6 qu e todas as trts rcgdes do lnop f or sdo independrntes uma da outra. As tr6s express6es dainstrugio 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"ralgo; 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

iterateiterate

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 especializadoquesimplificaatarefadesefazerumloopatrav6s de um array ou um conjunto. Neste capitulo, vamos nos concentrar no uso do f or aprimorado para fazer loopsatrav6s de arrays. No Capitulo 7, revisaremos o f or aprimorado ao discutirmos os conjuntos - que 6 onde o f oraprimorado realmente faz a diferenga.

Em vez de ter hts componentes, o f or aprimorado t em dois. Vamos fazer um loop atrav6s de um array & forma bisica(antiga), e depois usando o for aprimorado:

int [] a = {1,2,3,4};for(int x = 0; x < a.length; x++)

System. out.print (a Ix] ) ;for(int n : a)

/ / Ioop for b5sico

/ / J-oop for aprimorado

Page 224: Java - Scjp 5 - Portugues

198 Copftulo 5: Controle de fluxo, exceg6es e ossertivos

System. out.print (n) ;

/ / Aar]: r: nAac I f nr '

fnrllnnn rr . Ia \ .

Farllann ln T.a\ .

v6lidas

for(int[]n:twoDee)tfor(inL n2 : twoDee[2]) ifor(Strings: sNums) ;

for(Objecto:sNums);

for(Animal a : animal-s) i

/ / declarae6es "for" INVALIDAS

for(x2 : la) ;

for(int x2 : twoDee) ;

fnrlinf v? . la\

for(Dogd: animals) ;

O que produz esta saida:

L234L234

Mais formalmente, vamos descrever o for aprimorado da seguinte forma:

fnrldanl araaVa . avnraq<Anl

As duas panes da instrugio f or sio:

I Declarag6o A vari6vel de bloco rudm-dularada, de um tipo compativel com os elementos do array que voc6esti acessando. Essa vari6vel estari disponivel dentro do bloco f or, e o seu valor ser6 o mesmo que o doelemento atual do array.

I Expressio Estadeveavaliarcomooaffayatrav6sdoqualvocequerfazeroloop.PodeserumavariAve|dearrayou uma chamada a m6todo que retorne um array. O array pode ser de qualquer tipo: primitivo, objeto, at6 mesmo arraycontendo arrays.

Usando as definig6es acima, vejamos algumas declarag6es vfidas e inv6lidas de for aprimorados:

r-nt x;long x2;Long [] ta = {4L, 5L, 6L};

]ong Jl 1a = {7L, BL, 9L};

int [][] twoDee = {{1,2,3}, {4,5,6}, {7,8,9}};String [] sNums - {"one", "two", "three"};enimal [] animals - {new DosO, new CatO};

/ / faz um 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 refer€ncia Object para

/ / cada String/ / deflne uma refer6ncia Animal para

/ / cada elemento

/ / x2 j6 foi declarada

/,/ impossivel colocar um array dentro de um int// impossivel colocar um longr dentro de um int.

/ / 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 forb6sico quanto ao aprimorado.

Usando break e continue

As palavras-chave 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.Adiferengaentreessaspalavras 6 se ser6 ou nio dado prosseguimente com a execugio de uma nova iteragio ou se salaremos para a primeirainstrugio depois do loop e continuaremos o processamento a partir dai.

Page 225: Java - Scjp 5 - Portugues

JAVA 5 I99

oBSERVAe6rspeneoErreME

Lembre-r de que as inshagdet continue deuem ser inseridat dentw do loop; do contuiio, uocl uerti am erm do conpilador. At inshagdubreak deuem ter usadat denho do kop ou de uma in$rugdo swi tch. Oburuagdo: Iso ndo v aplica a insturgdetbreak mtuladas.

. _A instruglo brea.k fari com que o programa encerre a execuglo do loop atual e inicie o processamento na linha dec6digo posterior ao bloco.

A ingtrugio continue far6 com que s omente a iteragioatual do loop s elaencerradaeque a pr6xima iteragio domesmo loop seja iniciada se a condiglo deste for atendida. Quando usar uma instrugio coniinuJem um loop ior, vocAteri 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 deitera$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, ainstrugio continue 6 usada dentro de um teste i f como vemos abaixo:

for (int i = 0; i < 10; i++) {

System. out.printfn ( "fnside 1oop" ) ;

if (foo.doStuff O == 5) {

continue;

)

/ / mais c6digo do 1oop, que ndo ser6 executado quando o t.este if acima

/ / for verdadeiro

Instrug6es neo rotuladas

Tanto a instrugio break quanto continue podem ser nlo-rotuladas ou rotuladas. Embora seja muito mais comumusar instrug6es break e continue nio rotuladas, no exame ser6 esperado que voc6 saiba como as instrug6es breake conEinue rotuladas funcionam. Como mencionado antes, a instrugio break (n1o-rotulada) sairi da estrutura doloop atual e prosseguir6 na linha de c6digo posterior ao bloco do loop. O exemplo abaixo demonstra uma instrugiobreak:

boofean problem = trueiwhife (t.rue) {

r f lnr^h I aml {

System.out.println("There was a problem" ) ;

break;

]

// pr6xi-ma linha do c6digo

No exemplo anterior, a instrugXo break nio foi rotulada. A seguir temos o exemplo de uma instrugio continue nioronrlada:

while (!EOF) {

/ / 16 vm canpo de um arquivoif f Fh6ra r^7=c : nr^hl 6m\ I

continue; / / passa para o campo seguinte do arquivo

)

/ / caso contr5rio, faz outras coj-sas com o campo

Page 226: Java - Scjp 5 - Portugues

200 Copftulo 5: Controle de {luxo, exceE6es e ossertivos

Nesse exemplo, os campos de um arquivo esteo sendo lidos um de cada vez. Quando um erro for encontrado, o

programa ffr.."{ p"r" o ."*po r.g.tittt. do. arquivo e usari a instrugXo continue para voltar ao loop (t.."1oestiver no ?inal do arquivo) . .o.tti-ttrr"r a leituri dos outros campos. Se o comando break fosse usado,.o c6digo

encerraria a leitura do arquivo quando um erro fosse encontrado e passaria para a pr6xima linha de c6digo. Ainstrugio conti-nue 6 ima maneira de dizer: "Essa iteragio espeLifica do loop precisa ser encerrada, mas nXo o

loop inteiro. Apenas nio quero que a execugio do resto do c6digo dessa iteragXo seja terminada' portanto,processe a expressio da iteraglo i, em seguida, reinicie no teste nXo se preocupando com o que est6 abaixo da

instrugio continue".

Instrug6es rotuladas

Embora muitas instrug5es emJava possam ser rotuladas, 6 mais comum usar r6tulos com instrug5es loop tais como f ore whi 1e, em conjunto com instrug6es break e continue. Uma instruEio de r6tulo deve ser colocada logo antes da

instrugio sendo rotulada, e consiste de um identificador vllido que termina com dois pontos 0.Voc6 precisa entender a diferenga entre instrug6es break e continue rotuladas e nio-rotuladas. As rotuladas serio,r...ss6rias somente nas situag6es em que voc6 tiver um loop aninhado e precisar indicar qual quer encerrar ou a panir de

qual deseja continuar a pr6xima iteragio. Uma instrugio break sair6 do loop rotulado e nio do loop atual, se a palavra-

chave break for combinada com um r6tulo. IJm exemplo do formato de um r6tulo se encontra no c6digo abaixo:

foo:

for (int x = 3; x < 20; x++) {

while(y > 7) {

Y-- i

)

O r6tulo precisa estar de acordo com as regras de nomes de variiveis vilidos, e deve estar em conformidade com a

convengXo de nomeagloJava. A sintaxe para o uso de um nome como r6tulo junto com uma instrugio break consiste na

palavra-chave break seguida do nome do r6tulo e de um ponto e virgula. Abaixo podemos ver um exemplo mais

completo do uso de uma instrugio break rotulada:

boolean i-sTrue = true;outer:

for(int 1=6; i<5; i++) {

while (isTrue) {

System. out .println ( "Hel1o" ) ;

break outer;j / / fim do loop for interno

Swst-em-out nri nfln(\'Orrt-er "l nnn t'\: // n5o seri exibidoeJsLerrr.vuu.y-rrrurrl\ vsevr +vvy.

j / / fin do loop for externo

System. out.println ( "Good-Bye" ) ;

A execugio &sse c6digo produzir6

Hel1o

Good-bye

Nesse exemplo a palavra Hello ser6 exibida uma vez. Em seguida, a instruglo break rotulada ser6 executada e o

fluxo sair6 do loop rotulado com outer. Entio, a pr6xima linha de c6digo exibiri cood-bye. Vejamos o que

acontecera se a instrugio continue for usada em vez de break. O c6digo do exemplo a seguir 6 similar ao anterior,exceto pela substituigio de break por continue:

outer:

for (int 1=6; i<5; i++; t

for (int j=0; j<5; j++) {

System. out.println ( "He11o" ) ;

continue outer;

Page 227: Java - Scjp 5 - Portugues

JAVA 5 20]j / / fim do loop for interno

System. out.println (..outer,, ) ; // Nunca 6 exibido]

System. out..println (..Good-Bye,, ) ;

A execugio desse c6digo produzir|:

Hello

Hel1o

HeIfo

He11o

Helfo

cood-Bye

Nesse exemplo, a palavra Hel1o ser6 exibida cinco vezes. Depois que a instrugio continue for executada, ofluxo continuare com a pr6xima iteragio do loop identificado pelo r6tulo. Para concluir, quando a condigio doloop externo fior avaliada como fal-se, o loop ser6 encerrado e a palavra Good-Bye ser6-exibida.

Exercfcio 5-2

Criando um loop while rotuladoTente criar um loop whi 1e rotulado. Crie o r6tulo outer e fornega uma condigio para verificar se a idade em umavariivel 6 menor ou igual a 21. lentro do loop, ela deve aumentar a idade em uma unidade. A cada vez que o loop forpercorrido, ela verificari se a idade 6 igual a 16. Caso afirmativo, uma mensagem seri exibida solicitando sua licengi demotorista e o fluxo continuar6 no loop externo. Do contririo, apenas seri exibida a mensagem "Another year".

r O r6tulo outer deve ficar exatamente antes do loop while comegar. Nio imporra se na mesma linha ou nlo.

I Certifique-se de que a variAvel age seja declarada fora do loop uft i 1e.

PREI'ARAQAO PARA O E)GME

As iutrugdes continue e break rotuladas deuem ficar dentro do loop que tiaer o mesmo rotulo; cato contririo, o aldigo ndo senicombilado.

At . .ctc\JoleTrvo poro o centttcocoo

Manipulando exces6es (Obietivos 2.4 e 2.5 do exame)2.4 Escreuer aidigos quefagan uso @ropiado de excegdes e de clduvlat de nanipulapdo de exngdu (try, nhb,fnalfi) e declarar mdtodossabscrilos oa nio, os qmis /ancem exrcSdes.

2.5 Rcconbecer o efeito de ama exnpdo lanpada em um ponto etpufrn dofragwento de an cddigo. E bom ressahar que a excegdo pode ser de

tenpo de exuugdo, uerifcada oil um etro.

Um velho axioma relacionado ao desenvolvimento de softwares diz que 80 por cento do trabalho sio usados em 20 porcento 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 umemaranhado conftrso. Ainda assim, a detecgio e manipulagio de erros podem ser os ingredientes mais importantes dequalquer aplicativo robusto. A linguagemJava fornece aos desenvolvedores um mecanismo sofisticado para manipulagio deerros 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 paratestar valores retornados. Melhorainda, nos permiJe manter um c6digo de manipulagio de exceg6es nitidamente separadodo c6digo que gerariaexcegio. A16m disso, permite que o mesmo c6&go de manipulagio de exceg6es lide com as diferentesexceg6es possiveis.

O exame tem tr€s objetivos relativos ao tratamento de exce96es. Abordaremos os dois primeiros nesta segXo e, na pr6ximasegio, abordaremos os aspectos do tratamento de exceg6es que foram introduzidos no exameJava 5.

Page 228: Java - Scjp 5 - Portugues

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,

*"t -o

"rqrrirro nio puier ser aberto, a execugXo desse m6todo seri encerrada e o c6digo que foi escrito para lidar

.orn .ss"iitnagio seri processado. Portanto, precisamos de uma maneira para informar ) JVM que c6digoexecutar 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 chamadode regido protegida (que na verdade significa: "Aqui enlrari um c6digo arriscado"). IJma ou mais cliusulas catchassoJi"rio uma excegio especifica (ou classe di exceg6es - veremos mais sobre isso posteriormente) a um blocode c6digo que a manipularZ. Abaixo podemos ver o formato em pseudoc6digo:

1. try {

2. // F-ssa 6 a primeira linha da "regido protegida"

3. / / q)e 6 control-ada pela palavra-chave try.4. // Insira um c6digo agui que possa causar algum tipo de exceqao.

5. // Podemos ter muit.as linhas de c6digo aqui ou apenas uma.

6. ]'7 aalrh lMrrE'i r<l- E'v.ahf i ^h\ {\rrJr rrves.l

8. // Inslra um c6digo aqui que manipule essa exceq6o.

9. / / Essa 6 a linha seguinte do manipulador de exceeao.

10. / / F,ssa 6 a riltima linha do manipulador de exceqao'

1-1. ]1) c:l-ctr aM\rqa.^ndEynonfi nn\ {

\.rJ vvvv^.gg

13. // Insira um c6digo aqui que manipule essa excegdo.

1.4. j

15.

16. / / Algum outro c6digo nao protegido (comum, ndo arriscado) comeqar6 aqui

Nesse exemplo de pseudoc6digo, as linhas 2 a5 constituema regiio protegida que ser6 controladapela cl6usula try. Alinha sete 6 o manipulador para uma excegio do tipo MyFirstException. A Linha 12 6 um manipulador para uma excegeo

do tipo MySecondException. Observe que os blocos catch aparecem imediatamente ap6s o bloco try. Isso 6 umrequisito; se uocd tiuer um ou mait blocos catchi, eles deuem @arecer imediatamente @d: o bkco try. Al6m disso, todos os blocoscalch precisam ficar um ap6s o outro, rcm nenhuma instrugdo ou bloco entre elet A ordem na qual os blocos catch foreminseridos 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 seritransferida 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, flinhas 8 a 10 serio processadas para que todo o bloco catch seja executado e depois o processamento passar6 para a linha15 e dari prosseguimento.

Observe que se uma excegao ocorresse, digamos, na linha 3 do bloco try, as outras linhas desse bloco (4 e 5) nunca seriamexecutadas. Uma vez que o controle do flrxo salar para o bloco catch, ele nXo retornar6 para concluir o restante do blocotry. No entanto, isso dexatamenre o que queremos. Imagine se seu c6digo fosse parecido &* ttt. pt.ndoc6digo:

try {

.anl- rrraAr-r i \roNaRedg

I ei aArmr i \/nePreenchaTabela

)

catch (NdoPodeCapturarArquivoNaRede ) {

rrseArmrirrnT.ocaf

)

O pseudoc6digo anterior demonstra como geralmente as excegSes sio usadas. O c6digo que depende de uma operaEXo

arriscada (como o preenchimento de umi tabela com dados de arquivo depende da captura do arquivo na rede) foi

Page 229: Java - Scjp 5 - Portugues

JAVA 5 203

agruPado em um bloco try de uma maneira que se, digamos, a primeira operagio falhar, vocA nio dariprosseguimento na,tentativa de executar outro c6digo que com cenezatamb6m falhar|. No exemplo dopseudoc6digo, voc6 nio conseguir6 ler o arquivo se nio puderprimeiro capturiJo narede.

Um dos beneficios de us.1r a manipulagio de exceE6es 6 que o c6digo de manipulagio de alguma excegio especificaque Poss, ocorrer !a regilo controlada precisa ser escrito somente vmavez. Voltando

"o rroiso c6digo anterior, pode

haver tr6s locais diferentes-no bloco Lry capazes de gerar uma exceglo MyFirstException, mas o.rJ. qr.r q.t. .1"ocorra seri manipulada pelo mesmo bloco catch (da linha Z). Discutiremos ourros-beneficios da manipulaglo deexceg6es peno do fim deste capitulo.

Usando finallyOs blocos t.ry e catch fornecem um 6timo mecanismo de captura e manipulagi,o de exceg6es, mas ainda ficamos como problema de como nos organizar depois. J6 que a execugio 6 transferida pari fora do bloco try assim que uma excegio 6langada, nio podemos inserir nosso c6digo de limpeza no final desse blocoi esperar que seja executado se uma excegioocorrer. lJma id6ia quase tio inadequada quanto essa seria inserir o c6digo de limpezi nos blocos catch.

Os manipuladores de excegio representam um local inapropriado para a limpeza depois da execuglo do c6digo do blocotry porque cada manipulador precisari de sua pr6pria c6pia do c6digo de limpeza. Se, por exemplo, voc6 alocasse umsocket de rede ou abrisse um arquivo em um algum local & regiXo protegida, cada manipulador & excegXo teria que fechar oarquivo ou liberar o socket. Isso tornaria f6cil esquecer a inclusio da limpeza e levaria a um c6digo redundante. Para resolveresse problema, a linguagemJava oferece o bloco f ina11y.

Oblocofinally enfeixar6oc6digo,quevnpreserS,exesfiadoemalgumpontodepoisdobloco Lry,vunaexcegdoforlangada ou ndo.Mesmo se houver uma instrugio de retorno no bloco t.ry, o bloco f ina11y seri executado logo ap6s essainstrugio!Esse 6 o local certopara fecharseus arquivos,liberarseus sockets de rede e executar qualquer outralimpezaque seuc6digo necessitar. Se o bloco try for executado sem exceg6es, o bloco f ina11y ser6 processado imediataminte ap6s oblocotry serconcluido.Sehouverumaexcegio,oblocofinally seriexecutadologodepoisqueoblococatchapropriado for concluido.

Examinemos outro exemplo de pseudoc6digo:

1: try i2t // EsLa 6 a primeira linha da "regi5.o resguardada".

4: catch(MyFirstException) {

q. // Danha:mli ^ tAAi^^ para manipular este erro.

7: catch(MySecondException) {

B: // Ponha aqui o c6digo para manipular este erro.q. 1

10:

11 :

!2:1?. 1

L4:

1-5: / / l.,tais c6digo aqui

Como antes,.a execuglo 6 iniciada "a primeira linha do bloco try, a linha 2. Se nio houver exceg6es langadas no bloco try, aexecugio ser6transferida para a linha 11, aprimeira linha do bloco f inal1y. Por outro lado, se uma excegioMySecondException for langada enquanto o c6digo do bloco try estiver sendo executado, o processamento ser6 transferidopara a primeira linha do manipulador dessa excegio, a linha 8 da cldusula catch. Depois que o c6digo inteiro da cliusulacqtc|,r for executado, o programa passari para a linha 11, a primeira linha da cl6usula f inal1y. Repita comigo: acl6usula f ina11y rcmpre seni exuutada. Ok, teremos de refinir isso um pouco, mas, por agora, comect a m emorizar aidl;iadequefinally sempreseriexecutada.seaexcegioforlangada,a&iiukfinally seriexecutada.Seaexcegionaoforlangada, a clausala f inal1y tamb6m ser6 executada. Posteriormente examinaremos alguns cen6rios nos quais f ina11ypode nio ser executada ou concluida.

kmbrese de que as cl6usulas f ina11y nlo sio obrigat6rias. Se voc6 nio quiser escrwer uma, seu c6digo ser6 compilado eexecutado da mesma maneira. Na verdade, se vocA nio tiver recursos a liberar depois que seu bloco try for concluido,provavelmente nio precisari& umacl6usula f inally. A16m disso, ji que o compilador nXo exige nem mesmo cl6usulascatch, em algumas situag5es voc6 se deparard com c6digos com um bloco try imediatamente seguido porum blocof inal ly. Um c6digo dese tipo 6 6til quando a excegio 6 retornada para o metodo chamador, como explicaremos napr6xima seglo. O uso de um bloco f inalIy permitiri que o c6digo de limpeza seja executado at6 mesmo quandonXo houver uma cl6usula catch.

finally {

// Ponha aqui o c6digo para liberar qualquer recurso que

/ / |'enhamos a]ocado na c15.usu1a trv.

Page 230: Java - Scjp 5 - Portugues

204 Copitulo 5: Conlrole de fluxo, exceg6es e ossertivos

O c6digo vilido aseguir demonstra um bloco try com f inally, por6m, sem catch:

trY t

/ / faz aTgo

) finally {

// faz a limPeza

]

O c6digo v6lido a seguir demonstra os blocos try, catch e f inally:try {

/ / faz al-go

) catch (SomeException ex) t

// trata aexceqao

) finally {

// faz a limneza

)

O c6digo inudlido asegir demonstra um bloco try, sem catch ou f ina11y:

LrY {

/ / faz algo

]

/ / 5 preciso um catch ou finally aqui

System.out.println("out of try block") ;

O c6dtgo inu,itidna seguir demonstra um bloco catch inserido erroneamente:

trY {

/ / faz a1-go

)

/ / nd.o se pode ter c6digo entre trylcatchSystem.out.println( "out of try b1ock" ) ;

catch(Exception ex) { }

oBSERVAQ6ES penn O EJGME

Nda i considerado udlida asar uma cliasula try sem uma cldusula catch oa f inaLly. Uma cldusula Lry indiuidaal resaltariem um etro do conpilador. puaQuer cliusula catch deue uir inediatamente @ds o bloco try. pualquer cl,lusula f inall-y deae uirinediatanente apis a riltina cliuwla catch (ou deue seguir inedntamente o bkco Lry se ndo boauer an catch/. E unlido omitir acldusula catch ow a cllaula f inall-v, mas ndo as daas.

oBSERVAQ6ESpeneOE)(AME

V'oci ndo pode inseir nenham ctidigo entre os blocos try e catch (oa try e f inal-l-y). O cddigo a seguir nio sericonpilado:

trY {

/ / faz al-go

]

System.out.print("be1ow the try") ; // Tnv6lidotcatch(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 tryquando nio houver nenhuma cl6usula catch esperando por ela? Realmente, nio 6 um requisito a codificagio de umacliusula catch paracada excegio que possa ser langada no bloco try correspondente. Na verdade, hi drividasse 6 possivel conseguir tal proezal Quando um m6todo nio fornece uma cl6usula catch para uma excegioespecifica, diz-se que esse m6todo est6 "passando" a excegio (ou "passando a responsabilidade").

Page 231: Java - Scjp 5 - Portugues

JAVA 5 205

EntXo, o que acontecer6 a uma excegio transferida? Antes de discutirmos isso, precisamos revisar rapidamente o conceito depi/ba de rbanadar A maioria das linguagens apresenta o conceito de uma pilha ie m6todos ou de chamadas. Colocando demaneira simples, a pilha de chamadas 6 a cadeia de m6todor qn. r.,r programa executari para chegar ao m6todo atual. Se seuPrograma comeqar no m6todo main ( ) e este chamar o m6todo

-a ( ) , que chamari b m6tod6 U ( ) que, por s uavez,chamar6om6todoc( ),apilhadechamadaspoder6serrepresentadadamaneiraaseguir:

lr

"-;il" 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 nofinal. O primeiro m6todo do rastreamento de pilha serla o que voc6 estivesse executando atualmente. Se nos movAssemospara baixo na pilha, passariamos do m6todo atual para o m6todo chamado anteriormenre. A Figura 5-1. ilustra umamaneira de representar como a pilha de chamadas funciona emJava.

Agora examinaremos o que acontece )s exceg6es transferidas. Imagine um pr6dio, digamos, de cinco andares tendo em cadaandar uma varanda ou sacada. Agora imagine que em cada varanda, uma pessoa est6 vestindo uma luva de baseball. Asexceg6es sio como bolas passadas de uma pessoa a outra, comegando do riltimo andar. Primeiro a excegio 6 langada doinicio da pilha (em outras palavras, pela pessoa do riltimo andar) e se nio for capturada pela mesma pessoa que a langou (apessoa do riltimo andar), elacirS.paraom6todo anterior da pilha de chamadas, que seri a pessoa qui estivei um andarabaixo. 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. hso6 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 assimcomo 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 aplicativoao 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.

method2fl chama method30method l0 chama method2$main chama methodl0main inicia

A ordem na qual os m6todos sio colocados na pilha de chamadas

2) A pilha de chamadas enquanto method3$ esti sendo executado.A execugio volta para method2Q

I T methatQ I method2Q vai finalizar

2 [ method$-l method l() vai finalizar

t [:"3ajn"-o*J main0 vai finalizar e aJVM terminari a sua execugio

A ordem na qual os m6todos finalizam

Figuro 5-l A pilho de chomodqs de m6todos do Jovo

OBSERVAQ6ESpeneoE)(AME

Vocd pode langar ama excegio para outrot mitodos da pilba. Mas, e quando cbegar ao ruitodo main ( ) no fnal? Tanbim podeni langar aexcegdofora duse mitodo. Isso resltani em uma interrupgdo da ndq*ina uirtual Jaua [1./M, taua Virtaal Machine) e o rastreamento dapilba seni exibido na vida. O aidtgo a segair /anga ama excepio,

class TestEx {

public static void main (String [] args) t

doStuff ( ) ;

)

static void doStuff ( ) t

doMoreStuff ( ) ;

]

4

3

z

I

Page 232: Java - Scjp 5 - Portugues

206 Copftulo 5: Controle de

statici-nt

)

fluxo, exceg6es e ossertivos

void doMoreStuff O {

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 chamarioutro m6todo. Se uma excegio for langada no outro m6todo, ele teri que manipuliJa. Uma instrugio f inally seriincluida para indicar que tudo foi concluido. O m6todo chamado serd denominado reverse, e inverteri a ordem dos

caracreres da string. Se a string nXo tiver caracteres, ele propagari uma excegXo at6 o m6todo main ( ) .

I Crie uma classe chamada Propagate e um mdtodo main ( ) , que perm anecerAvazio por enquanto.

r Crie um m6todo chamado reverse. Ele usar6 como argumento e retornar6uma string.

I Em reverse, verifique se a string tem um comprimento igual a 0 usando o m6todo String . length ( ) . Se o

comprimento for igual a 0, ele langar6 uma nova excegXo.

I Agora incluiremos o c6digo para inverter a ordem da string. J6 que ess e nlo 6 o t6pico principal deste capitulo,forneceremos o c6digo de inversio, mas sinta-se lvontade parate$6lo como quiser.

String reverseStr = "";for ( int i=s. length ( ) -1; i>=0; --i ) {

reverseStr += s. charAt (i) ;

)

return reverseStr,'! Agora, no m6todo main ( ) tentaremos chamar esse m6todo e manipular qualquer excegio em potencial. Al6m disso,

incluiremos uma instruglo f inal 1y que nos informar6 que a execugio foi concluida.

Temos discutido as exceg5es como um conceito. Sabemos que elas sio langadas quando um problema de algum tipo ocorree que efeito terio sobre o flrxo de seu programa. Nesta seEio desenvolveremos os conceitos um pouco mais e usaremos as

exceg6es em um c6digoJava frrncional. Anteriormente dissemos que a exceglo 6 uma ocorr6ncia que altera o fluxo normaldo programa. Mas, ji que estamos falando deJava, tudo que nlo for um tipo primitivo deve ser... Um objeto. As exceg6es

nSosio,bem,vmaexcepioaessaregra.Todaexcegio6ainstAnciadeumaclassequepossuiaclasseException emsuahierarquia de heranga. Em outras palavras, as exceg6es sio sempre alguma subclasse de j ava . lang . Exception.

Quando uma excegXo 6langada, o objeto de um subtipo Exception especifico 6 instanciado e inserido no manipuladorde exceg6es como um argumento para a cliusula catch. Uma cllusula catch real tem este formato:

try {

/ / a1 ortm e6di qo acrui

)

catch (ArraylndexoutofBoundsException e) {

e . printStackTrace ( ) ;

)

Definindo excec6esJ

Page 233: Java - Scjp 5 - Portugues

JAVA 5 207

Nesse exemplo, e 6 a instAncia de uma classe charnada resumidamente de ArrayrndexoutofBoundsException.Como ocorreria com qualquer outro objao, vod pode chamar seus metodos.

Hierarquia de exces6es

Todas as classes de exceE6es sio subtiFos da clase Exception. Essa classe 6 derivada da classe Throwable (que 6derivada da classe obj ect). A figura 5-2 mostra a hierarquia das classes de exceg6es.

Como voc6 pode ver, hiduassubclasses que derivam de Throwable: Exception e Error. As classes que derivamde Error rePresentam situag6es incomuns que nio sio causadas por errot tro prog.ama e indicam coisas que nioocorreriam normalmente durante sua execuglo, como a JVM Ticar ..-

"rp"gJ tra mem6ria. Geralmente, os

aplicativosrrio conseguem se recuperar de-um erro, ponanto, nio precisarnos manipul6-los. Mesmo se seu c6digonio os manipular (e geralmente eles nlo o fazem), ele ainda seri compilado sem probl.-.t. Emborafreqiientemente considerados como condig6es excepcionais, o, .rror^t..nicamente nlo sio exceg6es porque nioderivam da classe Exception.No Ambito geral, uma excegio representa algo que ocorre nio como o resultado de um erro de programagio, mas, em vezdisso, porque algum recurso nio-isti disponivel ou por alguma outra condigio requerida para

" .".ltgao i"rreta nio esrar

Presente. Por exemplo, se seu aplicativo tivesse que ie com.tnica. com outro aplicativo ou computador que nio estiverrespondendo,.essa 6 uma excegio que nio:er6 causada por urn erro. A Figura S-Z tamb6m mostra um iubtipo de Excep-tion chamado RuntimeException. Essas exceg6ei sio um caso esp.iial potqne, ls vezes, indicam realm.rrt.

"rror-no Programa. Elas tamb6m podem representar condig5es excepcionais r-aras e dificeis de manipular. As exceg6es de tempode execugio serio discutidas mais detalhadamente neste capitufo.

A linguagemJava fornece muitas classes de exceg6es, a maioria delas tendo nomes bem descritivos. Hl duas maneiras deobter informag6es sobre uma excegio. A primeira 6 sobre o tipo_da propril exceglo. A outra 6 sobre as informag6es que voc6pode obter do objeto de.exceglo. A classe Throwable (no topo da 6rvoie de heranga de exceg6es) fornece aos seusdescendentes 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 fizemosno exemplo anterior, ser6 exibido o rastreamento de pilha do local onde a excegXo ocorizu

Vimos que uma pilha de chamadas 6 criada em ordem inversa com o rlltimo m6todo chamado inserido no inicio. Voc6 verique o m6todo printstackTrace ( ) exibir6 o m6todo inserido mais recentemente primeiro, e dar6 prosseguimento,exibindo o nome de cada m6todo ao percorrer a pilha de chamadas (isso 6 ch arnado de dr:ronknento fupiiba)

" piri. do

inido.

oBSERVAQ6ESpeneOE)(AME

No exam4 nio seni necessdrio conhecer nenham dot ndtodos contidot nas c/asvs Throwabl e , inc/uindo Except i on e Error.Senl esperado que uocd saiba qae ot tipos Exception, Error, RuntimeException e Throwabl e podem ser langadoscLm 0 trr7 da palatra-chaue throw e que podem ur c@turados (enbora raramente sela c@turado algo que ndo s/a un snbtipo Excep-tion).

Figuro 5-2 Hierorquio do closse Exception

Page 234: Java - Scjp 5 - Portugues

208 Copitulo 5: Controle de fluxo, exceg6es e ossertivos

Manipulando uma hierarquia inteira de classes de exces6es

Vimos que a palavra-chave catch permite a especificagXo do tipo de excegio que seri capturado. Na verdade'',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' Noentanto, se a classe especificada na clAusula catch tiver subclasses, qualquer objeto de excegio com .rabclasses da classe

especifcada mmb6m seni c@tarado.

Por exemplo, a classe TndexoutofBoundsException possui duas subclasses,

ArraylndexoutOfBound,sExcetion e Stringlnd,exOutOfBoundsExcetion. VocA pode querer escrever

um manipulador que lide com as exceg6es produzidas pelos dois tipos de erro de intervalo, mas talvez nlo esteja

preocupado com qual exceglo foi realmenti gerada. Nesse caso, poderia escrever uma cl6usula catch como a seguinte:

try {

/ / Alg,rm c6digo aqui capaz de lanqar uma excegao de limites]

catch (IndexOutOfBoundsException e) {

e . printStackTrace ( ) ;

)

Se algum c6digo do bloco try langarArrayrndexoutof BoundsExcetion ouStringlndexoutof Bound.sExcetion, a 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, voc6descartari informag6es valiosa, sobre ,^.xcegio. E claro que voc6 pode descobrt exatamente que classe de excegio foi gerad4mas se quiser fazer isso, ser6 melhor escrever uma cliusula catch separada para cada tipo de excegio que lhe interessar.

AOTRABALHO

Resista i tentagdo de esreaer somente um rzanipa/ador que captilre todas as excepdes encontradas como o descrito abaixo:

trv {

/ / o c6digo

)

catch (Exception e) {

e . printstackTrace ( ) ;

)

Esse aidtgo uai c@turar todas at excegdu geradas. E claro que nenbum manipu/ador de excegdo pode nanipular indiuidualmente de maneira

@mpiada cada exnpdo e uma pngmnagdo feita dessa maneira prejadicani o objetiuo do pnyta Ot manipuladoru de excepdo que ca?tararem

naitos enos de uma sri ueVpmuauelmenn reda{rdo a confabilidad.e de rea pmgrama Porque d possiuel que c@turem uma excegdo que ndo saibam

como tratar.

Correspond6ncia de exceg6es

Se voc6 tiver uma hierarquia de exceg6es composta de uma superclasse e virios subtipos, e estiver interessado em manipularum dos subtipos de maneira especial, manipulando todos os outros juntos, ter6 que escrever somente duas cl6usulas catch.

Quando uma excegio for langada, Java tentar6 encontrar (procurando nas cl6usulas catch disponiveis, de cima parabaixo) uma cliusula catch para o tipo da exceglo. Se nlo encontrar, ir6 procurar um manipulador para um supertipo da

excegio.Senzoencontrarumacliusulacatch quecorrespon&aosupertipodaexcegio,entAo,aexcegioser6propagadapara baixo na pilha de chamadas. Esse processo 6 chamado de coresponddncia de excegdes.

Examinemosumexemplo:

1: import java.io.*;2: public class ReadData {

3: public static void main(String arqs[] ) {

4: try {

5: RandornAccessFile raf =

6: new RandomAccessFile ( "myfile. txt", "a"; t

7: byte b[] = new byte[1000];8: raf.readFully(U, 0. 1000);

Page 235: Java - Scjp 5 - Portugues

JAVA 5 209

10: catch(FileNotFoundException e) {

11 : System. err. println ( ',Fi1e not f ound,, ) ;t2: System.err.println(e.getMessageO);13: e.printStackTraceO;t4: )

15: catch(fOException e) {

1-6: System.err.println("fO Error,');!7 : Syst.em. err.println (e. toString ( ) ) ;

18 : e. printstackTrace O ,.

1q. l

20: )

21 : j

Esse programacurto_tenta abrir um arquivo e ler alguns dados nele. A abenura e leitura de arquivos podem gerar muitasexceg6es, a maioria delas sendo algum tipo de roException. Suponha que nesse program; estiv3ssemos'inreressadosem sabersomente se a excegao hngada foi rileNotFoundnxceition. ^Caso

contr6rL, nio nos importar6saber qualfoi exatamente o problema.

FileNotFoundException 6 uma subclasse de roException. Porranto, poderiamos manipuli-la na cl6usulacatch. cuja finalidade 6 capturar todos ossubtipos de roExcep_tion, mas ter?amos que tesrar Jexcegio p"radeterminarse 6 r'ltemotFbundException. Emvezdisso, codificamos um maniputdorde exceg6es eqpecialparaFi leNotFoundException e um manipulador separado para todos os outros subtipos de toException.Seessec6digogerarumaexcegioFilelJotFoundException,elaserimanipuladapelacliusulacatch quecomeganalinha 10.Se geraroutra excegeo roException-talvezEoFException, que 6 uma subclasse de loException-elaser6manipuladapelacl6uzulacatch quecomeganalinha15.Seoutraexcegioforgerada,comoalgumtipode-excegiode tempo de execugio, nenhuma das cl6usulas catch ser6 executa&, .

" .*..glo ,. ri'propagadap".""b"i*o n" pilha de

chamadas.

Observe que acliusula caLch, de FileNotFound.Exception, foi inserida acimado manipuladordeloException. Isso d importantelSe for feito de maneira inversa, o programa nio sericomplado. Os nanipuladores deexcegdet mais espedfcos deuen sempre ser inseridos acima dos de exngdu gerais. O c6digo a seguir nio ser6 compilado:

try {

/ / faz operag6es de E/S arriscadas

) catch (IOException e) t

/ / traLa loExceptions qerais

) catch (Fil-eNotFoundException ex) {

/ / Lrata apenas FileNotFoundException

)

Voc€ obteri o seguinte erro de compilador:

TestEx. java: 15 : exception java. io. FileNotFoundException has

already been caug'ht

] catch (FileNotFoundException ex) {

Se pensarmos nas pessoas com luvas de baseball (da segio "Propagando Exceg6es Nio-Capturadas'), suponha que as luvasmais 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 doquinto andar (digamos, Fred) tiver uma grande luva lOException, nio poder6 evitar a caprura de uma bolaFileNotFoundException com ela. E se o sujeito (digamos,Jimmy) do segundo andarestiverusandoumaluvaFi leNotFoundException, essa bola nunca chegari a ele, ji que sempre ser| aparada por Fred, no quintoandar, 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 niofor o subtipo ou supeftipo da outra, enteo, a ordem na qual as cl6uiulas catch serio inseridas n1o imponar{.

Page 236: Java - Scjp 5 - Portugues

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 Ymm6todo 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 formadescrita a seguir para listar as exceg6es que um m6todo pode langar:

void myFunctionO throrus MyExceptionl, MyException2 {

/ / c6digo para o m6todo aqui

)

Esse m6todo tem um tipo de retorno void, que nio aceita argumentos e declara que langa duas exceg6es do tipoMyExceptionl eMyuxception2 (s6porqueom6todo declaraquelangaumaexcegeoniosignificaquesemPreo

fani. Ele ap enas inf o rma qu e p o fu faz|-lo).

Suponhamos que seu m6todo nio langasse diretamente uma excegXo, mas chamasse um m6todo parafa{-lo. Voc6 pode _

priferir nio manipular a excegio e, em vez disso, apenas declarA-la, como se fosse rz m6todo que realmente tivesse langado a

ixcegio. Se vocA declarar a excegio que seu m6todo capturari de outro m6todo e nlo fornecer um bloco try/catch para

ele, entlo, o m6todo propagariaexcegio devoltapara o m6todo que o chamou e elasericaptwradaai.oucontinuarS'asertransferida 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

declar-ila. Isso inclui os m6todos que nio estiverem langando-a diretamente, mas que estiverem otransferindo'e deixando a

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 ocompilador far6 uma checagem parater certez.ade que voc6 sabe que "algo inadequado pode acontecer aqui".

Lembre-se do seguinte:

Todo mdtodo deae ou tratar todat as excepdu ueificadag fomecendl ama cl,iusula catch, oa entdo listar cada exagdo uerifcada

que ndo tiuer recebido tratamento c0m0 tlma exegdo langada.

Essa regra 6 conhecida como o requisito "tratar ou declarar'deJava (is vezes chamado tamb6m de "captvrar oudeclarar').

oBSERVAQ6ES pene O F)GME

Procure aidigcs qae charuem am mdtodo para declarar ama excepdo, na qaal o ndtodo que esrtuer chamando ndo manipa/e ou declare a exceg1o

uerifcada. O cddigo a ngair (que usa a palaura-chaue throw para langar uma excegdo manaalmente - falaremos mais sobre isso a segair)

@ntenta dois grandes problenas qae o conpilador euitani:

void doStuff O idoMore ( ) ;

)

void doMoreO {

throw new foException ( ) ;

]

Primeiro, o mdtodo doMore ( ) langa uma excepdo uerifcada, mas ndo a dulara! Ponim, suponha qae o mdtodo doMore ( )

fosse corigido da maneira a segair:

void doMore O throws lOException { ... i

OnitododoStuff ( ) ainda@re-rentardproblemasporqueeletanbimprecindeclararaexcegdolOException,amenlrqileananipule por meio do fomecimento de am bloco Lry f caLch, com una cllasala catch que posta tratar a exregio

JUE;XCe1)C.r_On.

Novamente, algumas exceg6es estio dispensadas dessa regra. Um objeto do tipo RuntimeException pode ser

langldo {e Walquer m6todo sem ser especificado como parte da interface priblica do metodo (e um manipulador nlo

precisari estar presente). E mesmo se um m6todo declarar realmente uma excegio RuntimeException, om6todo que o chamar nio ser6 obrigado a manipul6-la ou declar6-la. As exceg6es RuntimeException, Error e

todos os seus subtipos sio exceg6es ndo uerifcadas, e as excegdes ndo ueifcadas ndo precisam nr especifcadas ou nanipaladas.

Aqui estl um exemplo:

import java.io.*;class Test {

Page 237: Java - Scjp 5 - Portugues

JAVA 5 2I Ipublic int myMethodl ( )

return myMethod2 O ;

)

public int myMethod2 ( )

// Ponha aqui algum

return 1;

]

throws EoFException {

throws EOFException {

c6digo para fazer o lanqamento da exceqdo

)

ExaminemosmyMethodl( ).J6queaexcegioEoFException 6subclassedeToException,que,porsuavez,6

rybclasse dg o<ception, elaser6,verificadaedeve serdeclaradacomoumaexcegeo quepode ser langadaporlsse m&odo. Masde onde realmente vir6 a exce$o? A interface priblica do m6todo mlzMethod2 ( ) cliam-ada aqui, declara que uma exce$odas5stipopodeserlangda. Se esse m6todo realmente langar6 aexceSo ouchamar6outro m6todoparalang6-14 nlotem-importAncia; apenas sabemos que temos de captlrar a exce$o ou declarar que a lanEamos. O m6todo myzt{ethodl ( ) niocaptura a excefro, portanto, decl ara que alanprL Agora examinemos outro exemplo vilido, qilethod3 ( ) .

public void myMethod3 ( ) {

// Ponha aqui algum c6digo que jogue uma NullPointerException)

De acordo como comentirio, esse m6todopode langaruma excegioNullPointerException.J6queRuntimeException 6asuperclasseimediatadeNul-lPointerException,ela6umaexcegao nioueifcadaenioprecisar6 ser declarada. Podemos ver que myMethod ( ) nio declarou nenhuma excegio.

As exceg6es de tempo de execugio sio conhecidas como excegdu ndo uerifcadas. Todas as outras exceg6es, ou seia, todasaquelas 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 niocapturar elsa e*cegio em algum local, seu c6digo nio seri compilado. E por isso que elas sio chamadas de exceg6esveri{icadas; o compilador verifica para se cenificar se elas foram declaradas ou manipuladas. Virios m6todos das bibliotecasJava 2 Standard Edition langam exceg6es verificadas, portanto, voc6 geralmente estari escrevendo manipuladores para rratarde 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 pr6priaexcegio, simplesmente crie uma subclasse de Exception (ou uma subclasse a partir das subclasses de Excep-tion) da maneira a seguir:

class MyException extends Exception { }

E sevocA langar a excegeo, o compiladorse certificar6 de que adeclare damaneira a seguir:

class TestEx {

void doStuff O {

throw new MyException (l ; / / LanCa uma exceqSo verificada

)

O c6digo anteriorpreocupari o compilador:

TestEx.java:6: unreported exception MyException; must be caught ordeclared to be thrown

l- hrar^r n6r^r M\rFv-anf i nn I \ .

oBSERVAQ6ESpeneOE)(AME

puando o objeto de um subtipo /a Exception for langado, ele teni que ser manipulado oa declarado. Esses objetos sio chamados de

excegdes uerifcadas e incluem todas as excegdes, excetl as que sio rubtipor /e RuntimeExceptiort, consideradas exupdes niouerifcadat Estla preparado para identifcar mitodos que ndo sigan a regra da ruanipulagdo ou declaragdo, coml em

class MyException extends Except.ion {

void someMethod O {

doStuff ( ) ;

]

Page 238: Java - Scjp 5 - Portugues

212 Copitulo 5: Controle de fluxo, exceE5es e ossertivos

void doStuff ( ) throws MyException

trY {

fhrat^t narrr MlrFv^ani i nn / ) .

)

catch(MyException me) {

throw me,'

)

]

Vocd terd que uber que esse cfidigo ndo serd nmpilado. Se tentar corzpild-lo, obteni

TestEx.java:8: unreported exception MyException; must be caught or

declared to be thrown

doStuff ( ) ;

RtparequesomeMethod( ) nioconseguenemtratarnemdeclararaexcepioquepodeserlangadopordoStuff O.

Voc6 teri que saber a diferenga entre um objeto Eror e exceg6es verificadas e nio verificadas. Objetos do tip o ErrornXo sXo objetos Exception, embora representem condig6es excepcionais. Tanto Exception quanto Errorcompaftilham 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) nomomento em que voc6 recebeu o erro. Em outras palavras, nio espere que a essa altura a JVM diga: "Executar ocoletor de lixo? Oh, muito obrigado por me solicitar isso. Nunca teria me ocorrido. Certo, o fareiimediatamente...". Ou melhor, o que faria se surgisse um virtualMachineError? Seu programa ji estariadanificado no momento em que voc6 capturasse o erro. Portanto, nXo hi realmente por que capturar uma dessas

gracinhas. Apenas lembre-se de que voc6 pode faz|-lot O c6digo abaixo seri compilado adequadamente:

class TestEx {

publLc static void main (String [] args) t}r:AMaFhnrl 1 \

)

static void badMethodO { / / Ndo 6 necess6ri-o declarar um errodoStuff ( )

)

static void doStuffO { // Ndo 6 necess5rio declarar um errotry {

throw new Error ( ) ;

)

catch (Error me) {

throw me; / / Capturamos, mas depois relanqamos

]

)

Se f6ssemos langar uma excegio verificada em vez de run erro, enteo, o m6todo doStuf f ( ) teria que declarar a excegio.Mas lembre: Ji que o objeto nrror nio 6 um subtipo de Exception, nio ter6 que ser declarado. Voc6 est6livre paradeclari-lo se quiser, mas o compilador simplesmente neo se impoftar6, de uma maneira ou de outra, quando ou como oerro w6,7angado, ou ainda por quem.

Page 239: Java - Scjp 5 - Portugues

JAVA 5 2I3AO TRABALHO

Jd que a linguagen Jauapwsui excegdes uerifcadat, narnalmente diq+e qae elaforga ot dercnuoluedores a manipular erros. Sim, a linguagem Jauanosforga a esmuer manipaladores para cada excegdo que possa oeornr dilrante a operapilo nomtal, mas 6 nossa responnbilidadcJaTer * qot ^f#f*"t

de excegdo realmente executem algo ilril. Conhecemos gerentet de rofware que n6o amditaran qaindo uiran am pigramador

try {

callBadl"Iethod ( ) ;

] catch (Exception ex) { }

Notou aQofaltando? Ndo onita a excepdo capturando-a sem manipuldJa realmente. Voc6 nem newo podeni informar qae a excegdolclrretl, Plrque nunca aerd o rastreamento da pi/ha.

Relangando a mesma excesao

Damesma forma que voc6 pode langaruma novaexceglo apartir de umacl6usula catch, tamb6mpodelangara mesmaexcegio que acabou de capturar. Aqui est6 uma cliusula catch que faz isto:

catch(IOException e) {

/ / paz coisas, e se voc6 decidir depois que ndo vai fazer o tratamenEo. . .

throw e;

]

Todas as outras cl6usulas catch associadas ao mesmo bloco try serio ignoradas, um bloco f ina11y, se existir, seriexecutado e a excegio ser6langada novamente para o m6todo chamador (o pr6ximo m6todo na pilha de chamadas). Se voc6langaruma excegio verificada a partir de uma cl6usula catch, tamb6m t er|, que dzclararessa excegio! Em outras palavr as,ter|quemanipularedeclarar,eniomanipular oudeclarar.Oexemploaseguirnio6v6lido:

public void doStuff ( ) {

try {

/ / operaedes de E/S arriscadas

] catch(fOException ex) {

// impossivel tratarthrow ex; / / Impossivel lanqar a ndo ser que voc6 a declare

]

Noc6digoanterior,6evidentequeom&ododoSLuff ( ) podelangarumaexcegioverificada-nessecasoumaexcegioIoException-portanto,ocompiladordir6:"Certo,6formid6velquevoc6tenhaumbloco Lry/caich ai,masnio6 o suficiente. Se voc6 quiser relangar a excegio loB<ception que capturou, teri que declariJa!".

Exercfcio 5-4

Criando uma excegao

Neste exercicio tentaremos criar uma excegio personalizada. Nio introduziremos nenhum m6todo novo (s6 os herdadosde Exception), e j6 que ela estenderi Exception, o compilador a considerar6 uma exceglo verificada. O objetivo doprograma ser6 verificar se um argumento de linha de comando, representando um alimento especifico (como uma string),sericonsiderado aceitivel ou nlo.

I Primeiro criaremos nossa excegio. Ela ser6 chama& de eadFoodException. Essa excegio seri langada quando umalimento nio aceit6vel for encontrado.

I Crie uma classe de inclusio chamada MyException e um m6todo main ( ) , que permanecerivazio porenquanto.

I Crie um m6todo chamado checkFood ( ) . Ele usar6 uma string como argumento e langari nossa excegio se nioachar aceit6vel o alimento que for fornecido. Do contr6rio, nos informari que o alimento 6 aceit6vel. VocA pode adicionari lista qualquer alimento de que nio gostar especificamente.

I Agora, no m6todo main ( ) , vocA extrair6 o argumento de linha de comando do array de strings e, em seguida,passar6 essa string para o m6todo checkFood ( ) . J6 que se trata de uma excegio verificada, om6todocheckFood ( ) precisa declar6Ja e o m6todo main ( ) teri que manipuliJa (usando um bloco trylcatch).

Page 240: Java - Scjp 5 - Portugues

214 Copitulo 5: Controle de fluxo, exceg6es e ossertivos

NXo faga com que main ( ) declare o m6todo, porque se main ( ) passar a excegXo, quem mais exar|lLparacaptur6Ja?

I Mesmo com a manip ulagilo de exceg6es sendo tXo iti7, ainda ficar| a cargo do desenvolvedor fazer uso

apropriado dela. A *"nipnl"gio de exceg6es tornarif6cil a organizagio de seu c6digo e a detecaio de

probi"-"r, mas os manipuladores de excigXo terio que ser escritos. VocA veri que.mesmo as situag6es mais

iomple"as-podem ser manipuladas e que poder6 torn"r seu c6digo reutiliz6vel, legivel e de ficil manutengio.

Obietivo poro o CertificoEdo

Erros e Exceg6es Comuns (Objetivo 2.6 do Exame)2.5 Reconhecer sinagdes qae reultaram em qaalquer um dos seguintes sendo lanpado: ArElndexOulOJBoundsException,

ClassCastException, IllegaL4rgumentException, Illegalsn*Exception, NullPointerException, NumberFormatException,

AssertionError, ExcEtionlnlnitialiTgrError, StackOuerfkwError ou NoC/astDeJFoundEmor. Entend.er qaais duset sdo lanpadot pela

miquina uiiua/ e reconhuer sitaagda em qtle nillrlr deuerio vr /angadot progmmaticammte'

O tratamenro de exceg6es 6 outra 6rea que a equipe de criagio do exame decidiu expandir para o exame SCJP 5 . Esta seglo

discute os.aspectos dasexceg6es que foram adicionadas para e$a nova v€rsio. A intengXo do Objetivo 2.6 6 certificar que voc6

est6 familiarizado com alguns dol erros e exceg6es mars comuns que rra encontrar como programadorJava.

OBSERVAQ6TSpeneOF)(AME

As questdes desta sepio prouauelmente ser6o algo do tipo :'Eh aqui algun cddigo que acabou defaTer buteira, qaal excegdo ser,l langada?"

Ao longo de exame, as questdes apretenturAt algun aldigo e lhe pedird.o para deterrztinar se o aidigo uai rodar, ou se serd lanpada una excegdo.

Uma ueTque essas que$des sdo tdo comuns, entender saas caasas ,!fundamentalpara 0 sea sacesso.

Este 6 outro dos objetivos que estarlo por todo o exame ('uma excegio 6 langada em tempo de execugio" lhe diz alguma

coisa?), entXo cenifique.se de dedicarbastante atengio aestasegio.

De Onde V6m as Exceg6esVolte i p6gina anterior e dO uma olhada na ultima frase do Obletivo 2.6.Eimportante entender o que causa exceg6es e

erros, e de onde eles v6m. Para o prop6sito de preparar voc6 para o exame, vamos definir duas categorias maiores de

exceg6es e erros:

I Exceg6es da JVM As exceg6es ou erros que sXo ou exclusivos ou mais logicamente langados pela JVM.

r Excegdes Program6ticas As exceg6es langadas explicitamente pelo aplicativo e ,/ ou pelos programadores da API.

Exceg6es Langadas pela fVMComecemos 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.ionquando 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 umgrgabFi 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

Page 241: Java - Scjp 5 - Portugues

JAVA 5 2I5stackoverf lowError. A maneira mais comum de isso acontecer 6 criando-se um m6todo recursivo. lJmm6todo recursivo 6.aqrrele que.chama a si mesmo no corpo. Embora isso possa parecer esquisito, 6 rlma t6cnicabastante 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 buraconegro; gro ( ) chamando go ( ) chamando go ( ) at6 que, nio importa quanta mem6ria voc6 tlnha, voc6 receber6 umStackoverf lowError. Novamente, apenas a JVM sabe quando esse momento ocorreri, e a JVM ser6 a fontedesse erro.

Exceg6es Langadas ProgramaticamenteV. ejamos agora as exceg5es langadas programaticamente. Lembra-se que definimos "programaticamente" como significandoalgocomo:

Criado por um aplicativo e / ou por um desenvolvedor de ApI.

Por exemplo, muitas classes na APIJava t€m m6todos que usam argumentos string, convertendo essas strings emprimitivos num6ricos. Um bom exemplo dessas classes sio as chamidas "classes wrapper" que estudamos no Capitio 3.

H6 muito tempo, algum prog{amador escreveu a classe j ava . lang . rnteger e criou m6todos como parsefnt ( ) evalueof ( ) ' Esse programador decidiu sabiamente que,-se um desses m6todos recebesse uma string que nlopudesse ser convenida em um nrimero, o m6todo deveria langar uma NumberFormatException. O16'A9oparcialmente implementado poderia se parecercom o seguinte:

int parselnt(String s) throws NunlcerFormatException {

boolean parseSuccess = false;int result = 0;

/ / faz um parsing complicado

if ( tparseSuccess) / / se o parsing tiver falhadothrow new NunlcerFormatException ( ) ;

return resul-t;]

Outros exemplos de exceg6es program6ticas incluem um AssertionError (ok, nio se trata de uma excegio, mas esseerro E langado Prograrnaticanente), elangaruma 11legalAr$unentException. Naverdad., o nosso nriticodesenvolvedordaAPlpoderiaterusadolllegalArgumentException paraoseum6todoparselntO.MasocorrequeNumberFormatException estendelllegalArgumentException e6umpoucomaisprecisa,deforma 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, elang6-las sempre que quiser. Essas exceg6es personalizadas tamb6m recaem n"."t.gori" dr "e*ceE6is langaiasProgramaticarnente'.

Um Resumo das Exceg6es e Erros para o ExameO Objetivo 2.6 lista dez exceg6es e erros especificos. Nesta segao, n6s discutimos o Stackoverf lowError. As outrasnove exceg6es e erros listados no objetivo serio abordadas em outras parres deste livro. A Tabela 5-2 resume essa lista efornece referAncias para os capinrlos onde voc6 poded encorrtr". ,,

"*fog6es e erros nio discutidos aqui.

Tobelo 5-2 Descrig6es e Fonles de ExceE6es Comuns.

Excegio (Localizagio do Capitulo) DescrigioNormalmente

Langada

ArraylndexOutOBoundsException

(Capitulo 3, "Atribuig6es") Langada ao se tentar acessar um arraycom um valor de indice invilido(ou negativo ou maior do que aextensio do array),

Pela JVM

Page 242: Java - Scjp 5 - Portugues

21 6 Cooilvlo 5: Controle de fluxo, exceE6es e ossertivos

ClassCastException(Capitulo 2, "Orientaglo a Objetos")

Langada ao se tentar converter umavari6vel de refer6ncia em um tipo que

nio passa no teste E-UM.

Pela JVM

lllegalArgumentException(Capitulo 3, "Atribuig5es")

LanQada quando um m6todo recebe

r.r* irg,r-..rto formatado de formadiferente do que o m6todo esPera.

Programaticamente

IllegalStateException(Capitulo 6, "Formataglo")

Langada quando o estado do ambientenio bate Com a operagio sendo tentada,pot:I:Tql", usando-se um Scannerque ,a lor lecnaoo.

Programaticamente

NullPointerExceDtion(Capitulo 3, "Atribuig6es")

Langada ao se tentar acessar um objetocom uma variivel de referAncia culovalor atual seia nuI1.

PelaJVM

NumberFormatException(Capitulo 6, "Formatagio")

Langada quando um m6todo que converteuma String em um nimero recebe

uma String que nio consegue converter.

Programaticamente

AssertionError (Este Capitulo) Langada quando o teste booleano de

uma instruglo retorna f af se.Programaticamente

ExceptionlnlnitializerError(Capitulo 3, "Atribuig6es")

Langada ao se tentar inicializar uma variivel Pela JVMestttica de um bloco de inicializaglo.

StackOver{lowError @ste Capitulo) Normalment e Tangada quando um m6todofaz recurs6es profundas demais(Cada chamada 6 adicionada i pilha).

Pela JVM

NoClassDeffoundError(Capitulo 10, "Desenvolvimento")

Langadaquando aJVM nio consegue encontrar PelaJVMuma classe de que precisa, por causa de um errode linha de comando, uma questao relerenteao classpath ou um arquivo . class que

esteja faltando.

,A. l r ,.t.(Jbletivo poro o centttcogoo

Trabalhando com o mecanismo de assertivas(Objetivo 2.3 do exame)

23 Esmuer aldigos qaefagan ast apropriadt de assertiuas e distingair o un de asrcftiuar adeqaado do inadequado.

Voc6 sabe que nio devefazer suposiE6es, mas nio poderievitilas quando estiver escrevendo um c6digo. VocO as

coloca em comentirios:

if (x>2&&y) {

/ / faz al-go

] else if (x .2 ll Y) {

/ / faz al-go'l o1co f

// xdeveser2/ / faz ortrra coisa

]

VocA escreve instrug6es print com elas:

while (true) {

if G>21 t

break;

Page 243: Java - Scjp 5 - Portugues

JAVA 5 217System.out.print("ff we got here something went horribly

wrong");

]

Adicionadas ) linguagem Java n? verseo 1.4, as assertivas permitireo que voc6 tesre suas suposig6es duranre odesenvolvrmento, sem o desgaste (tanto de seu tempo quanto de sobrecarga no programa) de escriver manipuladores parae.xceg6es.quesestpaenanvlcorrerdo,umavezqueoprog?amativersaidoda'faseiedlsettrolrri-.rrtoefortoialmente'distribuido.

A p1{r-do exame 31G035 (versig 1.4 do exame dgProgramadorJava Certificado pela Sun), e continuando com o exameat ull 31G055 fava5), ser6 esperado que v.oc6 conhega Js aspectoi bisicos de .o-o

", ^r.nivas (emJava) furrcioo"rrr,-

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 ( ) ) nunca ser6negalivg. No momento do teste e depuraglo, voc6 quer validar sua suposigio, mis nio que, t., qrr. ..*o ver irstrug6espint,qryupula{oresdeexcegiodetempodeexecugiooutestesif/else-quandotiverconiluidooiesenvoL'i*.nto.boi6*,'deixar todos esses recursos inseridos trar6, no minimo, um impacto no desempenho. E ai que as asseftiv.. *r"* p"r"ajudar. Observe o c6digo a seguir:

private void methodA(int num) {

if (num >= 0) {

/ / faz al-go

) el-se { / / nt:m deve ser < O

// Nunca chegaremos a este cddigolSystem.out.println(..yikes! num is a negative numberl " + num);

)

]

J6 que voc6 esti tio. certo de sua suposigio, nio guer perder tempo (ou trazer um impacto ao desempenho do programa)escrevendoumc6digodemanipulagiodeexceg6es.Enotempodeexecugio,nSodisejarestesif/Lrse insirid6spoiquese rvalnmte chegar i.condigio el sFr_isso significari que sua l6gica anterior (o que quer que estivesse sendo e*.c.rt"do^*tesdesse 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 seridentificado 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 nio s6 permitem que seu c6digo permanega mais limpo e menor, mas, como elas ficam inativas, amenos que seram especilicamente "postas em agio" (ativadas), o c6digo ser6 executado como se tivesse sidoescnto assrm:

private void methoda(int num) {

useNum(num + x), // testamos isto;/ / zaara d5laemos que est6 tudo bem aqui

]

As assertivas funcionam de maneira bem simples, Voc6 sempre assumiri qu e algo 6. uerdadeiro. Se realmente for, nio haveriProblemas. O c6digo continuar6 a ser exeiutado. Mas, se sua assertirrlr r. irortr", errada (false), eniio, serilangado um erro AssertionError (que vocA nunca, jamais deve manipular!) imediatamente,'de modo quevoc6 possa corrigir a falha na l6gica que levou ao problema.

Existem duas vers6es das assertivas: simples e muito simples, como podemos ver abaixo:

Muito simples

private void doStuff ( ) {

assert (y > x) ;

/ / mais c6digo assumindo-se que y seja maior do que x

Page 244: Java - Scjp 5 - Portugues

218 Copitulo 5: Controle de fluxo, exceE5es e ossertivos

]

Simples

private void doStuff ( ) {

assert (y > x): tty ig o + Y \r s x ig " +:t;

/,/ mais c6digo assumindo-se que y seja maior do gue x

)

A diferenga entre elas 6 que a versXo simples adiciona uma segunda exPressao, seParada da primeira (a expressio

booleana) por dois pontor, q,r. ".r.rienta

algumas informag5es a mais ao ra$rearnento da pilha. As duas vers6es

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 assertivasAs 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' Oimponante 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 umAssertionError.A segundaexpressio, usada somente naversio simples de umainstrugio assert, pode ser qualquercoisa.que resulte em

um rialor. Lembre: a segunda 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

System.out.printl-n( ),nofatodequeivocOpoderiplssarumiipoprimitivoouumobjeto,eelaoconverterdemuma representagio com Strings. Seu resultado lel que ser um valor!

O c6digo abaixo lista express6es vilidas e inv6lidas pa ra anrbar as panes de uma instruglo assert. Lemb_re-se, a exPres-

sion2 6"usada apenas com a instrugXo assert sirnples, em que a segunda expresseo existe somente para lhe dar mais

algumas informag6es para a depuragio:

void noReturno

int aReturno {

void go0 {

intx=1;boolean b =

{}return 1; )

/ / as segwj-ntes

^^^^es /.. -- 1\.aDDs!L \^ -- J/ ,

accarl- th\ .

assert true,'^^^^rr /.. -- 1 \ .

:ccarl- lv == 1 \ .

-^^^e! /-. --

1\ .oD-erL\^ -- f/ .

// as seguintes^^^^e! /..

- 1 \ .

a>-s!Lt^ - fr,

assert (x) ;

assert 0;

ac<arl- lv == 1 'l .

assert(x == 1) :

assert(x == 1) :

instrug6es assert sdo v6lidas

x;aReturnO;new ValidAssert O ;

instruqSes assert sao TNVALTDAS

// nenhuma delas 6 booleana

. / / nenhrrma del as retorna um val-or

noReturn { ) ;

ValidAssert va;

Page 245: Java - Scjp 5 - Portugues

JAVA 5 2'I9oBSERVAe6rspaneoEl<eME

Se uoc6 se dtparar cam a palawa "expressio" em uma pergunta sobre asertiuas e ela n6o especifcar n esti se refeindo i pineira express1o (aexprusio booleana) ou i rcgunda (o ualor a ser exihido n0 rastreamentl da pilhQ, entdo, ir$re prenna quiuti se ,tj'triuao i prineiraexprusio, o teste boo/eano. Por exemp/0, se /he pergmtanzos o rcguinte,

"tlma expressio assertiva deve resultar em um valor booleano, verdadeiro ou falso?',,

Preuma apa/awa 'expressdo'como nndo apimeira expressdo de uma instrugdo assert, atsim a du/aragdo dapergunta ettani comta. Sea declaragdo estiaesse se refeindo i segunda exprestdo, no entanto, ndo estaria coreta,jd que esa exprexdo pode to rloo rcsultado quaQuerua/or e ndo apenas ambooleano.

Ativando assertiyas

Sevoc6quiserusarassertivas,teri.queconsiderarprimeiro comocompilarcomelasemseuc6digoecomoser|aexecupdocomessas asseftivas 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-ChaveAntes da versio L.4, vocd poderia muito bem ter escrito um c6digo como esse:

int assert = getlnitialValue O ;

if (assert == getActualnesult O ) {

/ / faz algo

]

Observe que no c6digo anterior, assert 6 usada como um identificador. Nio haveria problema antes da versio 1.4. Maslembre-sedequevoc6niopodeusar.umapalavra<have/reservadacomoidentificador,eapartirdaversio 1.4, assert rttamoa uma palana-chaue! A, conclusio 6

VocA pode usar "assert" como uma palavra-chave ou como um identificador, mas nXo como ambos.

AOTRABALHO

SeporalgummotiuoaociestiuerusandoumconpikdorJaua/.4,eettiuerutantloassert comoumapa/aara-chaue(enoutraspa/atras,estiuer realmente tenlando nnfrrnar algo en seu aidigo), entdo, teni que atiuar explicitaaente o recofihecimento de assertiuas no ienpo derorpi/agio, como descrito abaixo:

javac -source 1.4 com/geeksanonymous/TestClass

Vocd pode ler esse aidigo assin: 'bonpila a classe hilClass do direhirio com/geeksanony.mous usando a maneira enpregadapelauersio |.4, err qtre asserL ti unapalawa-chaue".

Usando a Vercio 5 de java e javacNo que se.refere ao exame, voc6 SEMPRE estari usando a versio do compilad or Java $avac), e a versio 5 doexecutor de aplicativos Java fiava). Voc6 poder6 ver quest6es sobre vers6el mais intigas de i6digosfonres, masessas quest6es sempre estarao no contexto de compilar e executar c6digos antigos com as vers66s atuais de javac eJava.

Compilando um C6digo Atento is AsertivasO compiladorJava 5 usari a palavra-chave assert por padrio. A nio ser que voc6 o instrua do conrrd.rio, o compiladorrra gerar uma mensagem de erro se encontrar a palavra assert sendo usada como identificador. Entretanto, rroc? podedizer ao compilador que esti dando. a ele um .giligo aittlSg para compilar, e que ele deve fingir que 6 um compilador^antigo!(Mais sobre comandos do compilador no C"ptt"lg 10) pig?rnos que voc€ p_ricise fazer um ieparo ripido em^um c6digo"antigo da versio 1.3 que use assert como um identificador. Voc6 pode digitar na linha deio**iot

javac -source 1.3 CodiqoAnti_go. java

O compilador emitiri avisos quando descobrir a palavra assert usada como identificador, mas o c6digo iri compilar eexecutar. Suponha que voc6 diga ao compilador que o seu c6digo 6 da versio 1.4 ou posterior, por exemp"lo:

javac -source 1.4 CodigoNaoTaoAntigo. java

Nesse caso, o compilador emitir6 erros quando descobrir a palavra assert sendo usada como identificador.

Se quiser dizer ao compilador para usar regrasJava 5, voc6 pode fazer uma das trAs seguintes coisas: omitir a opgio -

Page 246: Java - Scjp 5 - Portugues

220 Copitulo 5: Controle de fluxo, exceq6es e ossertivos

source, que 6 o padrio, ou adicionar uma das duas seguites op96es de source:

-source 1.5 ou -source 5. (Vi,rcomodclaraadistinglodaSunentre 1.5e. 5?)

Se quiser usar assert como identificador no seu c6digo, vocA PRECISA compilar usando 19pEa" -source1 . i. A Tabela 5-3 resume a forma como o compilador java5 reagir|a assert como identificador ou como

palavra-chave.

Tobelo 5-3 Usondo Jovo 5 poro Compilor C6digo que use Assert como ldenti{icodor ou como Polovro-Chove

UnhadeComando Se assert for um Identifi cador Se assert for uma Palavra4have

javac -source 1.3 TestAsserts. java O c6digo compila com avisos. A compilagio falha.

javac -source 1.4 TestAsserts.java A compilagio falha. O c6digo compila.

javac -source 1. 5 TestAsserts. java AcompilagXofalha. O c6digo compila.

javac -source 5 TestAsserts.java A compilagio falha. O c6digo compila.

javac TestAsserts . java A compilaglo falha. O c6digo compila.

Execugio com asseltiv.urAgoracheganros ) par"te interessante. IJma ve z quevocAtiver escrito seu c6digo, o qual reconhece assenivas (em outras

.

pi"rrr^, ,rio .6digb que ,rse assert como palavrachave, para realment. .iecotar at "ssertivas

no temPo de execugio),

poderi optar por ativ6Jas ou desativllas! Lembre-se de que as asseftiuas u4n dcsatiuadarporpadrio.

Ativando assertiy.F no temPo de execugioAtive as assertivas no tempo de execu$o com

java -ea com. geeksanonymous. TestClass

ou

j ava -enableagsertiona com. geeksanonymous . TestClass

Os switches de linha de comando anteriores informam a JVM para ser executado com as assertivas ativadas.

Desativando assertiyas no tempo de execugioVoc6 tamb6m precisa conhecer os switches de linha de comando para a desativagio de assertivas,

java -da com. geeksanonymous. TestClass

ou

j ava -disableas gert Lons com. geeksanonymous . Tes tCf as s

Ji que as asseftivas slo desativad x por padfro, usar os switches de desativag5" q"+ parccer desnecess6rio. De fato, o

*o dor switches, da maneira que mostr-amos no exemplo anterior, lhe fornecer6 simplesmente o comPortam€nto ,

padrlo (em ouras palavras, vod obteri o mesmo rgsultado independente do uso dos switches & desativagio). Por6m,

vocp tamb6m pode ativar e desativar as assertivas seletivamente, -cle

modo que- elas figuem ati.vadas para.algumas

classes e/ou p"aot.r e desativadas para outros, enquanto um programa especifico estiver sendo executado.

Ativagio e desativagio seletivaOs switches de linha de comando para advaqAo e desativagio de assertivas podem ser usados de v6rias maneiras:

I Sem argumentos (como nos exemplos anteriores) Ativa ou desativa assertivas em todas as classes, exceto Para as

classes do sistema.

I Com o nome de um pacote Ativa ou desativa assertivas no pacote especificado e em qualquer Pacote abaixo

dele na mesma hierarquia de diret6rio (veremos mais detalhes sobre isso em breve).

I Com o nome de uma classe Ativa ou desativa assertivas na classe especificada.

Voc6 pode combinar switches para, digamos, desativar assertivas em somente uma classe, por6m, mantendo-as

ativadas para todas as outras classes, como descrito abaixot

java -ea -da : com. geeksanonymous' Foo

A linha de comando anterior informa ) JVM para ativar assertivas no Ambito geral, por6m, desativando-as na

classe com. geeksanonymous . Foo. Voc€ pode ter a mesma seletividade para um pacote como vemos a seguir:

I ^--^ t- - ^.lava -ea -od:com.geeksanonymous. . .

Page 247: Java - Scjp 5 - Portugues

JAVA 5 221

A linha de comando anterior informa i JVM para ativar asserrivas no imbito geral, por6m desativando-as noP-acote coru.geeksanonlmous e en todos os yus^ tubpac.oteslVoc6 pode nio estar familiarizado com o termo ubpacote, ji queele nio era muito usado antes da exist6ncia das assertivas, O nbpacote pode ser qualquer pacote de um subdiretorioO"

:::* mencionado. Por exemplo, observe a 6wore de diret6rio abaixo,

apalrcan i nr.)rmousI

_Foo

_twelvest.eps

_StepOne

_StepTvo

Essa irvore lista tr6s diret6rios.

geeksanonymous

twelvesteps

e tr6s c]asses:

com. geeksanonymous . Foo

com. geeksanonlzmous . twelvesteps. Stepone

com. geeksanonlzmous . twel-vesteps . StepT\^ro

o subpacote de com. geeksanionymous 6 o pacote twelvesteps. Lembre que emJava,com. geeksanonymous. twelvesteps 6tratado como umpacote completamente distintosem relacionamento comos pacotes acima dele (nesse exemplo, o pacote com. geeksanonl.mous), exceto por compartilharem alguns diret6rios.A Tabela 54lista exemplos de switches de linha de comando paraaativagioe desativagio de asserrivas.

Tobelo 5-4 Swilches de /inho de cornondo poro osserfivos

Exemplo de linha de comando O que significa

lava -ea

java -enableassertions Ativa assertivas

java -da

j ava -disableassertions Desativa assenivas (o comportamento padrlo da versio 1.5)

java -ea:com.foo.Bar Ativa assenivas na classe com.foo.Bar

lava -ea:com. too. Ativa assertivas no pacote com.foo e em todos os seut subpacotes

java -ea -dsa Ativa assenivas no Ambito geral, por6m desativando,as nas classes do sistema

lava -ea -da:com.too Ativa assertivas no Ambito geral, por6m desativando-as n o pacote comrfoo e em

todot os sets subpacotes

Usando as assetrivas apropriadamenteNem 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 cliusulacatch etentarumarecuperaglo.Quantolvalidade,noentanto,AssertionError 6umasubclassedefhrowal>1e, o que significa quepofuser capturada. Por6m, nio o faga! Se voc6 quiser tentar alguma recuperagio, faga-a comuma exceglo. Para &sencoraji-lo de tentar substituir uma assertiva por uma excegio, o erro AssertionError nloconcede acesso ao objeto que o gerou. Tudo que voc6 vai conseguir ser6 uma mensagem de String.Entio, quem decide o gue 6 ou nio @ropiado? A Sun. Tanto o exame quanto esta segio, usam a documentaEi.osobre assertivas "oficial" da Sun para deterrninar o uso apropriado e nio-apropriado.

Page 248: Java - Scjp 5 - Portugues

222 Copftvlo 5: Controle de fluxo, exceE5es e ossertivos

PREPARAQAO PARA O EXAME

No exame, se uocd se fuparar com a pakna "apropriado", ndo a confunda cont "u,l/ido". Apmpiado :empre se refere d maneira cono algo deue

ser usado, d.e acordo com os desenuoiuedores do-nian*no oa com as pniticas ofcialnente adotadas pela Sun. Se u\cA enc\ntrar a palaura

"cyrreto" n0 cyntex,tg das assertiaas, c0n0 en, 'A tinba 3 apretenta un uto cunetr para aJ assertiuas", tambim deue presamir qae essa pa/at'ra

uni v refeindo a como as assertiaas deaem ser xsadas em aeqde comopodeiam ser zudas dc maneira adlida.

N6o use ossertivos Pard vdlidar drgumentos de um m6todo public

O c6digo a seguir mostra um uso inapropriado das assertivas:

public void doStuff(int x) {

assert (x > 0) ;

/ / faz coisas com x

]

Umm6todopublic podeserchamadoapartirdeumc6digoquevoc6niotenhacontrole(ouquejamaistenhavisto).J6queosm6todospuniic fazempartedeiuainterfaceexpostaloambienteexterno,6precisogarantirquenenhuma?ertrigio

" "rgumentos seja imposta pelo pr6prio m6todo. Por6m, como.nio 9e pgde as-segurar que-as assertivas sejam

,.dmlrrr. e*I*tadas (normal-.ote .sao deiativadas em um aplicativo distribuido), a imposigio nio ocorrer6 se elas nioforem ativadas. Voc6 nXo ir6 querer um c6digo de acesso priblico que s6 funcio ne condicionalmente, dependendo das

assertivas estarem ou nio ativadas.

Se voc6 tiver que validar argumentos de m6todos publ ic, poder6 usar_exceg6-es para langar, digamos, umaI 1 I ega lArgumentExi ept i on se os valores passados ao m6todo nio forem v6lidos.

Use as assertiyas para validar argumentos de um m6todo PrivadoQuando vocd escrever um m6todo private, 6 quase certo que tenha escrito (ou que controle) todos os c6digos que o

ciamario. Quando quiser presumii que a l6gica do c6digo que estiver chamando s-u m6todo private est, correta,

poder6 testar essa suposigio com uma instrugio assert como a que vemos abaixo:

private void doMore(int x) {

assert (x > 0);/ / faz coisas com x

)

A rinica diferenga importante entre o o<emplo anterior e o fomecido antes dele 6 o modificador de acesso. Portango, impgnha

restrig6es aa{gumeniosprivat e,n x o}oa^6todospubl ic. E claro q.te yod pode compilarum c6digo de assertivas com

"^ irnaaZ"napropnadzdea{gumentospublic,mas,noorame(enavidareal)6precisosaberqueniadewfaz&lo.

Nio use asseltiyas para validar argumentos de linha de comandoNa verdade, esse 6 apenas um caso especial da regra: "Nio use asseftivas para validar argumentos de um m6todopubl ic'1 5" ,r, prbgr* a preitsar i"

"tgu*rttios de linha de comando, voc6 poderi ,tt"t o tttecattismo de exceg6es

para forgar sua utilizaglo.

Nio use assertiv.ilr, mesnro em m6todos Public, para procurar instrug6es c.rse que sabegue nunca ocorrereoIsso pode incluir blocos de c6digo que provavelmente nunca serio alcangados, como o bloco def ault de uma instrugioswitch 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 xtemqueserigualiZ,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 umafalha autom6tica em sua assertiva/suposigio.

Page 249: Java - Scjp 5 - Portugues

JAVA 5 223

Nio use express6es assettivas que possam causar efeitos colaterais!O c6digo a seguir seria muito inadequado:

public void doStuff ( ) {

assert (modiflrlhings( ) ) ;

// segue adiante

J

public boolean modifylhings ( ) {

x++ = y;ral- rrrn l- rrra.

)

A regra 6: Uma exprufio atserfiua deue deixar o programa no metno estado em que estaua antes da exprusdolPense nisso. Nio h6garaffia de que as express6es assertivas sejamsempre executadas, ponanto, voc6 nio ir6 querer que seu c6digo se componedilerentemente caso as assertivas sejam ativadas. As asseftivas nio devem causar nenhum efeito colateral. Se elas foremativadas, a rinica alteragio na maneira como seu programa ser6 executado 6 que um AssertionError pode ser lanEadose 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 umanalista de controle de qualidade esquentado utd ubrau/andoporque 0 sea cddigo ndofunciona, a uelha devupa de "bom, elefunciona naMINHA nAauina" ndo uai adiantar.

Resumo para a certificagioEste capitulo abordou uma 6rea vasta, toda ela envolvendo maneiras de controlar o fluxo de seu programa, com base emum teste condicional. Primeiro voc6 conheceu as instrug6es i f e swi tch. A instrugio i f avfia uma ou mais express6escom relagio a um resultado booleano. Se o resultado for true, o programa executari o c6digo do bloco que estiverinseridonainstrugioif.Seumainstrugioelse forusadaeaexpressioapresentarumresultadofalse,bc6digoposterioraelse seriexecutado.Seainstrugioelse nioforusada,nenhumdosc6digosassociadosiinstrugioitser6exectrtado.

VocA tamb6m aprendeu que a instrugio switch 6 usada para substituir virias instrug6es i f -else. A instrugeoswi tch pode avaliar tipos primitivos inteiros que possam ser conveftidos implicitamente em um tipo int (esses tiposslo byte, short, int e char), oupode avaliar enums.

No tempo de execugio, a JVM tentar6 encontrar uma coincid6ncia entre o argumento da instrugio swi tch e oargumento de uma instrugio case correspondente. Se a coincid6ncia for eniontrada, a execugio comegar6 coma.instrugio case correspondente e continuarA apaftir daiat6 que uma instrugio break surja ou que ocorra ofinal da instru$o swiLch. Se nio houver correspond€ncia, a instrusio case default ser6 executad4 caso haja uma.

VocA conheceu as tr€s estruturas de loop disponiveis na linguagem Java. Essas estruturas slo os loops f or(incluindo o for bisico e o for aprimorado que foi introduzido emJava 5), while e do. No Ambito geral, oloop for 6 usado quando sabemos quantas vezes ser6 preciso percorrer o loop. O loop whi 1e 6 usado quandonio 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$ nobloco e ser6 verificada a cada iteragio do loop. O loop do nio verifica a condigio antes de percorrer o loop umavez. O principal beneficio do loop f or 6 o recurso de iniciahzar uma ou mais vari6veis e aumentar ou diminuirseus valores na definigio do loop.

As instrug6es break e continue podem ser rotuladas ou nio-rotuladas. Quando nio 6 rotulada, a instrugiobreak forga o programa a interromper o processamenro da estnrtura mais interna de loop e prossegue na linha dec6digo 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 breakou continue for rotulada, ela seri executada da mesma maneira, com uma exceglo. A instrugio nio ser6 aplicadaao loop mais interno, emvez disso, ser6 aplicada ao loop com o r6tulo. A instrugio break geralmente 6 mais usadajunto com a instrugio switch.

Quando houver uma correspond6ncia entre a expressio switch e o valor de case, o c6digo posterior a caseseri executado. Para interromper a execugio do c6digo, seri preciso introd:uzir a instrugio break.

Voc6 viu como a linguagem Java fornece um mecanismo sofisticado de manipulagio de exceg6es. A manipulagio

Page 250: Java - Scjp 5 - Portugues

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 deverivirimediatamente depois dobloco try). Ele sempre serl chamado, exceto em casos especiais, quando o c6digo de tryoucatch emitirum System.exit( ).

O objeto de exceglo 6 uma instAncia da classe Exception ou de uma de suas subclasses. A cl6usula catch usa,

como parAmetro, uma instAncia de objeto de um tipo derivado da classe Exception. A linguagem Java exige que

todo m6todo capture a exceglo verificada que pode vir a langar ou enteo declare que langar6 a excegio. A declaragio

da excegio f.azfarte da interface priblica do m6todo. Na declaragio de uma exceglo que poder6 serlangada, apalavra-

chave throw Z usada em uma definigio do m6todo, junto com uma lista de todas as exceg6es verificadas que

poderio ser langadas.

As exceg6es de tempo de execugio sio do tipo RuntimeException (ou de uma de suas subclasses). Essas exceg6es

sio um caso especial porque nio precisam ser manipuladas ou declaradas e, portanto, sio conhecidas como exceg6es

nXo verificadas. Os erlos ilo do tipo j ava . 1ang. Error ou de suas subclasses e, como as exceg6es de tempo de

execugio, nio precisam ser manipulados ou declarados. As exceg6es verificadas incluem qualquer tipo de exceglo que

nio seja do tipo RuntimeException ou Error. Se seu c6digo nlo manipular uma excegio verificada ou declarar

que ela serilangada, ndo serA compilado. Por6m, quanto )s exceg6es nio veificadas ou objetos do tipo Error, nioimporta para o compilador se voc6 os declarou ou manipulou, se fez algo com eles ou criou alguma combinagXo de

declaragio e manipulagio. Em outras palavras, voc6 pode declar6los e manipuliJos, mas o compilador nlo se

imponar6 se fez uma ou outra coisa. No entanto, nio 6 boa priticamanipular um erro, ji que raramente vocO

poderi {azer algo para se recuperar dele.

As exceg6es podem ser geradas pela JVM ou pelo programador.

As assenivas, adicionadas i linguagem na versio 1.4, slo uma nova ferramenta ritil de depuragio. Voc6 aprendeu comopode us6Jas em testes, ativando-as, por6m, mantendo-as desadvadas quando o aplicativo for distribuido. Se voc6 tiverum 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 siocompiladas como palavras-chave por padrio, mas devem ser habilitadas explicitamente em tempo de execugio.

Voc€ aprendeu que as instrug6es assert sempre incluem uma expressXo booleana e que, se a expressXo for true, o

c6digo prosseguir6 com a execugio, mas se ela for f a1se, um AssertionError ser6 langado. Se voc6 usar a

instruglo assert de duas express6es, a segunda expressio serl avaliada, convenida para uma representagio em

String e inserida no rastreamento da pilha para fornecer mais algumas informag6es de depuragio. Para

concluir, voc6 viu por que as assertivas nio devem ser usadas para impor o uso de argumentos aos m6todos

priblicos, e por que as express6es assert nio devem apresentar efeitos colaterais!

',/ Exercicios ripidosAqui estio algtrns dos ponroschave de cada objetivo para certificagio deste capinrlo. VocA pode percorrA-los virias vezes, se

estiver interessado em passar no exame.

Escrever o c6digo usando instrug6es if e switch (Obi. 2.l)E A instrugXo i f deve ter todas as express6es enfeixadas por pelo menos um par de parOnteses.

O O rinico argumento vAlido para uma instrugio i f 6 um valor booleano, em outras palavras, uma expressio que

tenhacomo resultado umvalor ou umavariivel booleana.

E Cuidadocomatribuig6esbooleanas(:)quepodemserconfundidascomtestesdeigualdadebooleanos (==):

boolean x = false;

if (x = true) { } / / uma atribuiqdo, entdo x sempre ser6 true!

fl As chaves serio opcionais para blocos if que tiverem s6 uma instrugio condicional. Por6m, cuidado com

Page 251: Java - Scjp 5 - Portugues

JAVA 5 225

recuos enganosos.

E As instrug6es switch podem avaliar somente os tipos de dados byte, short, int e char. VocA nio podeescreven

long s = 30;

switch(s) { }

E O argumento de case deve ser umavariivel literal ou f ina1, ou uma expressio constante, incluindo um enurn" Voc6nio pode ter uma instrugio case que inclua uma variivel que nio seja final ou um intervalo de valores.

E Se a condigio de uma instrugio switch coincidir com o valor de uma instrugio case, todo o c6digo da instrugioswi tch que estiver ap6s a instrugio cas e coincidente, ser6 executado at6 que uma instrugio break ou o final dainstrugio switch seja alcangado. Em outras palavras, a instrugio case coincidente ser6 apenas o ponto de entradapara o bloco case, por6m, a menos que haja uma instrugio break, a instrugio case coincidente nio ser6 o rinicoc6digo do bloco case a ser execurado.

D Apalavra-chavedefault deveserusadaemumainstrugioswitch sevoc6quiserexecutarumc6digoquandonenhum dos valores das instrug6es case coincidir com o valor condicional.

tr Oblocodefault podeserinseridoemqualquerlocaldoblocoswitch,portanro,senenhumainstrugiocaseaPresentar correspondAncia, o bloco de f aul t ser6 executado, e se ele nlo tiver uma instrugio break, continuard a

ser executado (passagem completa) at6 o final da instrugio switch ou at6 que a instrugio break seja encontra&.

Escrevendo o c6digo usando loops (Objetivo 2.2)E UmainstrugXofor b6sicaposzuitr6spartes:adeclaragioe/ouniciahzaglo,aavaliagiobooleanaeaexpressi.ode

it€nado.

fl Se uma variivel for incrementada ou avaliada dentro de um loop f or bisico, ter6 que ser declarada antes do loop oudentro da declaragXo do loop f or.

E Uma variivel declara& (e nio apenas inicializada) dentro da declaragio do loop f or blsico nio poder6 ser acessada forado loop (em outras palavras, o c6digo abaixo do loop for nio poder6 us ar avariivel).

B Voc0 pode inicializar mais de uma variivel na primeira parte da declaragio do loop for b6sico; cada inicializaSo devariivel tem que ser separada por uma virgula.

D Uma instruglo f or aprimorada (uma novidade doJava 5) tem duas panes, a declaragio e a expressio. E usada apenasparasefazerloop atrav6s de arrays ou conjuntos.

D Com um for aprimorado, a expressio 6 o array ou conjunto atrav6s do qual voc6 dese jafazer oloop.

E Com um f or aprimorado, a declaraglo 6 avari|vel do bloco, cujo tipo 6 compativel com os elementos doaffay ov conjunto, e essa variivel cont6rn o valor do elemento para aiteraglo em questio.

tr Voc6 nXo pode usar um nfmero (antiga estrutura de linguagens do estilo C) ou outro item que nXo resulte em umvalor booleano como a condiglo de uma instrugio i f ou estrutura de loop. Nio pode, por exemplo, escrever:if (x) , a menos que x seja uma vari6vel bool-eana.

tr O loop do-while entrarino corpo do loop pelo menos umave4 mesmo se a condigio do teste nio foratendida.

Usando break e continue (Objetivo 2.2)E Uma instrugio break niorotvladafaricom que a interagio atual & estrutura de loop mais interna seja interrompida

e a linha de c6digo posterior ao loop seja executada.

E Uma instrugio continue nXo-rotulada fari com que a iteragio atual do loop mais interno seja interrompida e a

condigio desse loop seja verificada, se ela for atendida, o loop ser6 executado novamente.

E Se a instruglo break ou continue for rotulada, ela far6, com que uma agi,o semelhante ocorra no loop rotulado e

nio no loop mais interno.

Manipulando exceg6es (Objetivos 2.4,2.5 e 2.6)E As exceg6es vAm em duas vers6es: verificada e nXo verificada.

E As exceg6es verificadas incluem todos os subtipos de Exception, excluindo as classes que estendemRuntimeException.

B As exceg6es verificadas esio sujeitas I regra de manipulagio ou declaragio; qudquer m6todo que puder langar umaexcegio verificada (incluindo os m6todos que chamem outros m6todos c p^zes de realizar essa tarefa) deve

Page 252: Java - Scjp 5 - Portugues

226 Copftulo 5: Controle de fluxo, exceE5es e ossertivos

declari-lausando a palavra-chave throws ou manipul6-la com um bloco trylcatch apropriado.

E Os subtipos de Error ou RuntimeException nio sio verificados, portanto, o compilador nio imp6e a

regra de manipulagio ou declaragio. Voc6 pode manipuliJos e tamb|m declar6-los, mas o comPilador nio se

imponari se uma ou outra coisa ocorreu.

E Se voc6 usar o bloco opcional f ina]Iy, ele sempre ser6 chamado, independente de uma excegio do bloco

try correspondente ser ou nio langada e de uma excegio langada ser ou nio capturada.

tr A rinica excegio i regra do bloco f inally ser sempre chamado seri quando a JVM for encerrado. Isso

poder6 acontecer se o c6digo do bloco try ou catch chamar system. exit ( ) .

D 56 porque f inally seri chamado nlo significa que seri concluido. O c6digo do bloco f inally pode ele

pr6prio langar uma excegio ou emitir um System. exit ( ) .

O As exceg6es nio capturadas serXo propagadas para baixo na pilha de chamadas , a partir do m6todo em que a

excegio foi langada e terminando no primeiro m6todo que tiver um bloco catch correspondente a esse tipode excegio ou com o encerramento da JVM (que ocorreri se a excegio chegar a main ( ) e esse m6todopassar a exceglo declarando-a).

tr Voc6 pode criar suas pr6prias exceg6es, geralmente estendendo Exception ou um de seus subtipos. Ela sericonsiderada uma excegio verificada e o compilador fiorgarS. a aplicagio da regra de manipulagio ou declaragio a

essa excegio.

E Todos os blocos catch devem ser ordenados do mais especifico ao mais geral. Se voc6 tiver uma cliusula catch

tanto para lOException quanto para Exception, ter6 que inserir o bloco catch de TOExceptionprimeiro em seu c6digo. Do contr6rio, a excegio roException seria capturada pelo bloco catch (nx-ception e), porque um argumento catch pode capturar a excegio especificada ou qualquer um de seus

subtipos! O compilador o impedir6 de definir cl6usulas catch que nunca poderio ser alcangadas.

fl Algumas exceg6es slo criadas pelos programadores, outras pela JVM.

Trabalhando com o mecanismo de assertivasE As assenivas lhe fornecerio uma maneira de testar suas suposig6es durante o desenvolvimento e a depuragio.

E As assertivas geralmente slo ativadas durante o teste, mas desativadas durante a distribuigio.

E Voc6 pode usar assert como uma palavra-chave (na versio 1.4) ou um identificador, mas nio como ambos. Para

compilar c6digos antigos que usem asserL como um identificador (por exemplo, o nome de um m6todo), use oflagdelinhadecomando -source 1. 3 em javac.

E As assertivas sio desativadas no tempo de execuglo por padrio. Para ativi-las, use o flag de linha de comando

-ea ou -enabl-eassertions.fl VocA pode desativar as assertivas seletivamente usando o flag -da ou -disableassertions.E Se voc6 ativar ou desativar assertivas usando o flag sem nenhum argumento, estar6 ativando ou desativando-as

no Ambito geral. E possivel combinar switches de ativagio e desativagio para ter as assertivas ativadas em

algumas classes e/ou pacotes, mas nXo em outros.

D Voc6 pode ativar ou desativar assertivas por classe, usando a sintaxe a seguir:

iarra -ea -da:MvClass TestClasS

E VocA pode ativar ou desativar assertivas por pacote, e qualquer pacote que especificar tamb6m incluir6 todosos subpacotes (pacotes abaixo na hierarquia do diret6rio).

tr Nlo use assertivas paravalidar argumentos de m6todos priblicos.

tr Nio use express6es asserrivas que causem efeitos colaterais. A execugio das assertivas nio 6 sempre garantida,

portanto, nlo seri bom rer um compoftamento que se altere dependendo das assertivas estarem ativadas.

fl Use assertivas * mesmo em m6todos public- para garantir que um bloco de c6digo especifico nunca seja

alcangado. VocA pode usar assert false; para um c6digo que nunca deve ser alcangado de modo que umerro de assertiva seja langado imediatamente se a instrugio assert for executada.

Teste individual

l. Dado o seguinte c6digo:

Page 253: Java - Scjp 5 - Portugues

JAVAS 227

public class OrtegorumFunction {

public int computeDiscontinuous(int x) {

inf r - 1.

T+=X;

if ((* > 4) && (x < 10)) {

r+=2*xi) else (x <= 4) {

r+=3xX;] al qa f

r+=4*x;)

r += 5 * v.

roi. rrrn r.

)

public static void main(String [] args) {

OrtegorumFunction o = new OrtegforumFunction( ) ;

System.out.println( "OF(L1) is : .. + o.computeDiscontinuous (11) ) ;

)

]

Qual6 o resultado?

A. oF(11) is: 45

B. oF(11_) is: 56

c oF(11-) is: 89

D. oF(11) is: LL1"

E. Acompilagofalha.

- irE 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 1 false) ;

A\

E as quatro seguintes chamadas de linha de comando:

javac -source 1.3 One.javajavac -source 1.4 One.javajavac -source 1.3 Two.javajavac -source 1.4 Two.java

Qual6 o resultado? (Marque todas as corretas)

,d Apenas uma compilaeeo teri sucesso.

B. Exatamente duas compilag6es tereo sucesso.

Page 254: Java - Scjp 5 - Portugues

228 Copftulo 5: Controle de {luxo, exceg6es e ossertivos

C. Exatamente tr0s compilag6es terio sucesso.

D. Todas as quatro compilag6es terio sucesso.

E. Nenhum aviso serl produzido pelo compilador.

F. Pelo menos um aviso ser6 produzido pelo compilador.

3. Dado:import java. io. *;

c]ass Master {

String doFileStuff ( ) throws FileNotFoundException { return "a"; }

)

class Slave extends Master {

public static void main(string[] arqs) {

String s = nul1;

try { s = new SlaveO.doFileStuffO ;

] catch ( Exception x) {

s = "b"; ]

System. out . println (s ) ;

]

/ / insira o c6digo aqui

]

QualopgXo,inseridaindependentementeem // insira o c6digo aqui,iricompilareproduzirasaidab?(Marque todas as corretas)

A" String doFileStuff O { return "b"; }

B. String doFileStuff O throws IOException { return "b"; }

C String doFileStuff(int x) throws loException { return "b"; }

D. String doFileStuff O throws FileNotFoundException { return "b"; }

E. String doFileStuff O throws NunberFormatException { return "b"; iE String doFileStuff ( ) Lhrows NumberFormatException,

FileNotFoundException { return "b"; }

4. Dado:alaqc Tnhrrl- {

public static void main(string[] args) {

Strrng s = \r-";

try {

doMath(args [0] ) ;

s += "t "; // Iinha 6

]

finally { System.out.println(s += "f "); }

)

public static void doMath(String a) iint y = 1 / Integler.parselnt(a);

))E as chamadas de linha de comando:

i ^.-- T-^,.r_J4Va rrrPuL

i^--- T6-..! nJ qvq f rrPuL v

Quais afirmativas sio verdadeiras? (Marque todas as corretas)

Page 255: Java - Scjp 5 - Portugues

JAVA 5 229

A. A linha 6 6 executada exatamente O vezes.

B. A linha 5 6 executada exatamente 1 vez.

C. A linha 6 6 executada exatamente 2vezes.

D. O bloco f ina11y 6 executado exatamenre O vezes.

E. O bloco finally 6 executado exatamente 1 vez.

F. O bloco f ina11y 6 executado exatamente 2vezes.

G. Ambas as chamadas produzem as mesmas exce96es.

H. Cada chamada produz uma excegio diferente.

5. Dado:1. cl-ass Crivitch {

2. public static void main(String [] args) {

3. int x = 0;

4. // insira o c6digo aqui5. do { } while (x++ < y; t

6. System.out.println(x);t1

8. )

Qual opgio, inserida na linha 4, produz a s atd^ 12?

,{"inty=x;B.inty=10;CintY=It;D.inty=12;E. int Y = 13;

E Nenhuma das anteriores permitiri que a compilagio tenha sucesso.

6. Dado:class Pl-ane {

staticStrings=N-/'public static voj-d main(String[] args) {

new P]ane O . s1 (1 ;

System. out . println ( s ) ;

]

void s1 O {

try { s2O; )

catch (ExcePtion e) { s += "c"; }

)

void s2 ( ) throws Exception {

s3O; s += \\2";

s3O; s += "2b";)

void s3 ( ) throws Exception {

throw new ExceptionO;

)

)

Qual6 o resultado?

A"-

Page 256: Java - Scjp 5 - Portugues

230 Copitulo 5: Controle de fluxo, exceg6es e ossertivos

B. -cC -c2D. -2cE. -c22bE -2c2bG -2c2bcFL Acompila$ofalha-

7. Dado:try { int x = Integer.parsefnt("two"); }

Qual opgio poderia ser usada para se criar um bloco catch apropriado? (&Iarque todas as corretas)

A ClassCastExceptionB tllegralstateExceptionC NumberFormatExcepLion

D. t 1 legalArgumentExceptionE. Excepti-onInInitiali zerErrorF. ArraylndexOutOf BoundsException

8. Dado:1. class Ping extends Utils {

2. public static void main(String [] argrs) {

3. Util_s u = new Ping0;4. System.out.print(u.getlnt(args[0]));

;. int setrnt(strins ars) t

7 . return Integer.parselnt (arg) ;

B, }

9. )

10. class Utils {

11. int getlnt(String x) throws Exception { return 7; }

t2. j

E as tr6s modificag6es possiveis:

C1. Declarar que main ( ) langauma Exception.

C2. Declarar que Ping . getlnt ( ) langa uma Except ion.

C3. Encapsular a chamada de getrnt ( ) em um bloco try / catch.

Qual(is) modificagio(6es) permite(m) que o c6digo compile? (Marque todas as coretas)

,A. Cl sozinha 6 suficiente.

B. C2 sozinha 6 suficiente.

C C2 sozinha 6 suficiente.

D. C1 e C2 sio obrigat6rias.

E. Cl eC3 sio obrigat6rias.

E C2 e C3 sio obrigat6rias.

G Todas as trAs modificag6es sio obrigat6rias.

9. Dado:class Swi11 {

Page 257: Java - Scjp 5 - Portugues

JAVA 5 23Ipublic static void main(String[] args) {

String s = "-",'switch(Timezone.CST) {

case EST: s += \e,';

case CST: s += t c,, i

case MST: S += \m".'

default: s += rtl'rt

case PST: s += "p,,;

]

System. out . println ( s ) ;

)

)

enum TimeZone {EST, CST, MST, PST }

Qual6 o renrltado?

.4" -cB. -xC -cm

D. -cmp

E. -cmXp

E Acompila$ofalha.a 3r t -G E langada uma excegeo no tempo de execugio.

10. Dado:class Circus {

public static void main(String[] args) {

intx=9;intY=6'for(int z = 0; z < 6; z++, y--) {

if (x > 2) x--ilabel:

if(x>5) {

System.out.print(x + " ").--x;continue label-;

)

Y--.

)

Qual6 o resultado?

A"8B.87c876D. Acompila$ofalha.

E. E langada uma exce$o no tempo de exeor$o.

Page 258: Java - Scjp 5 - Portugues

232 Copitulo 5: Conlrole de fluxo, exceE6es e ossertivos

t l. Quais afirmativas s6o verdadeiras? (Marque todas as corretas)

.4. Eapropriadousarassertivasparavalidarargumentosparam6todosmarcadoscompublic.

B. li apropriado capturar e manipular erros de assertivas.

C Nao 6 apropriado usar assertivas para validar argumentos de linha de comando.

D li apropriado usar asseftivas para gerar alertas quando vod alcang um c6digo que nio deveria ser alcanEado.

E, Nna 6 apropriado que assertivas modifiquem o estado de um Programa.

12. Dado:1. class Loopy {

2. public static void main(String[] args) {

3. int[] x = {7,6,5,4,3,2,L);4. // insira o c6digo aqui

5. System.out.print(y + " ");

7. ]at

Qual opgXo, inserida independentemente na linha 4, compila? (Marque todas as corretas)

A for(int y : x) {

B for(x : int y) tC int y = 0; for(y : x) {

D. for(int y=0, z=0; z<x.length; z++l { y = xlzliE. for(int, y=9, int z=0; zcx.length,' z++) { y = xLzJ;F inL y = 6r for(int z=0; z<x.length; z++) { y = x[z];

| 3. Dado:1. class Ring {

2. f inaL stat.ic int x2 = '7 ;

3. final static Integer x4 = 8;

4. public static void main(StringlJ args) {

5 . Integer xl- = 5;

6. SLring s = "ao,'

7. if (x1 < 9) s += ttSrt

8. switch(x1) t

9 . case 5: s += \'c",'

1-0. case x2: s *= t'd";

LI- case x4: s += "e";LZ. j

L3. SysLem.out.println(s);14 ]

1s. )

Qual6 o resultado?

,{. abc

B. abcde

C A compilagio falha devido apenas a um erro na linha 7.

D. A compilagio falha devido apenas a um erro na linha 8.

E. A compila$o falha devido apenas a um erro na linha 10.

Page 259: Java - Scjp 5 - Portugues

JAVA5 233

F. A compilagio falha devido apenas a um erro na linha 11.

G. A compilagio falha devido a erros em virias linhas.

14. Dado:class Hnu {

static String s = \-" i

public static void main(String[] args) {

try {

throw ne\^/ Exception( ) ;

) catch (Exception e) {

try {

try { throw new Exception0;] catch (Exception ex) { s += "ic "; }

throw nehr Exception0; )

catch (Exception x) { s +- *mc \r }

fina11y { s += "mf "; }

) fina11y { s += "of "; }

system. out.println (s ) ;

Qual6 o renrltado?

,{. -ic ofB. -mf ofC -mc mf

D -ic mf ofE. -ic mc mf ofn -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?

Page 260: Java - Scjp 5 - Portugues

234 Copilulo 5: Controle de fluxo, exceE6es e ossertivos

A. nu1lB. null nullC. E langada uma ClassCastException.D. E langada uma NullPointerException.E. E langada uma NoClassDefFoundEror.F. E langada uma ArichmeticException.G. 6 langada uma rllegalArgumentException.H. E langada uma ArraylndexOutO f Bounds Exc ep t i on.

| 6. Quais das seguintes opg6es normalmente seo langadas pelo desenvolvedor da API ou doaplicativo, em vez de serem langadas pelaJVM? (Marque todas :$ corretirs)

A. ClassCastExceptionB. rllegalstateExceptionC. NurilcerFormatExcept ionD. r1 I egalArgumentExceptionE. ExceptionlnlnitializerError

Respostas1 Eest6correta.Ainstrugio it |invllda.Oif-else-else devesermodificadoparaif-else if-else,oque

resultariaem OF ( 11 ) 6: 111.

A, B, C, D e F estlo incorretas com base no exposto acima. (Objetivo 2.1)

2. B e F estio coretas. A classe One compilari (e emitir6 um aviso) usando o flag 1 - 3 , e a dasse Two compilar6 usando o flagL.4.

A, C, D e E estlo incorretas com base no exposto acima. (Objetivo 2.3)

3. A, D, E e F esteo corretas. E vilido que um m6todo subscritor lance as mesmas exceg6es, exceg6es mais restritas, ounenhuma exce$o. E 6 v6,lido que esse m6todo lance quaisquer exceg6es de tempo de execu$o.

B est6 incorreta porque o m6todo subscritor est6 tentando langar uma excegio mais ampla.

C est6 incorreta. Este m6todo nio subscreve , portanto, a suda 6 A. (Objetivo 2.a)

4. A, F e H estio corretas. lJma vez que ambas as chamadas langm o<ceg6es, a linha 6 nunca 6 atingida. Uma vez que ambas as

exceg6esocorreramdentrodeumbloco try, o bloco fi-na11y sempre ser6exmrtado. AprimeiracharnadalangaumaArraylndexOutOfBoundsException,easegundalangaumaarithmeticException porcausadatentativadedividirporzero.

B, C, D, E e G e$eo incorretas com base no exposto acima. (Objetivo2.5)

5. Cest6correta.x atingeovalordell,emcujopontootestewhile falha.x 6entloincrementada(depoisdotestede comparaglo!), e o m6todo println ( ) roda.

A, B, D, E e F esteo incorretas com base no exposto acima. (Objetivo2.2)

6. Besticorreta.Depoisques3Olangaaexce$opa$s2$,s2O alangaparaslO,emaisnenhumc6digodes2Oserio<ecrrtado.

A, C, D, E, F, G e FI estio incorretas com base no exposto acima. (Objetivo 2.5)

7, CeDestiocorretas. Integer.parselntpodelangarumaN'umlcerFormaLException,eIllegalArgumentException 6asuasuperclasse(ouseja,umaexcegi.omaisampla).

A, B, E e F nio estlo na hierarquia de classe de rrrumberFormatException. (Objetivo 2.5)

8. A e C estio corretas. Lembre-se de que ahrtha 4 est6fazendo uma chamada polim6rfica, de forma que o compiladorsabe que uma exceglo poder6 ser langada. Se C 1 for 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.

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 dosswi tch; ou seja uma vez encontrada uma correspond0ncia, significa que o swi tch foi iniciado, e que todos os

Page 261: Java - Scjp 5 - Portugues

JAVA 5 235

demais blocos rcdario caso nio seja encontrada nenhuma instrugio break. Observagio: d.efault nioprecisa ser o riltimo.

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

10. Dest6correta.Umcontinue rotuladofuncionaapenasparaloops.Nestecaso,emboraor6nrlosejavilido, labelnio 6 um r6tulo em uma instrugio loop, 6 um r6tulo em uma insrrugio i f .

A, B, C e E estio incorretas com base no exposto acima . (Objetivo2.2)

lL C, D e E sio instrug6es corretas.

A est6 incorreta. E aceit6vel usar assertivas para testar os argumentos de m6todos private.B esrl incorraa Embora os erros de assertivas possam ser capturados, a Sun recomenda que vod nio o faa. (Objetivo 2.3)

12' A,D eF estiocorretas.A 6umexemplodoloop for aprimorado. DeFsioexemplosdoloop for bisico.

B esti incorreta porque os selrs operandos estXo trocados. C esti incorreta porque o for aprimorado deve declarar o seuprimeiro operando. E usa sintaxe incorreta para declarar duas variiveis em uma instru$o f or. (Objetivo 2.2)

tl. F esti correta. Uma instrugio switch exige qge as suas express6es de caso sejam consrantes, e variiveis wrapper(mesmo as que forem final static) nio sio consideradas como constantes. O resto do c6digo esti correto.

A, B, C, D, E e G estlo incorretas com base no exposro acima. (Ob.ietivo 2.1)

14. E esti correta. Nio hi nenhum problema em aninhar blocos trylcatctr- Como de costume, quando uma excegio 6langada, o c6digo do bloco catch 6 executado, e depois o c6digo do bloco f ina11y 6 execuiado.

A, B, C, D e F esteo incorretas com base no exposto acima . (Objetivo 2.5)

15. E est6 correta. A chamada deveria ser j ava Miner, em cujo caso seria produzido nul1 nul1.A, B, C, D, F, G e H estio incorreras com base no exposto acima. (Objetivo 2.6)

16. B, C e D estio corretas. B no-rmalmente 6 usada para relatar um problema de ambiente, por exemplo, uma tentativa de se

acessanrm r€curso que esd fechado. C geralmente 6langda em metodos de API que tentem convefter argumentos Stringrmal-formados emvalores num6ricos. D geralmente 6langdaem m6todosdeA?Iquerecebam argumentos mal-formados.

A e E sio langadas pelaJVM. (Objetivo 2.6)

Page 262: Java - Scjp 5 - Portugues

236 Copitulo 5: Controle de fluxo, exceg6es e ossertivos

Page 263: Java - Scjp 5 - Portugues

Strings, E/S,

FormataEio eParsing

Obierlvos pqrq qcertificoe6o

II

Usor Siring, StringBuilder e

StringBuffer

E/S de Arquivos Usondo o Pocote

iovo.io

Seriolizog6o com o Pocole iovo.io

Trobolhor com Dotos, N0meros eMoedos

Usor Express6es Regulores

Exercicios 16pidos

Teste individuol

li,r'

Page 264: Java - Scjp 5 - Portugues

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 1emcom uma enorme API, e bo" p"ne do r..t trabalho como programado rJavateriaver com o uso dessa API. A equipe doexame decidiu se concentrar nas APIs de E/S, formatagio e paning. Cada um desses t6picos poderia preencher um livrointeiro. Felizmente, voc6 nXo precisar6 se tornar um guru completo de E/S ou de regex para sair-se bem no exame. Aintengio 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.

A Classe String

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 compensarpor alguns dos pontos fracos da classe String (por exemplo a imutabilidade).

Esta segXo abordar6 a classe String, e o principal conceito a se entender 6 que, uma vez criado um objeto String, ele nunca

poderi ser modificado - entio o que acontece quando um objeto String parece estar se modificando? Vamos &scobrir.

Strings sio objetos inalter6veisComegaremos com alguma informaglo de apoio sobre strinp. Naverdade, voc6 nXo precisari dessas informag6es no teste,

mas um pouco de contexcualizaglo sempre ajuda. A manipulagio de "strings" de caracteres 6 um aspecto fundamental damaioria das linguagens de programa$o. EmJava, cada caractere de uma string 6 um caractere Unicode de 16 bits. J6 que

caracteres Unicode t€m 16 bits (e nio os restritos 7 ou 8 bits que a ASCII fornece), um conjunto de caracteres sofisticado e

ntemaqonal |facilmente representado em Unicode.

EmJava, as strings sio ob.ietos. Exatamente como acontece com outros objetos, voca pode criar a instancia de uma Stringcom apalavra-chave new, como vemos abaixo:

String s = new StringO;Essa linha de c6digo cria um novo objeto da classe String e atribui a vari6vel de refer€ncia s a ele. At€ aqui os objetos Stringse parecem iguais aos outros objetos. Agora, daremos um valor a String:

s = "abcdef";

Como talvez vocA jA soubesse, a classe String possui virios construtores, portanto, podemos usar um atalho mais eficiente:

String s = new String("abcdef") ;

E j6 que voc6 usari strings o tempo todo, poderi at6 mesmo escrever o seguinte:

String s = "abcdef";

H6 algumas diferengas sutis entre essas opg6es, que discutiremos posteriormente, mas o que elas t6m em comum 6 que

todas criam um novo objeto String, com valor igual a "abcdef ", e o atribuem a uma variivel de refer6ncia r. Agora,digamos que voc6 quisesse uma segunda referAncia ao objeto String para a qual s apontasse:

String s2 = s; / / faz s2 apontar para a mesma Stringr que s

At6 aqui tudo bem. Os objetos Stringparecem e$ar se comportando exatamente como os outros objetos, portanto, porque 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 - tamb6mdiscutiremos as raz6es posteriormente, nio nos deixe esquecer. A boa nova 6 que embora o oletoStingseja inalterivel, sua

uariduel de r@nciando o 6,rpo.rtanto, continuando com nosso exemplo anterior:

s = s.concaL(" more stuff"); // o m6todo concato anexa

// um literal ao fim

Mas espere um momento, nXo acabamos de dizer que as Strings slo inalter6veis? Entlo, o que significa essa conversa de

Page 265: Java - Scjp 5 - Portugues

JAVA 5 239

"acr6scimo ao final da string"? Boapergunta; examinemos o que aconreceu realmente...

OVMpegouovalordaStrings(queera"abcd,ef") eadicionou"more stuff"aofinal,nosdandoovalor"abcdef more stuff".JiqueasStringssioinalter6veis,oVMniopoderiainseriressanovaStringnaquelareferenciada por s, poftanto, criou um novo objeto String, dzu a ele o valor "abcdef more stuf f " e fez com que so 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,porqueoargumentoliteral "more stuf f " que foi concatenado 6 por si s6 um novo objeto String. Contudo, temos referAncias apenas )'abcdef " (referenciado por s2) e "abcdef more stuf f " (referenciado por s).

E se ni.o tMssemos a visi,o ou a softe de criar uma segunda vari6vel de refer6ncia para a String "abcdef " antes de

chamarmoss = s.concat("more stuff ");?NessecasoaStringoriginalnioalteradacontendo"abcd.ef"ainda existiria na mem6ria, mas seria considerada "perdida". Nenhum c6digo de nosso programa teria como referencii-la -estaria perdid aparan6s.E bom observar, no entanto, que a String "abcdef" original nio foi alterada (nio pode ser,

lembre.se: ela b inalter,hnl; s6 a vari6vel de refer6ncia s foi alterada para referenciar uma String diferente. A F tgara Gt mostrao que acontecer6namem6riaquando voc€ reatribuirumavariivel de referAncia. A linhatracejada indicaumarefer6nciao<cluida

Para recapinrlar nosso primeiro exemplo:

String s = "abcdef"; // cria um novo objeto String, com o val-or "abcdef",

String s2 = s;

/ / faz s apontar para ele

/ / 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? OVM cria um segundo objeto String com o valor "Java Rules ! ", mas sem algo que o referencie!!! O segundo objetoString 6 perdido instantaneamente; ningu6m jamais poderi alcang6Jo. A variivel de referOncia x continuar6 referenciando oobjeto String original de valor "Java". A Figura G2 most raacriagio deum objeto String sem a atribuigio a umarefe€ncia

Iremos expandirese exemplo. Comegaremos com:

String x = "Java";x.concat(" Rules!");System. out . printl

Agora adicionemos:

x. toUpperCase O ;

System.out.println(tx = " + x) i // a saida ainda 6: x = Java

(finhamos realmente acabado de criar um novo objeto String com o valor 'JAVA", mas ele foi perdido , e x ainda relerencia a

String'Java" original inalterada). Que tal se adicionarmos:

x.replace('a', 'X');System.out.println("x = " + x) ; // a saida ainda 6: x ='Java

VocA pode dizer o que aconteceu? O VM criou mais um objeto String, com o valor "JXvX", (substituindo as letras aporx), mas novamente essanova String{oiperdida, deixando xreferenciando o objeto String original inalterado e inutduelde

Page 266: Java - Scjp 5 - Portugues

240 Copftulo 6: Strings, E/S, FormotoEdo e Porsing

Passol: String

Varidvel derefer6ncia String

Passo3: s = a,concat.

Vari6vel de

Yariivel derefer€ncla String

Figurc 6-1 Obietos Sfring e suos voridveis de refer6ncio

valor "\tava". Em todos esses casos chamamos v6rios m6todos do objeto String para criar uma nova String alterandooutra ji existente, ruls nunst aaibminos i Sting recim<iada uma vaiivel derefer6ncia.

Mas, podemos inserir umapequena inversio no exemplo anterior:

String x = ",Java";

x = x.concat(" Rules!"); // Agora estamos atribuindo x ir nova StringSystem.out.println(\rx = " + x) ; // a saida ser6:

/ / x = rTava Rules!

Dessa vez, quando o VM executar a segunda linha, um novo ob.ieto String ser6 criado com o valor Java Rules!" e x ser6configurado para referenci6-lo. Mas espere, ainda hi mais: agora o objeto String original, Java", foi perdido e ningu6m oesti referenciando. Portanto, nos dois exemplos criamos /aar objetos String e someite smavariivel de refer6ncia, & modoqug um d9s dois objetos String foi abandonado. Consulte a Figora63 par:r ver uma representaglo gr6fica desa tristeest6ria- A linhatracejada indicauma refer6ncia excluida

Examinemos esse exemplo urnpouco mais detalhadamente:

String x = "Java"ix = x.concat(" Rules!");System.out.println ( "x = N

x. tolowercase ( ) ;

System.out.println( \x = \

x = x.tolowerCaseO ,-

+ )<); // a saida 4: x = Java Rules!

/ / sem atribuiqdo, cria uma nova String abandonada

+ x); / / sem atribuiqdo, a saida ainda 6:

// x = Java Rules

/ / cria uma nova String, atribuida a x

Page 267: Java - Scjp 5 - Portugues

JAVA 5 24I

Passo l: Slring

System.out.println("x = " + x) ;

Repare que neo 6 criada nenhumavariivel de referencia Para acessar a

string'Java Rulest".

Figura 6-2 um obieto Sfring 6 obondonodo quondo criodo

// a aLrtbuiqdo origina a saida:

//x=javarules!

Varidvel de

referGncia Str

r------rtlYariivel de

refer3ncia String

A discussio anterior cont6m as chaves para a compreensXo da inalterabili&de do objeto StringJava. Se voc0 entender

realmenre os exemplos e diagramas, at6 mesmo detrilsparafrente, d€ve conseguir acenar 80 por cento das perguntas sobre

objetos String do exame.

Abordaremos mais detalhes desses objetos a seguir, mas nio se engane: em termos d€ beneficios para seu objetivo, o que i6discutimos6 de longe aparre mais imponante dacompreenslo de como osobjetos Stringfuncionam emJava.

Terminaremos esta segio apresentando um exemplo com o tipode pergunta maldosa sobre objetos String quevocO pode

esperar no exame. Nio se apresse e udlizr um papel para pensar (dica: tente manter um controle de quantos objetos e

variiveis de refer6ncia existem e quais se referem aqu€).

SLring s1 = "spring ";String s2 = s1 + "sunmer ";st.concat("fal1 ");s2.concat (s1) ;

s1 += "wi"nter " ;

System.out.println(sl- + * " + s2);

Qual seri o resultado? E quantos objetos String e vari6veis de refer6ncia foram criados antes da instruEio println?

Resposta:.O resuhado desse fragmento de c6digo 6 "spqg_winter spring summer". H6 duas variiveis de refer0ncia, s1 e

sz.^No toral foram criados oito objetos String comoisti descrito a seguir: "sprhg",."Surnmer" (p.t{{o), tptin8summer", "fall" (perdido), "springiall" (perdido), "springsummerspring" (perdido), "winter" (perdido)' "springwinter"(nesse ponto 'spring" foi perdido). 56 dois dos oito objetos String nio foram perdidos nesse Processo.

Fatos importantes relacionados aos obietos String e a mem6ria

Nesasegio discuriremos como a linguagemJavamanipulaobjetos de stringnamem6riae algumas das raz6es que estiopor tris desses compoftamentos.

Um dos objetivos principais de qualquer linguagem de plogramaglo sofisti cada|faznr vneficiente da mem6ria. Com o

crescimento dos .plicatinos, 6 muito iomum que strings literais ocupem grandes espagos da mem6ria, e que geralmente haja

muita redgndAncia dentro do universo das strings literais de um programa. Para tornar a lingu€emJava mais eficiente no

Strinl__\q-Y

Page 268: Java - Scjp 5 - Portugues

242 Copllulo 6: Strings, E/S, FormotoE6o e Porsing

Passol: String x = "Java";

Variivel dereferGncia String

Passo2: x = x. concat

Vari{vel derefer€ncia String

Repare, no Passo 2, que niloh6 nenhuma referGncia

v6lida i String'Java"; esseobjeto foi "abandonado", efoi criado um novo objeto.

Figuro 6-3 Um obiefo Sfring onfigo sendo obondonodo

Criando nov.ls stringsPrometemos 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 objeioString no pool:

1 - String s = 'abc"; / / cria um objeto String e uma

/ / varilvef de referGnciaNesse caso simples, 'abc" ser6 inserido no pool e ro referenciari.

2 - String s = new String(..abc,,); / / cria dois objetos e uma

/ / varilvel de refer6ncia

uso da mem6ria, a JVM deixa reservada uma 6rea especial chamada "pool constante de strings". Quando ocompilador encontra uma string literal, verifica o pool para ver se ji existe uma id€ntica. Se uma coincid6ncia forencontrada, a refer6ncia ao novo valor literal seri direcionadapara a String existente e nenhum objeto Stringliteral 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 paraa mesma String sem nem mesmo terem informagio disso, serra muito ruim se alguma delas pudesse ter o valor daString alterado.

Voc6 pode estar pensando: "Bem, est6 tudo muito bom, mas e se algu6m sobrescrever a funcionalidade da classeString; 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.

Nesse "aso,

j5 que-usamos a palavra-chave new, a linguagem JavaciarS,umnovo objeto String na mem6ria comum (e niono pool) e s o referenciari. Al6m disso, a string literal "abco seri inserida no pool.

M6todos impoltantes da classe StringOs m6todos a seguir sio alguns dos mais usados da classe String, a16m de serem os que mais provaveLnenteaparecerio no exame.

r charAt( ) Retornaocaracerlocalizadonoindiceespecificado

I concat( ) Anexa uma String ao final de ourra (" +" tamb|mfunciona)

",Java Rul-es !

Page 269: Java - Scjp 5 - Portugues

JAVA 5 243

I equalslgnorecase( ) Determina a igualdade de duas strings, ignorando a caixa

f length( ) Retorna o nrimero de caracreres de uma String

I replace( ) Substitui as ocorrAncias de um caracter por um outro caracter

r substring( ) Retorna uma parre de uma String

r tolowerCase( ) Retorna uma String com os caracteres em caixa alta convenidos para baixa

r toString( ) Retorna o valor de uma String

I toUpperCase( ) Retorna uma String com os caracteres em caixa baixa convertidos para alta

I trim( ) Remove os espagos em branco no inicio e no fim de Strings

Vejamos esses m6todos com mais detalhes.

public char charAt(int index) Esse m6todo retorna o caractere localizado no indice especificado da classeString. Lembre-se de que os indices de String t6m inicio no zero. Por exemplo,

String x = "airplane";system.out.println( x.charAt(2) ); // asaida6'r'

public String concat(String s) Esse m6todo retorna um objeto String com o valor da string que foi passada para eleacrescido ao final da string usadapara cham6Jo. Por exemplo,

String x = \\taxi";

System.out.println( x.concat(" cab") ) t // a saida 6 "taxi cab"

Os operadores de sobrecarregados + e + : executam fung6es semelhantes a do m6todo concat ( ) . Por exemplo,

String x = "library";System.out.println( x + " card");1. Stri-ng x = "Atlantic";2, x += \r ocean"

3. System.out.println( x );

// a saida 6 "library card"

Observe no exemplo anterior, cuja saida foi "Atlantic ocean", que o valor de x i realmente alteradollembre-se de queo operador + : 6 um ope rador de aaibuSdo, poftanto, a linha 2, na verdade, esti criando um novo objeto String, "At1an-tic ocean",eatribuindo-oavari6velx.Depoisquealinha2forexecutada,astringoriginalquex estavareferenciando,"At I ant i c ". ser6 abandonada.

/ / a saida 6 "Atlantic ocean"

publicbooleanequalslgnoreCase(Strings) Essem6todoretornariumvalorboof eano (true ou false)baseado na coincid6ncia entre o valor da String do argumento e o usado para chamar o m6todo. O m6todo retornari truemesmo quando os caracteres dos objetos String que estiverem sendo comparados tiverem caixas diferentes. Por exemplo,

String x = "Exit";system.out'print]-n(x.equa1sIgrnoreCase(..EXrT,,));//retornaSystem.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

Os arrals tdm um atribato (e n6o 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

ou

String Il x = new String[3];qi'c|-6n

^lrf nTint-'ln1 v lana|-h/l l.

public String replace(char old, char new) Esse m6todo retornari um objeto String cujo valor seri o da Stringusada para chamar o m6todo, aatalizado de modo que qualquer ocorr€ncia do tipo char do primeiro argumentoseja sobrescrita pelo do segundo. Por exemplo,

Page 270: Java - Scjp 5 - Portugues

244 Capitulo 6: Slrings, E/S, FormotoEdo e Porsing

String x = "oxoxoxox";system.out.println( x.replace('x', 'x') ); / / a saida 6 "oXoXoXoX"

public String substring(int begin)iublic String"substring(Int begfi, int end) O m6todo substring ( ) 6 usado para retornar umapane(ou.zubstring) dJobjeto Strilg empiegado na clramada do m6todo. O primeiro argumento representa o local onde a substring

.o*.9" (L*itri.io no r"ti. S..clamadas6tiverum argumento, isubstringraornadainiluir6os caracteres.mfq*"1hat6 o fini d. String original. Se a chamada tiver dois argumentos, a substring retornada terminar6 com o caractere localizxlona en6sima posigi6 dabtring original, em que n 6 repr-esentado pelo segundo argumento. In felizmente, o argumento finalnlo teri iniiio tro zero, pon-"ntol se o segwdo argumento for 7, o rihimo caractere da String retornada seri a posi$o 7 da

String original, que 6 o indice 6. Examinemos alguns exemplos:

String x = "0123456789"; / / como num passe de m6gina, o valor de cada char

// 6 o mesmo que o seu indicel

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 om&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"

System.out.println( x. toStrinS ( ) ) ; / / a saida 6 - tente descobrir!

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 umobjeto 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.prinLln ( x.substring (5) ) ;

System.out.println( x.substring(5, B) ) ;

// asaida 6 "56789"

// asaida6"567'

// o resuTLado 6 " hi//oresultado6"hix"

public String toUpperCaseS Esse m6todo retornaum objeto Stringcujovalor6 aStringusadapara chamar om6todo, por6m, com os caracteres que estiverem em letras minfsculas agoraconverddos paramairisculas. Por exemplo,

String x = "A New Moon";

System.out.println( x. toUpperCase O ) ; / / a saida 6 "A NEW MooN"

public String trimQ Esse m6todo retorna um objeto String cujo valor 6 a String usada para chamar o m6todo,por6m, com qualquer espato em branco precedente ou interno removido. Por exemplo,

c+'.in^v-\1^.i\\.vLlfrry ^ -

System.out.println( x + "x" );System.out,println( x.Erim( I + "x") ;

xn

As classes StringBufrer e StringBuilder

fu classes java.lang.StringBuffere java.lang.StringBuilder devem serusadas quando voc6 tiver que fazer muitas alterag6es emstrines de caracteres. Como discutimos na secio anterior. os obietos Strine sio inalter6veis, portanto, se vod optar por fnnrstringp de caracteres. Como discutimos na segio anterior, os objetos String sio inalter6veis, portanto, se vod opt ar por fnnrmuitas manioulac6es envolvendo esses obietos. terminar6 com virios deles abandonados em seu Dool. (Mesmo quemuitas manipulagdes envolvendo esses objetos, terminar6 com virios deles abandonados em seu pool. (Mesmo que

rcnhamos acesso agigabytes de RAMhojeem dia, nio 6 uma boaid6iadesperdigarmem6riacomobjetos dopool deStrines descartados.) Por outro lado. os obietos do tipo StrineBuffer podem ser alterados repetidamente sem deixar pStrings descartados) Por outro lado, os objetos do tipo StringDuffer podem ser repetidamente sem deixar paratr6s 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 StringBuilderA classe StringBuilder foi adicionada emJava 5. Ela tem exatamente a mesma API que a classe StringBuffer, exceto pelofato de que StringBuilder nio 6 segura em relagio aos threads. Em outras palavras, os seus m6todos nio siosincronilados. (Filaremos mais sobre a seguranga de threads no Capitulo 9.) A Sun recomenda que voc6 use

Page 271: Java - Scjp 5 - Portugues

JAVA 5 245

StringBuilder semPre que possivel, porque essa classe roda mais rapidamente (e talvez pule mais alto. tamb6m).Asstm, tirando a sincrolizagio, tudo. que dissermos sobre os m6todos de StringBuildei6 verdadeiro iamb6mPara os m6todos de StringBuffer, e vici-ve-rsa. O exame poder.i usar essas classJs na criagio de aplicativos comthreads seguros, e n6s veremos como isso funciona no Capitulo 9.

Usando StringBufrer e StringBuilderNa se-gio anterior, vimos que o exame pode testar o que voc6 entendeu sobre a inalterabilidade do objeto Stringcom fragmentos de c6digo como este:

String x = *abc";

x.concat("def");SysEem.out..println("x =' + x) ; / / a saida €! $x = abc"

J6 que nenhuma nova atribuigio foi gerada, o novo objeto String criado com o m6todo concat ( ) foiabandonado instantaneamente. Tamb6m vimos exemplos como este:

Obtivemos um objeto String novo a panir da operagio, mas a desvantagem 6 que a string "abco anterior foiperdida no pool de strings, ocupando, poftanto, espago na mem6ria. Se estiv6siemos usando um objetoStringBuffer emvez de um objeto String, o c6digo ficaria assim:

StringBuffer sb = new StringBuffer("abc");

String x = n-5."t

x = x.concat("def");SysEem.out.println("x = " + x);

sb,append(t'def ");System.out.println("sb="+sb); //

Todos os m6todos de StringBuffer que discutiremos operamm6todo. Portanto, uma chamada a sb. append ( "def " ) ,'

sb). As chamadas desses m6todos podem ser encadeadasumx

StringBuffer sb = new StringBuffer("abc");sb.append("def") .reverse() .insert (3, "---") ;

System.out.println( sb ) ;

// a saida 6 .x = abcdef"

// asaida 6 "fed---cba"

a saida 6 "sb = abcdef"

sobre o valor do objeto que estiver chamando ona aerdade ectd atescentando "def" a i mesma (StringBufferas outras. Por exemplo,

R.p.o que, em cada um dos dois enemplos anteriores, houve uma s6 chamada a new, de forma qtre, nos dois *emplos, n6snio criamos nenhum objao adicional. Cada exemplo precisou de apenas um objeto String)Gx par-arodar.

oBSERVAQoBS pene O EXAME:

Pmuauelmefie 0 exame aaaliani rcu conheciaento nbn a diferenga entre objetos Stringe StringBtlfer. Jd que os objetos StringBtfferpodeanr alteradoq ofragnento de cddigo a segair se comportari dfenntenmte de amfragnento de aidigo semelbante qrc w oSetos Shing

StringBuffer sb = new StringBuffer("abc");sb.append("def");

System.out.println( sb ) ;

Nesse caso, a saida nni; "abcddef "

M6todos importantes das classes StringBuffer e StringBuilder

O m6todo aseguir retornaum objeto StringX:orcom ovalor do argumento acrescido ao do objeto que chamouo m6todo:

public synchronized StringBuffer append(String s) Comovimos anteriormente, ese m6todo atualizar6 ovalordoobjao que o chamou, tendo ou nio o vdor de retorno sido atribuido a uma variivel. O m6todo usari muitos argumentosdiferentes, boohattot, char, furbla,Jkat, int, longe outros, por6m, o mais prov6vel de se encontrar no exame seri um objetoString.Poro<emplo,

Strj-ngBuffer sb = new StringBuffer("set ");sb.append("point") ;

System.out.println( sb ) ;

StringBuffer sb = new StringBuffer("pi = ");sb.append(3.14159f);

System.out.println( sb ) ;

// a saida 6 "set point"

// asaida 6 "pi = 3.74L59"

Page 272: Java - Scjp 5 - Portugues

246 Copitulo 6: Sirings, E/S, FormotoE6o e Porsing

System. out.println(sb.delete (4, 6) ) ;

public StringBuilder delete(int start, int end) Este m6todo retorna um objeto StringBuilder e atualiza o

ialor do objeL StringBuilder'que chamou o m6iodo. Nos dois casos, uma substring 6 removida do objeto ori,ginal.

O indice incial da su6string a ser removida 6 definido pelo primeiro argumento (que comega pelo zero), e o indice

final da substring a ser rem"ovida 6 definido pelo segundo argumento (mas este comega pelo um)! Estude o seguinte

exemplo com cuidado:

StringBuilder sb = new StringiBuilder ("0L23456789" ) ;

// asaida6"0\236789"

public StringBuilder insert(int offset, String s) Esse m6todo retorna um objeto StringBuilder e atualiza o valordo objeto StringBuilder que chamou o m6todo. Nos dois casos, o objeto String passado para o segundo argumentoser6 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 pelosegundo argumento (booleano, char, double, f 1oat, int, long e outros), mas o argumento Stringprovavelmente 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 doobjeto StringBuffer que chamou o m6todo. Nos dois casos, os caracteres do.objeto StringBuffer sio invertidos, como primeiro caractere se tornando o riltimo, o segundo se tornando o penriltimo e assim por diante:

StringBuffer sb = new StringBuffer("A man a plan a canal Panama");

sb.reverse{);System. ouL . pri-nt1n ( sb) ; / / a saida 6 "amanaP lanac a nalp a nam A"

public String toStringQ Esse m6todo retorna o valor do objeto StringBuffer que chamou o m6todo comoum objeto String:

StringBuffer sb = new StringBuffer("test string");System.out.println( sb.tostring() l; / / a saida 6 "test string"

Isso 6 rudo com relagio aos objetos StringBuffer e StringBuilder. Se houve algo que voc6 conseguiu captar nestasegio 6 que dferennnente dos objetot String, os objetos StringBffir e StingBuilderpodem ser alterados.

oBSERVAQ6TS pene O EXAME

Muitas dat perguntas do exame que abordam os fllpicos dute capitulo usam ama parte nnplicada p dfrcil de ler) da sintaxe Jaaa conhecida

como mltodos encadeados. Uma instrugio com mitodos eacadeados aPrerenta a teguinteJormageral:

resultado=m6todo1( ) .m6todo2( ) .m6todo3 ( ) ;

Na teoria, uma quantidade ilinitada de mdtodos pode or roroirodo dessa maneira, embora normalmente n6o s/am encontrados mais que tr€r.

Aqui estd como decifrar esses "atalblr pr/iticls Jaua" quando enconhd-los:

/ . Descubra o qae a chamada do mdtodo da exhvma esquerda rctomani (cbamaremos ase aa/or dc x).2. Use x como o objeto que chanari o segando ndtodo (a partir da uqaerda). Se hoauer somente dois ndtodos encadlados, o rualtado da

segttnda cbamada de mitodo ser,i o re.ruhado da express1o.

3. Se houuer am terceiro mdtldo, o res/tado da seganda chamada de mdtodo seni asado para chamar o terceim mitodo, culo reuhado senl o

resultado da expressio, Por exeuplo,

String x = "abc";String y = x.concat("def"),toUpperCaseO.replace('C','x'l; //m6todo concatenado

system.out.println("y= " +y); // o resultado 6 "ABXDEF"

Exaninemos 0 qt/e nczrrerl. O ualorliteral "def "1ki concatenado a "abc", niando um objeto Shinginarnedidio terzporiio (qre bgoseriperdido),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

Page 273: Java - Scjp 5 - Portugues

JAYA 5 247

cln'eta atandl ar seguinter cksu ()s uerys em combinagdo) dr jaua.io: BaferedReader, BffiredlViter, File, FileRtader, Filell/riter ePrifiIYriter.

O hipico referente a E/ S ten un bishirico estranho com a certifcagdo SCJP. Estaua incluido nat uendet do exame at6 a /.2, depo*foiremoyido na aersio 1 .4 e depois incluido nlaamefite na uersdo Jaua 5.

E/S 6 um t6pico imenso, de forma geral, e as APIsJava que lidam com E/S de uma forma ou de outra sio tamb6mimensas. Uma discussio geral de E/Spoderia incluir t6picos como E/S de arquivos, E,/S de conrrole, E/S de threads, E/Sdealto desempenho, E/Sorientado a.6ytes, E,/S orientalo a caracreres, filtragem e wiapping de E/S, serializaglo, e outros.Felizmente para n6s, os t6picos de E/S incluilos no exameJava 5 se restringe"m aE/S piaciacreres e serial dEi".Eis um resumo das classes de E/S que voc6 precisari entender para o exame:

I F{:. A {PI diz que a classe File 6 "uma representagio abstrata de nomes de caminho de arquivos e diret6rios". Aclasse File nlo 6 usada para ler ou escrever dados, propriamente; 6 usada para trabalhar em um nivel mais alto, criar arquivosvazios, procurar por arquivos, apagar arquivos, criar diretorios e trabalhar com caminhos.

r FileReader Esta classe 6 usada para ler arquivos de caracteres. Os seus m6todos read ( ) sXo de nivel relativamentebaixo, permitindo que voc6 leia caracteres isolados, todo o stream de caracteres ou um nrlmero fixo de caracteres. OsFileReaders normalmente slo mcapuladw (wrapped) por objetos de nivel mais alto, como BufferedReaders, os quaismelhoram 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 eficeis de rfar. Comparados com FileReaders, BufferedReaders l6em pedagos relativamente grandes de dados retirados doarquiv-o de uma s6 vez, e mantAm esses dados em um buffer. Quando voc0 pede o caracter ou linha seguinte, ele 6 retiradodo buffer, o que minimiza o nirmero de vezes que as demoradas operaE6es de leitura de arquivos serlo realizadas. Al6mdisso, BufferedReader fornece m6todos mais convenientes, como readline ( ) , que lhe permite obter a pr6xima linhade caracteres de um arquivo.

r FileVriter Esta classe 6 usada para escrever em arquivos de caracteres. Os seus m6todos write ( ) lhe permitemescrever caraderes ou Strings em um arquivo. Os File\Triters geralmente sio encapsulados por objetos \Triter di nivel maisalto, tais como Buffered$Triten ou Print'\0riters, que fornecem melhor desempenho e m6todos de alto-nivel mais flelveispara escrever dados.

r BufferedVriter Esta classe 6 us adaparatomar classes de baixo-nivel, como FileIflriters, mais eficiernes e ficeis de usar.Comparados com Filetilflriters, Buffered\0(riters escrevem pedagos relativamente grandes de dados no arquivo de uma s6 vez,minimizando o nimero de vezes que as demoradas operag6es de leitura de arquivos serio realizadas. Al6m disso, a classeBufferedVriter fornece um rn6todo newline ( ) que facilita a criagio autom6tica de separadores de linhas especificos iplataforma.

I PrintVriter Esta classe foi melhorada significativamente emJava 5. Devido aos novos m6todos e construtores (porexemplo corstruir um PrintVriter com um File ou String), voc6 poderi perceber que poder6 usar Print\(/riter em lugaresonde, anteriormente, precisava que um \Triter fosse encapsrlado com um FilerilTriter e /ou um BufferedlVriter. Novosm6todoscomo format ( ),printf O eappendO tornamosPrint$(ritersbastanteflexiveisepoderosos.

OBSERVAQ6ESpenaOH(AME

As elases de stream fio usadas para /er e etcreuer b1tes, e os Rcadert e lVriters sdo utados para ler e esmuer caratteres. (Jma ueqqae todos os

aipins de E/ S de arquiuot do exane se relacionam a caracterer, caso uoci uqfa nones de c/asses API contendo a palaura "Shvam", porexefirPll DataOutputStream, entdo a questio prouauelmente se refere d nialiqagio, ou a algo qae ndo tem a aer clm o objeto de E/ Spropianente dito.

Criando Arquivos com a Classe FileOs objetos do tipo File slo usados para representar os arquivos (mas nlo os dados dos arquivos) ou diret6rios que existemno disco fisico de um computador. Apenas para nos certificarmos que estamos sendo claros, quando falarmos de umobjeto do tipo File, diremos File, que significa arquivo em ingl€s. Quando estivermos falando sobre o que exisre em umdisco rQido, o chamaremos de arquivo, emportugu0s (a nlo ser que se trate d€ um nome de variivel em algum c6digo).Comecemos com algtrns exemplos b6sicos de criagio de arquiv.os, de escrita neles e & leitura a panir deles. Primeiramente,vamos criar um novo arquivo e escrever algumas linhas de dados nele:

// o exame Java 5 se concentra em

// classes de java.ionlaqc lalri farl I

public statj-cFile file = / / Ajnda n5o hii

// um arquivo!

void main(String [] args) {

new File ( "fileWritel. txt,, ) ;

Page 274: Java - Scjp 5 - Portugues

248 Copitulo 6: Strings, E/S, Formoloq6o e Porsing

]

]

Se voc6 compilar e rodar esse programa, quando observar o conterido do diret6rio atual, voc6 nio descobriri;br.il;;;;i;"""h"*" i"di."ia.3.

"*'"r'q"i"o chamado f ilewritel . txt. Quando cria uma nova instAncia da

classe File, uoci ndo estti criando um arqaiao propn)nede, e$ri ciando @enas um nome de _arquiuo. A.panir.do momento em que

voc6 tem um lbjetlFile,existem diversai m'aneiras de se criar um arquivo propriamente dito. Vejamos o que podemos

fazer com o objeto File que acabamos de criar:

imnar| irrra in *.JsYs.rv. ,

class Writerl- {

publj-c static void main(String []Ery {

boolean newFlle = false;File fi-le = new File

args) {

/ / aviso: possiveis exceg6es

("fileWrite1.txt"System. out.println ( f i1e. exists ( ) )

newFile = fiIe. creaLeNewPile ( ) ;

System. out . println (newFile ) ;

system. out.println (file. exists ( ) )

] catch(fOException e) { }

/ / 6 anan:q rrm ntr'iefnv syerrqs srr vvJ v ev

);i / / procura por um arquivo real

/ / Lalvez crie um arquivo!/ / iA aviqr'a?

i // olhe novamente

iIsso produz a saida

falseE.rue

t n:"* t.*b6m um arquivo vazio no seu diret6rio atual. Se voc6 rodar o c6digo nouamenle,receberi a seguinte saida

ti::.:-nar essas duas saidas:

I Primeira Execugio A primeira chamada a exists ( ) retornou f alse, que era o que esper6vamos... lembre-se de

quenew FileO nlocriaumarquivoemdisco! Om6todocreaLeNewFileO,essesim,criouumarquivoeretornou true, indicando que o novo arquivo fora criado, e que antes dele nio havia nenhum. Finalmente, n6s chamamosexistsO novamente,edestavezeleretornoutnre,indicandoqueagoraexisteoarquivoemdisco.

I SegundaExecugeo Aprimeirachamadaaexists O retornatrue porquen6scriamosoarquivoduranteaprimeira execugio. Depois, achamadaacreateNewFile ( ) retorna false, umavezqtrc o m6todo nio criou umarquivo 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 voc6escrever. 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 dosm6todos de File nesse c6digo:

I boolean exists ( ) Estem6todo retorna true se conseguirencontraro arquivo.

I bootean creat€lilevrFile ( ) Este m6todo cria um novo arquivo caso ele ainda nio exista.

oBSERVAQ6ESpeneOE)(AME

I-znbre-se de qw os criadores d.o exame estardo vmprc tentando co/ocar unagrandt q*antidade de cidigo en espaprPequenor, defonna que,

no exemplo anterior, en aeqdettas trds linbas de c6digo,

boolean newFile = false;

Page 275: Java - Scjp 5 - Portugues

JAVA s 249

newFile = file.createNewFile ( ) ;

System. out . println (newFile ) ;

Voci poderia uer algo como a seguinte linba de aldigo so{nha, o que i mais difcit de /er, mas que realiqa a muma coisa:

Syst.em. out.println (file. createNewFile ( ) ) ;

Usando FileWriter e FileReaderNa 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 atarquivo semwrapping:

import java.io.d;class writer2 {

public static void main(String [] args) {

charl] in = new char[50]; // para armazenar a ent.radaint size = 0;

trY {

File file = new File( // aper'as um objeto"fileWrite2.txt") ;

FileWriter fw =

new FileWriter(fi1e) ; / / cria um arquivo propriamente dit.ofw.wrj-te("howdy\nfolks\n,'); / / escreve caracteres no

I / arqurvofw. flush( ) ; / / Timpa antes de fecharfw.close0; / / fecha arcruivo ao terminar

FileReader fr =

newFileReader(file) ; // FileReader

/ / objeLosize=fr.read(in); //16o arquivoint.eiro!System.out.print(size + " "); // quantos bytes lidosfor(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

folksEis o que acaboude acontecer:

l.FileWriter fw = new FileWriter(file) feztr6scoisas:

a- CriouumavariiveldereferdnciaFile\Writer. fui.

b Criou um objeto FilerJfriter e o atribuiu a fi/4/.

c Criou um arquivo vazio em disco (e voc6 pode provar que isso aconteceu).

2.Escrevemost2caracteresnoarquivocomom6todowriteO,erealizamosumf}ushO eumcloseO.3. Criamos um novo objeto FileReader, que tamb6m abriu o arquivo em disco para leitura.

4. O m6todo readO leuoarquivointeiro, umcaracterdecada vez,eo colocouem char[ ] in.5. Exibimos o nfmero de caraaeres cujotamanho ('size") foi lido, e fizemos um loop atrav6s do alray rn CIdbindo cada

caracter que tenhamos lido, e depois fechamos o arquivo.

Page 276: Java - Scjp 5 - Portugues

250 Copitulo 6: Sfrings, E/S, Formotogdo e Porsing

Antesde avangarmos,vamosfalarsobre flush( ) e close( ). Quandovoc6 escreve dados emumstream, certa

quantidade de &dor r.ri"r*azenadaem buffer, e nunca 6possivel sabei ro^rrtt":.aqug{o lyfimaparte dos dados seri

,ealmerrt. en',riada. VocA pode iareaLzar mtttas operag6es & escrita emum stream antes de fech6Jo, e chamar o m6todo

f lush ( ) garante que a ,lltima parre dos dados seja de fato escrita no arquivo. Sempre que terminar de usar um arquivo,

seja lendo Ju escrevendo nele, vtc6 deve chamar o m6todo close ( ) . Ao realizar E/S de arquivos, voc6 est6 usando

recursos preciosos e limitados do sistema operacional; portanto, quando tiver terminado, libere esses recursos chamando

close ( ).

Agor4 de voka ao nosso rikimo exemplo. Aquele programa ceftantente funaonarl" mCI ele 6 inadequado por alguns motivos:

1. Quando esr6vamos escrevendo dados no arquivo, inserimos manualmente os separadores de linha (neste caso \n) em

nossos dados.

2. Quando est{vamos lendo de volta os dados, os colocamos emum array decaracteres. Por se tratar de um array, tivemos

de declarar o sen tamanho antecipadamente, de modo que teriamos problemas caso nio o ti#ssemos.feito_grande o

suficiente! Poderiamos ter lido oi d"dos .t* caracter de cada vez, procurando pelo fim do arquivo ap6s cada read ( ) ,

mas isso 6 bem inadequado tamb6m.

Devido a essas limitag6es, normalmente n6s sempre usaremos classes E/S de nivel mais alto, como BufferedWriter ou

BufferedReader, em combinafro com FilelVriter ou FileReader.

Combinando Classes de E/S

Todo o sistema de E/S deJava foi elaborado tendo-se em mente a id6ia de se usar diversas classes combinadas. Essa

combinaglo de classes de E/S 6 is vezes chamadade u.,rappingeisvezesde tncadeamento. O pacote java.io cont6m cercade 50

classes, 1.0 interfaces e 15 exceg6es. Cada classe do pacote tem um prop6sito bem especifico (criandose uma alta coesio), e as

classes foram elaboradas paraserem combinadas entre si de inrimeras formas, para lidar com uma ampla gama de situag6es.

Quando chegar a hora de trabdhar com E/S na vida real, vocA ceftamente se ver6 debrugado sobre a API java.io, tentando

descobrir de quais classes ir6 precisar, e como faz&las trabalhar juntas. Para o exame, vocA ter|, delazer o mesmo, mas n6s

reduzimos artificialmente a A?I. Em termos de estudar para o Objetivo 3.2 do exame, podemos fazer de conta que todo o

pacote java.io consiste das classes listadas no Objetivo 3.2 do exame e resumidas na Tabela6-t,a nossa mini API de E/S.

Tobelo 6-'l iovo.io Mini API

Classe

de iava.io

Estende de Argumentos Principaisdo(s) Construtor(es)

M€todos Principais

t r-l-e Obj ect k1t6 qrrrndr +:v, v er +++y

SLringString, String

createNewFi-1e ( )

delete ( )

exists ( )isDirect,ory ( )

r_st, l-le ( )

1i-st omkdir ( )renameTo ( )

FileWriter Wri-ter F'AICString

close (

f 'l rrqh /

wrrte (

Buf feredWriterWriter Wrr-terflush ( )newline ( )

write ( )

PrintWriter Writer File (em Java 5)String (em .Tava 5)r\lrt-nrrt-Q|-r6amvu uys es u! usrrl

Writer

cl-ose oflush ( )

format ( )

nrini/\Y!:frg \ / ,

write ( )

* nrint-fl\*, yrr:ru! \,

nri-r1n/\v! f rref rr \ /

FileReader Reader t areString

read ( )

read( ) readline ( )* Discutidos posteriormente

Bu f f eredReader Reader Reader

Page 277: Java - Scjp 5 - Portugues

JAVA 5 25IAgo1a, di8amos 9ue guis6ssemos achar uma maneira mais f6cil de escrever dados em um arquivo e ler o contetdo desse

Tq*"9 * *lta para a mem6ria. Comegando com a tarefa de escrever dados no arquivo, eis um processo para se determinarde quars classes rremos precisar, e como as colocaremos para trabalhar juntas:

1. Sabemos que queremos' em ultima instincia, trabalhar com um objeto File. Entio, quaisquer que sejam as outras classesque usarmos, uma delas precisa ter um constnrtor que use um objeto do tipo File.

2. Encontre um m6todo que, pelo nome, parega ser a forma mais poderosa eflclde reahzar atarefa.Observando a Tabela6-1, podemos ver que Buffered\Triter tem um m6todo newline ( ) . Isso soa um pouco melhor do que ter de colocarmanualmente um separador depois de cada linha, mas, se olharmos mais adiante, veremos que Print$riter tem umm6todo chamado println ( ) . Essa aparenta ser a abordagem mais ficil de todas, entio eicolheremos essa.

3. Quando observamos os construtores de Print\7riter, vemos que podemos construir um objeto Print\Triter se tivermosum objeto do tipo File, entio, tudo o que precisamos fazer para criar um objeto Print\Y/riter 6 o seguinte:

Ok, hora de um pequeno teste. Antes deJava 5, Print\Triter nio tinha construrores que usassem nem String nem File. Sevoc6 estivesse escrevendo um c6digo de E/S emJava 1.4, como faria um Print\flriter iscrever dado. .- ,r- Fil.? Dica: voc6pode 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 umadas pontas da cadeia, e que queremos um objeto Printtlflriter na ourra ponta. Podemos ver na Tabela GL que umPrint\(/ritertamb6mpodesercriadousando-seumobjeto\friter.Embora'Writernio seilaumachssepresintenatabela,podemos v_ er que diversas outras classes estendem S7riter, a qual 6 igualmente adequada par" os nosos prop6sitos; equalquer classe que estenda Writer 6 uma candidata. Olhando mais adiante, podemos ver que File\Triter tem os doisatributos pelos quais estamos procurando:

I Pode ser construida usando-se um File.

2. Estende\7riter.

Dadas essas informag6es, podemos escrever o seguinte c6digo (lembre.se: este 6 um exemplo deJava 1.4):

File f ile = new FiIe (..f ilewrite2 . txt.') ;

Printwri-ter pw = new Prj-ntWriter(fi1et ;

File file = new File("fileWrite2.txt,'\;FileWriter fw = new Fil-eWriter(fi1e);

new File ( "fileWrite2. txL" | ;

FileReader fr =

new FileReader(fife);

BufferedReader br =

I / cria um File/ / passa o arquivo para

// o construtor de

// PrintWriter

/ / eri a rrm otrief o Eile

/ / cria um FileWriter

/ / que enviarS. a sua

/ / saida para urn File

/ / cria um PrintWriter

/ / qre enviarii a sua

/ / saida para um Writer/ / escreve os dados

/ / eri e rrm ohiet- o File E

/ / abre "filewrite2 . txt."

/ / cria um FileReader para obter

// dados a partir de 'file'

/ / cria um BufferReader para

Printwri-ter pw = new Printwriter(fw);

pw.println( "howdy" ) ;

pw. prinLln ( " folks " ) ;

A esta dtura, dever6 ser relativamente ficil produzir o c6digo para ler mais facilmente a partir do arquivo, enviando as

informag6es para a mem6ria. Novamente, olhando na tabela, vemos um m6todo chamado readline ( ) que aparentaser uma forma bem melhor de ler dados. Passando por um processo semelhante, chegamos ao seguinte c6digo:

File file =

new Buf f eredReader ( fr),-

Page 278: Java - Scjp 5 - Portugues

252 Copllvlo 6: Strings, E/S, Formotog6o e Porsing

String data = br.readlineO;

OBSERVAQ6TS pene O EXAME

/ / obLer os seus dados a partir de um Reader

/ / Ld aLguns dados

E quase garantido qae aoci encontrari quutdu flo exame que testardo o seu conhecinento de cono as classes de E/ S poden ter encadeadas.

St)tto ,;iA*n ngdi ndo lhe tiuerfcado-clara, recoruendamos que uoci use a Tabela 6-1 cono referdncia e etcreua aldigos parafaTgr

experilncias sobre qaais combinagdes de encadramento s6o adlidat e quais sdo inudlidas.

Trabalhando com Arquivos e Diret6riosAnteriormente, n6s aludimos ao 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.

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

) em um objeto File. Por exemplo:

/ / ainda ndo existe um arquivo

// cria um arquivo. "foo", qnre

// 6atribuidoa'fi1e'

2. CriaumReader, ouumVriterouumaStream. Especificamente, criaumFileReader, umFile\flriter, umPrint\(riter,um FilelnputStream, ou um FileOutputStream. Sempre que cria uma instAncia de uma dessas classes, voc6automaticamente cria um arquivo, a nio ser que ji exista um, por exemplo:

I Chamaro m6todo createNewFile (

File file = new File("foo") ;

file . createNewFile ( ) ;

File file = new File(.'foo,');Printwriter Pw =

nevr' Printwriter ( file) ;

File myDir = new File ( "mydir" ) ;

myDir.mkdirO;

/ / ainda ndo existe um arguivo

/ / ari a rrm ohiefo PrintWriter E

// cria um arquivo, r\foo", ao qual// ,+:1a' 6 at-rihrridn E aFritrrri

/ | rri: rrm nlriol-n

/ / cria um diret6rio real

/ / 'pvr' ao PrintWriterA criagio de um diret6rio 6 semelhante I de um arquivo. Novamente, usaremos a convengio de nos referirmos a um obietodo tipo File, que represente um diret6rio real, comb um objeto Directory File, com D mairirculo (mesmo que seja do tipoFilej E chamaremos os diret6rios reais, presentes em um computador, simplesmente de diret6rio. Caramba! Assim comona 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 ( ) :

Assim que tiver um diret6rio, vocd pode colocar arquivos nele e trabalhar com esses arquivos:

rile myFile = new File(rnyDir, "myFile.LxL");myFile. createNewFile ( ) ;

Esse 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 formacomo voce poderia escrever dados no arquivo myFile:

PrintWriter pw = new PrintWriter(myFile);

Page 279: Java - Scjp 5 - Portugues

JAVA 5 253

pw.println ("new stuf f ,, ) ;

pw. flushO ;

pw.closeO;

Cuidado ao criarnovosdiret6rios! Comovimos, construirumReaderou \trfritercriariautomaticamenteumarquivo, casonio existaum, mas nio acontece o mesmo com diret6rios:

File myDir = new File("mydir',) ;

//myDit.mkdir0; // chamada amkdiro omitida!File myFile = new File(

myDir, "myFile.txt");myFile.createNewFileo; // exceqio se ndo houver mkdir!

Isso irigeraruma exce$o parecida com

java.io.IoException: No such file or direcforv

VocApodeapontarumobjetoFile paraumarquivooudiret6rioexistenre.Porexemplo,imaginequej6tenhamosumsubdiret6rio chamado existingDir, no qud reside um arquivo existingDirrile . txl, o qual cont6m algumaslinhas de texto. Quando voc6 roda o seguinte c6digo,

File existingDir = new File("existingDir,,); // atribui um diret6rioSystem. out . println ( exist j-ngDir. isDirectory ( ) ) ,

File existingDirfile = new File(existingDir, "existingDirFile.txt"); / / aluribu! um arcrurvo

System. out.println (existingDirFile. isFile ( ) ) ;

FileReader fr = new FileReader (existingDirFile) ;

BufferedReader br = new BufferedReader(fr); / / cria um Reader

String s;

while( (s = br.readline0) != nul1) // 16 dados

System. out.println (s) ;

br.closeO;

a seguinte saida serl gerada:

l-rrra

:::.r'" sub-dj-r dara

line 2 of textline 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 ummetodo f lush ( ) . Ao ler um arquivo, nXo 6 necessirio fezer flushing, de forma que vod nem sequer enconrrar6 umm6todo 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 c6digodemonstra 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 diret6riodelDir.mkdirO;

File de]Filel = new File(delDir, "de1Fi1e1.txt") ; / / adiciona um arquivo ao diret6rio

Page 280: Java - Scjp 5 - Portugues

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

System.out.println( "delDir is "

+ delDir.deleteO);

File newName = new File (

delDir, "newName.txt" ) ;

delFi1e2 . renameTo (newName ) ;

File newDir = new File("newDir");defDir. renameTo (newDir) ;

/ / adiciona um arquivo ao diret6rio

Isso gera a saida:

delDir is false

e nos deixa com um diret6rio chamado newDir que cont6m um arquivo chamado newName . txt. Eis algumas regras

que podemos deduzir desse resultado:

I delete ( ) Nio 6 possivel apagar um diret6rio se ele nio estiver vazio, que 6 o motivo pelo qual a chamadadelDir. 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 paradiscutir, que 6 aformadeprocurarporum arquivo. Panindo doprincipio quetemos umdiret6rio chamadosearchThis no qual queremos fazer a busca, o seguinte c6digo usa o m6todo File . list ( ) paracrtar vmarrayString 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; //criaalistafor(String fn: files) // iLera atrav6s dela

System.out.println( "found " + fn) ;

No nosso sistema, obtivemos a seguinte saida:

found dirlfound dir2found dir3found 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. Poroutro lado, se voc6 entendeu tudo o que abordamos nesta segio, estarl bem preparado para lidar com quaisquer perguntasreferentes a java.io no exame (exceto no que se refere d senaltza$o, que serA abordadana seg6o seguintQ.

/ / aE:aga um arquivo

/ / lcenta apagar

/ / o diret6rLo

/ / um novo objeto// renomeia o arquivo

// renomeia o diret6rio

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,

Page 281: Java - Scjp 5 - Portugues

JAVA 5 255

Filelnputstrean, Fileoatpatstrean, oblutlnputStrean, objectoutputstrean e seiati\abte.

Imagine que voc6 queira salvar o estado de um ou mais objetos. Se Java nlo tivesse a serializagio (como nio tinha,naprimeira versio), voc6 teria de usar uma das classes E/S para escrever o estado das variiveis de instAncias detodos. os objetos.que quisesse salvar. A pior parte seria tentar reconstruir novos objetos que fossem praticamenteidAnticos aos objetos que voc€ estava tentando salvar. VocA precisaria ter o seu pr6prio protocolo pira a maneirapela qual escreveria e restauraria o estado de cada obleto, caso contririo poderia aiabafdefinindoiari6veis comos valores errados. Por exemplo, imagine que voc6 tenha armazenado um objeto que tenha vari6veis de instAnciaspara altura e Peso. No momento em que silvar o estado do objeto, voc6 poderia .screvet a altura e o peso comodois ints em um arquivo, mas a ordem em que voc6 os escrevesse seria crucial. Seria muito f6cil recriar oobjeto, mas trocar os valores de altura e de peso - usando a altura salva como o valor do peso para o novo objeto e vicevena-

A serializaglo lhe permite simplesmente dizer "Salve este objeto e todas as suas variiveis de instAncias". Naverdade, 6 um pouco mais interessante do que isso, porque vocd pode adicionar'...a nio ser que eu tenhamarcado explicitamente uma vari6vel como translent, o que significa que nio 6 para incluir o valor davari6vel transiente como parte do estado serializado do objeto".

Trabalhando com ObjectOutputStream e Objectl nputStreamA migica da serializagio bisica acontece com apenas dois m6todos: uma para serializar objetos e escrevA-los emum stream, e um segundo para ler o stream e deserializar os objetos.

Obj ectOutputstream. writeobj ect ( )

Obj ectinputstream. readObj ect ( )

As classes j ava. io . Obj ectoutputstream e j ava . io . Obj ectlnputstream sio consideradas comode alto nivel no pacote java.io, e, como aprendemos anteriormente, isso significa que voc6 os usari paraencapsular classes de n(vel mais baixo, tais como java.io.FileOutputStream e java.io.Filelnputstream. Eis umpequeno programa que cria um objeto (CaQ, o serializa, e depois o deserializa:

i mnnrl. "i arra i n * .

class Cat irylenentg Serial-izalcle | | ll tpublic class SerializeCat {

public static void main(String[] args) {

Cat c = nevr c,aE(lt ll 2

try {

FileOuLputStream fsObj ectOutputstream

os.writeobject (c) ;os. close O ;

) catch (Exception e)

trv {

FilelnputStream fis

// serial-iza e escreve

// AOe deserializa

= new FileOutputstream( "testser. ser" ) ;

os = new ObjectOutputstream(fs),.

t/ 3

{ e.printstackTraceO ; }

= 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; elanlo tem nenhum m6todo para implementar. (Nas pr6ximas segSes, falaremos de virias regras sobre quandovoc6 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 quepud6ssemos de fato serializar nosso Cat. Primeiramente, tivemos de colocar todo o nosso c6digo relativo a E/Sdentro 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 m6todomigico de serializagio de que precisamos. lembre-se de que a chamada de writeobj ect ( ) realba duas tarefas:

Page 282: Java - Scjp 5 - Portugues

256 Copitulo 6: Slrings, E/S, Formoioq6o e Porsing

serializa o objeto e depois escreve o objeto serializado em um arquivo.

4. Deserializamos o objeto Cat chamando o m6todo readObject ( ). O m6todo readobject ( ) retorna umObject, de modo que precisamos convener o objeto deserializado de volta em um Cat. Novamente, tivemos de passar

pelos passos tipicos de E/S para configurar isso tudo.

Esse 6 um exemplo simplificad o da serializagno na prhtica. Ao longo das pr6ximas p6ginas, veremos algumas das quest6es

mais complexas associadas com aserializagio.

Gr6ficos de ObjetosO 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 oobjeto em outra instincia daJVM, mesmo que rodando no mesmo computador em que o objeto foioriginalmente serializado, a refer6ncia seria inritil.

Mas, e quanto ao objeto para o qual a referAncia aponta? Observe esta classe:

class Dog {

private Collar LheCollar;nrirzafe inr doqSize;

public Dog(Co1lar co1lar, int size) t

thecollar = col-Iar;doqSize = size;

)

public Coll-ar getcoll-ar() { return theCollar; }

t

nl:qq f-n]l:r f

nrirrafa int- nnl 1:rqi za.

nrrhl in /-allarlinf cizal t

public int getCol-farSize (

)

Agora crie um Dog... Primeiramente, voc6 cria um Collar (*coleira") para o Dog:

Coffar c = new Collar(3) ;

E entio cria um novo Dog, passando a ele o Collar:

Dog d = new Dog(c, 8);Agor4 o que acontece se voc6 salvar Dog? Se o objetivo 6 salvar e depois restaurar um Dog e se o Dog restaurado for umaduplicata erata daquele que foi salvo, entlo o Dog precisa de um Collar que seja uma duplicata qrata do Collarr que estavaatribuido a Dog no momento em que ese riltimo foi salvo. Isso sigpifica que tanto Dog quanto Collar devem ser salvos.

E se o pr6prio Collar tivesse referAncias a outros objetos - talvez um objeto Color, por exemplo? Isso fica bemcomplicado rapidamente. Se fosse responsabilidade do programador conhecer a estrutura interna de cada objeto a

que Dog se referisse, para que o programador pudesse salvar o estado de todos os objetos que com certezaestivessem 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 paraser restaurado. Por exemplo, se voc€ serializar um objeto Dog, o Collar seri serializado automaticamente. E se aclasse Collar contiver uma referencia a um outro objeto, esse outro objeto tamb6m seri serializado, e assim pordiante. E o rinico.objeto que voc6 precisa de-preocupar em salvar e testaurar 6 o Dog. Os outros objetos lggueridospara 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 serializiveis, antertaceSeridizable. Se quisermos ulvar objetos Dog por er<emplo, rcremos de modificar a classe Dog da seguinte forma

cfass Dog implenenLs SerLalizable {

/ / resxo do c6digo id6ntico ao anterior/ / SeriaTizabl-e ndo tem m6todos para implementar

]

E agora podemos salvar o Dog com o seguinte c6digo:

colLarSize = size; ]I I r^fr1rn nnl I arQi zo. I

Page 283: Java - Scjp 5 - Portugues

JAVA 5 257'imnnrl- i=rra in t:*'*..-..i

public class SerializeDog {

public static void main(StringlJ args) 1

Co11ar c = new Co11ar(3);

Dog d = new Dog(c, 8);trY {

FileOutputstream fs = new FileOutputstream( "testser. ser,, ) ;

ObjectOutputstream os = new ObjectOutputstream(fs),.os.writeObject (d) ;

os. close O ,.

) catch (Exception e) i e.printstackTraceO; )

)

]

Por6m, quando executarmos esse c6digo, receberemos uma exceEio de tempo de execuEio parecida com esta

java. io.NotSerializableException: Co1lar

O que foi que esquecemos? A classe Collar TAMBEM deve ser Serializable. Se modificarmos a classe Collar e atornarmos serializ6vel, enteo neo haverh problemas:

class Collar implements Serializable {

// mesma coisa

)

Eis a listagem completa:

import java.io.*;pubfic class SerializeDog {

public static void main(String[] arqs) t

Collar c = new Collar(3) ;

Dog d = new Dog(c, 5);Svsrem orrf . nri nf l n ( "hefore. co11ar size is "

+ d. getCollar ( ) .getCollarSize ( ) ) ;

cry t

FileOutputstream fs = new FileoutputStream( "testser. ser" ) ;

ObjectOutputstream os = new ObjectOutputstream( fs) ;

os.writeobject (d) ;

os. c1ose O ,.

) catch (Exception e) { e.printstackfraceO; }

try {

FilelnputStream fis = new Filelnputstream("testser.ser") ;

Objecttnputstream ois = new ObjecLlnputStream(fis) ;

d = (Dog) ois.readobjectO;ois.closeO;

) catch (Exception e) { e.printStackTraceO; }

System.out.println("after: coffar size is "

+ d. getCollar ( ) . getCollarSize ( ) ) ;

]

class Dog implements Serializable {

private Coll-ar thecollar;

Page 284: Java - Scjp 5 - Portugues

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 inf aat-(-nllareiual\ I rafrrrn an1l:reiza. lyuv+re rrre Yvuvvrrs!er-v\/ t !eusrrr

)

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 niotiv6ssemos a opgeo de tornar a classe Collar serializ6vel? Ficamos restritos a um Dog n1o-serializ6vel?

Obviamente, n6s poderiamos criar uma subclasse de Collar, marcar a subclasse como Serializable, e usar a

subclasse emvez da classe Collar. Mas isso tamb6m nio 6 sempre uma opgio, por virios motivos potenciais:

1.. A classe Collar poderia ser final, impedindo a criagio de subclasses.

OU

2. A pr6pria classe Collar poderia referir-se a outros objetos nlo-serializ6veis e, sem conhecer a estrutura internade Collar, voc6 nlo ter6 como fazer todos esses reparos (panindo do principio que voc6 sequer iria quererTENTAR esse caminho).

OU

3. Se criar uma subclasse nio for uma opgXo por outros motivos relacionados ao seu projeto.

Entio... O que voc6 faz se quiser salvar um Dog?

li ai q.te entra o modificador transient. Se vocd marcar avari|velde instAncia Collar de Dog como trran-sient, a serializaglo ir6 simplesmente ignorar o Collar durante o processo:

class Dog implements Serializable {

private Uransient Col1ar theCollar; // adicionamos transient/ / resto da classe id6ntica i ancerror

]

class Collar { / / ndo 6 mais Serializable// mesmo c6digo

I

Agora n6s temos um Dog serializivel, com um Collar nlo-seializivel, mas o Dog marcou o Collar como tran-sient; asuda6

before: collar size is 3

Exception in thread *main" java. lang.NullPointerExceptionE agora, o que n6s faremos?

Usando writeobiect e readObjectConsidere o problema: n6s temos um objeto Dog que queremos salvar. O Dog tem um Collar, e o Collar tem umestado que deve tamb6m ser salvo como parte do estado de Dog. Mas... O Collar nda |Sefializable, de forma queprecisamos marc6-lo como transient. Isso significa que, quando o Dog for deserializado, ele voltar6 com umCollar nulo. O que podemos fazer para nos certificarmos de que, quando for deserializado, o Dog receba deal-guma forma um novo Collar com as mesmas caracteristicas daquele que estava atribuido a Dog quando estedltimo foi salvo?

Page 285: Java - Scjp 5 - Portugues

JAVA 5 259

A serializagio Java possui um mecanismo especial para esse caso - um conjunto de m6todos privados que vocQpode.implementar na sua classe que, se presente, ser6 chamado automaticimenre durante a sirializagi6 e adese{*izaglo. E quase_ como se os m6todos fossem definidos na interface. Serializable, excero pelo fato de que nXosio! 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 veriisso logo adiante), estes m6todos serio chamados durante o p.ocesso de serializagio/deserializagio,

Esses m6todos lhe permitem interferir 19 processo de serializagio e des-serializagdo. Assim, eles sio perfeitospara.resolver o.problema com Dog e Collai: quando um Dog esti sendo sdvo, vot6 pode interferir no meio daserializaglo e dizer ,"A prop6silo, eu gostaria de adicionar o estado da vari6vel (int) de Collar ao stream quandoo Dog for serializado". VocO adicionou manualmente o estado do Collar i representagio serializada de Dog,mesmo que o pr6prio Collar nXo seja salvo.

E claroqne vod precisari restaurar o Collar durante adxializa$o, interferindo no processo e dizendo: "Eu vou ler aqueleint extra que sakei no stream de Dog e us6Jo para criar grn novo Collar, e depois airibuir esse novo Collar ao Dog que e$6sendo deserializaclo". Os dois m6todos apeciais que vod define devem rer asinaturas EXATAMENTE como e$as;

-

private void writeObject (ObjectOutputstream os) {

/ / aqvi entra o seu c6digo para salvar as vari6veis de Co11ar

]

private void readObject (ObjectfnputSt.ream os) {

/ / aqur entra o c6digo para ler o estado de Collar, criar um novo Col]ar,/ / e atribui-lo ao Doq

]

Sim, n6s vamos escrever m6todos que t6m o mesmo nome daqueles que estivemos chamando! Onde sio colocadosesses m6todos? Vamos modificar a classe Dog:

class Dog implements Serializable {

transient priwate Collar theCollar; | | nilo Dod€mos geriaLizar ietoprivate int dogSize,.

public Dog(Co11ar col1ar, int size) {

theCollar = collar;dogSize = size;

]public Co1lar getCollarO { return theCollar; }

Drivate void writaObject (ObjectorltDutstrearn oF) l

/ / Ianqa loExceptiontry {

os.defaultwriteobject ( ) t

os . writelnt (theCollar. getcol-l-arSize ( ) ) ;

) catch (Exception e) { e.printStackTraceO; }

)

Drivate voidt readObj ect (Obj ecthDut,st,ream ie ) {

/ / l-anqa IoException, ClassNotFoundException

trY {

is.defaultaeadObject ( ) ;theCollar = new Coll-ar(is.readlntO );

) catch (Exception e) { e.printStackTraceO,- }

// r

// 2

// 3

// 4

// s

// 6

]

Vamos dar uma olhada no c6digo anterior.

No noso cenirio, n6s concordamos que, por qudquer que seja o motivo no mundo real, nio podemos serializar um objetoCollar, mas queremos serializar um Dog. Para isso, iremos implementar writeObj ect ( ) e readObj ect ( ) . Aoimplementar esses dois metodos, voc€ esri dizendo ao compilador: "se alguem chamar writeobj ect ( ) oureadobj ect ( ) em rela$o a um objao Dog use ese c6digo como parte da leitura e da escrita".

Page 286: Java - Scjp 5 - Portugues

260 Copitulo 6: Strings, E/S, Formotog6o e Porsing

1. Como a maioria dos m6todos relativos a E/S, writeobj ect ( ) pode langar exceg6es. Voc6 as pode declarar

ou tratar, mas recomendamos que as trate.

2.QuandovocdchamadefaultWriteobjectO apartirdewriteobjectO,est6dizendoAjVMpararealizaro 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 Dogserializado. Voc6 pode escrever esses dados extras antes e /ou depois Qye chamardef aultWriteobj ect ( ) . MAS... Quando frzer aleitura deles, vocA teri de ler os dados extras na mesma

ordem em que os escreveu.

4. Novamente, decidimos tratar as exceg6es, emvez de declari-las.

5. Quando chegar a hora de deserializar, defaultReadobj ect ( ) cuidar| da deserializagio normal que ocorrese voc6 nXo implementar um m6todo readobj ect ( ) .

6. Finalmente, criamos um novo objeto Collar paru o Dog usando o tamanho que serializamos manualmente.

ffivemos de chamar readlnt (l atpolt de te.mos cha=mado def aultRea-aoni ect ( ) , ou os dados streamedsairiam de sincronia!)

Lembre-se de que o morivo mais comum para se implementar writeobj ect ( ) e readobj ect ( ) ocorrequando voc6 tJm de salvar uma pafte do estado de um objeto manualmente. Se preferir, voc6 pode escrever e lerTOOOS 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 Objectnio 6 serializ6vel? Existem algumas coisas em Java que simplesmente nXo podem ser serializadas, porque sioespecificas do tempo de execuEXo. Coisas como streams, threads, o pr6prio tempo de execugio, etc., e at6 mesmoalgumas classes GUI (que se conectam ao SO subjacente) nio podem ser serializadas. O que 6 ou nio 6 serializivelem Java NAO cai no exame, mas voc6 precisari saber disso para serializar objetos complexos.

Como a Heransa Afeta a SerializagioA serializagio 6 muito interessante mas, para apliciJa efetivamente, voc6 ter6 de entender como as superclassesda sua classe afetam a serializagio.

oBSERVAQ6ES pnnn O EXAME

Se uma superclasseforSeialiqable, entdo, de aeordo com ar regrat nornais de interfaceJaua, todas at ubclasses dela automaticanente

inplenmtardo Seialiqable inplicitanente. Em outrat palauras, uma subclasse de uma clasn marcada cono Seialiqabh parsa fio teste E-UMpara 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€ ubeCOM CEKTEZA que a classe ndo i seriali4luel, porque a elasse Object NAO implementa Seialiqabk.

Isso nos traz a outra que$eo importante a respeito da serializagio... O que acontece se uma superclasse nio for marcadacomo Serial i zable, mas a subclasse for? Ser6 que a subclasse ainda poder6 ser serializada, mesmo que a sua superclasse nXoimplemente S eriahnble? Imagine o seguinte:

class Animal { }

class Dog extends Animal implements Serializable {

// restante do c6diqo de Dog

]

Agora voc6 tem uma classe Dog serializ6vel, com uma superclasse nio-serializ6vel. E funciona! Mas existem algumasimplicag6es potencialmente drias. Paraentender completamente essas implicag6es, vamos voltarever adiferengaentre umobjeto 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 construtorsobrecarregado, at6 que um dos construtores sobrecarregados chame o construtor da superclasse).

3. Todos os construtores de superclasses finnliz.urr.

4. As vari6veis de instAncias que sio inicializadas como parte das suas declarag6es recebem os seus valores iniciais (em vezdos valorespadrXo que recebem antes de os construtores das superclasses finalizarem as suas tarefas).

5. O construtor finaliza.

Page 287: Java - Scjp 5 - Portugues

JAVA 5 26I

Mas esrat coisas NAO acontecem quando um objeto i deniali7atlo. Quando uma instAncia de uma classe serializivel 6deserializada, o construtor n-o roda, e as vari6veis di instlncias NAO recebem os seus valores iniciais! pensenisso - se o construtor fosse chamado, e / ou as variiveis de instAncias recebessem os valores contidos nas suasdecla.raE6e-s, o objeto que voc6 esti tentado restaurar voltaria ao seu estado original, emvezde voltar refletindo asmodificag6es que ocorreram ao estado.eT 4gur" momento depois da sua cria[io. Por exemplo, imagine que voc6tenha uma classe que declare uma variivel deinstAncia e atribua a ela o valor int 3, e inclua n* mEtodo qr'remodifique o valor da variivel de instAncia para 10:

class Foo implements Serializable {

1nt num = 3;

void changeNumfl { num = 10; J

)

Obviamente, se voc6 serializar uma instAncia de Foo tlepoh que o m6todo changeNum ( ) rodar, o valor davariivel num deveri ser 10. Quando a instAncia de Foo foi des-serializada,voc| quer que avari|velnum aindaseja 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 processode inicializagio de um objeto (e, na verdade, elas DE FATO se tornam um s6 m6todo diinicializacio embytecode). A questXo 6 que, quando um objeto 6 deserializado, n6s NAO queremos que a inicializigio normalacontega. Nio queremos que os construtores rodem, e nio queremos que os valores explicitamente declaradossejam atribuidos. Queremos apenas que os valores sejam salvos como parte do estado serializado do objeto a serreatribuido.

E claro que, se voc6 tiver vari6veis marcadas como transient, elas nio serio restauradas aos seus estadosoriginais (a nio ser que voc6 implemente defaultReadobj ect ( ) ); em vez disso, elas receberio o valorpadrio par^ o tipo de dados em questeo. Em outras palavras, mesmo se voc6 disser

class Bar implements Serializable {

transientintx=42;)

quando a instAncia de Bar for deserializda, avari|vel x sera definida como um valor de 0. As refer€ncias a objetosmarcadas como transient. serio sempre resetadas como nu11, independentemente de se elas foraminicializadas no momento da declaragio na classe.

EntXo,6 isso o que acontece quando o objeto 6 deserializado, e a classe do objeto serializado estende objectdiretamente, 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-serializ6velcom uma subclasse Dog seriaJizAvel:

class Animal {

nrrhl i c St- ri nq p6111g;v eL +Afv

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 deserializandoum). Isso significa que todas as coisas que acontecem com um objeto durante a construgio irio acontecer - masapenas is panes Animal do Dog. Em outras palavras, as variiveis de instAncias da classe de Dog serio serializadase deserializadas corretamente, mas as vari6veis herdadas da superclasse Animal, ni.o-serializ6vel, voltario com osseus 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 aprimeira HERDAR da superclasse sereo resetadas aos valores que receberam durante a construgeo original doobjeto. 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 umaforma ou de outra, porque, depois que o primeiro construtor for chamado, ele obviamente chama o seu superconstrutor, 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 nioserio, 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) {

Page 288: Java - Scjp 5 - Portugues

262 Copilvlo 6: Slrings, E/S, FormotoE6o e Porsing

Dog 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 - /n^^\ ^ic r^a^.th-iaat-l\,v - \uvvt vrD.rsqsvvjevur/ /

ois.closeO;) catch (Exception e) { e.printStackTraceO; }

System.out.println("after: " + d.name + * \

+ d.weight) ;

)

)

class Dog extends Animal implements Serializable(l- ri rn n:ma .

Dog(int w, String n) iweight = w;

name = ni

)

)

nl aqc Anim:] I

int weight = 42;

]

/ / l:erdado

/ / ndo herdado

/ / ndo serializ6ve-

que produz esta saida:

before: Fido 35

afLer: Fido 42

O ponto principal aqui 6 que, pelo fato de Animal nio ser serializ6vel, o seu construtor rodou e resetou a variivelweight de Dog, herdada de Animal, quando Dog foi deserializado.

oBSERVAQ6ES pene O EXAME

Se uoci seialiqar am conjunto 0u afll affE6 todos os elementos deuen ser seiali4lueis! Un sd elemento ndo-seiali4luel que sfafar,i aseialiqapdo falhar. Obsene tambim que, enqaantl as interfaces dos conjuntot ndo sdo serialiqiueis, o sdo as classes conmtas dos conjantotnaAPIJaua.

A Serializageo nao 6 para EstiticosFinalmente, voc| poder| perceber que falamos APENAS sobre varilveis de instAncias, e neo sobre variiveisesdticas. As vari6veis estiticas devem ser salvas como parte do estado do objeto? Nio 6 importante saber o estadode uma variivel estetica no momenro em que o objeto'foi serializado? Sim e'nio. Pode ser i.nport"ttte, mas neo fazparte do estado da instincia de forma alguma. Lembre-se de que voce deve pensar nas vari6veis estiticaspuramente 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 quaisforam serializadas em momentos diferentes, e todas as quais foram salvas quando haviam valores diferentes deuma mesma variSvelestitica da classe Oog . Qual instAricia seria a "vencedbra"? O valor e$etico de qual instAncia

Page 289: Java - Scjp 5 - Portugues

JAVA 5 263

seria lsado para substituir aquele atualmente presente na (rinica) classe Dog atualmente carregada? Entendeu oproblema?

As vari6veis est6ticas NLINCA sio salvas como parte do estado do objeto, porque elas nio perrencem ao objeto!

oBSERVAQ6ES pene O EXAME

E quanto a DatalnpatStream e DataOulputstream? Elas utdo nos objetiuos! Ocorre qae, enquantt o exane estaua sendo criado, decidiu+eqile eiJas duat c/assu ndo caiiam flaPrlaa, mas a/gudm se esqueceu de retini-/at tlos objetiuos. Portanto, uocd consegaiu unafo/ga. E anacoisa a menos com qae re preoillpar.

AOTRABALHO

Por mais que s/a flcil ucreuer aidigo de rcrialiqagdo, poden ocotrer problemas referentes is uersdes das clasxs, no mando real, Se uoed saharun objxo Dog usando uma uersdo da clare, mas tentar dueialiqti-/o usando uma aertio dferente, mais noua, o procero poderdfalhar.Consalte a API Jaua para nais detalhet sobre questdet e solugdes rgferentes a uercb-et de clasw.

Obietivo poro o Certificog6o

Datas, Nfmeros e Moeda (Objetivo 3.4 do Exame)i.4 UsarAPIs padrdo J2SE no pacote jaua.text parafonnatar ou exibir conetanente datas, nilmeros e ualores monetdrios para uma/ocalidade espufrca; e, dado um nndrio, deterrtinar os mdtodos propriados caro uoci qaeia usar o local padrlo ou algum outro localespecifn. Desmuer o propdtito e o an da classe jaua.fiil.L.ocale.

A APIJava fornece um conjunto extenso (talvez extenso um pouquinho demais) de classes para$td6-lo a trabalharcom datas, ntimero e moedas. O exame testari o seu conhecimento das classes e m6todos bisicos que voc6 usar6 paratrabalhar com datas e que tais. Ao terminar esta seqio, voc6 dever4 ter uma base s6li& em tarefas, como: criar novosobjetos Date e DateFormat, convener Strings em Dates e vice-versa, realizar fung6es de calend6rio, exibir valoresmoneterios corretamente formatados, e fazer tudo isso para qualquer localidade do planeta. Na verdade, um dosprincipais motivos pelos quais esta seglo foi adicionada ao exame foi para testar se vo c6. 6 capaz de realizarinternacionalizagno (ds vezes abreviada como "i18n') bisica.

Trabalhando com Datas, Nrimeros e Moedas

Se voc6 quiser trabalhar com datas de todo o mundo (e quem nio quer?), precisari familiarizar-se com pelo menos quatroclasses dos pacotes java.text e java.util. Na ve rdade, jiadmitiremos logo, voc6 poderi encontrar perguntas no exame queusem classes que nio foram mencionadas especificamente no objetivo da Sun. Eis as quatro classes relacionadas a datas quevoc€ precisad entender:

I j ava . ut i I . Dat,e A maior pane dos m6todos desta classe foram depreciados, mas voc6 pode us6-la como umaponteentreasclassesCalendar eDate Format.UmainstAnciadeDate representaumadataehoramut6veis,at6 a resoluglo de milisegundos.

I java.util.Calendar Estaclasseforneceumagrandevariedadedem6todosquelhe $ltdamaconverter e manipular datas e horas. Por exemplo, se quiser adicionar um m6s a determinada data, ou descobrirem que dia da semana vai cair 1o de janeiro de 3000, os m6todos da classe Calendar estio ai para isso.

I j ava. text . DateFormat Esta classe 6 usada paraf.ormatar datas nio apenas fornecendo virios estiloscomo "01/01 /70" ov"January l, 1970", mas tamb6m paraformatar datas para diversos locais em todo o mundo.

Esta classe 6 usada para f.ormatar nrimeros e moedas para diversosI java. text.NumberFormatloacis em todo o mundo.

I java.util.Locale Esta classe 6 usada em conjunto com DateFormat e NrunberFornrat paraformatar datas, nri.meros e moedas para locais especificos. Com a ajuda da classe Locaf e vocd poderi converter umadata como "10/08/2@5" para "Segunda-feira, 8 de Outubro de2@5" instantaneamente. Se quiser manipular datas semproduzir output formatado, vod poderi usar a classe Locale diretamente com a classe Calendar.

Orquestrando Classes Relacionadas a Datas e NfmerosQuando trabalhar com datas e ntmeros, vocA freqiientemente usari diversas classes juntas. E i-portante entendercomo as classes que descrevemos acima se relacionam umas com as outras, e quando usar quais classes emconjunto. Por exemplo, voc6 ter6 de saber que, se quiser format ar a data para um local especifico, tera de criar oseu objeto Locale antes do seu objeto DateFormat, porque voc6 precisari do seu objeto Locale como umargumento para o m6todo de criaglo de DateFormat. A Tabela 6-2 fornece uma visio geral de casos comuns de

Page 290: Java - Scjp 5 - Portugues

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

Tobelo 6-2 Cosos de Usos Comuns oo se Trobolhor com Dolos e N0meros

Caso de Uso Etapas

Obter a data e ahora atuais 1. Crie um Date: orte2. Obtenha o seu valor:

d = new DaE.e ( );String s = d.toStrj.ng0i

Obterum objeto que lhepermitarealizar c6lculos de data e hora no seu local

1.. Crie um Calendar:carendar c2. IJse c.aaa(. . ) e c.ro11 (.de data e hora.

Calendar. getlnstance ( ) ;

) para realizar manipulaE6es

Obter um objeto que lhepermitarealizarcilculos de data e hora em um local diferente.

1. CrieumLocale:Locale loc = new Locale(1ingtua); ouLocale foc = newlocafe(1ingua, pais)i2. Crie um Calendar para esse local:Calendar c = CaLendar.getlnstance(1oc);3.Usec.aaa(. .)ec.ro11 (. .) parareahzar manipulag6esde data e hora.

Obter um objeto que lhe pe rmitareafinarcilculos de dataehora,e depois formataro resultado em diferentes locais comdiferentes estilos de datas.

1. CrieumCalendar:Calendar c = Calendar.getlnstanceO;2. Crie uml-ocale para cada local:Locale 1oc = new Locale(. .);3. Convena seu Calendar em um Date:Date d = c.getTime0;4. CrieumDateFormatparacadaLocale:DateFormat df = DateFormat.getDatelnstance

(sty1e, loc) I

5. Use o m6todo formatfl paracriar datxformatadas:String s = df.format(d)i

Obterum objeto que lhe permitaformatar nrimeros ou moedas em diversos locais.

1. Crie um Locale para cada local:Y r r i ttLocaleloc : newl,ocale(. . Ji2. Crie um NumberFormat:NumberFormat nf = NurnberFormat.getlnstance(loc) ; OUNumberFormat nf = Num.berFormat.

getcurrencylnstance ( l-oc) ;

3. Use o m6todo formatQ para criar saidas formatadas:String s = nf.format(alqunNfmero);

A Classe DateA classe Date tem um passado nebuloso. O projeto da sua API nXo fazia um bom trabalho ao lidar com situag6es deinternacionalizagio e de localizagio. No seu

^est jdo atual, a maioria dos seus m6todos foram depreciados e, pari a maioriadas situag6es, vocA usari a classe Calendar em vez da classe Date. A classe Date est6 no exame por v6rios motivos: voc6poder6 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

^rmazenaonimero de milisegundos (voc6 sabe, sio 1000 deles por segundo), entre a data sendo representada e 10. de janeirodet970.

J6 parou para pensar em como os nrimeros sXo grandes? Vamos usar a classe Date para descobrir quanto tempodemorou para passar um trilhio de milisegundos, comegando em Lo. de janeiro de 1970:

'imnnrl- i:rra rrl- i l *.

a1:ec m6ern=f66 {

public static void main(String[] args) {

Date d1 = new Date(1-000000000000L); // um trilhSolSystem.out.println("1st date " + d1.tostrinS() ) ;

Page 291: Java - Scjp 5 - Portugues

JAVA 5 265

)

Na nossa JVM, que usa um local dos Estados Unidos, a saida 6

1st date Sat Sep 0B 1_9:46:40 MDT 2001

Ok, para refer6ncia futura lembre-se de que h6 um trilhio de milisegundos a cada 3L e 2/3 anos.

Embora a maioria dos m6todos de Date tenham sido depreciados, ainda 6. aceitllelusar os m6todos getrime esetrime, embora, como veremos em breve, seja um pouco inadequado. Vamos adicionar uma hora ) nossla instAncia deDate, a panir do exemplo anterior:

imnnyf -.i-r'- ,,!il *,frrrvvrL Jqvo.uLft. ,

class Test.Dates {public static void main(String[] arqs) {

Date d1 = new Date(1000000000000L) ; / / um trilhdo!System.out.println("1st date ,, + d1 .tostrinSO );dl.setTLne(dl.getTime() + 350000O); /| 3600000 milisegundoE / horaSygtem.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 diversioque seria se voc6 precisasse adicionar, digamos, um ano a determinada data. N6s voltaremos ) classe Date maisadiante, mas, por agora, arinica coisa que voc6 precisa saber 6 que, se quiser criar uma instAncia de Date pararepresentar "agora", voc6 usa o construtor sem argumentos de Date:

Date now = new Dateo;(Pela nossa estimativa, se voc6 chamar now. getrime ( ) , ir6 receber um nrlrmero entre um trilhio e dois trilh6es.)

A Classe CalendarAcabamos de ver que manipular datas usando a classe Date 6 complicado. A classe Calendar foi elaborada Dara tornara manipulagio de datas maii f6cil! (Bem, pelo menos mais f6cil que Date.) Embora a classe Calendar tenha^milh6es decampoi e m6todos, depois que'ttocA pegai o jeito de algumas delis as outias tendem a funcionar de forma semelhante.

Quando t_entar usar a classe Calendar pela primeira vez, poderi perceber que ela 6 uma classe abstrata. Nio 6possivel dizer

Calendar c = new Calendaro; // inv6l-ido, Calendar 6 abstrataPara poder criar uma instAncia de cal-endar, voc6 precisa usar um dos m6todos estAticos sobrecarregadosdafTncfanno I \.

Calendar ca1 = Calendar.getlnstanceO ;

Quando voc6 obt6m uma refer6ncia Calendar, como cal no exemplo acima, a variivel da sua refer€ncia Calendar naverdade est6 se referindo a uma instAncia de uma subclasse concreta de Calendar. Nio 6 possivel saber com certeza qualsubclasse voc6 receberi (muito provavelmente, se-ri j ava . uti 1 . GregorianCalLndar), mas isso nio lhe {arAdiferenga. Voc6 estar6usando a API de Calendar. (A medida queJava continua a se espalhar peio mundo, p aramanter acoesio, voc6 poder6 encontrar novas subclasses de Calendai especificas para diferentes locai$.

Certo, agora que n6s temos uma instAncia de Calendar, vamos voltar ao nosso exemplo anterior e descobrir emque dia da semana caiu o nosso trilion6simo milisegundo, e depois vamos adicionar um mAs a essa data:

imnnrl- iarra rrf i l *-

class Dates2 {public static void main(String[] args) {

Date d1 = new Date(1000000000000L);(rr<t-am

^rrf ^-;hf ln/$1^t i-ts^ r\ + A1 F^ef rira/\ \.eJJuelr.vuu.!,rIIILIII\ I-L uqLC T UI .LvJL!IttV\r r,

Calendar c = Calendar.getlnstanceO ;

Page 292: Java - Scjp 5 - Portugues

266 Copitulo 6: Sirings, E/S, FormotoE6o e Porsing

e.setTine(d1);

c.add(Calendar.HOUR, -4) ;

c.add(Calendar.YEAR, 2) ;

c . add (Calendar. DAY_oF_WEEK,

// subtrai 4 horas do valor de

/ / adicj-ona 2 anos ao valor de

-2); // subtrai dois dias do

/ / valor de c

if (c. SITNDAY == c. getFirstDalofWeek ( ) )

System.out.println("Sunday j-s the first day of the week");

System.out.println("trillionth mi1li day of week is "

+ c. get (c.DAY-OF-WEER) ) ;

c.add (Calendar.MONTH, 1 ) ;

Date d2 = c.getTime()tSystem.out.println("new date " + d2.toStringO );

ll #L

ll #2

)

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 oprimeiro dia da semana). A classe Calendar fornece campos semelhantes para dias da semana, meses, o dia dom6s, 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 m6todoadd ( ) de Calendar. Esse m6todo bastanie poderoso lhe permite adicionar ou subtrair unidades de tempoapropriadas para qualquer campo de Calendar que voc6 especificar. Por exemplo:

/l *3

ll *4

il*s

5. Convena o valor de c de volta em uma instAncia de Date.

O outro m6todo de Calendarquevoc6 devericonhecerparao exame6 ro11( ). O m6todo ro11( ) agecomo om6todo add ( ) , exceto pelo fa^to de que, quando uma pafte de um Date 6 incrementada ou diminuida, panesmaiores do Date em queltio nlo serlb inirementadas bu diminuidas. O qu6? Por exemplo:

// asqrrma mre c 6 8 de outubro de 2001

c.rol](Calendar.MONTH, 9); // repare no ano da saida

Date d4 = c.getTimeO;System.out.print]n("new date " + d4.tostringO );

A saida seri algo como

new date Fri .Tu1 0B 19:46:40 MDT 2001,

Repare que o ano nio mudou, embora tenhamos adicionado 9 meses a uma data de outubro. De formasemelhante, chamar ro11 ( ) com HOUR nio modifica a data, nem o m6s e nem o ano.

Para o exame, voc6 nio teri de memorizar os campos da classe Calendar. Se precisar deles para ajud6Jo a re-sponder uma pergunta, eles serio fornecidos na pr6pria pergunta.

A Classe DateFormatTendo aprendido como criar e manipular daras, vamos descobrir como format6-las. Para estarmos todossincroniiados, eis um exemplo de como uma data pode ser formatada de diferentes maneiras:

import java.text.*;import java.util. ";

Page 293: Java - Scjp 5 - Portugues

JAVA 5 267

cl-ass Dates3 {public static void main(String[] args) {

Date d1 = new Date(1000000000000L);

DateFormat[] dfa = new DateFormat[5];

dfa [0] = DateFormat. getlnstance ( ) ;

dfatll = DateFormat.getDat.elnstance( ) ;

dfa[2] = DateFormat.getDatelnstance (DateFormat. SHORT) ;

dfa[3] = DateFormat. gletDatefnstance (DateFormat.MEDIUM) ;

dfa [4] = DateFormat.getDatelnstance (DateFormat.LONG) ;

dfa [ 5 ] = DateFormat . getDatelnstance (DateFormat . FULL) ;

for(DateFormat df : dfa)q\/qf am nrrl- nri nl- l n ldf f nm:f /Al \ \ .vJvuelrtvuL.v!fllLrrr\u! \sr/ /,

J

que, na nossaJVM, produz

9/8/01,7:46 PM

Sep B, 2001

9/B/0L

Sep 8, 2001

Septemlcer 8, 2001

Saturday, September 8, 200L

Examinando esse c6digo, percebemos algumas coisas logo de cara. Primeiramente, parece que DateFormat 6

mais uma classe abstrata, enteo nio podemos usar new p^ra criar instAncias de DateFormat. Neste caso,usamos dois m6todos de fLbica, qetlnstance ( ) e getDatefnstance ( ) . Repare quegetDatelnstance ( ) est6 sobrecarregado; quando e$udarmos os locais, veremos a o:urra versio degetDatelnstance ( ) que voc6 precisar6 conhecer para o exame.

Em seguida, usamos campos estiticos da classe DateFormat para personalizar as nossas virias instlncias deDateFormat. Cada um desses campos e$6ticos representa um estilo de formataglo. Neste caso, parece que a verseosem 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 Stringformatada no estilo da instAncia de DateFormat sendo usada, e converte a String em um objeto Date. Como voc6pode imaginar, essa 6 uma operagio arriscada, porque o m6todo parse ( ) poderia facilmente receber uma Stringmal formada. Por causa disso, parse ( ) pode langar uma ParseException. O seguinte c6digo cria umainstAncia de Date, usa DateFormat. f ormat ( ) para convertd-la em uma String e depois usaDateFormat . 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) {

Page 294: Java - Scjp 5 - Portugues

268 Copitulo 6: Slrings, E/S, FormotoE6o e Porsing

System.out.println( "parse exc" ) ; )

Locale locPT = new Locale("it");

Locale locBR = new Loca]e("it", "CH");

c. set (20L0 , I:., L4) i

em 0)

Date d2 = c.getTimeO;

que, na nossaJVM, produz

d1 = Sat Sep 08 L9:46:.40 YIf,lT 2001

9/8/01parsed = Sat SeF 08 00:00:00 MDT 2001

Repare que, pelo fato & e$armos usando um estilo sHoRT, perdemos alguma precisio quando convertemos o Date em

uma String. Essa per& de precisio surgiu quando convertemos de volta para um objeto Date, e a hora passou de 7:46

para mela-norte.

AO TRABALHO

A API para DateFormat.parse( explica que, porpadrio, o mdtodo parse ( ) d ben to/erante ao faqerparsing de datat. Pela nosa

expeilncia, parseQ ndo i tdo tolerante a retpeito daforraatagdo de Strings que insere com Jilcestl em datas; cuidado ao usar esse nitodo!

A Classe LocaleAnteriormente, 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 adominagio do mundo. Tanto a classe DateFormat quanto a NumberFormat (sobre a qual falaremos em segurda) podemusar uma instincia de Locale para personalizar uma saida formatada para que ela se adapte a determinado local. Voc6 poderiaperguntar, comoJava define um local? A API diz que um local 6 "uma regiio geogrifica, politica ou cultural especifica". Osdois 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 stringpara alingta. Existem mais de 500 c6digos ISO, incluindo um para Klingon ("tlh"), embora Java ainda nXooferega 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 teride 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, tudode que precisa 6 o c6digo dessa lingua. Se, por outro lado, quiser representar o italiano usado na Suiga, voc6indicaria esse pais (sim, o c6digo de pais para a Suiga 6 "CH"), mas que a lingua 6 o italiano:

// Italiano/ / Suisa

IJsar esses dois locais em uma data poderia nos dar uma saida como estai

sabato 1 ottobre 2005

sabato, 1. ottobre 2005

Agora, vamos juntar tudo isso em um c6digo que criar6 um objeto Calendar, definir6 a sua data, e depois oconverter6 em um Date. Depois disso, pegaremos o objeto Date e o exibiremos usando diversos locais do mundo:

Calendar c = Calendar.getlnstance (l ,.

/ / 14 de dezembro de 20L0

/ / (a contagem dos meses comeqa

Locale locIT = new Locale("it",

Locale locPT = new Locale("pt");

Locale locBR = new Local-e("pt",Locale l-oclN = new Locale("hi",

\\pDnI.

\ T\TZ I

f Laffa

Portugaf

BrasilIndia

Locale 1oc,JA = new Locale("ja");

DateFormat dfUS = DaleFormat.getlnstanceO i

System.out.println("US " + dfUS.format(d2) ) ;

Page 295: Java - Scjp 5 - Portugues

JAVA 5 269

DateFormat dfUSfull = DateFormat. getDatefnstance (

DateFormat . FULL ) ;

System.out.print.ln("US fu11 .' + dfUSfull.format(d2) ) ;

DateFormat dffT = DateFormat.getDatelnstance(

DateFormat.FULL, l-ocfT) ;

System.out.println("ftaly " + dfIT.format(d2) ) ;

DateFormat dfPT = DateFormat.g'etDatelnstance (

DateFormat.FULL, l-ocPT) ;

Svsl-om orrl- nrinl- 'l n1.'p^rfrraal '. + rlfp.n f^.lm^l-//lrl )\v-t I t

DateFormat dfBR = DateFormat. get.Datefnstance (

DateFormat.FULL, l-ocBR) ;

System.out.println("Brazi1 " + dfBR. format (d2) ) ;

DateFormat dfIN = DateFormat.getDatelnstance(

DateFormat.FULL, locIN) ;

System.out.println("India " + dfTN.format (d2)) '

DateFormat df.IA = DateFormat. getDatelnstance (

DateFormat. FULL, locrTA) ;

System.out.println(",Japan " + dfJA. format (d2) ) ;

Isso produz, em nossaJVM

US 1,2/14/1,0 3:32 PM

US ful1 Sunday, December l-4, 20L0

Italy domenica 14 dicernbre 2010

Portugal Domingo, 14 de Dezembro de 2010

Rrazil T)omincq, 14 de Dezembro de 2010

Tnr{i: 2}2a?? 21 2?22?? t2?2

Japan 2010?12?1,4?

Opa! A nossa m6quina nio est6 configurada para dar suporte a locais da india ou do Japio, mas o obietivo doexemplo era mostrar com um mesmo objeto Date pode ser formatado para funcionar par^ v6rios locais.

oBSERVAQ6ES peRA O EXAME

I-zmbre-se de que tanto os objetos DateFormat qtlaltto os NamberFormat podem ter os seas /ocais defntdot tonente n0 nlnentl dainstanciagdo. Cuidado czm cddigzs que tentam modficar o local de una instdncia existente - ndo existe nenhtm mitodo que fapa isso!

Existem mais alguns m6todos em Locale (getnisplayCountry ( ) e getDispl-aylanguage ( ) ) que voc6precisari conhecer para o exame. Esses m6todos lhe permitem criar Strings que representem o pais e a lingua dedeterminado 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"); / / BrasilLocale l-ocDK = new Locale("da", "DK"); // Dinamarca

Locale loclT = new Locale("it", ., IT,,); / / IL6,Iia

Page 296: Java - Scjp 5 - Portugues

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 Brazilloc Brasi-1

def Danish

loc dansk

D>I danese

Dado que o local da nossaJVM (o padrio, para n6s) 6 us @stados Unidos), o padrio pan o Brasil 6 "Brazil",e o padrio para a lingua dinamarquesa 6 "oanish". No Brasil, 6. claro, o pais se chama "Brasil " e, naDinamarca, a lingua 3 chamada de "dansk". Finalmente, s6 por diverslo, descobrimos que, na Itilia, alinguadinamarquesa 6 chamada de "danese".

A Classe NumberFormatTerminaremos 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 degetcurrencyf ns tance ( ) para criar um objeto NumberFormat. Nio 6 surpresa que essa classe seja usada paraformatar nrimeros ou valores monetArios:

fLoat f1 = L23.4567f:

Locale locFR = new Locale('fr");

NuniberFormat[] nfa = new NumberFormat[4];

/ / Er^rra

nfa [0] = NumberFormat. getrnstance ( ) ;

nfa [1] = NumberFormat.get.Instance (locFR) ;

nfa12) = NumberFormat.qetcurrencylnstance ( ) ;

nfa [ 3 ] = NunlcerFormat . getcurrencylnstance ( locFR) ,

for(NumberFormat nf : nfa)qlrqlam arrf nrintlnlnf fnmal /f1 ) ).

Isso produz, na nossaJVM,

L23 .457

t23 ,45'7

>J_ZJ .40

rz5 ,40 !

Nio se preocupe se, como no nosso caso, o seu sistema nio estiver configurado para exibir os simbolos do franco,da libra esterlina, da rupia, do yen, do baht ou do dracma. Nlo ser6 esperado que voc6 conhega os simbolosusados para moedas: se voc6 precisar de um, ele seri especificado na questAo. Voc6 poder6 encontrar m6todosdiferentesdeformat 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 ;

Page 297: Java - Scjp 5 - Portugues

JAVA 5 271

try {

System. out.println (nf .parse ("1234.567,, ) ) ;

nf . setParselntegeronly ( true ) ;System.out.println (nf .parse ( "1234. 567" ) ) ;

) catch (ParseException pe) {

System.out.println( "parse exc" ) ;

J

Isso produz, na nossaJVM,

3 I23.457 L23.45678

t234.567

t234

Repare que, neste caso, o nfmero inicial de digitos fracion6rios para o NumberFormat padrio 6 de tr€s, e que om6todo 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 om6todo parse ( ) deve rodar em um bloco try/caLch e que o m6todo setParserntegeronly ( ) usa umvalor 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 ji 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 oum6todos usados para criar instAncias de todas as classes que discutimos nesta segio.

Tobelo 6-3 CrioEdo de lnstdncios poro os Principois Closses de iovo.text e de iovo.util

Classe Principais Opg6es de Criagio para as Instincias

util . Date new DateO;new Date (lonq milisegnrndosDesdeOlOl70) ;

util . Calendar Calendar. geLlnstance ( ) t

Calendar. getfnstance (Locale ),

util . Local-e Locale. getDefault (

new locale (St.ringnew locale(String

),lingua) ;

'I inarra Ql-r'ina naiq\ 'frrY Y\4Av, t

text . DateFormat DateFormat. getlnstance ( ),DateFormat . getDatelnstance ( ) ;

DateFormat . getDatelnstance ( estif o ) ;DateFormat. getDatefnsLance (esti1o, Loca]e) ;

text . NumberFormat NumberFormat. getlnstance ( )

NumberFormat . qetlns tance ( Locale )

NumberFormat . getNumberlns tance ( )

NumberPormat . getNumberf ns tance ( Local e )

NumberFormat . getcurrencyTnstance ( )

NumberFormat . getcurrencylnstance (Locale )

Obietivo poro o Certificog6o

Parsing, Tokenizagilo e Formatagio (Objetivo 3.5 do Exame)3.5 Escreuer aidigo que urc as APIs J2SE padrdes dos pacotesjaua.atil e jaua.uti/.regexparafotwatar oufaryrparcing de $ings ou

ttreams. Para stringt, escreuer aidigo q/./e ilre as classes Pattern e Matcher e o mdtodo String.s?lxt, Reconhecer e asarpaddes de exprusduregularesparacorresponddncia(linitadosa:.(ponto),x(asteisco),+(nais),?,\/,\1,\r,[],0).Oasode+,*e?serilimitadoaqaantifcadoresgananciosos, e o operadorpar4nteses serd audo @enas coml am mecanismo de agruparuento, e ndopara c@tararconteildo

dtrante a determinagdo da correspond1ncia. Para streams, escreuer cddigo usando as classes Foraatter e Scanner e os mdtados

PrintViter.format/prinf. Reconhecer e usarpardmetros defornatapio (linitados a: ohy' o/oc, %d, W ohs) en Stingt deformatos.

Page 298: Java - Scjp 5 - Portugues

272 Copitulo 6: Sirings, E/S, Formoioqdo e Porsing

Comegaremos com mais um aviso: esta pequena segio nio vai lhe transformar de iniciante em regex em guru de

regex. Nesta segio, abordaremos tr0s id6ias bisicas:

I Encontrar coisas VocA tem montes de texto onde precisa procurar algo.Talvez esteja fazendo umaselegio de tela, talvez esteja lendo de um arquivo. De qualquer modo, voc6 precisa de maneiras ficeis paraencontrar agulhas textuais em um palheiro tixtual. IJsaremos as classes java.regex.Pattern, java.regex.Matcher e

java.util.Scanner para nos ajudar a encontrar coisas.

I Tokenizar coisas VocA tem um arquivo delimitado do qual deseja extrair alguns dados riteis. VocA quertransformar 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 paratokenizar os seus dados.

r Formatar coisas VocA precisa criar um relat6rio e transformar uma variivel float com um valor de32500.000f em uma String com um valor de "$32,500.00". N6s lhe apresentaremos a classe java.util.Formattere os m6todos printf ( ) e format ( ).

Um Tutorial de Busca

Esteja voc€ procurando por coisas ou tokenizando coisas, muitos dos conceitos sio os mesmos, enteo comecemospelo bisico. Nio importa linguagem que voc6 esteja usando, mais cedo ou mais tarde provavelmente iri se

deparar com a necessidade de realizar buscas em grandes quantidades de dados textuais, procurando por coisasespecificas.

As express6es regulares (abreviadas como regex) sio um tipo de linguagem dentro da linguagem, elaboradas paraajudar os programadores nessas tarefas de buscas. Toda linguagem que fornece fung6es regex usa um ou maismltnres regex. Os motores regex f.azem buscas atrav6s de dados textuais usando instrug6es que sio programadas emexpressdu.IJma expressio regex funciona como um pequeno programa ou script. Quando voc6 chama um motorregex, 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 quefalarmos 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 express6esmelhores do que as que iremos apresentar. Tenha em mente que, no geral, estaremos criando essas express6esusando apenas uma parte do conjunto total de instrug6es regex, muito obrigado.

Buscas SimplesPara o nosso primeiro exemplo, gostariamos de buscar na seguinte Stringfonte

abaaaba

por todas as ocorrAncias (ov con'eEondincia) da expressdo

ab

Em todas as explicag6es, assumiremos que as nossas fontes de dados usam indices que comegam no zero, de modoque, se aplicarmos um indice )s nossa string fonte, obteremos

fonte: abaaaba

indices : 0i-23456

Podemos ver que temos duas ocorr6ncias da expressio ab: uma comegando na posigXo O e outra comegando naposigio 4. Se envi6ssemos esses dados-fonte e essa expressio para um motor regex, ele responderia nos dizendoque encontrou correspond€ncias nas posig6es 0 e 4:

imnarf iarr: rrt. i l . regex. x ;

cl-ass Regexsmall {

public static void main(String [] argrs) {

Pattern p = Pattern.compile( "ab") ;

Matcher m = p.matcher("abaaaba");

boolean b = false;while (b = m. find( ) ) {

System.out.print(m.startO + " ");]

)

/ / a expressdo

/ / a fonLe

Page 299: Java - Scjp 5 - Portugues

JAVA 5 273

]

Isso produz:

04Nio 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 c6digosde e<emplo fario muito mais sentido. Eis um exemplo mais complicado de uma fonte e uma e4pressio:

fonte: abababa

l_n(I]-ces i urz345b

express5.o: aba

Quantas ocorrencias teremos neste caso? Bem, claramentehi uma ocorr6ncia comegando na posigXo O, e outracomegando na posiEio 4. Mas e quanto )quela que comega na posigio 2? Em geral, no mundo regex, a string abaque comega na posigio 2 nio serh considerada uma ocorrdncia v6lida. A primeira regra geral de busca regex 6

Emgera/, uma basca regex roda da uquerdapara a direita e, dEoh que am caracter dafonte tenba sido usado em ama ocorr€ncia, e/e ndo

pode ser reatiliqado.

Assim, no nosso exemplo anterior, a primeira correspondAncia usou as posig6es 0, I e 2 para bater com aexpressXo (outro termo comum para isso 6 que os tr6s primeiros caracteres da fonte foram consumidor). Pelofato de o caracter da posigio 2 ter sido consumido na primeira correspond€ncia, ele nio p6de ser usadonovamente. 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 algumasp6ginas, veremos uma excegio ) primeira regra que escrevemos acima.

Entio, achamos correspond6ncias para strings exatas, mas o que fariamos se quis6ssemos encontrar algo umpouco mais dinimico? Por exemplo, e se quis6ssemos encontrar todas as ocorr6ncias de nrimeros hexadecimais,ou nrimeros de telefone. ou CEPs?

Buscas Usando MetacaracteresPor pura sorte, regex 6 um mecanismo poderoso para lidar com os casos que descrevemos acima. No cerne desse mecanismoreside a ideia de um metamatter. Como um exemplo simples, dg** que queremos procurar, em algwrs dadosfonte, portodas as ocorr6ncias de digitos num6ricos. Em regex, a seguinte expressio 6 usada para se procurar por digitos num6ricos:

\d

Se modific6ssemos o programa anterior para aplicar a expressio \d i seguinte string fonte

fonte': aI2c3e455f

indice: 0123456189

regex nos diria que achou digitos nas posig6es !,2, 4, 6,7 e 8. (Se quiser tentar isso em casa, voc6 teri de "escapar"o argumento "\d" do m6todo compile, transformando-o em "\ \d", mas falaremos mais sobre isso logoadiante.)

Regex fornece um rico conjunto de metacaracteres que vocA pode encontrar descritos na documentagio API para

.|ava.util.regex.Pattern. Nio os discutiremos todos aqui, mas descreveremos aqueles de que voc6 precisari para o exame:

\d Umdigito

\s Um caracterde espago em branco

\w (Jm caracterde palavra (letras, digitos ou "-" (underscore))

Entio, por exemplo, tendo-se:

fonte: "a 1 56

indice: 0]-2345678

padrSo: \w

regex retornar6, as posig6es 0 ,2,4,5,7 e 8. Os fnicos caracteres nessa fonte gue n6o batem com a definiglo de um caracer de

palavra sio os espagos em branco. (Observagio: neste exemplo, colocamos os dados-fonte entre aspas para indicarclaramente que nio havia espagos em branco nem no comego e nem no fim.

VocA pode especificar tamb6m conjuntos de caracteres a serem procurados, usando colchetes; e intervalos de caracteres a

serem procurados, usado colchetes e um hifen:

fal-rcl Procrrra :ncnas nor a's . l-r's ou c'S

[a-f] procura apenas pelos caracteres a, b, c, d. e ou fAl6m disso, voc6 po* procurar em diversos intervalos de uma s6 vez. A seguinte expresslo busca por ocorrOncias das letrasa- f ou A- F, mas NAO procura por uma combinagSo fa:

Page 300: Java - Scjp 5 - Portugues

274 Copltulo 6: Strings, E/S, FormoioE6o e Porsing

t a- fA-F I Busca pelas seis primeiras letras do alfabeto, em mairlsculas ou minrisculas.

Entio, por exemplo,

fonte: "cafeBABE"

indice: 01234567

pattern: Ia-cA-C]

retornaas posig6es 0, 7, 4, 5, 6.

AO TRABALHO

Aldn das fungdet descritas para 0 examq uocd pode tanbdm aplicar os seguintes atribatos a conjuntos e interualos dentro de cobhetes: '^"para negar os caracteres especifcados, colchetes aninhados para criar ama anido de corgiuntos e "&.&" para especifcar a internpdo de

conjantos. Embora esrr,s clnstratlres ndo caiam flo exane, e/es sdo bastante ilteis, e bons exemplos deles poden ser encontrados na API paraa c/asse jaua. ati /. regex.Pattern.

Buscas Usando QuantificadoresDigamos 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-FlA expresslo acima poderia ser descrita como: "encontre um conjunto de caracteres no qual o primeiro caracterseja um "0", o segundo seja ou um 'x" ou um "xo, e oterceiro seja ou um digito de "0" a "9", ou uma letra de "a"a *f o ou uma letra mairiscula de "A" a'F". tlsando a expressio anterior, e os seguintes dados,

fonte: "12 0x 0x12 OXf 0xcr"

indice : 0I234561 890L234567

regex retornaria 6 e 1,1,. (Observagio: 0x e Oxg nio sio nimeros hexa v6lidos.)

Como segundo passo, vamos pensar em um problema mais ficil. E se quis6ssemos apenas que regex encontrasseocorr€ncias de nrimeros inteiros? Os inteiros podem ter um ou mais digitos, entio seria 6timo se pud6ssemos dizar "rrmou mais' em uma expresslo. H6 um conjunto de construtores regex chamado de quantificadores, que nos permitemespecificar conceitos tais como "um ou mais". Na verdade, o quantificador que representa 'um ou mais" 6 o caracter " + ".Veremos os outros em breve.

A outra questlo que isso suscita 6 que, quando estamos buscando por algo cuja extensio seja vari6vel, obter apenas umaposigio inicial como valor de retorno tem pouco valor. EntXo, al6m de retornar posig6es iniciais, uma outrainformagio que um motor regex pode retornar 6 a correspond6ncia inteira, ou o grupt, que encontrar.Modificaremos a forma como falamos sobre o que regex retorna, especificando cada retorno na sua pr6pria linha,lembrando que agora, para cada retorno, receberemos de volta a posigio inicial E depois o grupo:

fonte:. "1, a72 234b"

padrdo: \d+

VocA pode ler essa expressio como: "Encontre um ou mais digitos seguidos". Essa expressi,o produz a

seguinte saida regex

01J 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 umnrimero inteiro com um valor de 12, e depois, na posigio 6, h6 um nrimero inteiro com um valor de 234".Yoltandoagora ao nosso problema com hexadecimal, a riltima coisa que precisamos saber 6 como especificar o uso de umquantificador para apenas uma parte de uma expresseo. Neste caso, precisamos ter exatamente uma ocorrAncia de0x ou 0X, mas podemos ter de uma a muitas ocorr6ncias dos "digitos" hexa que se seguem. A seguinte expresseoadiciona 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 expressioque os Preceoe.

Os outros dois quantificadores que iremos examinar sio:

* Zero ou mais ocorrAncias

? Zero ou uma ocorr6ncia

Page 301: Java - Scjp 5 - Portugues

JAVA 5 275

Digamos que voc6 tenha um arquivo de texto contendo uma lista, delimitada por virgulas, de todos os nomes dosarquivos- em um diret6rio que contenha virios projetos importantes (a prop6sito, nio 6 assim que n6s organizariamosnossos diret6rios!). VocA deseja criar uma lgta de todos os arquivos cujos nomes comecem com pro j 1. Voc6 poderie.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 operadorregex nlo cai no exame, mas ele nos ajudari a criar uma solu$o ideal para o nosso problema. O ^ 6 o simbolo de negaSo emrego<. Por o<emplo, se quiser encontrar nrdo, exceto letras 4 b e c em um arquivo, voc€ poderia usar

[ ^abc ]

Entio, armados com o operador ^ e o quantificador * (nenhum ou mais), podemos criar o seguinte:

projl([^,])*Se aplicarmos essa expressio apenas ao pedago do arquivo de texto que listamos acima, o regex retorna

lll nr^r le.ha.l ndf

25 projl

A principal parte dessa expressio 6 a que diz"me retorne zero ou mais caracteres que nio sejam urna virgula." Oriltimo 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 umhifen (ou um espago) seguido de outros quatro digitos, entio temos um candidato. Eis alguns exemplos denrimeros 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 ouum hifen" no meio dos nossos digitos:

\d\d\d( [-\s] 1 ?\d\d\d\d

O Ponto Pr6-definidoAl6m 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". Porexemplo, a seguinte fonte e o seguinte padrio

fonte: "ac abc a c"padrdo: a.c

produzirio a saida

3 abc

7 acO "." 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 umcomportamento que 6 conhecido como "ganancioso", "relutante" ou "possessivo". Embora voc6 precise entenderapenas o quantificador ganancioso para o exame, iremos apresentar tamb6m o quantificador relutante para servir de

base para comparagio. Primeiramente a sintaxe:

? 6 ganancioso, ?? 6 relutante, para zero ou um

o 6 ganancioso, 'e? 6 relutante , para zero ou mais

+ 6 ganancioso, + ? 6 relutante, para um ou mais

O que acontece quando temos a fonte e o padrio seguintes?

fonte: yyxxxyxx

padrio: . *xx

Primeiramente, estamos {azendo algo um pouco diferente aqui, ao procurarmos por caraceres que ajam como prefixo da

pane est6tica 0o<) da expresslo. Acreditamos que estamos dizendo algo como: "encontre conjuntos de caracteres que

Page 302: Java - Scjp 5 - Portugues

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 anteriormenteque, 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 quatroprimeiros 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 resultadocomo este:

0 yyxx

4 xyxx

lJm outro argumento plausivel 6 que, uma vez que pedimos um conjunto de caracteres que termine com xx,poderiamos receber um resultado como este:

0 yyxxxyxx

A maneira como pensamos nisso 6 considerando o adjetivo ganancioso. Par.a Qye. a segunda resposta esteja correta, omotor regex teria que olhar (gananciosamente) em todo o conjunto-fonte de dados para poder determinar que haviaum xx no final. Entlo, na realidade, o segundo resultado 6 o correto, porque, no exemplo original, n6s usamos oquantificador ganancioso 's. O resultado que encontra dois conjuntos diferentes pode ser gerado usando-se oquantificador relutante *?. Novamente:

fonte: l lxxxyxxpadrdo: . *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 (procuradadireitaparaaesquerda) at6 achar a corresponddncia mais i direita. Nesse momento, ele inclui tudo o que existir nos dados-fonteat6 (e incluindo) os dados que fazem pane da correspond6ncia mais ) direita.

AO TRABALHO

Exixem maitos outms aspectos referentes a quantifcadores regex do qlrc 0s qtle discutimos aqut, rzasj,i abordamos mais do qae o rufcientepara o exame. A Sun ten diuersos tutoriais que lbe ajudardo a aprender mais sobre os quantificadoru e a tomd-/o o guru em quantficadoresno sea ambiente de trabalbo.

Quando Metacaracteres e Strings ColidemAt6 aqui, estivemos falando sobre regex de um ponto de vista te6rico. Antes de podermos coloc6-lo em pritica, temos dediscutir mais uma questao. Quando chegar a hora de implementar regex em nosso c6digo, seri bem comum que os nossosdados-fontes e /ou as nossas express6es sejam armazenados em Strings. O problema 6 que metacaracteres e strings nXofuncionam muito bem juntos. Porexemplo, digamos que queremos apenas criarum simples pa&io regex queprocurepordigitos. 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 ,talvezsejauma 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 comouma seqiiAncia de escape. E quanto ao metacaracter ponto Q? Se quisermos usar um ponto na nossa expressio como ummetacaracter, sem problemas, mas e se estivermos lendo alguns dados-fonte que por acaso usem ponros comodelimitadores? Eis uma outra forma de estudar as nossas opg6es:

Stringp=\\.',;//oregexv6issocomoometacaractef-.i-^ h - \r\vulJrrY v - \. // o compilador v€ isso como uma

Page 303: Java - Scjp 5 - Portugues

JAVA 5 277

/,/ seqr.i6ncia de escape invelida em \lava

// o compilador fica feliz, e o regex ve um

// ponto, e nao um metacaracterUm problema semelhante pode ocorrer quando voce passar metacaracteres a um programa Java por meio deargumentos de linha de comando. Se quisermos passar o metacaracter \d para o nosso programa java, a nossa JVMfaz a coisa certa se dissermos

? java ooRegex "\d"Mas 6 possivel que o seu JVM talvez nio faga. Se tiver problemas para executar os seguintes exemplos, voc6 podetentar adicionar uma barra invenida (ou seja, \ \d) aos seus metacaracreres de linha de comando. Nio sepreocupe, voc€ nio ver6 nenhum metacaracter de linha de comando no exame!

AO TRABALHO

A linguagen Jaua defne diuersas seqii1ncias de uc@q inclaindo

\n = linerted (que uocd poderi enczfrtrar no exame)

\b = backspace

\t = tab

E oilras, que uocd poderi encontrar na Etpecifcagdo da Linguagen Jaua. Fora uma euentual apaipdo dc um \n dentro de una String uoci

ndo precisard v preocupar com seqi.i4ncias de ucape Jaaa no exame.

Neste ponto, ji aprendemos o suficiente sobre a linguagem regex para comegar a us6-la em nossos programasJava.Comegaremos e$udando o uso de express6es regex para encontrar coisas, e depois passaremos para um t6picointimamente relacionado, que 6 o de tokenizar coisas.

Localizando Dados atray6s da Correspond6ncia de Padr6es

Depois que vod aprendeu um pouco de regex, usar as classes java.util.regex.Panern @attern) e java.util.regex.Matcher(Matcher) 6 bem simples. A classe Pattern 6 usadaparaarmaznnar uma representagio de uma expressio regex, para quepossa ser usada e reusada por instAncias da classe Matcher. A classe Matcher 6 usada para chamar o motor regex com aintengio de se realizarem operag6es de corresponddncia. O seguinte programa mostra Pattern e Matcher em agio,e 6 uma boa base para voc6 iniciar os seus pr6prios experimentos com regex:

import java.util. regex. * ;a]acc Paaav f

public static void main(String [] args) {

Pattern p = Pattern.compile (args [01 ) ;

Matcher m - p.matcher(args [1] ) ;

boolean b = false;q\rcl-6m drrl- nrinl-lrl\DAl-l-arn i< \ +m nal-tarnl\\.vJ v eer!! t

while(b = m.findO) {

System.out.printl-n(m.startO + " " + m.groupO);

]

Esse programa usa o primeiro argumento de linha de comando (args t 0 J ) para representar a expresslo regex quevoc6 deseja usar, e usa o segundo argumento (arqs [ 1 J ) para representar os dados-fonte em que voc6 desejaprocurar. Eis uma execugeo de teste:

% java Regex "\d\w" "ab4 56_'7ab"

Isso produz a saida

Pattern is \d\w

456

Page 304: Java - Scjp 5 - Portugues

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, nioencontrar6 quaisquer conitrutoreJlistados. Voc6 usarl o m6todo est6tico sobrecarregado.compile ( ) (que usaStringe>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.Esse6om6todoquedefatoiniciaomotorregexerealizaabusca. O m6todo f inO ( ) retorna true caso ache uma correspondAncia, e memoriza a posigio inicial dessa

correspondAncia. Se f ind O retornar true, voc6 pode chamar o m6todo start ( ) para obter a posigXo

inicial da correspond6 ncia, e pode chamar o mbtodo group ( ) para obter a string que representa o pedago

propriamente dito dos dados que foi encontrado como correspondOncia.

AO TRABALHO

(Jm motiuo clmum para se asar regex i para realiqar operagdes de busca e substitaipdo. Embora as operagdu de nbstitaipdo ndo caiam no

exame, uoc€ deueni nber que a classe Matcherfomece diuersos ndtodos qae realiqan operagdu de busca e de substituipio. Consulte os mitodos

appendReplacement ( ), appendTail ( ) e replaceAll O na API d.e Matcberpara nais detalbes.

AclasseMatcherlhepermiteprocuraremzubconjuntosdosseusdados.fonteusandoseumconceitochamado regdes.Naidareal, as regi6espodemmelhorarsubsancialmente odesempenho, masvod n1oprecisadsabernadasobreelasparao exame.

Buscando com a Classe Scanner Embora a classe java.util.Scanner sirva principalmente para tokenizar dados (sobre oque 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 aplicarexpress6es 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 pedepor input usando System . in. Ele exibe uma mensagem sempre que uma correspond6ncia| encontrada:

imnnrl- iarra rrf il *.

class ScanIn {

public static void main(String[] args) tq\/<|-am nrrl- nrinl- f \\innl1f . t\\.rJousrrL.vuu.vrfare\ frlvue. /,

System. out . flush ( ) ;

Lrv {

Scanner s = new Scanner(System.in) ;

ql-ri hd t-^Lah .

do{token = s.findlnl,ine(args[0] );System. out.println ( "f ound " + token) ,'

) while (token t= null);) catch (Exception e) { System.out.println("scan exc"); }

]

Achamadaeoinput

java ScanIn "\d\d".i nnrrts. 1l^t^"aqf456f rrPuu.

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 aleitura de um arquivo delimitado para se ter o contefdo do arquivo movido para dentro de lugares iteis, tais como

Page 305: Java - Scjp 5 - Portugues

JAVA 5 279

2bjetgs' arrays ort conjuntos. Estudaremos as duas classes da A?I que fornecem recursos de tokenizagio: String

(usando o m€todo split ( )) e Scanner, que possui muitos m6rodbs tteis para a tokenizagio.

Tokens e DelimitadoresQuando-falamos em tokenizagio, estamos falando de dados que, no inicio, sio composros de duas coisas: tokens edelimitadores. Os tokens sio os pedagos propriamente ditos dos^daios, e os deiimitadore^s sio as express6es q ve rfiaramos tokens uns dos outros.. Quando. muitas peisoas pensam em delimitaiores, elas pensam em caractires ir"l"ior, Jo*odtCT, 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"ium contunto de dados-lonte e realizar tokenizagio nele, usando diversos delimitadorei:

fonte: "ab, cd5b, 6x, 24,,

Se dissermos que o nosso delimitador 6 uma virgula, enrao os nossos quatro tokens serio

ab

cd5b

6x

z4

Se usarmos a mesma fonte, mas declararmos nosso delimitador como sendo \d. obteremos tr6s tokens:

ab. cd]a

x,zEm geral, quando tokenizamos dados-fonte, os delimitadores sio descartados, e tudo o que nos resta sAo ostokens. Assim, no segundo exemplo, definimos os digitos como delimitadores, de forma-qu e 5, 6 e 4 nioaparecem nos tokens finais.

Tokenizando com String.splitQO m6todo split ( ) da classe String usa uma expressio regex como o seu argumento, e rerorna um array Stringpreenchido 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, eargs [ 1] para armazenar o pa&io regex a ser usado como delimitador:

imnnrf iarzr rrtsi I x.Jsws.sLfr. ,

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, quesio carregados no array de Strings chamado tokens. Todo o c6digo depois disso s6 estSli para verificar o que a

operaglo de divisio gerou. A seguinte chamada

t java SplitTest "ab5 ccc 45 @" "\d"produz

count 4

>ab<

>ccc<

>@<

(ObservagXo: lembre-se de que, para representar "\' em uma string, voc6 poderi ter de usar a seqii6ncia de escape"\ \". Por causa disso, e dependendo do seu SO, o seu segundo argumento poder6 ter de ser "\ \ d" ou at6 mesmo"\\\\d".)N6s colocamos os tokens dentro de caracteres

foram usados como delimitadores, e que os digitos contiguos criaram um token vazio.

Page 306: Java - Scjp 5 - Portugues

280 Copitulo 6: Strings, E/S, FormotoE6o e Porsing

IJm inconveniente de se usar o m6todo string. split ( ) 6 que freqiientemente voc6 desejarl ver os tokens no

momento em que est1o sendo produzidos, e, possivelmente, interromper uma operaEio de tokenizagXo ap6s ter criado os

tokens de que p*.ir". Po, ex.mplo, .ro.6 pod"ri" buscar um nrimero de telefone em um grande arquivo-. Se esse nrimero

"p"r...r 1ogo ,ro inicio do arquivo, voc6 gistaria de poder fin alivar o processo de tokenizaElo logo que obtiver seu nimero'

A dasse Scannerfomece uma ricaAPlpara redizar justamente isso'

oBSERVAQ6ESpeneoE)(AME

Pelofan /e System. out.printJ.nO rcrumdo com lantafeqiilncia no examq uoc|podenl uerexenplos de rcqiidncias de escape

nisimdas en qawtdes de praticamente qualquer t6pico, inclaindo regex. Itmbre-u fu que, n precisar criar uma String qae contenba aspas

dtpks (') ou uma bara inuertida (,), teni de adicionar un caracter de ur@e pimeiro:

System.out.println ( "\" \\" ) ;

Isso exibe

E n uociprecisarpmwrarpnrpontos (.) nls seus dados-fonte? Se sinp/esmente co/ocar o ponto na exprvssdo regex, aod obteri o

comportuhentu "quolqar ioroitrr". E se uoc6 tentar\.,-entdo? Agora o compiladnr Jaua acba que uocl estd tentando criar ana teqiidncia de

etcape qae ndo existe. A sintaxe correta d

String s = "ab.cde.fg";String[ ] tokens = s.split("\\.");

Tokenizando com ScannerA classe java.util.Scanner 6 o Cadillac do processo de tokenizaqio. Quando precisar executar tarefas s6rias de tokeniza$o, use

Scanner- essa maravilhosa classe tem de tudo. Al6m das fung6es bisicas de tokenizagio fornecidas porString . split ( ) , a classe Scanner oferece os seguintes recursos:

r Scanners podem ser construidos usando-se arquivos, streams ou Strings como fontes.

r AtokenizaEio|reahzadadentrodeumloop,paraquevocOpossafinalizaroprocessoaqualquermomento.

r Os tokens podem ser convertidos automaticamente para os seus tipos primitivos apropriados.

Vejamos um programa que demonstra diversos m6todos e fung6es de Scanner. O delimitadorpadrlo de Scanner 6 o espago

em branco, que 6b que este programausa. O programa cria dois objetos Scanner: s1, sobre o qual6 feita umaiteragio como m6todo mais gen6rico next ( ) , o que retoina todos os tokens na forma de String, enquanto que s2 6 analisado comv6rios 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, hitsScanner s1 = new Scanner(args[0] );Scanner s2 = new Scanner(args[0] );while(b = sL.hasNextO) {

s = sl.next0; hits += \s"-

iwhile(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" ;

)

Page 307: Java - Scjp 5 - Portugues

JAVA 5 28I

)

System.out.println("hits " + hits) ;

)

Se esse programa for chamado com

? java ScanNext ..1 true 34 lni,ele produziri

hits ssssibis2

E claro que nio estamos fazendo nada com os tokens depois de os obter, mas voc6 pode ver que os tokens de s2sio convenidos para os seus respectivostipos primitivos-. lJm ponto fundamental

"q"i 6 q.tt m6todos

chamados hasNextXxx ( ) testam o valor do pr6ximo token, mas neo o obt€m realmenti, nem se movem para opr6ximo token nos dados-fonte. Todos os m6todos nextxxx ( ) realizam duas fung6es: obtdm o pr6ximo t6ken, eem seguida se movem para o token seguinte.

A classe Scanner tem m6todos nextxxx o (por exemplo nextlong o ) e hasrexLxxx o (por exemplohasNextDouble ( ) ) para todos os tipos primitivos exceto char. Al6m disso, a classe Scrnn.r te* .rh m6todouseDel 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 niopu&ssemos colocar nrimeros negativos entre parenteses? Quest6es vitais como essas fizeram a equipe & criagio do exameincluiraformataEiocomopanedoexameJava5.Osm6todosformatO eprint.f O foram-adicionadosajava.io.PrintStream emJava 5. Esses dois m6todos se comportam exatamente da mesma maneira, enteo tudo o quedissermos sobreum aplica-se a ambos. (Diz a lenda que a Sun adicionou printf ( ) apenas para agradar aos veihosprogramadores de C.)

Nosbastidores,om6todo formatO usaaclassejava.utif .Formatterpar^f.azerotrabalhopesadodeformatagio. VocA pode usar a classe Formatter diretamente se quiser, mas, para o exame, tudo o que precisarisaber 6 a sintaxe b6sica dos argumentos que vocA passa ao m6todo f ormat O . A documentagio parJessesargumentos de formatagio pode ser encontrada na API de Formatter. Iremos apresentar brevemente a sintaxe paraformatagio de Strings, o que ser6 mais do que suficiente para permitir que voct realize diversas tarefas deformatagio E gabarite todas as quest6es de formatagio do exame.

Vamos comegar parafraseando a documentagio API para formatagio de strings (para uma abordagem maiscompleta, muito mais completa do que voc6 precisa para o exame, consulte a API de java.util.Formarter):

printf ("string de formataqdo", argumento (s) ) ;

A string de formatagio pode conter tanto informag6es de strings literais nXo-associadas com argumentos quantodados de formatagio especificos de argumentos. A dica para determinar se voc6 esti olhando para dadosformatados 6 que estes sempre comegam com um simbolo de porcentagem (o/o). Vejamos um exemplo, e nlo entreem 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 depoisuma segunda string de formatagio. Repare que misturamos literais com as strings de formatagXo. Vamos agoramergulhar um pouco mais fundo e observar a construgio das strings de {ormatagio:

* larg_index$] [flags] [width] [.precision] conversion char

Os valores dentro de [ ] sio opcionais. Em outras palavras, os rlnicos elementos obrigat6rios de uma string deformatagio sio o 7o e um caracter de conversio. No exemplo acima, os rinicos valores opcionais que usamos foram paraindexagiodeargumentos.O2grepresentaosegundoargumento,eo 1$ representaoprimeiroargumento(reparequeniotem problema em trocar a ordem dos argumentos). O d depois dos argumentos 6 um caracter de conversio (mais oumenos o tipo do argumento). Eis um resumo dos elementos das strings de formatagXo que voc€ precisari conhecer

Para o exame:

arg-index Um nrimero inteiro seguido diretamente por um $, isso indica qual argumento dever6 ser exibidonessa posigio.

flags Embora existam muitos flags, para o exame voc6 teri de conhecer:

Page 308: Java - Scjp 5 - Portugues

282 Copitulo 6: Strings, E/S, Formotoqdo e Porsing

r "-" Justifica o argumento ) esquerda

! "+" Inclui um sinal (+ ou -) com este argumento

I '0" Preenche os vazios deste argumento com zeros

I '," lJsa separadores de agrupamentos especificos do local (ou seia, a virgula em 123,456)

I "(" Coloca nfmeros negativos entre par€nteses

width Este valor indica o ndmero minimo de caracteres a serem exibidos (se quiser ter colunas bem

organizadas e bonitas, voc6 usari este valor o tempo todo).

precision Para o exame, voc6 s6 precisar6 disto ao formatar um nimero de ponto flutuante e, no caso desses

,r,t*..or, precision indica o ndmero de digitos a serem exibidos depois do ponto decimal'

conversion O tipo do argumento que voc6 est6 formatando. Os que voc6 precisa conhecer:

I b boolean

I c char

f d integer

r f floating point

I s string

Vejamos algumas dessas strings de formataglo na pr6tica:

int i1 = -L23;

System.out.printf (">ts1$ (7d< \n" , rL) ;

System.out.printf (">t0, 7d< \n", i2\ ;

System.out. format ( ">%+-7d< \n", j.2) ;

System.out.printf(">%2$b + t1$5d< \n", i1-, false);Isso produz:

> (123)<

>01,2,345<

>+12345 <

>false + -123<

Q.,l6s adicionamos os literais ) e ( para ajudar a demonstrar como funcionam as larguras minimas, ospreenchimentos com zeros e o alinhamento). Finalmente, 6 importante lembrar que, se voc6 definir tiposdiferentes para o tipo especificado no seu caracter de conversio e para o seu argumento, receber6 uma excegio de

tempo de execugio:

System.out. format ( "%d", L2.31 ;

Isso produz algo como

Exception in t.hread \\main" j ava . util . 11 legalFormatConversionEx-

ception: d != java.lang.Double

Resumo para a certificagioStrings A coisa mais importante a se lembrar sobre Strings 6 que os ofietotString sio inalteriveis, mas x rcfer€ncias a

Strings nio! Voc6 aprendeu que pode criar uma nova String usando outra j6 existente como ponto de partida, mas se nioahibairumavarT6vel de referAncia a uma nova String, ela ficar6 perdida para seu programa - voc6 nlo ter6 como acessar sua

nova String. Recapitule os m6todos imponantes da classe String.

A classe StringBuilder foi adicionada em Java 5. Ela tem exatamente os mesmos m6todos que a antiga classe

StringBuffer, exceto pelo fato de os m6todos de StringBuilder nlo serem seguros em relagio aos threads. Por esse

motivo, os m6todos de StringBuilder tendem a rodar mais ripido do que os de StringBuffer, portanto, escolha

StringBuilder sempre que os threads nio forem uma preocupagio. Tanto os objetos StringBuffer quanto os

StringBuilder podem ter os seus valores modificados virias vezes, sem que se precise criar novos objetos. Se voc6estiver manipulando muitas strings, esses objetos serio mais eficientes do que objetos String imutlveis, que sXo maisou menos "usados uma vez, mantidos na mem6ria para sempre". Lembre-se de que esses m6todos senptt modificam ovalor do objeto chamador, mesmo sem nenhuma atribuiglo explicita.

Page 309: Java - Scjp 5 - Portugues

JAVA 5 283

E/S de arquivos Lembre-se de que os objetos do tipo File podem representar arquivos ou diret6rios, mas, at6que voc6 chamg createNewFile ( ) ou mkDir ( ) , ;inda n{o tericriado nada ,ro i.., disco rigido. As classes doPacote java.io foram elaboradas para serem encadeadas. Raramente voce utilizar| um FileReadei ou File\Tritersem os "encapsular' em um objeto BufferedReader ou Buffered\7rirer, o que the d6 acesso a m6todos maispoderosos, 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 quaislhe-permitem criar PrintrVriters diretamente do nome de uma String ou de um objeto File, 6 possivel qrr" .rro.6 rrr"Buffer\(riters com bem menos freqiiAncia.

Serializagio A serializagio lhe permite salvar, distribuir e restaurar tudo o gue vocd precisa saber sobre umobjeto ativo. E quando o seu ob.ieto aponta para outros objetos, eles sio salvoi tamb6m. As classesjava.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, usereadMethod ( ) . Para serializar um objeto, ele precisa implementar a intertace Serializable. Marque as vari6veis deinstlncias com transient caso voc6 nio queira que o estado delas entre no processo de serializagio. Voc6 podeampliar 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 normaisde 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 superclassenio implementar Serializable, entXo, quando um objeto da subclasse for deserializado, o construtor unserializableda superclasse 6 executado - tenha cuidado! Finalmente, lembre-se de que a serializagio diz respeito lsinstAncias, 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 deentender 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 de1970, armazenado em um long. A maioria dos m6todos de Date for depreciado, entio use a classe Calendar paraas 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 comDateFormat 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 fornecediversos mecanismos que usam os conceitos de express6es regulares (regex). As express6es regex podem serusadas com as classes Pattern e Matcher do pacote java.util.regex, e tamb6m com java.util.Scanner e com o m6todoString. split ( ) . Ao criar padr6es regex, voc6 pode usar caracteres literais para a combinagio ou pode usarmetacaracteres, 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 "encontreuma ou mais destas coisas em seqii6ncia". Voc6 nio precisar6 entender os m6todos de Matcher que facilitem a

substituigio de strings nos seus dados.

Tokenizar 6 dividir dados em pedagos delimitados. Os delimitadores normalmente sio simples virgulas, maspodem ser tao complexos quanto qualquer outro padrio regex. A classe java.util.Scanner fornece capacidadescompletas de tokenizaglo usando-se regex, e permite que voc6 tokenize em um loop, para que possa interromper oprocesso 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 tempopara serem processadas.

A formatagio de dados para saida pode ser feita usando-se a classe Formatter, ou mais comumente usando-se osnovosm6todosdePrintStream, formatO eprintf O. Lembre-sedeque formatO eprintf Osecomponam de forma similar. Para usar esses m6todos, voc6 cria uma string de formatagio que 6 associada comtodos 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 caracterde conversXo que nio corresponder aos seus dados, ser6 langada uma excegio.

Exercicios rdpidosAqui estio alguns dos pontos principais dos objetivos para certificagio deste capitulo.

Usando String, StringBuffer e StringBuilder (Objetivo 3.1)E Os objetos String sio inalter6veis, por6m, as variiveis de refer0ncia String nio.

E Se voc6 criar uma nova String sem atribuila, ela{icar| perdida para seu programa.

E Se voc€ redirecionar a referAncia a uma String para uma nova String, o objeto String anterior pode ser perdido.

El Os m6todos String usam indices iniciados em zero, exceto para o segundo argumento de substring ( ) .

E A classe String 6 f inal - seus m6todos nio podem ser sobrescritas.

Page 310: Java - Scjp 5 - Portugues

284 Copitulo 6: Strings, E/S, FormotoE6o e Porsing

fl Quando uma String literal for encontrada pela VM, ela seri adicionada ao pool.

fl As Strings tpm um m6todo chamado length ( ) e os arrays tem um atributo chamado lengLh.

tr A API de StringBuffer 6 a mesma que a nova API de StringBuilder, exceto pelo fato de que os m6todos de

StringBuilder nXo s5o sincronizados Para seguranga de threads.

D Os m6todos de StringBuilder deverio rodar mais ripido do que os de StringBuffer.

E Todos os seguintes itens aplicam-se a StringBuffer e a StringBuilder:

E Os StringBuffers sio alteriveis - eles podem ser alterados sem a criaglo de um novo objeto.

El Os m6todos StringBuffer atuam sobre o objeto chamador, mas os objetos podem ser alterados sem umaatribuigio explicita na instrugXo.

tr O m6todo equals ( ) de StringBuffer nio 6 sobrescrito; ele nlo compara valores.

E Lembre-se de que m6todos encadeados sio avaliados da esquerda para a direita.

E M6todos String que voc6 deve memorizar: charAt O , concat O, equalslgnoreCase O ' length O,replace ( ) , substring ( ) , tolowerCase ( ) , toString ( ) , toUpperCase ( ) e trim ( ) .

D MdtodosdeStringbufferquevoc€devememorizar:appendO, deleteO,insertO, reverseO e

toString ( ) .

E/S de Arquivos (Objetivo 3.2)E As classes de java.io que vod precisa entender sXo File, FileReader, BufferedReader, File\7riter, Buffered\(/riter e

PrintVriter.

D Um novo objeto File nio significa que h6 um novo arquivo no seu disco rigido.

tr Objetos File podem representar um arquivo ou um diret6rio.

D A classe File lhe permite gerenciar (adicionar, renomear e apagar) arquivos e diret6rios.

O Os m6todos createNewFile ( ) e mkDir ( ) adicionam entradas ao seu sistema de arquivos.

fl File\Writer e FileReader sio classes de E/S de baixo nivel. VocA pode us6-las para escrever em arquivos e 16-

los, mas normalmente elas devem ser encapsuladas.

fl As classes de java.io devem ser "encadeadas" ou "encapsuladas" (esse 6 um uso comum do padrlo de projetodecorador).

E E bastante comum "encapsular" um BufferedR eader em um FileRead er, para se ter acesso a m6todos de nivelmais alto (mais convenientes).

E E, bastante comum'encapsular" um BufferedVriter em um FilelW'riter, para se ter acesso a mdtodos de nivelmais alto (mais convenientes).

E PrintVriters podem ser usados para encapsular outros \ilflriters mas, a partir de Java 5 eles podem ser criadosdiretamente apartir de Files ou Strings.

O OsPrintrVritersdeJava5t6mnovos m6todos appendO, format ( ) eprintf O.

Serializagio (Objetivo 3.3)D As classes que voc6 precisa entender esteo todas no pacote java.io; incluem: ObjectOutputStream e

ObjectlnputStream principalmente, e FileOutputStream e FilelnputStream, porque voc€ as :utilizar| para criarstreams de baixo nivel para serem usados pelas classes ObjectXxxStream.

E As classes precisam implementar a interface Serializable para que os seus objetos possam ser serializados.

tr O m6todo ObjectOutputstream.writeObjecL ( ) serializa objetos, e o m6todoObj ectlnputstream. readObj ect ( ) os deserializa.

E Se voc6 marcar uma vari6vel de instAncia com transient. ela nio seri serializada. embora todo o resto doestado do objeto seja.

E VocA pode ampliar o processo automitico de serializagio de uma classe implementando os m6todoswriteObjectO ereadObjectO.Seofizer,aschamadasinseridasparadefaultWriteObjectO e

defaultReadObject ( ),respectivamente, cuidarlodapartedaserializa$oqueacontecenormalmente.

E Se uma superclasse implementar Serializable, entio as suas subclasses tamb6m a implementam automaticarnente.

0 Se uma superclasse nio implementar Serializable, entio, quando um objeto da subclasse for deseri alizado, oconstnrtor da superclasse sera executado.

Page 311: Java - Scjp 5 - Portugues

JAVA 5 285

E DatalnpudtreameDauOutputStream,naverdade,nlocaemnoenamgapaardoqueatiescritonosobjetivos&Stm.

Datas, Nrimeros e Moeda (Objetivo 3.4)E As classes que voc6 precisa entender slo java.util.Date, java.util.Calendar, java.text.DateFormar,

java.text.NumberFormat e java.util.Locale.

D A maioria dos m6todos da classe Date foram depreciados.

tr Um Date 6 armazenado como um 1ong, e refere-se ao nrimero de milisegundos desde 1o. de janeiro de 1970.

fl Os objetos Date sio uma esp6cie de ponre entre as classes Calendar e Locale.

D Calendar fornece um poderoso conjunto de m6todos para manipulagio de datas, para realizar tarefas comoobter dias da semana, ou adicionar determinado nirmero de meses ou anos (ou outros incrementos) a uma data.

tr Crie instincias de Calendar usando m6todos est6ticos de f6brica (getrnstance ( )).

E Os m6todos de Calendar que voc6 deveri entender slo add ( ) , que lhe permite adicionar ou subtrair viriaspartes (minutos, dias, anos e assimpordiante) dedatas, e ro11 O, guefuncionacomo ad.d ( ), masnioincrementa as partes maiores de uma data (por exemplo: adicionar 10 meses a uma data de outubro modi{ica om6s para agosto, mas nio incrementa o valor do ano de Calendar).

E InstAncias de DateFormat sio criadas usando-se m6todos estiticos de fibrica (getrnstance ( ) egetDatelnstanceO ) .

B Existem diversos "estilos" de formatagio disponiveis na classe DateFormat.

E Os estilos de DateFormat podem ser aplicados a diversos Locales para se criar uma s6rie de saidas paradeterminada data.

tr O m6todo DateFormat. f ormat ( ) 6 usado para se criar Strings contendo datas devidamente formatadas.

D A classe Locale 6 usada em conjunto com DateFormat e NumberFormat.

E Tanto objetos DateFormat quanto NumberFormat podem ser construidos com um Locale especifico e

imutivel.

E Para o exame, vocA deveri entender o processo de criaglo de Locales usando-se linguas ou uma combinagio de

lingua e pais.

Parsing, Tokenizagio e Formatagao (Objetivo 3.5)D regex 6 uma abreviaEio de express6es regulares, que sio padr6es usados para se procurar por dados dentro de

grandes fontes de dados.

f,l regex 6 uma sublinguagem existente em Java e em outras linguagens (como Perl).

Q regex lhe permite criar padr6es de busca usando caracteres literais ou metacaracteres. Os metacaracteres lhepermitem procurar por dados ligeiramente mais abstratos, como "digitos" ou "espago em branco".

E Estude os metacaracteres \d, \s, \we. (ponto).

fl regex fornece quantificadores que lhe permitem especificar conceitos como: "Procure por um ou mais digitosem seqii€ncia".

E Estude os quantificadores gananciosos ?, 't e + .

E Lembre-se de que os metacaracteres e Strings nio trabalham bem juntos, a nio ser que voc6 se lembre de f.azer

o devido escape deles. Por exemplo, String s = "\\d";D As classes Pattern e Matcher t6m as capacidades regex mais poderosas em Java.

D VocAdeverientendero m6todo compile O dePatterne os m6todosmatcher( ),patternO, findO,start ( ) e group( ) de Matcher.

J Y oc| nda precisar6 entender os m6todos de substituigio de Matcher.

tr Voc6 pode usar java.util.S canner patafazcr buscas regex simples, mas o objetivo original dessa classe 6 a tokenizagio.

f,l A tokenizagio 6 o processo de se dividir dados em pequenos pedagos delimitados.

D Na tokenizaglo, os dados que vocA deseja dividir sXo chamados tokens, e as strings que separam os tokens seo

chamadas de delimitadores.

0 A tokenizagio pode ser feita com a classe Scanner ou com String. split ( ).

tr Os delimitadores sio caracteres rinicos, como virgulas, ou entAo complexas express6es regex.

Page 312: Java - Scjp 5 - Portugues

286 Copftulo 6: Strings, E/S, Formotogdo e Porsing

O A classe Scanner lhe permite tokenizar dados de dentro de um loop, o qual lhe permite interromper a

operagio sempre que quiser.

E A classe Scanner lhe permite tokenizar Strings, $reams ou arquivos.

I O m6todo String. split ( ) tokeniza toda a fonte de dados de uma s6 vez, de modo que grandes

quantidades de dados podem levar um longo tempo para serem processadas.

D Existem dois m6todos novos em Java para formataglo de dados. Esses m6todos sio f ormat ( ) e print f O .

Eles se encontram na classe PrintStream, da qual o out de System. out 6 uma instlncia.

E Os m6todos f ormat ( ) e printf ( ) tAm funcionalidades indAnticas.

O A formataglo de dados com print.f ( ) (ou f ormat ( )) 6 realizada usando-se stings deformatagdo que sioassociadas com argumentos primitivos ou strings.

O O m6todo f ormat ( ) lhe permite misturar literais com as suas strings de formatagXo.

O Os valores para strings de formataglo que voc€ deve conhecer sio:

O Flags: -, +, 0, "," e (

E Convers6es: b, c, d, f e s

E Se o seu caracter de conversSo nd,o bater com o tipo do seu argumento, ser6 langada uma excegio.

Teste Individual

L Dado:import java.util. regex. * ;

class Regex2 {

public static void main(String[] args) {

Pattern p = Pattern.compile (args [0] ) ;

Matcher m - p.matcher (args []-l ) ;

boolean b = false;while(b = m.findO) {

System.out.prinL (m.startO + m.group( ) ) ;

)

E a linha de comando:

java Regex2 "\d*" ab34ef

Qual 6 o resultado?

4.234B. 334

c.2334D.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

)

Page 313: Java - Scjp 5 - Portugues

JAVA s 287

class CardPlayer extends player implements Serializable {

CardPlayerO { System.out.print.(..c,,) ; }

public static void main(Stringtl args) {

CardPlayer c1 = new CardplayerO;

trY I

FileOutputstream f os = new Fileoutputstream(..p1ay.txt,') ;

Objectoutputstream os = new Objectoutputstream(fos) ;

os.writeobject (c1) ;

os. close O ;

FilelnputStream fis = new FilelnputStream(..play.txt,,) ;

Objectlnputstream is = new Object.InpuLStream(fis) ;

CardPlayer c2 = (CardPlayer) is.readObjectO;is.closeO;

) catch (Exceptionx ) { }

i]

Qual6 o resultado?

A.pcB. pcc

c.pcpD. pcpc

E. A compilagio.

- r4r r { t -F. E langada uma excegio no tempo de execugio.

3. Dado que bw 6 uma refer6ncia a um BufferedWriter v6lido. E o seguinte fragmento:15. BufferedWriter b1 = new BufferedWriter(new File("f") );16. BufferedWriter b2 = new Bufferedwriter(new Filewriter("f1-") );1,'7 . Bufferedwriter b3 = new BufferedWriter (new PrintWriter ("f2" ) ) ;

1-8. BufferedWriter b4 = new BufferedWriter (new Bufferedwriter (bw) ) ;

Qual6 o resultado?

A. A compilaglo tem sucesso.

B. A compilagio falha devido apenas a um erro na linha 15.

C. A compilaglo falha devido apenas a um erro na linha 16.

D. A compilaglo falha devido apenas a um erro nalinha 17.

E. A compilagXo falha devido apenas a um erro na linha 18.

F. A compilaglo falha devido a erros em diversas linhas.

4. Dado:c_Lass 'l't(u I

public static void main(String[] arqs) {

String s = il-/,'

Integer x = 343;

long L343 = 343L;

if (x. equals (L343 ) ) s += '\ . e1 " ;

if (x.eguals(343)) s += ".e2 ";

Page 314: Java - Scjp 5 - Portugues

288 Copitulo 6: Strings, E/S, Formotog6o e Porsing

Short s1 = (short) ((new Short((short)343)) / (new Short((short)49)));

if(s1 == 7) 5 += "=5 ";if(s1 < new fnteger(7+1) ) s += "fly ";System. out . println ( s ) ;

j

Quais das seguinres opg6es serXo incluidas na String de saida s? (A4arque todas as corretas)

A. . e]-

B. .e2

C. =s

D.flyE. Nenhuma das anteriores.

F. A compilagio falha.n 3r I n | .G. E langada uma excegio no tempo de execuglo.

5. Dado:f. import java.text.*;

2. class Dateone {

3. public stacic void main(string[] args) i4. Date d = new Dare(11-23631685981L) ;

5. DateFormat df = new DateFormat ( ) t

6 . System. out.println (df . format (d) ) ;

7. ]

8. ]

E dado que 112363I68598IL 6 o nirmero de milisegundos entre L". de janeiro de 7970 e algum momento em9 de

agosto de 2005, qual 6 o resultado? (Observagio: a hora do dia na opgio A poderi variar.)

A.8/9/05 5:54PM

B. 1123631685981L

n 4r I r I rC. 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) {

^^6^"F^- a^n6rrf6rt\.LvrrrPuLs! vurrrPuus!\/,

a cl-nraTf la\ .

)

void storelt(Computer c) {

trY {

ObjectOutputstream os = new Objectoutputstream(

new FileOutputstream( "nyFi1e" ) ) ;

os . writeObj ect ( c ) ;

Page 315: Java - Scjp 5 - Portugues

JAVA 5 289

os.closeO;System. out.prj_ntLn (..done,, ) ;

) catch (Exception x) {System.out.println("exc"),. }

]

Qual 6 o resultado? (Marque todas as corretas)

A. exc

B. done

C. A compilagio falha.

D. Exatamente um obieto 6 serializado.

E. Exatamente dois objetos sio serializados.

7. Usando a menor quantidade de fragmentos possfvel (e preenchendo a menor quantidadepossivel de espacos dm branco), comElete o c6diso abaixo de forma que a classe trie umdiret6rio 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:

trY {

t)f i I ^

dir

] catch

FileDescriptor,'

. createNewDir ( ) ;

(Exception x)

. createNewFile O ;

(dir, "fi1e3" ) ;

("dir3". "fi1e3");

File dir( "dir3" 1 ;

= new File(dir, file);.mkdj-rO;

Di ranf nnr.

F r-re

= new Filenra: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.

E. Uma mesma instAncia de NumberFormat pode ser usada para se criar objetos Number a panir de Strings e

para criar nimeros formatados a partir de nrimeros.

Page 316: Java - Scjp 5 - Portugues

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 sdoverdadeiras? (Marque todas as corretzr)A Todas as tr6s classes t6m um m6todo length ( ) .

B. Os objetos do tipo StringBuffer sio seguros em relagXo aos threads.

C Todas as trAs classes t6m m6todos append ( ) sobrecarregados.

D. O " + " 6 um operador sobrecarregado para todas as tr,3s classes.

E. De acordo com a API, StringBuffer seri mais r6pida do que StringBuilder na maioria das implementag6es.

F. O valor de uma instAncia de qualquer um desses tr6s tipos pode ser modificado atrav6s de virios m6todos da

API.

I l. Dado que I I 19280000000L 6 aproximadamente o n0mero de milisegundos de 1". dejaneiro de 1970 at6 20 de junho de 2005, e que voc6 deseja exibir essa data em alemao, usandoo estilo LONG tal que " ,June " ser6 exibido como ".Juni " , complete o c6digo usando osfragmentos abaixo. Observagio: vocC pode usar cada fragmento no m6ximo uma vez ou entaodeix6-lo sem uso, e pode ser que n6o precise preencher todos os espagos.

Code:

import java.

import java.

class DateTvro {

public static void main(Strinq[] args) {

Date d = new Date(1119280000000L);

DateFormat. df =

);

System. out . println (

]

Fragmentos:

io. *; new DateFormat ( Locale. LONG

nio. *, DateFormat..getfnstance ( Locale.GERMANy

utif. * i DateFormat.getDatelnstance ( DateFormat..LONG

text. *; util.reg,ex,' DateFormat.GERMANY

date.*; df.format(d)); d.format(df));

12. Dado:'imnnrf i:.': in *.

class Directories {

static String [] dirs = 1"dirl", "dir2"];public static void main(String [] args) {

for (String d : dirs) {

Page 317: Java - Scjp 5 - Portugues

iAVA s 291

// insira o c6digo L aquiFile fi-f e = new File(path, args [0] ) ;// insira o c6digo 2 aqui

)

e que a chamada

java Directories fi1e2.txt6 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'iquaisconjuntosdefragmentosde c6digo devem ser inseridos? (N4arqG todas as corretas)

A String path = d;System.out.print(fi1e.exists() + " ") ;

B. String path = d;System.out.print(file.isFileO + \ ") ;

C. String path = File.separator + d;System. out.print (f i1e. exists ( ) t')

;

D. String path = File.separator + d,.

System.out.print(file.isFile() + " ") ;

13. Dado:n'l ace Dnl i <h I

public static void main(String[] args) {

int x = 4;

StringBuffer sb = new StringBuffer(". . fedcba") ;

sb.delete(3,6) ;

sb.insert(3, "az");if(sb.lengthO > 6) x = sb.indexof("b") ;

sb.delete( (x-3), (x-2) | ;

System. out . println ( sb) ;

])Qual6 o resultado?

A. .fazaB. .fzbaC. . . azba

D. . fazbaE. . . fezbaF. A compilaglo falha.n Ar I i t nG. E langada uma excegao no tempo de execugio.

14. Dado:L. import java.uLil.*;

2. cfass Brain {

3. public static void main(String[] args) {

4. // lnsira o b1oco de c6digo agui

s. ]

6. )

Qual opg5o, inserida independentemente na linha 4, compila e produz a saida "I23 82"? (Marque todas as corretas)

Page 318: Java - Scjp 5 - Portugues

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 i n *-.._.*-. ;

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;

Page 319: Java - Scjp 5 - Portugues

JAVA 5 293

)

Quais opg5es slo verdadeiras? (Marque todas as corretas)

A. A compilagdo f.alha.

B. Asaida610 0 9

C.Asaida6to o roD.AsaidaEto t g

E. Asaida6ro z roF. Para dterar o processo padrio de deserializa$o, vod sobrescreveria o m6todo readobj ect ( ) de Specialserial.G. Para alterar o processo padrio de des-serializagio, vocA sobrescreveria o m6todo def aultReadobj ect ( ) de

SpecialSerial.

Respostas

2.

E esi correta. O \d estA procurando por digitos. O * 6 um quantificador que procura por zero ou mais ocorrAncias dopadrio que o precede. Por termos. especificado 'r, .o m6todo group ( ) retorna Strings vazias at6 que digitosconsecutivos sejam encontrados, de forma que o rinico momento em que group ( ) retorna um valor 6 quandoretorna 34, quando o matcher encontra digitos comegando na posigio 2. O m6todo start ( ) retorna a posigio inicialda correspond6ncia anterior porque, novamente, n6s especificamos a busca por zero ou mais ocorr6ncias.

A, B, C, D, F e G estlo incorretas com base no exposto acima. (Objetivo 3.5)

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 queos construtores nio rodam em classes deserializadas que implementem Serializaf[s.

A, B, D, E e F esteo incorretas com base no exposto acima. (Objetivo 3.3)

B esti correta. Buf f eredwriters somente podem ser constru(dos encapsulando-se um rVriter. As linhas 16,

lTet9esteocorretasporqueBufferedWriter,Filewriter ePrintWriter estendemWriter.(Observaglo: Buffered\Triter 6 uma classe decorator. As classes decorator sio usadas extensivamente no pacote java.iopara lhe permitir estender a funcionalidade de outras classes)

A, C, D, E e F e$eo incorretas com base no exposto acima. (Objetivo 3.2)

4. B, C e D estio corretas. Lembre-se de que o m6todo equals ( ) para os wrappers de integers somente retornariotrue seosdoistiposprimitivoseosdoisvaloresforemiguais.ComC,6validof.azerunboxingeusar::.EmD,6vilido criar um objeto wrapper com uma expresseo, e fazer unboxing dele para comparagio com um tipo primitivo.

A, E, F, e G estio incorretas co.m base no exposto acima. (I-embre-se de que A esti usando o m6todo equals ( ) paratentar comparar dois tipos diferentes) (Objetivo 3. 1)

5. Eesticorreta.AclasseDateselocalizanopacotejava.uLil,demodoqueelaprecisaserimponada(import),eosobjetos DateFonrnt devemsercriadosusandeseumm6todo static como DateFormat . getlnstance ( ) ouT1=f 6E-^.m.|- d6fTf-f ^TndFrnaa r Iueugr' vlrrqu . vsuuaLeIIrD LaI99 t,/ .

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

6. A est6 correta. Uma instAncia do tipo Computer ("computador") Tem-Um Keyboard ("teclado"). Pelo fato de

Keyboard nio implementar Serializable, qualquer tentativa de serializar uma instAncia de Computer cuasari olangamento de uma exceglo.

B, C, D e E estio incorretas com base no exposto acima. Se Keyboard implementasse Serializable, enteo doisobjetos teriam sido serializados. (Objetivo 3.3)

7.

import java.io.Pil-e;class Maker {

public static void main(String[] args) {

try {

Fil-e dir = new File("dir3") ;

dir.mkdirO;File file = new File(dir, "fi1e3");file.createNewFile ( ) ;

) catch (Exception x) t )

Page 320: Java - Scjp 5 - Portugues

294 Copilulo 6: Strings, E/S, FormotoE6o e Porsing

Observag6es: as instrug6es new File nio criam arquivos ou diret6rios, apenas objetos. VocO precisa dos

m6todosmkdir O e createNewFile ( ) parade fato criar o diret6rio e o arquivo no disco. (Objetivo 3.2)

8. B, C, D e E estio corretas.

A est6 incorreta, DateFormat . parse ( ) 6 usado para convener uma String em um Date. (Objetivo 3.4)

9. A, C, F e G estio corretas. O caracter de conversio 8b (booleano) retorna true para qualquer argumentonio-nul1 ou nio-booleano.

B esti incorreta, o caracter de conversio 8c (caracter) espera um caracter, e nio uma String. D esti incorreta, ocaracter de converslo I f (ponto flutuante) nio promove automaticamente um tipo integer. E est6 incorreta, ocaracter de converslo o/od (integral) nio 6. capaz de usar um nrimero de ponto flutuante. (Observagio: Os m6todosf ormat ( ) e prinLf ( ) se componam de forma id€ntica.) (Objetivo 3.5)

l0.AeBestlocorretas.

C esti incorreta porque String nio tem um m6todo "append". D est6 incorreta porque somente objetos Stringpodem ser manipulados usando-se operador sobrecarregado " + ". E esti ao contririo, StringBuilder normalmente6 mais rApida por ndo ser segura em relagSo a threads. F esr6 incorreta porque objetos String sio imut6veis. UmareferOncia String pode ser alterada para referir-se a um objeto String diferente, mas os pr6prios objetos sioimut6veis. (Objetivo 3. 1)

11.

i mnnrf i:rrr rrt- i I * .

i mnart- i :rzr I avt- * .

class DateTVo {

public static voj-d main(Strinq[] args) {

Date d = new Date(1119280000000L);

Dat.eFormat df = DateFormat.qetDatelnstance(

DateFormat. LONG, Locale. GERMANY) ;

System. out.println (df . format (d) ) ;

)

ObservagSes: Lembre-se de que voc6 deve construir objetos DateFormat usando m6todos esteticos. Lembre-setamb6m de que voc6 deve esp ecrticar umLocale paraum objeto naterormat no momento do instanciamento. Om6todo getrnstance ( ) nio usa um Locale. (Objetivo 3.a)

12. A e B estio corretas. Pelo fato de voc6 e$ar chamando o programa a partir do diret6rio em cujos subdiret6rios diretos a

buscadeveriserfeita,niosecomegaocaminhocomumcaracterFile.separator.Om6todoexistsO verificaaexist6nciadearquivosoudiret6rios;om6todoisFileO verificaapenasarquivos. IJmavezqueestamosprocurando por um arquivo, ambos os m6todos funcionam.

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

13. C est6 correta. Lembre-se de que os m6todos StringBuffer usam indices que comegam pelo zero, e que osindices finais normalmente sio exclusivos.

A, B, D, E, F e G esteo incorretas com base no exposto acima. (Objetivo 3.1)

14.CeDestlocorretas.Oespagoembranco6odelimitadorpadrio,eoloopwhileavangaatrav6sdaStringusando nexLlnt ( ) ou next ( ).

A e B estio incorretasporqueo loop while nilovaial6mdo primeironio-int. E eF estSoincorretas. O loopdo farium loop infinito uma vez encontrado o primeiro nio-int, porque hasNext ( ) nio avanga atrav6s dosdados. (Objetivos 3.5)

15. C e F estio corretas. C esti correta porque vari6veis static e transient nio sio serializadas quandoum objeto o 6. F 6 uma instrugio vilida.

A, B, D e E estio incorretas com base no exposto acima. G este incorreta porque voc6 nio sobrescreve o m6tododef aultReadobj ect O , mas o chama apaftir do m6todo sobrescrito readObj ect O , junto com quaisqueroperag6es de leitura personalizadas de que a sua classe necessite. (Objetivo 3.3)

Page 321: Java - Scjp 5 - Portugues

Gen6ricos ea-.,LOnf unros

Obierivos poro qcertificog6o

r Projetos Usondo Coniuntos

r Sobrescrever equols( ) e hoshCode( ),Distinguir enlre :: e equols|

I UsorVers6es Gen6ricos de ConiuntosIncluindo Set, List e Mop

I Usor Por6metros de Tipos, Escrever

M6todos Gen6ricos

I Usor iovo.util poro Clossificor e Fozer

Buscos

I Usor Comporoble e Comporotor

t/ Exercicios 16oidos

P&R Tesle individuol

Page 322: Java - Scjp 5 - Portugues

296 Cooftulo 7: Gen6ricos e Coniunlos

Os gen6ricos sXo possivelmente o recurso mais comentado de l_ava 5. Algumas pessoas.os adoram, outras os odeiam,

mas"eles vieram paraficar. Na sua forma mais simples, eles podem ajuCry -Vtottt"r o. c6digo mais f6cil de escrever e

mais robusto. No que t6m de mais complexo, podim s.r mrrito, muito dificeis de criar e de manter. Felizmente, os

criadores do .*"-. d..idiram abordar o l"do tn"ir simples dos gen6ricos, cobrindo os recursos mais comuns e riteis, e

deixando de fora a maior parte das quest6es mais complicadas. A cobernra dos coqjryrtgs njstg_exame se expandiu & duas

formas, em relaSo ao exarne anterior', o uso de gen6riios em conjuntos , e a capacidaAe de classificar e vasculhar conjwrtos.

Obietivo poro o certificoEdo

Sobrescrevendo hashCode( ) e equals( ) (Obietwo 6.2 do exame)

6.2 Dininguirar sobrescrigdu arretas dos ndadot hashC,ode e Eaal^s das incurctas, e upbma difrrwqa mhe == e o mfitudo Euals-

Vod 6 um objeto. Acosnrmese a isso. Vod tem um e$ado, um comportamento e um trabalho (ou pelo menos suas chances

de conseguir um aumentario depois que passar no exame). Se excluirmos os tipos primitivgs, rudo_eqJava 6 um objeto. Nios6 ,rm oSjeto, rns um Objeto .orn 'O' mairisculo. Cada exce$o, cada wento, cada arny 6 derivado dg pacgtejava.lang.bbject. No exame, vocd nlo precisar6 saber cada m6todo de Objea , mas tufti qlre conhecer os listados na Tabela 7-1.

OCapinrlogabordar6wait( ),noLify( )enotifyAll( ).Om6todofinalize( )foiabordadonoCapinrlo3.Portanto, nesta seElo examinaremos apenas os m6todos hashcode ( ) e equals ( ) . oh, iso &ixa de fora tostring (

) , nlo? Ceno, falaremos sobre ele agora mesmo porque s6 levar6 dois segtrndos.

Tobelo 7-1 M6fodos do c/osse Obiect qbordodos no exorne

M6todo Descrigio

boolean equals (object obj ) Decide se dois objetos sio significativamente equivalentes.

void fina]-ize( ) Chamado pelo coletor de lixo quandon1o pode ser referenciado.

este percebe que o objeto

int hashCode ( ) Retorna o valor int do c6digo de hashing de um objeto, de modoque esse objeto possa ser usado em classes Collection quepr.gu.* o hashing, incluindo Hashtable, HashMap e HashSet.

final- void notify( ) Notifica umobjeto.

thread que estiver agtardando o bloqueio desse

final void notifyAll ( ) Notifica todot os threads que estiverem aguardando o bloqueiodesse obieto.

final void wait ( ) Faz com que o thread atualnotify ounotlfyAll

aguarde at6 que outro thread chamenesse obieto.

String toString ( ) Retorna uma "representaglo em texto" do objeto.

O metodo toString( )Sobrescrwa toString ( ) qtrando quiser que simples mortais consigam obter um resultado

iffeligivel ,elacionio'aos objetos de zua class". U* .^odigo po& chamar tostring ( ) ernryu objeto quando precisar de

detalhes riteis sobre ele. Por exemplo, quando vod passar a refer€ncia a um objeto para o m6todoSystem. out . println ( ) , o m6todo toString ( ) dese objao seri chamado e retornat6 o que vemos exibido aqui:

public class HardToRead {

public static void main (String [] args) {

HardToRead h = new HardToReadO ;

System. out.println (h) ;

)

A execugio da classe HardToRead nos forneceri o interessante e significativo resultado,

% java HardToRead

HardToRead@a47e0

A saida anterior 6 a que voc6 obter6 quando nio sobre*rever o m6todo toString ( ) da classe Objea. Ela forneceri onome da classe (pelo-menos zira ten rlanlncia) seguido do simbolo @ e da representagio hexadecimal nXo assinalada doc6digo de hashing do objeto.

Page 323: Java - Scjp 5 - Portugues

Talvez o fato de ter visto ese resultado o motive a sobrescrever o m6todo toString (

exemplo;

public class BobTest {

pubfic static void main (String[] args) t

JAVA s 297

em suas classes, por

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 dasvari6veis de instAncia imponantes).

Entio,isso6tudoqueprecisamossabersobretoString( ).Agoraabordaremosequals( )ehashCode( ).

Sobrescrevendo equals( )Voc6 conheceu o m6todo equals ( ) em capitulos anteriores, ao examinarmos as classes wrapper. Discutimoscomo a comparaglo de duas referancias a objetos com o operador : : retornar^ Lrue se elas apontarem para omesmo 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 podermoscomparar 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 dovalor 5 existir em dois objetos separados nio importa.

Quando voc6 tiver que saber realmente se duas referdncias slo id6nticas, use : : . Mas quando tiver que saber se ospnipriw oQetw (e nio as referAncias) sio iguais, use o m6todo equals( ). Para cada classe que escrever, voc6 teri quedecidir se fari sentido considerar iguais duas instAncias diferentes. Em algumas classes, voc6 pode definir que doisobjetos nunca serio iguais. Por exemplo, imagine uma classe Car que tenha vari6veis de instAncia para itens comomarca, 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 saiadirigindo 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 ambasestio relacionadas a am carro, e nio a dois que tenham os mesmos atributos. Assim, no caso de uma classe Car talvezvoc6 nunca precise, ou queira, sobrescrever o m6todo equalsQ. Sabemos, por6m, que a est6ria nio termina aqui.

O que significar6 a neo sobrescr:Sio de equals( )H6 uma limitagio potencial escondida aqui: se voc6 nio sobrescrever o m6todo equals ( ) , ndo ?odeni usar o objeto como

a cbaue em ama tabela de hashing e provavelmente neo obteri Sets precisos, de forma tal que nlo haja duplicatas conceituais.

O m6todo equals ( ) de Object usa somente o operador : : p^racomparag6es, portanto, a menos que vocAsobrescreva eguals ( ) , dois objetos s6 serlo considerados iguais re as duas ryfer€ncias apnntarcm para o metno objeto.

Examinemos o que significa nio poder usar um objeto como a chave de uma tabela de hashing. Suponhamos que voce

Page 324: Java - Scjp 5 - Portugues

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 eM"ry), e quisesse inserir em um objeto HashMap (um tipo de tabela de hashing, a qual examinaremos posteriormenteneste 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 Personcorresponden!. 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. Enoutras palauras, uoci ndo pode riar um oQeto Car iddntico e usdJo na puqaiv.

A conclusio 6 essa: se voc6 quiser que os objetos de sua classe sejam usados como chaves de uma tabela de hashing (oucomo 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 oexemplo do carro? Voc6 pode sobrescrever o m6todo equals ( ) , a fim de que use o VIN (Vehicle IdentificationNumber) exclusivo como base da comparagio. Dessa forma, poderi empregar uma instAncia quando adrcionS-La aumconjunto 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 umobjao 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, emvezde usar a irstAncia real do carro como chave no par carco/propriet6:io, vod poderia empregar simplesmente uma String querepresentasse o identificador exclusivo do carro. Assim, nunca ted mais de uma instAncia representando um carro especifico,

mas ainda podera usar o curo - ou, em vez dele, am dc seus alributos - como a chave da pesquisa.

lmplementando um m6todo equals( )Digamos que voc6 decidisse sobrescrever equals ( ) em sua classe. O c6digo poderia ficar com o formato a seguir:

public class EoualsTest {

public static void main (String [] args) {

Moof one = new Moof(8);Moof two = new lqoof (8) ;

if (one. equals ( two) ) {

System.out.println("one and two are equal");]

)

)

class Moof {

private int moofval-ue;

Mnnf f irf rr:l l {

moofValue = val;)

public int getMoofValue ( ) {

return moofValue;

)

public boolean equafs(Object o)

if ( (o instanceof Moof) && ( (

== 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 oargumento desse construtor - ela atribui o valor avariLvel de instAncia moofValue. Suponhamos que voc6 definisseq,ri dois objetos Moof serio iguais se suas vari6veis moofvalue forem idAnticas. Ent-io, voc6 estiri sobrescrevendo om6todo equals ( ) ao comparar as duas variiveis moofvalue. E simples assim. Por6m, analisemos o que ocorreno m6todo equats ( ) :

Page 325: Java - Scjp 5 - Portugues

JAVA 5 299

public boolean equals(Object o) {

if ( (o instanceof Moof) && ( ( (Moof)o).getMoofValueo

== this.moofValue) ) {

3. return truei4. ) else {

5. return false;6. )

7. j

Em primeiro lugar, voc6 drue observar todas as regras da sobrescrigio; e na linha L estamos realmente declarando umasobrescrigio v6lida do m6todo equals ( ) que herdamos de Object.

E na linha 2 que ocorre toda a agio. Logicamente, temos que fazer duas coisas para tornar uma comparageo de

igualdade v6lida:

Pnmeiro, assegurar que o objeto testado sela do tipo comto!Ele 6 inserido polimorficamente como do tipo Object, portanto, voc6precisa que ele passe por um teste instanceof . Ter dois objetos de tipos de classe diferentes sendo consideradosiguais 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 poder6converter o argumento do objeto para o tipo correto, de modo a poder acesar seas rudtodos ou vari6veis e faqer realmente acomparagio. Lembre-se de que se o objeto nio passar no teste instanceof, entio, voc6 veri uma excegio de tempode execugio ClassCastException. Por exemplo:

pubfic boolean equals(Object o) {

if ( ( (Moof)o).getMoofValueO == this.moofValue) {

// a Linha anterior compila, mas 6 ma1-escrita!

return E.rue;

] else {

- return false;

)

)

A conversio (Moof ) o falhari se a vari6vel a nXo referenciar algo que SEJA-UM objeto Moof.

Em segundo lugar, conrparar os atibutos releuantes (nesse caso, apenas moofValue). 56 os desenvolvedores podem decidir oque torna duas instAncias iguais (por raz6es de desempenho, ser6 melhor verificar a menor quantidade possivel de

atributos).

Aprop6siro,casovocAtenhaestranhadoasintaxede ((Moof)o) .getMoofValue( )comoumtodo,estamossimplesmente convertendo a variAvel de refer6ncia de objeto, o, simultaneamente ) tentativa de chamarmos umm6todo que esti na classe Moof, mas nlo em Object. Tenha em mente que, sen a conversio, voc6 nio conseguir6compilar 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, comodissemos anteriormente, mesmo com a conversio o c6digo falhari no tempo de execugio se o objeto referenciado por onio for algo que possa ser convertido em um objeto Moof. Portanto, jamais se esquega de usar o teste instanceofprimeiro. Ai estA outrarazio paravalorizar o operador de abreviagio && - se o teste instanceof falhar, nuncachegaremos ao c6digo que executa a conversio, de modo que sempre estaremos seguros no tempo de execugioescrevendo o seguinte:

if ( (o instanceof Moof) && ( ( (Moof)o).getMoofValue( )

== t.his, MoofValue) ) {

recurn Erue;

) else {

return false;

]

Entio, isso encerra eguals ( ) ...

Calma... Nlo tio r6pido. Se voc6 examinar a classe Object na documentagio da APIJava, veri o que chamamos de umconhato especlficado no m6todo equa 1 s ( ) . Um nnran Java 6 um conjunto de regras qrc dnrm rer *eurdas, ou melhor,dann ser segridas se wd qtiserfomecer una intplenmh1do "mmta" coruo as ouhas ?essnar esfurao etp€randa, Ou para colocar de outra forrna, se

vocA nlo seguir o contrirto, pode conseguir que a compila$o e a execudo sejam processadas, mas seu c6digo (ou o de outra

1.

2.

Page 326: Java - Scjp 5 - Portugues

300 Copftulo 7: Gen6ricos e Coniuntos

pessoa) talvez seja interrompido no tempo de execuglo de maneira inesperada.

OBSERVAQ6TS pene O EXAME

l-.embre-sedequeosmdtodosequals( ),hashCode( )rLoString( ) tiotodospilblicu.Ocddigoaseguirndoseriaumasobrucrigdo udlida do mdtodo eqwal-s ( ) , embora padesse parecer qile sim te uocd n6o o/hasse com bastante atengdo durante 0 €xat//€:

class Foo {boolean equals(Object o) { } }

E cuidado tambdm com ot tipos de argumento. O ndtodo abaixo d ama nbrecarga e nio ama sobrucrig1o do mdtodo equals ( ).'

class Boo {public boolean equals (Boo b) { } }

Certifque-u de estar ben faniliaiqado com ar regras da sobrescrigdo para qtle posw identifcar se um nitodo de Objut utti sendo sobrescrito,

sobrecamgado ou inaalidamente redalarado em t/ma c/asn. O mitodo equaLs ( ) da clare Boo a/tera o argumento de Objutpara Boo,

se tornando, portanto, um mdtodo sobruarregado, e ndo senl cbamado a menlt qile 0 setl nidigo, o qua/ conbece ese mdtodo nouo e diferente

qtle Plr acanl tambdn se cbama equa1 s ( ) , sda o chamador.

O contrato de equals( )Extraido diretamente da documentagloJava, o contrato de equals ( ) diz:

f E reflexiztotPara qualquer valor de referAncia de x, x. equals ( ) deve retornar true.a E sinitrico: Para qualquer valor de referAncia de x e y, x. equals (y) deve retornar true se, e somerue se,

y. equals (x) retornar true.I E transitizso:Para qualquer valor de referAncia de x, y e z, se x. equal-s (y) retornar true e y. equals (z )

tamb6m retornar true, enteo, x. equals (z) deve retornar true.) E consistenteiP^ra qualquer valor de referAncia de x e y, mriltiplas chamadas de x. equals (y) retornario

consistentemente true ou consistentemente f alse, contanto que nenhuma informaqio usada nascomparag6es do objeto de eguals tenha sido alterada.

I Paraqualquervalorderefer6nciadex queniosejanull,x.equals(nu11) deveretornarfalse.

E voc6 ainda nem chegou perto de estar seguro. Nlo examinamos o m6todo hashCode ( ) , mas eguals ( ) ehashCode ( ) estio vinculados por um contrato de associagio que especifica qtue se dois olensforen condderados iguaispeb ndtodo equal s ( ) , entdo, Precisardtt ter uakres de hasbing iddntint Poftanto, para estar realmente seguro, voc6 deveadotar a regrapriticaque diz para se submuerequals ( ) , deue-se sobresmuerhashCode( ) tanbin. Agorapodemospassar para hashCode ( ) e ver como esse m6todo esti associado a equals ( ) .

Sobrescreyendo hashCode( )Os c6digos de hashing normalmente sio usados para melhorar o desempenho de grandes conjunros de dados. O valorde hashing de um objeto 6 usado por algumas classes de conjuntos (examinaremos os conjuntos posteriormente nestecapitulo). 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 paradeterminar onde ele deve ser armarynado no conjunto, i o c6digo 6 empregado novamente como auxflio na localizagiodo objeto dentro do conjunto. No exame voc| nio rcrA que conhece. muitos detalhes sobre como as classes do conjuntoque usam hashing sio implementadas, mas precisari saber quais conjuntos as empregam (por todos usarem hasb nonome voc6 precisa ser realmente astuto nesse ponto). Tamb6m teri que reconhecer uma implementagio @npriada oucomta de hashCode ( ) . Isso nlo significa udlida e nem mesmo efciente. E perfeitamente vilido ter um m6todo dec6drgo de hashing absolutamente ineficiente em sua classe, contanto que ele nio viole o contrato especificado nadocumentagio da classe Object (examinaremos esse contrato em breve). Portanto, no exame, se lhe for solicitado queselecione o uso apropriado ou correto do c6digo de hashing, nlo confunda apropriado com a,ilido ov efciente.

Entendendo os c6digos de hashingPara 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|a1, B igual a 2, e assim por diante, e somando os valores num6ricos de todas as letras do nome. (Jm nome espedfn semprc

resultani do mumo aidigo; paraver um exemplo, consulte aFigaraT-1,.

Nio introduziremos nada aleatoriamente, simplesmente temos um algoritmo que sempre seri executado da mesmamaneira, dada uma entrada especifica, portanto, a saida serl sempre idAntica para duas entradas tamb6m id6nticas. At6aqui tudo bem? A maneira como voc6 usa esse c6digo (e passaremos a cham6-lo de aidigo de hashin! ir6 determinar emque balde o pedago & papel deve ser inserido (suponhamos que cada balde represente um nri.mero diferente de c6digo quepossa ser obtido). Agora imagine que chegue ,1gtr6-, mostre a voc6 um nome e diga: "Por favor, recupere o pedago de papel

Page 327: Java - Scjp 5 - Portugues

JAVA 5 3OI

que coincida com esse nome". VocA olhari para o nome que esti sendo mostrado e executar6 o mesmo algoritmo degeragio do c6digo de hashing. Esse c6digo lhe informar6 em que balde deve olhar para encontrar o nome.

No entanto, voc6 deve ter notado uma pequena falha em nosso sistema. Dois nonu diferentespodem resltar no ruesmo ualor.

Por exemplo, os nomes Amy e tuay t6m as mesmas letras, portanto, o c6digo de hashing ser6 id6ntico para os dois.Isso 6 aceitivel, mas significa que quando algu6m lhe pedir (o vendedor de balde$ o pedago de papel no qual se

encontra o nome Amy, voc6 teri que procurar no balde de destino lendo cada nome at6 encontrar Amy emvez de May.O c6digo s6 lhe informar6 em qtre bolth prwrrar,mas nlo como localizar o nome trma vez que tenha chegado a esse balde.

Chave Algoritmo do C6digo deC6digo de

A(f) + L(12) + E(s) +X(24) =42B(2)+o(15)+B(2) = leD(4) +l(e) + R( 18) + K( | l) = 47F(6) + RilS)+ E(s) + (D) = 33

Conjunto

Baldes com os

C6digos de HashingLlr]

Figuro 7-l lJm exernp/o de codigo de hoshing simplificodo

oBSERVAQ6ES pene O EXAME

En casos reais de hashing, n6o d raro ter mafu de uma entrada em un deptitito. Norma/nente, a recuperagdo adeqaada barcada en hashing 6

am procesto de duas etapas:

/ . Encontrar o deprisito certo (usando hashcode ( ) /.2. Procurar no dEdsito o elemento mto (anndo equals ( ) ).

Porranto, para obter efici6ncia, seu objetivo ser6 distribuir os pap6is da maneira mais regular possivel por todos os

baldes. O ideal seria que voc6 pudesse ter apenas um nome por balde para que quando algu6m solicitasse um papel

fosse possivel simplesmenre calcular o c6digo de hashing e apanhar esse papel individualmente no balde especifico

(sem que seja preciso ir abrindo todos os pap6is desse balde at6 localizar o que esta sendo procurado). Um gerador

de c6digo de hashing menos eficiente (por6m, ainda funcional) retornaria o ///esmt c6digo (digamos, 42) independente

do nome, de modo que todos os pap6is seriam inseridos em um mesmo balde, com os outros Permanecendo vazios.

O vendedor teria que ir at6 esse balde e olhar cada um dos nomes at6 que o correto fosse encontrado. E se

funcionasse realmente assim, ele tamb6m poderia nunca usar os c6digos de hashing, e emvez disso ir at6 o balde

grande, escolher como comegar e olhar cada papel at6 encontrar o desejado.

O exemplo de distribuigio por baldes 6 semelhante I maneira como os c6digos de hashing sio usados em coniuntos.

Quando voc6 inserir um objeto em um conjunto que use c6digos de hashing, o conjunto usari o c6digo do obieto para

decidir em que dep6sito/slot ele deve ser inserido. Em seguida, quando voc€ quiserpraclrraresse objeto (ou, em uma

tabela de hashing, recuperar o valor associado a esse objeto), ter6 que fornecer ao coniunto uma referdncia a qual ele

vi comparar com os objetos qae utiuer annarynandt. Contanto que o objeto (armazenado no conjunto, como o papel no balde)

que voc0 estiver tenrando encontrar tenha o nurzto aidigo de hashirgdo objeto que estiver usando na pesquisa (o nome

mostrado ) pessoa que esrava trabalhando com os balde$, ele ser6 encontrado. Mas... E esse 6 um grande Por6m'imagine o que aconteceria se, voltando ao nosso exemplo dos nomes, voc6 mostrasse ao vendedor de baldes um nome

e ele calculasse o c6digo baseado somente em metade das letras emvez de usar todas. Ele nunca encontraria o nome

porque nXo procuraria no balde correto!

Agora voc6 consegue perceber por que se dois objetos sio considerados iguais, seus c6digos de hashing tamb6m

devem ser iguais? Do contr6rio, voc6 nunca poderia encontrar o objeto j6 que o m6todo padrio de c6digo de hashing

da classe Object virtualmente sempre 6 usado com um nrimero exclusivo para cada objeto, uumo qaando o mitodo

equals O d sobrescrito de uma maneira erz que dois oa nafu o@etos sdo considerados igaais. Nio impona quanto sio iguais os objetos

se seus c6digos de hashing nio refletem isso. Portanto, repetiremos: se dnis objetosforcm igaait, reur c6digos de basbing

tambim terdo que ser.

lmplementando hashCode( )Como ser6 que um algoritmo real de c6&go de hashing se parece? Algumas pessoas obt6m seu grau de PhD em

algoritmos de hashing, portanto, do ponto de vista da ci6ncia da computagio, isso esti al6m do escopo do exame. Aparte 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

AlexBobDirkFred

l-Dl T_] f xl l=_l t4tlT*\l'Bob" "Fred" ::i';i:

Page 328: Java - Scjp 5 - Portugues

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 {

^'.1-li^ i-f -.yuvf fe

HasHash(int xVal) {x = xVal; }

public boofean equals(Object o) {

HasHash h = (HasHash) o; / / Nao tente isso em casa

// um teste instanceofif (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 noscertificar de que os objetos de mesmo valor x retornem c6digos de hashing iddnticos.

oBSERVAQ6SS peRA O EXAME

Um mdtodohashCode ( ) qae retnme 0 mesmo uakrpara todas as instincias, vndo elas iguais oa ndo, ainda seni un mdtodo utllido - e atdmuno @ropiado! Por exerrpk, o aidigo ndo estaria uiolando 0 cnnhatz.

public int hashCodeo {return 1492; }

Dois ofietos com um ua/or x tgua/ a 8 terdo o mesmo aidtgo de hathing. Pordn, 0 metmr aconteceria con dofu nbjetls dferenter, um com o aalordexiguala/2 eoouhvcom um uakriguala-920. EsemdtolahashCode ( ) rimaitoinefciente; lenbre+e disso,porqaefardcomquetodos ot objetos s/an innidos no mesmo depdsito, mas, meJmr assim, o objeto podeni ser encontrado depois que o conlanto uascu/har no inicodepiitl - usandrt eqoaT.s ( ) -, tentando desesperadaante knliryC @6s muita puquisa, o objeto correto. En oatrat palatras, o aldigo de

hashing ndo @ttdou em nada a aalerar a pesqlis4 embora afnalidade do hashtng :e1a obter etsa uelocidafu! No entanto, esse adtod.o qae returfllasomeflte um cddigo de basbing seria conidtrado @npriado e atd comto porqae ndo tiola o contrato. Rqetirei nais xtma ae<r correto ndo ignficanecessariamente bom.

Normalmente, voce ver6 m6todos hashCode ( ) que usario alguma combinagio de ^ (XOR) exclusivo envolvendoas vari6veis de instAncia, junto com, digamos, sua multiplicageo por um nrimero primo. Independente do caso, emborao_objetivo seja obter uma distribuigio abrangente e aleat6riados objetos nos dep6sitos, o contrato (e o fato de umobjeto poder ou neo ser encontrado) s6 requer que dois objetos iguais tenham c6digos de hashing id6nticos. Nio seriesperado no exame que voc6 avalie a eficiAncia de um m6todo hashCod.e ( ) , mas 6 preciso conseguir reconhecerquais funcionario ou nio (funcionar significando "fazer comque o objeto seja encontrado no conjunto").

Agora que sabemos que dois objetos iguais devem ter c6digos de hashing iddnticos, o inverso tamb6m 6 verdadeiro?Dois objetos com c6digos de hashing idAnticos t6m que ser considerados iguais? Pense nisso - voc6 poder6 ter viriosobjetos 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 voc6conseguiria 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 dehashingid6nticos rretornar true parao m6todo equals ( ) . Demodo quen5oMoutramaneiraanio sersobrescreverosdois m6todos para estar absolatammte mto dz que seas o$etus poderdn ser asados en n@unfos que eruprcguern hasting.

O contrato de hashCode( )Agora direto da fabulosa documentagXo da API Java referente i classe Object, apresentamos para voct. (rutar detambores) o contrato de hashCode ( ) :

r Sempre que for chamado no mesmo objeto mais de vmavez durante a execueeo de um aplicativo Java, o m6todohashCode ( ) ter5, que retornar consistentemente o mesmo inteiro, contanto que nenhuma informagio usadanas comparag6es de equals ( ) envolvendo o obleto tenha sido aherada. Esse inteiro ter6 que permanecerconstante de uma execugio a outra do mesmo aplicativo.

r Se dois objetos forem iguais de acordo com o m6todo equals (obj ect ) , entio, a chamada do m6todohashCode ( ) nos dos dois objetos deve produzir como resultado o mesmo inteiro.

Page 329: Java - Scjp 5 - Portugues

JAVA 5 303

r NXo 6 obrigat6rio que quando dois objetos forem diferentes de acordo com o m6todoequals (java.lang.object), a chamada ao m6todo hashCode ( ) nesses objetos produza resultadosinteiros distintos. No entanto, o programador deve ficar aJertapara o fato de que produzir resultados inteirosdistintos para objetos diferentes pode melhorar o desempenho das tabelas de hashing.

E o significado disso serl...

Condigiopermitido)

Obrigat6rio Nio 6 obrigat6rio (mas

x.equals (y) == true x.hashCode( ) ==rz hr chl^nr{o / \J .A4ssrrvvsv \ |

x.hashCode( ) ==

rr hach(-nAa / \I

x.equals(y) == true

Sem requisitosde hashCode ( )

x. hashCode (

y. hashCode (

x.equals(y) == false

Portanto, examinemos o que maispode causar uma falha no m6todo hashCode ( ) . O que aconteceria se voc6incluisse 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 iniakqado. 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_;

)

\ r-

)

public int hashCodeorofrrrn fv ^ rr\

]

{

/ / E v6lido, por6m, ndo correto/ / usar uma vari6vel transi-ente

public boolean equals(object o) {

SaveMe test = (SaveMe)o;

if (test.y == y && test.x == x) t // Valido, mas ndo correto1611r7n rrrr6.

i else {

return false;

)

Aqui est6 o que poderia ser feito em um c6digo como o do exemplo anterior:

I Fornecimento de algum estado para o objeto (atribuigXo de valores a suas variiveis de instAncia).

I Insergio do objeto em um HashMap, sendo o objeto a chave.

I Salvar o objeto em um arquivo usando a serializagio sem alterar nada em seu estado.

I Recuperar o objeto no arquivo por meio da desserializagio.

I Uso do objeto deserializado (reativado na mem6ria) para extraiJo de HashMap.

Opa. O objeto do coniunto e o supostamente mesmo objeto reativado nio slo mais id6nticos. A vari6vel transiente doobjeto retornarS. comum valor padrio emvez do valor que tinha no momento em que foi salva (ou inserida em

Page 330: Java - Scjp 5 - Portugues

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 forinserida no objeto HashMap, j6 que , ser-6 usado no cilculo flp c6digo de hashing, quando seu valor for alterado esse

c6digo tamb6m ser6. E quando essa mesma instAncia de Savp$Ae for reativada na desserializagd,o, x, = = 0:

rndepintlenn dc sea ualor no iomento em qtle 0 objetofoi seriafiqatto. Por{ahto, o novo cilculo do c6digo de hashing resultar6 em

um c6digo diferente e o m6todo "q,tais

( ) tamb6m falhhii j6 que x ser6 usado como um dos indicadores da

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

Col-f ectionLl-st

Queue

mapas

HashMap

Hashtable

TreeMap

em conjuntos:

Conjuntos (Objetivo 6. I do exame)l5.1 Dado um cenirio de pmleto, deterwinar qaait classu ef oa intefaces deuem w utadot para se implemennr adequadamente o pmjeto, inclaindo o

aso da interface Conparable.

Voc6 consegue imaginar escrever aplicativos orientados a bbjetos sem usar estruturas de dados como as tabelas de

hashing ou listas encadeadas? O que voc6 faria quando prgcisasse ter uma lista classificada com, digamos, todos os

membros de seu fi-clube dos Simpsons? E claro que podeda faz6-lo por sua conta; a Amazon.com deve ter milhares de

livros sobre algoritmos que vocA poderia comprar. Mas cofn o tipo de prazos aos quais os programadores estao

submetidos atualmente, chega a ser incoerente demais parf que possa ser considerado.

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

conjuntos do pacote java.util est6 repleh de interfaces e

Mas o que fazer com um coniunto?

H6 algumas operag6es bisicas que normalmente sio

a Adiaonar objetos ao conjunto.

I Remouer objetos do conjunto.

I Saberse am objeto (oagntpo de objetos) est6 no conjunto.

I Renperarum objeto no conjunto (sem remov6Jo).

I Iterarpelo conjunto, examinando cada elemento (o um ap6s o outro.

Interfaces e classes-chave da estrutura de coniuntosNo exame, voc6 ter6 que saber qual conjunto selecionarcomesa com um grupo de interfaces, mas tamb6m fornteri que conhecer no exame (e na vida) sio as sete descr

As principais classes concretas de implementagio queoutras, mas o exame nio as abor& especificamente):

coniuntos istas

HashSet

LinkedHashSet

TreeSet

n base em um reouisito declarado. A API de coniuntosvirias classes .orr.r.t"r. As principais interfaces q.te voc6a segurr:

Sorted Set

Sorted Map

ter6 que conhecer no exame sio as treze a seguir ft6

Filas Utilitirios

rr-r-T i ^l!!aylfDL D-.i ^-.i frrArrarra .ClleCtiOnSf uJ Yevuv

Arrays

LinkedlistLinkedHashl.{ap

Nem todos os coniuntos da estrutura implementam realrnente a interface Collection. Em outras palavras, nem todos os

conlantos passam no tute E-(JM se @licado o C)tktrioo. Especificamente, nenhuma das classes e interfaces relacionadas a maPas

Page 331: Java - Scjp 5 - Portugues

JAVA 5 305

sio derivadas de Collection. Portanto, embora SonedMap, Hashtable, HashMap, TreeMap e LinkedHashTable sejamtodas consideradx confuntoq nenhuma 6 realmente derivada de Collection. Para tornar as coisas um pouco maisconfusas, na verdade hi tr6s empregos simultlneos para apalavra"conjunto":

t *T:*] F-"-.,"'E ['."y1 tr'.til [-";f f-:"{l F..@-;1

implementa

Uma classe de implemena$o pode ser nioclasificada e nioordenad4 ordenadae nioclassficada ou or&nada e dassificada

Mas uma implementa$o nunca pode ser classficada e nioordenad4 porqu€ a classifica$o 6 um tipo especifico de

ordenamento, comovocivedem breve. Por exemplo, F{ashset 6umconiunto nloordenado e nioclassificado, enquanto

LinkedHashser 6 um conjunto orrdenado (rnas nioclassificadQ que maff6m a ordem na qrul os objaos foram inseridos.

<<interhce>>Set

<<interfuce>>

Queue

<<interhce>>SortedSet

<<interface>>SortedMap

r"**il r'.",ffi;l [-;ili i,.*,',,1

Figuro 7-2 A hierorquio de inlerfoces e c/qsses de conjunlos

I conjunto, que representa qualqaerumadas estruturas de dados nas quais os objetos sio armazenados e Passam Poriterag6es.

r Colleaion (C' mairisculo), que, na verdade, 6 aintertacejava.util.Collection da qual Set, List e Queue sioderivadas (est6 certo, deriuadar, e nio implementadas. Nio h6 implementag6es diretas de Collection.)

I Collections (C' maiusculo e com 's' no final), que, na verdade, 6. a clastejava.util.Collections, a qual armazena

virios m6todos utilit6rios static para serem usados com os collections.

oBSERVAQ6ES pene O EXAME

E ruuhof,lcil nnfandir "Collections" cum "Co//ection" - tome cuidado. I--embre-se de que Collections d ma classe, con mitodos utilitdrios

utdtims, enquantr Collection d una interface com as declaragdes dos mitodos comans i maioria dos conjuntos inclusiae add( ), re-move ( ), contains ( ), size ( ) r iterator( ).

Os conjuntos v6m em quatros vers6es b6sicas:

Listas Listas de itens (classes que implementam List).

Coniuntos Itens exclusivos (classes que implementam Sed.

Mapas Itens com uma identificagio exclusiva (classes que implementam Map).

Queues Itens arranjados na ordem em que serio processados.

A Figura 7-3 ilustra a estrutura dos objetos List, Set e Map.

Mas h6 outras vers6es dentro desses tr6s tipos:

Classificada(Sorted) Nio-classificada(IJnsoned) Ordenada(Ordered) Nio.ordenada (Unordered)

Page 332: Java - Scjp 5 - Portugues

306 Cooitulo 7: Gen6ricos e Coniuntos

fimmffi[il'ffi[ilLisc O itineririo do vendedor (duplicatas sio permitidas)

E'-.spr{l

Set O territ6rio do vendedor (duplicatas nio sio permitidas)

Baldes com os c6digos de Hashing ffi Eq WA | ] E@,/ ,rt \snformado{

Valores Gancho Chave Inglesa Inversor de fase LaPacltor oe rluxo

HashMap: Os produtos do vendedor (Chaves geradas a partir das lDs dos produtos)

Figuro 7-3 Obietos List, Sef e Mop

Talvez precisemos ser explicitos com relageo ) diferenEa entre classificado e ordenado, mas primeiro temos quediscutir 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 coniunrogeralmente 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 c6digode 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 demaneira aparentemente aleat6ria com modificag6es no conjunto.

Ordenado Quando um conjunto 6 ordenado, significa que vocA podeiterar em seus elementos em uma ordemespecifica (nio aleat6ria). Um conjunto Hashtable nio 6 ordenado. Embora ele tenha uma l6gica interna paradeterminar a ordem (com base nos c6digos de hashing e na implementagio do pr6prio conjunto), voc6 nlb ver6nenhuma ordem quando iterar pelo coniunto. O conjunto Arraylist, no entanto, mant6m a ordem estabelecida pelaposigio do indice dos elementos (exatamente como um xray).LinkedHashSet mantlm a ordem estabelecida pelainsergXo, portanto, o rlltimo elemento inserido ser6 o riltimo do conjunto (diferente de Arraylist, no qual voc6 podeinserir um elemento na posigio especifica do indice). Para concluir, hi alguns conjuntos que mant6m uma ordemconhecida como ordem nataral dos elementos, e eles nio sio apenas ordenados, mas tamb6m classificados. Examinemoscomo a ordem natural funciona em coniuntos classificados.

Classificado Um conjunto dasufcado significa que a ordem do conjunto estl determinada por alguma(s) regra(s),conhecida(s) como ordem de classificagio. IJma ordem de classificagio nio tem nada a ver com o momenro em que oobjeto 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 conjuntodescobriri 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 usealgum tipo de ordem de classificagio. Na maioria das vezes, a ordem usada 6 algo chamado de ordem natural. O queisso significa?

VocA sabe como classificar alfabeticamente - A vem antes de B, F vem antes de G, e assim por diante. Em um conjuntode 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 ouat6 que seu desenvolvedor fornega um4 por meio de uma interface (Comparable) que defina como as instAncias deuma classe podem ser comparadas entre si (a instAncia a vem antes de b, ou b vem antes de a?). Se o desenvolvedordecidir 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 daclasse Foo de como usar a vari6vel de instAncia bar para determinar a ordem. E claro que a classe Foo poderiatamb6m herdar uma ordem natural de uma superclasse emvez de definir a sua pr6pria ordem, em alguns casos.

Afora a ordem namral especficada pela interface Comparable, 6 possivel tamb6m definir outras ordens de classifica$odiferentes usandose runa outra interfacs Comparator. Falaremos sobre como usar Comparable e Comparator paradefinir

Page 333: Java - Scjp 5 - Portugues

JAVA 5 307as 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 ListNo conjunto List o indice tem relevAncia. A rinica coisa encontrada em List que conjuntos diferentes nio tAm siovirios m6todos relacionados ao indice. Entre esses m6todos principais esteo, por exemplo, get (int index) ,

ind.exOf ( ) , add ( int ind,ex, Obj ect obj ) , e outros. Todas as tr& implementag6es de List sio or&nadas atrav6s

da posiSo do indice - uma posiglo que wd deterrnnailrconfigurando um objeto em um indice especifico ou adicionandoo:en especificar a posigio, quando o objeto 6 inserido no final. As tr6s implementag6es de Lis serio descritas na pr6xima se$o.

Arraylist Considere esse conjunto como um array que pode crescer. Ele proporciona iterapdo e acesso aleat,rio com

rqideT,Declaraglo 6bvia: 6 um conjunto ordenado (por indices), mas nAo 6 classificado. VocO pode vAJo a partir da

verslo 1..4, e atualmente ele implementa a nova interface RandomAccess - uma intedace marcadora (o que significaque nio possui m6todo$ que informa' "Essa lista di suporte ao acesso aleat6rio r6pido (geralmente de formaininterrupta)". Prefira essa lista a Linkedlist quando precisar de iteragio r5rpida e n6o pretender executar muitasinserg6es e exclus6es.

Vector E,r'trn re-anescente dos prim6rdios daJava; Vector e Hashtable sio dois coniuntos originais, os outrosforam 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 SetO conjunto Set d6 relevAncia i exclusividade - ele nio permite duplicatas. O m6todo equals ( ) determinari se

dois objetos sio id6nticos (situagio na qual s6 um poder6 ficar no conjunto). As tr6s implementag6es de Set seriodescritas nas se96es seguintes.

HashSet Hashset 6 um conjunto Set nio-classificado e nlo-ordenado. Ele usa o c6digo de hashing do objeto que estisendo inserido; portanto, quanto mais eficiente for sua implementagio de hashCode ( ) melhor seri o.desempenho

obtido no acesso. lJse essa classe quando quiser um conjunto sem duplicatas e nio precisar de ordem na iteragio.

LinkedHashSet LinkedHashSet 6 uma versio ordenada de HashSet que mant6m uma lista com encadeameflto

duplo para todos os elementos. IJse essa classe em vez de HashSet quando a ordem da iteragio {or imponante.Ni iteiagio em HashSet a ordem 6 imprevisivel, enquanto LinkedHashSet permitir6 que voc6 itere pelos

elementos na ordem em que foram inseridos.

oBSERVAQoES pene O EXAME

Ao usar Hashset ou I;inkedHashset, os objetos que uocd adicionar a eles deaerio sobrescrezer hashCode ( ) . Se ndo o fTgrem, o

ndtodt padrAl Ob j ec t . hashCode ( ) pennitir,i qae nilhplot objetos que uoci poderia considerar como "stgnficatiuamente igaais"

sejan adicionados ao seu conjanto d.e "tluplicatas ndo pennitidas".

Treeset TreeSet 6 um dos dois conjuntos classificados (o outro 6 TreeMap). Ele usa uma estrutura de irvore vermelha e

preta (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 MapPara Map os identificadores exclusivos 6 que sio relevantes. lJma chaue exclusiva (o identificador) ,6 napeada para umuakrespecifico, em que 6 claro que tanto i cboue quanto o uakrsio objetos. E provivel que voc6 esteja bem familiarizado.o- oi coniuntos Map, ji que muitas linguagens dio suporte a estnrturas de dados que usam pares thauef uabr ou nomef

uakr. As.implementag6es de M1n permitirio que voc6 faga coisas como procurar um valor com base na chave, solicitarum con;unro apenas com os valoris ou somente com as chaves. Como Sets, Maps depende do m6todo equals ( )

para determinar se duas chaves sio as mesmas ou se slo diferentes.

HashMap HashMap fornece um conjunto Map nio-classificado e nio-ordenado. Quando voc6 precisar de umconjunto Map e nio estiver preocupado com a ordem (na iteraEio), enteo, FlashMap seri sua melhor opgio; os outros

Page 334: Java - Scjp 5 - Portugues

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 dehashing da chave, portanto, assim como HashSet, quanto mais eficiente a sua implementageo de hashCode ( ) ,melhor o desempenho de acesso voc6 ter6. HashMap permite uma chave e diversos valores nulos no conjunto.

Hashtable Como Vector, Hashtable existe desde os prim6rdios daJava. 56 por diversio, nio esquega deobservar a inconsist6ncia na nomeagio: HashMap versus Hashtable. Onde esti o "t" mairlsculo? Bem, nio esperarnosque esse detalhe entre na pronrincia. De qualquer forma, assim como Vector 6 uma contrapartida sincronizada doconjunto 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 dizerapenls que os mitodot chave da classe sio sincronizados. Outy difercnga, no entanto,6 que enquanto HashMappermite que vocO tenha tanto valores quanto uma chave nla, Hasbtabb nio perwitini a existincia de algun componente na/0.

LinkedHashMap Como sua contrapartida Set, LinkedHashSet, o conjunto LinkedHashMap mant6m a ordem deinsergio (ou, opcionalmente, a ordem de acesso). Embora seja um pouco mais lento do que HashMap para adiironar eremover elementos, pode-se esperar uma iteragio mais r6pida com LinkedHashMap.

TreeMap Agora voc6 j6 deve ter adivinhado que TreeMap 6 um conjunto Map clcxstfcado. E ji sabe que issosignifica "classificado pela ordem natural dos elementos". Como TreeSet, TreeMap permitir| que voc6 introduza suasp.pi^ regras de comparaglo (por meio de um Comparable ou Comparator) no momento da criagio do TreeMap,para especificar como os elementos devem ser comparados entre si quando forem ordenados.

A Interface QueueA fungio de Queue 6. armazenar uma lista de "coisas afazor", ou itens a serem processados de alguma forma. Emboraoutras ordens sejam possiveis, as filas normalmente sio consideradas como do tipo FIFO (em que o primeiro item aentrar.6 o primeiro a sair). As filas oferecem suporte a todos os m6todos-padrio de Collection, e tamb6m adicionamm6todos para acrescentam e subtrair elementos e revisar elementos da fila.

PriorityQueue Esta classe 6 uma novidade de Java 5. Uma vez qlre a classe Unkedlist f.oi aprimorada, paraimplementar a interface Qugue, as filas bisicas podem ser manipul-adas com uma Linkedlist. O prop6sito de umaPriorityQueue 6 criar uma fila com ordenamento "prioridade de entrada-prioridade de saida", em vez do sistemaFIFO. Os elementos de PriorityQueue sio ordenados ou naturalmente (em cujo caso os elementos que forem osprimeiros na ordem serio acessados primeiro) ou de acordo com um Comparator. Em qualquer urrrdos casos, aordenagXo dos elementos representa a prioridade relativa deles.

oBSERVAq6TS pena o EXAME

Vocd pode elininarfacilmente algarnas retplstas re reconhecer que, por exentplo, um co{anto M@ nio pode ser a classe escolhida quandofornecessdrio am coryiunto de pares none/ ualor, jd que M4 i arua interface, e ndo ama c/asse conneta de inrplenentagdo. A rvdapda do exame 11

explicita qaando iro impnrta, putantq se lhe solicitarem que selecione ama inteface, esco/ha uma inteface ea ueqde uma classe que ainplemente. O inuerso tambdm i uerdadtiro - se lhe solicitarem para selecionar uma clase de implementagio, ndo esco/ba un tipo de interface.

A Tabela 7-2 resume 11 das 13 classes concretas relativas a conjuntos que voc6 precisari conhecer para o exame. (OsArrays e os Conjuntos v6m logo a seguir!)

Iobelo 7-2 C/osses concretos de imp/ernentocdo de infe#oces de coniunfos

Classe Mapa Conjunto Lista Ordenado Classificado

Hash-l.{ap Nio Nlo

NioNio

TreeMap X Classificado Por ordem natura/ouregras de comparagiopersonalizadas

LinkedHashMap X Porordemde insergio ouultimo acesso

N"ao

HashSet N"ao N*ao

TreeSet X Classificado Por ordem natara/ou regras de comparagiopersonalizadas

LinkedHashSetNio

X Por ordemde insergio

Page 335: Java - Scjp 5 - Portugues

JAVA 5 309

Arraylist X Por indice Nlo

Vector X Por indice Nlo

Linkedlist X Por indice Nio

Dri nri l- r;f'lrrarro+ ef Ysvsv Classificado Por ordem de"coisas a fazer"

OBSERVAq6ES pene O EJGME

Certifque-se de aprender a interpretar a Tabela 7-2 de maneira pnltica. I\o exame, podem lbe solicitar qae selecione um conjanto com base em

am requisito especifn, no qua/ essa nuessidade sela expressa c0///0 am cendrio. Por exemplo, qae conjunto uocd usaria se precisasse manter e

faTgr puquisas em utna lista de pegas, identifcadas por seu nltmero seqilencial afanamirico exclusiuo, sendo Part o tipo da pEa? Vocialteraria stla retpltta se muddssemot o requisito de modo que tarztbim fosse precin exibir as peps em ordem, por rcu nilmero de sdrie? Naprimeirapergunta, uocd tem a classe Part, mas apuquisa dos objetot senl baseada em ilm fltirltero seqtiencia/, portanto, precisard de urtconjunto M@. A cbaue serd o nrimero seqiiencial nafonna de um objeto Stringe o ualor serd a instdncia de Part. A opEdo padrdo deue ser

HashM@, o conjanto Mqp de acesso na* nipido. Porim, qaando acrercentarmls o reqaisito de incluir o ordenanento das pegas por nilmero

rcqiiencia/, precisarenos de un TruMap - que manhim a ordem natural das chauet J,l que a chaue 6 uma String, a ordem nataral seni uma

classtfcagdo alfabitica padrdo. Se o requisito tiuuse sido raslrear qaalfoi a illtina pepa acerada, prouauelmente iiamos precisar de um

LinkedHashMap. Masli que o LinkedHashM4 perdeia a ordem natural (sabstitaindo-a pela ordem do illtino item acessado), se

precisarntos /istar as pegas por nilmero de sirie, leremos que classficar exp/icitamente o conjunto, asando um ndtodo uti/iniio.

Obietivo poro o CertificoE6o

Usando a Estrutura dos Conjuntos (Objetivo 6.5 do Exame)6.5 IJsarJungdes do pacotelaua.utilpara umuer cddigo qae manipule uma lista clarifmndo-a, realiqandn nela urua buva bindria, ou conuertendo-a

ea um arEl. (Jnrfungdes do pacotelauauti/pma esmuer nid,igo qae manipub un arrEt clasifcando-0, realiqando nelc uma burca bindria oa

conuertendo o arE eru uma lista. (Jsar at intufacesjaua.util.Comparator elaua.kng.Conparablz para inflaenciar a classifcag1o dt l$as e arrqys.

Ahm diso, reconhecer o efeito da "ordrnapdo natural" das classes atr@perprinitiuas e dejaua.kng.Stringsobre a classficagdo.

J6 demos uma olhada te6rica nas principais interfaces e classes da Estrutura dos Conjuntos, e vamos ver agora comoelas funcionam na pr6tica.

Fundamentos de ArraylistA classe java.util.Arraylist 6 uma das mais freqiientemente usadas de todas as classes da Estrutura dos Conjuntos. EIa

6 como um array anabolizado. Algumas das vantagens que Arraylist tem em relagio aos arrays sio:

I E capaz de crescer dinamicamente.

I Fornece mecanismos de insergio e de busca mais poderosos do que os dos arrays.

Vejamos como se usa um Arraylist que contenha Strings. Um dos principais objetivos do projeto da Estrutura dos

Conjuntos foi oferecer uma rica funcionalidade no nivel das principais interfaces: List, Set e Map. Na pritica, voc6

geralmente instanciari um Arraylist polimorficamente, desta forma:

r 'i ^F h.'r'i af - nar^r Arr:rzT.i qj- / \ .lIDL rrryufr d!!qj!rru\/,

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 deJava5nao 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, Arraylist.<String> 6 semelhante a String [ ] , no sentido de que declara um containercapaz de

^rm zen^r apenas Strings, mas que 6 mais poderoso do que um String t J . Vejamos alguns dos recursos

que um Arraylist possui:

imnarf ir.': r:f il *.rrr(yvru Jsvs.surr. ,

n"l-'-l i a al ac< rl6ctArr^\rT.i <f {ysv4+v

publ-ic static void main(String[] args) {

Page 336: Java - Scjp 5 - Portugues

310 Copitulo 7: Gen6ricos e Coniuntos

List<String> test = new Arraylist<String> ( ) ;(t- rinc q - "hi /.

test. add ( "string" ) ;

l-aqf add/c\.

test.add(s+s);System. out.println (test. size ( ) ) ;

System. out.println (test. contains (42l, | ;

System. out . println ( test . contains ( "hihi " ) ) ;

test . remove ( "hi " ) ;

System. out.println (test. size ( ) ) ;

])o que Produz:

3

rda5e

true2

H6 uma s6rie de coisas acontecendo nesse pequeno programa. Repare que, quando declaramos o Arraylist, nio demos a

ele um tamanho. Em segurda pudemos pedir que o Arraylist nos informasse o seu tamanho, pudemos pergu.ntar se elecontinha determinados objetos, removemos um objeto que estava presente nele, e depois verificamos novamente otamanho.

Classificando Conjuntos e Arrays

ct- rrf f rAA I \rn6nr16r,, \***, ----"-- );stuff . add ( "Boulder" ) ;

qfrrff arirl /\\Iai 1 / \ .

-r,,€€ ^aa /\\^^r.^hrr\5 LU! r . dUU \ Aspell ,l ;

T6picos referentes i classificagio e busca foram adicionados ao exame paraJava 5. Tanto con untos quanto arrayspodem ser classificados e busiados usando-se m6todos da API.

Classificando Coleg6esVamos comegar com algo simples, por exemplo, classificar um Arraylist de Strings alfabeticamente. Acha que issodeve 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 classeiava.util.Collections fornece um:

import java.util.*,'

class Testsortl {

public static void maj-n(Stringll args) {

ArrayList<String> stuff = newArrayliEt<String>()r // #1-

Autoboxing com Conjuntos

Em geral, os conjuntos sio capazes de armazenar Objetos, mas nio tipos primitivos. Antes de Java 5, um uso bastantecomum 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 Java5, os tipos primitivos ainda precisam ser encapsulados, mas o autoboxing faz esse trabalho para voc6.

List mylnts = new ArrayI,ist (l ; / / decfaraqdo pr6-.Tava 5

myfnts.add(new Integer(42)l; / / era preciso encapsular um intA partir de Java 5, podemos usar

mylnts.add(42) ; / / o autoboxing cuida disso!

Neste riltimo exemplo, ainda estamos adicionando um objeto rnteger a myrnts (e nio um int primitivQ; maso que acontece 6 que o autoboxing reaJizao encapsulamento para n6s.

Page 337: Java - Scjp 5 - Portugues

JAVA 5 3I I

stuf f . add ( "Te1luride" ) ;

System.out.println("unsorted .. + stuff) ;

Collections. sort (Etuff) tSystem.out.println("sorted " + stuff) ;

DVDInfo(String t, String g, String a) {

title = t; etenre = g; leadAct.or = a;

)

public String toString ( ) {

return title + " " + gfenre + "

l/ / ftaff^Te 6 caflar --rl

l/ #2

)

Isso produz algo como:

unsorted IDenver, Boulder, Vai]-, Aspen, Telluridelsort.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 nosater i classificagio.

Vamos imaginar que estamos construindo a melhor aplicagio de automagio de casas j|f.eita. Hoje, estamos nosconcentrando no home theater, e mais especificamente no centro de controle do DVD. J6 temos o software de E/Sparaler e €screver dados entre o arquivo dvdrnf o . txt e as instAncias da classe ovornf o. Eis aqui os principaisaspectos da classe:

class uvu-Lnto {

C+e;F- f .i Fl ^.p!rrrrv LrLrs,

String genre;

Strj-ng leadActor;

+ leadActor + \\\n"

I

Eis os dados de DVDs presentes no arquivo dvdinfo.txt:

Donnie Darko/sci-f i/Gyl1enhal1,,JakeRaiders of the Lost Ark/action/Ford, Harrison200L/scL-fi/??

Caddy Shack/comedy/Murray, Bil-1

Star Wars/sci-f i/Ford, HarrisonLost in Translation/comedy/Murray, BiltPat.riot Games /action/Ford, Harrison

No nosso aplicativo de automaqio de casas, queremos criar uma instAncia de D\rDrnf o Dara cadalinha de dados ouetivermos lido a panir doarquivo dvdinf o. txt. Para cada instAncia, faremos parsing dr linhr de dados (embra-slede st.ring. split ( ) ?) e preencheremos as trAs variiveis de instAncias de ovbrnto. Finalmenre. oueremoscolocar todas as instincias de nvntnto em um Arraylist. Imagine que o m6todo populatel,ist (') (abaixo) fagatudo isso. Eis um pequeno fragmento de c6digo do nosso aplicat'ivo:

'

Arraylist<DVDfnfo> dvdlist = new Arraylist<DVDInfo> ( ) ;

popul-atelis:uO; / / adiciona os dados do arquivo ao ArraylistSystem. 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

Page 338: Java - Scjp 5 - Portugues

312 Copftulo 7: Gen6ricos e Coniuntos

cfass DVDfnfo implements Conparable<D\IDlnfo> {

/ / a6di ao exi sfente

^"1-1 i^ inf nnmn:r6rlr^tf)\iT)Tnfn d\ {yuvrrv f rlu vvrrwu! v

return title.coqrareTo(d.getTitle ( ) ) ;

])

/ / c6di oo i nexi stcnte

public int compareTo(Object o) {

, Lost in Translat.ion comedy Murray, Bill, Patriot Games action Ford, Harrison

l

(Observagio: N6s sobrescrevemos o m6todo toString ( ) de DVDInfo,.portanto, quando chamamos println ( )

p^rao AirayList, ele chamou tostring ( ) para cada uma das instAncias.)

Agora que temos um Arraylist preenchido, vamos classific6lo:

Colfections. sort (dvdlisL) ;

Ops!, voc6 recebe algo como:

TestDVD. java:13 : cannot fi-nd symbol

s)rmbol : method sort ( java.util.Arraylist<DVDInfo>)

focation: class java.util.CoffectionsColfections. sort (dvdlist) ;

O que est6 acontecendo aqui? N6s sabemos que a classe Collections possui um m6todo sorL ( ) , e mesmo assim este

erro di a 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).

Se vocA j6 descobriu qual 6 o problema, n6s chutariamos que voc6 o fez sem a ajuda da obscura mensagem de erro

^oxr^d^ airma.. Afinal, .o-o ,. classificam as insdnciai de DVDrnf o? Como 6 que n6s conseguimos classificar

instAncias de String? Quando voc6 consulta Collections. sort ( ) na API, a suaprimeirareagio poderia ser

entrar em pAnico. Mas nio se desespere. Mais vmavez, a seglo dos gen6ricos lhe.ajudari a ler. a estranha assinatura

desse m6toio. Se voc6 ler a descrigio do m6todo sort ( ) de um argumento, ver6 que esse m6todo usa um argumento

List, e que os objetos em List precisam implementar umainterface chamada_Comparable. Ocorre que Stringimplementa Comparable, e 6 por isso que-fomos capazes de classificar uma lista de Strings usando o m6todoCollections. sort O .

A Interface ComparableA interface Comparable 6 usada pelos m6todos Cof lections. sort O e java.utils.Arrays. sort opara classificar Lists e arrays de objetos, respectivamente..Para implementar Comparable, a classe precisa

implementar apenas um m6todo, compareTo ( ) . Eis uma chamada de compareTo ( ) :

int x = thisObject.compareTo (anotherObject) ;

O m6todo compareTo ( ) retorna um int com as segu.intes caracteristicas:

I negativo Se thisobject < anotherobjectI zero SethisObject == anotherObjectI positivo Se thisObject > anotherObject

O m6todo sort ( ) usa compareTo ( ) para determinar como o List ou o array de objetos deve ser classificado.

Como voc€ tem a opgio de implementaicompareTo ( ) para as suas pr6prias classes, poderi usar quaisquer

crit6rios que desejaipara classificar as instAncias das suas classes'

Voltando ao nosso exemplo anterior para a classe DVDInfo, podemos optar pela solugio mais ficil e usar a

implementaEio da classe String de compareTo ( ) :

Na linha 1, n6s declaramos que a classe DVDInfo implementa Comparable de uma forma tal que objetos DVDInfopodem ser comparados a ourros objetos DVDInfo. Na linha 2, impllmentamos compareTo ( ) ao.compararmos os

titulos dos dois objetos DVDInfo. IJmaurzque sabemos que os tirulos sio Strings, e que String imo_lementa Compi-rable, essa 6 uma maneira f6cil de classificar oi nossos objetos DVDlnfo: por titulo. Antes da introdugio dos gen6ricos,

em Java 5, teria sido necess6rio implementar Comparable de uma forma parecida com esta:

class DVDInfo implements Comparable {

// +r

// +2

/ / ttsa rrm Oh-iect em vez de

// um tipo especifico

Page 339: Java - Scjp 5 - Portugues

JAVA 5 3I3DVDInfo d = (DVDInfo)o;

return tit1e. compareTo (d. gretTitle ( ) ) ;

]]Isso ainda 6 vilido, mas vocA.pode ver que nio s6 6 complicado como tamb6m arriscado, porque vocA precisa fazeruma conversio, e precisa verificar se a conversio nio vai falhar antes de tenti-la.

oBSERVAQAO pene o EXAME

Einpoftante/embrarque'quandosobresrezaequals O,uociprecisailsartlmargamentodotipoObjecL,ma!,quantlosobrescreaecompareTo O , uocl deue lltar tlm argumento do tipo qae utd clatsfiundo.

Juntando tudo, a nossa classe DVDInfo deveri se parecer com a seguinte:

cl-ass DVDInfo implements Comparable<DVDTnfo> {

Qfrinn Iit-la.

a|-rinn don16.

(t-rinn 1a:dAafnr.

DVDfnfo(String t, Stri-ng g. String a) ititle = t; g'enre = g; leadActor = a;

)

public String toStringO {

ret.urn title genre +

]

"+leadActor+"\n";

public :Lnt coqrareTo(Dt/Dlnfo d) troturrr title. corqrareTo (d. getTitle ( ) ),

)

public String getTitle ( ) {

return title;)

/ / ^111r^a

dafF^'^ ^ ^^!!^-.^/ / vuLrvo vsuLgrD g DgLLct-

)

Agora, quando chamarmos Collections. sort (dvdlist); obteremos

[2001 sci-fi ??

, Caddy Shack comedy Murray. Bill, Donnie Darko sci-fi Gyllenhall, Jake

, Lost in Translation comedy Murray, Bill, Patriot cames action Ford, Harrison

, Raiders of the Lost Ark action Ford, Harrison, Star Wars sci-fi Ford, Harrisonl

Viva! Nosso Arraylist foi classificado por titulos. E claro que, se quisermos que o nosso sistema de automagio decasas 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 queestamos em um beco sem saida. 56 podemos implementar compareTo ( ) uma vez emuma classe,intlo comofazemos para classificar nossas classes em uma ordem diferente daquela que especificamos em nosso m6todocompareTo ( ) ? Boa pergunta. Por sorte, a resposta vem logo em seguida.

Classificando com ComparatorEnquanto estava procurando o m6todo Col-lections . sort ( ) , vocA deve ter reparado que existe uma versiosoblecarregada de q9r_t (_) qre usa um List E algo chamado de Comparator ('comparado4. A interface Comparatorlhe fornece a capacidade de classificar uma dada colegio de uma s6rie de formas difirentes. A outra coisa ritil sobre ainterface Comparator 6 que voc6 pode uslJa para classificar insdncias de qualquer classe - at6 mesmo classes quevoc6 nio pode modificar -, ao contr6rio de interface Comparable, que lhe iorgi a modificar a classe cujas instinciasvoc6 deseja classificar. A interface Comparator tamb6m 6 Eastante f6cil de implementar, rendo apenas um m6todo,

Page 340: Java - Scjp 5 - Portugues

31 4 Copitulo 7: Gen6ricos e Con juntos

compare ( ) . Eis uma pequena classe que pode ser usada para classificar um List de instAncias de DVDInfo, porg6nero.

import java.utiJ-.*;class Genresort implements Comparator<DVDlnfo> {

public int compare(DVDInfo one, DVDfnfo two) t

return one. getcenre ( ) .compareTo (two. getcenre ( ) ) ;

)

O m6todo Comparator. compare ( ) retorna um int cujo significado 6 o mesmo do valor de retorno do m6todo

Comparable. compareto ( i. Neste caso, estamos tirando vantagem disso ao pedir que compareTo ( ) faga o

trabalho de comparaglo para n6s. Eis um programa de teste que nos permite testar tanto o nosso c6digo Comparable

quanto o nosso novo c6digo Comparator:

imnnrf iarrr rrfil *.

'imnnrt- i:rr: in *.

public cl-ass TestDVD {

/ / *^---1 ^L^r I ^!, t :I.ecisa diStO// PVlrUr4Lslf-L\' !

Arraylist<DVDInfo> dvdlist = new Arraylist<DVDlnfo> ( ) ;

pubLic static void main(Stringll arqs) inew TestDVDO.goO;

]n"].'lia "^.iz{ aal\ Ivuvfru vvrs Yv \ /

nnnrrl afaT.i c|- I I .

System. out . println (dvdlist ) ;

Collections. sort (dvdlist) ;

System. out . println (dvdlist ) ;

Genresort gs = new GenreSort ( )

Collections. sort (dvd1ist, ers) ;

System. out . println ( dvdlist ) ;

]

/ / a saida, conforme lida a parti-r do arquivo

/ / a saida, classificada por titulo

/ / a saida, cfassificada por g6nero

nrrl.rlin rrnid nnnrr'lat-6T.icl- I\ Ivgv+4vwvfgyvyg4l4

/ / 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, Harrisona:rtdrr ehaaL nnmadrr M11rr^\/ R i l 1

, vusvJ vvrrresj rrsr r eJ

, Lost in Translation comedy Murray, Bill, 200L sci-fi ??

, Donnie Darko sci-fi Gyll-enhall, Jake

, Star Wars sci-fi Ford, Harrison

l

Pelo fato de as interfaces Comparable e Comparator serem tio parecidas, estera atento para o fato de que o exame

poderi tentar lhe confundir. Por exemplo, poderia ser pedido que voc6 implementasse o m6todo compareTo ( ) na

lnterf.ace Comparator. Estude a Tabela 7-3 para memorizar as diferengas entre essas duas interfaces.

Page 341: Java - Scjp 5 - Portugues

JAVA 5 3I5Tobelo 7-3 Comporondo Comporoble e Comporolor

iava.lang.Comparable java.util.Comparator

int objOne. conpareTo (objT\uo) int compare (objOne, objT\ryo)

Retornanegativo se obj Onezerose objOne ==positivo se ob j One

O mesmo que Comparable< objTwooj)l'rwo> objTwo

Vod precisa modifi car a classe

cujas irstincias deseja classificar.Voc€ cria uma classe separadadaquela cujas instlncias deseja classificar.

56 pode ser criada uma seqii6ncia de classificagio. Podem sercriadas muitas seqiiAncias & classificaglo.

Implementada freqtientemente na API por:String, $?rapper classes, Date, Calendar...

Elaborada para ser implementadacom o obietivo de classificarinstAncias de outras classes.

Classificando com a Classe ArraysEstivemos usando a classe java.util.Collections para classificar conjuntos; vamos ver agora como usar a classejava.util.Arrays para classificar arrays. A boa noticia 6 que classificar arrays de objetoJfunciona da mesma formacomo classificar conjuntos de objetos. O m6todo Arrays. sort ( ) 6 sobrescrito da mesma forma que o m6todoCollections. 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 declassificagio para todos os tipos de primitivos. Os m6todos Arrays . sort i ) qn classificam tipos primitivoss.emPle o .fazem com base na ordem natural. Nio se engane com uma questio do exame que ten6 classificar vm arrayde primitivos usando um Comparator.

Finalmente, lembre-se de que os m6todos sort ( ) tanto para a classe Collections quanto para a classe Arrays sioe_st6ticos, e que eles alteram os objetos que esteo chssificando, emvez de retornar um objeio classificado de iormadiferente.

oBSERVAQoTS pene O EXAME

l{isfalamos um bocado nbre a clastifcapdo por ordem nataral e nbre o aso de Comparatorc para classficar. A r)ltina regra qae uocd

preasani memoriTar 6 que, tempre qile quiser classificar ilm affal oa um coiunto, os elementos contidos nesses objetos deuem vr todos

mataamente companiueis. Em oatrat pa/atras, se uocd tiuer un Obj ecL I J e colocar obietor CaE e Dog dentro dele, ndo Dodeniclasfici-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 ConjuntosAs classes Collections e Arrays fornecem m6todos que lhe permitem procurar por um elemento especifico. Ao fazerbuscas em conjuntos ou arrays, aplicam-se as seguintes regras:

I As buscas sio realizadas usando-se o m6todo binarySearch ( ) .

I As buscas bem-sucedidas retornam o indice int do elemento sendo procurado.

r Buscas mal-sucedidas retornam um indice int que representa o ponto de insergdo. O ponto de insergio 6 o lugar noconjunto/ array onde o elemento seria inserido para manter o conjunto / array corretamente classificado. Pelo fatode valores de retorno positivos e O indicarem buscas bem-sucedidas, o m6todo binarySearch ( ) usa nrimerosnegativos para indicar pontos de insergio. lJma vez que 0 6 um resultado vilido para uma busca bem-sucedida, oprimeiro ponto de inserglo disponivel 6 -1. Assim, o ponto de insergio 6 realmehte represenrado como (-(pontode insergio) -1). Por exemplo, se o ponto de insergXo de ,rma busca estiver no elemento 2, o valor real do'fontoretornado 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 serioprevrsrvers.

I Se o conjunto/array em que voc6 deseja-procurar tiver sido classificado na ordem natural, a busca deve ser feitanessa mesma ordem. (Isso 6 feito ao NAO se enviar um Comparator como argumento para o m6todo

Page 342: Java - Scjp 5 - Portugues

3l6 Copiiulo 7: Gen6ricos e coniunlos

binarySearch ( ) .)

I Se o conjunt o/array em que voc€ deseja procurar tiver sido classificado com um Comparator, a busca deue ser feitausando-se o mesmo Comparator, que 6 passado como o segundo argumento ao.m6todo binarySearch ( ) 'Lembre-se de que Comparators nio podem ser usados ao se buscar em arrays de tipos primitivos.

Vejamos um exemplo de c6digo que p6e em pritica o m6todo binarysearch ( ) :

import java.util.*;class SearchObjArray {

public static void main(String [] args) {

String [] sa = {"one"

Arrays.sort(sa) , ,, Ot

for(String s : sa)

System.out.print(s + " ");q1r<fam nrrf nrinj- lnl\r\nnno ='\

+Arrays.binarySearch(sa,"one")); // #2

System.out.println("now reverse sort") ;

ReSortComparator rs = new Resortcomparator0; / / +3

Arrays . sort ( sa, rs ) ;

for(String s : sa)

System.out.print(s + " ")'q\/qfam nrri- nrinl- ln{"\nonc = "

+Arrays.binarySearch(sa,"one")); // #4

Qrr<l-om ^rrf ^-i-ts]h/\^FA - Nrf r ue.rL. vqL , P! IIf L If I \ vrlE -

+ Arrays.binarySearch(sa,"one".rs)) ; / / #5

Itstatic cl-ass ReSortComparator

implementsComparator<String> { // #6

public int compare(String a, String b) {

returnb.compareTo(a); // #7

)

]

)

o que produz algo como:

four one three two

one=1now reverse sorttwo three one fourone = -1one=2

Eis o que aconteceu:

Linha 1. Classifica o arruy sa, alfabeticamente (a ordem natural).

Linha2 Procura pela localizagio do elemento *um", que 6 1.

Linha 3 Cria uma instAncia de Comparator. Na linha seguinte, n6s re-classificamos o array usando o Comparator

Linha 4 Tentafazor uma busca no array, N6s nio passamos ao m6todo binarySearch ( ) o Comparator que

usamos para classificar o arr^y, e, por isso, recebemos uma resposta incorreta (indefinida).

Linha 5 Nova busca, passando o Comparator a binarySearctr ( ) . Desta vez obtemos a resposta correta,2.

Linha 6 Definimos o Comparator; 6 permitido que esta seja uma classe interna.

Page 343: Java - Scjp 5 - Portugues

LinhaT Ao trocar o uso dos argumentos na chamada a compareTo (

oBSERVAQ6TS pene O EXAME

Ao reto/uer quesldes sobre busca e classifcap1o, os dois errot mais cotzuns tdo:

l. Procurar em tlm an"El ou conjunto que ndo tenha sido c/assficado.

2. Usar um Comparator oa sd na classifcagdo ou sd na basca, mas ndo em ambas.

JAVA 5 3I7

) , obtemos uma classificagio invertida.

Convertendo Arrays em Listas e de Volta em ArraysExistem alguns m6todos que lhe permitem converter arrays em Lists, e Lists em affays. As classes List e Set possuemm6todos toArray ( ), e a classe Arrays poszui um m6todo chamado aslist ( ) .

O m6todo Arrays . aslist ( ) copia um array para dentro de um List. A API diz, "retorne uma lista de tamanhofixo baseada no array especificado (modificag6es feitas na lista retornada sio escritas diretamenre no array)." Quandovoc6 usa o m6todo asl,ist O , o array e o List ficam unidos como se fossem um s6. Quando voc6 atualiza um deles, ooutro 6 atualizado automaticamente. Veiamos:

String[] sa = {"one"List slist = Arrays.aslist(sa);System.out.println("size " + s],ist.sizeO ) ;

System.out.println( "idx2 " + sl-ist .geL(2) | ;

qT,iqt- qal- /? "qiv.\

sa[1] = "five";fnrlQfrind c . <al

System.out.print(s + " ");System.out.println("\nsf [1] " + slist.get (1) ) ;

/ / cria um List

Isso produz

sj-ze 4

idx2 threeone five three srxs1 [1] five

Repare que, quando exibimos o estado final do array e do objeto List, cada um foi atualizado com as modificag6esfeitas 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 m6todotoArray ( ) ; ele tem dois tipos: um que retorna um novo array Object, e um que usa o array que voc6 envia para elecomo o xray de destino:

List<fnteger> iL = new Arraylist<Integer> ( ) ;

for(int x=0; x<3; x++)

i-r,. add (x) ;

// modifica List// modifica o array

/ / tri r rrm =rrarr Al*--*r _JlecE.

/ / rri a rrn :rr:\/ Tnf 6ft6r

Object[] oa = iL.toArray(];Integerll taz = new Integer[3];ia2 = iL. toArray (ia2) ;

Usando ListsLembre-se de que os objetos List sio usados normalmente para manter as coisas em ordem, de alguma forma. Voc6pode usar um Linkedlist para criar uma fila no estilo primeiro-a-entrar-primeiro-a-sair. Voc6 pode usar um Arraylistparu manter registro dos locais que visitou, e em qual ordem. Repare que, em ambos os exemplos, 6 perfeitamentenzoAvel 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. AntesdeJava 5, e do loop f or aprimorado, a maneira mais comum de se examinar um List "elemento por elemento" erausando-se um Iterator. Voc6 ainda encontrarilterators sendo usados em c6digosJava que encontrar, e 6 possivel queencontre alguns deles no exame. Um Iterator 6 um objeto associado com um conjunto especifico. Ele lhe permite fazerum loop atrav6s do conjunto, um passo de cadavez. Os dois m6todos Iterator que vod precisa conhecer para o exame sio:

Page 344: Java - Scjp 5 - Portugues

318 Cooitulo 7: Gen6ricos e Coniuntos

I boolean haelilext ( ) Retorna true se houver pelo menos mais um elemento no conjunto em que esta

sendo feito o loop. Chamar hasNext ( ) NAO move o foco para o pr6ximo elemento do conjunto.

I object next ( ) Este m6todo retorna o pr6ximo objeto do conjunto, E move o foco para o elemento que vemdepois daquele que acabou de ser retornado.

Vejamos um pequeno c6digo que usa um List e um lterator:

imnnrt- i:rra rri-il *.

cfass Dogr {

^"1-'1 ia efrinn n:ma.yuvrfv

Dog(String n) { name = n; }

]

class rtTest {

public static void main(String[] args) {

List<Dog> d = new Arraylist<Dog>O;Dog dog = new Dog("aiko");d :Ari ldnn\ .

d. add (new Dog ( "cl-over" ) ) ,'

d. add(new Dog ( "magno1ia" ) ) ;

Iterator<D,o9> i3 = d.iterator(); ll cria un Lteragor

while (i3.hasNextO ) {

Dog d2 = i3.nex!O; / | ndo 6 preciso converterSystem. out. println (d2 . name) ;

)

System.out.println("size " + d.size() ) ;

System.out.println("getl- " + d.get (1) .name) ;

System.out.println("aiko " + d.indexOf (doS) ) ;

d. remove (2 ) ;

object[] oa = d.toArrayO;for(Objecto:oa) {

Dog d2 = (Dog)o;

System.out.println("oa " + d2.name) ;

]

]

)

Isso produz

aiko

clovermagnolia

size 3

geLl cloverA1KO U

oa aiko

oa cloverPrimeiramente, 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 iteratorMas, assim, n6s teriamos de ter convertido o valor retornado:

Dog d2 = (DoS) i3.next ( ) ;

Page 345: Java - Scjp 5 - Portugues

JAVA 5 319

O restantedo c6digodemonstraousodosm6todos size O, get O, indexof ( ) e toArray( ). Nloh6nadadenovo em nenhum desses m6todos. Daqui a algumas piginas, a Tabela 7-5listaritodos os m6todos de List, Set e Mapcom os quais voc6 dever6 estar familiarizado para o exame. Como um riltimo aviso, lembre-se de que List 6 uma

-

interface!

Usando SetsLembre-se de que os Sets slo usados quando voc6 nio quer ter nenhuma duplicata no seu conjunto. Se tentar adicionarum elemento a um Set que j6 exista nele, o elemento duplicado nio ser6 adicionado, e o m6todo add ( ) retornarifalse. Lembre-se, HashSets tendem a ser bastante ripidos porque, como vimos anteriormente, eles usam c6digos dehashing.

Voc6 pode tamb6m criar um TreeSet, que 6 um Set cujos elementos sio classificados. E preciio rer caurela ao se usarum TreeSet (6 explicaremos o porqu6):

imnnrl- i:rra rrf il *.

class SetTest {

public static void main(String[] argrs) {

boolean[] la = new boolean[5.t ;

// insira c6d.igo aqui

bat01 = s.add("a");ba[1] = s.add(new Integer(421);ba[2] = s.add("b");h:f?l = c aAdlse/\.

ba[4] = s.add(new ObjectO );for(int x=0; x<ba.length; x++)

System.out.print(ba[x] + " ");System. out.println ( " \n" ) ;fnrt0h'ioat n . <\

System.out.print(o + " ").

)

Se voc6 inserir a seguinte linha de c6digo,

Set s = new HashSeto; // lnsira este c6digo

receber6 uma saida como esra:

true true true false truee 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 ""g

garantem nenhum.tipo & ordenagio. Al6m disso, repare que a quarta chamada a add ( 1 falhou,porque tentou inserir uma entradaduplicada (uma String com o valor a) no Set.

Se inserir esta linha de c6digo,

Set s = new TreeSet0; // insira este c6digo

vocA receber6 algo assim:

Exception in thread "main" java.lang.ClasscastExceptlon: java.

1ang. Stringat 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 mutuamentecompariveis. Lembre-se !e que, a nio ser que seja especificado o contr6rio, objetos de tipos diferentes nio siomutuamente comPaf avers.

Page 346: Java - Scjp 5 - Portugues

320 Cooitulo 7: Gen6ricos e Coniuntos

Usando MapsLembre-se de que, quando voc6 usa uma classe ftIash) que implementa Map, quaisquer classes que usar como. parte

das chaves pari o ^apaem

questio deverio sobrescrever os m6todos hashCode O e equals O . @em, voc6s6precisa sobrescrev&los se tiver interesse em obter informag6es do Map. Mas falando s6rio, 6 vilido usar uma classe

que nlo sobrescreva equals ( ) e hashCode ( ) como chaves em um Map; seu c6digo iri compilar e rodar, voc6 s6

nio conseguir6 obter informaglo nenhuma.) Eis algum c6digo demonstrando o uso de um HashMap:

imnarr iarra rrfil *.

cl-ass Dog {

public Dog(String n) { name = n; }

public String name;

public boolean equals(Object o) {

if ( (o instanceof Dog) aa

( (DoS)o).name == name) ) {

reEurn true;) else 1

return false;i

)

public int hashcode ( )

)

class Cat { }

(return name.lengTthO ; l

enum Pets {DOG, CAT, HORSE }

al acc ManrFact I

public static void main(String[] args) {

Mapcobject, Object> m = new Hashlvlap<object, Object>O;

m.put("k1", new Dog("aiko")); // adiciona algruns pares de chave / va]-or

m.put ("k2" , Pets.DOG) ,

m.put (Pets.CAT, "CAT key" ) ;

Dog d1 = new Dog("clover"\; // vamos manter esta refer6nciam.put(d1 , "Dog key");m.put(new CatO , "Cat key") ;

System.out.println(m.get("k1") ) ; / / #1,

String k2 = "k2";System. out.printLn (m. get (k2) ) ; / / #2

Pets p = Pets.CAT,.

System.out.println(m.get (pl ) ; / / #3

System,out.println(m.get (dI) ) ; / / #a

System.out.println(m.get(new Cat O ) ) ; / / #5

System. out.println (m. size (l ) ; / / #6

]

o que produz algo como isto:

Dog@1c

DOG

Page 347: Java - Scjp 5 - Portugues

JAVA 5 32I

CAT key

Dog key

nul-l-

5

Vamos estudar a saida. O primeiro valor obtido foi um obieto Dog (o seu valor poderi ser diferente.) O sezundo valorobtido foi um valor enurn-(DOG). O terceiro valor obtido foi umJStrine: reDara oue a chave 6 um vilor erium. Tester6pido: 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 classejava.lang.Enum na API, ver6 que, de fato, esses m6todos foram sobrescritos.

A quana saida 6 uma String. O ponto mais imponante sobre essa saida 6 que a chave usada para obter a String 6

composta de um objeto Dog. A quinta saida 6 nu 1 1 . O ponto imponante aqui 6 que o m6todo Se t ( ) nio conseguiuencontrar o objeto Cat que fora inserido anteriormente. (A riltima linha da saida confirma que, de fato, exisrem cincopares de chaves,/ valores no Map.) Por que nio conseguimos achar a String com chave Cat? Por que foi possivel usaruma instAncia de Dog como chave, enquanto que usar uma instAncia de Cat como chave nio teve sucesso?

Eficl.rer que Dog substituiu equals ( ) e hashCode ( ) , enquanto que Cat nio ofez.

Vamos dar uma olhada r6pida nos c6digos de hashing. IJsamos uma f6rmula de c6digo incrivelmente simplificada naclasse Dog - o c6digo de um objeto Dog 6 do tamanho do nome da instAncia. Assim, neste exemplo, o c6digo = 4.Vamos comparar os dois seguintes m6todos hashCode ( ) :

public int hashCodeO {reLurn name.length0; } // +1,

public int hashCodeO {return 4; } // #2

Hora de mais um teste r6pido: os dois hashcodes acima sio v6lidos? Ser6 que eles terio sucesso em obter objetos a

panir de um Map? Qual deles ser6 o mais r6pido?

As respostas para as duas primeiras perguntas sio Sim e Sim. Nenhum desses c6digos de hashing ser6 muito eficiente(na verdade, eles seriam ambos incrivelmente ineficientes), mas ambos sio v6lidos, e ambos funcionario. A resposta )riltima pergunta 6 que o primeiro c6digo seri um pouco mais ripido do que o segundo. Em geral, quanto maissingulares os c6digos criados por uma f6rmula, mais r6pida ser6 o obtengio de dados. A primeira f6rmula acimairigerar um c6digo diferente para a extensio de cada nome (por exemplo, o nome Roberto ir| gerar um c6digo, e onome Pedro i-r.6gerar um c6digo diferente). A segunda f6rmula iri sempre produzir o mesmo resultado, 4, e,porisso, serl mais lenta do que a primeira.

O nosso ultimo t6pico relacionado a Map 6 sobre o que acontece quando um objeto usado como chave tem os seus

valores modificados. Se adicionarmos duas linhas de c6digo ao MapTest . main ( ) anterior,

d1.name = "magnofia"q1/<|-6m

^rr|- nrirt- lnlm nat. ld'l\\.vJ e LvfrL I vsv . yr 4rf e+

obteremos algo como:

DogB4

DOG

CAT key

Dog key

nul1

5

nu11

O Dog que havia sido encontrado anteriormente nlo pode mais ser encontrado. Pelo fato de a variivel Dog . name ser

usada para criar o c6digo de hashing, modificar o nome causa a modi{icaglo do c6digo. Como um rtltimo teste

relacionado aos c6digos, determine a saida das seguintes linhas de c6digo, caso elas sejam adicionadas ao final de

MapTest.main ( ) :

d1.name = "magnolia";

System.out.println(m.get(d1 )); // #L

d1.name = "clover";System.out.println(m.get(new Dog("clover") ) ); / / #2

dl- . name = "arttrur" ;

System.out.printfn(m.get(new Dog("c1over")) ); / / #3

Page 348: Java - Scjp 5 - Portugues

322 Cooiiulo 7: Gen6ricos e Coniunlos

Lembre,se de que o c6digo de hashing 6 igual ao tamanho da variivel name. Ao se deparar com um problema desse

tipo, pode ser ritil pensar nas duas etapas da obtengio:

1.. Usar o m6todo hashcode ( ) para achar agaveta correta

2. Usar o m6todo equals O paraachar o objeto dentro dagaveta

NaprimeirachamadaagetO,oc6digo68(magrnolia) edeveriaser6(clover),demodoqueaobtengiofalhanopassoLen6sobtemosnull.NasegundachamadaagetO,osc6digossioambos5,entioopassoltemsucesso.Tendo achado a gaveta correta (a gaveta "tamanho de name : 6"), o m6todo equals ( ) 6 chamado e, uma vez que o

m6todo equals O de Dog compara nomes, equals O tem sucesso, e a saida 6 oog key. Na terceira chamada a

set O, ot.rr.doc6digo temsucesso, mas otestede equals O falhaporque arthur NAO 6 igual a clover.

Daqui a algumas paginas, a Tabela 7-5 resumir6 os m6todos & Map com os quais vocA deveri estar familiarizado para oexame.

Usando a Classe PriorityQueueA 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 ordenaos 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 podeser ordenada usando-se um Comparator, que lhe permite definir qualquer ordenamento que quiser. As filas possuemalguns 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;

)

public static void main(Strj-ng[] args) {

int[] ia = {1,5,3,1,6,9,8 };eriorityQueue<fnteger> pq1 =

new PriorityQueue<Integer> ( ) ;

fnrf inl- v . i:\

na1 nffar /v\ .

for(int x : ia)System.out.print(pq1 .poll() + " ");

System. out . println ( " " ) ;

PQsort pqs = new PQsort ( ) ;

Prj-orityQueue<Integ'er> pq2 =

new PriorityQueue<Integer> ( 10, pqs ) ;

for(int x : ia) // carrega a filana? nffar 1v\

System.out.println("size " + pq2.sizeO ) ;

System.out.println("peek " + pq2.peekO ) ;

System.out.println("size " + pq2.sizeO ) ;

System.out.println("po11 " + pq2.po11 O ) ;

System.out.println("size " + pq2.sizeO ) ;

for(int x : ia) // revisa a filaSystem.out.print(pq2.po1l 1 I + " ") ;

/ / ordem inversa

/ / rrnl-rnvina

/ / dados n5o-ordenados

/ / usa a ordem natural-

// aarranz: fil:

// revisa a fila

/ / obL6m um Comparator

// usa o Comparator

Page 349: Java - Scjp 5 - Portugues

JAVA 5 323

)

Esse c6digo produz algo como:

1356789

sj-ze 7

peek 9

size 7

poll 9

size 6

B'1 6531-null

Vejamos isso em mais detalhes. O primeiro loop f or itera atrav6s do anay ia, e usa o m6todo of fer ( ) paraadicionar elementos ao PriorityQueue chamado ps1. O segundo loop for itera atrav6s de pq1 usando o m6todopoll ( ) , o qual retorna a entr^da com maior prioridade em pq1 E remove essa entrada da fila. Repare que oselementos 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 confirmaquepeekoretorna o elemento com a prioridade mais alta na fila sem o remover, e po11 ( ) retoma o elemento com a prioridademais alta E o remove da fila- Finalmente. revtl,samos os elementos restantes da fila.

Visio Geral dos M6todos para Arrays e ConjuntosNo que se refere a essas duas classes, j6 abordamos os m6todos mais complexos que voc6 poder6 encontrar no exame.A Tabela 74 apresentaum resumo dos m6todos que voc6 tamb6m precisa conhecer. (Observagio: A sintaxe t [ ]ser6 explicada mais adiante neste capitulo; por agora, pense nela como significando "qualquer array que NAO seja umarray de tipos primitivos.")

Tobelo 7-4 Principois M6todos em Arroys e Coniunlos

Principois M6todos em iovo.util.orroys DescriE6es

static List aslist (f t I ) C-onvene um ar:ry em um List (e vincula um ao outro).

static int binarySearch (Object[ ],k"y)static int binarysearch (primiLive [ ] , key)

Procuram em urn array classificado por um dado valor,retornam um indice ou ponto de insergio.

static int binarySearch (T[ ], key, Comparator) Procura um valor em um array classificado comComparator.

static boolean equals (Object[ ], Objectt I )

static boolean equals (primitive[ ], primitive[ ] )

Comparam dois arrap para determinar se os seus

conteridos sio iguais.

public staticvoid sort (Object[ ] )

public static void sort (primitive [ ] )Classificam os elementos de um arrav por ordem natural.

public staticvoid Eor! (T[ ], Comparator) Classifica os elementos de um array usando umComparator.

public static String tostring (Object[ ] )

public static String toString (primitive [ ] )Criam uma String que possui o conterido de um array

Page 350: Java - Scjp 5 - Portugues

324 Copitulo 7: Gen6ricos e Coniuntos

Principois M6todos em iovo.util.Collections DescriE6es

static int binarySearch (List, key)static int binarysearch (List, key, Comparator)

Procuram em um List "classificado" por um valor,

retornam um indice ou ponto de inserglo.

static void reverse (List) Inverte a ordem dos elementos em um List.

static Comparator reverseOrder ( )

static Comparator reverseOrder (Comparator)Retornam um C-omparator que classifica o inverso da atual

seqiiAncia de classificaglo do conjunto.

static void Eort (List)static void sort (List, Comparator)

Classificam um List ou pela ordem natural ou por umComparator.

Visio Geral dos Mtitodos para List, Set, Map e Queue

No caso dessas quatro interfaces, ji abordamos os m6todos mais complexos que voc6 poder| encontrar no exame. ATabela 7-5 apresenta um resumo dos m6todos de List, Set e Map que voc6 tamb6m precisa conhecer.

Tobelo 7-5 Principois M6todos em Lisl, Set e Mop

Para o exame, os m6todos de PriorityQueue que vocA precisa entender sio of f er O (que 6 semelhante a add O ),peekO (que obt6mo elementono iniciodafila, masnio o apaga) epo11( ) (que obt6m oprimeiro elementoe oremove da fila).

OBSERVAQ6TS pene O E)GME

E inpotante conhecer a/guns detalhes da ordenagdo natural. O rcguinte cddtgo lhe qudm,l a entender as poigdu rclatiuat de caractms naitisculos,minilscu/os e eJ\a[os na ordena€do natura/:

Principois M6todos do Inter{oce List Set Mop DescriE6o

boolean add (element)boolean add (index. element)

Adicionam um elemento. Para Lists,opcionalmente adicionam o elemento em umponto indice.

boofean contains (object)boolean containsKey (object key)bool-ean containeValue (obj ect value)

XX

Procuram em um conjunto por um objeto (ou,

opcionalmente, por Maps com urna chave),

retornam o resultado como um valor booleano.

object get (index)object get (key) x

ObtAm um objeto de um conjuntq atrav6s de

um indice ou uma chave-

int indexOf (object)Obt6m alocalizagio de um objeto em um List.

Iterator iterator ( ) Obt6m um Iterator panr um List ou Set.

Set keyset, ( ) Retorna um Set contendo as chaves de um lvlap.

Dut (key, value) Miciona um par de chave / valor a um ldap.

remove ( index)remove ( obj ect )

remove (key)X

Removem um elemento atrav6.s de um indice,do valor do elemento ou de uma chave.

i-r ^i-^/\rrrL srze t, xRetorna o nrimero de elementos de umconiunto.

ObjectI I toArray (1

r[ ] toArray (Tt I )X X

Retornam um arraycontendo os elementos doconluruo.

Page 351: Java - Scjp 5 - Portugues

JAVA 5 325

String[] sa = {"tf f.", \\> f<'i\, \,>f <,,, l,>FF<\\ }; / / est6. ordenado?

PriorityQueue<String> tre3 = new Priorj-tyeueue<String> ( ) ;

for(String s : sa)

na? nffarlc\ .

for(String s : sa)

System.out.print(pq3.poll O + " ") ;

Isn pndu4

> f< >FF< >f < >ff<

Se uoc6 se /embrarque os espaEot sdo cobcados antes dos caracteres e qae at lehas naitiscalu sdo colocadas antes das minilsculr, utani bempara o

exane,

Obietivo poroi o CertificoEdo

Tipos Gen6ricos (Objetivos 6.3 e 6.4 do exame)

5.3 Estreuer cddiga qt/e ilse a., uersdu gendricar da API dos Conluntos, en particular as tnterfans Set, List e Map e as clatses de implenentagio.

Reconhecer as kmitagdes da API nda-gendica dos Co$untos e como refatorar cddigo para usar as uersdes gendicas.

6.4 Desenuoluer aidigo qae use @mpriadanente os parhmehts de tipo en declaragdes de clasnsf intufacu, uaridueis dz insti.ncias, argamentos de

nitodns 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, antesde Java 5, nlo havia nenhuma sintaxe para declarar um conjunto com esse mesmo comportamento. Para criar umArraylist de Strings, voc6 usava:

Arraylist mylist = new Arraylist ( ) ;

ou o equivalente polim6rfico:

r i -f mvT i cf - nar.r Arra\rT..i <1- l l .!f Du ILLJIrDL - Irgw n!!qt!f ru \ / ,

Nio havia nenhuma sintaxe que lhe permitisse especificar que mylist usaria Strings e somente Strings. E, niohavendo 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 motivagiopara os gen6ricos terem sido adicionados ) linguagem.

E essa nio foi uma decisio f6cil, nem foi uma adigio inteiramente bem-vinda. Isso porque, junto com capaci&de de se

usar tipos especificos, os gen6ricos v6m com uma consider6vel bagagem - a maior pane vod nunca ver6 nem ter6 de se

preocupar com ela, mas existem algumas quest6es que surgem de forma str4rreen&ntemente r6pida Abordaremos aquelasmais 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 demoraramtento), foi como lidar com c6digos antigos escritos sem os gen6ricos. Os engenheiros Java da Sun obviamente neoqueriam estragar todos os c6digos Java existentes, enteo, tiveram de encontrar uma maneira de as classes Java com tipoespecifico (gen6ricas) e as sem tipo especifico (nXo-gen6ricas/pr6-Java 5) conseguirem funcionar juntas. A solugXoencontrada nlo foi a mais amig6vel, mas ela lhe permite usar c5digo antigo, nio-gen6rico, ao mesmo tempo usandoc6digo 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 serdesastrosas e, infelizmente, a maioria dos desastres ocorrem em tempo de execugio, e nio de compilagio. Felizmente,no entanto, a maioria dos compiladores geram avisos que lhe informam quando voc6 esti usando conjuntos nio-seguros (significando nio-gen6ricos).

O exame Java 5 aborda conjuntos tanto no estilo pr6-Java 5 (nio-gen6rico) quanto no estilo Java 5, e vocA veri quest6esque esperam que voc6 entenda os complexos problemas que podem surgir quando mistura c6digo nio-gen6rico comgen6rico. E, como alguns dos outros t6picos deste livro, seria possivel escrever um livro inteiro se f6ssemos abordar

Page 352: Java - Scjp 5 - Portugues

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 desenvolvedoresprecisar| usar na prinica.

A Forma Antiga de se Usar ConjuntosEis uma revisio de um Arraylist pr6-Java 5 criado para armazenar Strings. (Dissemos "criado" porque isso era tudo oque voc6 podtafazer - criar o conjunto -, mas nada garantiaque o Arraylist iria armazenar apenas Strings).

List mylist = new ArraylistO; // impossivel- declarar um tipo

Um conjunto nio-gen6rico 6 capaz_de armazonar qualquer tipo de objeto! Um conjunto nio-gen6rico armazenaalegremente qualquer coisa que NAO seja um tipo primitivo.

Isso significava que era responsabilidade total do programador ser... Cuidadoso. Nlo ter nenhuma maneira de garantiro tipo do conjunto nio era muito amistoso para o programador em um linguagem tio rlgtda com relagXo aos tipos.Estamos tio acostumados com o compilador nos impedindo de, por exemplo, atribuir um int a uma refer6nciabooleana ou uma String a uma refer6ncia Dogl rn?s' com os coniuntos, a hist6ria era "pode entrar! A porta estisempre abena! Todos os objetos sio bem-vindos aqui a qualquer hora!"

E, uma vez que um conjunto podia armazcnar qualquer coisa, os m6todos que retiram objetos do conjunto s6 podiamter uma esp6cie de tipo de retorno - java.lang.Object. Isso significava que, para retirarmos uma String da nossa listaque-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 possivelcolocar 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 nosseus conjuntos. Vamos atualizar a lista String:

List<String> mylist = new Arraylist<String> ( ) ;

/ / OK, armazena SLrings

/ / erro de compilagSo ! !

Perfeito. E, e"ata-ente isso o que queriamos. Ao usar a sintaxe dos gen6ricos - o que significa colocar o tipo entresinais de maior e menor ( String ) , estamos dizendo ao compilador que esse coniunto s6 poder6 armazenar ob.ietosString. O tipo declarado dentro dos sinais 6 conhecido como "tipo parametrizado", "parAmetro de tipo" ou, 6 claro, onosso bom e velho "tipo". Neste capitulo, iremos nos referir a ele usando os dois novos termos tamb6m.

Entio, agora que garantimos o tipo do que seri INSERIDO, voc6 pode tamb6m garantir o tipo do que ser6RETIRADO, e isso significa que voc6 pode se livrar da conversio quando receber algo do conjunto. Em vez de:

String s = (String)mylist.get(0); // pr6-gen6rj-cos, quando ndo

/ / era garantido que receberi.amos uma Stringagora podemos usar simplesmente

Stri-ng s = mylisL. get (0 ) ;

O compilador j6 sabe que mylist cont6m apenas coisas que podem ser atribuidas a uma refer6ncia String, entXo,nio 6 mais necessirio usar uma converslo. At6 aqui, tudo parece bem simples. E, com o novo loop for, 6 claro quevoc6 pode fazer iterag6es atrav6s da lista de Strings:

for (String s : myl,ist) {

int x = s.lengtho;/ / n6,o 6 preciso converter antes de chamar um m6todo string! o

/ / compilador j6 sabia que \rs" era uma String vindo de Mylist

]

E, 6 claro, vocA pode declarar um parAmetro de tipo para um argumento de m6todo, que, enteo, transforma oargumento em uma refer€ncia de tipo especifico.

mrrT.i cf ad.l / \E'rad " \---- , i

mylist.add(new Dog ( ) ) ;

myl-ist. add (new fnteger (42) \ ;

mylist . add ( "Fred" ) ;mylist.add(new Dog( ) ) ;

/ / iv a1 a anazan^ Qf rihdc

/ / e armazena Dogts tamb6m

// eAnLegers...

Page 353: Java - Scjp 5 - Portugues

JAVA 5 327

void t.akel,istOfStrings (List<String> strings) {

strings. add ('.foo', ) ; / / adiedo de uma String sem problemas

)

O m6todo acima NAO compilaria se o modificissemos para:

void takelistOfStrings (List<String> strinqs) {

strings.add(new Integer(42)l; // NAO! ! strings s6 pode receber Stringrs]

Obviamente, tipos de retorno tamb6m podem ser declarados com tipo especifico:

public Set<Dog> getDoglist ( ) {

Set<Dogr> dogs = new HashSet<Dog> ( ) ;

/ / mais c6digo para inserir dogs

return dogs;

)

O compilador o impedir6 de retornar qualquer coisa que nio seja compativel com um Set(Dog) (embora essaquestlo de o que 6 e o que nio 6 compativel ficari bem interessante logo a seguir). IJma vez que o compilador garantaque apenas um DogSet de tipo especifico ser6 retornado, os objetos que chamarem o m6todo nio precisario de umaconversio para retirar Dogs do Set:

Dog d = getDoglist0.get(0); // fr sABrDo que receberemos um Dog

Com c6digo pr6-Java5, nio-gen6rico, o m6todo getDoglist ( ) seria

public Set getDogl,ist ( ) iSet dogs = new HashSet0;

/ / c6digo para adicionar apenas Dog,s., . Cruzem os dedos. . .

return dogs; / / um Set de QUAIQUER COISA funcionar6 aqui

)

e o chamador precisaria de uma conversao:

Dog d = (Dog) getDoglistO .gret(0);

(A conversio neste exemplo aplica-se ao que vem do m6todo seL ( ) de Set; n6s nio estamos conveftendo o que 6

retornado do m6todo getDoglist ( ) , que 6 um Set)

E quanto ao beneficio de um conjunto completamente heterogeneo? Em outras palavras, e se voc6 gostasse do fato deque, antes dos gen6ricos, era possivel criar um Arraylist que armazenasse qualquer tipo de objeto?

List mylist = new arraylist O ; / / esLilo antigo, n5o-gen6rico

6 quase id€ntico a

Lj-st<Object> myl,ist = new

Arraylist<Object> O; / / armazea QUALQUER tipo de objeto

Declarar um List com um parAmetro de tipo < Object > cria um conjunto que funciona quase da mesma forma que osconjuntos pr6-Java 5, nio-gen6ricos - 6 possivel colocar QUATQUER tipo de Object no conjunto. VocA veri maisadiante que os conjuntos nio-gen6ricos e os conjuntos de tipo < Object > nio sXo completamente similares, mas, namaior parte do tempo, as diferengas nio imponam.

Ah, se isso fosse o fim da hist6ria... Mas ain& existem algumas quest6es complicadas referentes a argumentos dern6todos, polimorfismo e a integragio entre c6digo gen6rico e niogen6rico, de modo que estamos apenas nosaquecendo aqru.

Page 354: Java - Scjp 5 - Portugues

328 Copitulo 7; Gen6ricos e Coniunlos

Gen6ricos e C6digos AntigosA 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 doconjunto, 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 .i ^r - *ar.r LrrarzT,i c{- 1\ .!I>L rttyll>L - IIsw dt!4J!f oL \ / t

se torna

List<Integer> mylist = new Arraylist<lnteger> ( ) ;

uma lista criada para arm zenar apenas Strings passa de

public List changeStrings(Arraylist s) { i

para isto:

public List<String> changestrings(Arraylist<String> s) i ]

Moleza. E se houver c6digo quee$ragar o c6digo de ningu6m:

Thf^d6t i - /Tnranar\frrLc:jer f - \rrrLsvs!/

Misturando Conjuntos Gen6ricos e Nio-Gen6ricos

E aqui que as coisas comegam a ficar interessantes... Imagine que tenhamos um Arraylist, do tipopassando para um m6todo de uma classe de cujo c6digo-fonte nlo temos acesso. Ser6 que isso aqui

/ / uma classe Java 5 usando um conjunto gen6rico'imnnrf iarr: rrf i l *.

public class Testlegacy {

public static void main(String[] args) {

List<Integer> myl,ist = new Arraylist<Integer> ( ) '

// .^n"irlnl-^ da f inn aenanifinn| | vv.LJ Lfyv esyve

mylisr.add(4);myl,ist.add(6);Adder adder = new eddero;int total = adder.addall(myl,ist);

// passado para um argumento sem tipoSystem. out.println (tota1 ) ;

]

Eis a classe antiga, nio-gen6rica, que queremos usar:

'imnnrf i:rr: rrt- i'l *.

class Adder {

int addA]1(List list) {

/ / m6todo com um argumento List n5o-gen6rico,/ / mas assume (sem garantia nenhuma) gue serSo Int.egfers

Iterator it = 1ist. iterator ( ) ;

int total = 0;

usava a verseo nio-gen6rica e realizavauma conversao para obter coisas, isso nio vai

list.get(0li // a conversSo ndo 6 mais necess5ria,

/ / mas deix6-1a aqui ndo causar6 problemas

lnteger, e o estamosvai funcionar?

Page 355: Java - Scjp 5 - Portugues

JAVA 5 329

No exemplo anterior, o m6todo antigo addA11 ( )restringida a Integers, mesmo que, quando o c6digodo programador ser cuidadoso.

)

Sim, fu-nciona sem problemas. E possivel misturar c6digo gen6rico correto com c6digos anrigos, nio-gen6ricos, e todosficam felizes.

presumiu (confiou? torceu?) que a lista passada estava de fatofoi escrito, nio houvesse nenhuma gararfiia. Era responsabilidade

Umavez que o m6todo addAll ( ) nio estava fazendo nada, exceto obter o Integer (usando uma conversio) de umalista e acessar o seu valor, nio houve problemas. Nesse exemplo, nio houve nenhum risco para o c6digo do chamador,mas o m€todo antigo poderia ter falhado caso a lista que foi passada contivesse qualquer coisa que nio fosse umInteger (o que teria causado uma ClassCastException).

Mas, imagine agora que voc6 chame um m6todo antigo que nio apenas leia um valor, mas adicione algo ao ArraylistlSer6 que vai funcionar?

import java.util.*;nrrl-r'l i a nl:c< rn6ciR^dT.6dA^1r Is\4\4seYsvj 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-gen6ricovoid 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 foraoriginalmente declarada como ( Integer ) , portanto, nlo h6 nenhum problema.

Mas... E se modificarmos o m6todo insert ( ) desta forma:

while (it.hasNextO )

int i = ((Integer)total += i;

)

return total;

void insert(List list) {

1 i cf :rt^ /rat.r cfrih^/\/t/ \ \ .\rrsw oulfrrv \ a- I I I

]

{

it.next ( ) ) . intValue( ) ;

// nAa rrma al-rinn n: lic+-:| / Pvv ffry rfs

/ / <anAa n:cc:da

Ser6, que isso vai funcionar? Sim, infelizmente funciona! Isso compila e executa. Nenhuma exceglo de tempo deexecugio. 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 c6digosantigos (a ultima coisa que a Sun queria era pedir que milh6es de desenvolvedores Java modificassem todos os seus

c6digos existentes).

Page 356: Java - Scjp 5 - Portugues

330 Copitulo 7: Gen6ricos e Coniuntos

Assim, o compilador Java5 6 forgado a permitir que voc6 compile oseu c6digo novo mesmo que ele chame um

m6todo de ,tma classe antiga que usa rr- "rgorn"nto

sem tipo especifico, e faga deus-sabe-o-qu6 com ele.

Entretanro, s6 porque o compiladorJava 5 permite que esse c6digo compile, nio quer {ize1 que ele fique FELZ com

isso. Na verdade, oiompilador iri thi advertir de qG est6 assumindo um grande, {ande risco ao enviar o seu

excelente Arraylist ( Integer ) para um m6todo perigoso que pode inserir Floats, Strings ou at6 mesmo Dogs na sua

lrsta,

Quando voc6 chamou o m6todo addall ( ) em um exempl_o anterior, ele nio inseriu nada nalista (simplesmente

adiciorrou os valores dentro do conjunto), de forma que nio houve risco, para o chamador, de que a sua lista fosse

modificada de alguma forma horrivel. O c6digo compilou e executou sem problemas. Mas, na segunda versXo, com o

m6todo antigo insert ( ) que adiciona uma String, o compilador gerou um aviso:

j avac TestBadlegacy. java

NoLe: TestBadlegacy.java uses unchecked or unsafe operations.

Note: Recompile with -Xfint:unchecked for details.

lrmbre-se de que os auisos do runpiladlrNAo sdo consifuradot un erm dr compikgdo. O compilador gerou um arquivo de classe

perfeitamente v6lido a partir & compilagio, mas foi gentil o suficiente para lhe dizer o _equivalente a: ."Eu esPero

ieriamente que voc6 saiba o que esta fazendo,porque este c6digo antigo NAO tem nenhum respeito (e nemconhecimento) do seu tipo especifico ( lnteger ) , e poderi fazer o que quiser com o seu preciosoArraylist(Integer)".

OBSERVAQ6ESpeneOE)(AME

Certifqa*se de saber a dfervnga entre "a compila4dofalha" e "conpila rem enos", e enhe 'bonpila sem auisos" e "compila com auisot". Na maioia

das quutdes do exame, sd d preciso uber w compi/a ou w a conpikgdo falha - auisos do conpzlador nio fardo diferenga para a naior parte do exama

Porin, quando uoc| estiaer usando gendricot e misturando aldigo com e sem tipos especlfcos, ot auisos passam afaryr difmnga.

De volta ao nosso exemplo com o c6digo antigo que fazuma inserglo, tenha em mente que, para AMBAS as vers6es

do m6todo insert ( ) (uma que adiciona umlnteger e outra que adiciona uma String), o compilador emitir6 avisos.

O compilador NAO sabe se o m6todo insert ( ) esti adicionando a coisa cena (Integer) ou a errada (String). A razlopela qual o compilador produz um aviso 6 porque o m6todo esti ADICIONANDO algo ao conjunto! Em outraspalavras, o compilador sabe que h6 uma chance de que o m6todo possa adicionar a coisa enada a um conjunto que ochamador pensa ser de tipo especifico.

OBSERVAQ6ESpRneOE)(AME

Para os propdsitot do exame, a ndo vr que a que$do inc/aa uma resposta que mencione auisos, mtia, mesmo qae wc6 niba que a compi/agdo os

pmdu{ri, ainda asim se trata dz una compilagdo com sacesso!A nnpila.{Ao com auins NUI'JCA d considerada como unafalba de nnpihEdo.

Mais urua aeq- se uir um cddigo que uoc| sabe qae iri compi/ar com auisos, I\{AO escolha "a corrpilag1ofalha" como a retposta. A quutdo d a

seguinte: am aidigo que nmpilt com auins ainda d una compikgdo cun st'lcesso. Se a pagunta d.o exame quivr testar o rea conhecinento dc se o

nldigo pnda{ni am ayiso (oa o que mc€ pode faryr con o nidigo para EIJMII,{AR os auisos), a peryunta (ou a rcspwtQ induinl explcitamente a

palura "auisos".

At6 aqui, ji vimos como o compilador irS,gerar avisos caso perceba que h6 uma chance de que o seu conjunto de tipoespecifico 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 temid6ia de que o seu Arraylist devia armazenar apenas Integers. A informagio sobre os tipos nio existe em tempo deexecugio! 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 - tantoos 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 outraspalavras, que vocA tenha ESCRITO

List<Integer> mylist = new Arraylist<Integer> ( ) ;

Page 357: Java - Scjp 5 - Portugues

JAVA 5 33I

Depois que o trabalho do compilador termina, aJVM vA o que ele sempre viu antes deJava 5 e dos gen6ricos:

Lj-st mylisL = new Arraylist O ;

O compilador at6 mesmo insere as convers6es para voc6 - aquelas que voc6 tinha de fazer para retirar coisas de umconjunto prdava 5.

Pense nos gen6ricos como uma proteglo estritamente de tempo de compilaglo. O compilador usa informag6es detipos, gen6ricos (o < tipo ) entre sinais de maior e menor) para ceftificar-se de que o seu c6digo nio colocar6 as coisaserradas em um conjunto, e de que voc6 nio atribuir6 o que receber de um conjunto ao tipo de refer6ncia errado. MasNADA dessa protegio existe em tempo de execugio.

Isso 6 um pouco diferente dos arrays, que lhe fornecem protegeo TANTO em tempo de compilagio quanto emtempo de execuglo. Por que eles fizeram os gen6ricos assim? Por que nio existe informagio de tipo em tempo deexecuglo? Para dar supofte a c6digos antigos. Em tempo de execufXo, os conjuntos slo similares ios conjuntos deantigamente- O que voc6 ganha ao usar os gen6ricos 6 uma protegio de tempo de compilagio o qual garante que voc6nio colocari a coisa errada em uma colegio com tipo definido, e tamb6m elimina a necessidade de uma conversio aose retirar algo, uma vez que o compilador ji sabe que, de uma lista Integer, s6 pode sair um Integer.

O fato 6 que voc6 nio PRECISA de protegio em tempo de execugio... At6 que comece a misturar c6digo gen6rico e

nio-gen6rico, como fizemos no exemplo anterior. Ai entlo voc6 pode ter desastres acontecendo em tempo deexecugio. O 6nico conselho que podemos dar 6 prestar muita atenglo nestes avisos do compilador:

javac TestBadlegacy. java

Note: Test.Badlegacy.java uses unchecked or unsafe operations.Note: Recompile with -Xlint:unchecked for details.

Esse aviso do compilador nio 6 muito descritivo, mas a segunda observagio sugere que voc6 recompile com -xlint : unchecked. Se o fizer, voc6 receber6 algo como isto:

javac -X1j-nt :unchecked TestBadlegacy. java

TestBadlegacy. java: 17 : warning: [unchecked] unchecked cafl- toadd(E) as a member of the raw tl4)e java.util.l,ist

list. add (new String (" 42" \ ) ;

1 warning

Quando voc6 compila com o flag -Xlint : unchecked, o compilador lhe mostra exatamente guais m6todospoderio fazer algo perigoso. Neste exemplo, uma vez que o argumento da lista nio foi declarado com um tipo, ocompilador o trata como se fosse um c6digo antigo e assume que nio h6 risco a respeito do que o m6todo colocar6 nalista.

No exame, voc6 precisar6 ser capaz de reconhecer quando est6 compilando c6digo que ir6 produzir avisos, mas, aindaassim, compilar. E qualquer c6digo que compile (mesmo com avisos) ir6 executar! Nenhuma violaqXo de tipo ser6detectada em tempo de execugio pelaJW[, at6 que essas violag6es bag;uncem o seu c6digo de alguma outra forma. Emoutras palavras, o ato de adicionar uma String a uma lista ( Integer ) nlo vai falhar em tempo de execugio at6 quevoc6 tente tratar essa String-que-voc6-pensa-ser-um-Integer como um Integer.

Por exemplo, imagine que voc6 queira que o seu c6digo retire algo do seu (supostamente seguro)Arraylist (Integer), no qual um c6digo antigo inseriu uma String. Ele compila (com avisos). E executa... Ou pelomenos o c6digo que faz essa insergio de uma String executa. Mas quando voc6 retira a String-que-nXo-deveria-estar-16da 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 nioaparece no momento em que voc6 usa add ( ) no conjunto. Ele s6 aparece depois, quando voc6 tenta usar algo da listae esse elemento nio bate com o que voc6 esperava. Antigamente (no tempo pr6-lava 5), vocA sempre assumia quepoderia receber a coisa errada de um conjunto (uma vez que nenhum conjunto era de tipo especifico), entao vocetomava 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 terescrito c6digo com tipos especificos. Basta se lembrar que, assim que vocA repassa o seu conjunto de tipo especificopara nm c6digo antigo, que nio usa tipos especificos, a protegio j6fioi para o espago.

Novamente, preste muita atengio nos avisos do compilador, e esteja preparado para ver quest6es como essas

aParecendo no exame.

Page 358: Java - Scjp 5 - Portugues

332 Copftulo 7: Gen6ricos e Coniuntos

oBSERVAQ6TS pene O EXAME

Ao uur conjuntot anlgos (sen tipo eEedfn) - caidado comproblemas de unboxingl Se uocd declarar am conjanto ndo-gendico, o mitodo

get ( ) SEMPRE retomard una referlncia do tipo jaua.lang.Objut. Lznbre-se de que o uaboxing ndo i c@a7de conuerter um Objut erz

un tipoprimitiuo, nem meimt se a referincia duse Objut apontarpara am Integer (oz algun outro tipoprinitiuo) no he@. O unboxing

somente conuerte de una referincia a uma clatse wrapper (como um Integer au uru Lnng) para un tipo pinitiuo.

Mais ama coisa a se tomar cuidado com re/ag6o a anboxing

List test = new Arraylist ( ) ;

test.add(43);i -r -- - / T-r^^^-\ r^^r ^^F / n \ ,rfru i - lfrlLs\Js!/ Ls-L.vsL\v/ t / / 6 preciso converter I !

List<Integer> test2 = new Arraylist<Integer> ( ) '

test2.add(343) ;

int x2 = test2.qet(O); // a conversdo ndo 6 necess6ria

Cuidado com conuercdesfaltando em conjantos pri-Jaua 5 ndo-gendicos.

Polimorfismo e os Gen6ricos

Os conjuntos gen6ricos lhe dio os mesmos beneficios da seguranga de tipos que voc6 sempre teve com os arrays, mas

existem algumas diferengas cruciais que podem lhe pegar se voce nXo estiver preparado. A maioria delas tem a vercom o polimorfismo.

Voc6 ji viu que o polimorfismo se aplica ao tipo "base" do conjunto:

List<fnteqer> mylist = new Arraylist<Integer> ( ) ;

Em outras palavras, podemos atribuir um Arraylist a uma refer6ncia List, porque List 6 um supeftipo de Arraylist.Nada especial ai - essa atribuigio polim6rfica funciona da maneira como sempre funcionou em Java,independentemente dos tipos gen6ricos.

Masequantoaisto?

cl-ass Parent { }

class Child extends Parent { }

List<Parent> mylist = new Arrayf,ist<Chi1d> ( ) ;

Pense nisso por um minuto.

Continue pensando...

Nlo, isso nlo funciona. H6 uma regra bastante simples aqui - o tipo da declaragio davari|vel precisa bater com o tipoque vod passa ao tipo real do objeto. Se vod declarar List ( Foo ) foo, entio qualquer coisa que vod atribuir ) refer6nciafooDEVEserdotipogen6rico (Foo>.Nioumsubtipode (Foo).NXoumzupertiposw (Foo).Apenas (Foo).

Estes estlo errados:

List<Object> mylist = new Arraylist<JButton>O; // NAo!

List<Numlcer> numbers = new Arraylist<Integer>O; // NAOI

// lembre-se de que Integfer 6 um subtipo de Number

Mas estes esteo corretos:

List<'JButton> myl,ist = new Arraylist<JButton>O; // sLm

List<Object> mylist = new Arraylist<Object>O; / / sLm

List<Integer> mylist = new Arraylist<Tnteger>O; // sim

At6 aqui, tudo bem. E s6 manter id6nticos o tipo gen6rico da refer6ncia e o tipo gen6rico do objeto ao qual ela se

refere. Em outras palavras, o polimorfismo aqui se aplica apenas ao tipo "base'. E, por "base", queremos dizer opr6prio 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,

Page 359: Java - Scjp 5 - Portugues

JAVA 5 333

onde 6 permitido que voc6 faEa isto,

import java.util.*;nlacc Daranf I l

class Child extends Parent { }

public class Testpoly {

public static void main(String[] argrs) {ParentlJ myarray = new childt3l; // sim

I

o que significa que ramb6m 6 permitido que voce faga isto

Object[] myArray = new'JButton[3] ; // slm

mas nio isro:

List<Object> lisL = new Arraylist<JButton>O; // NAOI

Po1 que as regras para definigio de tipos em arrays sio diferentes das regras para definigio de tipos nos gen6ricos?Falaremos sobre isso em um minuto. Por agora, apenas memorize que o polimorfismo nio funiiona da mesma formapara 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 implicag6esda questlo nio-h6-atribuigio-polim6rfica-para-tipos-gen6ricos que apresentamos acima. Mas como 6 que poderia estarse sentido ) vontade? Um dos grandes beneficios do polimorfismo 6 que voc6 pode declarar, digamos, um argumentode 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 umveterin6rio (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

System. out.println ( "Cat checkup" ) ;

]

]

c6digo especifico de Cat

class Bird extends Animal {

public void checkupO { // implementa c6digo especifico de BirdSystem. out . println ( "Bird checkup" ) ;

])Esquecendo os conjuntos,/arrays por um momento, apenas imagine o que a classe AnimalDoctor precisa para poderter um c6digo que tome qualquer tipo de Animal e chame o m6todo checkup ( ) de Animal. Tentar sobrecarregar aclasse AnimalDoctor com m6todos checkup ( ) para cada tipo poss(vel de animal seria absurdo, e obviamente nio-extensivel. VocA teria de modificar a classe AnimalDoctor a cada vez que algu6m adicionasse um novo subtipo deAnimal.

Assim, na classe AnimalDoctor, vocd provavelmente teria um m6todo polim6rfico:

public void checkAnimal (Animal a) t

Page 360: Java - Scjp 5 - Portugues

334 Copftulo 7: Gen6ricos e Coniunlos

a.checkup?; // n6o importa com qual subtipo de animal o

// m6todo checkupO sobrescrito de cada Animal execute

)

E, 6 claro, queremos que AnimalDoctor tamb6m tenha c6digo que possa tomar affays de Dogs, Cats ou Birds, para

quando o veterinirio vier a uma exposigio de cies, gatos ou pissaros, resPectivamente.

Novamente, nio queremos m6todos sobrecarregados com a$ays paracada subtipo potencial de Animal, entXo

usaremos polimorfismo na classe AnimalDoctor:

public voj-d checkAnimals (Animal[] animals) {

for(Animal a : animals) {

a ahan'Lrrn /*'-------*Y'l i

j

Eis o exemplo inteiro, com o teste do polimorfismo do array que usa qualquer tipo de array de animais (Dos [ ],car [ ], Bird[ ]).

import j ava. utj-1 . *;

abstract class Animal {

public abstract voj-d checkupO;

]

class Dog extends Animal {

public void checkupO { // implementa c6digo especifico de Dog

System. out . println ( "Dog checkup" ) ;

)

)

class Cat extends Animal {

public void checkupO { /,/ implementa c6digo especifico de Cat

System. out . println ( "Cat checkup" ) ;

)

]

class Bird extends Animal ipublic void checkupO { // implementa c6digo especifico de Bird

System. out.println ( "Bird checkup" ) ;

)

)

public class AnimalDoctor {

/ / o m6Lodo usa um array de qualquer subtipo de animalpublic 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 ( ) ;

Page 361: Java - Scjp 5 - Portugues

JAVA 5 335

)

Isso, 6 claro, funciona a contento (n6s sabemo-s, n6s sabemos, isso nio 6 nenhuma novidade). Mas eis o motivo por queresolvemos 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 conjuntode qualquer subtipo de Animal! Isso significa que Arraylist ( Dog ) nio pode ser passado para um m6todo com umargumenb de Araylist<Animal), mesmo que, como n6s sabemos, isso firncione bem com arrays simples.

Obviamente, essa diferenga entre arrays e Arraylist 6 condizente com as regras de atribuigio de polimorfismo que jivimos - 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 comtrpos especrtrcos.

N6s sabemos que nio vai funcionar corretamente, mas vamos tentar modificar o c6digo de AnimalDoctor para usarI,

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

doc.checkAnimals(dogs); // passa o Dog[ ]

doc.checkAnimals(cats) ; / / passa o Cat[]doc.checkAnimals(birdsl ; / / passa o Bird[]

/ / cri,a Arraylist.s em vez de arrays para Dog, Cat, BirdListcDog> 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 Arraylistsdoc.checlrrnLnals(dogs) i // anvLa un r,iat<Dog>

doc.checklninals(cats) i ll enwi.a un r,ist<Cat>

doc.checlrAninalg (birds) ; l l enwLa un t ist<Bird>

)

Entio, o que acontece?

j avac AnimalDoctorGeneric . j ava

AnimalDoctorGeneric. java : 51 : checkAnimals ( java. util.Arraylist<animal>) in animalDoctorceneric cannot be applied to( java. util . List<Dog>)

doc. checkAnimals (dogs) ;

Anj-malDoctorGeneric. java : 52 : checkAnimals ( java.util.

Page 362: Java - Scjp 5 - Portugues

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( j ava. uti1 . List<Bird>)

to

doc. checkAnimals (birds ) ;

3 errors

O compilador nos interrompe com erros, e nXo avisos. Voc€ simplesmente NAO PODE atribuir os ArraylistsindividuaisdossubtiposdeAnimal(<Dog>, (Cat) ou <Bird>)aumArraylistdosupenipo (Animal),que6o tipo declarado do argumento.

Essa 6 uma das quest6es mais complexas para programadores Java que esteo tio familiarizados com o uso depolimorfismo comarrays,ondeomesmo cenArio (enimalt J podesereferiraDog[ ],Cat[ ] ouBirdI f )funciona da maneira como voce esperaria. Assim, n6s temos duas quest6es na verdade:

1.. Por que isso nXo funciona?

2. Como faz6-lo funcionar?

Voc€ nos odiaria, e a todos os engenheiros da Sun, se lhe diss6ssemos que nlohicomo faz&lo funcionar - ou seja, quevoc6 teria de aceitar as coisas como slo e teria de escrever c6digos horrivelmente inflexiveis que tentam antecipar ecodificar 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 umArraylist ( 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 6perfeitamente 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 poderiarm zen r objetos de virios subtipos do supertipo, e enteo voc6 poder6 manipular o arcal asiumindo que tudo nelepode responder ) interface Animal (em outras palavras, tudo no array pode responder a chamadas a m6todos definidasna classe Animal). Assim, estamos usando o polimorfismo aqui nio para o objeto paru o qual a ref.er|ncia do arrayaPonta, mas sim para o q-ue o array pode de fato ARMAZENAR - neste caso, qualquer subtipo de Animal. VocO podeIazer o mesmo com gen€ncos:

List<Animal> animals = new Arraylist<Animal> ( ) ;

animals.add(new CatO ) ; / / OK

animals.add(new DoSO ) i / / OK

Assim, esta parte funciona tanto com arrays quanto com conjuntos gen6ricos - podemos adicionar uma instlncia deum subtipo em um $ray o! conjunto declarado com um supertipo. Vocd pode idicionar Dogs e Cats avmarrayAnimal (animal [ 1) ou a um conjunto Animal (Arraylist ( Animal >).

E, com arrays, isso se aplica ao que acontece dentro de um m6todo:

public void addAnimal(Animal[] animals) {

animals [0] = new Dog ( ) ; / / sem problema, qualquer Animal funciona

,/ / em animal [ ]

)

Entio, se isso for verdadeiro, e voc6 puder colocar Dogs em um Arraylist ( Animal > , enteo por que voc6 nio podeusar o mesmo tipo de cenirio de m6todos? Por que nlo 6 possivel fazer isto?

public void addAnimal (Arraylist<Animal> animals) {

animal-s.add(new DoSO ) ; / / permitido em alguns casos...)

Page 363: Java - Scjp 5 - Portugues

JAVA 5 337

Na verdade, voc6 PODE fazer isso sob ceftas condig6es. O c6digo acima IRA compilar com sucesso SE o que voc6passar ao m6todo for tamb6m um Arraylist < Animal > . Essa 6 a parte onde isso difere dos arrays porque, na versXodos 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 umArraylist < Animal ) ! (Assumindo que voc6 nio esteja tentando passar um subtipo de Arraylist, uma vez que,lembre-se, o tipo "base" pode ser polim6rfico.)

A pergunta permanece - por que isso 6 inv6lido? E por que 6 inv6lido para Arraylist, mas nio para arrays? Por quenlo6possivelpassarumArraylist(Dog) aumargumentodeArraylist<Animal)?Naverdade,oproblemaEigualmente perigoso esteja voc6 usando arrays ou um conjunto gen6rico. Ocorre apenas que o compilador e aJVM se

comportam de formas diferentes p^ra ^rr^ys

e para conjuntos gen6ricos.

A razio pela qual 6 perigoso passar um conjunto (array ou Arraylist) de um subtipo para um m6todo que use umconjunto de um supertipo 6 que voc6 poderia adicionar alguma coisa. E isso significa que voc6 poderia adicionar acoisa ERRADA! Isso provavelmente 6 muito 6bvio, mas, pelo sim pelo nio (e para reforgar o conceito), vamosanalisar alguns cen6rios. O primeiro 6 simples:

^,,Lr j^ -,^ji €^^/)

{PuvffL vvfu lvv\

Doq[] dogs = {new DoSO, new DogO};:rlAlnim:l/d^dc\. // <an nrnhla-^ ^-_-l^ ^ n^-r I nara

^m6i-6dd\svvv, , , , ----ltta, crrvf4 u uv:| t I yqrq

]

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 foipermitido 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 Dogpode 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 umarraydo tipo caat l, e nioanimal [ ], e voc6 est6prestes itenta. adicionarum Doga ele. Para o compilador, voc6p,rssou vm

^rray do tipo Animal, enteo ele nio tem como perceber o problema.

ESSE 6 o cen6rio que estamos tentando impedir, independentemente de se 6 um array ou um Arraylist. A diferenga 6que o compilador permite que isso funcione com arrays, mas nio com coniuntos gen6ricos.

A razlo pela qual o compilador nio lhe permitir6 passar um Arraylist ( Dog ) para um m6todo que use umArrayliJtcAnimal> 6 que, dentro do m6todo, o parAmetro 6 do tipo Arraylist(Animal>, e isso significa que voc6poderia colocar qualqueriipo de Animal dentro dele. Nio haveria como o compilador the impedir de colocar um-Dog

em um List que fo.a originalrnente declarado como ( Cat ), mas que esti agora sendo referenciado a partir doparAmetro <Animal).Ainda temos duas perguntas... como se contorna essa problema e por que, afilal, o compilador permite que voc6assuma 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 Dogpara 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 6tm array Dog, receber6 a excegio.

Mas NAO hi uma excegio equivalente para gen6ricos, por-causa do apagamento dos tipos! Em outras palavras, emtempo de execugXo aJVM SABE o tipo dos

^rr^ys, mas NAO sabe o tipo de um conjunto. Todas as informag6es de

tipoi gen6ricos sio removidas dtrante i compilaSo, de forma que, no momento em que ela chega )JVM, simplesmente nlo

Page 364: Java - Scjp 5 - Portugues

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 exatamentecomo os problemas que voc6 tem quando usa c6digo antigo, sem tipo especifico).

Assim, este, na verdade, 6 um c6digo VAtnO:public void addAnimal (List<Animal> animals )

animals. add (new Dog ( ) ) ;

= new AnimalDoctorGeneric ( ) ;

/ / 6 AQUI que surge o problema!

{

isto 6 sempre v61ido,

uma vez que Dog pode

ser atribuido a uma refer6nciade 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), ocompilador ficaleliz - sabendo que qualquer subtipo de Animal que voc6 adicionar seri vilido (voc6 sempre podeadicionar um Dog a um conjunto Animal, etc e tal). Mas se voc6 tentar chamar addAnimal ( ) com um argumento dequalquer OUTRO tipo Arraylist, o compilador o impedir6, uma vez que, em tempo de execugio, aJVM nio terianenhuma forma de impedir que voc6 adicionasse um Dog ao que foi criado com um conjunto Cat.

Por exemplo, este c6digo que modifica o tipo gen6rico para ( Dog ), mas sem modificar o m6todo addAnimal ( ) ,NAO ir6 compilar:

public void addanimal (ListcAnimal> animal-s) {

animals.add(new DoSO ) ; / / ainda oK como sempre

)

public static void main(Strinq[] args) {

List<Dog> animal-s = new Arraylist<Dog> ( ) ;

anj-mals.add(new Dog ( ) ) ;

animals.add(new DoS( ) ) ;

AnimalDoctorGeneric doc

doc. addAnimal (animals ) ;

)

O compilador diz algo como:

j avac AnimalDoctorGeneric . j ava

AnimalDoctorGeneric . j ava : 4 9 : addAnimal- ( j ava . ut i 1 . Li s t<Animal> )

in AnimalDoctorceneric cannot be applied to (java.util.List<Dog> )

doc . addlnimal ( animals ) ;

1 errorRepare que essa mensagem 6 praticamente a mesma que vocd receberia ao tentar chamar qualquer m6todo com oargumento errado. Esti dizendo que voc6 simplesmente nio pode chamar addAnimat (List<Animal>) usandoalgo cuja referAncia tenha sido declarada como List (Dog>. (E o tipo da refer6ncia, e nio o pr6prio tipo do objetoque importa, mas lembre-se: o tipo gen6rico de um objeto 6 SEMPRE o mesmo que o tipo gen6rico declarado narefer6ncia. List(Dog) po& se referir A?ENAS a conjuntos que sejam subtipos de List, mas que tenham sidoinstanciados 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.)

Page 365: Java - Scjp 5 - Portugues

JAVA 5 339

De volta I questio principal - como contornamos isso? Se o problema esti relacionado apenas ao perigo de seadicionar a coisa errada ao conjunto, e quanto ao m6todo checkup ( ) que usou o conjunto passado como desomente-leitura? Em outras palavras, e quanto aos m6todos que chamam m6todos de Animal para cada coisa doconiunto, o que iri funcionar independentemente de qual esp6cie de subtipo de Arraylist 6 passada?

Eisso6umadica! Om6todo add O 6que6oproblema,entio oqueprecisamos6deumaformade dizeraocompilador'ei, estou usando o conjunto-passad6 apenas parachamir m6todos para os elementos - e prometo NAOadicionar nada ao conjunto". E de fato EXISTE um mecanismo paradizer ao compilador que voc6 pode usar qualquersubtipo gen6rico do tipo do argumento declarado, porque nlo iricolocar nada no conjunto. E esse mecanismo 6 ocoringa < ?>.

A assinatura do m6todo se modificaria de

public void addAnimal (ListcAnimal> animals)

Para

public void addAnimal(List<? extends Animal> animals)

Ao usar < ? extends Animal>, estamos dizendo: "Eu posso receber um conjunto que seja um subtipo de List e

com o tipo definido de < Animal ) ou qualquer coisa que estenda Animal. Ah sim, e PROMETO que nio vouADICIONAR nadaao coniunto". @xistem mais alguns detdhes, mas chegaremos li.)

Assim, 6 claro que o m6todo addAnimal ( ) acima nXo vai compilar nem mesmo com a notagio do coringa, porqueesse m6todo ADICIONA algo.

public void addAnimal (List<? extends Animal> animals) {

animal-s.add(new DosO) ; // NAol Nao se pode adicionar se

sarmos <? extends Animal>

)

VocA receberi um erro bastante estranho que poderi se parecer com isto:

j avac Ani-malDoctorGeneric . j ava

AnimalDoctorGeneric. java: 38 : cannot f ind symbol

symbol : method add(DoS)

location: interface java.util.List<capture of ? extends Animal>

animals. add (new Dog ( ) ) ;

l- errorque basicamente diz: "voc6 nio pode adicionar um Dog aqui". Se modificarmos o m6todo de forrna que ele nioadicione nada, passarl a funcionar.

Mas eqpere - ainda tem mais. @ a prop6sito, tudo o que abordamos nesta sedo sobre ggn6ricos provavelmente ser6 te*adono exame, com ex@o do "apagamento de tipos", sobre o qual nlo 6 necessdrio que vod saiba quaisquer detalhes)

Primeiramente, <? extends Animal> significa que vocd pode usar qualquer subtipo de Animal; entretanto, esse

subtipo pode ser OU uma subclasse de uma classe (abstrata ou concreta) OU um tipo que implemente a interface que

vem depois da peJavra extends. Em outras palavras, a palavra-chave extends no contexto de um coringarepresenta tanto as subclasses quanto as implementag6es de interfaces. Nio h6 uma sintaxe <? implementsSerializabLe>. Se voc6 quiser declarar um m6todo que use qualquer coisa que seja de um tipo que implementeSerializable, voc6 ainda usaria extends desta forma:

void foo(List<? extends Serializable> list) // forma esquisita, mas correta// de usar "extends"

Parece estranho porque vocA nunca usaria isso em uma declaraglo de classe, porque Serializable 6 uma interface, niouma classe. Mas a sintaxe 6 essa, entio memorize-a!

Mais uma vez - s6 existe llMA palavra-chave coringa que representa tanto implementag6es de interfaces qlrantosubclasses. E essa palavra-chave 6 extends. Por6m, quando a vir, pense em "E-LIM", no sentido de dgo que passa noteste de instanceof .

Entretanto, hi outro cenirio ern que voc6 pode usar um coringa E aindaadicionar ao conjunto, mas de uma formasegura - a palavra-chave super.

Imagine, por exemplo, que voc6 tenha declarado o m6todo desta forma:

public void addAnimal(List<? super Dog> animals) {

animals.add(new DoSO) ; ll em alguns casos 6 correto adicionar com super

]

Page 366: Java - Scjp 5 - Portugues

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 umsupenipo 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 perfeitamentevilido adicionar um Dog a ela. Se voc6 passar uma lista do tipo Dog, 6 perfeitamente v6lido adicionar um Dog a ela.Ese 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 umdos seus supertipos, umayez que - e esta 6 parte principal do que faz isso funcionar - um conjunto declarado comoqualquer 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 ir6funcionar. Assim, a palavra<have super na notaglo do coringa perrnite que vocA tenha umi forma restrita, masainda possivel, de adicionar a um conjunro.

Assim, o coringa lhe fornece atribuig6es polim6rficas, mas com certas restrig6es que voc0 nio tem no caso dos arrays.Pergunta r.lpida: estes dois sio iddnticos?

public void foo(List<?> list) { }

public void foo(List<Object> list) { }

Se EXISTE uma diferenga (e aindanio estamos dizendo que existe), qual 6?

Sim,EXISTEumagrandediferenga.List<?>,que6ocoringa<?>semaspalavras-chaveextends ousuper,significa simplesmente "qualquer tipo". Assim, isso significa que qualquer tipo de List pode ser atribuido aoargtrmento. Poderia ser um List de ( Dog ) , ( Integer ) , (JButton ) , ( Socket ) , qualquer coisa. E usar o coringasozinho, sem a palavra-chave super (r.g*d" de um tipo), significa que voc6 nio pode ADICIONAR nada i listareferida como List < ? >.List<object.> 6 completamente diferente de List<?>. List<object> significa que o mdrodo SOMENTEpode usarum List<obj ect>. Nio um List.<Dog>, nem um List<Cat>. Significa, no entanto, que voc6 podeadicionar. i lista, uma vez que o compilador ji se certificou que voc6 est6 passando apenas um List < Object > v6lidopara o m6todo.

Com base nas explicag6es anteriores, descubra se o seguinte ir6 funcionar:

imnnrf iarr: r'ri1 *.

public class testWildcards {

public static void main(String[] argrs) {

List<Integer> mylist = new Arraylist<Integer> ( ) ;

Bar bar = new BarO;

bar . dofnsert (myl,ist ) ;

l

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 queumalistadeQUALQUER tipo seja passada ao m6todo, mas o m6todo add ( ) nlo 6 v6lido, pelas raz5es que exploramosanteriormente (que voc6 podia colocar o tipo errado de coisas no conjunto). Assim, desta vez, a classe Test\Tildcards

Page 367: Java - Scjp 5 - Portugues

JAVA 5 34]

nio. causa problemas, mas a classe Bar nio compilar6, porque elarealizaum add ( ) em um m6todo que usar umcoringa (sem super). E se modificarmos o m6todo dotnsert ( ) para isto:

public class TestWildcards {

public static void main(String[] args) {

List<Integer> mylist = new Arraylist<fnteger> ( ) ;

Bar bar = new Bar ( ) ;

bar. dof nsert f mwT,i st- ! :

]

)

cfass Bar {

void dolnsert (List<Object> list) {

list.add(new DogO );]

]

E agora,vai funcionar? Se nlo, por quA?

Destavez,aclasseBar,comom6tododornsertO,compilasemsobressaltos.Oproblema6queoc6digoTest\il/ildcards est6 tentando passar um List ( Integer ) para um m6todo capaz de usar APENAS um List ( Object > .

E narla mus pode substituir < Obiect > .

A prop6sito, List< ? extends ob j ect.> e List< ?> slo absolutamente id6nticas! Ambas as instrug6es dizem:"Eu posso me referir a qualquer tipo de objeto". Mas, como voc6 pode ver, nenhuma delas 6 o mesmo queList < 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 usadoo ( tipo ) especificado, e absolutamente NADA ALEM DELE. List ( Dog ) significa List ( Dog ) , e nioList ( Beagle ), List ( Poodle ) nem qualquer outro.subtipo de Dog. Mas List < ? extends Dog ) poderia significarList(Beagle), List(Poodle) e assim pordiante. E claro que List<?> poderia ser... Qualquer coisa.

Tenha em mente que os coringas s6 podem ser usados para declarag6es de referAncias (incluindo argumentos,variiveis, tipos de ietornos e assim por diante). Nio podem ser usados como o parAmetro de tipo quando voc6 cria umnovo conjunto com tipo especifico. Pense nisso: enquanto uma refer6ncia pode ser abstrata e polim6rfica, o pr6prioobjeto criado deve ser de um tipo especifico. VocA precisa definir o tipo quando cria o objeto usando new.

Como uma pequena revisio antes de seguirmos adiante com os gen6ricos, observe as seguintes instrug6es e descubraquais irio compilar:

1) List<?> list = new Arraylist<Dog>O;2) List<? extends Animal> alist = new Arraylist<Dog>O;3) List<?> foo = new Arraylist<? extends Animal>O;

4) List<? extends Dog> clist5) List<? super Dog> blist =

= new Arraylist<Tnteger> ( ) ;

new Arraylist<Animal> ( ),'

6) List<? super Animaf> dlist = new Arraylist<Dog>O;

As respostas corretas (as instrug6es que compilario) sio t,2 e 5.

As tr6s que nio irio compilar sio

llnstrugiot:List<?> foo = new Arraylist<? extends Animal>O;

Problema: nio 6 possivel usar a notagAo com coringa na cnagio do objeto. Assim, new Arraylist<? extendsAnimal> O nio compilari.

I Instrugio: List<? extends Dogr> cl,ist = new Arraylist<lnteger> ( ) ;

Problema: Nio 6 possivel atribuir uma lista de Integers a uma refer6ncia que aceita apenas um Dog (incluindoquaisquer subtipos de Dog, 6 claro).

l lnstruglo: List<? super Animal> dT,ist = new ArraylistcDog> O;

Problema: Nlo 6 possivel atribuir um Dog a <? super Animal>. O Dog est6'baixo" demais na hierarquia daclasse. Somente ( Animal ) ou ( Obiect ) teriam sido vilidos.

Page 368: Java - Scjp 5 - Portugues

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 aespecificagio de tipos gen6ricos funcionJcom outias classes da API? E, finalmente, 6 possivel declararmos as nossas

proprias il.sses co*o iipos gen6ricos? Em outras palavras, podemos criar uma classe (ue requeira que algu6m passe

um tipo quando adeclararem e instanciarem?

Primeiro, a resposta que vocA obviamente ji conhece: a API lhe diri quando um tipo parametrizado for esperado. Porexemplo, esta 6. a declaragio API para a interface java.util.List:

public interface List<E>

O <E> 6 um marcador parao tipo quevoc6 passar6. A interface List estise comportando como um "modelo" (maisou menos como os modelos do C+ +) e, ao escrever seu c6digo, voc6 o modifica de um List gen|rico puaumList < Dog ) ou List ( Integer ) , e assim por diante.

O E, a prop6sito, 6 apenas uma convengio. Qualquer identificadorJava vilido funcionaria aqui, mas E significa"Elemento",e6usadoquandoomodelo6umconjunto.Aoutraconvengioprincipal 6T(significa"tipo"),usadopara, bem, para as coisas que NAO forem conjuntos.

Agora que voc6 ji viu a declaragio dainterface para List, como imagina que seja o m6todo add ( ) ?

boolean add(E o)

Em outras palavras, o que quer que E seja quando voc6 declarar aList, i itso o que wc|podni adicionar a ela. Assim, imagineeste c6digo:

List<Animal> list = new ArraylistcAnimal> ( ) ;

OEnaAPldeListderepentedeixadeserumabstrato (seutipoaqui> epassaaserumListdeAnimals.EsedumList de Animals, enteo o m6todo add ( ) de List obviamente deve se comportar desta forma:

boolean add(Animal a)

Quando consultar uma classe ou interface gentrica na API, escolha um parAmetro de tipo (Dog, JButton ou mesmoObject) e faga uma operaglo de busca e substituigXo mental para cada instAncia de E (ou qudquer identificador queesteja sendo usado como marcador para o parAmetro do tipo).

Criando a sua Pr6pria Classe Gen6ricaVamos tentar criar a nossa pr6pria classe gen6rica, para termos uma ideia de como isso funciona, e depois veremosalguns detalhes remanesceftes sobre a sint"axe dos-gen6ricos. Imagine que algu6m tenha criado.r-".f".r. Rental('aluguel'), que gerencia um pool de itens que podem ser alugados.

public class Rental {

nri rral- a T. i qi- rant-a l Dnn l .

private int maxNum,.

public Rental(int ma><IrTum, List rentalPool) {

this.maxNum = maxNumi

this. rentalPool = rentalPool ;

)

nrrhlin Ol-!iadt- aal-Ponl-al /\ IvvJ ev u yeur\srf uq! \ / t

// bloqueia at6 que haja algo disponivelreturn 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. VocAPOOena comegar com algo deste ttpo:

import java.util.*;public class CarRental extends Rental {

Page 369: Java - Scjp 5 - Portugues

JAVA 5 343public 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 /a\ .qf \el ,

)

public void returnRental (Object o) {

if (o instanceof Car) {

qrlner ral-rrrnPant-:1 lnI .

] alca I

System. out.println ( ..Cannot add a non-Car,, ) ;

/ / provavelmente langa uma exceqao

)))Mas quanto mais vocA olha, mais vocA percebe que:

1. Voc6 ex6fazendo a sua pr6pria verificagio de tipo no m6todo returnRental ( ) . Nio 6 possivel modificar o tipodo arg-umento de returnRental ( ) para usar um Car, uma vez que se trara de uma sobrescrigio (e nio uma

-

sobrecarga) do m6todo & classe Rental. (Sobrecarregar acabaria com a sua flexibilidade polim6rfica com Rental).

2. VocA realmente nio quer criar zubclasses separadas para cada tipo possivel de coisas que podem ser alugadas(carros, computadores, sapatos de boliche,iriangas, e assim por diante).

Mas com a sua intelig6ncia natural (aumentada por este cenirio complicado), vocA rapidamente percebe que podecriar a classe Rental como um tipo gen6rico - um modelo para qudquer tipo de coisJque pode Jer aluga& -i irtoresolve o seu problema.

(N6s dissemos complicado... Uma vez que, na realidade, voc6 poderia muito bem querer ter diferentescomPortamentos para diferentes tipos de coisas que podem ser alugadas, mas at6 mesmo isso poderia ser resolvido deforma mais limpa atrav6sde algum tipo d.e composigio de componamento, em vez de com a [eranga (usando-se opadrio de projetos Estrat6gia, por exemplo). E nio, os padr6es de projetos nio caem no exame, mas ainda assimachamos que vocA deveria ler o nosso livro sobre padr6es de projetos). Assim, aqui est6 a sua nova e aprimorada classegen6rica Rental:

import java.util.*;public class RentalGeneric<T> {

private List<T> rentalPool- t

private int maxNum;

public RentalGeneric (

int maxl\trum, l,ist<T> rentalPool) {

this.maxNum = maxNum;

this. rentalPool = rentalPool ;

)

public T getRental0 {

// bloqueia aL6 que haja algo disponivelreturn rentalPool. get (0) ;

void returnRental (T returnedThing) {

rentalPool . add ( returnedfhing) ;

/ / "'t" significa o parAmetro

/ / do tipo/ / Use o tipo da classe como

/ / o tipo de List

// o construtor usa um

/ / List do tipo da classe

// estamos alugando urn T

// e o locador

// retorna um T

)

public

Page 370: Java - Scjp 5 - Portugues

344 Copitulo 7: Gen6ricos e Conluntos

]

]

Vamos testar esse c6digo:

class TestRental {public static void main (String[] args) t

/ /cria alguns Cars para o Pool

Car c1 = new CarO;Car c2 = new CarO;List<Car> carlist = new Arraylist<Car> ( ) ;

carlist . add ( c1 ) ;

carlist . add ( c2 ) ;

Rentalceneric<Car> carRental = new

Rentalceneric<Car> (2, carlist) ;

/ / reLira agora um car, e ndo serd necess6rio converter

Car carToRent = carRental.getRentalO ;

carRental . returnRental ( carToRent ) ,'

/ / ser6. que podemos colocar alguma outra coisa na carlist original?carlist. add (new Cat ( "Fluffy" ) ) ;

l

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 errorAgora temos uma classe Rental que pode ter o tipo definido para qualquer coisa que o programador escolha, e ocompilador 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 outraclasse simples que usa o tipo parametr:uado da classe de diversas maneiras:

public class Testcenerics<T> {

rF anTncf an-o -

rF f I :nArr:rrAfTs-r tJ srl.drrqaeLL-t

TestGenerics (T anlnstance) {

this. anlnstance = anlnstancei

// aama o tino da elasse

/ / como um tipo de vari6vel de instAncia

/ / como um tipo de array

/ / rama lln f in^ do :rrrrmanl-nue qrY4rrelrev

)

T nat_rFl\ I / J aama rrh l- ind .la rol-drnoYeLr \, e4tsv ev

return anfnstance;

J

Obviamente, esse 6 um uso absurdo dos gen6ricos e, na verdade,voce precisa entender os di{erentes tipos de sintaxe gen6rica queesses exemplos at6 que os tenhamos abordado todos.

voce raramente veri gen6ricos fora de conjuntos. Maspoderi encontrar, de modo que continuaremos com

Page 371: Java - Scjp 5 - Portugues

Voc6 pode usar mais de um tipo parametrizado em

^,'Lll^ ^r^^^ rr^^1;uurre urdb> u>eTwO<T, X> {

)

!_voc6 podg ular uma forma de notagio com coringa em uma definigio de classe, para(chamado de "limites") para o ripo que poderi ser usado para o parimetro do tipo:

public class AnimalHolder<T extends Animal> {

T animal;

public st.atic void main(SLring[] args) {

AnimalHolder<Dog> dogHolder = new Animal-Holder<Dog> ( ) ;

AnimalHofder<Integer> x = new AnimalHolder<Tnteger> ( ) .

)

)

imnnrl- i:rz: rrli l *-*"*.*-**. ;

public class CreateAnArraylist {

public <T> void makeArraylist(T t) t

]

T

uma 6nica definigio de classe:

T one;

X two;

UseTwo(T one, X two) {

thiq nna = ^na.rLl ^ r-,^LITI-.LWU - LWU;

getT0 { return one; }

getxo { return two; }

/ / faz um teste, criando com <String, Integer>

public static void main (String[] arg.s) {

UseT\do<String, Tnteger> twos =

new UseTwo<String, Integer> ( "foo" , 42) ;

Strino theT = ft^roq acf.F/I. / / ralnrna rrma efrih-

int thex = twos.getx(l; // reLorna Integrer, faz unboxing para um intt1

especificar um intervalo

JAVA 5 345

/ / use "T" em vez

/ / .16 \\?"

Criando M6todos Gen6ricosAt6 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 possiveldefinir 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 eadrcione a rn$ancia ao Arraylist. A classe em si nXo precisa ser gen6rica; basicamente, n6s queremos apenas umm6todo u!4it6rio ao qual possamos passar um tipo e que seja capaz de usar esse tipo para construir um 6onjunto comtipo especifico. Usando um m6todo-gen6rico, pod.-os declarai o m6todo ,.- r"r- tipo especifico e depoiJobter ainformagio do tipo com base no tipo do objeto passado ao m6todo. Por exemplo: -

// oK

// NAol

/ / Loma um objeto de umn

I / |-ipo desconhecido e usa um

nFrA ranfaqanl-ar n finnr v Lrvv

/ / agora podemos criar o

/ / l.ist usando "T"

-trl-st<'I'> -L f sE.

list.add(t);

= new Arrayl,ist<T> ( ) ;

Page 372: Java - Scjp 5 - Portugues

346 Copitulo 7: Gen6ricos e Coniuntos

]

No c6digo.acima, se voc6 chamasse o m6todo makeArraylist ( ) com uma instAncia de Dp& o /n6todo se

componaria como se tivesse tido esta aparAncia o tempo todo:

public void makeArraylist(Dog t) {

List<Dog> list = new Arraylist<Dog> ( ) ;

list.add(t);)

E, 6 claro, se voce chamar o m6todo com um lnteger, o T ser6 substiruido por Integer (nio no bltecode, lembre-se -estamos descrevendo como ele aparenta se compott"r, e nlo como de fato acontece).

A coisa mais estranha a respeiro dos m6todos gen6ricos 6 que voc6 precisa declarar a vari6vel do tipo ANTES do tipode retorno do m6todo:

public <T> void makeArraylist (T t)O < T > antes de void simplesmente define o que T 6 antes que voc6 o,use como um tiPo no argumento. VocA DEVE

declarar o tipo dessa forro", a nio ser que ele seja especificado para a classe. Em CreateAnArraylist, a classe nio 6

gentrica,portanto, nio h6 nenhum marcador de parAmetro de tipo que Possamos usar.

VocA tem a opgio tamb6m de colocar limites sobre o lipo qu9 declarar;por exemplo, se q-uiser restringlr o m6todo

makeArrayllst ( ) a apenas Number ou os selrs subiipos (Integer, Float e assim por diante), vocd usaria

public <T extends Number> void makeArraylist(T t)

oBSERVAQ6E,S pene o EXAME

E tentador uquuer qse o argumentt do nhodo NAO eshi onde aocd declaroa a uariduel de pardwetro de tipo T. Para usar ama aaiduel de

tipo como T, iw6 priciw t6-/a dutarado 0a c0m0 o k'po de pardnetro da classe oa no mitodo, antes do tipr de retuml. A linha abaixo podetl

Parecer coteta,

public void makelist(r t) { }

Mar a ilnicafonaa de ela ser uilida seia se defato hosuerse lma classe chamadaT, em c{o caso o argumentofunciona como qualqtter oatra

du/amg6o de h'po para ama aaritiael. E qzanto aot argumeltos dl constnttores? Tanbdn eles podem ser dlclarados com am tipo genirico, mas

aifca ainda mais utranbo, uma ue<qile os construtores ndo t4n nenhum tipo de retotwo:

public class Radio {

public <T> Radio(T t) { } // construtor v61ido

]

Se uocd KEALMENTE qaerfaryr algo absrdo (ou nr despedido), pode declarar uma clasv com um ttlme que s/a o meimo do marcador do

pardmetro do tipo:

class x { public <X> X(X x) t } }

Sim, irofunciona. O X qae i o nome do constnttor ndo tem nlagdo nenhama con a dularag1o de tipo <X>, qile' pzr sila ue7, ndo tem

re/ag6o nenhuma com o identifcador do argumento do consh'ntoy que tambim 6, claru, X, O conpi/ador convguefaryrpasing disso e hata

cada um dot asos de X defonza independente. Asin, ndo ocom nenbum conf/ito entre 0t fllmes das clares, dos narcadores dotpardmetms

de n'pos e dos identifcadores de uari,lueit

tJm dos enganos mais cumafis qte ospmgramadores conetem ao criarvm classes ou mitodos geniricos i asar am 4?t na intaxe do coringa

em aeqde uma uariduel de h'po <T>, 1E), e assin por diante. Este cddigo pode parecer con'eto, mat ndo i:

public class NumberHolder<? extends Number> { }

Enbora o ponto d.e innrrogagdo funcione ao se declarar ama referincia para uma uaitluel, ete NAO funciona para dularapdes de c/ases e

mitodos geniicos. Este aidigo ndo i u,llido:

public class NunberHolder<?> { z atlum; } // NAOI

Mas se uocl sub$ituir o <?> por am identifcador a,ilido, tudo bem:

public class NumberHolder<T> { T aNum; } // Sim

98o/o detudo o que voc6 provavelmente fari com os gen6ricos 6 simplesmente declarar e usar coniuntos com tiPoespecificado, inituindo usilos (e pass6-los) como argumentos. Mas agora voc6 sabe muito mais (por6m, de formaalguma tudo) sobre a maneira como os gen6ricos funcionam.

Page 373: Java - Scjp 5 - Portugues

JAVA 5 347

Se esse assunto ficou claro e filctl paravocA, excelente. Se foi... Complicado, saiba que a adigio dos gen6ricos iFg""F:* J"yt chegou perto de cansat .tm" revolta entre alguns doi desenvolvedoies Java mais exp"erientes. A maioriados criticos simplesmente estava descontente com a complexidade, ou nio estava convencida de que o beneficio de seter coniuntos com tipos especificados. :*l "

pena pelos milhares de regrinhas que voc6 tem de decorar agora. E

".tF* que, go.mlava 5, ficou mais dificil p5nder a linguagem. Mas icredite em n6s... Nunca vimos niigudm levarmais do que dois dias para entender os gen6ricos. Isso sio s6 48 horas consecutivas.

Exercicios ripidos

Resumo para a certificagioN6s comegamos com uma breve revisio do m6todo toString ( ) . O m6todo toString0 ser6 chamadoautomaticamente quando voc6 solicitar a system. out . println ( ) que exiba um objeto - voc6 o sobrescreveparafaz{lo retornar uma String de dados significativos a respeito dos seus^objetos.

4 :.gYit, ryvislmop a finalidade do operador_ = :_(saber se duas vari6veis de referAncia apontam para o mesmogbjtt.) e do m6todo equals ( ) (siber se dois objetos sio tignrfcatiuanmte eqriaahtet). VocA conheceu a dewantagemde nio sobrescrever equals ( ) - pode n5o ser possivel enconirar o objetoem um conjunto. Discutimos.r* poi.t ocomo escrever um m6todo equals ( ) adequado - nio esquega de usar instanceof e referenciar os atrib-utossignificativos do objeto. Revisamos os conrratos de sobrescr(io de eguals ( ) e hashCode ( ) . Conhecemos ateoria 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 omesmo valor.

A seguir passamos para os conjuntos, momento em que conhecemos os conjuntos Iist, Set e Map, e vimos a diferengaentre conjuntos ordenados e classificados. Aprendemos os atributos principais das classes comuns de conjuntos, e-quando us6-los.

Abordamos os detalhes sobre as classes Collections e Arrays: como classificar e como procurar nelas. Aprendemossobre 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 deuma colegio, ele ser6.do tipo que voc6 espera, sem que seja necessirianenhuml conversio. VocA pode misturarc6digo antigo com c6digo que usa gen6ricos, mas isso pode causar exceg6es. As regras para o polimorfismo mudamg.ulndo voc6_ usa os gen6ricos, apesar de que, usando coringas, voc6 ainda pode criar conjuntos polim6rficos. Algumasdeclarag6es de gen6ricos permitem a leitura a panir de umionjunto, mas nio permitem a attahzagio do conjunio.

Enfim, foi um capitulo muito interessante.

Aqui estio alguns dos pontos principais do Capitulo 7.

Sobrescrevendo hashCode( ) e equals( ) (Objetivo 6.2)O equals( ),hashCode( ) e tostring( ) siopriblicos(finalize( ) 6protegido).

E Sobrescreva toString ( ) para que System. out . println ( ) ou ouuos m6todos possam obter algo 6til, comoo estado de szu objeto.

E Use : : para determinar se duas vari6veis de refer6ncia apontam para o mesmo objeto.

O Use equals ( ) 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 classeapropriada.

D Quando sobrescrever equals ( ) , compare os atributos significativos dos objetos.

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

Page 374: Java - Scjp 5 - Portugues

348 Copitulo 7: Gen6ricos e Coniuntos

D Quando ser5, nub: se x nio for nu11, x. equals (nu1l) ser6 falso.

D Sex.equals(y) forverdadeiro,x.hashCode( ) = = y.hashCode( ) deveser true

E Se voc6 sobrescrever equals ( ) , sobrescreva hashCode ( ) '

E As classes HashMap, HashSet, Hashtable, LinkedHashMap e LinkedFlashSet usam hashing.

E Uma sobrescriglo vilida de hashCode ( ) ter6 que se ater ao contrato.

E Uma sobrescriglo eficiente de hashCode ( ) distribuir6 chaves de forma igualit6ria em v6rios dep6sitos.

D Para reiterar: se dois objetos forem iguais, seus c6digos de hashing tamb6m devem ser.

B E vilido que um m6todo hashCode ( ) retorne o mesmo valor para todas as instAncias (embora na priticaseia muito ineficiente).

E Aspectos do contrato de hashCodeQ que foram realgados:

D E consistente: virias chamadas a x. hashCode (y) retornarAo o mesmo inteiro'

E Se x. equals (y) for true, x.hashCode ( ) == y.hashCod.e ( ) deve ser trueO Se x. equals (y) for f a1se, x.hashCode ( ) -= y.hashCode ( ) podedser true ou false, mas

false indtcar| uma tend6ncia a gerar mais eficiAncia.

D As vari6veis transiente nio sio apropriadas para equals ( ) e hashCode ( ) .

Conjuntos (Objetivo 6.1)E As atividades comuns dos conjuntos incluem a insergio e a remoElo de objetos, a verificagio de objetos incluidos, a

recuperagXo dos mesmos e a iteragio.

D TrAs significados para "conjunto":

E conjunto - representa a estrutura de dados na qual objetos sio armazenados;

D Collection - java.util.Collection - Interface estendida por Set e List;

E Collections - uma classe que ^rmazen

m6todos utilit6rios esteticos de conjuntos.

E As quatro uersdesbasicx dos conjuntos sio as L)stas, Conluntos, MEar e Filas:

E Listas de itens: Ordenada, repetigio perruitida, comum indice,

E Conjuntos de itens: Podem ou nio ser ordenados e/ou classificados e a @etigdo ndo dpermitid4

E Mapas de itens com chaves: Podem ou nlo ser ordenados e/ou classificados e a rqeilgdo de chaau ndo i pemitida.

tr Filas de itens a serem processados: Ordenados por FIFO ou Por prioridade.

E As quatro subvers6es bisicas dos conjuntos sio: classficada, ndo- clarifcada, ordenada e ndo-ordenada.

D Ordenado significa a iteragio em um conjunto, obedecendo a uma ordem especifica nio-aleat6ria.

D Classificado significa aiteragio em um conjunto, obedecendo uma ordem classficada estabelecida.

E A classificagio pode ser alfab6tica, num6rica ou definida pelo programador.

Atributos principais das classes comuns de coniuntos (Obietivo 6.1)[J Arraylist: iteragio e acesso aleat6rio r6pidos;

fl Vector: Como um Arraylist um pouco mais lento, principalmente devido a seus m6todos sincronizados;

O Linkedlist Adequado para ainsergilo de elementos ao final, ou seja, para pilhas e filas;

E HashSet: Assegura a nio existAncia de duplicatas, nio fornece ordenamento;

tr LinkedFlashSet: Sem duplicatas; iterapor ordem de insergio;

D TreeSet: Sem duplicatas; itera na ordem classificada;

E HashMap: atualizag6es mais ripidas (pares-chave/valor); permite uma chave nul1 e muitos valores nu1l;

E Hashtable: Como um HashMap mais lento (semelhante a Vector, devido a seus m6todos sincronizados). Nenhumvalor ou chave nu11 6 permitido;

E LinkedHashMap: iterag6es mais r6pidas; itera por ordem de insergio ou de rtltimo item acessado, permite umachave nu1I e muitos valores nul1;

E TreeMap: Um mapa classificado.

tr PriorityQueue: IJma lista de coisas a f.azer ordenada pela prioridade dos elementos.

Page 375: Java - Scjp 5 - Portugues

JAVA 5 349

Usando Classes de Conjuntos (Objetivo 6.3)E Os conjuntos s6 podem armazanar Objects, mas tipos primitivos podem ser usados com autoboxing.

D Faga iterag6es com o loop for aprimorado, ou com um Iterator via hasNext o & next ( ).D hasNext ( ) determina se existem mais elementos; o Iterator nao se move.

E next ( ) retorna o elemenro seguinte r move o Iterator adiante.

E Para funcionarem corretamente, as chaves de um Map devem sobrescrever eguals ( ) e hashcode ( ) .

tr As filas usam of fer.( ) paraadicionar um elemento, poll ( ) para remover o primeiro item da fila, e peek ( )para ver o primeiro item da fila.

Classificando e vasculhando arrays e listas (Objetivo 6.5)D A classificagio pode ser feita na ordem natural, ou arrav6s de um Comparable ou de virios Comparators.

E Implemente Comparable usando compareTo ( ); fornece apenas uma ordem de classificagio.

E Crie v6rios Comparators para classi{icar uma classe de v6rias formas; implemente compare ( ) .

D Para um List ser classificado e vasculhado, os seus elementos devem ser compar6veis.

0 Para ser vasculhado, um array ou List deve ser classificado primeiro.

Classes Utilit6rias: Collections e arrays (Objetivo 6.5)tr Ambas essas classes de java.util fornecem

tr Um m6todo sort ( ). classifica usando um comparator ou usando a ordem natural

D Um m6todo binarySearch ( ). Busca em um aftay oul-ist prdclassificado.

D Arrays . aslist ( ) cria um List a parrir de um array e vincula um ao outro.

U Collections. reverse ( ) inverre a ordem dos elementos de um List.

E Colf ections. reverseorder ( ) retorna um Comparator que classifica ao contririo.

E Lists e Sets tAm um m6todo toArray ( ) para criar arrays.

Gen6ricos (Objetivo 6.4)E Os gen6ricos lhe permitem forgar a seguranga de tipos, em tempo de compilagio, par4 conjuntos (ou outras classes

e m6todos declarados usando-se parAmetros de tipos gen6ricos).

tr Uq Arraylist < Animal > pode aceitar refer6ncias do dpo Dog, Cat ou qualquer outro subtipo de Animal(subclasse ou, se Animal for uma interface, implementigio).

tr A.o usq conjuntos gen6ricos, nXo 6 necess6ria uma conversio para se obter elementos (de tipo declarado) a panirdo conjunto. Com conjuntos nio-gen6ricos,6 preciso converrer:

List<St.ring> glist = new Arraylist<Strj_ng> ( ) ;

List list = new Arraylist ( ) ;

/ / mais c6dioocts-.I -^ ^ - -ruLtrrre - - r-i=a.get(0); // ndo6 preciso converterString s = (String)list.get'(0) ; // convers6o obrigat6ria

tr Voc6 pode passar um conjunto gen6rico para um m6todo que use um conjunto nio-gen6rico, mas os resultadospodep ser desastrosos. O compilador.nXo poderi impedirque o m6todo insira o tipo errado no conjuntoanteriormente seguro em relagio ao tipo.

D Se o compilador colseguir reconhecer que um c6digo de tipo inseguro esti potencialmenre colocando em perigoalgo que voc6 originalmente declarou como de_dposeguro, voc6 riceber6 um aviso do compilador. Por eiemplo,se passar um List ( String ) para um m6todo declarado como

void foo(List al,ist) { al,ist.add(anlnreger),. }

o compilador emitiri um aviso, porque o m6todo add ( ) 6 potencialmente uma "operagio insegura".

I Lembre-se de que "compila sem erros" nio 6 o mesmo que "compila sem avisos". No exame, um aviso decompilagio nio 6 considerado como erro ou falha de compilagio.

tr A informagio de tipos gen6ricos nXo existe no tempo de execudo - ela s5 existe para a seguranp em tempo decompila$o. Misturar gen6ricos com c6digo antigo pode criar um c6digo compilado que poder6 langar uma exce$o notempo de exean$o.

Page 376: Java - Scjp 5 - Portugues

350 Copitulo 7: Gen6ricos e Coniunlos

D As atribuig6es polim6rficas aplicam-se somente ao tipo-base, e nio ao parAmetro de tipo gen6rico. Voc6 pode usar

List<Animal> alist = new ArraylisL<Animal>O; / / sim

Mas nio

List<Animal> al,ist, = new ArraylistcDoS>O; // n6'o

fl A regra.de atribuigio polim6rfica se aplica sempre que uma atribuigio puder ser feita. Os seguintes nia siopermitidos:

void foo(List<Animal> al,ist) { } // ndo pode usar um List<Dog>

List<Animal> baro t ] // ndo pode retornar um List<Dog>

Q A sintaxe dos coringas permite que um m6todo gen6rico aceite subtipos (ou supenipos) do tipo declarado do

argumento do m6todo:

void addD(List<Dog> d) {} // s6 pode usar <Dog>

void addD(List<? extends Dog>) {} // pode usar <Dogl> ou <Beagle>

O A palavra<have coringa 6 usada para significar ou "estende" ou "implementa". Assim, em <? exLends Dog>,

Dog pode ser uma classe ou uma interface.

QAoseusarumcoringa, List<? extends Dog>,oconjuntopodeseracessado,masniomodificado.

Q Ao se usar um coringa, List<?>, qualquer tipo gen6rico pode ser atribuido i refer6ncia, mas aPenas Para acesso,

e nXo para modificag6es.

QList<Object>refere-seapenasaumList<Object>,enquantoqueList<?>ouList<? extendsobj 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 Listboolean add(E o) // Dec]-araqdo de List.addo

tr O identificador de tipo dos gen6ricos pode ser usado em declarag6es de classes, m6todos e variiveis:

class Foo<t> { } // vma classe

T anrnstance; / / vma variiivel de instdnciaFoo(T aRef) {} // o arqtmento de um construtorvoid bar(T aRef ) {} / / o argttmento de um m6t.odo

T bazo {} // vm tiPo de retorno

O compilador fornecerS,o tipo propriamente dito.

B VocA pode usar mais de um tipo parametrizado em uma declaragio:

public class UseTwo<T, X> i itr VocA pode declarar um m6todo gen6rico usando um tipo nio definido na classe:

public <T> void makelist(T t) { }

ndo estivsando T como o tipo de retorno. Esse m6todo tem um tipo & retorno void, mas para usar T dentro doargumento do m6todo voc6 deve declarar o < T ) , o que acontece antes do tipo de retorno.

Teste individual

l. Dado:import java.util.*;

class Test {

public static void main(String[] args) {

/ / :.'nsira o c6digo aqui

x.add("one";;x.add("Lwo"1;

x.add("TWO");

System.out,println(x.poll O ) ;

)

Page 377: Java - Scjp 5 - Portugues

JAVA 5 35I

)

Quais opg6es, inseridas em / / insira o c6digo aqui, irio compilar? (Marque todas as corretas)

A. listcstring,> x = new Linkedlist<String> O ;

B.TreeSet<String> x = new Treeset<String>O ;

C.HashSet<String> x = new Hashset.<String> O ;

D. Queue<Stringr> x = new Priorityeueue<Strinq> ( ) ;

E.errayl,ist<String> x = new Araylist<String> ( ) ;

F.f,inkedf,ist<String> x = new Lj,nkedlist<String>O ;

2. Dado:public static void main(String[] args) {

// INS]RA A DECLARAqAO AQUI

for (int i = 0; j- <= 10; i++; {

List<Integer> row = new Arraylist.<Integer> ( ) ;

for (int j = 0; j <= 10; j++)

row.add(i * j);table.add(row) i

)

for (List<Integer> row : table)q\t<l-am

^rri- nrinl- ln Irnt^rl .rr\.vYf /,

)

Quais instrug6es poderiam ser inseridas em / / TNSIRA A DECLARACAO AQUI para permitir que esse c6digocompile e rode? (Marque todas as corretas)

A. List<List<Integfer>> table = new List<List<Integer>> ( ) ;

B. t,ist<f,ist<Integer>> table = new Arraylist<List<Integer>> ( ) ,.

C. list<l,ist<Integer>> table = new Arraylist<Arraylist<Integer>> ( ) ;

D.f,ist<f,ist, Inteqer> tabl-e = new List<List, Integer>O;E.List<List, Integer> table = new Arraylist<List, Integer>O;F.list<l,ist, fnteger> table = new Arraylist<Arraylist, Integer>O t

G. Nenhuma da" anteriores.

l. Quais das declarag6es abaixo s6o verdadeiras com relagao i comparagdo de duas instinciasda.mesma claslq, dado que os m6todos equals ( ) e halhcode ( ) foram apropriadamentesobrescritos? (Marque todas as corret:N)

A.Seom6todoequals( ) retornartrue,ooperador::decomparagiodehashCode( ) poderetornartrue.B.Seom6todoequals( ) retornarfalse,ooperador- = decomparaglodehashCode( ) poderetornar

E.rue.

C. Se o operador :: de comparagXo de hashCode ( ) retornar true, o m6todo equals ( ) deve retornartrue.D. Se o operador = : de comparaSo de frashCode ( ) retornar true, o m6todo equals ( ) pode retornar true.E. Se o operador !: de comparagio de hashCode ( ) retornar true, o m6todo equals ( ) pode retornartrue.

4. Dado:import java.util.*;

class Flubber {

public sEatic void main(String[) args) {

List<String> x - new Arraylist<String>O;

Page 378: Java - Scjp 5 - Portugues

352 Copftulo 7: Gen6ricos e Coniunlos

x.add(" x") ; x.add("xx") ; x.add(*Xx") ;

/ / insira o c6digo aqui

for(String s: x) System.out.printfn(s) ;

))E a saida:

xx

Xx

x

Qual c6digo, inserido em / / insira o c6digo aqu j., produziri a suda acima? $4arque todas as corretas)

A. CoLlections. sort (x) ;

B. Comparable c = Collections.reverseO ;

ColLections. sort (x, c) ;

C. Comparator c = Collections.reverseO ,'

Collections. sort (x, c) ;

D. Comparabl-e c = Coflections.reverseOrderO ;

Collections. sort (x, c) ;

E, Comparator c = Collections.reverseorderO,'Collections. sort (x, c) ;

5. Dado:10. public static void main(String[] args) {

11. Queue<String> q = new Linkedlist<String> O ;

1,2 . q. add ( "Veronica" ) ;

13. q.add("Wa1lace");

14. q.add("Duncan");

15. showAll (q) ;

16. ]

L1 .

18. public static void showAll (Queue q) {

19. q.add(new Integer(42]']r;

20 . while ( lq. isElmpty O )

2L. System.out.print(q.removeO + " ");22. ]

Qual 6 o resultado?

A. Veronica Wallace Duncan

B.Veronica Wallace Duncan 42

C. Duncan Wafface Veronica

D.42 ouncan Wallace Veronica

E. A compilagio falha.

F. Ocorre uma excegio em tempo de execugio.

6. Dado:public static void before ( ) {

Set set = new TreeSet ( ) ;

set. add ("2" ) ;set.add(3);

Page 379: Java - Scjp 5 - Portugues

JAVA 5 353

set.add("1");Iterator it = set. iterator ( ) ;

while (it.hasNextO )

Svstem 6lll- nrinj- lif navl- l\ + \\ $.|..rfvr:u \ / I I I

)

Quais das seguintes afirmativas sio verdadeiras?

A. O m6todo before O exibir|12

B. O m6todo before <l exjbiritZlC. O m6todo bef ore ( ) exibir6 tr6s ndmeros, mas a ordem nio pode ser determinada.

D. O m6todo before ( ) nio compilari.

E. O m6todo before ( )langari uma excegio no tempo de execugio.

7. Dado:.i n*^rts i ar,- ,, F .i 1 * .flrLlrur L Jqvq. uLr! . ,

class MapEQ {

public static void main(String[] args) {

Map<ToDos, Strj_ng> m = new HashMap<ToDos, String>O;ToDos t1 = new ToDos("Monday,,);

ToDos t2 = new ToDos ( "Monday,, ) ;

ToDos t3 = new ToDos ( "Tuesday" ) ;

m.put (t1, "dolaundry" ) ;

m.put (t2, "payBi11s" ) ;

m nrrl- /f? rr^la^nAff i^,,\.

qr/ql-am nrrj- nrinl-lnlm cizot\1.

)

]

class ToDos{

String day;

ToDos(String d) { day = 6' 1

public boolean equals(Object o) {

return ( (ToDos)o).day == this.day;)

// public int hashCodeo { return 9; }

)

Quais afirmativas estio corretas? (Marque todas as correks)

A. Como est6, o c6digo nio compilar6.

B. Como est6, o c6digo produit|asuda2.

C. Como est6, o c6digo produrzir|asarda3.

D. Se o m6todo hashCode ( ) for ativado, retirando-se o / /, a saida seri 2.

E. Se o m6todo hashCode ( ) for ativado, retirando-se o / /, asaidaser63.

F. Se o m6todo hashCode ( ) for ativado, retirando-se o / /, o c6digo nio compilari.

8. Dado:12. public class AccountManager {

13. private Map accountTotals = new HashMap0;

14. private int retirementFund;15.

Page 380: Java - Scjp 5 - Portugues

354 Copftulo 7: Gen|ricos e Coniuntos

16. public int getBalance(Strj-ng accountName) {

L7. Integer total = (Integer) accountTotals.qet(accountName);

18. if (totaI == nul1)

L9. total = Integer.valueof (0) ;

20, ret.urn total-. intValue ( ) ;

2L. )

23' public void setBalance(string accounLName' int amount) t

24. accountTotals.put(accountName, Tnteger.valueOf(amount) ) ;

25. )

26. j

Esta classe precisa ser atudizada para usar os tipos gen6ricos apropriados, sem modificag6es no comportamento (nem

para melhor nem para pior). Quais destes passos poderiam ser realizados? @Iarque tr6s)

A. Substituir a linha 13 por

private Map<String, int> accountTotals = new HastrMap<String, int> O ;

B. Substituir a linha 13 por

private Map<String, Integer> accountTotals = new HashMap<Strinq, Integer>O;

C. Substituir a linha 13 por

private Map<String<Integer>> accountTotals = new Hash.N{ap<String<Integer>> ( ) t

D. Substituir CI linhas l7-20por

int tot.al = accountTotals.get (accountName) t

if (total == null)total = 0;

return total;E. Substituir as linhas 17-20 por

Integer t.ot.a1 = accountTotals.gret (accountName) i

if (total == nu1I)

t.otal = 0;

return total;F. Substituir as linhas 17-20 por

return accountTotals. get (accountName) ;

G. Substituir alinha 24 por

accountTotals.put (accountName, amount) ;

H. Substituir alhrha 24 por

accountTotals.puL (accounLName, amounL. intValue ( ) ) ;

9. Dado um array String devidamente preparado, contendo cinco elementos, qual faixa deresultados 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

Page 381: Java - Scjp 5 - Portugues

JAVA 5 355

10. Dado:interface Hungry<E> { void munch(E x); }

interface Carnivore<E extends Animal> extends Hungry<E> {}interface Herbivore<E extends Plant> extends Hungry<E> {}abstract class Plant { }

class Grass extends Plant { }

abstract class Aninal { }

class Sheep extends Animal implements Herbivore<Sheep> {public void munch(Sheep x) {}

)

class Wolf extends Animal implements Carnivore<Sheep> {public void munch(Sheep x) {}

)

Quais das seguintes modificag6es (feitas separadamente) permitiriam que esse c6digo compilasse? (Marque todas as

corretas)

A. Modificar a interface Carnivore para

int.erface Carnivore<E extends Plant> extends Hungry<E> { }

B. Modificar a interface Herbivore para

interface Herbivore<E extends Animal> extends Hungry<E> {}C. Modificar a classe Sheep para

class Sheep extends Animal implements Herbivore<Plant> {

public void munch(Grass x) {}

iD. 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 fornecer6acesso indexado a seus elementos, nao tendo, por6m, m6todos sincronizados? (Marquetodas as corretas)

A. java.util . Hashset

B. j ava. util . LinkedHashset

C. java. util . ListD. java.util .AnaylistE. java.util.vect,or

F. java. util . Prioritl4ueue

12. Dado:i-mport java.util.*;public class Group ext.ends Hashset<Person> {

Page 382: Java - Scjp 5 - Portugues

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 in hnnlaan :AAfohiont- nt ty$ry4+!

System.out.println("Adding: " + o),'

return super.add(o);

)

]

nla<q Parcnn {

nri rrafo fi na l Cl-ri nd hana.

public Person(String name) { this.name = name; }

public String toStringO { return name; }

]

Quais das seguintes coisas ocorrem pelo menos uma vez quando o c6digo 6 compilado e executado? M*q* todas as

corretas)

A.Adding Hans

B.addingr LotteC. Adding ,fane

D. total: 3

E. total: 5

F. O c6digo nio compila.n 4r r ^G. E langada uma excegeo no tempo de execugio.

13. Dado:'imnnrf i:rr: rrri'1 *.

class AlgaeDiesel {public static void main(String[] args) {

String[] sa = {"foo", "bar", "baz" };/ / lnsira as chamadas de m6todos aqui

]

]

Quais m6todos de j ava. util . Arrays e./ou j ava. util- . Collections voce poderia usar para converter as

em um List e depois procurar no List pelo indice do elemento cujo vaTor 6 "f oo"? (Marque de um a tr& m6todos)

A. sort ( )

B. asl,ist ( )

C. tor-ist ( )

D. search ( )

E. sortr,ist o

Page 383: Java - Scjp 5 - Portugues

JAVA 5 357

F. contains ( )

G. binarySearch ( )

14. Dado que String implementa java.lang.CharSequence, e:import java.util.*;public cLass LongWordFinder {

public static void main(String[] args) {

StrinslJ array = { "123", "72345678",

ListcString> list = Arrays. aslist (array) ;

Collection<String> resultlist = getlongwords (1ist) ;

)

// INSTRA A DECLARACAO AQUT

t

Collection<E> longwords = new Arraylist<E> ( ) ;

for (E word : coll)if (word.lengthO > 6) longWords.add(word);

return lonqWords,.

)

]

Quais declarag6es poderiam ser inseridas em /,/ INSIRA A DECLARACAO aQUr de forma que o programacompile e rode? (Ir4arque todas as corretas)

A.public static <E extends CharSequence> Collection<? extends CharSequence>

get.Longwords (Collection<E> co11 )

B.publj-c static <E extends CharSequence> List<E>

getlongwords (CollectioncE> co11 )

C. public st.atic Collection<E extends CharSequence>

getlongwords ( Col- lection<E> coll_ )

D. public static List<Charsequence>

getlongwords ( Col I ect ion<CharSequence> co 1 1 )

E.public static List<? extends CharSequence>

getlongwords (Collection<? extends CharSequence> co11)

F. st.atic public <E extends CharSequence> Collection<E>

getlongwords (Collection<E> co11 )

G, static public <E super CharSequence> Collection<E>

getlongwords (Collection<E> co11 )

15. Dado o c6digo a seguir,

12. Treeset map = new Treeset ( ) ;

13. map.add("one");

14. map.add("two");

15. map.add("three");

16. map.add("four");

17. map.add("one");

18. Iterator it = map.iteratorO;19. while (it.hasNext() ) t

Page 384: Java - Scjp 5 - Portugues

358 Copftulo 7: Gen6ricos e Con juntos

20. System.out.print( it.next0 + " " ) ;

2L. \

qual ser6 o resulmdo?

A. A compilaglo falha

B. one two three fourC. four three two one

D. four one three two

E. one two three four one

F. one four three two one

G. I1 hngada uma excegio no tempo de execuglo.

H. A ordem de exibiEio nio 6 garantida.

| 6. Dado um m6todo declarado como:public static <E extends Nudber> List<? super E> process(List<E> nums)

Um programador deseja usar esse m6todo da seguinte forma:

// INSIRA AS DECLARAqOES AQUT

output - process(input) ;

Quais pares de declarag6es poderiam ser colocados em / / INSTRA As DECLARACOUS aQur para permitir a

compilagio do c6digo? (Marque todas as corretas)

A.Arraylistclnteger> input = nu1l ;

Arraylist<Integer> output = nul1;

B,ArrayList<Integfer> input = nu1l;

List<Integer> output = nu1l;

C. Arraylist.<Integfer> input = null;ListcNumber> output = nu11,'

D,f,istctrtumber> input = null;Arraylistcrnteger> output = nu11;

E.r,ist<Number> input = nu1l;

List<Number> output = nu11;

F.listcrnteger> input = nu11;

List<Integer> output = nul1;

G. Nenhuma das anteriores.

Respostas do teste individual1. D e Festio corretas. O m6todopoll Oassocia-se comQueues. AclasseLinkedlistimplementaainterface

Queue.

A esti incorreta porque a interface List 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.(Objaivo6.3)

2. B est6 correta.

A est6 incorreta porque List 6 uma interface, de modo que vocd nio pode usar new List ( ) independentementede 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 tipodeclarado de List i esquerda. (Objetivo 6.4)

Page 385: Java - Scjp 5 - Portugues

JAVA 5 359

3. B e D. A resposta B 6 verdadeira porclue, freqiientemente, dois objetos diferentes podem retornar o mesmo valorparaoc6digodehashing. D6verdadeiraporquese acomparagiodehashCode( ) retornar: :, osdoisobjetos podem ou nio ser iguais.

As respostas A, C e E estio incorretas. C est6 incorreta porque o m6todo hashCode ( )6 muito flelvelem 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 m6todoCollections . reverseorder ( ) usa um Comparator, e nio um Comparable, para reclassificar o conjunto.

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

5. B esti correta. Hi um aviso do compilador na linha 19 devido a uma atribuiglo nlo verificada, mas, fora isso, tudocompila e executa sem erros. Embora tenha sido declarada originalmente como Queue<SLring>, emshowAll O ela 6 passada como um Queue sem tipo especifico - nada no compilador ou naJVM nos impede deadicionar um Integer depois disso. O m6todo add ( ) coloca itens no final da fila, enquanto que remove ( ) osredra do inicio da lista, de forma que os itens sio exibidos na ordem em que foram colocados.

A, C, D, E e F estio incorretas com base no exposto acima. (Objetivo 6.3)

6. E est6 correta. Nio 6 possivel colocar Strings e ints no mesmo TreeSet. Sem os gen6ricos, o compilador nio temcomo 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 compararum Integer com uma String, langar6 uma ClassCastException. Observe que, embora o m6todo bef ore ( ) nio usegen6ricos, ele usa autoboxing. Tome cuidado com c6digo que use recursos novos e antigos misturados.

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

7. CeDestiocorretas.SehashCodeO nioforsobrescrito,entaocadaentradair|paraoseupr6priodep6sito,eom6todo sobrescrito equals ( ) nlo ter6 efeito no que diz respeito a determinar a equivalAncia. Se

hashCode ( ) for sobrescrito, entio o m6todo equals ( ) sobrescrito veri t1 e t2 como duplicatas.

A, B, E e F estio incorretas com base no exposto acima. (Objetivo 6.2)

8. B. E e G estio corretas.

A esti errada porque voc€ nlo pode usar um tipo primitivo como parAmetro de tipo. C est6 errada porque umMap usa dois parAmetros de tipo separados por uma virgula. D esti errada porque um int nio pode fazer

autoboxing para um nu1 1, e F est6 errada porque um nu1 1 nio pode ser desencapsulado para um 0. H est6

errada porque voc6 nio pode fazer autoboxing de um tipo primitivo apenas tentando chamar um m6todo com ele.

(Objetivo 6.4)

9. G esti correta. Se uma correspond6ncia for encontrada, binarySearch ( )retornar6 o indice do elemento da

corresponddncia. Se nio for encontrada, binarySearch ( ) retornar6 um nrimero negativo que, se invertido e

depois diminuido, lhe informa o ponto de inserEio (indice do array) no qual o valor buscado deveri ser inserido

no array para que a classificagio apropriada seja mantida.

A, B, C, D, E, F e H estio incorretas com base no exposto acima. (Objetivo 6.5)

10. B est6 correta. O problema com o c6digo original 6 que Sheep tenta implementar Herbivore<Sheep> e

Herbivore declara que o seu parametro de tipo E pode ser qualquer tipo que estenda Plant. Uma vez que um Sheep

nio 6 um Plant, Herbivore<Sheep> nio faz sentido - o tipo Sheep est6 fora da faixa permitida do parimetro Ede Herbivore. Apenas solug6es que ou alterem a definigio de um Sheep ou alterem a definigio de Herbivorepoderlo 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, fizemosSheep estener Plant, e

^gora a classe

'Wolf falha porque o seu m6todo munch ( Sheep ) nio atende mais ao

contrato de Carnivore. (Objetivo 6.4)

11. D estl coffeta. Todas as classes de conjunto permitirlo que voc6 aumente ou diminua o tamanho de seu coniunto.O conjunto Arraylist fornece um indice para seus elementos. As classes de conjunto mais recentes tendem a

nio ter m6todos sincronizados. O conjunto Vector 6 uma implementagio mais antiga da funcionalidade de

Aruayl,ist e possui m6todos sincronizados; 6 mais lento que Arrayl,ist.As respostas A, B, C, E e F estlo incorretas com base na l6gica que esti descrita acima. Observag6es: C, List 6

uma interface e F, PriorityQueue nlo fornece acesso por indice. (Objetivo 6.2)

12. F e*6correta. O problema aqui reside no m6todo add ( ) de Group - ele deveria ser add ( Person ) , uma vez que a

classe estende Hashset<Person>. Assim, isso nlo compila. Teste ripido: o que aconteceria se voc6 consertasse

essec6digo,modificandoadd(object) paraadd(Person)?Tenteexeantaroc6digoparaverseoresultadobatecom o que voce esPerava.

Page 386: Java - Scjp 5 - Portugues

360 Cooitulo 7: Gen6ricos e Coniunios

A, B, C, D, E e G estio incorretas com base no exposto acima. (Ob.ietivo 6.4)

13. A, B e G sio obrigat6rias. O m6todo asl,ist O converte um array em um List. Voc6 pode encontrar o indice de

um elemento de um List com o m6todo binarySearch ( ) , mas, antes de fazcr isso, voc6 deve classificar a lista

usando sort ( ).

F est6 incorreta porque contains ( ) retorna um booleano, e nio um indice. C, D e E estio incorretas porqueesses m6todos nio estao definidos na interface List. (Objetivo 6.5)

14. F esti correta.

A chega perto, mas esti errada porque o valor de retorno 6 vago demais. A rlltima linha do m6todo espera que ovalorderetornoseiaCollectioncstring>,enioCollection<? extends CharSequence>.Best6errada porque longWords foi declarado como Collection<E>, e isso nio pode ser implicitamente convertidoem um List.<E> para bater com o valor de retorno declarado. @mbora n6s saibamos que longwords naverdade 6 um ArraylistcE>, o compilador s6 tem conhecimento daquilo que foi declarado) C, D e E estioerradas 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 nlofaz sentido - super poderia ser usada em conjunto com um coringa, mas nio com uma vari|vel de tipo como E.(Objeaivo6.3)

15. D est6 correta. TreeSet assegura entradas sem repedgeo; al6m disso, se acessado, retomari elementos na ordemnatural, o que para Strings ignrfca afabdtica.

As respostas A, B, E, F, G e H estio incorretas com base nal6gica que este descrita acima. Observe que, emboravoc6 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 Ae D estio erradas. C est6 errada porque o tipo de retorno resulta em um List<rnteger>, que nio pode seratribuido a uma variivel do tipo l,istcNumber>. E claro que todas essas provavelmente causariam umaNullPointerException, uma vez que as varilveis ainda sio nulas - mas a questio s6 nos pediu parafazer oc6digo compilar.

Page 387: Java - Scjp 5 - Portugues

Classes internas

Obiefivos porq qcertificoq6o

I Closses inlernos

I Closses inlernos locois de m6todos

I Closses internos on6nimos

I Closses estdlicos oninhodos

a/ Exercicios rdpidos

P&R Teste individuol

Page 388: Java - Scjp 5 - Portugues

362 Copitulo B: Closses internos

A classes internas (incluindo as classes est6ticas aninhadas) aparecerio em todo o exame. Emboranio hajaobietivosoficiais do exame eipecificamente sobre classes internas, o Objetivo 1.1 inclui classes internas (tamb6m conhecidas como

aninhadas). O mars rmporranre e que o codigo usado para representar perguntas sobre qaal7aert6pico no exame pode

envolver classes internas. A menoJque vocA iompreenda detalhadamente as regras e a sintaxe delas, 6 provivel que erre

perguntas que poderia responder corretamente. Como seji ndo bastasse o exame ar tdo dffcil.

Este capitulo examinar6 asvantagens e desvantagens (pr6s e contras) das classes internas e o colocar|frenteaexemplos comos tipoi de sintaxe (geralmente de"apar6ncia.rtrirha)]ot qoais vocA ver6 no decorrer de todo o exame. Portanto' na

verdade,voc|ter6 dbis objetivos neste capitulo: aprender o necess6rio para responder as perguntas que avaliarem seu

conhecimento sobre classes internas, e aprender iomo ler e entender os c6digos de classes internas para que possa

acompanhar corretamente o fluxo de perguntas que testarem seu conhecimento em outros tdpicos.

Entio, por que todo o espalhafato relacionado is classes internas? Antes de entramos no assunto, temos que lhe avisar (se

voc6 ji nio souber) que as classes internas tOm gerado debates apaixonados do tipo amor e 6dio desde que foramintroduzidas na nerslo 1.1 da linguagem. Pelo menos dessa vez, tentaremos ser reseryados em nossas opini6es e apenas

apresenraremos os fatos & maoeita q.te voc6 precisari para o exame. Ficar6 sob sua responsabilidade decidir como - e at6

q.t. ponto - deve us6-las em seu pr6prio desenvolvimento. E s6rio. Nem mesmo o toirr q.t. .ts"r-os revelar6 o que

Jchamos realmente delas - certo, c&o, vamos dizer entio! Achamos que elas tAm alguns empregos poderosos e eficientes

em siruag6es muito especificas, incluindo c6digos que sejam mais f6ceiJde ler e de manutengio simples, mas tamb6mpodem 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 parasuas classes j6 que voc6 poderifazer com que uma classe seja membro de outra. Da mesma forma que as classes Possuemvariiveis e m6todos-m.*b.o, tamb6m poiem rer classes-rnembro. Elas v6m em virias vers6es,iependendo d. comoe 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 umaclasse estitica aninhada nio deixa de ser uma classe definida dentro do escopo de outra classe, tamb6m a abordaremosneste capitulo sobre classes internas.

Diferente do que ocorre nos outros capitulos deste livro, os objetivosparaaceftificagio sobre classes internas nio t6mnrimeros 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 vezde quatro o$etiuosoficiais do exame.

I Classes internas

I Classes internas locais de m6todos

I Classes internas an6nimas

I Classes estiticas aninhadas

Obietivo poro o certificog6o

Classes internasVocA 6 um programador que usa o modelo OO, portanto, sabe que para obter reutilizagio e flexibilidade/extensibilidadeprecisa 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 maisadequada para essatarefa.As vezes, no entanto, nos vemos projetando uma classe na qual descobrimos ser preciso umcomportamento 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 algumatarefa como, digamos, um cliente de batepapo; pode querer que os m6todos especificos desse cliente (aceitar entradas, lernovas 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? Ouainda 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 m6todospara manipular os "eventos" (pressionamento de bot6es, digitaglo no teclado, E/S disponivel e outros), os quaiscontrolario as chamadas aos m6todos desse cliente. O cenArio ideal - da perspectiva do modelo OO - 6 manter os m6todosdo 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. ComoeEecia/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

Page 389: Java - Scjp 5 - Portugues

JAVA 5 363

(indicando que q-uer que a mensagem que digitou sej a enviada para o servidor do bate-papo) , o c6digo do cliente de bate-papo que enviar6 amensagem ter6 que ler em um campo de texto especifco.Em outras palavias, se o isuirio clicar no botioA, o programa ter6 que extrair o texto do objeto- TextF ieldB, de ama inttdncia espedfca fu ChatClienr Nlo em algu m otlhoc1ynp9.de texto de um objeto dzferente,mas especificamente no campo de texto que determinada instAncia da cilseChatClient 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 nioPode fazer.com que uma_classe seja derivada de v6rias classes, portanto, inserir todos os c6dig-os (o c6digo especifico docliente de bate-papo e o de-manipulagio de eventos) na mesmi classe nlo funcionar6 nesse cio. Entio,6 qui voc6p^oderiafazerseria se beneficiar da insergio de seu codigo de eventos em uma classe separada (melhor pr6tica no modeloOO, encapsulapglto e o recurso de estender uma classe diferente da estendida por ChatClient), mas,linda assim,concedendo a ele f6cil acesso aos membros da classe ChatClient.(para que o c6digo de manipulagio possa, por exemplo,atualizar xvari6veis de instAncia privadas de ChatClie nt).Y oc€ potter; conseg,rii isso fazenio .o- qrlr or rttembros de'ChatClient pudessem ser acessados pela classe de manipulagio ao torn6Jos, por exemplo, priblicos.'Contudo, essatamb6m nlo 6 uma boa solugio.

Voc6 i6 sabe para onde estamos indo - um dos beneficios principais da classe interna 6 o "relacionamento especial" que ainstdncia de uma classe intemacompanilha com uaa instincia da classe ex.tema. Esse "relacionamento especial" concede ao c6digoda classe interna acesso aos membros da classe que a estiver encapsulando (externa), como se a claise intemafryrseparte daextema.Naverdade, 6 exatamente isso que significa: a classe interna dumapane da classe externa. Nio s6 uma "parte', masum nembm individual da classe externa. Sim, uma instAncia da classe interna teri acesso a todos os membros da ilasseexterna, mgsTo aque/es marcados comopriuados- relaxe e lembre-se de que o objetivo era esse. Queremos que essa instAnciaespecifica da classe interna tenha um relacionamento intimo com a instAncia da classe externa, por6m, mantendo todo oresto separado. E, al6m disso, se voc6 escreveu a classe externa, enteo tamb6m criou a interna! Ponanto, nio est6 violando oencapsulamento;voce o prljetlzz dessa forma.

Codificando uma classe interna "comum"IJsamos o termo comilmpararepresentar classes internas que niosejam:

I Estiticas

I Locais de m6todo

I An6nimas

No resto desta seEio, no entanto) usaremos apenas otermo classe internaedescartaremos a palavra clmam - quandopassarmos para um.dos outros tr6s tipos da lista anterior, voc6 saber6. Defina a classe interna dentro das chaves da classe

externa como descnto a segurr:

alacc Mrrflrrt-ar I

class Mylnner { }

)

Muito f6cil. E se voc6 compilar isso,

Sjavac Myouter.java

terminar6 com /oziarquivos de classe:

MfOuter.dass

MlOuter$Mykrner.class

A classe interna continua sendo uma classe separada, portanto, um arquivo de classe 6 gerado. Entretanto, voc6 nio poder6acessar o arquivo da classe interna da maneira usual. Nio poder6, por exemplo, escrever:

*java MyOuter$MyInner

esperando executar o m6todo main ( ) da classe interna, porque uma classe inte rna comam ndo possui declarag6es estiticasde nenhum ipo. A iinica maneira de uocd conseguir acessar a classe interna seni por meio de una instdncia afiua da c/are externalEmoutras Palavras, s6 no tempo de execugio quando ji houver uma instAncia da classe externa a qual associar a instAncia daclasse interna. VocA veri tudo isso em breve. Primeiro, aperfeigoaremos um pouco as classes:

nlacc MrrArrtar I

private int x = 7;

/ / definisSo da cfasse internaclass Mylnner {

public void seeOuter() t

Page 390: Java - Scjp 5 - Portugues

364 Cooitulo B: Clqsses internos

System.ou!.grintln(r'Out,er x is " +:{)i

)

I / / fecha a definiQdo da classe internaj // fecha aclasseexterna

O c6digo anterior 6 perfeitamente vilido. Observe que a classe interna est6 realmente acessando um membro privado da

classe externa. Isso esti correto, porque a classe interna tamb6m 6 um membro da classe externa. Portanto, exatamente comoqualquer membro da classe externa (digamos, um m6todo de instAncia) pode acessar algum outro membro dela, privadoou nio, a classe interna - que tamb6m 6 um membro - pode fazer o mesmo.

Ceno, portanto, agora que sabemos como escrever um c6digo que conceda i classe interna acesso a membros da classe

externa, como o usaremos?

Instanciando uma classe internaPara 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 umainstAncia especifica da classe externa.

Instanciando uma classe interna a partir do c6digo da classe externa Geralmente, 6 a classe externa que cria instinciasda classe interna, ji que 6 ela que costlrma usar a instAncia interna como objeto arxiliar para seu uso pessoal. Vamos alterar a

classe M@ter para que irstancie Mylnner:

nlaec Mrzf)rrt.ar {

private int x = 7;

public voj_d makefnnerO {

Mylnner j-n = new Mylnner ( ) ;

in caaOrrt-or1\ -

1

a l a << Mr;Tnnar I

public void seeOuter ( ) {

/ / cria uma instdncia interna

System.out.println("Outer x is " + x) ;

)

Vod podever no exemplo anterior que o c6digo de MyOutertrataMylnner exatamente como se fosse qualquer outraclasseque pudesse ser acessada - ele a instancia usando o nome da classe (new Myrnner ( )) e, em seguida, chama umm6todonavari6veldereferdncia(in.seeouter( )).Contudo,ainicarazloporqueessasintaxefunciona|queoc6digo 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 dealgum local fora da classe MyOuter? Isso 6 ao menos possivel? @em, j6 que teremos o trabalho de criar um novo subtitulopara esse assunto, como voc6 verA a seguir, o grande mist6rio nio ser6 resolvido aqui.)

Criando um obieto de classe interna fora do c6digo da instincia da classe externa Uau! Esse 6 um grandesubtitulo, mas realmente explica o que tentaremos fazer. Se quisermos criar uma instAncia da classe interna, 6 preciso teruma instAncia da classe externa. Voc6 j6 sabe disso, mas pense nas implicag6es... Significa que, sem uma referbnciaaumainstAncia 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 classediferente. 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 classeexterna 6 simples, mas voc6 deve memorizar isso para o exame!

public static void main (String[] argrs) iMarnrrf 6r MrrArrf ar f \ .lrJvsuv! rlJvuLst \, ,

lllouter.Mylnner inner = mo.new ltylnner()tinner. seeOuter ( ) ;

)

O c6digo anterior 6 o mesmo, independente de o m6todo main ( ) estar dentro da classe MyOuter ou de algoma ouhaclasse (supondo-se que a outra classe tenha acesso a MyOuter, e ji que essa tem acesso padrXo, isso significa que o c6digo

Page 391: Java - Scjp 5 - Portugues

JAVA 5 365

deve estar em uma classe do mesmo pacote de MyOuter).

Caso goste de c6digos curtos, poder6 faz6-lo desta forma:

public static void main(String[1 args) 1

MyOuter mo = new Myouter1; // vai comegar uma instAnciatI,Eouter.Mylilrer inner = ttro.new lrDrfnner ( ) tanner-seeolrfer()

]

Voc6 pode considerar essa situagio como se estivesse chamando um m6todo na instAncia externa que, por acaso, fosse umm6todo de instanciagio especial da classe interna chamado com o uso da palavra-chave ner. e insttcilgio de uma classeinterna 6 o ilnico cen6r.io no qual vocA chamar6 new emumainstincia, e nio para conshairvmainstAncia.

Aqui est6 um resumo ripido das. diferengas entre um c6digo de instanciaglo de classe interna que estej a dzntv da classeexterna (por6m, sem ser est6tico) e um qu e ex€lafora daclasse externa:

I De dentro do c6digo da instAncia da classe externa, use o nome da classe interna normalmente:

public stat.ic void main (String[] args) {

MyOuter.Mylnner inner = new MyOuterO.new MylnnerO;inner.scootrfArl)'

)

r De fora do c6digo dainstAncia da classe externa (incluindo o c6digo do m6todo est6tico da classe externa), o nome daclasse interna agora deve incluir o da classe externa

MyOuter. Myfnner

e para instanciar, vocA precisa usar uma referAncia i classe externa,

new MyOuter( ) .new Mylnner( ); ou outerobjRef.new Uylnner( );se i6 tiver uma instAncia dela.

Referenciando a instAncia interna ou externa de dentro da classe internaComo um objeto re{erenciari a ele pr6prio normalmente? Usando a referdncia this. Revisio ripida de this:r A palavra-chave this pode ser usada dentro do c6digo da instAncia. Melhor dizendo, nio pode ser usada dentro do

c6digo static.r A referAncia this apontariparao objeto que estiver sendo executado no momento. Em outras palavras, o objeto cuja

refer6ncia foi usadapara chamar o m6todo que estiver sendo executado.

I A refer6ncia thi s 6 a maneira de um objeto passar uma refer6ncia dele pr6prio para algum outro c6digo, comoargumento de um m6todo:

public void myMethodO {

Mycl-ass mc = new MyClass O ;

mc.doStuff(this); // passa uma refer6ncia ao objeto executando myMethod

]

Dentro de um c6digo de classe interna, a referlncia thi s apontari para a instAncia da classe, como era de se esperar, j6 quethis sempre referencia o objeto que est6 sendo executado. Por6m, e se o c6digo da classe interna precisar de uma referdnciiexplicita i instAncia da classe externa a qual a instAncia interna estiver associada? Em outras palivras , nmo uoc6 nimti amponteiropara a "ryfer€ncia Lhis extema"?Embora normalmente o c6digo da classe interna nio precise de uma refer6ncia iclasse externa, porque j6 ter6 uma implicita que estar6 usando para acessar os membros dessa classe, pode precisar dareferAncia se tiver que pass6-la para algum outro c6digo como vemos a seguir:

nl:cc MrzTnnor I

public void seeouter ( ) t

System.out.printlp(\tQqter x is " + x) ;

System.out.println("fnner class ref is " + this);System. out.printl-n (\Outer cl-ass ref is \\ + Myouter. this) ;

Page 392: Java - Scjp 5 - Portugues

366 Copitulo B: Closses inlernos

Se executarmos o c6digo completo como 6 feito abaixo:

class MyOuter {

Private int x = 7;

public void makelnner ( ) {

Myfnner in = new MyInner0;in.seeOuterO;

]

class Mylnner {

publj-c void seeOuterO {

System.out.println("Outer x is " + x) ;

System.out.println("Inner class ref is " + this);System.out.println("outer cfass ref is " + Myouter-this);

]

)

public scatic void main (String[] argrs) {

MyOuter . MyInner inner = new MyOuter O . new MyInner O ;

inner. seeOuter ( ) ;

)

)

asaidaseri:

Outer x is 7

Inner class ref is Myouter$MyInner@113708

Outer class ref is MyOuter@33f1d7

Poftanto, as regras para uma classe interna que aponte para si pr6pria ou para a instancia externa sAo as seguintes:

I P ara re{erenciar a instAn cia da pr6pria classe interna , de dcnhv do c6digo dessa classe, use thi s .

I Para apontar para a refer6ncia " thi s ex'terna" (instAncia da classe externa) de dentro do c6digo da classe interna, use

NomeDaClasseExterna. this (exemplo, MyOuter . this).Modificadores de membros aplicados a classes internas A classe interna comum 6 um membro da classe

externa, exatamente como os m6todos e variiveis de instAncia, portanto, os modificadores a seguir podem ser aplicados a

umaclasse interna:

I finalI abstractI publicI privateI protectedI static - a excepio d qae sLatic a ttma uma classe aninhada de niuel supeior, em ueqde uma classe intema.

I strictfp

Obietivo poro o certificoe6o

Classes internas locais de m6todoO escopo de uma classe interna comum se encontra dentro das chaves de outra classe, por6m, fora do c6digo de qualquer

m6todo (em outras palavras, no mesmo nivel que uma variivel de instAncia 6 declarada). Ainda assim, voc6 tamb6m pode

delinir uma classe interna dentro de um m6todo:

cl-ass Myouter2 {

private String x = "outer2";

Page 393: Java - Scjp 5 - Portugues

JAVA 5 367

void doStuff O {

cfass Mylnner {

public voj_d seeOuter ( ) {

System.out.println("Outer x is " + x);j / / fecha o m6todo da cfasse interna

j / / fecha a definiqdo da classe interna\ / / fecha o m6todo doStuff0 da classe externa

j // fecha aclasseexternaOc6digoanteriordeclaraumaclasse,Myouter2,comumm6todo,doStuff ( ).Por6m, duttrodedoSLuff ( ),outra classe, MyTrurer, 6 declarada com seu m6todo pr6prio, seeouter ( ) . O c6digo acima 6 completamente inritil,no entanto, p orqve ndo instancia a clase intemalS6 por que vo cE declarou a clxse, neo significa que criouuma insldncia dela.Ponanto, se quiser realmente llsara classelnterna (digamos, para chamar seus m6todos), entao, voce ter6 que criar umainstincia dela em algum loc al dentro fu ndtodo, mas abaixo da defnipdo da dasse intema. O c6digo abaixo mostra como instanciare usar uma classe interna local de m6todo:

a'lacc MrrOrrfar? I

private String x = "Outer2";void doStuff O {

class Mylnner {

public void seeouterO {

System.out.println("Outer x is " + x);j / / fecha o m6todo da classe interna

\ | / focha a dofininSo da classc interna

MyTnner m1 = new Mylnner ( ) ; / / Esta linha deve vrr/ / Aaaai c rl: nla<<

mi. seeout.er O ;

) / / fecha o m6todo doStuff ( ) da classe externa

I // fecha a classe externa

O que um obieto interno local de m6todo pode ou neo fazer

A classe interna local de mtitodo sd podeni ser instanciada dentro do nhodo ondefor defnida. Melhor dizendo, nenhum c6digo que

estiver sendo executado em qualquer outro m6todo - dentro ou fora da classe externa - poder6 instanciar a classe internalocal de m6todo. Como os o6ietol da classe interna comum, o objeto da classe interna local de m6todo compartilhar6 umrelacionamento especial com o objeto da classe que o estiver encapsulando (externa) e poderi acessar seus membrosprivados (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 oescopo de uma variivel local 6 limitado ao m6todo em que foi declarada. Quando o m6todo 6 fin alizado, o quadro da pilha6 eliminado e a vari6vel vira hist6ria. Contudo, mesmo depois que o m6todo 6 concluido, o objeto da classe interna criadodenrro dele ainda pode estar ativo no heap se, por exemplo, uma referAncia_a ele tiver sido passada para algum outro c6digoe, em seguida, arriazrnada em uma vari6vel de instAncia. J6 que.as vari6veis locais nio t6m_ garantia de continuarem ativas

por tanto tempo quanto o objeto da classe interna local de m6todo, esse objeto_nio pode usi-las. A menor qae as umiiueis

locais vlan maridas cono f inal.'lO c6digo a seguir tenta acessar uma varilvel iocal de dentro de uma classe interna local de

metoclo:

class MyOuter2 {

nri rra1-e Sfri r16J x = "OUter2";v!+vsev

void doStuff O {

String z = "local variable";al:qc M\/Tnhar I

public void seeouter ( ) {

qlrqt- em orr1- nr:int1n("Ogter X iS " + x) ;

Svsfem-out-ni:int1n("Local variable z is " + z); // Ndo vai compilar!

Page 394: Java - Scjp 5 - Portugues

368 Copitulo B: Closses inlernos

\ / / fecha o m6todo da classe internaj / / fecha a definigdo da classe interna

\ / / fecha o m6todo doStuff ( ) da classe externa

j //fechaaclasseexternaA compilagio do c6digo anterior realmente preocupari o compilador:

Myouter2.java:8: local variable z is accessed from within j-nner class;needs to be declared final

q\/ql-am nttl- nrinflnlNT,^.al rrariah1 a z iq \'+ zl.

Marcar a vari6vel Ioca| z com f inal corriglr.^ o problema:

final String z = "1ocal variable" ; / / Agora o objeto interno pode usii-laApenas um lembrete sobre os modificadores de um m6todo: as mesmas regras das declarag6es de vari6veis locaissio aplicadas )s classes internas locais de m6todo. VocA nio pode, por exemplo, marcar uma classe interna localde m6todo com public, private, protected, static, transient e algo semelhante. Os rinicosmodificadores que voc€pader,i aplicar a essa classe sio abstract e f inal - mas 6 claro que nunca os dois aomesmo tempo como para qualquer outra classe ou m6todo.

oBSERVAQ6ES pene O EXAME

L.embre-se de que uma c/ase /oea/ du/arada em um mdtodo static terd acesn rlmente a membros static 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 c ndo baueni a referdncia Lhis, portantl, aclasse intema de um mdtodo s t a t i c utd suleita as mesmas restipdes desse mdtodo. Em outras pa/arras, ndo tem ace$o a "uaidueis de

in$dncia".

Classes internas an6nimas simples, versao um

Observe o c6digo abaixo; vilido, por6m, estranho ) primeira vista:

class Popcorn {

public void pop ( ) tq\/cl-am nrr1- nrirts ln / rtnana^r^r, \ -vJvuutt.vsu.yrfllufrr\ yvvuvrll /,

)

cl-ass Food {

Popcorrr D = nevt eopcorn() {

public void popfl {

System. out.println ( "anonlmous popcorn,' ) ;

hl-t r. r.f.\,roleTtvo poro o centttcocoo

Classes internas an6nimasAt6 agora examinamos a definigio de uma classe dentro de outra classe encapsuladora (uma classe interna comum) e dentrode um m6todo (uma classe interna local de m6todo). Para concluir, examinaremos a sintaxe mais incomum que voc€ veriemJava: classes internas declaradas sem qualquer nome (dai a palavr a an6nina).E se isso nio fo. estrarrho o bastante, vocApoderi 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 tipoclasse interna an 6nima imples)e, em seguida, a classe interna an6nima decl arada no argomento.

Talvez sua tarefa mais importante aqui seja aprender a ndo se confundir quando se d.eparar com essa intaxe. O exame est6 repleto dec6digos com classes internas an6nimas. 56 para ter uma id6ia, voc6 poderi v6-los em perguntas sobre threads,wrappeobre, sobrescrigio, coleta de lixo, etc.

Page 395: Java - Scjp 5 - Portugues

JAVA 5 369

I;)

Examinemos o que ocorreu no c6digo anterior:

r Definimos duas classes, Popcorn e Food.

I Popcorn tem um m6todo, pop ( ) .

I Food tem uma variivel de instAncia, declarada com o tipo Popcorn. Isso 6 tudo quanto i Food. Essa classe nattemm6todos.

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 subclassean6nina (ndo noneada) de Popcorn.

Examinemos apenas o c6digo da classe an6nima:

? P6n^6rn n = nar^r Ddn^nrn/l {v _ rruYv rvyvvrrl\/ L

3. public void popo {

4. System. out.printl-n ( "anonlzmous popcorn" ) ;

6. j;Linha2 A linha 2 comega como uma declaragio de vari6vel de instAncia do tipo Popcorn. Mas, em vez de ter este

formato:

Popcorn p = new Popcorn (\ ; / / - repare no ponto-e-virgula ao finalh6 uma chave no final da linha2, onde normalmente estaria um ponto-e-virgula

Popcornp = new Popcorn(\ { // _uma chave emvez do ponto-e-virgulaVoc6 pode ler a linha 2 como:

"Declare uma variivel de referAncia, p, do tipo Popcorn. Em seguida, declare uma nova classe que nio temnome, mas 6, uma sbclasse de Popcorn. E agora temos a chave que abre a definigio da classe..."

Linha 3 Em seguida, a linha 3 6, na verdade, a primeira instrugio dentro da definigio da nova classe. E o que elafaz? Sobrescreveu o m6todo pop ( ) da superclasse Popcorn. Aqui este o ponto crucial da criagio de uma classe

interna an6nima: sobresmuer am ou mais mtitodos da saperclasse (ou implementar m6todos de uma interface, masguardaremos isso para mais tarde).

Linha 4 Alinha46aprimeira (enesse casoailnica) instruglodom6todopop( ) novo. Nadaespecialaqui.

Linha 5 A linha 5 cont6machave defechamento do m6todopop( ). Nadaespecial aquitamb6m.

Linha 6 E aqui que vocA ter6 que prestar atengeo: a linha 6 inclui uma chauefechando a defnipdo da classe andnina (6 a

chave que acompanha a da linha 2), por6m, aindah| mais! Essa linha tamb6m tem 0 plnto- e-uirgula qaefnali7a a inshztgdo

iniciada na linha 2, instruglo em que tudo comegou - a que declara e inicializa a vari6vel de referAncia Popcorn.Portanto, terminaremos com uma referAncia de Popcorn a uma instAncia rec6m-criada da novissima rubclasrc

an6nima (sem nome) instantAnea de Popcorn.

oBSERVAQ6ES peRA O EXAME

Geralnente, d diftcil identifcar o ponto-e-uirgula de fechamento. Portanto, uocd pode uer am cridigo conl este n0 exame:

? Dnnnnrn n - iar^r Dnnnnrnf \ {zt rvvuvlr] P - rrefv rvyevlrr\/

2 ^,,1-1 .i ^ -.^; d pop ( ) iPuvrfe vvr

4. SysLem.out.println("anonymous popcorn") ;

6. ) // Fllta o ponto-e-virgiula aecesgdrio p,ara finalizar a instrugto en 2!!7. Foo f = new FooO;

Voci precisard de um cuidado especia/ com a sintaxe qaando houuer classes internas enuoluidas, porqae o aidigo da linba 6 parece perfeitanente

natural. Ndo estamos acostumadot a uer o ponto-e-uirgala depois de chaues (a ilnica oatra sitaagdo em qae isso ocorre t1 em atalhos na

inicialirygdo de anay).

O polimorfismo entra em cena quando classes intemas an6nimas estlo envolvidas. kmbrese & q*, como no exemploantarior 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:

Page 396: Java - Scjp 5 - Portugues

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 eatoh.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 sobrescreverum 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 declasses da superclasse.

Observe o c6digo inv6lido a seguir:

nlacc Dnnnnrn fvvv v! rr r

publ-ic void pop0 {

System. out.println ( "popcorn" ) ;

]

cLass Food {

PoPcorn P = new PopcornO {

^,,1-1 .i ^ ,,^r,{ sizzle ( ) tPuvffu vvrs

System. out.println ( "anonymous sizzling popcorn" ) ;

]

public void pop ( ) {

System. out.println ( "anonlmous popcorn" ) ;

]

];

public void poplt ( ) {

p.pop O ; / / oK, Popcorn tem um m6todo pop op. sizzle (l ; / / Inv6lido ! Popcorn ndo tem sizzfe ( )

]

]

compilaglo do c6digo anterior nos dara,

Anan i:rr: . 1 q ' .^nh^f racnl rra crmlln lv uJ f L'!vr

symbol : method slzzle lllocation: class Popcorn

p,sizzle);

A

que 6 a maneira de o compilador dizer: "NXo consigo encontrarseguido de: "Consiga uma pista".

o m6todo sizzle ( ) na classe Popcorn",

Page 397: Java - Scjp 5 - Portugues

Classes internas an6nimas simples, versio doisA rlnica diferenga entre as vers6es um e dois 6 que a primeira cria umaespecificado, enquanto a verslo dois cria um implerueitador an6nimo doanteriores, definimos uma nova subclasse an6nima do tipo popcorn

Popcorn P = new PopcornO {

Mas, se Popcorn fosse um tipo de intefaa emvez de um tipo de classe, entAo ainp 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 :

JAVA 5 371

subclasse an6nima do tipo de classe

tipo de interface especificado. Nos exemploscomo vemos abaixo:

nova classe an6nima seria um

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 rinicavezqlrevoc6 ver6 a sintaxe,

new Cookable ( )

emqueCookable 6umainterfanemvezdeumtipodeclassenioabstract.Porque,pensebem, uoc6niopode

instanciar uma inteface, emboraparega que 6 isso que o c6drgo est|fazendo. Mas 6 claro que ele nio est6 instanciando umobjeto 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 queimplementarainterfacecookable.Mas,ahsim,aindanio temotumaclassequeimplementeCookable,portanto,cflaremos uma agora mesmo. Nio precisamos de um nome para a classe, mas ela seri uma classe que implementar6Cookable, 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. Naverdade, uma classe interna an6nima nio pode nem estender uma classe e implementar uma interface ao mesmo tempo. Aclasse interna precisa da definiglo de se ir6 ser a subclasse de uma classe nomeada - e de maneira alguma ir6 implementardiretamente qualquer interface - az se implementari uma rinica interface. Por "diretamente", queremos dizer usando a

palavra-chave implements como parte da declaragio da classe. Se a classe interna an6nima for uma subclasse do tipo de

uma classe, ela se tornari automaticamente um implementador de qualquer interface criada pela superclasse.

oBSERVAQ6ESpeneOE)(AME

l,{60 se deixe enganar por qaalquer tentatiua de instanciagdo de intefan que ndo s/a uma clase intema an6nima. A linha a tegair ndo 6

u,llida,

Runnable r = newRunnabl-el); // impossivel instanciar a interface

enqaantl a qae re encontra abaixo d udlida, porque estui instanciando ua implementador da inteface Runnable (una classe de

iruplenentaqdo aninina):

Runnable r = new Runnable O { / / chave em vez de ponto-e-virqulapublic void runo { }

);

Classe interna an6nima definida no argumento

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

Page 398: Java - Scjp 5 - Portugues

372 Copitulo B: Closses internos

gostariamos de nos responsabilizar completamente pela confusio. Por6m, ficaremos felizes em compartilhar.

Certo, se voc€ chegou a essa sentenga presumiremos que voc6 compreendeu a segio anterior e adicionaremosapenas uma nova alteragio. Imagine oien6rio a seguir. Voc€ est6 digitando, tentando criar a classe perfeita, e

.i.r.n. o c6digo que chama um m6todo em um objeto ear e usa um objeto do tipo Foo (uma interface).

cfass MyWonderfulClass {

void go0 {

Barb=newearo;b.doStuff(AckweDon'tHaveAFool) i / / Nao tente compilar isso em casa

]in|-ovf:aa Fna I

void foof O ;

]

class Bar {

void doStuff(Foo f) { }

)

Sem problemas, exceto por voc6 nlo ter-o objeto de uma classe que.implemente Foo. Contudo, tamb6m nio.podeinstanciar um, porque nem mesml tem umaclasse que implenenteFoo, o que dizer da instAncia dela. Assim, primeiro voc0precisa de uma classe que implemente Foo e, em seguida, precisar6 de uma instAncia dessa classe que ser6 passada para om6tododoStuff ( )daclasseBar.SendoumprogramadorJavaastuto,voc6simplesmentedefiniriumaclasseinternaan6nima, dentro do argumenlo. Exatamente, logo onde voc6 menos esperaria encontrar uma classe. E aqui est6 o formato deseu c6digo:

1. class MyWonderfulClass {

2. void goO {

3.

A

5.

6

Barb=newBarO;

b.doStuff(new FooO {

n,,1-r1 ia r,^.i^ +^^f o {

q\tqfpm arrt. nrinfln / \f^^f\r/ \ .

7. j // final-izaom6todofoof8, j) ; / / finaliza as instruq6es def, arg' e end da classe interna9. j // finalizago(lL0. j // final-iza a classe11.

12. interface Foo {

13. void foof ( ) ;

14. ]

15. class Bar {

L6. void doStuff(Foo f) { }

1,7. \

Toda a agio comega na linha 4. Estamos chamando doStuf f ( ) em um objeto Bar, mas o m6todo usa uma instAnciaque E-Um Foo, em que Foo 6 uma interface. Ponanto, temos que criar tanto um a clxse de implementagdo quanto umainstdnciadessaclasse, tudo bem aqui no argumento de doStuf f ( ) . EntXo,6 o que faremos. Escreveremos

new FooO {

para iniciar a nova definigio da classe an6nima que implementar6 aintertace Foo. Foo s6 tem um m6todo a implementar,f oof ( ) , portanto, nas linhas 5, 6 e 7 implementamos esse m6todo. Em seguida, na linha 8 - calma! - aparece mais umasintaxe estranha. A primeira chave fecha a nova definiglo da classe an6nima. Mas, nio esquega que isso tudoocorreu como parte do argumento de um m6todo, de modo que o par6ntese de fechamento ')' finaliza a chamadado m6todo, e ainda temos que encerrar a instruQio que comeqou na linha 4; assim, finalizaremos com um ponto-e-virgula. Esiude essa sinta*ei YocE ueri classes internai an6nimas no exame e teri que ser muito cuidadoso com a

Page 399: Java - Scjp 5 - Portugues

JAVA 5 373

maneira como sao fechadas. Se elas forem locais de argumento, terminario assim,

));mas se forem classes an6nimas simples, entao, sereo finalizadas assim:

j;

De qualquer forma, a sintaxe nio 6, a que voc6 usar6 em praricamenre qualquer outra parre da linguagem Java,Poftanto, seja cuidadoso. IJma pergunta de alguma pane do exame pode envolver claises internas an6nimasconstituindo o c6digo.

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 internase$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 classeestitica aninhada nio tem esse privil6gio. EIa simplesmente 6 uma cLsse nio-interna (tamb6m conhecida como"de nivel superior") cujo escopo se encontra dentio de outra classe. Ponanto, quando'se trata de classes estiticas,na verdade, a resolugio do nome-espago conta mais do que um relacionamento implicito entre as duas classes.

IJma classe aninhada estatica 6 simplesmente aqaela que d um merybro utdtico da classe encapsulatlora, como vemos abaixo:

class BigOuter {

static class Nested { }

)

A classe propriamente dita nio 6 realmente "est6tica"l nio existem classes est6ticas. O modificador static,nesse caso, informa que a classe aninhada 6. um membro utitico da classe extema.Isso significa que ela pode ser acessada,como qualquer outro membro estAtico, sem ter tma instdncia da c/asse extema.

Instanciando uma classe aninhada estiticaUse a sintaxe padrio para acessar uma classe aninhada est6tica a p^ftir da sua classe imediatamente externa. Asintaxe para a instanciagio de uma classe aninhada estatica 6 um pouco diferente daquela de uma classe internacomum, e tem este formato:

nl:qq Rial.)rrt-or I

static class Nest {void go( ) { System.out.println("hi"); } }

]

class Broom {

static class 82 {void goB2( ) { System.out.println(..hi 2,,\; } }

public static void main(String[ ] args) {

new Bigouter.Nest( ); // an,bos nomes de cl_asses

// acessa a classe interna

Obietivo poro o certificoc6o

Classes est6ticas aninhadas

Bigouter.Nest n =

n.go( );82b2= new82( );b2.goB2( );

)

O que produz

hir]i2

Page 400: Java - Scjp 5 - Portugues

374 Copitulo B: Closses inlernos

oBSERVAq6ES pene O EXAME

Assim como aru mdtodo estdtico n6o terz acesso is aai,iueis de instdncjas e m,itodos ndo-sEatic da c/asse, uma clasrc estdtica

aninhada ndo tem acetso ir uaritlueis de instincias e aos mdtodos ndo-sLaLic da claxe extema. Procare por c/asses aninhadas

static con aldigo que se czmplfte tuml uma classe ndo+stdtica (intena regukr).

Resumo para a certificagioAs 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 codificaruma 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 umril".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 umaclasse intern4 precisa de uma refer6ncia ) instAncia da classe externa.

A seguir examinamos as classes internas locais de m6todo - classes definidas dentro de um m6todo. Vimos que o c6digode uma classe interna local de m6todo parece vinualmente igual ao de qualquer definig1o de classe, exceto por nlo.serpossivel aplicar um modificador de acesso da maneira que sio usados em uma classe interna comum. VocA tamb6maprendeu por que as classes internas locais de m6todo nio podem usar variiveis locais que nio seiam finais declaradas

dentro do mesmo m6todo - a instAncia da classe interna pode ter uma sobrevida depois que sair do quadro da pilha,portanto, a variivel local po& desaparecer, enquanto o objeto da classe interna ainda estar6 ativo. Mostramos que, Para usar

i classe interna, voc6 precisa irstanii6-1a e que a instanciagio deve vir depois da declaragio da classe no m6todo.

Tamb6m examinamos o tipo de classe interna mais estranho de todos' a classe interna an6nima. Voc6 aprendeu que elas

v6m em duas formas: simples e local de argumento. As classes internas an6nimas, digamos, normais, sio criadas comoparte 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 internasan6nimas 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 an6nimadefinir 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, naverdade, nio sio classes internas. Conhecidas como classes aninhadas est6ticas, uma classe aninhada marcada com omodificador s tat i c 6 bem semelhante a qualquer outra classe nio interna, exceto pelo fat o de que pan acess6-la, oc6digo deve ter acesso tanto ) classe aninhada quanto ) classe encapsuladora. Vimos que como a classe 6 estitica, nenhumainstAncia da classe encapsuladora 6 necessiria e, portanto, a classe aninhada est6tica nlo compartilha um relacionamentoespecial 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 ripidosAqui estXo alguns dos pontos principais deste capitulo.

Classes internasE Uma classe interna "comu m" 6, declaradadentro das chaves de outra classe, mas fora de qualquer m6todo ou outro

bloco de c6digo.

E A classe interna 6 um membro individual da classe encapsuladora (externa), portanto, pode ser marcada com ummodificador de acesso, assim como com o modificador abstracL ou f inal (mas 6 claro que nunca com ab-stract e f inal ao mesmo tempo - lembre-se de que abstract significari que ela deve ter subclasses,

enquanto final quer dizer que ela nXo pode ter subclasses).

E A instAncia da classe interna companilhari um relacionamento especial com uma instAncia da classe encapsuladora.Esse relacionamento concederi ) classe interna acesso a todos os membros da classe externa, incluindo os

marcados com private.fl Para instanciar uma classe interna, voc6 precisa ter uma refer6ncia i instAncia da classe externa.

E A partir do c6digo da classe encapsuladora, vocA pode instanciar a classe interna usando somente o nome dela,

como vemos abaixo,

Myfnner mi = new MyTnner ( ) ;

Page 401: Java - Scjp 5 - Portugues

JAVA 5 375

E A partir de um c6digo externo aos m6todos de instAncia da classe encapsuladorq vod pode instanciar a classeinterna usando somente os nomes das classes interna e extema e uma refer€ncia i classe extern4 como no c6digo abaixo:

Myouter mo = new MyOutero;Myouter.Myfnner inner = mo.new MylnnerO;

D A partir de um c6digo dentro da classe interna, a palavra-chave this pode armazenar uma refer6ncia iinstAncia da classe interna- Para apontar para a refer|ncia this .*t.rrr" (em outras palavras, a instAncia daclasse externa a qual essa instincii interna esti associada) anteceda a palavra-charr. i5i" com o nome daclasse externa como na linha abaixo:

MrzOrri- ar thi c.

Classes internas locais de m6todoD 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 mesmom6todo, por6m, ap6s o c6digo de definigio da classe.

E Uma classe interna local de m6todo.nio pode usar variiveis declaradas dentro do m6todo (incluindoparAmetros), a menos que essas variSveisie.lam marcadas com f inal.

E Os rinicos modificadores que voc6 pode aplicar a uma classe interna local de m6todo sio abstracL ef inal (nunca os dois ao mesmo rempo, no entanto).

Classes internas an6nimasE As classes internas an6nimas nio t6m nome, e seu tipo deve ser uma subclasse do tipo nomeado ou um

implementador da interface nomeada.

D Uma classe interna an6nima 6 sempre criada como pane de uma instruEio, portanto, nio esquega de fechar a instrugio,com uma chave, ap6s a definigXo da classe. Essa 6 uma d"s raras vezes em que voc6 ver6 uma clave seguida de umpontoe-virgula em Java.

D Por causa do polimorfismo, os inicos m6todos que voc6 poder6 chamar em uma refer6ncia ) classe interna an6nimaserio os delinidos na classe (ou interface) da variivel de referOncia, ainda que a classe an6nima seja, na verdade, umasubclasse 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 podee$ender uma classe e implementar uma interface, nem implemlntar mais de uma interface.

E Uma classe interna de argumento local 6 declarada, definida e automaticamente instanciada como pane de uma chamadade m6todo. O importante a lembrar 6 que a classe estar6 sendo definida dentro do argumento de um m6todo, portanto,a sintaxe finalizariadefinigio da classe com uma chave, seguida de um par6ntese de feihamento para encerrar alhamadado m6todo, que ainda ser6 seguido por um ponto-e-virgula, o qual fechari a instruEio: ] ) ;

Classes aninhadas esteticasD As classes aninhadas estiticas sio classes internas marcadas com o modificador static.E Tecnicamente, uma classe aninhada est6tica nio 6 uma classe interna, mas, em vez disso,6 considerada uma classe

aninhada de nivel superior.

tr J6 que a classe aninhada 6 estdtica, nio compartilha nenhum relacionamento especial com uma instAncia da classe externa.Naverdade, voc6 nio precisa de uma instAncia da classe extgrnapara instanciarumaclasse aninhadaest6tica.

E Instanciar uma classe aninhada estitica requer o uso tanto do nome da classe enerna quanto o da aninhada, comovemos abaixo:

BigrOuter.Nested n = new BigOuter.NestedO ;

D Uma classe aninhada estitica nlo pode acessar membros nioest6ticos da classe extern4 ji que nio tem uma refer6ncia implicitaa nenhuma instAncia externa (em outras palavras, a instAncia da classe aninhada nio usa uma referAncia thi s orterna) .

Teste individualAs perguntas a seguir o ajudario a avaliar sua compreensio do material dinAmico e transcendente apresentadoneste capitulo. Leia todas as opg6es com cuidado. Selecione todas as resposras corretas para cada pergunta. Nlo se

apresse. Relaxe.

l. Dado o c6digo a seguir,

public class MyOuter {

Page 402: Java - Scjp 5 - Portugues

376 Cooftulo 8: Closses internos

public static class Myrnner {public static void foo ( ) { } }

]

que instruglo, se inserida em uma classe diferente de MyOuter ou Mylnner, criar6 uma instAncia da classe aninhada?

,{. Myouter.Mylnner m = new Myouter-Myfnner( );

B. uyouter.Mylnner mi = new Mylnner( );

C Myouter m = new uyouter( );Myouter.MyInner mi = m.new Myouter.MyInner( );

D. Myrnner mi = new MyOuter.Mylnner( );

2. Quais das declarag6es abaixo s6o verdadeiras com relagao i classe aninhada estetica? (Marque

todas as corretas)A Voc6 precisa ter uma referdncia ) instAncia da classe encapsuladora para instanci6-la.

B. Ela nio tem acesso a membros nlo-sLatic da classe encapsuladora.

C Suas variiveis e m6todos devem ser static.D. Se a classe externa se chamar Mlouter, e a classe aninhada se chamar Myrnner, ela pode ser instanciada usando

new Myouter.Myfnner( ) ;

E. Ela deve estender a classe encapsuladora.

3. Dado:public interface Runnable { void run( ); }

O que cria a instAncia de uma classe interna an6nima? Qr4arque todas as corretas)

A.Runnabler=newRunnable( ) { };B.Runnable r = new Runnable(public void run( ) { });C.Runnable r = new Runnabfe{public void run( ) { }};D. Runnable r = new Runnable ( ) {public void run{ } };E. System.out.println(new Runnable( ) {public void run( ) { }});F. System. out.println (new Runnable (public void run ( ) { } ) ) ;

4. Dado o c6digo a seguir,class Boo {

Boo(String s) t ]

BooO t ]

]

class Bar extends Boo {

BarO { }

Bar(String s) {super(s) ; }

voi_d zoo O {

/ / insira o c6digo aqui

]

]

quais das instrug6es abaixo criam uma classe interna an6nima de dentro da classe Bar? (Marque todas as corretas)

,d eoo f = new eoo(24) { };B. Boo f = new Bar( ) { };C Boo f = new Boo( ) {Stri-ng s; };D. gar f = new Boo(String s) { };E, Boo f = new Boo.Bar(String s) { };

Page 403: Java - Scjp 5 - Portugues

JAVA 5 377

5. Dado o c6digo a seguir,1. class Foo {

2. class Bar{ }

4. class Test {

5. publj_c static void main (String [] args) t6. 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 dem6todo? (Marque todas :N correhs)

A Ela deve ser marcada com f i-nal.

B. Elapode ser marcada com abstract.C Elapode ser marcada compublic.D. Ela pode ser marcada com stat.ic.E. Ela pode acessar membros privados da classe encapsuladora.

7. O que 6 verdade com relagao ) classe interna an6nima? (Marque todas as correhs),4" Ela pode estender somente uma classe e implementar apenas uma interface.

B. Ela pode estender somente uma classe e implementar v6rias interfaces.

C Ela pode estender somente uma classe ou implementar apenas uma interface.

D. Pode implementar virias interfaces, independente de tamb6m estender uma classe.

E. Pode implementar virias interfaces, se nio estender uma classe.

8. Dado o c6digo a seguir,public class Foo {

Foo() {System.out.print ("foo") ; }

class Bar{

Bar( ) {System.out.print ( "bar" ) ; }

public void go() {System.out.print ("hi") ; }

]

nrrhl ic <j- :l- ic rrnid main /qt- rina f l :ra<) {

Foo f = new FooO,-

f .makeBar O ,'

]rrnid maLaF.arI\ t

(new BarO t]).goO;]

Page 404: Java - Scjp 5 - Portugues

378 Cop(tulo B: Closses internos

qual ser6 o resultado?

A. A compilagio falhar6.

B. Um erro ocorreri no tempo de execugio.

C. foobarhiD. barhiE. hi

9. Dado o c6digo a seguir,1. public class TestObj {

2. public static void main (String [] argrs) t

3. Object o = new Object0 {

4 . publ j-c bool-ean equa]s (Obj ect obj ) t

5. return true;6. )

7. ]

8. System.out.println(o.equals("Fred") ) ;

q]

10.)

qual ser6, o resultado?

A. Uma excegio ocorreri no tempo de execugio.

B. trueL. ralseD. A compilagio falhari por causa de um erro na linha 3.

E. A compilaglo f.alhari por causa de um erro na linha 4.

F. A compilagXo falhari por causa de um erro na linha 8.

G. A compilagio falharipor causa do erro em uma linha que nio 6 a 3, 4 ou 8.

| 0. Dado o c6digo a seguir,1. public class HorseTest {

2. public static void main (String [] args) {

3. class Horse {

4. public String name;

5. public Horse(String s) {

6. name = s;

7. )

B. ]

9. Object obj - new Horse("Zippo");10. Horse h - (Horse) obj;1,1. System.out.printfn(h.name) ;

t2. ]1? ]

qual serd o resultado?

A. Uma excegio de tempo de execugio ocorrer6 na linha 10.

B. zipppo

C. A compilagio f.alhar| por causa de um erro na linha 3.

D. A compilaglo falhari por causa de um erro na linha 9.

E. A compilagdo falhar6 por causa de um erro na linha 10.

Page 405: Java - Scjp 5 - Portugues

F. A compilaglo falharipor causa de um erro na linha 11.

I l. Dado o c6digo a seguir,1-. public class HorseTest {

2. public static void main lsrrino [t aras] {

3. class Horse {

4. public String name;

5. public Horse(String s) {

5. name = s,.

t. )

8. ]

9 . Object obj = new Horse ( "Zippo,') ;

10. System.out.println(obj.name) ;

1.r. )

12. jqual ser6 o resultado?

A. Uma exceglo de tempo de execugio ocorrer6 na linha 10.

B. zipppo

C. A compilagdo falharipor causa de um erro na linha 3.

D. A compilagio falhari por causa de um erro na linha 9.

E. A compilagd,o f.alhar|por causa de um erro na linha 10.

12. Dado o c6digo a seguir,publ-ic abstract cl-ass AbstractTest {

public int getNum0 {

return 45;

)

public abstract class Bar {

public int getNumo t

return 38;

]

)

public static void main (String [] args) {

AbstractTest t = new AbstractTestO {

public int getNum( ) {

retwrn 22;

]

];AbstractTest.Bar f = t.new BarO {

public int getNumo {

return 57;

]

];q\/c1-am arrl- nrinf lnlf nal-\Trrmt\ + \'t\ + | dafT\Trrmf ]).

Page 406: Java - Scjp 5 - Portugues

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.

1.

,)

3.

4.

f,.

Respostas do teste individualA. Mylnner 6 uma classe aninhada est6tica, portanto, deve ser instanciada com o uso do nome do escopo

completo que 6 MyOuter.Mylnner.

A resposta B esti incorreta porque nio usa o nome da classe encapsuladora na instrugio new. C est6 errada

porque usa a stnraxe ,rrcor.et". Quando voc6 instanciar uma classe aninhada. chamando a palavra-chave new.* ,rrn" instAncia da classe encapiuladora, nio teri que usar o nome dessa classe. A diferenEa entre A e C 6

que C est6 chamando new em uma instAncia da claise encapsulador^, ern uez de chamar a,palavra-chave

iioladamente. D est6 incorreta porque nio usa o nome da classe encapsuladora na declaragio da variivel.

B e D. A resposta B est6 correta porque uma classe aninhada estitica nio 6 associada a uma instAncia da classe

encapsuladori e, porranto, nio podi "cersar

or m.mbros nio-static da classe (da mesma forma que um m6todo

stalic niopodeacessarosmimbrosnioesr6ticosdeumaclasse).Dusaasintaxecoffetaparainstanciagiodeumaclasse 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 ouaninhadatenha que estender algo.

E estA correta. Ela define a instAncia de uma classe interna an6nima, o que tamb6m significa que ao mesmo tempo cria

uma instAncia dessa nova classe an6nima. A classe an6nima 6 um implementador da interface Rur:nable, portanto,deve sobrescrever o m6todo run ( ) de Runnable.

A resposta A est6 incorreta porque nlo sobrescreve o m6todo run ( ) , portanto, viola as regras da

implementagio de interfaces. B, C e D usam a sintaxe incorreta.

B e C. A resposta B est6 correta porque as classes internas an6nimas nio slo diferentes de nenhuma outraclasse quando se trata de polimoifismo. Isso significa que vocA sempre poder6 declarar uma vari6vel de

refer€niia do tipo da superclasse e ter essa vari|vel referenciando a instincia de um tipo da subclasse, que,nesse caso, 6 uma subclasse an6nima de Bar. Ji que Bar 6 uma subclasse de Boo, tudo funciona. C usa a sintaxecorreta para a criaglo de uma instAncia de Boo.

A resposta A esti incorreta porque passa um tipo int para o constnrtor de Boo, e nio hi um construtorcoincidente na classe Boo. D est6 errada porque viola as regras do polimorfismo; voc6 nio pode referenciarum tipo da superclasse usando uma variivel de refer6ncia declarada com o tipo da subclasse. NXo 6 garantidoque a superclasse tenha tudo que a subclasse possui. E usa a sintaxe incorreta.

B est6 correta porque usa a sintaxe certa - emprega os dois nomes (das classes externa e interna) na declaraEioda 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 nadeclaraglo da variivel de referAncia e porque a sintaxe de new nio esti correta. D est6 incorreta porque nio usa o nomeda classe externa na declaragio da variivel de refer6ncia. E est6 errada porque a sintaxe de new est6 incorreta.

6. BeE.ArepostaBesticorretaporqueumaclasseinternalocaldem6todopodeserabstract,emboraissosignifiquea necessidade da criagio de uma subclasse da classe interna se a classe abstract for usada (ponanto,6 improv6velque uma classe interna local de m6todo abstract seja ritil). E est6 correta porque uma classe interna local de m6todofunciona como qualquer outra classe interna - tem um relacionamento especial com uma instincia da classe externa, de

modo que pode acessar todos os membros dessa classe.

A resposta A est6 incorreta porque uma classe interna local de m6todo nio precisa ser declarada como f inal (emboraseja viiido faz€-lo). C e D esteo erradas porque uma classe interna local de m6todo nio pode ser public(embre-se de que voc6 nio pode marcar nenhuma variivel local com public) ou static.

7. C esth correta porque a sintaxe de uma classe interna an6nima s6 permite um tipo nomeado depois de.new, e

esse tipo tem que ser apenas uma interface (caso no qual a classe an6nima implementari essa interface) ouvma inica classe (situag5o em que a classe an6nima estender6 essa classe).

As respostas A, B, D e E estXo todas incorretas porque nio seguem as regras da sintaxe descritas na resposta

Page 407: Java - Scjp 5 - Portugues

JAVA 5 381

C.

8. C esti correta pgrgue primeiro a instAncia de Foo 6 criada, o que significa que o consrnrtor de Foo foiexecutado 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 (deum subtipo an6nimo de Bar)

^ partir da qual o m6todo go0 6 chamJdo. Repare que a linha (new Bar ( ) {

] ) . so ( ) ; cria uma pequena classe interna an6nima, um subtipo de Bar.

As respostas A, B, D, E e F estXo incorretas com base na l6gica do programa que esd descrita acima.

9. G. Esse c6digo seria vilido se a linha 7 terminasse com um ponto-e-virgula. Lembre-se de que a linha 3 6 umainstrugio que nio termina at6 a linha 7 e, como instrugio, precisaria de um ponto-e-virgulicomo fechamento!

As respostas $ B, C, D, E e F estio incorretas com base nal6gica do programa descrita acima. Se o ponto-e-virgula fosse adicionado i linha 7, entio a resposta B estaria correta - o programa exibiria true, o retbrno dom6todo equals ( ) sobrescrito pela subclasle an6nima de obj ect.

10. B. O c6digo da classe FlorseTest 6 perfeitamente v6lido. A linha 9 cria uma instAncia da classe interna local dem6todo Horse, usando uma variivel de refer6ncia declarada com o tipo Object. A linha 10 converte o objetoHorse na vari|vel de refer6ncia Fforse, o que permitir6 que a linha 11 seja compilada. Se a linha 10 fosseremovida, 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 voc6usar uma vari6vel de refer€ncia do tipo obj ect, poderi acessar somente os membros definidos na classeObj 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 subclassesconcretas dessa classe. O objeto referenciado pela vari6vel t 6 a instAncia de uma subclasse concreta deAbstractTest, e a classe an6nima sobrescreve o m6todo getNum( ) para que retorne 22. Avariiryelreferenciada por f 6 a instAncia de uma subclasse an6nima de Bar, e essa subclasse tamb6m sobrescreve om6todo getNum ( ) (para que retorne57). Lembre-se de que para criar uma instAncia de Bar, precisaremos deuma instAncia da classe externa AbstractTest, a fim de associ6-1a I nova instincia da classe interna Bar.AbstractTest nio pode ser instanciada porque 6 abstract, portanto, criamos uma subclasse an6nima (nio-abstract) e, em seguida, usamos essa instAncia associando-a ) nova instAncia da subclasse de Bar.

As repostas B, C, D, E e F estio incorretas com base na l6gica do programa que esd descrita acima.

Page 408: Java - Scjp 5 - Portugues

382 Copitulo 8: Clqsses internos

Page 409: Java - Scjp 5 - Portugues

Threads

Obietivos poro qcertificog6o

I Inicior Threods

I Reconhecer Estodos e TronsiE6es deThreods

I Usor o Bloqueio de Objetos poro

Evitor o Acesso Simult6neo

I Escrever C6digo que Use woii0,notifyfl ou noiifyAll0

r' Exercicios 16pidos

P&R Teste Individuol

Page 410: Java - Scjp 5 - Portugues

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.pr6ximaagio :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' pore*implo,.rm arriso pudesse ser comunicado instantaneamente. Todo o tempo, o usuirio estaria interagindo com.outras

panei do aplicativo. A an6lise tamb6m poderia ocorrer em um thread separado, para que o usu6rio pudesse trabalhar em

outros lociis do aplicativo enquanto os resultados estivessem sendo calculados'

Mas, o que exatamente i um thread? EmJava, "thread" significa duas coisas diferentes:

I Uma instAncia da classe java.lang.Thread;

I umthreaddeexecuglo.

Uma instAncia de Thread 6 apenas... IJm objeto. Como qualquer outro objeto emJava, ele tem vari6veis e m6todos, reside e

6 eliminado no heap. Mas um thread de exuapdo6 um processo individual (um processo "simples") que possui sua pr6priapilha 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 threadprincipal. 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 primeirom6todo da pilha - o m6todo na parte inferior dela. Por6m, logo que voc6 criar w nouothread, uma nova pilha se

materializar|eos m6todos chamados a partir duythreadserio executados em uma pilha de chamadas separada da pilha de

main ( ) . A execugio dessa segunda pilha de chamadas 6 considerada simultAnea a do thread principal, mas

aperfeigoaremos essa noglo ao percorrermos este capitulo.

VocA pode achar confuso estarmos falando de c6digos sendo executados simultaneamenle - como se estivessem emparelhadu

-, jh que voc6 sabe que hi somente uma CPU na maioria das miquinas que processam Java. Do que se trata entio?A JVM, que obt6m sua parcela da CPU independente do mecanismo de agendamento que o sistema operacionalusar, funciona como um mini-sistema operacional e agenda seus pr6prios threads, nlo imponando o sistemaoperacional 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 maisimportante a entender em todo este capirulo 6: Quando se trata de threads, h6 poucas garantias.

Poftanto, seja muito cuidadoso com a interpretagdo de algum comportamento com o qual voc6 se deparar em /./ma

m6quina, como "a maneira do thread funcionar". Seri esperado no exame que voc6 saiba o que 6 ou nio umcomporramento garantido, para que seja possivel projetar um programa de maneira que funcioneindependentemente da JVM subjacente. Issofaqpafte do conceito pincipal da linguagem Jaua.

AO TRABALHO

Nio comela o erro de proletar reil pragrama baseado em ama implementagio especifca da JL/M. Camo uocd aprenderd posteionnente, JW|ISdiferentes 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.

As perguntas do exame sobre threads estio entre as mais dificeis. Na verdade, para a maioria das pessoas elas sla

Page 411: Java - Scjp 5 - Portugues

JAVA 5 385

realmente I mais dificeis, e com qrxttro objaivos sobre threads voc6 terd que responder udriarpergontassobre eles. Se aindanio estiver familiawado com os threa&, provavelmente ter6 que passar algum tempo fazendoieGs. Al6m disso, ai vai umaviso final de isen$o: Este t@ituk ndt i ama lentatiua fu lhe mstnmcomoprEehruru Elicatun con uirios tbrcatls fuJonna atleqaatla e segara bemos

@rcsentar@enat o hisim sobv esse a<finso hhito neste capitublVo& estS aqui para aprender os frrndamentos do uso de threads, etamb6m o que precisa para acertar as perguntas do exame sobre threads. Antes de conseguir escrever um c6digo adequadocom 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 siothreads "do usu6rio". Voc0 e o sistema operacional podem criar um segundo tipo de thread, chamado de threaddaemon. A diferenga entre esses dois tipos (do usuiiio e daemon) 6 que a JVM16 finaliza um aplicativo quandotodos 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 dequaisquer threads daemon. Mais uma vez, esse t6pico ndo cai no exame.)

Criando um threadUm tlrread emJava comega como uma insAncia de java-lang.Thread Vod encontra.ri m6todos na classe Thread para gerenciaros threads, o que inclui zua cia$o,inicio e pausa- No exame, vod ter6 que conhecer, pelo menos, os m6todos a sryin

start ( )

yield( )

st-eep ( )

run( )

Toda a aglo comega no m6todo run ( ) . Considere o c6digo que voce quer executar em um thread diferente,como "o trabalho a ser feito". Melhor dizendo, vocA tem alguma tarefa que precisa ser executada, digamos, odownload 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 tarefuexecutada 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 nn( ). O m6todorun ( ) chamar6outros m6todos,6 claro, mas othreaddeexecu$o - anovapilhade chamadas - sempre comegarlchamando run ( ). Entlo,onde entrari o m6todo run ( ) ? Em uma das duas classes que vod pode usar para definir o trabalho de seu thread.

VocO pode definir e instanciar um thread de uma das duas maneiras:

I Estender a classe java.lang.Thread

I Implementar a interface Runnable

VocA ter6 que conhecer as duas no exame, embora no mundo real seja muito mais provivel que implementeRunnable emvez de estender Thread. Estender a classe Thread 6 mais f6cil, mas, geralmente, nio 6 uma boaprhrica no modelo OO. Por qu6? Porque a criagio de subclasses deve ser reservada para classes que estendam umaclasse j6 existente, por elas serem uma versio mais especializadada superclasse mais gen6rica. Portanto, a rinicasituaglo em que realmente faz sentido (da perspectiva do modelo OO) estender Thread 6 quando temos umaverslo 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 livrepara estender alguma aatra classe.

Definindo um thread

Para definir um thread, voc6 precisa de um local para inserir seu m6todo run ( ) e, como acabamos de discutir, 6

possivel fazer isso estendendo a classe Thread ou implementando a interface Runnable. Examinaremos as duassituag6es nesta segXo.

Estendendo java.lang.ThreadA maneira mais simples de definir que um c6digo deve ser executado em um thread separado 6:

I Estender a classe Thread;

I sobrescrever o m6todo run ( ) .

O formato 6 este:

Page 412: Java - Scjp 5 - Portugues

386 Copftulo 9: Threods

cl-ass MyThread extends Thread {

public void run ( ) {

System.out.println( "Tmportant job running in MyThread" ) ;

]

A limitagio dessa abordagem (al6m de ser uma opgio fraca para o projeto na maioria dos casos) 6 que se voc6 estender

Thread, nio poderd utender nada mais. E nlo se trata de esse comportamento herdado da classe Thread ser exclusivamentenecess6rio, porque para usar um thread voc6 teri que instanci6-lo de uma maneira ou de outra.

Lembre-se de que voc6 pode sobrecarregar o m6todo rurr ( ) em sua subclasse de Thread:

cl-ass MyThread extends Thread {

public void runo {

q\/ai-am nrrl. nrirl-ln t"Tmn^rj-:hl- inh rrtnnino in MvThrcad") .

]

public void run(Strj-nq s) {

Qa,cf6m ^,1f

hrinflh/\\cts'.i-^ i- r"n i. " + S);

].]

Masesteja a)ertaparaisso:omitodarun(String s) MbrecarregadoserdignoradopelaclasseTbreadamenosqueuoc6ochane.A

classe Tbread espera um milodo run ( ) um argumentos, e executari esse mdtodo para uoci ert una pi/lta de chamadas sQarada dEois que

otbreadtiuerseiniciad.o.Comumm6todorun(string s),aclasseThreadniochamar6om6todoparavocA,e,mesmoque voc6 chame o m6todo diretamente, a execugao nio ocorrer6 em um novo thread com uma pilha de chamadas s eparada.Acontecer6 na mesma pilha que a do c6digo de onde voc6 fez a chamada, como acontece com qualquer outra chamada a

m6todo normal.

I mplementando java.lang.RunnableA implement aElo dalntertace Runnable lhe proporcionari uma maneira de estender a classe que quiser, al6m de definir ocomportamento que serA executado por um thread separado. O formato 6 esse:

class MyRunnable implements Runnabfe {

public void runo {

Qa'dfan arrf nrihf lnl$Tnn^rf:nl- -inh rrrrlnlpg in MyRUnnabfe,,);

]

)

Independente de que mecanismo voc6 escolher, ji tem um c6digo que pode ser processado por um thread de execugio.Portanto, examinaremo s agoraa inttancia(alde sua classe habilitada para threads e, em seguida, veremos como fazer a coisa

fancionarrealmente.

Instanciando um thread

Nio se esquega de que todo thread de execuglo comega como uma instAncia & classe Thread. Independente de seu m6todorun ( ) estar em uma subclasse de Thread ou em uma classe de implementagio de Runnable, voc6 ainda precisar6 de umobjeto Thread parafazer t:udo funcionar.

Se voc6 estendesse a classe Thread, a instanciagio seria muito simples (veremos mais alguns construtores sobrecarregadosdaquiapouco):

MyThread t = new UyThreadQ ;

Se voc6 implementar Runnable, a instanciagio serl um pouco menos simples. Para ter um c6digo executado por um thread,uocdaindaprecinrideanainttdnciade-I'hread.Contudo,emvezdeinserirothreadeatarefu(oc6digodom6todorun( ))emuma classe, voc6 teri que dividi-los em duas classes: a classe Thread para o aldigc espedfn do thread, e sua classe de

implementagio de Runnable para o c6digo da tarefa que seri executada pelo thread. (Uma outra forma comum de se

considerarisso6pensandoqueThread6o"trabalhador",eRunnable6o"trabalho"aserfeito.)

Primeiro, instancie sua classe Runnable:

MvRrrnnatr'lF r = no\^r MrzPrrnn:hlol\.

A seguir, crie uma instAncia de java.lang.Thread (algo tem que executar sua tarefa...) e passe para ela a tarefa!

Page 413: Java - Scjp 5 - Portugues

JAVA 5 387

Thread t = new Thread (r) ; / / passe seu Runnable a ThreadSe voc0 criar um thread usando o constnrtor sem argumentos, ele ch,amarS,seu pr6prio m6todo run ( ) quandofor 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 classeRunnable que voc€ passari para o construtor de ThriaJ6 chamada de destino on classe Rannabi de de$ino.

VocA s6 pode passar uma instAncia de Runnable para os virios objetos Thread, de modo que a mesma instAncia setorne o destino de miltiplos threads, como vemos a seguir:

public cl-ass TestThreads {

public static void main (String [] args) {

MyRunnable r = new MyRunnableO;

Thread foo = new Thread(r);Thread bar = new Thread(r);Thread bat = new Thread(r);

l

Fornecer o mesmo destino para vlrios threads significa que mriltiplos threads de execugio estario executando amesma tarefa (e que a mesma tarefa seri feita diversas veies).

OBSERVAQ6TS pene O EXAME

A pnipria classe Tbread inplementa Rtnnable (afna/, ela tern am adtodo run ( ) qae estiuamos sobrescreuendo). I:sa signfica que uocd

poderia passar am Thread a 0ulr0 clnstrutzr de Tbread:

Thread t = new Thread(new MyThread( ) );Isso d am pouco estranho, nas adlido. Neste caso, na uerdade, uocd sd precisa de um Rttnnable, e criar oatro Thread d an exagerl.

Al6m do constnrtor sem argumentos e do que usa uma instAncia de Runnable (o destino, a instAncia que cont6m o trabalhoa ser executado), hi outros construtores sobrecarregados na classe Thread. Os construtores relevantes para n6s seo:

I Thread( )

I Thread(Runnable target)I Thread(Runnable target, String name)

I Thread(String name)

VocA ter6 que conhecer todos eles no exame! Posteriormente, discutiremos alguns dos outros construtores da lista anterior.

Entio, voc6 j6 criou uma instAncia de Thread e sabe qual m6todo run ( ) chamar. Mas ainda ndo hti nada anntecendo.I\essemomento, tudo o que temos 6 um objetoJava simples do tipo Thread. Ainda nio d un tbread de exuupio.Para obter umthread real - uma nova pilha de chamadas - ainda teremos qre iniciaro thread.

Quando um thread tiver sido instanciado, por6m, nio iniciado (em outras palavras, o m6todo start ( ) nio foichamado na instAncia de Thread), diz-se que ele est6 no estado novo. Nesse est6gio, o thread ainda nio 6 conside rado atiuo.

Depoisqueom6todo start ( )6chamado,othread6considerado comoatiuo(emboraom6todorun( )possaaindanio ter comegado a rodar). Um thread 6 considerado como desativado (nio mais ativo) depois que o m6todo run ( ) finaLza-O m6todo i sAl ive ( ) 6 a melhor maneira de determinar se um thread foi iniciado, mas nio concluiu seu m6todomn ( ) . (Observagio: o m6todo getstate ( ) 6 bastante ritil para a depuragio, mas voc6 nio precisar6 conhec6Jo paraoexame.l

Iniciando um threadVoc6 criou um objeto Thread e ele sabe seu destino (a instAncia de Runnable que foi passada ou ele pr6prio se voc6estendeu a classe Thread). Agora 6 hora de fazer toda essa est6ria de thread funcionar - iniciar uma nova pilha de chamadas.E tio simples que quase nao merece um subtitulo pr6prio:

t. start O ;

Antes de start ( ) ser chamado em uma instAncia de Thread, diz-se que o thread (quando usarmos o t minrisculo,estaremos nos referindo ao tbread de exuacio, e nio a classe Thread) este no estado novo. como foi mencionado. Oestado novo significa que voc6 tem um objeto Thread, mas ainda nio tem um thread rea/.Portanto, o que aconteceridepois que chamar start ( )? O que interessa:

I Um novo thread de execucio ser6 iniciado (com uma nova pilha de chamadas).

Page 414: Java - Scjp 5 - Portugues

388 Copitulo 9: Threoos

I O thread passar6 do estado novo Para o estado exuutduel.

r Quando o thread puder ser executado, o m6todo run ( ) de seu destino ser6 processado'

Certifique-se de memorizar o seguinte: a classe iniciada 6 Thread e nio Runnable. Chame start ( ) em uma

instAncia de Thread ( ) e nXo de Runnable.

OBSERVAQ6ES pene EXAME

Nno h,i natla especial na mitodo run ( ) da lingaagen laua. Cono main ( ) , sinrylesmente i o nome (e a assinatara) do mdtado que o

nouo thread chamard. Portanto, se uoft se deparar com un aidigo que cbame o mdtodo rwn ( ) em uma c/asse Rannable (oa mesmo em ama

instincia tle Thread), isso i pefeitanente udlida. Mas ndo stgntfca que o m,itodo run ( ) serd executado em uru thread sQarado! Chamar

um milatlo run ( ) drx)ninn tignfrco aPendr qile uoci estd cbamando am mitodo independente do thread qae estti sendo execatado, e ele

entrard na pi/ha de chamadas ataal, em ueqde no inicio de ma noua pilba. O cddtgo a seguir ndo inicia um nouo thread de exuupdo:

Runnable r = new Runnabfeo ;

r.runO; / / V61ido, mas ndo inicia um thread separado

O exemplo abaixo demonstra o que abordamos at6 agora: definigio, instanciagXo e inicializaEio de um thread:

class FooRunnable implements Runnable {

public void runO {

for(int x =1; x < 6; x++) tSystem. 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 runningRunnabfe runningRunnable 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 comque cada objeto Runnable exiba o nome do thread que executar seu m6todo run ( ) . O exemplo a seguir instancia umthread, 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 {

Page 415: Java - Scjp 5 - Portugues

nrthl ic ql-^l- id \z^id main (strind Il arfta\ I\ruLfrrv LJ q!vr/ r

NameRunnable nr = new NameRunnable (, ;

Thread t = new Thread(nr) ;

t. setName 1"nred,,) ;

t. start O ;

)

JAVA 5 389

)

A execugio desse c6digo pro duziri a saida especial a seguir:

? java NameThread

NameRunnable runninq

Run by Fred

Para obter o nome de um thread chame - quem adivinharia - getName ( ) na instAncia do thread. Mas, a instAnciaRunnable de destino nem mesmo tem uma referAncia ) instAncia de Thread, de modo que primeiro chamamos o m6todostat ic Thread. currentThread ( ) , que retorna uma referencia ao thread que estiver sendo executado e, emseguida, chamamos getName ( ) na refer6ncii retornada.

Mesmo se voc6 nio nomear explicitamente um thread, ele ter6 um nome. Examinemos o c6digo anterior, comentando ainstrugio que configura o nome do thread:

public class NameThread {

public static void main (String [] args) {

NameRunnable nr = new NameRunnable ( ) ;

Thread t = new thread(nr) ;

// t.setName("Fred");

t.start O ;

]

Agora a execugio do c6digo anterior nos dari:

% java NameThread

NameRunnable runninq

Run by Thread-O

Ej6queestamosobtendoonomedothreadatualusandoom6todostatic Thread.currentThread( ),podemos at6 obter o nome do thread que est6 executando nosso c6digo principal,

public class NameThreadTwo {

public static void main (String [] args) {

Svsfem.oilf nrinfln("thro^d iS "vJULLrr!rvsury!

+ Thread. currentThread( ) . getName ( ) ) ;

]

)

que seri

% java NameThreadTwo

thread is main

Certo, othreadprincipal j6temum nome -main ( ) (novamente, quem adivinhou?). AFigurag-1 mostra oprocesso de

inicializaeio de um thread.

Iniciando e executando mais de um threadJA brincamos o bastante; passemos para a execugio real de aiiosthreads (mais de dois, na verdade). J6 temos dois threads,porqn" o m6todo main ( ) comega no seu pi6prio thread, e depois't. start ( ) iniciou um seganlo thread. Oi6digo a seguir cria somente uma instAncia de Runnable e tr6s de Thread. Todas as tr6s instAncias de Thread t6m a

mesma instlncia de Runnable, e cad^ thread recebeu um nome exclusivo. Para concluir, todos os tres threads

foram iniciados com uma chamada a start ( ) nas instAncias de Thread.

Page 416: Java - Scjp 5 - Portugues

390 Coo(tulo 9: Threoqs

class NameRunnable implements Runnable {

public void runO t

for (int x = 1; x < 3; x++) {

q\rct-am nrrj. nrinl. lnl"Rrrn krv \'rJruvaLt.vuL.v! \ r\urr vJ

)

public class ManyNames {

nrrlrl in c|.at'ir rrnirl m:in /€j- rino Il aros)\ v e! r44Y

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

l-r^rn cf :rl- I \ .

|,hr^a ar^r|.l\.

pub) ic static void main{SL:ing I I args) i

+ Thread. currentThread ( ) . getName ( ) ) ;

+ " , x is " + x);

r1

*_ryI_-i

l) comega main0

Pilha Af--* *-.*--*

2) mainQ chama methodl()

i-..-'.."'-*Jj rtain i

Pilha A

i-----l

{

I 1 r**h"Ji I

I-a{: Il;r -lpilha B Pilha A

(thread t) (main thread)

3) methodlf comega um novo

/ / execuca

/ / al attm aAAl.d--"

//em maino

methodl(r;ii

,r I executa -. __-i**''- ''--i methodl j

/ / mais c6digroj

void nethodl{} {Runnah)l-e r : new MyRunnabLeO;

Thread t - new Thread{r);

t.sLartO; --.--__,

I I faz mais alguma coisa

)

Figuro

A execugio desse c6digo produzid o seguinte:

Z java ManyNames

Rrrn fr\/ F-re.l Y r_S 1

9-1 - lniciolizoEdo de um threod

thread

Page 417: Java - Scjp 5 - Portugues

JAVA 5 39I

Run by Fred, x is 2

Run by Fred, x is 3

Run by Lucy, x is 1

Run by Lucy, x i_s 2

Run by Lucy, x is 3

Run by Ricky, x is 1

Run by Ricky, x is 2

Run by Ricky, x is 3

Bem, pelo menos 6 isso o que foi exibido quando executamos o c6digo - desta vez, na nossa miquina. Mas ocomportamento que voc6 viu acima nio 6 garantido. Isso 6 tio crucial que voc€ teri que fazer uma pausa agora, respirarfirndo e repetir comigo: "O comportamento nio 6 garantido". Vocd prlcisa saber, para usar fufliramente comoprogramadorJava assim como no exame, que nio h6 nada na especi{icagloJava que informe que os threads comegario a serexecutados na ordem em que foram iniciados (em outras palavras, a ordem na qual start ( ) foi chamado em cadathread). E nlohA garantias de que uma vez que um thread comece a ser executado, continue at6 sua conclusio. Ou que umloop ser6 concluido antes que outro thread comece. Nio, meu caro. Nada 6 garantido no c6digo anterior, exceto isro:

Cada tbread seni iniciado e exuutado ati a eonclusdo.

Dentro de cada thread, as coisas acontecem em uma ordem previsivel. Mas as ag5es de diferentes threads podem se misnrarde 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 pequenamodificagio 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, eeventualmente comegamos a ver alguma oscila$o:

public void runo {

for (int x = L; x <= 400; x++) tSystem.out .println ( "Run by "

+ Thread. currentThread ( ) . getName ( )

* ", X is " + x);

J

A execuglo do c6digo anterior, com cadathreadprocessando o m6todo run de szuloop 400 vezes, comegou bem, masdepois se tornou nio linear. Aqui esd apenas um trecho da saida de linha de comando da execuEio desse c6digo. Paratornarmaisfacildistinguircadathread coloquei emit6lico asaidaqueincluiFred, eemnegrito adeLucy, deixando adeRickyinakerada:

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

Page 418: Java - Scjp 5 - Portugues

392 Cooitulo 9: Threoos

Run by Lucy, x is 344

...e continua...

Repare que nio h6 um padrio claro aqui. Se observarmos apenas a saida paraFred, vemos os nfmerosaumentando um de cada vez, como esperado:

Rttn bl Fred, x is 345

Ran b1 Fred, x is 345

Ran b1 Fred, x is 347

E o mesmo acontece se observarmos apenas a saida de Lucy ou Ricky. Cada um deles est6 se compoffando,individualmente, de uma forma bem ordenada. Mas juntos - caos! No fragmento acima, vemos Fred, depois Lucy e depois

Ricky (na mesma ordem em que originalmente iniciamos os threads), mas depois Lucy toma a vez de_Fred. Que falta de

educagiol E depois Ricky e Lucy se alternam por alguns irutantes, at6 que Fred tenha outra opornrnidade. Eles se revezam

dessa forma por "lgom

t.mpo, depois disso. Finalmente (depois da parte mostrada acima) Fred finaliza, e depois Ricky, e

entio Luryfinalizacomrlmalongaseqiidnciade saida. Assim, mesmo queRickytenhacomegado em terceiro, eleterminaemsegundo. 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 sidoconcluido. 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/readdeexuapdo.Ponarfio, se houver uma referOncia i instAncia de Thread, entio, mesmo quando essa instAncia nio for mais umtread de execugio, voc6 ainda poderi chamar m6todos nela, como em qualquer outro objeto Java. O que nio po derifazer,entretanto,6 chamar start ( ) novamente.

Una ueqqae o tread se tomar inatiuo, jamais podenl ser reiniciado!

Se voc6 tiver uma referAncia a um Thread, e chamar start ( ) , ele 6 iniciado. Se chamar start ( ) mais uma vez, issocausari uma excegio (uma IllegalThreadStateException, que 6 um tipo de RuntimeException, mas voc6 nio precisa se

preocupar com o tipo exato). Isso ocorre independentemente de o m6todo run ( ) ter ou nXo finalizado em relagio )primeira chamada a s tart ( ) . Apenas um novo thread pode ser iniciado, e apenas u mavez. Um thread que estiverrodando ou inativo nlo pode ser reinicializado.

At6 agora, vimos tr6s estados dos tread: nouo, executduel e inatiuo. Examinaremos outros estados antes de terminarmoseste capitulo.

O agendador de threadsO agendador de treads 4. a pane da JVM (embora a maioria das JVMs converca os treads Java diretamente emtreads do sistema operacional subjacente) que decide qual tread deve ser executado em algum momentoespecifico, al6m de tirarteads do estado execut6vel. Presumindo a existAncia de somente uma m6quinaprocessadora, 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 dizemosqaalifcado, 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 treadnio estiver no estado executAvel, enteo, neo poderi ser selecionado como o que ser6 imediatamente executado. E,portanto, fica evidente aprecariedade de garantias aqui:

A ordem na qua/ ot lreadt exuuhiueit sdo s/eaonadas nio i garantida.

Embora o comportamento deflksela comum, ele nio 6 garantido. Comportamento de fila significa que quando umtread tiver concluido sua execugio, passari para o fim da fila do pool executlvel e aguardar6 at6 que finalmente cheguea ser o primeiro, quando poderA ser selecionado novamente. Na verdade, chamamos isso de pool executavel, em vez de

fk executivel, para ajudar a reforgar o fato de que os trea& nio ficam todos alinhados numa ordem cena.

Apesar de nio controlarrnot o agendador de treads (nXo podemos, por exemplo, informar que um tread especificoseri executado), )s vezes, 6 possivel influenciilo. Os m6todos a seguir nos fornecerlo algumas ferramentas parainflaenciar o agendador. Somente nio confunda influ6ncia com controle.

oBSERVAQAO pene EXAME

Espere porpergunlas n0 exa e que aua/iardo sea conbecimento do que i oa ndo garantido! Voc|precisa ser capaTde olhar o aidigo de amtread e determinar se a saida serd realmente exibida de ama maneira esbecifrca ou se isso i indeterrnin,l:uel.

Page 419: Java - Scjp 5 - Portugues

JAVA5 393

Mdtodos da classe iava.lang.Thread Alguns dos m6todos que podem nos ajudar a influenciar o agendamentode threads sio os seguintes:

public static void sleep(long millis) throws rnterruptedExceptionpublic static void yieldopublic final void joinO throws InterruptedExceptionnrrhrl ic final rrnid qe|-Priori 1-rr(int. naurPrinri trr\uJ \ f rlL rlevv! r tv! f 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 InterruptedExceptionpublic final void notifyopublic 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, discutiremosos diferentes estados nos quais os treads podem se encontrar.

Obietivo poro o Certificocdo

Estados e Transig6es de Threads (Objetivo 4.2 do Exame)4.2 Reconhecer os estado: em que um thread pode existir, e identifcar at forwas pelas quais an thread pode passar de um estado para 0utr0.

J6 vimos tr6s estados - nouo, executduele atiuo -, mas espere! Ainda h6 mais! A tarefado agendador 6 colocar e tirar ostreads 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 estadoexecutavel. Um deles 6 quando seu m6todo run ( ) 6 concluido, situagio em que o tread passa do estado deexecugio diretamente para o inativo. A seguir, examinaremos algumas das outras maneiras pelas quais um treadpode 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 metodostart ( ) nlo foi chamado. Ele se torna um obieto Thread ativo, mas ainda nio 6 um tread de execucio. Nessemomento. o tread 6 considerado inatiuo.

I Execut6vel Esse 6 o estado em que um tread se encontra quando est6 qualificado para ser executado, mas oagendador nlo o selecionou como o tread a ser processado. O tread entra pela primeira vez no e$ado executivel quandoo m6todo start ( ) 6 chamado, mas tamb6mpode retornar ao estado executivel depois de serprocessado ou aoretornar de um estado bloqueado, de espera ou de suspensio. Quando o tread est6 no estado execut6vel, 6 consideradoatiut

I ExecuFo E o que interessa. O "grande momento". Onde acontece a aglo. Esse 6 o estado em que o tread se encontraquando o agendador o seleciona (no pool executivel) como o processo a ser executado imediatamente. IJm tread podesair 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 deentrar no estado de execugio: o agendador selecionar um tread no pool executivel.

t Espera/bloqueio,/suspensio Este 6 o estado de um thread quando est6 qualificado para executar. Ceno, entio temostr6s estados em um; mas todos possuem algo em comum: o tread ainda es6 ativo, por6m, nio esti qualificado paraexecngio. Em outras palavras, nio 6. exeuniwfmas pode rctomaraum estado execut6vel posteriormente, se um eventoespecifico ocorrer. Um tread pode ficar bkquead,t esperando por um recurso (como a E/S, ou o bloqueio de um objeto),caso em que o evento que o retornar6 ao esado executivel ser6 a disponibilidarle do recuno - por exemplo, quando foremrecebidos dados atrav6s do fluxo de entrada que o c6digo do tread estiver lendo, ou se o bloqueio do objeto ficardisponivel. 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 podeestar na erpcr4por W src6digo de exe cuglo a prouocou, caso em que o evento que o retorna rL para o estado

Page 420: Java - Scjp 5 - Portugues

394 Copitulo 9: Threods

execut6vel ser6 outro tread enviando uma notificagio de que nio 6 mais preciso aguardar. O ponto imponante6 que um tread nio inforrua ao outro que deve ficar bloqueado. Com alguns m6todos, pode pdrece,'que estea

dizendo a outro threid para bloqueai, mas nlo estio. Se voc6 tiver uma refer€ncia t a outro thread, pode

escrever algo como:

t.sleep( ); ou t.yield( )

Figuro 9-2 lronsigdo enfre os estodos dos threods

Mas esses sio , naverdade,m6todos estlticos da classe Thread - ebs ndo afetan a instdncia L;em vez disso, sio definidospara sempre afetar o thread sendo atualmente executado. (Esse 6 um bom exemplo de por que 6uma m6 id6ia usar

umavari6veldeinstAnciaparaacessarumm6todostatic -podecausarconfusio.H6umm6todo,suspend( ),na classe Thread, que perrnite a um tread informar a outro sualuspenslo; mas esse m6todo {oi reprovado e nio estarino exame (nem sua contrapartida, resume ( ) ). Hi ainda o m6todo stop ( ) , que tamb6m foi reprovado e nioser6 avaliado. Tanto susp-end ( ) quanto stop ( ) se mostraram muito perigosos, ponanto, voc€ nlo deve us6-los

e, nio esquega, porque foram reprovidos, nio aparecerio no exame. Nlo estude nada sobre eles, nio os use. Lembre-se

de que um tread no estado bloqueado ainda| considerado atiw.

I Inativo Um tread 6 considerado inativo quando seu m6todo run ( ) 6 concluido. Ele po& continuar sendo umobjeto Thread utiliz6vel, mas nio seri mais um tread separado de execugXo. lJma vez que um tread estiver inativo, nuncapoderi ser ativado novamente (tipo aquela coisa: "eu vejo treads mortos"). Se voc€ chamar start ( ) em umairstAncia inativa de Thread receber6 uma excegio de tempo de execuglo (e nio do compilador). E, provavelmente, nioser6 necesdrio um cientista espacial para lhe dizer que se um tread est6 inativo, ele nio 6 mais considerado atiw.

lmpedindo a execugeo do thread

Umtread que foi interrompido geralmente significaque passoupara o estado inativo. Mas o objetivo4.2avaliasuahabilidade para reconhecer quando um tread seri tirado do estado de execugio, por6m, sem entrar novamente no estado

execut6vel ou inativo.

No que dizrespeito ao exame, nXo estamospreocupados com o bloqueio de umtreadcausadoporE/a (digamos,

aguardando algo chegar de um fluxo de entrada do servidor). Estamos falando do seguinte:

I Suspensio

I Espera

I Bloqueio, porque precisa de um objeto bloqueado

Suspensio

O m6todo sleep ( ) 6 um mdtodo static da classe Thread. use-o em seu c6drgo para "desacelerar umtreadforgandoo a 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

despenado.

Entio, por que voc6 iria querer um tread suspenso? Bem, por achar que o treadex|percorrendo seu c6digo muitorapidamente. Ou precisar forgar seus treads a 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 quea maioria seria semelhante, e o que 6 mais imponante - seria um consumo precioso de largura de banda. A maneira maissimples de resolver isso 6 fazer com que um tread entre em pausa (suspensio) por cinco minutos depois de cada download.

Faga isso chamando o m6todo est6tico Thread. sl-eep ( ) , fornecendo um periodo em milissegundos, como vemosabaixo:

try {

Thread.sleep(5*60*1000); // Suspenso por 5 minutos

i catch (InterruptedException ex) { }

Page 421: Java - Scjp 5 - Portugues

JAVA 5 395

Observe que.o m6todo sleep ( )pode lanear uma excegio verificada InterruptedException (cuja possibilidadede 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.tlamoicada chamada de suspenslo em um bloco tryliatch, como no c6digo anterior.

Vamos alterar o c6digo de Fred, Lucy e Ricky usando a suspenslo para tentdrforgar os treads a se alternarem, em vezde.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" ) ;

^no cl-arf/1.

l-r^rn q|- :rl- I l .

l-hrao qi-arl-/\.

)

A execu$o desse c6digo exibiriFred, Lurye Rickyse alternando de maneiraadequada

t java ManyNames

Run by Fred

Run by Lucy

Run by Fred

Run by Lucy

Run by Ricky

Run by Fred

Run by Lucy

Pr rn h\/ P i ^L\/

Page 422: Java - Scjp 5 - Portugues

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. Emoutras palavras, se houver dois treads ativos no pool execut6vel, voc6 nio ter6 como saber com certeza se o que

nXo foi usado por riltimo ser6 o selecionado para execugio. Ainda asim, usar sLeep ( ) i a melhor maneira de tentarfaryr

clm que todos osireads tenbam a chance de serent executados!Ou, pelo menos, de garantir que um tread nlo entre em

execugio, e assim permanega atd sua conclusio. Quando vm tre^d encontrar uma chamada de suspensio, teri que

ficar suspenso pelo menos durante o periodo especificado em milissegundos (a menos que seja interrompido antes de

sua hora de deipertar, caso em que langari imediatamente a exceElo InterruptedException).

OBSERVAQAO pene EXAME

Sd porque o miitodo sleep ( ) do thread expirou e drpoit desperloa, n6o signtfca qae retomari ao estado de exuapdo! L,erabre-se de que

quando um thread d despertado simplesmente retorna a0 estado executduel. Portanto, o tempo especifcado em sl-eep ( ) ser,l o periodo

nfuimo durante o qua/ o lhread nio rcrd exuutado, mas nio seni operiodo tota/ durante o qua/ o thread ndo executari. De modo que uoc6

nio pode, por exenplo, confar no mdtodo sl-eep ( ) nno un tinerpfeitanma prcciso. Embom em naias @litatiws usm sl-eep ( )

nmotimerselasr.{uimtenmteadequada,mdprvcisasaberqaeotenpoespafuadanestemdtodo ndo d amagarantia de que o thread comeganl a ser

executado iouamente logo q*i ptriodo ixpirar e o tiread dupertar.

NXo se esquega de que s l eep ( ) 6 um m6todo estitico, portanto, nio se engane achando que um tread pode colocaroutronoeltadodeiuspensio.Voc€podeinseriroc6drgodesleep( )emqualquerlocal,j|quet0d0oc6digoser6executado po r alguntread. Quando o c6digo que estiver sendo executado (o que significa o c6digo do tread que estiversendo 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 suspenseoNeste exercicio criaremos um tread de contagem simples. Ele contar6 at6I}},fazendo uma pausa de um segundo antes de

cada nrimero. Al6m disso, continuando com o tema da contagem, ele exibir6uma st ingacadadeznimeros.

1. Crie uma classe e estenda Thread. Como alternativa, vocA pode implementar a interface Runnable.

2. Sobrescreva o m6todo run ( ) de Thread. E ai que entrari o c6digo que exibir6 os nrimeros.

3. Crie um loop for que seja executado 100 vezes. IJse a operagio de resto para verificar a exist6ncia de algumnrimero que seja o resto da divisio por 10.

4. Use o m6todo static Thread. sleep ( ) para f.azer uma pausa. lJm mimero do tipo long representar6os milissegundos.

Prioridade dos threads e o m6todo yield

Para entender yield ( ) , voc6 teri que compreender o conceito das prioridadu dos treads. Os treads sempre sioexecutados com algum nivel de prioridade, geralmente representado por um nrimero entre 1 e 10 (embora em alguns casoso intervalo seja menor que 1O). O agendador da maioria dosJVMs usa o agendamento prwmptiuo com base enpioidadu (oque implica algum tipo de divisio do tempo). Isso nio signfica qae todos os Jl/Ms unm a diuisdo do tempo. A, especificagio JVMnio imp6e ao VM a implementagio de um agendandor com divisio do tempo, onde seja aloc ado para cadatread umperiodo adequado e, em seguida, ele seja retornado para o estado executivel, dando oportunidade para outro tread serexecutado. Embora muitos JVMs realmente usem a divisio de tempo, outros podem usar um agendador que permita aum 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 umtread entra no estado executSvel e tem prioridade maior do que os outros treads do pool e do que o tread que e$A sendoexecutado, o tbreatl sendo executado cowprioridade nenorgeralmente i retornadopara o estado executduel e o de maiorpioridade iselecionado para exnugdo. Melhor dizendo, 6 comum o tread sendo executado nio ter uma prioridade menor do que os dopool. O thread que estiuer rcndo pmcetndo teni prioridade tgaal ou maior do qae a prioridade ntais aha dos tbreads do pool.Isso 6 a coisamais pr6xima de uma garantia que voc0 obteri da especificagioJVM; portanto, nunca poder6 confiar nas prioridades dostreads 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 igarantido, 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 treadsendo executado tem a mesma prioridade dos treads do pool. Se todas as prioridades forem iguais, aimplementagXo do agendador que a JVM usar poder6 fazer simplesmente o que quiser. Isso significa que umagendador pode executar uma das ag6es a seguir (entre outras coisas):

Page 423: Java - Scjp 5 - Portugues

rT

JAVA 5 397

Selecionar a execugio de um tread mantendo-o assim at6 que seja bloqueado ou conclua seu m6todo run ( ) ;

dividir o tempo dos treads do pool para dar a todos uma opoftunidade igual de execugio.

Configurando a prioridade de um tread O tread receberi uma prioridade padrio que ser6 igual a do tread deexecugio que o criou. Por exemplo, no c6digo

public class TestThreads {

pubfic static void main (String [] args) {

MyThread t = newMyThreado;

J

O tread referenciado por t teri a mesma prioridade do tread main ( ) , ji que esse esti executando o c6digo que cria ainsAnciadeMyThread

VocAtamb6mpodeconfiguraraprioridadedeumtreaddiretamentechamandoom6todosetpriority( )emumainstAncia de Thread. como vemos abaixo:

FooRunnable r = new FooRunnableO ;

Thread t = new Thread(r);t- <of Dvi nri rrr t a ).*-.'-J

'',;

t.start O ;

As prioridades sio configuradas com o uso de um inteiro positivo, geralmente entre 1 e 10, e a JVM nunca alterar6a prioridade de um tread. No entanto, valores de 1 a 10 nio sio garantidos. Alguns JVMs podem nio reconhecerdez 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 sendoexecutado em um JVM que aloque um intervalo com somente cinco prioridades, entlo, dois ou mais treads podemser mapeados para uma prioridade.

Embora apioridadepadrio t/a 5, a classe Thread possui trAs constantes (variiveis static f inal), as quais definemo intervalo das prioridades dos treads:

Thread.MIN_PRIORITY (1)

Thread.NORM_PRIORITY ( 5)

Thread. MAX_PRIORITY ( 110 )

O mdtodo yield( ) Mas o que o m6todo static Thread. yield ( ) tem a ver com tudo isso? Nio muito, napr6tica. O que yield ( ) fuuefazer |retornar o tread sendo executado para o estado executivel, a fim de permitir queoutrostreadscomanermaprioridadetenhamsuaoportunidadedeserprocessados.Portanto,afinalidade6usaryield( )

parapromoverum agendamento sofisticado de opornrnidades entre treads de prioridades iguais. Na verdade, o m6todoyield ( ) nlo garantefazer o que deveria, e mesmo se realmentefrzer com que um tread saia do estado de execugioretornando para o estado execut6vel, ndo hd gmantia deque o tread que ceder seu espago seja selecionado novamente entretodos os outros! De modo que, embora yieldQ possa - e geralmente o faz - fazer comque o tread sendo executado ceda

seu espago para outro tread execut6vel com a mesma prioridade, nlo h6 garantias.

Um yield ( ) nunca faz um thread entrar no estado espera/bloqueio/suspensio. O miximo que pode acontecer 6

yield ( ) fazerumthread passar de executado para executivel, mas, novarnente, ele pode tamb6m nio ter efeito nenhum.

O m6todo join( )Om6todonio-static join( )daclasseThreadpermitequeumtread"sejaadicionadoaofinaldeoutrotread".Sevoc6 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 noestado 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 treadprincipal) e o adiciona ao final do tread referenciado por t. Isso impede que o thread atual se torne execut6vel antes que othreadreferenciado 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 tamb6mpode chamar uma das vers6es sobrecarregadas do m6todo j oin ( ) que usa a duragio do tempo de espera, de modoque voc6 diga: "Espere at6 que o thread r seja concluido, mas se ele demorar mais de 5.000 milissegundos, interrompaa espera e se torne executivel assim mesmo". A Figura 9-3 mostra o efeito do m6todo j oin ( ) .

Page 424: Java - Scjp 5 - Portugues

398 Copftulo 9: Threods

At6 agora, examinamos tr6s maneiras pelas quais um thread sendo executado pode sair do estado de execugio:

I Uma chamada a sleep ( )

Garante f.azer comque o thread atual interrompa a execugio, ao menos durante o periodo especificado para a

suspenslo (embora possa ser interompido antes do temPo especificado)'

I Uma chamada a yield ( )

Nio garante muito, embora normalmente faga com que o thread sendo executado retorne ao estado executevel'

a fim de que outro thread com a mesma prioridade possa ter uma chance.

I Uma chamadaa join( )

Garante f.azer com que o thread atual pare de ser executado at6 que o thread ao qual foi adicionado (em outraspalavras, o thread no qual wait ( ) foi chamado) seja concluido. Se o thread no qual for adicionado estiverinativo, no entanto, o thread atual nio ter{ que retornar ao estado executevel.

Al6m desses tr6s, tamb6m temos os cen6rios a seguir, nos quais um thread pode sair do estado de execuglo:

I Se o m6todo run ( ) do thread for concluido (6bvio).

I Com uma chamada a wait ( ) em um obieto (nio chamamos wait ( ) em um tbread, como veremos em

breve).

I Quando um thread nio consegui r o bkq*eio do objeto cujo c6digo do m6todo estiver tentando executar.

I O agendador do thread pode decidir passar o thread atual do estado executado paru execut|vel, para permitirque outro thread tenha a chance de rodar. Nio 6 preciso nenhum motivo - o agendador do thread pode fazeressas trocas da maneira que desejar.

Principais eventos noc6digo do thread

Thread b = new Thread(aRunnable);b. start O t

r'/Os Threads v6m e voltamPilha A esti

sendoexecutacar*-_:l

;lt1] a"ottero Ii"lilLI

Pilha B estisenoo

executaoa

//Thread B finaliza !!//Thread A inicia novamencer

Pilha A

Figuro 9-3 O m6fodo join( )

Saida

A is runningn l- --.-'*i--A !r ! urlrrlrv

^ {D rurllruga ic rrrnninna ic nrnninaA ic rrrnninaA ic rilnhihdP ic rrrnrinaR ic nrnnindA ic nrnninnR ic vrrnninnA ie rrrnninnA ic rrrnhinnE i- *,--i--! +r r s4rf rrgR ic rrlnhi-dA ic rrrnrinnn i< -,rrninaA ic nrnhiaftR ic nrnnincR ic rirnnindR ic rrrnninnR ic firnhindR ic rrrnninaR ie rr:nninaR ic rrrnninnR ic rrrnniA ic rrrnaiA ic n:nninaA ie rrrnniraA ic nrnnincI ie rrrnninaA ic .1,hnin^

//A-iilnfa-sc ao finaf//de B

f-*--ttiI aosturQ

iilPilha A estii

""';lo;u

Pilha B rtldood'e4l

i___,1

i dostuf0 i

'a ---,JPilha Aunida i

Pilha B

Obietivo poro o certificocdo

Sincronizando o c6digo (Objetivo 4.3 do exame)4,i Dado am cendio, escreuer cddigo quefapa 0 utt @rlpriadr do bloqaeio de objetos para proteger uaidueis utiticat ou de instdncias de

prob/emas referentes a dcesso simultineo.

Page 425: Java - Scjp 5 - Portugues

JAVA 5 399

Voc€ consegue imaginar o problema que pode ocorrer quando dois threads diferentes com acesso ) mesmainstincia de uma classe chamarem m6todos nesse objeto, e esses m6todos alterarem o estado do obieto? Em outraspalavras, o que pode acontecer se doisthreads diferentes chamarem, digamos, um m6todo configurador no nermyobjeto? Um cenirio como esse pode corromper o estado de um objeto (alterando os valores delua vari6vel deinstAncia de maneira inconsistente) e se o seu estado compartilhar dados com outras parres do programa, bem, 6horrivel demais at6 mesmo paravisualizar.

Mas s6 porque gostamos de terror, examinaremos um exemplo do que pode acontecer. O c6digo a seguirdemonstra 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 duaspessoas 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 niofique extenso, essa conta comegari com um saldo igual a 50 e s6 poder6 ser usada para retiradas. A retirada ser6aceita mesmo se nio houver bastante dinheiro na conta para cobri-la. A conta simplesmente rcrL o saldo reduzidoda quantidade que voc6 quiser retirar:

^l -^^ l^^^,,-! rufa-D 6LLUUIrL I

private int. balance = 50;

pubfic int getBalance ( ) {

return balance;

]

public void withdraw(int amount) {

bafance = bafance - amounLt

)

]

Agora 6 que vai ficar divenido. Imagine um casal, Fred e Lucy, os dois com acesso ) conta e querendo fazerretiradas. Mas eles nio querem exceder o saldo, portanto, antes de fazerem uma retirada, ele ou ela primeiroverifica o saldo, a fim de ter certeza de que hi o bastante como cobenura. Al6m disso, as retiradas slo semprelimitadas a uma quantia igual a 10, de modo que deve haver pelo menos esse valor no saldo da conta para que umaretirada seja feita. Parece simples. Mas 6 um processo de duas etapas:

1. Verificar o saldo:

2. Se houver o suficiente na conta (nesse exemplo, pelo menos um valor igual a L0),fazer a retirada.

O que aconteceri se algo separar a etapa t da 2? Por exemplo, imagine o que aconteceria se Lucy verificasse osaldo e visse que h6 apenas o valor exato na conta, 10. Mas antes de elafaTer a retirada, Fred wifcasse o saldo e tambtim vireque h,l o bastante para a retirada. J6 que Lucy verificou o saldo, mas ainda nio f.ez sua retirada, Fred est6 vendo "dadosinv6lidos". 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 eleacha 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 objetocontendo uma refer6ncia a somente uma instincia da conta - poftanto, hi dois threads e uma conta.

A l6gica do c6digo de nosso exemplo ser6 a seguinte:

1. O objeto Runnable cont6m a refer6ncia a apenas uma conta.

2. Dois threads slo iniciados, representando Lucy e Fred, e cada um receber6 uma referAncia ao mesmo objetoRunnable (que cont6m uma referAncia i conta real).

3. O saldo inicial da conta 6 de 50, e cada retirada serA exatamente igual a 10.

4. No m6todo run ( ) , percorreremos um loop cinco vezes, e em cada loop:

I Faremos uma retirada (se houver o bastante na conta);

I Exibiremos uma declaraglo se a conta exceder o :aldo (o que nunca deve ocorrer, j6 que verificaremos o saldo antes

de fazer uma retirada).

5. O m6todo makewithdrawal ( ) da classe de teste (representando o comportamento de Fred ou Lucy) faz oseguinte:

Verifica o saldo para saber se hi o bastante para ^retk^d^;

Se houver o ba$ante, exibiri o nome de quem estiver fazendo a 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;

IT

I

Page 426: Java - Scjp 5 - Portugues

400 Copitulo 9: Threoos

I quando sair da suspensio, concluirl a retirada e exibiri que ela foi feita;

I se nlo houver o basranre, exibir6 uma declaragio mostrando quem 6 vocA e o fato de que nio hi dinheirosuficiente.

Porranto, o que esramos realmente tentando descobrir 6 se o seguinte 6 possivel: um s6cio verificar a conta e ver se

hi o bastante, mas antes da retirada real ser feita, o outro s6cio verificar a conta e tambdmver que hi o suficiente.

Quando o saldo da conta chegar a L0, se os dois s6cios o verificarem antes de fazer a retirada, ambos pensario que

esti tudo certo e a conta ficar6 com menos 10!

Aqui est6 o c6digo:

public class AccountDanger implements Runnabl-e {

private Account acct = new Account ( ) ;

public static void main (String [] argrs) {

AccountDanger r = new AccountDanger O ;

Thread one = new Thread(r);Thread two = new fhread(r);one. setName ( "Fred" ) ,'

two . setName ( "Lucy" ) ;one.start();two. start O t

)

public void runO t

for (int x = 0; x < 5; x++) {

makeWithdrawal (10) ;

if (acct.getBal-anceO < 0) {

System.out.println( "account is overdrawn! " ) ;

1

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 osaldo,othreaddeLurydespeftoueconcluiu silaretirad^e,emseguida,Fredconcltiuasua,eelesacabaramportirarmaisdoquepodiam? Veja a saida (numerada):

* i arra A--^rrnt. n:--**------rnger1 l'rad ic anin- f^ rrithArrt.r

Page 427: Java - Scjp 5 - Portugues

JAVA 5 401

2. Lucy is going to withdraw3. Fred completes the withdrawal4. Fred is going to withdraw5. Lucy completes the withdrawal6. Lucy is going to withdraw7. Fred completes the withdrawal8. Fred is going to withdraw9. Lucy completes the withdrawal10. Lucy is goinq to withdraw11. Fred completes the withdrawal12. Not enough in account for Fred to withdraw 0

13. Not enough in account for Fred to withdraw 0

14. Lucy completes the withdrawal15. account i-s overdrawn!

16. Not enough in account for Lucy to withdraw -1017. account is overdrawnl

18. Not enough in account for Lucy to withdraw -10

19. account is overdrawnl

Embora a cada vez que voc6 executar esse c6digo a saida possa ser um pouco diferente, percorreremos esse

exemplo especifico usando as linhas numeradas da saida. Nas primeiras quatro tentativas, tudo est6. correto. Fredverificou o saldo na linha 1 e viu que estava tudo bem. Na linha 2,Lucy verificou o saldo e viu que est6 tudo bem.Na linha 3,Predfez sua retirada. Nesse momento o saldo qtre Lury verificou (e acreditou qtre fosse preciso), na verdade, se

alterou depois da ihima vez qtre foi verificado. E agora Fred est6 verficando o saldo nouamente, antes de Lury concluir sua

primeira rdrada. A essa alrura, Fred tambdm est6 vendo um saldo potencialmente impreciso, porque sabemos que Lury vaiconcluir 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. Nalinha 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 fazeruma retirada. Mas nio sabe que Fred tambdn jti aeifcou o saldo na linha 8, dusaforma, ele acha que d segurofaqer a renradalNalinha 11, Fred conclui a retir^d^ para a qual verificou o saldo na linha 8. Isso levou o saldo a zero, mas Lucy aindatem uma retirada pendente que aprovou na linha 10! Voc€ sabe o que acontecere.

Nas linhas !2 e 13, Fred verficou o saldo e viu que nlo havia o bastante na conta. Connrdo, na linh a I4,Lua7 concluiu sua

retirada e BOOM! A conta agora esi estourada em 10 - algt que athamw qae seria euitada por meio de uma r,wficagdo anterior a uma ntirada

A Figura 94 mostra a linha de tempo do que pode ocorrer quando dois threads acessam simuhaneamente o mesmo objeto.

Tempo

Thread A acessari Obleto 2 somente

Thread B acessari Obleto I e entio o Objeto 2

Figuro 9-4 Problemos do ocesso simulfdneo

Esse problema 6 conhecido como "condigio de corrida", no qual mriltiplos threads podem acessar o mesmo recurso(normalmente as vari6veis de instincia de um objeto), e podem produzir dados corrompidos caso um thread corra"rapido demais" para entrar em aEXo antes que uma operagio que nlo deveria ser interrompida possa finalizar.

Impedindo que o saldo da conta seia excedido Entio, o que pode ser feito? A solugio 6 realmente muito simples.

Page 428: Java - Scjp 5 - Portugues

4O2 Cooitulo 9: Threods

Temos que garantir que as duas aapas da retbada - wrfiatr o saldo e jty a rcr.trada - nunca fiquem separadas. Precisamos que

elas sempre sejam executadas como urna opera$o, mesmo quando o thread entrar em suqpensio entre as etapx I e2l

Chamamos isso de "opera$o at6mica" (embora aqui a fisica esteja um porrco desatualizada, neste caso "at6mico" sigpfica

"indivisivel") porque a operaSo, independente da quantidade de declara6es efetivas (ou insrug6es bytecode zubjacentes),

serS concluida antesdo codigo de qudquer outro tlrread qtre attre sobre os mesmos dados.

Vocd ndo podz garantir que um tinico thread perrzanepa yndo execatado darante toda a operagdo atdmica. Entretanto, pode garantirque mesmo se o thread que estiver processando a opera$o at6mica entrar e sair do estado de execu$o, nenham oahn tbnad smda

execatada prsa ahtm sobrc os mesmos dados. Em outras palavras, se o thread de Lury entrar em zuspensio depois de verificar o saldo,

podemos i-pdit que Fred verifique o sddo anta de o thread de Lucy despenar e concluir sua retirada

E como voc6 protegeria os dados? E preciso fazer duas coisas:

I Marcar as vari6veis com private;

I sincronizar o c6digo que altera as vari6veis.

lembrese de proteger as variiveis de maneira normal usando um modificador de controle de acesso. E o codigo do moodoque voc6 precisa proteger, para qtre so um thread posa exe antA-lo por vez. Faga isso com a palavrachave slmchroni z ed .

Podemos resolver todos os problemas de Fred e Lucy adicionando uma palavra ao c6digo. Marcaremos o m6todomakeWithdrawal ( ) com slmchronized, como vemos abaixo:

private synchronized void makeWithdrawal(int amt) {

if (acct.getBalanceO >= amt) {

System.out.println(Thread. currentThread( ) .getName ( ) +

" is going to withdraw"),'trY {

Thread.sleep(500) ;

) catch(InterruptedException ex) { }

acct.wj-thdraw(amt);

System. out.println (Thread. currentThread ( ) . getName ( ) +

" completes the withdrawal");) else {

System.out.println("Not enough in account for "

+ Thread. currentThread ( ) . getName ( )

+ " to wj-thdraw " + acct.getBalanceO );)

]

Agoragarantimosquequandoumthread(LucyouFred)comegaroprocessoderetirada(chamandornakevvithdrawal( )),o outro thread nlo poderl acessar esse m6todo at6 que o primeiro conclua o processo saindo do m6todo. A nova saidaexibir6 o beneficio da sincronizagio de makewithdrawal ( ) :

I java AccountDanger

Frcd ic ooino 1-^ ldithdraw

Fred completes the withdrawalTrrcw is ooinc to withdraw

Lucy completes the withdrawalFred is going to withdraw

Fred completes the withdrawalLucy is going to withdraw

Lucy compl-etes the withdrawalFred is going to wiLhdraw

Fred completes the withdrawalNot enougfh in account for Lucy

Not enough in account for Fred

to

to

withdraw 0

withdraw 0

Page 429: Java - Scjp 5 - Portugues

JAVA 5 403

Not enough in account for Lucv to withdraw 0

Not enough j-n account for Fred to withdraw 0

Not enough in account for Lucy to withdraw 0

Observe que agora os threads, Lucy e Fred, sempre verificam o saldo da conta e concluem a retirada antes de ooutro thread poder verificar o saldo.

SincronizasAo e bloqueiosComo a sincronizagio funciona? Com bloqueios. Todo objeto em Java possui um bloqueio interno que s6 surgequando 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 esramoserecutando (a instAncia this). A operaEio de adquirir um bloqueio para um objeto tamb6m e conheiida comoobten$o do bloqueio, ou como bloquear o.objeto, on_ bloque ar no obj*o,ou sincronizar no objeto. Poderemos usar tamMmo termo monitor para nos referirmos ao objao cujo bloqueio estamos adquirindo. Tecnicamente, o bloqueio e o monitor sloduas coisas diferentes, mas a maioria das pessoas fala deles como se fossem a me$na cois4 e faremos o mesmo.

J6 que s6 h6 um bloqueio por objeto, se um thread usar o bloqueio, nenhum outro poder6 acessar o c6digosincronizado at6 que o bloqueio seja liberado. Isso significa que nenhum outro thread pode entrar no c6digo desincronizagXo (o que significa que nio pode entrar em nenhum m6todo sincronizado desse objeto) at6 que obloqueio tenha sido liberado. Normdmente, a liberagio de um bloqueio significa que o thread que o estAmantendo (em outras palavrx, o thread que est6 anulmente no m6todo sincronizado) sairi do m6todo sincronizado. Nessemomento, o bloqueio 6liberado at6 que algum outro thread entre em um m6todo sincronizado nesse objao.

VocA precisa lembrar dos seguintes pontos-chave sobre bloqueio e sincronizagio:

I 56 os ndtodos podem ser slmchronized, as variiveis, nio.

I Cada objeto possui apenas anbloqueio.

I Nen todot ot mdtodos de ama classe deuem ser sincroniqados.IJma classe pode ter tanto m6todos sincronizados quantonio-slmchroni zed.

I Se dois threads estiverem prestes a executar um m6todo slmchronized em uma classe, e ambos os threadsestiverem usando a mesma instAncia & classe para chamar o m6todo. somente um thread poder6 executar o m6todo decadavez.O outro teri de esperar at6 qu. o pri-.iro termine a sua chamada. Em outras piavras, quando um thread usaro bloqueio de um objeto, nenhum outro thread poderi acessar quaQaerdos m6todos sincronizados dessa classe(referentes a esse objeto).

I Seumaclassetivertantom6todosslmchronized quantonio-slmchronized, udriostbreahpodrrdoacessaros

mitodos nlo-symchronized da classe! Se houver m6todos que nio acessem os dados que voc6 esti tentando proteger,entXo, nio ser6 preciso marci-los como sincronizados. A sincronizaglo tem um impacto no dcsempenho (ou pode at6

cansar um impasse se usada incorretamente), ponanto, 6 melhor nio usi-la sem uma b oarozilo.

I St o, thread enhar em suspensdo, e/e mantdm os vus b/oqueiot - nio ot /ibera.

I Othreadpodeasarmaisdearzbloqaeio.Porexemplo,othreadpodeacessarumm6todoslmchronized,obtendoassim 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 mesmoobjeto, nio haveri problemas. A JVM saberd que esse thread ji possui o bloqueio desse objeto, portanto, elepoder6 chamar outros m6todos synchronized no mesmo objeto, usando o bloqueio que j6 possui.

I Voed Pode sincroniqar um bloco de cddigo em ueqde am nitodo.

li que a sincronizagio prejudica a concorr€ncia, 6 melhor nlo sincronizar nenhum outro c6digo al6m dosnecess6rios para proteger seus dados. Portanto, se o escopo de um m6todo for maior do que deveria, voc6 poder6reduzir o escopo da parte sincronizada para algo menor do que um m6todo completo - para apen s um bloqueio.Chamamos isso, por mais estranho que parega, de "bloco sincronizado", e seu formato 6 o seguinte:

nlacc q1m^rF6cf I

Psvrrv (

System. out.println ( "not slmchronized" ) ;

slmchronized(this) {

System, out . println ( " slmchronized" ) ;

]

Page 430: Java - Scjp 5 - Portugues

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 quepode 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 tantovoc6 poder6, por exemplo., empregar alguniobjeto.de terceiroipara bloquear essi trecho de codigo.,kso lheproporcronari o r.c.rr* de teimais de um bloqueio para a sincionizagio de c6digos dentro de um rinico obieto.

Ou voc6 pode sincronizar na instAncia atual (ttris), como no c6digo acima. (Jma vez que 6 a mesma instAncia emque os m6todos slmchronized bloqueiam, isso significa que voc6 pode sempre substituir um m6todo slm-chronized por um nio-slmchr onized, que contenha um bloco slmchronized. Em outras palavras, isto:

public synchronized void dostuff O {

System. out.println ( "slmchronized" ) ;

]

6 equivalente a isto:

public void doStuff ( ) {

slmchronized (this ) {

System. out . println ( " slmchronized" ) ;

]

Ambos esses m6todos t6m exatamente o mesmo efeito, na prhtica. Os bltecodes compilados poderlo nio serexatamente os mesmos para os dois m6todos, mas poderiam ser - e quaisquer diferengas existentes nlo sioimportantes. A primeira forma 6 mais curta e mais familiar para a maioria das pessoas, mas a segunda pode sermais 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 paraa sincronizaSo de m6todos estiticos - um bloqueio para tda a classe. Existe um bloqgeio assim; toda classe carregada em

Java possui uma insrAncia correspondente de,iava.lang.Class esa classe. E essa instincia de java.lang.Class cujobloqueio ser6 usado para proteger m6todos static da classe (se eles forem slmchronized). Nlo hi nada especial quesejapreciso fazer parasincronizar um m6todo static:

public static slmchronized void getcount ( ) {

return count;

)

Novamente, isso poderia ser substituido por c6digo que use um bloco slmchronized. Se o m6todo for definidoem uma classe chamada MyClass, o c6digo equivalente 6 o seguinte:

^'lh] ;^ rf-f;^.int- noft-nrrnf l\ JPulrIL >LdUfL Irru VEuevurrL\/ \

srmchrnni zcd(MttCl aqq nlacq\ IL

,

t"artt count;

)

Espere, que hist6ria 6 essa de MyClass.class? Isso se chama literal de classe. Trata-se de um recurso especial dalinguagem Java que diz ao compilador (que por sua vez diz ) JVM): 'encontre para mim a instAncia de Class querepresente a classe chamada MyClass." Voc6 tamb6m pode fazer isso com o seguinte c6digo:

public static void classMethodO {

Class c1 = Class.forName("MvClass") ;

slmchronized (cl) {

/ / faz alqo

]

)

Entretanto, essa verseo 6 mais longa, mais complexa e, o mais importante de tudo, nlo cai no exame SCJP. Mas 6

f6cil e ripido usar um literal de classe - basta escrever o nome da classe e adicionar . class ao final. Nio 6

preciso usar aspas. Agora voc6 tem uma expressio para o objeto Class que precisa sincronizar.

Page 431: Java - Scjp 5 - Portugues

JAVA 5 405

Exercfcio 9-2

Sincronizando um bloco de c6digoNeste exercicio tentaremos sincronizar um bloco de c6digo. Dentro desse bloco obteremos o bloqueio de umobjeto Para que outros threads nio possam altera-lo enquanto o bloco de c6digo estiver sendo executado.Criaremos tr6s threads, todos tentando manipular o mesmo objeto. Cada thread exibir6 a mesma letra 1OO vezes e,em seguida, a exibigio passar6 para a pr6xima letra. IJsaremos um objeto StringBuffer.

Poderiamos executar a sincronizagio em um objeto String, mas as strings nio podem ser alteradas depois que siocriadas, Portanto, nio poderiamos passar para a pr6xima letra sem gerar um novo objeto String. A saida finaldeveriter 100 As, 100Bs e 100 Cs, tudo na mesma linha.

1. Crie a classe e estenda Thread.

2. Sobrescreva o m6todo run ( ) de Thread. E ai que entrarS,o bloco de c6digo slmchronized..3. Para que nossos tr6s threads companilhem o mesmo objeto, teremos que criar um constnrtor que aceite um

objeto StringBuffer no argumento.

4. O bloco de c6digo slmchronized obter6 um bloqueio do objeto StringBuffer na etapa 3.

5. Dentro do bloco, exiba o objeto StringBuffer 100 vezes e, em seguida, passe para a letra seguinte. VocA podeconsultar 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, geretr6s 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 elefoi inpedido de obter o bloqaeio de un objeto. Essencialmente, o thread entrari em um tipo de pool desse objeto especifco e ter|que aguardar at6 que o bloqueio seja liberado e ele possa novamente passar para o estado executlvel/em execuEeo.No entanto, s6 porque um bloqueio foi liberado nio significa que algum thread especifico iri usilo. Pode havertr6s threads aguardando um rinico bloqueio, por exemplo, e nlo h6 garantias de que o thread que esteja esperandoh6 mais tempo seri o primeiro a obter esse bloqueio.

Ao se considerar o impedimento, 6 importante prestar atengio a quais objetos estio sendo usados para o bloqueio.

r Threads qtre chamam m6todos que nio sejam static slmchronized. da mesma classe so bloquearto uns aos outrosse forem chamados usandose a mesma insdncia. Isso ocorre porque cada um deles bloqueia na instAncia this, e, se

forem chamados usandose duas irstAncias diferentes, eles receberXo dois bloqueios, qlre neo interferem um com o outro.

I Threads que chamam m6todos static slmchroni zed da mesma classe sempre bloqueario uns aos outros- todos eles bloqueiam na mesma instAncia de Class.

I Um m6todo st,atic slmchronized e um que nio seja static slmchronized nunca bloqueario umao outro, jamais. O m6todo static bloqueia em uma instincia de Class, enquanto que o m6todo nio-static bloqueia na instincia this - essas ag6es nXo interferem umas com as outras de forma nenhuma.

lPara blocos slmchronized, voc6 precisa observar exatamente qual obieto foi usado para o blogueio. (O queest6 dentro dos par6nteses, depois da palavra slmchronized?) Threads que sincronizem no mesmo objetobloqueario umas )s outras. Threads que sincronizem em objetos diferentes nio o fard.o.

A Tabela 9-1 lista os m6todos relacionados a threads e se o thread abre mio de seus bloqueios como resultado da chamada.

Tobelo 9-l Metodos e o sfofus do b/oqueio

Abrem mlo do bloqueio Mant€m o bloqueio Classe que define o mdtodo

notify ( ) (Embora o thread provavelmente j ava. lang. Obj ectsaia do c6digo sincronizado depoisdessa chamada. Portanto, abrM mlodobloqueio)

wd,r \- \ )

yield( ) j ava. 1angr. Thread

inin/ I java. lang. Thread

sleep ( ) j ava . lang. Thread

Page 432: Java - Scjp 5 - Portugues

406 Copitulo 9: Threods

Entio, Quando Eu Preciso Sincronizar?A sincronizaglo pode ficar bem complicada, e voc6 pode estar se perguntando.pgr que iria.querer se dar a esse

trabalho, ,r-i lrei q,re pode evitiJo. Mas lembre-se do exemplo antes de "condigio de corrida" , com Lucy e

Fred fazendo r"qnei di conta deles. Quando usamos threads, normalmente precisamos usar alguma

sincronizagio em algum lugar para nos certificarmos de que nossos m6todos nio ir6o interromper uns aos

outros t" hor" "rr^i^,bag;ng""d"

os nossos dados. Geralmente, sempre que mais de um thread estiveracessando 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, voc6precisa se preocupar com campos itatic e nio-static, caso eles contenham dados que possam ser

modificados.

Para dados modific6veis em um campo nlo-static, voc6 normalmente usar6 um m6todo nlo-static para _

acess6-los. Sincronizando o m6todo, voc6 garante que quaisquer threads que tentem executar esse mdtodo usando

a mesma instAncia serio impedidos de ter.m "cesso

simultAneo. Mas um ihread que esteja trabalhando com umainstAncia diferente nio serlifetado, porque esti adquirindo um bloqueio na outra instAncia. E isso o quequeremos - que os threads trabalhanio .bm or mesrnos dados tenham de atuar um de cadavez, mas threadstrabalhando 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. Enovam ente, sincron)zando o m6todo, voc6 garante que quaisquer dois threads que tentem acessar os dados serioimpedidos de ter acesso simultAneo, porque-ambos os threadsterlo de adquirir bloqueios no objeto Class para a classe emque o m6todo static est6 definido. Novamente, 6 isso o que queremos.

Entretanto-esevoc6tiverumm6todonio-st.atic queacessaumcampostatic?Ouumm6todostatic.queacessaumcamponio-static (usandoumainstAncia)?Nessescasos,ascoisascomegamafrcarcomplicadasbemrhpido,e h6 uma boa chance de elas nio funcionarem da maneira que voc6 deseja. Se voc6 tem um m6todo static acessando

um campo nio-static, e sincronizar o m6todo, voc€ adquire um bloqueio no objeto Class. Mas e se houver um outrom6todo.que tamb6m acesse 9:ampg nio-static, desta vez usando um m6todo nio.static? Ele provavelmentesrlcromzanainstAnciaatual(this).Lembre-sedequeumm6todostatic slmchronizedeumqueniosejastat.ic slmchronizedniobloquearioumaooutro-elespodemrodaraomesmotempo.Deformasemelhante,sevoc6acessarumcampostatic.rsandoumm6todonio-est6tico,doisthreadspodemchit-rrr.m6todousandoduas instAncias diferentis de this. O que significa que nXo bloqueario um ao outro, porque estario usando bloqueiosdiferentes. O que significa que dois threads estio acessando simultaneamente o mesmo campo sLatic - exatamente otipo de coisa que estamos tentando impedir.

Fica muito confuso tentar imaginar todas as coisas estranhas que podem acontecer aqui. Para manter a simplicidade:para tornar uma classe segura no que diz respeito a threads, os m6todos que acessam campos modificiveis precisamser slmchroni-zed.O acetso a campos utdticos deue nrfeito apartir dc mdtodw stat.ic slmchroni zed. O acesso a campos ndo-esL6ticosdeue rerfeito apartir de ndtodos que ndo s/an sLatic slmchronized. Por exemplo:

public class Thing {

nrirra|-a cl-aFi^ inf <i:l-iaFia]A.

nri rzaf o i ht n^nql- af i .E i al .1 .

public static slmchronized int getstaticFieldO {

return staticField;]public static slmchronized void setstaticField(

int staticField)Thinq.staticField = staticField;

)

public slmchronized int qetNonstaticFieldO {

return nonstaticField;]

public symchronized void setNonstaticFj-eld (

int nonstaticField) {

this.nonstaticField = nonstaticField;

Page 433: Java - Scjp 5 - Portugues

JAVA 5 407

E se voc6 precisar acessar tanto campos static quanto nlo-static em um m6todo? Bem, existem maneirasde se fazer isso, mas esti.al6m do que voc6 precisa para o exame. Vocd viver6 uma vida mais longa e feliz sesinplesnente ndofryr isn. S6rio mesmo. N6s mentiriamos para voc6?

Classes Seguras em Relag6o a ThreadsQuando uma classe foi cuidadosamente sincroniz-adapara proteger os seus dados (usando-se as regras que acabamos deaPresentar, ou usando alternativas mais complicadas), dizemos que a classe 6 "segura em relagio aoi thtr"d.". Muitas classesnas APIsJava j6 usam a sincronizagio internamente para tomar i classe "segura". Por exemplb, String$uffer e StringBuildersio 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-bientemultithread enquanto Strin-gBuilder nio 6. @or outro lado, StringBuilder 6 um-pouco mais ripida, porque nio precisa sepreocupar com a sincroniza$o)

Entretanto,_mesmo.quando uma classe for "segura", na maioria dos casos 6 perigoso confiar nessas classes para fornecera protegio de thread que voc6 precisa. (Ora, o fato de usarmos repetidamente aspas em torno de "segura" tinha designificar algo, nlo?) Voc6 ainda precisa pensar com cuidado sobre como usar6 eisas classes. Como um exemplo,considere a seguinte classe.

import java.util.*;public class Namelist {

private List names = Collections.slmchronizedlist(nar.r T.i nlra^r.i cf r \ ) ;

public void add(String name) {

narnes. add (name) ;

)

public String removeFirst ( ) {

if (names.sizeO > 0)

return (String) names.remove (0) ;

else

return nuI1;

)

O m6todo Collections. synchronizedlist ( ) retorna um List cujos m6todos estao todos sincronizados e

"seguros", de acordo com a documentagXo (como um Vector - mas, uma vez que estamos no s6culo XXI, nXo iremosusar um Vector aqui). A questio 6, a classe Namelist pode ser usada de forma segura a partir de mriltiplos threads? Etentador pensar que sim; uma vez que os dados em names e$ao em um conjunto sincronizado, a classe Namelist tamb6m6 "segura". Entretanto, nio 6 o caso - o m6todo removeFirst ( ) pode, is vezes, langar umaNoSuchElementException. 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 usarNamelist destaf.orma

public static void main(StringlJ args; 1

final NamelisL n1 = new Namel,ist ( ) ;

n1 . add ( "Ozymandias " ) ;

class NameDropper extends Thread {

public void runo t

St.ring name = n1 .removeFirstO;System. out. println (name) ;

)

)

Thread t1 = new NameDropper ( ) ;

Thread t2 = new NameDroppero;

tl. start O ,-

t2.startO ;

Page 434: Java - Scjp 5 - Portugues

408 Copitulo 9: Threoos

O que. poderia acontecer aqui seria.que um dos threads removeria um name e o exibiria, e depois o outro thread

tenrarra remover,r- nam.l obteriJnull. Se pensarmos apenas nas chamadas a names. size ( ) e

names - get (0 ) , elas ocorrem nesta ordem:

Thread t1 executa names . size ( ), que retorna 1.

Thread t1 executanames . remove (0 ) , que retornaozlzmandias.

Threadt2 executanames. size ( ),queretorna 0.

Thread L2 nio chama remove ( o ) .

A saidaaqui 6

Ozlzmandias

nu11

Entretanto, se executarmos o programa novamente, poderi acontecer algo diferente:

Thread L1 executanames . sizeO, que retorna 1.

Thread t2 executanames . size ( ), que retorna 1.

Thread t1 executa names . remove ( 0 ) , que retorna Ozymandias.

Threadt2 executanames.remove(0),quelangaumaexcegloporquealistaagoraest^vazia.

O que voc6 precisa perceber aqui 6 que, em uma classe "segura" como aquela retornada por synchronizedlistQ, cada m6todoindividualestisinCronizado.Assim,narnes.sizeO est6slmchronized,enames.remove(0)tamb6m.Masnada impede que outro thread faga alguma outra coisa na lista no espago entre essas duas chamadas. E 6 ai que podemocorrerproblemas.

Hiumasolugio aqui: nlo confie em Collections . slmchronizedlist ( ) . Emvez disso, sincronize o c6digovocAmesmo:

imnnrr i=rz: ,rfil *.

public class Namel,ist {

private List names = new r-inkedl,ist ( ) ;

pubfic synchronized void add(String name) {

names.add(name);

]

public synchronized String removeFirst ( )

if (names.sizeO > 0)

return (String) names.remove(0) ;

elseraf rrrn nrrl1 .

J

Agoratodoom6todoremoveFirstO estisincronizado,edepoisqueumthreadoiniciarechamarnames.sizeO,ooutro thread nio poder6 mais interromper e roubar o ultimo name. O outro thread simplesmente teri de esperar at6 que oprimeiro finalize a sua operagXo com o m6todo removeFirst ( ) .

A moral aqui 6 que, s6porqueest6descritacomo "seguraem rela$oatlveads",nioquer dizerqueuma classe 6 sempre segura.

Se m6todos individuais estiverem sincronizados, isso pode nio ser o suficiente - pode seruma solugXo melhorcolocar a

sincronizaqio em um nivel mais alto (ou seja, colociJa no bloco ou m6todo que chama os outros m6todos). Depois que voc6faz 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 threadsficam impedidos de obter um bloqueio, cada um esperando pelo bloqueio do outro. Nenhum deles poderl ser executadoat6 que abram mXo do bloqueio, portanto, aguardario eternamente. Isso poder6 acontecer, por exemplo, quando o thread Achegar a um c6digo slmchroni zed, conseguir o bloqueio B e, em seguida, entrar em oaho m6todo (ainda dentro doc6digo slmchroni zed. parao qual possui o bloqueio) que tamb6m for slmchroni zed. Por6m, o thread A nlopoder4 obter o bloqueio par^ entr^r nesse c6digo slmchroni zed - o bloqueio C - porque outro thread, D, jiest6 com ele. Sendo assim, o thread A ir|, para o pool "de espera do bloqueio C", na esperanga de que o thread D

Page 435: Java - Scjp 5 - Portugues

JAVA 5 4O9

seja breve e o libere (concluindo o m6todo slmchronized). Mas o thread A ter6 que esperar realmente muitol:mpo'.Pgrqle depois que o thread l-) obteve o bloqueio C,.ele entrou em um m6todb slmchronized que usa obloqueio^ B. E.:l?to que o thread D nio conseguiu o bloqueio B, uma vez que o thread ,{ 16 .rt"lr" com ele.'E essethread nio vai liber6lo at6 que o thread D libere o bloqueio C.

Contudo,othreadDnioliberariobloqueioCantesdeobterobloqueioBedarprosseguimento.Eassimpermanecerio. O exemplo a seguir demonstra o impasse:

1. public cl-ass OeadlockRisk {

2. private static class Resource {

3. public int value;4. )

5. private Resource resourceA = new Resource ( ) ;

5- nrirrate ReSO111.Ce reSOUrCeB = new Resorrrce():

7. pubLic int read() {

B. slmchronized(resourceA) { // Pode haver impasse aqui_

9. slmchronized(resourceB) {

10. return resourceB.vafue + resourceA.value;1-r. )

1.2. )

13. )

L4.

15. public void write(inr a, int b) {

16. synchronized(resourceB) t // Pode haver impasse aqui1-'7 . slmchroni zed ( resourceA) {

18. resourceA.value = a;

19. resourceB.value = b;

20. )

21. )

))t

23. \Suponhamos que read ( ) tenha sido iniciado por um thread e write ( ) por outro. JA que temos dois threadsdiferentes que podem ler e gravar independentemente, exise o risco de impasse na linha 8 ou 15. O thread de leitura possuio 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 gravagXoem um ponto especifico e as chances de o impasse ocorrer sio muito pequenas. O aplicativo pode funcionar bem 99,9 porcento do tempo.

Esse exemplo simples 6 f6cil de corrigir; apenas troque a ordem do bloqueio do thread de leitura ou de gravaEio nas linhas16 e 17 (ou nas linhas 8 e 9). Situag6es mais complexas de impasse podem levar muito tempo para serem identificadas.

Independente de serem pequenas as chances de seu c6digo entrar em um impasse, a conclusio 6 t se yoc€ entrar em un impasse,

fcaniparalivdo. H6 abordagens de projeto que podem ajudar a evitar impasses, incluindo estrat6gias de sempre obterbloqueios 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 dosprogramadoresJava.

Obietivo poro o certificoc6o

lnteragio entre os threads (Objetivo 4.4 do exame)4.4 Dado am cenirio, escreuer ctidigo quefapa uto apropriado de wait, notfi ou notfrAll.

O fltimo item que precisamos examinar 6 como os threads podem interagir entre si para comunicar - entre outras coisas -ostatusdeseusbloqueios.AclasseObjectpossuitr6sm6todos-wait( ),notify( ) enotifyAll( )-queajudam os threads a obterem informag6es sobre o status de um evento importante para eles. Por exemplo, se atarela de um thread for a distribuigio de correspondAncia, e a de outro for o processamento de corresponddncia,

Page 436: Java - Scjp 5 - Portugues

410 Copitulo 9: Threods

este riltimo thread teri que verificar continuamente se hi alguma correspondOncia aprocessar. Usando o

mecanismo de espera (l'"ir) . notificaglo (notify), ele poderia procurar a correspond6ncia, e se nio encontrasse

nenhuma dizerr ;Ora,'nlo vou perder-meu tempo proiurando-correspond6nciai a cada dois segundos. Vou ficarpor aqui, e quando o distribuidbr de correspond6niia colocaralgo nacaixa de correio, farei com que ele me avise'

Assim, .n posso voltar ao estado execut ivel e f.azer meu trabalho". Em outras palavras, os m6todos wai t ( ) e

notify ( ) permitem que um thread fique em uma "sala de espera" at6 que algom outro thread o avise

(notifique) de que hi uma r^z1o para voltar ) atividade.

Um ponto a lembrar (e memorizar para o exame) sobre waitlnotify 6 esse:

Os ndtodos waiL ( ) , noti f y ( ) e noti fyA11 ( ) deuen ser chamados de dentn dr um contexto sincmniTado! O thread niopode chamar an mdtodo aait or,t notifi de am objeto a menls que obtenba o bloqueio duse objeto.

Agora apresentaremos um exemplo de dois threads que dependem um do outro para dar prosseguimento a suas tarefas, e

mosrraremos como usarwaiL ( ) e notify ( \ pirafazercom que interajamieguramente e no momento apropriado'

Considere uma m6quina controlada por computador que cone pedagos de tecido em formatos diferentes, e um aplicativoque permita que os usuS.rios especifiquem o formato do cone. A verslo atual do aplicativo possui somente um thread, oq"at pri-.iro solicita ao usuirio instrug6es e, em seguida, direciona o hardware para cortar no formato desejado, repetindoociclo&pois.

public void run ( ) {

while (true) {

/ / Obt6m o formato do usu5ri-o

// Calcula as etapas da m6quina para fazer o formato

/ / Envia as etapas para o hardware

'Esse projeto nlo 6 6timo porque o usuirio nio poder|fazer nada enquanto a miquina estiver ocupada e houver outrosformatos a definir. Precisamos melhorar a situa$o.

Uma solugio simples 6 separar os processos em dois threads diferentes, um deles interagindo com o usuirio e outrogerenciando o hardware. O thread do usu6rio enviar6 as instrug5es para o thread do hardware e, em seguida ,voltarh ainteragir com o usuirio imediatamente. O thread do hardware recebe as instrug6es do thread do usuirio e comega a instruira miquina imediatamente. Os dois threads usam um objeto em comum para se comunicarem, o qual cont6m o projetoatual que est6 sendo processado.

O pseudoc6digo abaixo mostra esse projeto:

public void userloopO {

while (true) {

/ / ObL6m o formato do usu6rio

/ / CaIcuIa as etapas da n6quina para fazer o formato

/ / Modrfica objetos comuns com as novas etapas da m5quina

]

)

public void hardwareloopO {

while (true) {

/ / Obt6m as etapas do objeto comum

/ / Envia as etapas para o hardware

l

Oproblema agora|.fazer comque o threaddo hardware processe as etapas &miquinalogo que estiverem disponiveis.AlSm disso, o lhread do usuirionio deve alter6Jas at6 que todas tenharn sido enviidas paia o hardware. A solugio 6 usarwait ( ) enotify ( ), al6mdesincronizaralgunstiechosde c6digo.

Lembre-sedequeosm6todoswait( ) enotify( ) slom6todosdeinstAnciadeObiect.Damesmamaneiraquetodo objeto poisui um bloqueio, pode haver uma lista de threads aguardando um sinal (uma notificagio) desse objeio. Umthread pode entrar nessa lista com a execugio do m6todo wait ( ) do objeto de desdno. A partir desse momento, ele nioexecutarl nenhuma outra instrugio at6 que o m6todo noti fy ( ) do obieto de destino seia chamado. Se muitos threadse$iverem aguardando no mesmo objeto, somente um seri selecionado (sem uma ordem definida) para prosseguir com suaexecugio. Se nio houver threads esperando, entao, nenhuma agio especifica seri tomada. Examinemos um c6digo real quemo$ra um objeto aguardando que outro o notifique (preste atenglo ji que 6 um pouco complexo):

Page 437: Java - Scjp 5 - Portugues

JAVA 5 411

1. class ThreadA {

2. public static void main(String [] args) {

3. ThreadB b = new ThreadBo;4. b.start0;5.

6 . slmchronized (b) i'7. try {

8. System.out.println("Waiting for b to complete.9. b.wair O ;

10. ] catch (InterruptedBxception e) i)1l-. System.out.println(..Total is: .. + b.total);42. )

l-3. )

L4. )

l_5.

16. class ThreadB extends Thread {I7 . int total;1_8.

19. public void runO {

20. slmchronized(this) i21_. for(int i=0;i<100;i++) {

22. total += i;23. )

24. notifyo;

zo. l

27. j

Esse programa condm dois obfetos com threads. ThreadA cont6m o rhread principal e ThreadB possui um thread ouecalcula a soma de todos os ntmeros de 0 a 99. Logo que a linha 4 chamar o m6todo start ( ) , ihreadA passar6 p'ara apf"ft"Jd* de c6digo de sua pr6pria classe, o qie si-gnifica.que pode chegar ) linha 12 antes que ThreadB concluaieucarcuro. r-ara rmpecur rsso, usamos o metodo wat-t ( ) na lrnha y.

Observe na linha 6 que o c6digo 6 sincronizado com o objeto b; isso porque, para chamarwait ( ) no objero, ThreadAprecisa.do.bloque-iodeb.Paraqueumthreadchamewait( )ounbtity[ ),.1.t.-queseroproprietiriodobloqueio desse objeto,. Quando o thread estiver aguardando, liberar6 temporariamente o bloqueio para outros threadsusarem, masprecisar6dele novamenteparadarpiossegurmento aexecugao. E comum enconirarmbsnm c6digo como osegumte:

slmctrronj-zed(anotherObject) { // este 6 o proprietarj-o do bloqueio em anotherObjecttry {

anotherobject.wait ( ) ,

// o thread libera o bloqueio e espera

/ / Para continuar, o thread precisa do bloqueio,/ / enLdo poder6 ficar bloqueado at6 que o obtenha.

] catch(InterruptedException e) { }

)

O c6digo anterior aguardariat| quLenoti fy ( ) seja chamado em anotherObj ect.swahrorizarl(th) q\ I nnfifrr/\ 1r rrvuflJ\/r J

Esse c6digo notificari qualquer outro que esteja aguardando o obieto this. O bloqueio pode ser obtido bem noinicio do c6digo, por eiemplo, no m6todo chamador. E bom ress;ltar que se o threid qui chamar wai t ( ) niotiver o bloqueio, uma excegXo rllegalMonitorstateException seri langada. Eisa exceglo nio 6 verificada,

Page 438: Java - Scjp 5 - Portugues

412 Copftulo 9: Threods

porranro, voc[ nlo precisa captari-la explicitament". E i*po.tante semPre deixar claro se um thread possui o

bloqueio de um ob.iito em um bloco de c6digo especifico.

Observe nas linhas 7-10 que hi um bloco trylcatctr encapsulando o m6todo wait ( ) . Um thread em esPera

p;jgr.; i"tlri"mpid" di -.rrrr" maneiraqnl. n- thread em suspenslo, portanto, voca ter6 que manipular a

exceglo:

trY{wai_t O ;

) catch(InterruptedException e) {

/ / Faqa alga sobre isso

)

No exemplo do tecido, esses m6todos serio usados parafazer.com que o hardware esPere.que.o formato fique

disponivel e o thread do usu6rio emita uma notificagio depois que is_etapas forem gravadas. As etaPas. da

*6q"itr" podem incluir etapas globais, como mover o tecido requerido para.a 6rea de cone e v6rias subetapas,

como a diregio e o comprimenio de um corte. A titulo de exemplo, elas poderiam ser:

int fabricRoll;int cuttingSpeed;

Point startingPoint,'tloat t I oarecE.lons;

rrvsu L

etc. .

E imponarrte que o thread do usuirio nlo altere as etapas da m6quina enquanto o thread do hardware as estiver,rsando, portanio, essa leitura e gravagS,o devem ser sincronizadas.

O c6digo resultante ter6 esse formato:

public void runO {

while(true) {

/ / ObL6m um formato do usu6rioslmchronized(this) {

// Calcula as novas etapas da m6guina para o formato

notifyO ;

]

iclass Machine extends fhread {

operator operator; // assuma que isso seja iniciali-zadopublic 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 ooperador 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 blocoiincronizado 6que o thread do hardware poder6 realmente iniciar oprocessamento das etapas da m6quina.

Page 439: Java - Scjp 5 - Portugues

JAVA 5 413

Enquanto um formato estiver sendo processado pelo hardware, o usu6rio poder6 interagir com o sistema eespecificar outro_formato para ser cortalo. Quanio o usu6rio tiver terminado o formato-e for hora de con6-lo, othread 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 asetapas da miquina pelas novas.

Ter dois threads 6 definitivamente uma melhoria sobre ter somente um, embora nessa implementagao ainda hajauma 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. Seo thread nio for interrompido,_continuarA sua eiecuglo nor-malment. tJ*p.. que for notificado ou o que 6,.*pode espera especificado expirar. Essa continuagXo comum consiste em sair do eriado de espera, ,rr", p"rl d"i

--r -

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 i t ( ) for chanado em um objeto, o thread que e$iaer executando use aidigo abinl mdo de tea bloqueioimediatamente. I\o entanto, quando noLify ( | for chamado, isso nio txCnifta qae o thread abrird mdo de sea bloqueii na mesma bora.Se o thread ainda eftiuer concluindo o ctidigo sincroniqado, o bloqaeio ndo seni liberado atd que ele saia duse nidtgo. Portanto, sri porqueno t i fy ( ) foi chamado nio signtfca que o bloqueio se tornani disponiuel nesse mlmentl.

4.q

1-0 .

11

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

Na maioria dos cenarios, 6 preferivel notifi car todls osthreads que estiverem esperando por um objeto especifico. Se issoacontecer, voc6 poder6 usar notifyAll ( ) no objeto pira permitir que todosbs threadi saiam da lrea de esperae 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 ser6usado 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 ( ) afetaritaPenas ym deles. Qual e*atamente nio ser6 especificado e depender6 da implementagio da JVM, porranro, voc6nunca deve confiar que determinado thread ser6 notificado no lugar de outro.

Nos casos em que podemos ter muitos threads esperando, a melhor maneira 6 usar noti fyAll ( ) .

Examinaremos isso em um c6digo. Nesse exemplo, h6 uma classe que a(ecuta um calculo e muitos threads de leitura queestio esperando para receber o c6lcrrlo concluido. Em algum momento, muitos *reads & leitura podedo estar esperando.

1. class Reader extends Thread {2. Calcu]ator c;

nrrl-r'l i c Raarlor /l-: l nrrl ^f ^r ^il ^l I

c = cafc,.

6. )

7.

8. publ-ic void runO {

crmnhrnni zaAlr\ t

j-rrr I

Qrr<fpm nrrl- nrini- ln/.'T^7^if ina fnr nalnrrl:f inn x\eJ v eurrL. \ vvqr Lf rrv Lf vrr. r r / ,

L2. n rrr:ifl\.

Page 440: Java - Scjp 5 - Portugues

414 Copitulo 9: Threods

l-3. ) catch (InterruptedException e) {i1,4. ]

l-5. System.out.println("Total is: " + c.total);

I7'18. public static void mai-n(String [] args) {

t9 . Cal-cul-ator calculator = new Calculator ( ) ;

20. new Reader(calculator) .startO ;

2L. new Reader(calculator) .startO ;

22. new Reader (calculator) . start ( ) ;

23. calculator.startO;24. )

25. j

26.

27 . class Calculat.or ext.ends Thread {

28. int total;29,

30. public void run0 {

31 . slmchronized (this ) {

32. for(int i=0;i<100;i++) {

33. total += i;34. ]

35. notifyAll O ;

36. )

3'7. )

38. )

Esse programainida tr6s threads, todos esperando para receber o cilculo concluido (linhas 18-2a), e depois inicia a

calcuiadJra e a sua tarefa. Observe qn. r. o m6todo run ( ) da linha 30 usasse notify ( ) em vez de notifyAll (

) , somente um thread de leitura seria notificado, em vez de todos.

Usando wait( ) em um LoopNa verdade, ambos os exemplos anteriores (Machine/Operator e Reader/Calculator) tinham um mesmo problema. Emambos,haviapelomenosumthreadchamandowaitO,eoutrothreadchamandonotifyO ounotifyAllO.Isso funciona muito bem, desde que os threads na espera rcnham comegado a esperar antes de o outro thread executar

notifyO ounoLifyAllO.Masoqueacontecese,porexemplo,oCdculatorrodarprimeiroechamarnotifyoantes de os Readers terem comeEado a esperar?

Isso poderia acontecer, uma vez que nXo podemos garantir em que ordem as diferentes partes do.thread irio executar.

InfeLmente, quando os Readers rodam, eles comelam a esperar imediatamente. Nlo faznmnadaparaver. se o evento pelo

qualestioespeiandoj6aconteceu.Assim,seoCalculatorjitiverchamadonotifyAll O,nioirAcham|-lonovamente-e os Readers na espera ficario esperando para sempre. Isso provavelmente nXo 6 o que o programador queria que

acontecesse. Quasl sempre, quandovoc6 queresperarporalgo, precisatamb6msercapazdevenficar se o wento j6ocorreu.

Geralmente, a melhor maneira de resolver isso 6 colocar algum tipo de loop que verifique em algum tipo de express6es

condicionais, e espere somente se o evento ainda nio tiver acontecido. Eis uma versio modificada, mais segura, do exemploanterior damiquina cortadora de tecidos:

class Operator extends Thread {Machine machine; // assume que isso seja inicializadopublic void runO {

while (true) {

Shape shape = getshapeFromUserO;

Machinefnstructions -iob =

Page 441: Java - Scjp 5 - Portugues

JAVA 5 415

calculateNewlnstructionsFor ( shape ) ;

machine. add,fob ( j ob) ;

J

O operador continuar6 o loop para sempre, obtendo mais formatos dos usuirios, calorlando novas instn46es para esses

formatos e enviando-os para a miquina. Mas agon al6grca para no t i fy ( ) foi movida para dentro do m6todo add,Job ( )dadasseMachine:

cl-ass Machine extends Thread {

List<Machinelnstructions> i obs =

new Arrayl,ist<Machinefnstructions> ( ) ;

public void addJob(Machinelnstructions job) {

slmchronized (jobs) {

jobs.add(job) ;

jobs.notifyO;

1

public void run0 {

urhila ttrrra\ I

crmnhrnnizod /'inhc\ I

/ / aqnara al- 6 mra no l o/ / veyvre

whil-e ( jobs. isEmpty( ) )

menos um job esteja disponivel{

try {

inl-'c 'uai t 1\

] catch (InterruptedException ie) { }

)

// Se chegarmos aqui, saberemos que jobs ndo est6 vazio

Machinelnstructions instructions = jobs.remove(0),.

/ / Envia as instruq6es da miiquina para o hardware

)

A m6quina mant6m uma lista dos trabalhos agendados. Sempre que um operador adiciona um novo trabalho i lista, ele

chamaom6todoadd.rob O ef.azaadtgio.E'nquantoisso,om6iodorunO continuaoloop,procurandoportrabalhosna lista. Se nio houver nenhum, ele comega a esperar. Se for notificado, iri parar de esperar e irl verificar novamente acondigio do loop: a lista ainda est6 vazia? Na pi6tica, essa verificagio dupla provavelmente nio 6 necessiria, uma vez que ortnico momento em que um noti fy ( ) 6 enviado 6 quando um novo trabalho acabou de ser adicionado i lista.Entretanto, 6 uma bo; id6ia exigir que o thread verifique novamente a condigio i sHrpty ( ) sempre que for reativado,porque 6 possivel que um thread tenha acidentalmente enviado um noti fy ( ) incorretamente.

Existe tamb6m uma situaglo possivel, chamada de reativagio espontenea, que pode existir em algumas situag6es - um threadpodeserreativadomesmoquenenhumc6di.gotenhachamadonotifyO ounotifyAllO.@elomenosnenhumi6Ag" de que voc€ tenha conhecimento. Als vezes aJW poderi chamar notify ( ) po1 raz6es que s6 ele sabe,_ou

programar ilgumas outras chamadas de classes por raz6es desconhecidas) O que isso significa 6 que, quando o seu thread 6

reativado depois de um wai t O , voc6 nlo sabe com ceneza por que motivo ele foi reativado. Ao colocar o m6todo wai t oem um loop whi 1 e e veriiicar novamente a condigio que representa o evento pelo qual estivamos esperando, nos

cenificamosdeque,qualquerquesejaomotivo,voltaremosawaitO se(esomentese) oeventoaindaniotiveracontecido.Na classe Machine, o que e$avamos esperando era que a lista de trabalhos nio estivesse vazia. Se estiver vazia, esperamos; se

nlo estiver, nio esperamos.

Reparetamb6mquetanto o m6todo run ( ) quantoo add.Tob ( ) sincronizamno mesmoobjeto-alistadetrabalhos.Tssoocorrepordoismotivos.Um6queestamoschamandowaitO enotifyO nestainstAncia,entiopfecisamossmcromzar para evlrar uma excegio IllegaiThreadState. O outro motivo 6 que os dados na lista de trabalhos sio

Page 442: Java - Scjp 5 - Portugues

416 Copitulo 9: Threods

modific6veis, e sio armazenados em um campo que 6 acessado por dois threads diferentes. Precisamossincronizar para podermos acessar esses dadoi mbdificiveis de iorma segura. Felizmente, os mesmos blocossincronizador 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 dadosmodificiveis 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 ajobs. add(job) - que modifica dados compartilhados. E o bloco sincronizado em run ( ) 6 grande o suficienteparaincluirtodooloopwhile-queincluiachamadaajobs.isEmptyO,queacessadadoscompartilhados.

Amoraldahist6ria6que,quandousawaitO enotifyO ounotifyAll{),quasesemprevoc6deveterumloop while junto com wait ( ) para verificar uma condigio e forgar a continuagXo da espera at6 que a condigioseja atendida. E vod deve tamb6m usar o requerimento de sincroniza$o para as chamadas await O e notify O , paraproteger tarnb6m quaisquer outros dados que estiver compartilhando entre tfreads. Se vir c6digo que falhe em fazer isso,

normalmente hi algo de errado com o c6digo - mesmo se vod tiver dificuldacles em ver qual 6 exatamente o problema"

OBSERVAQ6BS pene O EXAME

O:ndtodoswaiL( ),notify( )enotifyAll( ) sdonitodotnmentedejaua.lang.Objut,endodejaua.lang.Tltreadoujaua.lang.Rannable. Certfique-se de saber que mritodos sdo defnidu em Tbread, quais sdo en Objut e os de Runnable (sonente ran( ),plftantqesseificil).DosrzitodosprincipaisdeThread,ceftifique-sedesaberquaissdosLaLic -s1eep( )eyield( )- e

quaisndosdo-join( )estart( ).ATabela9-2 listaosmdtodotprincipafuqueuocdprecisaniconltecernoexame,czmosnitodosstatic exibidw em itdlico.

Tobelo 9-2 M6lodos principois dos threods

Classe Obiect ClasseThread Interface Runnable

wait0 staft0 run0

notdyQ jeld( )notifyAll0 tlttp( )

join0

Resumo para a certificagSoEste capinrlo abordou o conhecimento necessirio sobre threads que voc6 precisari aplicar no exame da certificagio. Osthreads podem ser criados pela extensio da classe Thread ou a implementageo da interface Runnable. O rinico m6todoque deve ser sobrescrito na intertace Runnable 6 run ( ) , mas o thread nio se tornarA. um tltread de execugio at6que 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. Voc6aprendeu 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. Noentanto, uma vez em execugXo, o thread pode se tornar inativo, entrar em suspensio, esperar que outro thread sejaconcluido, 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 banc6riade 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 entrethreadsdiferentes,useosm6todoswait ( ),notify( ) enotifyAll ( ).

Aqui estio alguns dos pontos principais de cada objetivo para a certificagio deste Capinrlo. Tire uma c6pia e durma com elesembaixo de seutravesseiro para completar a absorgio.

Criando, instanciando e iniciando novos threads (Objetivo 4.1)0 Os threads podem ser criados pela extensio de Thread e a sobrescrigio do m6todo public void run ( ).B Os objetos dos threads tamb6m podem ser criados com uma chamada ao construtor de Thread que usa um

obieto Runnable como argumento. Diz-se que o objeto Runnable 6, o tlestino do thread.

Exercicios ripidos

Page 443: Java - Scjp 5 - Portugues

oJAVA 5 417

Voc6 pode chamar start ( ) em um objeto Thread somente uma vez. Se start ( )for chamado mais devmavez em um objeto Thread, uma excegio RuntimeException seri langada.

E vilido criar muitos objetos Threadusando o mesmo objeto Runnable como destino.

QuandoumobjaoThreadforcriado,eleniosetomarawntlmaddemug'wxiq:eseum6todostart( )sejacharrudo.

Quando um objeto Thread existe, mas nio foi iniciado, est6 no estado nouo e nXo 6 considendo atiuo.

TransigSo entre os estados dos threads (Objetivo 4.2)E Uma vez que um novo thread for iniciado, ele sempre entrari no estado execut6vel.

E O agendador de threads pode alternar um thread entre os estados execut6vel e de execugio.

D Para uma m6quina tipica, de apenas um processador, s6 um thread pode ser executado por vez, embora muitos possamestar no estado execut6vel.

tr Nio hi garantia de que a ordem na qual os threads foram iniciados determinarl a ordem na qual serio executados.

tr Nio h6 garantia de que os threads terio a chance de ser executados de maneira justa. Isso 6 responsabilidade doagendador, 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 ( ). Issoimpedir6 que up thread domine.o processo sendo executado enquanto o outro estiver aguardando. (Noentanto, na maioria dos casos, yield ( ) funciona bem o suficiente para encorajar os seus threads a

trabalharem bem juntos.)

E Umthreadsendoexecutadopodeentraremumestadobloqueado/deesperaporumachamadaawait( ),s1eep( )

oujoin( ).

D Um thread sendo executado pode entrar em um estado bloqueado/de espera, porque nio p6de obter o bloqueio de

umtrecho de c6digo sincronizado.

E Quando o m6todo wait ou sleep for concluido, ou o bloqueio de um objeto se tornar disponivel, o thread s6 poder6entrar novamente no e$ado executivel. Ele ir6 diretamente da espera para a execuglo (bem, tudo por raz6es pr6ticas).

tr Um thread inativo nio pode ser iniciado novamente.

Sleep, yield e join (Objetivo 4.2)E A suspensio 6 usada para retardar a execugio por um periodo de tempo e nenhum bloqueio seri liberado quando um

thread entrar em suspensio.

E Um thread em suspenslo ficari inativo por pelo menos o tempo especificado no argumento do m6todo s leep ( ) (a

menos que seja interrompido), mas nio h6 garantias de quando o thread rec6mdesperto retornar6 realmente ) execugio.

D O m6todo sleep ( ) 6 um m6todo staEic que suspende o thread que estiver sendo executado. Um thread niopode informar a outro que deve ficar suspenso.

fl O m6todo setpriority ( ) 6 usado em objetos Thread para dar aos threads um n(vel de prioridade entre 1 Saixo)e 10 (alto), embora as 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.

E Se nio for configurada explicitamente, a prioridade de um thread seri a mesma do thread que o criou.

O O m6todo yield ( ) pode fazer com que um thread em execuglo se.ja interrompido se houver threads execut6veis com amesmaprioridade. Nio h6garantias de que isso ocorreri e de que quando o threadfor interrompido umthreaddiferenteser6selecionado paraexeorSo. Umthreadpode serinterrompido e reentrarimediatamente no esado deexean$o.

tr O mais pr6ximo que teremos de uma garantia serA que, em qualquer momento em que um thread estiver sendo

executado, ele geralmente nio ter6 uma prioridade menor do que a de algum outro thread do estado executivel. Se umthread de prioridade menor estiver sendo executado quando um thread de prioridade alta entrar no estado

executrvel, a JVM geralmente interromperA o thread de prioridade menor e comegar6 a executar o de

prioridade alta.

B Quando um thread chamar o m6todo j oin ( ) de outro thread, aquele que estiver sendo executado esperar6 at6

que o thread ao qual foi adicionado seja concluido. Considere o m6todo j oin ( ) como se dissesse: "Ei thread,quero ser acrescentado ao seu final. Deixe-me saber quando voc6 tiver encerrado sua execugio para que eu possa

entrar no estado execut6vel.

Problemas do acesso simultaneo e threads sincronizados (Obietivo 4.3)E Os m6todos slmchronized impedem que mais de um thread acesse o c6digo de um m6todo critico do

objeto simultaneamente.

tr VocA pode usar a palavra-chave slmchronized como o modificador de um m6todo ou para iniciar um bloco de

c6digo sincronizado.

uD

tr

Page 444: Java - Scjp 5 - Portugues

4l I Copitulo 9: Threods

E Para sincronizar um bloco de c6digo (melhor dizendo, um escopo menor do que o m6todo inteiro), voc6 ter6que especificar um argumento que seja o objeto em cujo bloqueio quiser basear a sincronizaglo.

E Embora s6 um thread possa acessar o c6digo sincronizado de uma instAncia especifica, virios threads podem acessar omesmo c6digo nio sincronizado do objeto.

E Quando um objeto entra em suspensio, seus bloqueios estario indisponiveis para outros threads.

E Osm6todosstatic podemserslmchronized comousodobloqueiodainstAnciadejava.lang.Classquerepresentar essa classe.

Comunicando-se com os objetos atrav6s da espera e notificagno (Objetivo 4.4)E O m6todo wait ( ) permite que um thread diga: "Nio hi nada que eu possa fazer aqui, portanto, coloque-me em

seu pool de espera e me avise quando acontecer algo que me interesse". Basicamente, uma chamada await ( )

significa "espere-me em seu pool", ou "quero ser inserido em sua lista de espera".

D O m6todo no t i f y ( ) 6 usado para enviar um sinal a somente um dos threads que estiverem aguardando no poolde espera desse mesmo objeto.

E O m6todo noti fy ( ) ndo pode especificar qual thread em espera deveri ser notificado.

E Om6todonotifyAll ( ) funcionadamesmamaneiraquenotify( ),s6queenviaosinalparatodososthreads que estiverem aguardando no objeto.

fl Todosostr€sm6todos-wait( )/notify( )/notifyall( ) -devemserchamadosdedentrodeumconteno sincronizado! O thread ter6 que chamar wait ( ) /notify ( ) em um objeto especifico, e seri necessirioque tenha o bloqueio desse objeto.

Threads em impasse (ObjetiYo 4.4)I O impasse ocorre quando a execugio do thread 6 interrompida porque o c6digo est6 esperando que os bloqueios sejam

removidos dos objetos.

D O impasse pode ocorrer quando um objeto bloqueado tentar acessar outro objeto bloqueado, que por sua vezesteja tentando acessar o primeiro objeto citado. Em outras palavras, os dois threads estio esperando aliberagio do bloqueio um do outro; ou se.ia, os bloqueios nunca serlo liberados!

tr O impasse 6 inadequado. Nio tente cri6lo.

Teste individualAsperguntas a seguir o ajudarXo a avaliar sua compreensXo sobre o material apresentado nese capinrlo. Se inicialmente achardificil, nio se culpe. Seja otimista. Algumas destas quest6es sio longas e intrincadas, espere ver quest6es longas e intrincadasno 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 + " ");)

Page 445: Java - Scjp 5 - Portugues

JAVA 5 419

Quais dos seguintes sio resultados possiveis? (lr4arque todas as corretas)

A Wallace-1 Wal]ace-2 Gromit-1B. Wallace-l- Gromit-2 Wallace-2 Gromit-1C Wallace-1 Gromi-t-1 Gromit.-2 Wallace-2D. cromit-1 cromit-2E. Gromit-2 Wall-ace-1 Gromit-l Wal-lace-2H Oc6digoniocompila.

G Ocorre umeffo no tempo de execu$o.

2. Dado:public class Letters extends Thread {

nri rral- o Qf ri r----.19f nalne;

nrrLrl i c T.of i- arc lQf rina n:mol tL

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. Quaisdasseguintadefinig6esdem&odospoderiamseradicionadas lclasselenenparase obteressa-garanrid (Marquetodas asco-rretas)

A public void runo { writel;; iB. public synchronized void runO { writeO; }

C public static slmchronized void runO { wriLeO; }

D. public void run0 { stmchronized(this) { writeO; } }

E. public void runO { stmchronized(Letters.class) { writeO; } iE public void runO { slmchronized(System.out) { writeo; } }

G public void runO { stmchronized(System.out.class) { writeO; } }

3. O seguinte bloco de c6digo cria um Thread usando um alvo Runnable:Runnable target = new MyRunnableO;

Thread myThread = new Thread(target);

Quais das seguintes classes podem ser usadas para criar esse alvo , de forma que o c6dtgo arterior compile corretamente?

,t public class MyRunnable extend.s Runnable{public void runo {}}B. public class MyRunnable extend.s object{public void. runo{}}C public class MyRunnable implements Runnable{public void runO{}}D. public class MyRunnable implements Runnabl-e{void runO {}}E. public class MyRunnable implements Runnabfe{public void startO{}}

Page 446: Java - Scjp 5 - Portugues

420 Copitulo 9: Threods

4. Dado:2. class MyThread extends thread {

3. public static voj-d main(String [] args) {

4. MyThread t = new MyThread|;5. t.srarto;6. System.out.print("one. ");'t . t. start O ;

8. System.out.prj-nt("two. ");9. )

10. public void runo {

11. System.out.print("Thread ");72. )

l-3. )

Qual6 o resultado desse c6digo?

A Acompilagofalha.

B. Ocorre uma exce$o no tempo de execu$o.

C Thread one. Thread two.D. A saida nio pode ser determinada.

5. Dado o c6digo a seguir,

1. class MyThread extends Thread {

2.

3. public static void main(String [] args) {

4. MyThread t = new l'tyThreado;

5. Thread x = new Thread(t);

6. x.startO;t1

8.

9 . public voi-d run O {

10. for(int i=0;i<3;++i) {

11. System.out.print(i + "..");1.2. )

1? l

14. )

qual ser6 seu resultado?

A. A compilagno falharit

8.1..2..3..

c.0..1..2..3..

D.0..1..2..

E. Uma excegeo ocorrer6 no tempo de execugio.

6. Dado o c6digo a seguir,

L. class test {

2.

3. public static void main(String [] args) {

4. printAll (args) ;

Page 447: Java - Scjp 5 - Portugues

JAVA 5 421

s. )

; public stati-c void printAll(Strins[] lines) {

8. for(int !=Q;i<1j-nes.length;i++){

9. System.out.printl-n(1ines Ii] ) ;

10. Thread.currentThreadO.sleep(1000);

11. ]

L2. ]

1? I

o m6todo stat.ic Thread. currentfhread ( ) retornar| uma referencia ao objeto Thread que estiversendo executado no momento. Qual seri o resultado desse c5digo?

A. Seri exibida cada String das linhas do array, com uma pausa de 1 segundo.

B. Ser6 exibida cada String das knhas do array, sem pausa entre elas porque esse m6todo nio 6 executado em um objetoEltr nread.

C. Seri exibida cada String das /inbat do array, sem garantias de que haveri uma pausa porquecurrentThread ( ) pode nio recuperar esse thread.

D. Esse c6digo nio ser6 compilado.

7. Suponhamos que voce tivesse uma classe com duas varieveis private: a e b. Quais dospares a seguir Podem impedir problemas de acesso simultAneo nessa classe (selecione todosque forem aplic6veis)?

'4" public int read(int a, int b) {return a+b}public void set(int a, int b) {this.a=a;this.b=b}

B. public synchronized int read(int a, int b) {return a+b}public slmchronized void set(int a, int b) {this.a=a;this.b=b}

C public int read(int a, int b) {synchronized(a) {return a+b}}public void set(int a, int b) {slmchronized(a) {this.a=a;this.b=b}}

D. public int read(int a, int b) {s}mchronized(a) {return a+b} }public void set(int a, int b) {slmchronized(b) {this.a=a;this.b=bi}

E. public synchronized(this) int read(int a, int b) {return a+b}public slmchronized(this) void set (int a, int b) {this .a=a; this.b=b}

H public int read(int a, int b) {slmchronized(this) {return a+b} }public void set(int a, int b) {synchronized(this) {this.a=aithis.b=b}}

8. Quais dos m6todos abaixo s6o da classe Object. (Marque todas as corretasx,d notify( );B. notifyAll ( );C isfnterrupted( r;D. slmchronized( );E. int-arrrrni-/ \'!. 4rf ue!rqvu I I I

E wait(1ong msecs);

G sleep(long msecs);

FL yield( );

9. Dado o c6digo a seguir,1. public class WaitTest {

2. public static void main(Srring [] args) {

Page 448: Java - Scjp 5 - Portugues

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. iqual seri o resultado se tentarmos compilar e executar esse programa?

,{, SuacompilagXofalhar6porqueaexcegaorllegalMonitorstateExceptiondewait( )nio6manipuladanalinhaT.

B. 1.23c13D.L 2

E. Notempodeexecuglo,elelangar6umaexcegiolllegalMonitor StateExceptionquandotentarentrarnoestado de espera.

E Sua compilagio falhar6 porque ele tem que ser sincronizado no objeto this.

10. Suponhamos que o m6todo a seguir tenha sido apropriadamente sincronizado e chamadopor um thread A no objeto B:

wait (2000) ;

Depois que esse m6todo for chamado, quando o thread A se tornar6 candidato a conseguir outra chance de ser executado

PelaCPI-llr

A Depois que o thread A for notificado, ou ap6s dois segundos.

B. Depois que o bloqueio de B for liberado, ou ap6s dois segundos.

C Dois segundos ap6s o thread A ser notificado.

D. Dois segundos ap6s o bloqueio de B ser liberado.

I l. Quais das declarag6es abaixo sio verdadeiras? (Marque todas as corretas)

A O m6todo notify ( ) deve ser charnado em um contexto sincronizado.

B. Para chamar wai E ( ) , um objeto deve possuir o bloqueio do thread.

C O m6todo notify ( ) 6 definido na classe java.lang.Thread.

D. Quando um thread esdver aguardando como resultado de waitQ, liberari seus bloqueios.

E. O m6todo not.i fy ( ) faz com que um thread libere imediatamente seus bloqueios.

E Adiferengaentre notify ( )enotifyAll ( ) 6quenotifyA]1 ( )notificatodos osthreads queesteo

aguardando, independente do objeto em que estio esperando.

12. Dado o cen6rio: Esta classe dever6 permitir que os usu6rios escrevam uma s6rie demensagens, de forma que cada mensagem seja identificada com a hora e a data, d6m do nomedo thread que escreveu a mensagem:

public class Logger {

private StringBuilder contents = new StringBuilderO;public void log(String messaqe) {

contents . append ( System. currentTimeMillis ( ) ) ;

contents.append(" : ") ;

Page 449: Java - Scjp 5 - Portugues

JAVA 5 423

contents . append (Thread. currentThread ( ) . getName ( ) ) ;

contents . append (message ) ;

contents . append ( " \n" ) ;

]

public String getcontentsO { return content.s.toStringO; }

)

Como podemos garantir que as instAncias dessa classe poderio ser usadas de forma segura por mriltiplos threa&?

A. Essa classe j6 6 segura.

B. Substituir StringBuilder por StringBuffer tornar6 essa classe segura.

C. Sincronizando apenas o m6todo Ios ( ) .

D. Sincronizando apenas o m6todo getContents ( ).E. Sincronizando log ( ) e getContents ( ).F. Nada pode tornar essa classe segura.

13. Dado:public static slmchronized void main(String[] args) throwsInterruptedException {

Thread t = new Thread0;t. start O ;

Syslem. out.print ( "X" ) ;

t.wait(l-0000);System. out.print ( "Y" ) ;

,I

Qual6 o resrltado desse c6digo?

A Exibexefinaliza.

B. Exibex enuncafinaliza.

C ExibexY efinalizaquaseimediatamente.

D. Exibe xY comum atraso de 10 segundos entre X e Y.

E. ExibeXY comumatrasode 10000segundosentreX eY.

E Oc6digoniocompila.n 4t | 'G E langada uma ex@o no tempo de exeor$o.

14. Dado o c6digo a seguir,

class MyThread extends Thread {ItyThread ( ) {

System. out. . print ( " My'Ihread" ) ;

)

public void run0 {

System.out.print ( " bar" ) ;

)

public void run(String s) {

System. out.println ( " baz" ) ;

]

public class TestThreads {

public static void main (String [] args) t

Page 450: Java - Scjp 5 - Portugues

424 Copiiulo 9: Threods

Thread t = new MyThread0 {

public void run0 {

q\rcfam nrrf nri nfl n l $ fnn" ) :rJ D usrrr. vsL r v! f !rurl! \

i

);t.start O ;

)

qual ser6 o resultado?

A. foo

B. MyThread foo

C Mythread barD. foo bar

E. foo bar baz

E bar foo

G Acompila$oQallariL

H E langada uma excegio no tempo de execugio.

15. Dadopublic class ThreadDemo {

slmchronized void aO { act.Busy0; istatic slmchronized void bO { actBusy0; }

static void actBusyO {

try {

Thread.sleep(1000) ;

) catch (fnterruptedException e) t)]

public static void main(String[] args) {

finaf ThreadDemo x = new fhreadDemoO;

final- ThreadDemo y = new ThreadDemoo;

Runnable runnable = new Runnable0 {

public void runo {

j-nt option = (int) (Math.random1 * 4l;switch (option) {

case 0: x.ao,' break;

case 1: x.b0; break;

case 2: y.ao; break;

case 3: y.bO; break,'

)

j;

Thread threadl = new Thread(runnabl-e);Thread thread2 = new Thread(runnable);threadl. start O ;

thread2. start O ;

Page 451: Java - Scjp 5 - Portugues

JAVA 5 425

Quais dos seguintes pares de chamadas a m6todos nunca poderiam ser executadas ao mesmo tempo? (l4arque todas ascorretas)

A.x.a0 em threadl, and x.ao em thread2B. x.ao em threadl , and x.b0 em thread2C. x.ao em thread.l , and y.ao em thread2D. x. a O em threadl , and y. b O em thread2E. x.bo em threadl , and x.ao em thread2F. x.bo em threadl-, and x.bo em thread2G.x.bo em Lhreadl, and y.ao em thread2H.x.bO em Lhread.l , and y.bo em t.hread2

| 6. Dado o c6digo a seguir,1. public class Test {

2. public static void maj-n (String [] args) {

3. final Foo f = new Foo O ;

4. Thread t = new Thread(new Runnable0 {

5. publ-ic void run ( ) {

6. f.doStuffo;t. ]

B. ));9. Thread g = new ThreadO {

10. public void runo {

11. f.doStuffo;1 '> \

1,4. t. start ( ) ;

l-5 . g. start O ;

16. ]

17. )

1. class Foo {

2. int x = 5,'

3. public void doStuff ( ) {

4. if (x<10) {

5. // nada a fazer6. 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.

Page 452: Java - Scjp 5 - Portugues

426 Copitulo 9: Threods

B. O c6digo nXo seri compilado por causa de um erro na linha 7 da classe Foo.

C. O c6digo nlo seri compilado por causa de um erro na linha 4 da classe Test'

D. O c6digo nio ser6 compilado por causa de algum outro erro na classe Test.

E. Uma excegio ocorrer| no temPo de execuqio'

F.xis5xis6

17. Dado:public class TwoThreads {

static Thread laurel, hardy;

public static void main(String[] args) t

laurel = new Thread0 {

public void run0 {

System. out.println ( "A" ) ;

try {

hardy.sleep(1000);

) catch (Exception e) {

System. out.println ( "B" ) ;

iq\rcfam nrrl- nrint-ln I irf-") :rf e uqrr. vuu . v! rarLrlr

)

);hardy = new rhread0 {

public void run0 iq\rcfam nrrl- nrint-ln l"Tl/) .vJpeurrr.vuu.Pif.rL4

trY {

laurel.wait ( ) ;

] catch (Exception e) t

System. out . println ( "8" ) ;

)q\rcl_am

^rrt- nrin|In INF"') :vtruelri.vuL.vr

]

);laurel. start O ;

hardy. start O ;

)

Quais letras acabarlo aparecendo em algum lugar na saida? (Marque todas as corretas)

,4. a

B.eCcD.pE.eEpG A resposta nio pode ser determinada de forma segura.

H Oc6digonSocompila.

Page 453: Java - Scjp 5 - Portugues

Respostas do teste individualC est6 correta. Ambos os threads exibirio duas mensagens cada. wallace-1 deve vir antes de wallace-2,e Gromit-1 deve vir antes de Gromit-2. Fora isso, as mensagens Wallace e Gromit podem vir emqualquer ordem.

A, B, D, E, F e G estlo incorretas com base 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 impedir6g|! os threads rodem simultaneamente, e garantir|xxYY ou YYx*. E um ponco incomum bloquear em umobjeto como system. out, mas 6 perfeitamente vilido, e ambos os threads estio bloqueando no mesmoobjeto.

A nio pode garantir nada, uma vez que nio tem sincronizagio. B e D sincronizam em uma instincia da classeLetters - mas como existem duas instincias diferentes no m6todo main ( ) , os dois threads nlo bloqueiam umao outro e podem rodar simultaneamente,. resultando em saidas como XYXY. C nio vai compilar, pbrque estitentando sobrescrever run ( ) com um m6todo static, e tamb6m est6 chamando um m6todo nio-stitica partir de um m6todo estitico. G nio vai compilar porque System. out . class nio existe. Um literal declasse deve comegar com um nome de classe. System. out 6 um campo, e nio uma classe, de forma queSystem. out. class nio 6 um literal de classe vilido. (Objetivo a.3)

JAVA 5 427

4.

1.

2.

J.

6.

&

9.

3. C est6 correta. A classe implementa a interface Runnable com um m6todo run ( ) v6lido.

A esti incorreta porque as interfaces sio implementadas, e nlo estendidas. B esti incorreta porque embora aclasse tenha um m6todo public void rin ( ) vilido, ela nio implementa a interface Runnable. D est6incorreta porque o m6todo run ( ) deve ser publ ic. E esti incorreta porque o m6todo a ser implementado 6run ( ), e nlo start ( ) . (Objetivo 4.1)

B esti correta. Quando se tenta usar o m6todo start ( ) pela segunda vez em um mesmo objeto Thread, om6todo lang*i uma IllegalThreadStateException. @mbora esse componamenro estejaespecificado na API, alguns JVMs nio langam uma excegio consistentemente neise caso.) Mesmo se o threadtiver 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 desintaxe, emyez de erros na l6gica especifica de cada classe. C e D estio incorretas com base na l6gica expostaacima. (Objetivo4.1)

D esti correta. O thread MyThread seri iniciado e executar6 um loop tr6s vezes (de 0 a 2).

A resposta A est6 incorreta porque a classe Thread implementa a interface Runnable; portanto, na linha 5,Thread pode usar um objeto do tipo Thread como argumento no construtor. B e C estio erradas porque a

vari6vel i do loop for comega com um valor igual a 0 e termina com2. E esti incorreta por causa da l6gica doprograma que esti desffita acima. (obj +.1)

D esti correta, O m6todo sleep ( ) deve ser inserido em um bloco try,/catch ou o m6todo printAll (

) deve declarar que langar6 a excegio rnterruptedException.A resposta E est6 incorreta, mas estaria correta se a excegio rnterrupetdException tivesse sido tratada(A 6 precisa demais). B est6 errada (mesmo se a excegio rnterruptedException fosse manipulada)porquetodo c6digoJava, inclusive o m6todomain( ),6 executado emthreads. C est6incorreta. O m6todosleep ( ) 6 suatic, portanto, mesmo se for chamado em uma instincia, continuari a{etando o thread queestiver sendo executado. (Objetivo 4.2)

B e F estio corretas. Se os m6todos forem marcados com slmchronized, os threads obterio o bloqueio doobjeto this antes de prosseguir. 56 um thread estar6 configurando ou lendo em determinado momento, oque assegura que read ( ) sempre retorne a soma de um par v6lido.

A resposta A est6 incorreta porque nio foi sincronizada; portanto, ni,o h6 garantias de que os valores somadospelo m6todo read ( ) pertengam ao mesmo par. C e D estio erradas; somente objetos podem ser usados nasincronizagio. E falha; nio 6 possivel selecionar outros objetos (nem mesmo thi s) para executar a sincro ruzergioquando um m6todo for declarado com slmchronized. (Objetivo 4.3)

A, B e F estio corretas. Eles estio todos relacionados ) lista de threads em espera no objeto especificado.

AsrepostasCrE"GeHestioincorretas. Osm6todos isrnterrupted( ) e interrupt ( ) slom6todosdeinstAncia &Thread.Osm6todossleep( ) eyield( ) siom6todosstatic deThread.Dest6erradaporquesynchroni 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 threadnodficar6 o thread principal, portanto, 3 nunca ser6 impresso. O programa ficar6 paralisado na linha 7.

A resposta A est6 incorreta; rllegalMonitorstateException 6 uma excegio nXo-verifica&. B e C estioerradas, 3 nunca ser6 exibido, jl que esse programa ficari em um estado continuo de espera, E esti incorreta porquerllegalMonitorStateExceptionnuncaser6langadaj6quewait( ) serifinalizadoemargrdentrodeum

7.

Page 454: Java - Scjp 5 - Portugues

428 Cooitulo 9: Threqqs

bloco de c6digo sincronizado pelos argumentos. F est6 errada porque qualquer objeto pode ser usado na

sincronizaglo e, al6m disso, this e static nio combinam. (Objetivo 4.4)

10. A esti correta. Um dos dois eventos fari com que o thread se torne candidato a ser executado novamente'

A resposta B est6 incorreta porque um thread em espera nio retornar6 para o estado exectt6vel quando o bloqueio

for liberado, a menos que uma notificagio ocorra. C est6 errada porque o thread se tornar6 candidato

imediatamente ap6s a notificagio. D tamb6m est6 incorreta potqne Jm thread nio sair6 de um pool de espera s6

porque um bloqueio foi liberado.

l,l.ArespostaAest6corretaporqueom6todonotifyAll( ) (untoawait( ) enotify( ))devesemPreser chamado em um contexto sincronizado. D 6 uma instrugio correta.

A resposta B est6 incorreta porque para chamar wait ( ) , o thread deve possuir o bloqueio do objeto em que

waiC ( ) est6 sendo chamido,i nio o contr6rio. C esti erradaporque notify( ) 6 definido emjava.lang.object.Eest6erradaporquenotify( ) niofar6comqueumthreadlibereseusbloqueios.Othread s6 poderi liberi-los saindo do c6Agb sincronizado. F est6 incorreta porque notifyAll ( ) notificar6rodos os threads que estiverem aguardando um objeto bloqueado especifico e nio todos os threads que estiverem

aguardando em qaaQaer objeto. (Objetivo 4.4)

12. E estit, correta. Sincronizar os m6todos priblicos 6 suficiente paru tornar a classe segura, en6o F 6 falsa. Esta

classe nioestar6 segura a nio ser que algum tipo de sincronizaglo proteja os dados sendo modificados.

B nio est6 correta porque, embora um StringiBuf fer seja sincronizado internamente, podemos chamarappend ( ) 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 executarenquanto o outro esti rodando, o que poderia resultar na leitura do conterido enquanto uma das mensagens aindaest6 incompleta, ou em algo pior. (VocA nio vai querer chamar getstring ( ) para o StringBuf terenquanto ele est6 modificando o tamanho do seu array de caracteres interno.) (Objetivo 4.3)

13. G esticorrera. O c6digonio adquireumbloqueioem t antesde chamar t.waitO, entio elelangaumaIllega1Thread.StateException. O m6todo est6 sincronizado, mas nio em L, entlo a excegio ser6langada. Se

a espera fosse colocada dentro de um bloco slmchronized (t ) , entAo a resposta correta seriaD.

A, B, C, D, E e F estio incorretas com base na l6gica exposta acima. (Objetivo a.2)

14. A resposta B est6 correta. Na primeira linha de main estamos construindo a instAncia de uma classe internaan6nima, 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 m6todorun ( ) 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 e H. A est6 correta porque os m6todos chamados para a mesma instAncia bloqueiam uns aos outros. F e

H nio poderiam acontecer porque m6todos static synctrroni zed da mesma classe bloqueiam uns aos

outros, independentemente de qual instAncia foi usada para chamar os m6todos. (I.{1o 6 obrigat6rio que umainstAncia chame m6todos stat.ic; apenas a classe est6 su.ieita a esse requerimento.)

C poderia acontecer porque os m6todos slmchronized chamados para diferentes instincias niobloqueiam uns aos outros. B, D, E e G poderiam acontecer, porque os m6todos de instAncias e os m6todosstatic bloqueiam em diferentes objetos, e nio bloqueiam uns aos outros. (Objetivo 4.3)

16. A resposta E est6 correta porque o thread nio possui o bloqueio do objeto em que chama wai t ( ) . Se om6todo fosse sincronizado, o c6digo seria executado sem langar uma excegio.

As respostas A, B, C e D estio incorretas porque o c6digo ser6 compilado sem erros. F esti errada porque a

excegXo ser6 langada antes que haja alguma saida. (Objetivo 4.4)

17 . A, C, D, E e F estlo corretas. Poderia parecer que 1aurel e hardy estio brigando para f.azer o outros leep O ou wait O - mas nio 6 o caso. LJma vez que sleep O 6 um m6todo static, ele afeta o threadatual, 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 niosincronizou em 1aure1, de modo que chamar laurel .wait ( ) causa imediatamente umaIllegalThreadstateException, e assim hardy exibe D, E e F. Embora a ordem da saida seja mais oumenos indeterminada (nio temos como saber se A ser6 exibido antes de D, por exemplo), 6 garrntido que A, C,D, E e F serio exibidos, em alguma ordem - enteo G est6 incorreta.

B, G e H estio incorretas com base no exposto acima. (Objetivo 4.4)

Page 455: Java - Scjp 5 - Portugues

JAVA 5 429

Respostas dos exercicios

Exercicio 9- l: Criando um thread e colocando-o em suspensioO 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 c6digoSeu c6digo pode ficar parecido com este quando concluido:

1. class Ins)mc extends Thread {

2. StringBuffer letter;?

4. public Inslmc(StringBuffer letter) {

5. this.letter = letter;6. )

'7.

8. public void runo {

9. slmchronized(letLer) {

10. for(int i = 1;i<=100;++i) {

11-. SysLem.out.print(letter);]-2. )

l-3. System.out.println( ) ;

1,4. // Incrementa a letra em StringBuffer:l-5. char temp = letter.charAt(0);16. ++tempt

1,7. letter.setCharAt(0, temp);

l-8. )

1q l

20.

2L. public static void main(String [] args) t

22. StringBuffer sb = new StringrBuffer ( "A" ) ;

23 . new Inslmc ( sb) . start O ;

24. new fnslmc (sb) . start ( ) ;

25 . new Ins)mc (sb) . start ( ) ;

26- )

Page 456: Java - Scjp 5 - Portugues

430 Copitulo 9: Threods

Page 457: Java - Scjp 5 - Portugues

i. .,

.:;

,tiir*

'ir,.,

rt

T

I

II

,i

t0Desenvolvimento

Oblerfuos pqru ocertlflcog6o

Usor Pocoles e lmports

Deierminor o Comoortomento em

Tempo de ExecuE6o de Closses eLinhos de Comondo

Usor Closses de Arquivos JAR

Usor Closspoths poro CompilorC6digo

a/ Exercicios r6pidos

P&R Teste lndividuol

Page 458: Java - Scjp 5 - Portugues

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

Compilando com javac

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$ntgduinportpara interagir con (atrauis do acessl 0u da beranga) o aldigo do exempb,

7.2 Dado am exemp/o de uma classe e uma linba dc comando, dtterminar o clmpnrtanentl espnadn en tempo dc exuugdo.

7.5 Dado o nome completamente qualifcado de uma classe dbtribuida dentro e / oufora dr an arquiao JAR, con$ruir a estrutura de

l:;::r::t **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 j avac e j ava um milhio de vezes;agora iremos dar uma olhada mais aprofundada neles.

O comando javac 6 usado parachamzr o compiladorJava. No Capitr:Io 5, n6s falamos sobre o mecanismo das assertivas esobre quando voc6 poderia usar a opgio - source ao compilar um arquivo. Existem muitas outras opg6es que voc€ podeespecificar ao rodar j avac; opg6es paragerar informag5es de depuragio ou avisos do compilador, por exemplo.Paraoex^me, voc6precisar6 entenderas opg6es -classpath e -d, as quais abordaremos nasp6ginas seguintes. Al6m disso,6importante 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 oexame. Tanto as [opg5esJ quanto os [arquivos - f onte] sio partes opcionais do comando, e ambas permitemmultiplas entradas. Seguem abaixo alguns comandos j avac v6lidos:

javac -he1pjavac -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 aocompiladorduas opgSes (-classpath, aqualtemelapr6priaum argumento de com: . e -9),epassaao compiladordois 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 -dPor padrio, o compilador coloca um arquivo . class no mesmo diret6rio que o arquivo-fonte . j ava. Isso funcionabem 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 lhepermitedizeraocompiladoremquediret6rioeledevericolocaro(s)arquivo(s).cl-assquegerar(d significadestino).Digamos que voc6 tenha a seguinte estrutura de diret6rios:

myProj ect

I

| --cdllFFA

I I -- MyClass. java

I

| - - classes

I

t--O sguinte comandqernitidonodiretoriomyProj ect,iticompilarMyClass . j ava ecolocaroarquivolvb€lass . cLass resultanrenodiretorio classes. (Obsena$o:istoassumequeMlClassniotenhaumainstrugopadcage;filarernos sobrepacoteseminstantes.)

Page 459: Java - Scjp 5 - Portugues

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

llI I --com

| - -wickedlysmart

| --MyClass.java

| ^1 -^^^^| - -ur4DDED

ll| | --com

I

| - -wickedlysmart

| | - - (Myclass . class vem para c6)

Se voc6 estivesse no diret6rio source, compilaria MyClass . j ava e colocaria o arquivo MyClass . cf ass resultanteno diret6rio classes/com/wickedlysmart com o seguinte comando:

javac -d . ./classes com/wickedlysmart/MyC1ass. java

Esse comando poderia ser lido como: "Pata de{inir o diret6rio de destino,volte para o ditet6rio myProj ect e depois v6para o diret6rio cl-asses, o qual ser6 o seu destino. Entio, compile o arquivo chamado MyClass . j ava. Finalmente,ponha o arquivo MyC 1 a s s . c 1 a s s resultante dentro da estrutura de diret6rios que bata com o seu pacote, neste caso

classes,/com/wickedlysmart." Pelo fato de MyClass . j ava estar em um pacote, o compilador sabia que

devia colocar o arquivo . class resultante no diret6rio cf asses/com/wickedlysmart.

De forma um tanto surpreendente, o comando j avac pode, em alguns casos, lhe ajudar ao ciar os diret6rios de que ele

precisa! Suponha que temos o seguinte:

package com. wickedlysmart ;

public class MyCIass { i

myProj ect

I

I - -cnrrrna

| | --com

I

| - -wickedlysmart

I

l--uyclass.java

Page 460: Java - Scjp 5 - Portugues

434 Cooitulo l0: Desenvolvimento

| --classes

E o seguinte comando (o mesmo do exemplo anterior):

javac -d . . /classes com/wickedlysmart/t"tyClass. java

Neste caso, o compilador criar6 dois diret6rios, chamados com e com/wickedlysmart, nessa ordem, para colocar oarquivo MyClass . class resultante no dirct6io coneto do pacote (com/wickedlysmart,/), o qual o compiladorcria dentro do diret6rio.. . /classes existente.

A ultima coisa sobre - d que voc6 precisar6 saber para o exame 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:

java:5: error while writing MyClass: classes/MyClass.class (No

such file or directory)

Iniciando Aplicativos com iavaO comando j ava 6 usado para chamar a miquina vimralJava. No Capitr:lo 5, n6s falamos sobre o mecanismo das assettivas e

sobre quando voc6 podetia usar flags como - ea ou - da ao iniciar um aplicativo. Existem muitas outras opg6es que voc€ podeespecificar 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 irmigemea - cp) e - D, as quais iremos abordar nas pdginas seguintes. Al6m dissq 6 impottante entender a estrutura desse comando.

Eis avisio geral:

java [opc6es] class [argumentosl

Aspartes [opg6es] e [argumentos] docomandojava sioopcionais,epodemambastermultiplosvalores.Vocd deve especiftcar exatamente um arquivo de classe para ser executadq e o comando j ava assume que voc€ estifalando de um arquivo . cf ass, entao nao especifique a extensio . cl-ass nalinha de comando. Eis um exemplo:

java -DmyProp=myvalue MyClass x 1

Deixando os detalhes para depois, esse comando pode ser lido como "crie umapropriedade de sistema chamada myProp e

defina o seu valor como myValue. Em seguida, abra o arquivo chamado MyCIass . cl-ass e envie para ele doisargumentos 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 SistemaJava 5 tem uma classe chamada j ava . util . Properties, que pode ser usada para se acessarinformag6es persistentesde um sistema, tais como as versdes atuais do sistema operacional, do compiladotJava ou da m6quina virtualJava. Al6mde forneceresse tipo de informagdo pa&iq voc6 podetambdmadicionare obteras suas pr6prias propriedades. Observe oseguinte c6digo:

import java.util.*;public class TestProps {

public static void main(StringlJ args) iProperties P = System.getProperties O ;

p. setProperty ( "myProp" , "myVa]ue" ) ;

p. Iist (System.out) ;

]

Se esse arquivo for compilado e chamado desta forma:

java -DcmdProp=cmdval TestProps

Voc6 receber6 algo como isto:

os.name=Mac OS X

mYProP=myvalug

j ava. specif ication.vendor=Sun Microsystems Inc.user. language=en

Page 461: Java - Scjp 5 - Portugues

JAVA 5 435

java.version=1.5.0 02

cmdProp=cmdVal

""0.;; retic6ncias (. . .) representam diversos outros pares de nome = valor. (O nome e o valor sio, ds vezes, chamados de

chave e propriedade, respectivamente) Duas propriedades norne = valor foram adicionadas is propriedades do sistema:myProp=myValue foi adicionada atavds do mEtodo setProperty, e cmdProp=cmdVal foi adicionada arravesda opgio -D na linha de comando.

Ao usar a opgio - D, se o seu valor contiver espagos em branco, entlo todo o valor deve ser colocado entre aspas, destaforma:

java -DcmdProp="cmdval take 2" TestProps

E caso voc6 nio tenha reparado, quando usa -D, o par nome = valor deve segak imediatamente,rrio sdo permitidos espagos.

O m6todo getProperty ( ) 6 usado para se obter uma fnica propriedade. Pode ser chamado com run s6 argumento(uma String que represente o norne, ou chave), ou pode ser chamado com dois argumentos (uma String que represente onome, ou chave, e um valor String padrio para set usado como a propriedade caso esta ainda nao exista), Em ambos oscasos, getProperty ( ) retotna a propriedade como uma String.

Lidando com Argumentos de Linha de ComandoVamos voltar a um exemplo de se abrir um aplicativo e passar a ele argumentos a partir da linha de comando. Se tivermos oseguinte c6digo:

public class CmdArgs {

public static void main(StringlJ args) {

int x = 0;

for(String s : args)

System.out.println(x++ + " element = " + s);

)

compilado e depois chamado da seguinte forma

java CmdArgs x 1

a saida ser6

0 element = x1 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],eassimpordiante,

Hnalmente, existe alguma flexibilidade na declaragio do m6todo ma i n ( ) usado Eara se iniciar um aplicativoJava- A ordem dos

modificadoresdemainO podeseralteradaumpoucqoaffrydeStringsnnoprecisasechamarargs e,apartirdoJava5,ometodopode ser declarado usando-se a sinta:<e dos argumentos vati6veis Todas as seguintes declarag6es s6o vilidas para ma in ( ) :

static public void main(StringlJ args)

public static void main(String... x)

static public void main(String bang_a_gongI J )

Procurando por Outras Classes

Na maioria dos casos, quando usafinos os comandos j ava e j avac, queremos que esses comandos procurem poroutras classes que serio necess6rias para completar a operagdo. O caso mais 6bvio 6 quando as classes que n6s criamos usamclasses 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 outrasclasses que tenham sido criadas fora do que 6 fornecido pela Sun, por exemplo as nossas pr6prias classes anterioffientecriadas. 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 precisouteracessoajava.util .HasMap,entioocomandojavaamb6mprecisat6encontrarjava.util.HashMap.

Tanto j ava quanto j avac usam o mesmo algoritrno bisico de busca:

Page 462: Java - Scjp 5 - Portugues

436 Copitulo I 0: Desenvolvimento

1. Eles t6m ambos a mesma lista de lugares (diret6rios) onde procuram por classes.

2. Ambos procuram nessa lista de ditet6rios na mesma ordem.

3. Assim que encontram a classe que estavam procurando, eles interrompem a busca por essa classe. No caso de as listas de

busca conterem dois ou mais arquivos com o mesmo nome, o ptimeiro arquivo encontrado ser6 usado.

4. O ptimeiro lugar onde eles procuram 6 nos diret6rios que contem as classes que v6m com oJ2SE.

5. O segundo lugar onde procuram 6 nos diret6rios definidos por classpaths.

6. Classpaths significam "caminhos de busca de classes". Eles sdo listas de diret6rios nos quais podem ser encontradasclasses.

7. Existem dois lugares onde classpaths podem ser declarados:

Um classpath pode ser declarado como umavari6vel de ambiente de sistema. O classpath declarado aqui 6 usado porpadrio 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. Classpathsdeclarados como opg6es de linha de comando substituem o classpath declatado como vari6vel de ambiente, mas s6persistem durante o tempo que durar a chamadz.

Declarando e Usando ClasspathsClasspaths consistem de um nrimero vari6vel de lociltzag6es de diret6rios, separados por delimitadores. Para sistemasoperacionais baseados no Unix, sio usadas banas notmais para construir localizag6es de diret6rios, e o sepatados 6 sinal dedois pontos O. Por exemplo:

-classpath / com/ foo/ acct: / com/ fooespecifica dois diret6rios nos quais poder6o ser encontradas classes: / com/ f oo / acct e / com/ f oo. Em ambos oscasos, esses diret6rios ficam absolutamente ligados h.ruz do sistema de arquivos, que 6 especificada pela barra inicial. Eimportante se lembrar que, quando especifica um subdiret6rio, vocd NAO est6 especificando os diret6rios acima dele. Porexemplq na d eclaragdo acima, o ditet6rio / com NAO ser6 usado na busca.

OBSERVAE6BS pene O EXAME

A maioria das quutdu do exame relacionadas a caminbos asani conuengdes do Unix. Se uocdfor usadio do l%indowq os seus diretrjriosserdo declarados usando-se banas inaertidas (\) e o caracter rcparador serd o ponto-e-uirgala 0. M^, nluamente, uod NAO precisani ternenbum conhecimento esputJtin sobre the//s para o exa///e.

Uma situagio bastante comum ocorre quando j ava ou j avac reclama que nio consegue encontrar um arquivo de classe,e mesmo assim vocd pode ver que o arquivo SE ENCONTP-{ no diret6rio ataal! Ao procurar pot arqwvos de classe, oscomandos j ava e j avac nio procuram no diret6rio atual por padrio. Voc6 precisa instrui-los aproctttar ar. A maneirade drzet a j ava ou j avac para procurar no diret6rio atual 6 adicionando um ponto (.) ao classpath:

-classpath / com/ foo / acct : /com/foo : .

Esse classpath 6 id€ntico ao antettor, EXCETO pelo fato de que o ponto (.) ao final da declangd.o instrui j ava ou j avaca 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 situagioem que existam classes com nomes duplicados localizadas em diferentes diret6rios nos seguintes classpaths, diferentesresultados 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 sobrese o comando j avac permite ou nio

^ ^brevi^tnra - cp. Na maioria das m6quinas ele permite, mas nao h6 garanias.

Pacotes e a ProcuraQuando 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 dequest6es relativas a pacotes / classpath especialmente para confundir voc6. Vamos comegar revisando os pacotes. Noseguinte c6digo:

package com.foo;public class MyClass { public void hj- O { } i

Page 463: Java - Scjp 5 - Portugues

JAVA 5 437

estamos dizendo que MyClass 6 um membro do pacote com. f oo. Isso significa que o nome totalmente qualificadoda classe agota6 com. f oo . MyClass. Depois que uma classe 6 colocada em rrm pa.ote ,^p^rtedo nome totalrnentequalificado referente ao pacote se torna at6mica - ela nunca pode ser dividida. Vocd nio pode-dividi-la na linha de comandqe tamb6m nio pode dividi-la em uma insrrugio import.Vejamos agora como podemos usar com. f oo . MyClass em outra classe:

package com.foo;public cl-ass MyClass { public void hi O { } }

E no pr6ximo arquivo:

import com. foo.MyClass;i mn^rf d^fi f^^ * .

/,/ qualquer uma das importaq6es funcionarS

public class Another

void go O {

MyClass m1 = new

^^- I ^^ rr- -dl -com. roo.lvlyulass

m1.hi O ;

mz.hiO;

i)

{

MyClass O ;

m2 = new com. foo.MyClass O ;

// nome-c6digo

/ / nome completo

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 classecom uma instrugio import (ou com um coringa em uma instrugio import do pacote). Ap6s ter definido o nometotalmente qualificado, voc€ pode usar o "nome-c6digo" no seu caidigo - mas o nome-c6digo est6 sempre se referindo aonome totalmente qualifi cado.

Agora que j6 demos uma revisada nos pacotes, vejamos como eles funcionam em coniunto com classpaths e linhas decomando. Primekamente, comegaremos com a id6ia de que, quando voc€ est6 procutando por uma classe usando o seunome totalmente qualificado, esse nome se relaciona intimamente com runa estrutura de diret6rios especifica. Por exemplqem 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 iesquerda do pacote (a"raiz" do pacote) como um subdiret6rio. Esse 6 um conceito importante, entao velamos um outroexemplo:

import com. wickedlysmart . Utils ;

class TestClass {

void doStuff O {

Utils u = new UtilsO; / / nome simplesu.doX("argt", "arg2" ) icom.wickedlysmart.Date d =

new com.wickedlysmart.Date O ; // nome completod. getMonth ( "Oct" ; ,

)

Neste caso, estamos usando duas classes do pacote com. wickedlysmart. Apenas a titulo de explicagio, n6simportamosonometotalmentequalificadoparaaclasseUtils,enioofizemosparaaclasseDate.Afnicadtfercnga6que, por termos listado Ut i l- s em uma instrugio import, nio tivemos de digitar o seu nome totalmente qualificadodenffo da classe. Em ambos os casos, o pacote 6 com. wickedlysmart. Quando chegar a hora de compilar ou executarTestCl-ass, o classpath ter6 de incluir um diret6rio com os seguintes attibutos:

I Um subdiret6rio chamado com (o chamaremos de diret6rio "ruz do pacote")

Page 464: Java - Scjp 5 - Portugues

438 Cooftulo l0: Desenvolvimento

I Um subdiret6rio dentro de com chamado wickedlysmartI Dois arquivos em wickedlysmart chamados Utils . cl-ass e Date . class

Finalmente, o diret6rio que tiver todos esses atributos precisa ainda estat acessivel (via um classpath) de uma das duas

seguintes maneiras:

1. O caminho at6 o diret5do deve ser absoluto; em outras palavras, a partit da ruz (at2|lz do sistema de arquivos, e neo a

do pacote).

2. O caminho at6 o diret6rio tem de ser corretamente relativo ao diret6rio atual.

Caminhos Relativos e AbsolutosUm classpath 6 uma 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 - ocaminho absoluto de um diret6rio 6 sempre o mesmo. Um caminho relativo 6 um que NAO comece com uma barra. Eis

um exemplo de uma estrutura de diret6rios completa, e um classpath:

/ (raj_zl

| - -dire

| - -aire

| - -airc

-cp dirB:dirB/dircNeste 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 voc6estiver procurando por arquivos de classes, e usar o classpath descrito acima, em quais diret6rios ser6 feita a busca?

dirA? dirB? dirC?

F6cil demais? E quanto i mesma pergunta, mas com o diret6rio atual sendo a ruz (/)? Quando o dttet6tio ataal 6 dttA,enteo dirB e dirC serio usados na busca, mas nio dirA (embre-se, n6s nio especificamos o ditet6rio atual

adicionando um ponto O ao classpath). Quando o diret6rio atual6 a raiz, ewmavez que dirB n6o 6 um subdiret6rioditeto 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 dirB nio tem um subdiret6rio chamada dirB. Em outraspalavras,Javaprocurar6porumdiret6riochamadodirB dentrodedirg (enioenconuara),sempetceberquei6est6em dirB.Vamos usar a mesma estrutura de diret6rios e um classpath diferente:

/ (raiz)

I

| --dirA

I

| - -dirB

| - -airc

-cp /dirB : /dirA/dirB/dircNeste 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 quecaminhos absolutos estio especificados, o resultado da busca ser4 sempre o mesmo. Especificamente, s6 ser6 feitabuscaem dirC, independentemente do diret6rio atual. O primeiro caminho (/dira; 6 inv6lido porque dirB ndo 6 um

Page 465: Java - Scjp 5 - Portugues

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 noclasspath (neste caso, dirC).

Obietivo poro o Certificogdo

Arquivos fAR (Objetivo 7.5)7.5 Dado o nome comp/etamente qualifcado de ama classe distribuida dentro e / oufora de un arquiao JAk, canstruir a estr*tara de

diretdrios @mpiada para esa cl.asse. Dada ua exenplo de aidigo e um clasEatb, deterzinar se o clarpatb perrnitinl que o aidigo compile consucest0.

ArquivosfAReaProcuraDepois 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 significaJavaArchive ('ArquivoJava'). Os arquivosJAR sio usados para comprimir dados (de forma semelhante a arquivos ZIP) e paraarquivar dados.

Digamos que voc6 tenha um aplicativo que use muitas classes diferentes,localtzadas em diversos pacotes diferentes. Eisuma 6rvore de diret6rios parcial:

faql-

I

| --UseStuff.java| --ws

| - - (crie My,Jar. j ar aqui )

| --mYAPP

| - -uti1s

I

I l--Dates.class (pacote myApp.utits;)

| - -Conversions. clags n il

I

| - -engl-ne

j - -r.a.. class (pacote myApp. engine,' )

| --minmax.class

Voc€pode cnarumrinico arquivoJARquecontern todos os anquhos de dasses demyApp, emantdrnaestruturade diret6rios de

myApp. Umarcz criado essearquiroJAR, elepode sertransferidoparaoutros diret6rios e outros computadores, e todas as dasses noalquvoJARpodedo seracessadasatrav6sdedasspathseusadaspor j ava e j avac.Tirdoissopodeacontecersemquevocd jamais

precise descompactar o arquivoJAR Embora voc€ nio precise saber como criar arquivosJAR para o exame, r'amos passar para o diretotiows, e em seguida cnat um arquivoJAR charnado My,Jar . j ar:

cd ws

jar -cf MyJar.jar myApp

OcomandoiarcriaumarquivoJARchamadoMyJar.ia4oqu;zliriconterodiret6riomyApp etodaairvoredesubdiret6rios e todos os arquivos de myApp. Voc6 poder6 examinar o conterido do arquivoJAR com o comando seguinte(isso tamb6m rti.o ca no exame):

j ar -tf Myilar. j arque listari o contetido doJAR, mais ou menos desta forma:

META_INF/

META- INF/MANIFEST. MF

Page 466: Java - Scjp 5 - Portugues

440 Copitulo I0: Desenvolvimento

mvApp/

myApp/ .lr5 score

myApp/uti1s/

myApp/ut i 1slDaLes . clas s

myAPp,/ut i1 s/ Convers ions . classmyApp/engine/

myApp/engine/rete . classmyApp/ engine /minmax . c 1as s

Certo, voltemos agora aos assuntos do exame. O processo de se encontrar um arquivoJAR atrav6s do classpath 6

semelhante ao de encontrar um arquivo de pacote em um classpath. A diferenga 6 que, quando voc€ especifica um caminhopara urn arquivo JAR, precisa incluir o nome do arquivo ao final do caminho. Digamos que voc€ queira compilarUseStuff.javanodiret6riotest,eUseStuff.javapreciseteracessoaumaclassecontidaemmyApp.jar.Para compilar UseStuf f . j ava, voc6 usaria

cd testjavac -classpath ws/myApp. jar Usestuff . java

Compare o uso do arquivoJAR ao uso de uma classe em um pacote. Se UseStuf f . j ava precisasse usar classes dodiret6rio myApp . utiIs, e a classe n6o estivesse em umJA\ vocd usaria

cd testjavac -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'{oexemplo anterior, myApp 6 o dfuet6rio-raiz do pacote myApp . ut i 1 s.) Repare que myApp pode ser o dret6io raizpara 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 osuper-diret6rio de myApp, entao as classes presentes tanto em myApp . ut i l- s quanto em myApp . eng ine seraoencontradas.

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 arnem 0rpacntes de java. util .regex! Esrcspacotes sdo totalnente indtpendentet entre $; a tinica coiv qae nrrpatilban i o mesmo

direnirio "raiq", mas ndo sdo o mesnl paclte. A tituk d.e infomagdq uoci n6o pode usar import, j ava . * I na esperanga de importarniltiplos pacotet - implesnente lembre+e, uma inshvgdo inlprrt xd i capa<dz inportar un rinico pacote.

Usando ..lirelllblext com Arquivos fARQuando voc6 instalaJava, € cnada uma enorme anote de diret6rios contendo coisas relacion adas comJava, incluindo os

arquivosJAR que cont€m as classes que v€m com oJ2SE. Como dissemos anteriormente, j ava e j avac t€m uma listade 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 ej avac poderio encontr6-los e usar os arquivos de classes contidos neles.

Nio 6 preciso mencionar esses subdiret6rios em uma instugio classpath - a procura nesse diret6rio 6 uma fungio internadeJava. A Sun recomenda, no entanto, que voce somente use esse recurso para testes e desenvolvimento internos, e niopata software que pretenda distribuir.

oBSERVAQoBS pene O EXAME

E possiuel criar aaridueis de ambiente queforne(am //m nome-cridigo para classpaths hngu. O cksspath de alguns arquiuos JAk no J2SEpode rcr bastante extenso, defonna qae i comum ilsar ilm nome-aidigo 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 direhiiosq/'/e eitamos especifcando explicitamente". Voei pode assumir que a ,IAVA_HOME literal ten un signifcado, e esti @ontando para oclasspathparcial que uocd estd uendo.

Page 467: Java - Scjp 5 - Portugues

JAVA 5 44I

Obietivo poro o Certificocdo

Usando lmportag6es Est6ticas (objetivo 7. I do Exame)7'1 Dado att exernplo de cridigo e um cendrio, escreuer cfidigo qae ase os deuidos nodfrcadoru de acesso, dularapdu de pacotes e in$rapdetimportpara interagir com (atrauis do ace$o ou da herangQ o aidigo do exempl0.

Observag6o: No Capinrlo 1, n6s abordamos a maior parte do que estd definido neste obietq mas deixamos as importag6esest6ticas para este capinrlo.

N6s vimos usando instug6es import ao longo de todo o livro. No fim das contas, o finico valor que as instrug6esimport t€m 6 que elas economizam dtgtagdo e podem tarr' r o seu c6digo mais f6cllde ler. EmJava 5, a instrugioimporf foi aprimoradapan fotnecer capacidades ainda maiores de economia de digitagio... Emtora algumas pessoasargumentem que isso prejudicou a legibilidade. Esse novo recurso 6 conhecido como importagio estitica. As importag5esest6ticaspodemserusadasquandovoc6desejausarosmembrosstatic deumaclasse.ffo.6podeusaresserecursoemclasses da API e nas suas pr6prias.) Eis um exemplo do tipo "antes e depois":

Antes das importag6es est6ticas:

public cl-ass Teststatic {

public static void main(StringlJ args) t

System. out . print]n ( Integer.lvl,i\X_VALUE ) ;

System. out. . println ( Integer. toHexStrj-ng (42) ) ;1

l

iDepois das importag6es est6ticas:

import stat.ic java. lang. System.out;

import static java. 1ang. Integer. *;hl'1^'1 .i

^ ^'l --^ r^^n.qf rf i nTmnnrt II/UUf rU LrdDD ICDLOLdLIUTTTLIJUT L I

public static void main(String[] args) {

out.printl-n (MAX VALUE) ;

out . prj-ntln (toHexst.ring (42) ) ;

)

ltAmbas as classes produzem a mesma saida:

2747 483647

Vamos ver o que est6 acontecendo no c6digo que usa o recurso das importag6es est6ticas:

1. Embora o recurso seja normalmente chamado de 'lmportagio estitica", a sintaxe DE\IE ser import staticsegu.ida pelo nome totalmente qualificado do membro stat i c que voc6 deseja importar, ou enteo um coringa. Nestecaso, estamos fazendo uma importagio estitica no obieto out da classe System.

2. Nestecaso,poderiamosquererusatdiversosmembrosstaticdaclassejava.lang.Integer.EstainstruEioimport stat ic usa o coringa para dtzer"eu quero fazer importagio est6tica de TODOS os membros stat i cdesta classe".

3. Agora finalmente estamos vendo o beneficio do recurso! Ndo tivemos de digitar System in System.out.prindn! Uau!Em segundo lugar, nio tivemos de digitat o Int.eger em Integer. MAX_VALUE. Assim, nessa linha de c6digo,pudemos usar um atilho para um m6todo static Epanuma constante.

4. FinaLmente, fazemos mais um atalho, desta vez p^r um m6todo da classe Integer.N6s fomos um pouco sarc6sticos sobre esse recurso, mas nio somos os rinicos. Ainda nio estamos convencidos de que aeconomia 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.

lmportag6es Est6ticas

// t// 2

// z

Page 468: Java - Scjp 5 - Portugues

442 Cooitulo l0: Desenvolvimento

Eis algumas regras para se usar importag6es estiticas:

I A sintaxe deve ser import sEaLic; static import est6incorreto.

I Cuidado com membros static com nomes ambiguos. Pot exemplo, se fizer uma importagdo est|icapafaaclasse Integer e para a classe Long, uma referdncia a MAX-VALUE causar6 um erro de compilaglo' uma l'ez que

tanto Integer quanto Long possuem uma constante MAX-VALUE , eJava nio poder6 saber a qual

MAX_VALUE vocd est6 se referindo.

I Epossivelfazerwma'tmportagdoest6ticaemrefer€nciasaobjetosstatic,constaotes(embre-sequeelassiostatic e final-). e m6todos static.

N6s comegamos explorando o comando j avac com mais profundidade. A opgio - d lhe permite colocar arquivos de

classes gerados pela compilagio em qualquer diret6rio que quiser. A op96o - d lhe permite especificat o destho dos arquivos

de classes rec6m-criados.

Em segrida, falamos sobre algumas das opg6es disponiveis atrav6s do iniciador de aplicativos j ava. Discutimos a otdem

dos argumentos que j ava plde usar, iniluindo [opq6esJ class largument.os] . N6s aprendemos como

consultar e afi^liz rptopriedades de sistema no c6digo e na linha de comando, usando a opgio -D.

O t6pico seguinte referiu-se ao tratamento dos argumentos de linha de comando. Os principais conceitos sio que esses

".go-..rtoJrio colocados em um arcay deStrings, e que o primeiro argumento vai para o elemento 0 do arr y, o segundo

argumento vai para o elemento 1 e assim por diante.

Passamos para o importante t6pico referente a como j ava e j avac Procuram por outros arquivos de classes quando

precisam deler, "

.oho ambos bs comandos usam o mesmo algoritmo para encontrar essas classes. Existem locais de busca

pr6-definidos pela Sun, e outros locais de busca, chamados classpaths, que sio definidos pelo usu6rio. A sintaxe para

ilasspaths no Uni* 6 diferente da sintaxe para classpaths do Windows, e o exame tende a usat a sintaxe do Unix'

O t6pico sobre pacotes veio em seguida. Lembre-se de que, depois que vocd colocar uma classe em um pacote, o seu nome

se torna at6mico - em outras palavras, n6o pode ser dividido. Existe um relacionamento intimo entre o nome de pacote

totaknente qualificado de uma classe e a estrutura de diret6rios na qual a classe reside.

Os arquivosJAR foram discutidos em seguida. Os arquivosJAR sio usados para comprimir e arquivar dados. Eles podem

ser usados para arquivar estruturas arb6reas de diret6rios inteiras em um tinico arquivoJAR. Os arquivosJARpodem ser

vasculhados pot j ava e pot j avac.

N6s tetminamos o capitulo discutindo um recurso novo deJava 5, as importag6es est6ticas. Esse 6 um recurso aPenas

deconveni€ncia,quereduzanecessidadedesedigitarnomeslongospa:amernbtosstatic dasclassesquevoc6usarem seus Pfogfamas.

E Aopgioexisa.

tr

tru

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.

- d pode criat, automatjcamente, classes de destino dependentes do pacote, caso o diret6ri o-ruz do pacote i6

fl Use aopgdo -Demconjuntocomocomando java quandoquisetdefinirumapropriedadedesistema.

As propriedades de sistema consistem de pares de nome = valor que devem ser anexados diretamente ap6s -D, porexemplo, j ava -Dmyproperty=myvalus.

Os argumentos de linha de comando sio sempre tratados como Strings.

O argumento de linha de comando java nfmero 1 6 colocado no elemento 0 do array; o argumento 2 € colocado noelemento 1, e assim por diante.

Procurando com java e javac (Objetivo 7.5)E j ava e j avac usam ambos o mesmo algoritmo P^t^procurat por classes.

E A busca comega pelos locais que cont6m as classes que v€m com oJ2SE.

D Os usu6rios podem definirlocais de busca secund6rios usando classpaths.

0 Padr6es de Classpaths podem ser definidos usando-se vari6veis de ambiente do SO.

Page 469: Java - Scjp 5 - Portugues

JAVA 5 443

E Pode-se declarat um classpath na linha de comandq e ele substirui o classpath padrio.

O Um mesmo classpath pode definir muitos locais de busca diferentes.

0 Em classpaths do Unix, sio usadas batas (/) p^x sepzu:^r os diret6rios que compSem um caminho. No rVindows, siousadas barras invertidas (\).

E Em Unix, sio usados dois-pontos (:) panseparar os caminhos dentro de um classpath. No Windows, sio usadospontos-e-virgulas (r.

D Em um classpath, para especificar o diret6rio atual como local de busca, use um ponto (.)

El Em um classpath , uma vez encontrada uma classe, a busca 6 interrompida, de modo que a ordem dos locais debusca 6 importante.

Pacotes e a Procura (Objetivo 7.5)E Quando uma classe 6 colocada dentro de um pacote, deve ser usado o seu nome totaLnente qualificado.

E Uma instrugdo import fornece um nome-c6digo para o nome totalmente qualificado de uma classe.

D Para que uma classe possa ser localizada, o seu nome toalmente qualificado deve ter um relacionamento intimo com aestrurura do diret6rio onde ela reside.

El Um classpath pode conter tanto caminhos relativos quanto absolutos.

0 Um caminho absoluto comega com uma / ou uma \.D Apenas o diret6rio final de um dado caminho ser6 vasculhado.

Arquivos fAR (Objetivo 7.5)Q E possivelatmazenar toda uma estrutura atb6rcade diret6rios em um mesmo arquivoJAR.

0 E possivel procurar em arquivosJAR usando-se j ava e j avac.

0 Quando voc6 inclui um arquivoJAR em um classpath, deve incluir nZo somente o diret6rio no qual se localiza oarquivoJA\ mas o nome desse arquivo tamb6m.

J Parafazer testes, voc6 pode colocar arquivosJAR em - . . / jre/l-ib/ ext,que fica em algum lugar dento da drvorede diret6riosJava na sua mdquina.

lmportag6es Estiticas (Objetivo 7. | )B Voc6 deve comegar uma instrugio de importagdo estitica desta forma: import staticE Voc€podeusarimportagdesestiticasparaciaratalhosparamembrosstatic (vari6veis,constantesem6todos

statie) de qualquer classe.

Teste Individual

l. Dadas estas cl:Fses de diferentes arquivos:package xcom,'

public class Useful {

int increment(int x) { return ++x; }

)

import xcom.*; // linha l"

class Needy3 {

public static void main(Srringll args) {

xcom.Useful u = new xcom.UsefulO; // Iin}ra 2

System.out.println(u. increment (5) ) ;

)

)

Quais afirmativas sio verdadeiras? (I\4atque todas as cortetas)

A Asaida60.

B. Asaida65.

Page 470: Java - Scjp 5 - Portugues

444 Copitulo l0: Desenvolvimento

C. Asafda66.

D. Acompilagtrofdha.

E. O c6digo compila se a linha 1 fot removida.

E O c6digo compila sealinha2formodificadapara

Useful u = new UsefulO;

2. Dada a seguinte estrutura de diret6rios:or9

| -- Robot.cl-ass

I

I -- .*| -- Pet.class

I

| -- 'hv| -- oos.class

E o seguinte arquivo-fonte:

^1 ^-^ ^"--^1 ^-^ |urdss rYryvrdsE 1

Robot r;Dats ^.

Dog d;

)

Qual(is) instrugio(6es) deve(m) ser adiciona(s) para que o arquivo-fonte possa compilar? (1\4arque todas as corretas)

A. package org,.

B. j-mport or9.* ;

C. package or9.*;D. package org.ex;E. import org. ex. *

,.

E package org.ex.why;

G. package org. ex.why.Dog,.

3. Dado:1,. // insira o c6digo aqui2. class StatTest {

3. public static void main(String[] args) {

4. System.out.println(Integer.I4AX_VALUE) ;

5. l-1b. 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. * ;

Page 471: Java - Scjp 5 - Portugues

JAVA 5 445

class _ {

static public void main(String. . . _A_V_) {Cf rin^ < - N/.vut^rr: Y -

f or ( int x=0 i ++x " _A_v_.length; )

g += _A_V_[xl;out.println($);

)

)

E a linha de comando:

java_-A

Qual 6 o resultado?

A- -AB. A.

C. -1.

D. -A.

E. _-A.E Acompilagdofalha.

G. E langada uma excegio no tempo de execugio.

5. Dado o classpath padrSo:

/fooE esta estrurura de diret6rios:

foo

I

I

xcom

| --A.class

| --8. java

E estes dois arquivos:

package xcom;

publicclassA{ }

package xcom;

public class B extends A { }

Qual opglo permite que B . j ava compile? $4arque todas as corretas)

,{. Definir o diret6do atual como xcom e depois chamat

i arr: n Il 'i elra

B. Definir o diret6rio arual como xcom e depois chamar

javac -classpath B.java

C. Definit o diret6rio atual como test e depois chamar

javac -classpath xcom/B. java

D. Definir o diret6rio atual como test e depois chamat

javac -classpath xcom B.iavaE. Definir o diret6rio arual como Eest e depois chamar

javac -classpath xcom:. B.java

Page 472: Java - Scjp 5 - Portugues

446 Copftulo l0: Desenvolvimento

6. Dados dois arquivos:package xcom;

public class Stuff ipublic static final int MY-CONSTANT = 5;

public static int doSt.uff(int x) i return (x++)*x; )

)

import xcom,Stuff.*;import j ava. 1ang. System. out ;

cl-ass User {

public static void main(Stringil args) {

new Userll.goO;

)

void goO { out.println(dostuff(MY_CONSTANT) ); }

i

Qual 6 o resultado?

a* 25

B. 30

c. 36

D. Acompilagdofalha.

E E langada uma exceg6o no tempo de execugio.

7. Dado que dois arquivos:a=b. j ava

c_d. class

Estio no diret6rio atual, qual(is) chamada(s) de linha de comando podeiafrnahzar sem erros? (I\4arque todas as corretas)

A java -Da=b c_d

B. java -D a=b c_d

C. javac -Da=b c_d

D. javac -D a=b c d

8. Dados tr6s arquivos:package xcom;

public class A i/ / insira o c6digo aqui

)

package xcom;

public class B extends A {public void doBO { System.out.println("B.doB"); } }

import xcom.B;

class TestXcom {

public static void main(Stringll args) {

g b = new BO; b.doBO; b.goO;

Page 473: Java - Scjp 5 - Portugues

JAVA 5 447

l

Qual opgdq se inserida em / / insira o c6digo aqui, permitir6 que todos os tr€s arquivos compilem? @larquetodas as coretas)

A void go() { System.out.println(..a.go"); }

B. public void goO { System.out.println("a.go"); }

C. private void goO { System.out.println("a.go"); }

D. protected void goO { system.out.println("a.go"); }

E Nenhuma dessas opg6es permitir6 que o c6digo compile.

9. Dado:class TestProps {

public static void main(Stringtl args) {

String s = System.getProperty("aaa","bbb" ) i

)

)

E a chamada de linha de comando:

java -Daaa=ccc TestProps

O que 6 sempre verdadeiro? (trIarque todas as correas)

.d O valot da propriedade aaa 6 aaa .

B. O valor da prcpriedade aaa 6 bbb.

C. O valor dapropriedade aaa 6 ccc.

D. O valor daptopriedade bbb 6 aaa.

E. O valor dapropriedade bbb 6 ccc.

E A chamadando frnalizat6 sem erros.

10. Se existirem tr6s vers5es de MyClass.iava em um sistema de arquivos:Avetsio 1em /foo/barAversio 2 em / foo/bar /bazAversio 3 em / foo /bar /baz /bing

E o dasspath do sistema incluir:

/foo/bar/bazE 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.javaB. / too/barlMyC1ass. java

C. / foo /bar /baz /MycLass. java

D. / foo/bar /baz/bing/MyClass . j ava

E O resultado nlo 6 previsivel.

I l. Quais afirmativas sio verdadeiras? (Marque todas as corretas).d O comando j ava pode acessar classes de mais de um pacote, a partir de run mesmo arquivoJAR.

B. Os atquivos JAR podem ser usados com o comando j ava, mas nio com o comando j avac,

C. Parapoderemserusadospor java,osarquivosJAR deuemsercolocadosnosubditet6rio / jrellibl extdentrodadtvore de diret6rios J2SE.

Page 474: Java - Scjp 5 - Portugues

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 inrrl-r-lia crrina zgluelt (String a, String b) { return a+b; }

)

import pkg.*;

c-Lass useKltr t

-,,L1 l^ ^r^r:^ -vq!f,ru ELduru yoid main(String[] args) {

String s = new Kit O .gluelt (args [1] , args [2J ) ;

System. out.println (s) ;

)

)

E a seguinte estrutura de subdiret6rios:

t--| --useK].f'.cIass

I

com

l--Kr-t.uar.larSe o ditet6rio atual for test, e o arquivo pkg/Kit . cl-ass estiver em Kit,far. j ar, qual linha de comandoproduzirS,a saida bc? O4arque todas as corretas)

A. java UseKit b cB. java UseKit a b c

C. java -cl-asspath com UseKit b cD. java -classpath com:. UseKit b cE java -classpat,h com/Kit,Jar. jar UseKit b cF. java -classpaLh com/KitJar.jar UseKit a b cG. java -classpath com/Kit,far.jar:. UseKit b cFI. java -classpath com,/KitJar.jar:. UseKit a b c

Respostas do Teste Individual'l'. D est6 cotreta. O m6todo increment ( ) deve ser matcado com public para ser acessado fora do pacote. Se incre-

mentQ fosse public, C, E e F estariam corretas.

A e B sio saidas incorretas, mesmo se increment ( ) for publ i c. (Objetivo 7.1)

Z B,EeFsSoexigidas.AfnicamanekadeseacessaraclasseDog6atrav6sdeF,que6umainstrugiopack^ge,IJmavezque voc6 s6 pode ter uma instrugio package em u1n arquivo-fonte, ter6 de obter acesso is classes Robot e Pet usandoinstrug6es 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 oc6digo tamb6m compilari sem nenhuma das importag6es.

4 B, D e F estlo incorretas com base no exposto acima. (Objetivo 7.1)

4. B est6 correta. Esta questdo estd usando identificadores v6lidos (mas inapropriados e esquisitos), importag6es est6ticas,var-args em main ( ) e l6gica de pr6-incrementagio.

Page 475: Java - Scjp 5 - Portugues

5.

JAVA5 449

A, C, D, E, F e G 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, ocompilador ndo a encontrat| se for chamado a partir do diret6rio xcom. Lembre-se de que - c las spath nio est6procurando 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 enconffarB. j ava. (Objetivo 7.2)

D est6 corteta. Para importar membros estAticos, a instrugZo import deve comegar com: import static.

A, B, C e E estio incorretas com base no exposto acima. (Obietivo 7.1)

A est6 cotreta. -D nio 6 um flagde compi-lagio, e o parnome = valor associado com -D precisavirlogo depois de -D,sem espagos.

B, C e D estao incorretas com base no exposro acima. (Objetivo 7.2)

B 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 B, D e E estio incorretas com base no exposto acima. (Objetivo 7.1)

C est6 cotteta. O valor de aaa 6 definido na linha de comando. Se aaa nio tivesse nenhum valor ouandoget Property foi chamado, entio aaztena sido definido como bbb.

A, B, D, E e F est6o incorretas com base no exposto acima. (Obietivo 7.2)

10. D est6 cotret^. Um - clas spath incluido com uma chamada a j avac substitui o classpath do sistema. Quandoj avac esti usando um classpath, ele 16 o classpath da esquerda para a direita e usa a primeira corresponddncia queencontrat.

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

11. AeDesteocoffetas.

B esti incorreta porque j avac tambdm pode usar arquivosJAR. C est6 incorreta porqueJARs podem estarlocalizados em . . . / jre / Iib / ext, mas eles tambEm podem ser acessados se residirem em outros locais. E estiincorreta, os arquivosJARmant€m estruturas de diret6rios. (Obietivo 7.5)

72. Hest6,coteta.

A,C,EeGestioincorretaspeiosimplesfatodequeargsI J comegaporzero.B,DeFestaoincorretasporquejavaprecisa 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)

6.

7.

8.

9.

Page 476: Java - Scjp 5 - Portugues

450 Copftulo l0: Desenvolvimento

Page 477: Java - Scjp 5 - Portugues

,it!,ii Ap6ndice A

Sobre os stqulvosdlsponlvels poro

donwlosd.

.. t :":

" ij:

Page 478: Java - Scjp 5 - Portugues

452 Ap6ndice A

Os arquivos disponiveis para donwload, no site wwrv.altabooks.com.br, vdm com o MasterExam (todos os arquivos estZo

em ingl6s). O software 6 ficil de instalar em qualquer computadorWindows 98/NT/2000, e para que os recursos do

MasterExam possam ser acessados ele precisa ser instalado. Para registrar-se para um segundo MasterExam, basta clicar nolink Bonus Material da pigrna principal e seguir as instrug6es para acessar o registro online.

Requisitos do sistemaO software requer o \X/indows 98 ou superior, o Internet Explorer 5.0 ou superior e 20 MB de espago no disco rigdo pan a

instalagio completa.

Instalando e executando o MasterExamA partir da tela de abertura voc6 poder6 fazer zinstzlagdo pressionando os bot6es do MasterExam. Isso iniciari o processode 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 tempopermitido foram definidos para ser uma representagio precisa do ambiente do exarne. Voc€ ter6 a opgdo de fazer um examecom o livto aberto, incluindo dicas, refer€ncias e respostas; um exame com o livro fechado; ou a simulaqio MasterExamcom tempo definido,

Quando voc6 iniciar o MasterExame, um rel6gio.ligrtal apatecer|no canto superiot esquerdo da sua tela. O rel6giocontjnuat6,acontagem tegressivaat€zero a menos que voc6 selecione terminato exame antes que o tempo expire. Pata seregistar a fim de teceber outro MasterExam, simplesmente clique no link Bonus MateialdapAgjna principal e siga as

instrugdes para o rcg1svo on-l.ine graruiro.

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

O MasterExam ser6 instalado em sua unidade de disco rigrdo. A fim de obtet melhores resultados no que diz respeito iremogio 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 poderemover os pfogramas de treinamento da LearnKey nesse local.

Removendo instalag6es

Suporte t6cnicoPara enviar perguntas relacionadas ao contefdo t6cnico do livro elet6nico ou do MasterBxam, visite o sitewww.osborne.com ou mande uma mensagem (em ingl€s) de correio eletr6nico para [email protected] fora dos Estados Unidos, devem enviar a mensagem para [email protected].

Suporte t6cnico da LearnKey

Para solucionar problemas t6cnicos no software (instalagio, operagio, remogio de instalag6es) e para enviar perguntasrelacionadas a qualquer conterido do treinamento on-line da LearnKey, visite o site www:learnkey.com ou mande umamensagem de coreio eletr6nico para [email protected].

Page 479: Java - Scjp 5 - Portugues

JAVA2 453

Page 480: Java - Scjp 5 - Portugues

Este livro foi impresso nas o{icinas gr6ficas da Editora Vozes Ltda.,

Rua Frei Luis, 100 - Pet6polis, RJ,

com papel fornecido Pelo editor.