Escolar Documentos
Profissional Documentos
Cultura Documentos
e desenuoluedor em Jaua
S an@
como
"Kathy Sierra 6 uma das poucas pessoas no mundo que consegue fazer coisas complicadas parecerem murto simple;. E se isso nio fosse suficiente, ela consegue fazer com que assuntos mon6tonos paregam interessantes. Sempre fico ansioso para ler o que Kathy escreve - ela 6 uma de minhas autoras favoritas".
- Paul IYheaton, Chefe
de
Aconpanbamento
da JauaRanch.com
"Quem melhor para escrever um guia de estudos sobre Java do que Kathy Si_err.a, que reina soberana quando se trata de treLamento emlava? Kathy Sierr-a conseguiu novamente - aqui est6 um guia de estudos que j6 poder6 lhe garantir a
cenifica$o!"
-
"O que mais aprecio em Kathy 6 seu esforEo p arafaznr comque todosnos lembremos de que estamos ensinando pessoas . nio aoenas fa"endo uma palestra sobre Tava. Seu entusiasmo e vontade em oferecer um treinamento da mais alta .. rreza nio encontra paralelo na sunEd. s.* a""iar, h6 centenas i; -
de
a suas aulas"
de
Sun
,1
aJq.
"Quero agradecer
**Jira
diiil;;;
sentir6 em uma sala de aula como se algu6m estivesse realmente lhe ensinando os conceitos e fria. As perguntas no final dos capftulos tambm slo MUTIo boas e estou certo de "ilde que aju&rio os candidatos a passarem no tesi. Fique alerta para esse livro incrivelmente astuto".
Kathy pelo EXCELENTE guia de esudos. O livro 6 bem.escrito,.informa especificamente o que voc6 ri'U.r.ro.*"-..."d,conceito 6 explicaio de maneiraclaracom autilizagio deum exemplo davidareal' Da
a
se
maneiraformal
Atfred RaouJ
Desenuoluedor de Solugdu
na
IYeb
da Sun cerramente nio foi como um passeio no parque' mas o material de Kathy permitiu nio s6 que eu Passasse no exame, mas que passasse bem!" - Mary lqhetsel, Etpecial^ta S1nior em Tecnologla, Integragdo e Estrategla de Aplicagdes, Tbc St. Paal Corapaniet
O exame de certificagio
de transformar com-plexidade em simplicidade ao oferecer um do que 6 necessirio para o exame da certificaqXo". percurso dirigido no aprendizado
habilidade em expressar claramente conceitos complexos aos que assistem consguem se tornar especialistas no que Ben tem a ensinar".
"por
sua
a seus
"Achei
ideal de
este
livro exrremamente 6til para ajudar o candidato a passar no exame. Ele foi muito bem escrito, com a qtrantidade
come"."ri"r b.*-ftJ-oi
tio dificil'
-Nico/e Y. McCallough
ecertar 980/o(60 de 61). Esse sucesso nio teria sido possivel sem
este livro!"
,,EvfizoSCJp
emJulho de 2004 e consegui 957o (58/.6l).Kathy e Ben t6m um estilo incrivel de escrever' literdmente-grav"ra- ot.o.t..itos principais na minha cabega."
1.4
"Eu fiz meu teste de certificagio semana passada e fui aprovado com 95o/o de acertos. Se nio tivesse estudado por este livro, teria poucas chances de obter um resultado tio bom. Obrigado, Kathy e Bert, pelo maravilhoso livro!" -lon W. Knsting (Smatoga, Califomia, Estadot Unidos)
"Nio hesite em fazer deste livro o seu principal guia para preparar-se para o SCJP 1.4. Os autores fizeram um trabalho magnifico ao apresentar os fatos imponantei qe pricisar6 sabei para o exame, ao mesmo rempo deixaram de lado "oc6 toneladas de outras informag6es que,em outro contextb, seriam importantes, mas que vlo al6m do escopo deste livro. Ambos os autores participaram da criagio das quest6es reais do exame, fornecendo iessa forma um valiosissimo insight sobre a verdadeira natureza do que vocA.encontrari no exame. Ao contririo de muitos outros guias de cenificagio. Esti aqui 6 uma leitura p razerosa. Neste livro, at6 os mais enfadonhos objetivos da Sun sio combinadoi com um revigo.*t. bo.rihumor."
-Vad Fogel (Onlaia, Canadi.l
tv
Certilicagiio
Sun@
5-
Do original Sun@ Certified Programmer for JavarM 5 Study Guide (Exam 3 I 0-05 5) - Copyright @ 2006 da Editora Alta Books Ltda. Authorized translation from the English language edition, entitled Sun@ Certified Programmer for JavarM 5 Srudy Guide (Exam 310-055), by Sierra & Bates, published by Osborne/MacGraw-Hill, publishing as The MacGraw-Hill Companies, Copyright @ 2006 by Osborne/MacGra,v-Hill. PORTUGUESE language edition published by Editora Alta Bool<s, Copyright @ 2006 by Editora Alta Bool{s.
Todos os direitos reservados e protegidos pela Lei 5988 de I4ll2l73. Nenhuma parte deste livro, sem autorizagdo pr6via por escrito da editora, poderS ser reproduzida ou transmitida sejam quais forem os meios empregados: eletr6nico, mecanico, fotogr6fico, gravag5o ou quaisquer outros. Todo o esforgo foi feito para fornecer a mais completa e adequada informagdo, contudo a(s) editora(s) e o(s) autor(es) nAo assumem responsabilidade pelos resultados e usos da informagdo fornecida. Recomendamos aos leitores testar a informagdo bem como tomar todos os cuidados necess6rios (como o backup), antes da efetiva fiilizagdo. Este livro n6o contdm CD-ROM, disquete ou qualquer
outramidia. Produgiio Editorial: Editora Alta Books Coordenagflo Editorial: Fernanda Silveira Thadugiio: Marcelo Soares Revis6o: Fernanda Silveira RevisEo T6cnica: Leonardo Rota-Rossi Colaboragflo T6cnica: Gabriel Fairbanks, Leonardo Gangemi eAnderson Xavier Diagramagiio : Aldenir Gil
Erratas e atualizag6es: Sempre nos esforgamos para entregar a voc6 leitor um livro livre de erros t6cnicos ou de conteido, por6m nem sempre isto 6 conseguido, seja por motivo de alteragilo de software, interpretagdo ou mesmo quando alguns deslizes constam na versdo original de alguns livros que traduzimos. Sendo assim, criamos em nosso site www.altabooks.com.br a seg6o Erratas, onde relataremos, com a devida corregSo, qualquer erro encontrado em nossos livros.
Aviso e Renfncia: Este livro 6 vendido como est6, sem garantia de qualquer tipo, seja expressa ou implicita.
Marcas Registradas: Todos os termos mencionados e reconhecidos como Marca Registrada e/ou comercial sdo de responsabilidade de seus proprietiirios. A Editora informa n6o esfar associada a nenhum produto e/ou fomecedor apresentado no livro. No decorrer da obra, imagens, nomes de produtos e fabricantes podem ter sido utilizados e desde j5 a Editora informa que o uso 6 apenas ilustrativo e/ou educativo, ndo visando lucro, favorecimento ou desmerecimento do produto/fabricante.
l'de
Julho de 1992 proibe expressamente o uso coletivo sem autorizagdo dos detentores
do direito autoral da obra, bem como a c6pia ilegal do original. Esta pratica generalizada nos estabelecimentos de ensino
provocam uma brutal bqixa nqs vendas dos livros ao ponto de impossibilitar os autores de criarem novas obras.
A McGraw-Hill/Osborne d uma entidade sem ligaEdes com a Sun Microsystems e ndo tem nenhum vinculo de afiliaqdo com a illtima. Essa publicaqdo pode ser usada como auxllio na prepqraqdo dos alunos para o exame de certificagdo da Sun em Java 2. Nem a Sun Microsystems ou a McGraw-Hill/Osborne garqntem que o uso dessa publicagdo assegurard sucesso no exame em questdo. Sun, Sun Microsystems e o logotipo da Sun sdo marcas registradas da Sun Microsystems.Inc. nos Estados Unidos e em outros paises. Java e todas as marcas relacionadas sdo marcas registradas da Sun Microsystems Inc. nos Estados Unidos e em outros paises. A McGraw-Hill/Osborne ndo tem ligaqdo com a Sun Microsystems, Inc.
Rua Viriva Claudio,29l - Jacaft Rio de Janeiro - RJ. CEP: 20970-031 TeI: 21 3278-8069/ Fax: 21 3277-1253
ESeitrrRl*|E wu{w.osborne.Eorn
JAVA
5V
ParaaComtrnida&Java
Sum6rio
capirulo | - DEclAnag6es
ldentificodores e
coNTRoLE DE AcEsSo....................................
.........
Polovros-chove........... Closses
Encontrondo Outros
..................'...... 2
............3
....--.-.-.. 3
Legais
...................
..........6
.....-.'............... 6
Outros Modificodores de Closses (N6o-re{erentes o Acesso) Exercicio l- | Criando uma Superclasse Abstrata e uma Subclasse
Concreta
.....' | 0
Objetivo
paraaCertificag6o............
.............
.......... ll .'........ I I
t4
14
Membros Protecl e
Defoult Protect
.......
.................
19
Acesso
..................... 23
Synchronized (vor-orgs)
..'.......... 27
.......-...-.......--.. 27
............. 30
...........' 30
........-.... 3l
.........
Declorog6es de
..........'.. 33
5 VII
Stotic.........'.. ..........
................ 35 ...... 37
CAPITULO
2'
.............
I do
exame)
.........50
................ 50
Exame)
.....52 ............55
TEM-UM
Exame)
........58
.......58
1.5 e 5.4
do
Exame)
..........60
................... 60
............... 63 ..... U ................ ................ .......
Chomondo o versOo do superclosse de um m6todo subscrito Exemplos de subscrilos de m6iodo v6lidos e ndo-v6lidos ................
Sobrecorgos
v6lidos
&
65
&
Exame)
.............
exame)
................71
exame)
74 ........74
.....
.................
74
75
.............
exame)
.........77
.........77
....................
77
..............77 ................ 78
................
79
ldentifcando se um constru Como voc6 pode ter o certezo de que um conslrutor podr6o ser6 criodo? O que oconlecer6 se o conslruiuor do superclosse tiver orgumentos?...........
..........80
vlll
Objetivo para a Certificagio
..........
................. 85 ................... 85
..........88
........ 88
Pilha e Heap
- Uma Revisio
.... 102
.............
I
.3 e 7.6 do
Exame)
.......1U
................ 05
.................... ]07
.......... I l0
Convers6o detipos
AtribuiE6es de vori6veis de
Usando umavari6vel ou elemento de array que nlo tenha sido Vori6veis de instdncio de tipo primiiivo e de obieto Voridveis de instdncio primitivos Vori6veis de insi6ncio de refer6ncio o obietos Vori6veis de instdncio de orroy Tipos primitivos e obielos locois (de pilho, outom6ticos)
Refer6ncios de Obietos
.......... I 13
.................
1.l3
..........-....... I 13
................... I 14 ...................... I l5
........... I 16
1ocois.......... ouiro
.................117
exame)
........ | | .......... I l8
............ l19
AlinguagemJavausaasemnnticadepassagemporvalor?
Objetivo para a certificagio
DedaraEio, construgao e inicializaEio de arrays (objetivo 1.3 do
Declorondo um orroy de tipos Construindo orroys Construindo orroys
exame)
...122
..... |-22
.....122
primitivos
unidimensionois multidimensionqis
...........123 .........124
JAVA
5 IX
lniciolizondo elementos em um loop ........... Declorondo, construindo e inciolizondo em umo linho Construindo e iniciolizondo um orrov on6nimo AtribuiEoes v6lidos poro os elemenlos do Arroys de tipos primitivos
..........
Arroys de referGncio AtribuiE6es de vori6veis de refer6ncio de orroys unidimensionois Atribuigoes de vori6veis de re{er6ncio de orroys multidimensionois Blocos de Iniciolizo96o ..............
............... o obietos
orroy
.............. ............
t33
133
wrapper octol)
porseXrx$ e
volueOffl .
....
..
............
::,
equolsfl Boxing
.................. l3B
Exame)
Sobrecorregondo do Moneiro Di{icil- Correspond6ncio de M6todos Sobrecorgo com Boxing e Vor-orgs Ampliondo Vori6veis de Refer6ncio Sobrecorgo no CombinoE6o de AmplioE6o com Boxing Sobrecorgo em CombinoE6o com Vor-orgs
142
exame)
............... ............
.... 143
............ 143
Como o coletor de lixo funciono? Escrevendo um c6digo que torne os objetos explicitamente qualificados Anulondo umo refer6ncio ............... Reotribuindo umo voridvel de referGncio lsolondo umo refer6ncio ............... ForEondo o coleto de lixo Fozendo umo limpezo ontes do coleto do lixo - o m6todo finolize( Cuidodos relocionodos com finolizefl ......... . .
..............144 ..144
) ..
...
exame)
.................. 162
......162 .........162
deAtribuiE6o Compostos
x
lguoldode de tipos pdmilivos lguoldode de vori6veis de referGncio lguoldode poro Enums Operodorde comporog6o inslonceo{ Erro de CompiloE6o de instqnceof .................
O Operodor
Resto
(%)
.'.........
168
Exome!) OperodoresL6gicosdeAbrevioE6o................ Operodores l6gicos (que n6o s6o de obrevioE6o) Operodores L6gicos ^ e !...........
Operodores Bitwise (N6o Coem no Resumo para a certificagio
E AssERTlvAs...o............. 183
t84
.......... 184
..................
186
............
Breokeopossogemcompletoemblocosswitch......... defoult
.....190
.........192
exame)
LoopforBdsico Declorog6oeiniciolizoE6o................ Loop for Bdsico: Express6o condicionol (booleono) LoopforBdsico: Express6ode iterog6o.. LoooforB6sico:Corocleristicosdolooofor.............. O Loop forAprimorodo (poro Arroys)
LoopforBdsico:
.................,l95
.....|95 .|95 .........
exame)
................. 20
exceg6es
.........208
JAVA
5 XI
......214
...................214
.....214 .....................214 .................215 .............215
ExceE6es JVM
......... Exome
...216
..........216
exame) ...............
................ iovoc
seletivo
Use os ossertivos poro volidor orgumentos de um m6todo ......222 N6o use ossertivos poro volidor orgumenios de linho de .......222 N6o use ossertivos, mesmo em m6iodos p0blicos, poro procuror instrug6es cose que sobe que nunco ocorre16o ..222 N6o use express6es ossedivos que possom cqusor efeitos ....223
privodo. comondo
..................222
coloteroisl
.............
exame)
.......238
......... 238 ...................238
.......................24
|
inolter6veis
mem6ria
String.........
............242
..............242
......244
.............245
......245
Exame)
246
...............246
.................247 ..................249 ......................250
.......252
do
Exame)
......254
........254
xil
Trobolhondo com ObiectOutputStreom e Gr6ficos de Usondo wrileObiect e Como o HeronEo Afeto o A SeriolizoEoo n6o 6 poro Est6ticos
................255 ...............256
............... 258
.........260 ...............262
Exame)
Nimeros
...263
.... ...............263 .................265 .............266 ............270
A Closse NumberFormot
Exame)
........27 | .......271
O Ponto Pr6-definido
,,,,.........'273 .............275
......275
.....................276
....277
..............279
......279
..............280
cApiTuLo7-GENfRlcosEcoNfuNToso.........o...o.ooo......o.o...................oo........zgs
Objetivo para a certificagio
.............
exame)
.......296
...296
...............297 .. ...............298 ............300 ............300
......30'l
... ....... .
.................
hoshing ................ ... Objetivo para a certificag6o ............. Conjuntos (Objetivo 6. I do exame)
lmplementondo hoshCodefl O conlroto de hoshCodefl
Interfoces e closses chove do estruturo de
........302
.......304
.......... 304
........304
coniuntos
.........307 ..........308
JAVA
5 XIII
309
Exame)
....... 309
Coleg6es
.......
..
3l
.............. ClossificondocomoClosseArroys........ Fozendo Buscos em Arroys e em Coniuntos .............. ConverJendo Arroys em Listos e de Voltq em Arroys
................... 312
....3j3
.....315 ......315
..........3j7
................... Coniuntos. VisSo Gerql dos M6todos poro Lisl, Set, Mop e Queue......
Usondo o Cfosse PriorityQueue Vis6o Gerql dos M6iodos poro Arroys e
..................322
.....32g
..............324
Exame)
..........32s .........325
Gen6rico Gen6ricos
......342
......................345
36 |
.............
interna
.......362
................3U
...........365
m6todo
...366
.............366
..................... 367
an6nimas
aninhadas
...373
....... 323
.............
.......384
.......... 384 ............... 385
........393
Exame)
.......... 393
Criando
.398
exame)
o
....... 398
se um threod n6o puder obter Ent6o, Quondo Eu Preciso Closses Seguros em ReloEdo o
O oue ocontecer6
Sincronizor? Threods
bloqueio?
""""'405
..."' 405
407
"""'
exame)
esperando
"409
...'.4
"
|3
Loop
"
414
Exercicio 9-l: Criondo um threod e coloconoo-o em Exercicio 9-2: Sincronizondo um bloco de c6digo
suspensfio..........'...
cApiTULO l0 - DESENVOLVIMENTO
........o.............o..o...............o..........oo............ 43 |
......432
Exame)
...-..." 432
..............432
-o
"""""' """"""
434 435
Declorondo e Usondo
Pocoleseo
Closspoths Procuro
JAVA
5 )ry
...... ....438
7.5)
439 .....439
.............440
JAR...........
Exame)
..............441 ..............441
APENDICE A..o..o.......o............................................................................................... 45 |
Requisitos do
sistema
...............452
lnstalando e executando o
MasterExam
....452
Suporte
t6cnico
......452
xvl
Sobre os Colaboradores
Sobre os Autores
Kathy Sierra foi desenvolvedora-lider do
exame SCJP paralaval. Sierra trabalhou como instrutora sAnior da Sun e' em 1997, fundou oJavaranch.com, a maiorcomunidade sobreJava nalnternet. Os seus livros recordistasdevendassobreJava
e ela 6
receberam v6rios prAmios da revista Sofrware Development Magazine, Java Champions da Sun.
6
ji
Bert Bates tem sido desenvolvedor-lider de virios exames de certificagio da Sun, incluindo o SCJP paraJava 5. Ele tamb6m moderador de um f6rum emJavaranch.com, e tem desenvolvido softwares por mais de 20 anos. Bert 6 co-autorde diversos livros recordistas de vindas sobreJava, e 6 membrofundador do programaJava Champions da Sun.
Sobre
Sobre o LearnKey
de aprendizado que respeita o ritmo do aluno, e apresenta solug6es de distribuigio de muldmidia para aprimorar habilidades pessoais e produiirridade empresarial. O_ LearnKey apresenta a maior biblioteca de rlm dinAmico aprendizado, rico em diversas fottt.." conterido di treinamento multimidia existent., "o, "irrrro, "'q.r"l videoclips, 6udio, grificos totalmenfe animados e ilustrag6es animadas. O site do LearnKey na web 6 midias, como
www.kamKey.aorrl
Nio
Em primeiro lugar,
honras vio para Kristin Stromberg - toda vez que voc6 vir um pon193-vilgula sendo usado .orrit"-.rrt., alradega a Kristin. Em seguida vem Burk Hufnagel, que_ consertou mais c6digos d9 que estamos.dispostos a admitir. Bill MiJtekkie Gian Franco Caiula corrigiram todos oJtipos dc erros que jogamos para eles - 6timo trabalho, pessoal! Devender Thareja certificou-se de que nidest6vamos usando giria demais, e Mgk Sgrlzler manteve o bom humor. ivfiU{ Z"it i" e Seema Manivannan fizerani impoftantes correg6es no livro todo, e Marilyn de Queiroz e Valentin Crettaz novamente fizeram um trabalho espetacular (novamente salvando os nossos pescogos).
as
Marcelo Onega, Jef Cumps (outro veterano) , Andrew Monkhouse e Jeroen Sterken completam o nosso time de rnp.r"rtror - o*brigado a todos voc6s. Jim Yingst panicipou da equipe de criagio do exame da Sun, e nos ajudou a escrever algumas das quest6es mais dificeis do livro (muahahaha).
Como sempre, toda vez que voc6 vir uma plgina bem esc ita, agradegaaos nossos revisores e, se encontrar um erro' com toda ceneza 6 por culpa dos autores. Ah sim,i um agradecimento final aoJohannes. VocA 6 demais, cara!
JAVA
)O/II
Agradecimentos
Kathy e Bert gostariam de agradecer
as pessoas a
seguir:
r I r r r I r I
Topas incrivelmente esforgadas da Osborne: Tim Green, Jim Kussow, Jody McKenzie e Jennifer Housh por 1s egssoas toda.a ajuda e por serem tXo compreensivas e pacientes - bem, certo, nem tio pacientes assim - mas muito profissionais e o grupo mais agrad6vel de pessoas com quem sepoderiaesperartrabalhar. Os nossos anjos Solveig Haugland
e
Midori Batten, por virem nos salvar quando realmente esr6vamos em apuros!
Akuns dos profissionais de software e amigos que nos ajudaram nos dias iniciais: Tom Bender, Peter Loerincs, Craig Matthews, Dave Gustafson, konard Coyne, Mbrgan Poner e Mike Kavenaugh.
Acima de tudo, a maravilhosa e talentosa equipe de cenificagio da Sun Educational Services, principalmente o Gerente do Progtama de Cenificagio, Steve ('Gooie') Moore e a pessoa mais persistente que ji conhecemos quando se trata de condrsio, Evelyn Cartagena (paraMnspelo rec6m-nascido, Evelyn).
Nossos melhores amigos
e
umexame.
As criangas, Eden e Skyler, por ficarem horrorizadas que os adultos - fora da escola - estivessem estudando tanto para
Todos os outros instrutores antigos e atuais de Java da Sun Ed por aju&rem a torn ar o aprendizado dessa linguagem um1 expel6nciadivenida, (para nomear apenas alguns) : Alan Petersen, Jean Tordella, Georgianna MJa$ier, _incluindo Antho-ny Orapallo, Jacqueline Jones, James Cubeta, Teri Cubaa, Rob '$7eingruber, John Nyquist, AsJk Perumaiiar,
r r
os nossos
Kara.
)o/il1
Preficio
O principal objaivo deste liwo
aJava 5.
6
ajud6-lo
a se
preparar
e passar
t6picos que a maioria dos desenvolvedoresJava encontrarlo nos seus A boanoticia 6 que o exame tende a "borda. tiabalhos. A noticia desafiadora 6 que o exame Java 5 tem escopo bem mais amplo do que o seu antecessor, o exame Java 1.4. Os novos objetivos passam poi muitas das-APIs mais utiliiadas emJava. A palavri-chave aqui 6 "passam por". A
representasse a certeza de que o candidato ente nde osfundanenns de io ex"*. foi qn diarquivos APIs, tais como aquelas usadas para E/S " "provagXo e express6es regulares. Este livro segue o miximo psssivel tanto o escopo quanto a profundidade do exame real. Pbr exemplo, ap6s ler este livro voc6 provavelmente nXo vai acordar no outro di" *-b ,rtn go* d. ,.gr*, mas, se estudar o material, e sair-se bem nos testes individuais, voc6 ter6 um entendimento bisico de regei e se sairilemno exame. Depois de terminareste livro, voc|tericeneza de que estudoutodos os objetivos
este
livro
Este
livro foi organizado de maneira a otimizar o seu aprendizado dos t6picos abodados pelo exame SClPJava- f . Sempre que possivel, n6-s organizamos os capitulos seguindo os objetivos da Sun, mas em.alguns casos misturamos objetivos ou os t-6picos em uma ordem mais adequada para o esnrdo do material. os repeumos parcialirente p"r" "prrs"nt"t
Em cada capitulo
N6s criamos um conjunto de blocos constituintes dos capitulos que chamario sua atengio.para itens importantes, reforgarXo pontos deiestaque e fornecerXo dicas riteis para a hora do exame. Veja o que voc6 encontrar6 em cada capinrlo:
I I I I I
Cada capitulo comegar6 com os Obietivos da Certificag5o - 9-guq vocA precisa saber para passar na seglo do exame que tratar do t6pico refeiente ao capinrlo. Os objetivos serio identificados dentro do capinrlo por seus cabegdhos, portanto' voc6 sempre saber6 qual6 o objetivo quando o vir!
A notas Observag6es para o exame chamario a atengio para informag6es e possiveis armadilhas relacionadas ao exame. LJma vez que eit6vamos na equipe que criou o exame, sabemos pelo que voc6 vai passar!
As notas Ao trabalho descreverXo aspectos priticos de t6picos da certificagXo que podem nio aparecer no exame, mas que serlo riteis no mundo real.
Os exercicios priticos foram incluidos no decorrer dos capitulos. Eles o ajudario a aprimorar as aptid6es,que se limite a leios exercicios! Eles fornecem a pritica na execugio com a Aprender fazendo 6 uma maneira eficaz de aumentar sua capacidade. qual voc6 teri que estar familiarizado.
segXo Nas salas de aula descrever6 as quest6es que surgem com mais freqiiAncia em cenirios de treinamento em salas de aula. Essas barras laterais lhe darXo uma perspe&iva vfiosa sobre t6picoJ relativos i cenificagio e aos produtos. Elas ressaltario alguns dos problemas mais comunJe confusos que os alunos encontram quando fazem um curso deJava.
P&R
I I I
O Resumo para
relacionados ao exame.
O Exercicio Mpido no finalde cada capitulo usado para uma revisio de ultima hora.
os t6picos, a estrutu ra e a naltezadas perguntas encontradas no exame de certificagio. As resposras a essas perguruas, assim como suas explicag6es, podem ser encontradas no final de cada capitulo. Aoiaznr oTeie Individual, depois da concluslo de cada capinrlo, vod reforgar6 o que aprendeu nele ao mesmo tempo em que se fam liarizarS, coma estrutura das perguntas do exame.
JAVA
5 XIX
lntrodu96o
Organizagio
livro foi organizado de maneiraa servircomo um estudo aprofundado sobre o exame de Programador Cenificado pela Sun na PlataformaJava 5 tanto para profissionais experientes na linguagem quanto para os que estiverem nos est6gios iniciais de vi#ncia com as tecnologias Java. Cada capinrlo aborda um dos aspectos principais do exame, com Anfase em perguntas como "por que" e'!olo" pJggramar na linguager-nJava. O livro tamb6m inclui um estudo detalhado dos itens essenciais para obter uma avaliagio positiva no projeto enviado para o exame de DesenvolvedorJava Certificado pela Sun.
Este
Tamb6m nio pretendemos ao mesmo tempo em que o preparamos para o exaffrc tund-|t un especialista n@lcto en Jaua.Esse 6 um guiade esrudos para o a(ame da cenifica$o e sua missio 6 muito clara.Isso nXo querdizer que apreparaSo para o exame nio o ajudari a se tornar um programador Java mais avangado! Pelo contririo, mesmo os mais experientes desenvolvedores Javageralmente relatam que o fato deterque se prepararpara o exame de cenificaSo ostornouprogramadores mais informados e completos do que seriam sem o estudo dirigido para o exame.
No site
Para obter mais informag6es sobre os arquivos para download, consrlte o Apdndice
A.
Algumas sugest6es
Quando tiver terminado de ler este livro, reserve algum te mpo parafazer uma revisio completa. Seria bom retornasse ao livro v6rias vezes e fizesse uso de todos os m6todos que ele oferece para revisar o material:
se
voc6
L Z
3.
RebiatodososExerciciotRtipidotoupegaaalgu|mparalhefazcrasperguntas.Voc6tamb6mpodeusarosexercicioscomo
uma maneira de fazer uma revisio ripida antes do exame. Ou criar alguns cart6es pedag6gicos em fichas 3x5 contendo o material dos Exercicios R6pidos.
Reteia todat as notas da segdo Alerta no Exame. a
Lembre-se de que essas observag6es foram escritas por autores que ajudaram se deparar6 - e com o que dwe tomar cuidado.
Indiuidaais.Fazer os testes logo ap6s ter lido o capitulo 6 uma boa id6ia, porque as perguntas ajudario a reforgar o que voc6 acabou de aprender. No entanto, uma ideia melhor ainda 6 voltar posteriormente e responder todas as perguntas do livro de uma s6 vez. Imagine.que est6 fazendo o exame real. (Quando percorrer as perguntas pela primeira vez, anote suas respostas em.um.pedago. de papel separado. Dessa forma, voc6 poderi responder as perguntas quantas vezes precisar at6 que se sinta familiarizado com o material).
Refapa wTestet Faga ot exercicios.Voc6
4.
fez os exercicios quando leu cada capitulo? Se nlo os fez, faga-os agora! Esses exercicios foram elaborados para abordar t6picos do exame e nio hi maneira melhor de conhecer esse material do que praticando. Certifiquese de compreender porque est6 executando cada etapa de cada exercicio. Se houver algo que nio tiver entendido, releia essa se$o do capinrlo.
os prazos
e
nio
apenas
impraticiveis, geralmente associados. Mas esse exame tentarA avaliar seu as partes com as quais voc6 se familiarizou em seu trabalho.
Somente a experiAncia nio o far6 chegar ao final do exame com uma nota que o aprove, porque mesm o o quevoc| arba qrrc conhece pode funcionarde formaumpouco diferente do que imagina. Nio 6 o bastante conseguirque seuc6digo funcione corretamente;voc|prccisacompreender os fundamentos bisicos de maneiraprofunda e com abrang6ncia suficiente para
xx
abordar tudo que possa surgir durante o uso da linguagem. O Exame de Desenvolvedor Certificado pela Sun 6 rinico no universo de certificaglo em inform6tica, porque naverdade ele avaliar6 sua habilidade como desenvolvedor, em vez de simplesmente seu conhecimento da linguagem ou das ferramentas. Se tomar um DesenvolvedorJ avaCenificado envolve, por defini$o, experiAncia em desenvolvimento.
de Associado,ProgramadoreDesenuoluedoresteo
associados com
Java Standard Edition. Os exames de Componentet IYeb, Ca@onentes de Negocin, Smigos IYeb e Proletista Empresarial estl.o associados com aJava Enterprise Edition . O exane de Aplicatiuot Mriueis est6 associado com aJava Micro Edition. Os exames de Associado, Programador, Componentes'Web, Componentes de Neg6cios, Servigos \il7eb e Aplicativos M6veis sio exclusivamente de mriltipla escolha e do tipo arrastar-e-soltar, e sXo feitos em um centro de testes, enquanto os exames de Desenvolvedor e de Projetista envolvem o envio de um projeto.
O exame
O exame de Programador foi projaado paratestar seu conhecimento na propria linguagem de programagio Java. Ele requer um conhecimento aprofundado da sintaxe da linguagem, dos conceitos principais e de uma pequena quantidade de interfaces de programagXo de aplicativos (APIs, Application Programming Interfaces). Este exame tamb6m testa o conhecimento intermediirio de conceitos de projetos orientados a objetos. Nio avaliarinenhuma questio relacionada ao projeto ou arquitetura do programa e nio perguntar6 por que uma abordagem 6 melhor do que a outra, mas, em vez disso, estarApreocupadoseaabordagem dadafuncionariemumasitua$oespecifica.Estee:<ameniotemnenhumpr6requisito.
O exame de Desenvolvedor tem inicio onde o exame de Programador termina. Ser6 necess6rio passar no exame de Programador antes que voc6 possa se dedicar ao exame de Desenvolvedor. Esse exame requer o desenvolvimento de um programa real e, em seguida, uma justificativa para as decis6es tomadas no projeto. Ele foi elaborado para testar sua compreensio do motivo pelo qual cenas abordagens sio melhores que outras em determinadas circunstAncias e para avaliar sua habilidade em seguiruma especificagio e implementarum programa correto, funcional e amig6vel. O exame de Desenvolvedor 6 composto de duas panes: a tarefa de criagXo de um projeto e um exame com quest5es dissenativas como acompanhamento. Seri dado um periodo & tempo ilimitado para conclusio do projeto, por6m, quando este for enviado, os candidatos terio que ir a um centro de testes e fazer um pequeno exame de acompanhamento comquest6esdissertativas, elaborado, principalmente, paravalidareverificar sef.oram eletquem o projetaram e construiram.
JAVA
5 XXI
as pessoas que estiverem usando o JSP $ava Server Pages) e o servlet da Ele foi baseado nas eipecificag6es do Servlet i ao jSn a.fUa"rna'JavaEnterprise Edition fava EE). Parafazrr esteexame, 6 necessirio que o candidato seja um ProgramadoiJava Cenificado pela Sun. ^
&
de componentes de ne.g6cios foi elaborado para os candidatos que estejam usando a tecnologia para criaraplicativos de camada de neg6cios. O exame se baseii na especificaglo f;n deirnida naJava Enterprise* Java.EJB Edition flava EE). Para fazer este exame, 6 necessirio que o candidato seja um ProgramadorJava Certificado pela Sun.
O exame de desenvolvedor
o exame de Projetista
Tecnolo
1gr_J2EE
(SCEA)
passe no exame de
Programador. O exame de Projetista tem tr6s panes: uma prova de mriliipla escolha baseadaim conhecimentos, um projeto de arquitetura e um teste de acompanhamento com quest6es dissertativas. VocA precisa passar na prova de multipla
escolha antes de
se
registrar e receber
tarefa do projeto.
ME (SCMAD)
O exame de. dese1,volv9d91{e aplicativos m6veis 6 para candidatos que esejam criando aplicativos para telefones celulares ou outros dispo_sitivos habilitados paraJava. O e_xame aborda a espeiificagio Java Technology for 'rt/ireless Indusry [T\fl), a API lil/ireless Messaging e as APh Mobile M edia.Parafaznr este exame, 6 necess6rio que o iandidato seja um SCJir.
Geralmente, os exames da Sylvan Prometric apresentam um funcionamento semelhante para todos os fornecedores. No entanto, h6 um fato imponante a se conheceriobre os exames da Sun: eles usam o formaio tradicional de te*e da Sylvan Prometric e nio o adotado recentemente. Isso d6 ao candidato uma vantagem, j6 que o formato tradicional permiteque as repostas sejam revisadas e refeitas durante o teste.
faler
para
cada
memorvaglo,os exames da Sun apresentam um conjunto potencialmente disinto de perguruas para candidatos diferentes. Na elaboragio do exame, centenas de perguntas sio compiladas e aprimoradas pot t.tt"doi.t beta. Desse co{gnto volumoso, sio extraidx as perguntas referentei a cada objetivo que, posteriormente, sio reunidas em v6rias vers6es diferentes do exame.
Para desencorajar.a simples
xxtl
Cada exame da Sun tem uma quantidade especifica de perguntas (o exame de Programado r conr6:mT2 Perguntas) e uma duragio para o teste (175 min.ttos p"t" o r*ame de Programador). Normalmente, otempo destinado ao teste 6 generoso' rcmpo remanescente 6 sempre exiLido no canto da tela-de teste, junto com a quantidade de perguntas que faltam. Se ele expirar durante o exame, o ieste seri encerrado e as respostas incompletas serio consideradas incorretas.
No final do exame, seu teste ser6 imediatamente avaliado e o resultado exibido na tela. As notas obtidas em cada assunto tamb6m serio fornecidas, mas o sistema nio indicar6 que pe{guntas especificas est avamincorretas. Um relat6rio seri impresso automaticamente na mesa do inspetor para que voc6 possa arquiv6Jo. A nota do teste 6 transmitida
eletronicamente para
a
Sun.
oBSERVAQ6ESpeneTE)(AME
puando
uocd
nilltipla
qw
conddera as mais pttadaeit e, em seguida, vtblinbe a @osta rascanho qaando uocljd tiuerpercorido 0 terte t/ma ueg
a corwta.
Aqai utui un
exemplo de
como
fcani
seu
2l.BouC
)3.AouC
exlrenamente titil paa uocl marcar a petgilflta e darpmsseguinenta Posteriorrzente, podeni retomar e resgatar inediatamente na onde parou, Enpregte esa timica para euitar ter que reler e reaualiar ar pergantas. Voc6 tambim tenl que usar seu raseanho em perguntat de andio nrnplexo, baseadas em texto, para criar imagens de nodo a compreender aelhor a qtestdo, Esa ticnica senl especialmente itil se aocd tiuer naisfacilidadt em c@tar conceitot uisualmente,
Iso
uri
raciocinio de
Sempre que possivel, as nossiu quest6es NAO lhe dirio quantas respostas corretas existem (diremos "marque todas as corretas"). Faremos isso para lhe ajudar a dominar o material. Alguns alunos experientes com testes poderiam eliminar .r tpott"s erradas se soubessem o nrlrmero de respostas corretas. Tamb6m 6 possivel, quando vocd sabe quantas e$eo corretas, escolher as respostas mais plausiveis. Masb nosso trabalho 6 p repar!-lo paraas dificuldades que encontrarA no enamereal!
O exame real normalmente numera as linhas de c6digo de cada questio. N6s normalmente nlo as numeramos - a principal razio 6 para termos espago para adicionar comentirios onde necessirio. No exame real, quando uma listagem de c6&go comegar pelo 1, isso indicique se trata de um arquivofonte inteiro. Se a listagem comegar por um nfmero maiordo que 1, significa que se trata de um arquivo-fonte parcial. Quando se tratar de um arquivo-fonte parcial, as$una sempre q.ri a parte ausente do c6digo est6 correta (por exemplo, a nio ser qrre esteja dito explicitamente o contririo, voc6 pode assumir que um arquivofonte parcial tem as instrug6es impon e package corretas).
Quest6es
de Arrastar-e-Soltar
Embora muitos outros exames de certificagio Java da Sun venham usando quest6es de arrastar-e-soltar h6 v{rios anos, esta 6 a primeira versio do exame SCJP que inclui esse tipo de questio. Como discutimos anteriormente, as questSes do exame que voc0 recebe sio sorteadas aleatoriamente, mas voce pode esperar que cercade2) a25olo das quest6es serXo do tipo arrastar+soltar,
As quest6es arrastar+soltar normalmente consistem de tr6s comPonentes:
I I I
Um cenirio Uma
Uma tarefa parcidmente redizada Uma listagem de c6digo, uma tabela ou uma irvore de diret6rios. A tarefa parcialmente realizxla conter6 espagos em bran6, indicadoJcom caixas (normalmente amarelas). Essas caixas devefro ser preenchidas para se complet ar atarefa.
Um conjunto
de fragmentos rpresentando respostas possiveis VocA clica nos fragmentos (normalmente caixas azuis) e os arrasta para o espago em branco correto. O cenario da questio lhe diri se voc6 pode reutilizar fragmentos.
das quest6es de arrastare.sohar teri cerca de 4 a L0 espagos em branco para serem preenchidos, e normalmente mais fragmenros do que o necess6rio (alguns fragmentos sio deixados sem utilizagio). As quest5es de arrastar-e-soltar freqiientemente sio as mais complexas do exame, e o ntlmero de possiveis combinag6es de respostas as tornam quase impossiveis de "chutar".
A maioria
JAVA
5 XXIII
o
oBSERVAe6rspeneonl<eME
No
que
n ,trto
fu questdes de arrastar-e-soltar, h,l um grande problena com o software de teste em muitos dos centros Pmmetric em todo lbe penzite reuisar at questdes que jd respondeu qilantas aerys quiw.
qautdu de arrastar-e-so/tar, entretanto, maitos candidatos tim relatado qae, se eles pedirem para reuer a questdo, o nfwaru anteioreil CUIDADO! Ati qae ese problena s/a nrrigido, recomendamos qae aocd mantenba uma lista de quait quutdet sdo de anastar-e-so/ta6 para que ndo reuise rma sem qaerer. Outra boa iddia d anotar as rerpostat duse tiPl de qilesfil, de modo qile se iltua for @agada, nrificil drgitar noaanente a rerporta.
No
caso das
aPaga a rerpo$a
pora traba/har
O cenhx de teste deueia lhefornecer o ruateria/ necesnirio para que uoei algurc casos, os centrosfomeeeram marcadores e qaadm in@ropriadog por urem peqilefllr denais e dficeis de uvr efetiuamente. Rtcomendamos qae uoc6 aeifque, antes do dia do examq se receber,l do cenhv kpis ou caneta e pelo menos algumatfolhar de papel en branco.
Isso nos rerlete a ouho problema que os candidatos tdm re/atado. nas questdes
por escrito.
En
respostas erradas,
tamb6m pode volt ar paramarcol suas respostas depois que tiver ponanto, 6 melhor marcar uma resposta do que deixar uma imediato. lembre como
ao fazer o exame 6 percorrJo uma vez e responder todas as perguntas que souber de
voltar e responder
as
se
responder
anterior.
Seja muito cuidadoso com os exemplos de c6digos. Primeiro, procure erros na sintaxe, conte as chaves, sinais de ponto e virgula e par6nteses e ceftifique-se se h6 a mesma quantidade desses simbolos na abeftura e no fechamento. Procure erros na colocagio de letras maiusculas e outros problemas de sintaxe antes de tentar descobrir qual a fungXo do c6digo.
Muitas das perguntas do exame dependerio de minricias da sintaxe. Voc6 precisar6 de um conhecimento consistente da
linguagemJava para que seja bem sucedido.
Os grupos de e$udo para a certificaglo 6 outro recurso excelente e vocA nXo encontrar6 uma comunidade maior ou mais participativa do que nos f6runs Big Moose Sallon do javaranch.com. Se tiver uma pergunta relacionada a este livro, ou de qualquer outro eiame simulado com o qual se deparar, ao envi|-laparaumf6rum sobre a certificagXo voc6 obteri a resposta, em quase todos os casos, dentro de um fi4 e na maioria das vezes, em algumas horas. VocA nos encontrari por [6 (os autore$ v6rlsvezes por semana, ajudando as pessoas que estXo iniciando.sua jornada de preparagXo para o exame. (Voc6 nio conseguiri pensar em nada que soe tao bem como a p alavra"jornada" quando estiver se preparando para o exame).
Finalmente, recomendamos que voc6 escreva v6rios pequenos programas emJava! Durante a escrita deste livro, n6s escrevemos centenas de pequenos programas, e se voc6 der ouvidos ao que dizem os candidatos mais bem-sucedidos (tipo aqueles com m6dia 987o), eles sempre relatam que escreveram muito c6digo como pane do estudo.
Quando voc6
opornrnidade
pa ra
rever
recomendo chegar tarde. Seu teste poderia ser cancelado ou voc6 pode nio ter tempo nrficiente para concluir o exame. Quando chegar no centro de testes, voc6 teri que se inscrever com o inspetor do exame. Para se inscrever, ser6 preciso fornecer dois tipos de identificagio. Os tipos aceitos sio identificag6es emitidas pelo governo (por exemplo, passaporte ou habilitagio de motorista), cart6es de cr6dito e crach6s de empresas. Sua fotografia deve consrar em uma das identificag6es. Eles s6 estario se certificando se voc6 nio enviou, em seu lugar, seu vizinho brilhante emJava, a quem
pagou para fazer o exame.
Al6m de um c6rebro repleto de informag6es, vod nio precisar6levar nada mais para o exame. Na verdade, seu c6rebro ser6 tudo que poder6 levar! Todos os testes devem ser feitos com os livros fechados, o que significa que voc6 nio precisa levar nenhum material de consulta. Tamb6m nXo poderi levar nenhuma nota ao sair da sala do exame. O inspetor do teste lhe forneceri papel e caneta. Alguns centros & teste podem fornecer uma pequena prancheta em vez disso. Recomendamos que voc6 leve uma garrafad'|goa. Duas horas 6 muito tempo para manter seu c6rebro em atividade e ele funcionar6 melhor se estiver bem hidratado.
Deixe seu pager e telefone no carro ou desligue-os. Eles s6 deixario a situagio mais tensa, ji que nio sio permitidos na sala do exame e talvez ainda possam ser ouvidos se tocarem fora da sala. Bolsas, livros e outros materiais devem ser deixados com o inspetor antes que voc6 entre na sala do exame. IJma vez na sala de testes, o inspetor se conectar6 com seu exame e vocO ter6 que verificar se seu nrimero de identificagio e o ntmero do exame esteo corretos. Se for a primeira vez que voc6 estiver fazendo um teste da Sun, poder6 selecionar um tutorial resumido existente no software do exame. Antes de o teste comegar,. serio dadas informag6es sobre o exame, incluindo a duragio, a quantidade de perguntas e a nota exigida para passar. E bastante prov6vel que seja pedido que voc responda a uma breve pesquisa antes de o exame propriamente dito comeEar. Essapesquisa lhe perguntar6. sobre o seu nivel de experiAncia em Java. O tempo que voc6 gastar n a pesquisa nio ser6 retirado do tempo propriamente dito do seu teste - nem voc6 ter6 mais tempo se responder a pesquisa rapidamente. Lembre-se tamb6m de que as quest6es no seu exarne ndo serio modificadas dependendo dx respostas que der i pesquisa. Em seguida, o rel6gio comegar6 a funcionar e a
diversioteriinicio.
O sofrware do teste 6 executado no rVindows, mas vod nXo ter6 acesso a 6rea de trabalho principal ou a qualquer acess6rio. O exame ser6 apresentado em tela cheia, com somente uma pergtrnta por tela. Os bot6es de navegagio permitirio que voc6 se mova para baixo ou para cima entre as perguntas. No canto superior direito da tela, contadores mostrario a quantidade de perguntas e o tempo remanescentes. O mais importante 6 que haver6 uma caixa de selegio chamada Mark no canto
superior esquerdo da tela essa ser6
JAVA
5 x)O/
O objetivo 6bvio de um exame 6 que as.perguntas sejam respondidasde maneira eficaz, mesmo que ourros aspecros possam distraiJo. Aqui estlo algumas dicas paraf.azer o exzLme mais eficientemente.
Avalie o desafio
Primeiro, d6 uma passada r6pida por todas
tempo nessa leitura.
as
tipoi
perguntas do exame. Elimine as f6ceis, respondendo.as imediatamente. Leia assunto. Como diretriz, tente gastar^menos do que 25 por cento de seu
Essa etaPa permitil6 q.ue vogQ ryalie o escopo e a complexidade do exame, lhe ajudando a dererminar como conrrolar seu tempo' Tamb6m dari uma id6ia de onde encontrar possiveis respostas para algumas das perguntar. As ,r.zes, redagio Je " umapergunta pode darpistas ou trazer a sua mem6iia outrapergurua.
voc6 nXo estiver totalmente ceno de sua reposta a uma pergunta, responda assim mesmo, mas marque a caixa Mark para indig.ar W9 fazer uma revisio.posterior nela. Caso voc6 fiqrr. i.ntpo, pelo menos ter6 forneci'do r pri*.ir" fve que lhe veio i cabega, em vez de deix6Ja em branco.
Se
r.*
t fjrt" e*
inteiro parecer dificil, voc6 saberi que nio poder6 gastar mais
percepglo que obteve na primeira leitura. Por exemplo, se o teste de circa de ,r- *irr.rto .- cada pergunta. Dirrij, o ..*po
a
cada 20
minutos".
a
Nesse estigio, provavelmente seri uma boa id6ia saltar as pergunras que exigirem mais rempo, marcando-as para leitura. Tente terminar essa fase antes de chegar a 5G6O por cJnto doiempJdo teste.
pr6xima
Em terceiro lugar, leia todas as perguntas que voc6 marcou para revisar, usando o botlo Review Marked da tela de revisio de Perguntas. Essa etapa inclui uma segunda leitura de todas as perguntas cujas respostas foram dadas sem cerreza, assim como responder as que exigem maistempo e que ,rocA posteigori at6 agora. Responda como achar melhor esse conjunto de perguntas ate que as tenha responctldo por completo.
Se voc6 estiver mais seguro para responder uma pergunta que marcou, desmarquea agora. Do contririo, deixe-a marcada. V6 trabalhando nas perguntas que exigirem mais tempo, principalmente as qrr. n ..tiit"rcm de c6lculos manuais.
Ao final
Se
dessa etapa, voc6 ter6 respondido todas as pergpntas do_teste, apesar de nlo te r ceneza em alzumas das respostas. ficar sem tempo na pr6xima etipa nio perder6 pbntos pela falta de uma pergunta. Estar6 bem se aiida tiver 1O-2b por cento de tempo remanescente.
rlma vez para procurar "pegadinhas". Fique panicularmente arento para as que de riliirnahora. VocO j6 eiti bem familiarizado com quase todas as perguntas a essa altura e pode encontrar algumas pistas que nio tinha visto antes.
O grande final
Quando estiverconfiante de todas as respostas, termine o exame enviando-o para avaliagio. Depois, do que parecerio os segundos mais longos de sua vida, o software do teste retornar6 sua nota. Geialmente, ela 6 exibida em um gr6fico de barras, que mostra a nota minima exigida, a nota obtida e um indicador PASS/FAIL.
Se LO
voc6 estiver curioso, poder6 ver sua m6dia de pontos nesse momento. Nio serio apresentadas as repostas a pergunras as perguntasserio reunidas em categorias e serio registradoirenrltados para c.d, cat"gorl. Ett. detalhe tamb6m estari em um relat6rio que teri sido impresJo auromaticaminte na mesa do inspetor do exam?.
especificas; em vez disso,
Quando voc6 sair do local do exame, ter6 que deixar seu rascunho para tris ou entreg6Jo ao inspetor. (Alguns centros de teste registram o nfmero de folhas que sio fornecidas, para tetem certezade que tod-as serio devolvidas). Em troca, vocp
receber6uma c6pia do relat6rio do teste.
relat6rio terl a marca do centro de testes gravada e voc6 deve guardiJo em um local seguro. Normalmente, os resultados sio transmitidos automaticamente para a Sun, mm podi r.r q.te voc6 precise doielat6rio emitido para provar que Passou no exame.
Esse
x)o/r
Em algumas semanas, a Sun lhe enviar6 um pacote pelo correio contendo um bonito cenificado, um alfinete de lapela e uma carta. Tamb6m podem lhe enviar instrug6es di como contratar o tabalho artistico para criaSo de um logotipo que
voc6 poderiusar em cart6es de visitapessoais.
,ro1r"rn.rrr..'Considere.se um po.tco
Se
-"is
esperanga. Tente aproveitar o que ganhou com a experiAncia e preParese Pararcntar informado. Voc conhece o fbrmato do teste um Pouco melhor e o relat6rio
fizer o teste mais uma vez sem demora, provavelmente voc Isso o ajudari a concentrar seus estudos na area certa'
se
lembrari
de
virias
ter errado.
Paraconcluir,lembrese que as ceftificag6es daSun sXo vdiosas, pois sio dificeis deobter. Afinal, se qudquerpesoa conseguisse, que valor teria? No final das contas, 6 necessirio uma atitude adequada e muito esnrdo, mas voc6 pode faz&lol
I
"'
lndividuol
2 Copitulo
: DecloroE6es e Conirole de Acesso N6s partiremos do principio de que, uma vez que esti planejando obter a cettificagio, voc i6 sabe o bisico deJava. Caso seja completamente iniciante na linguagem, este capinrlo - e o restante do livro - ser6 confusq entio, certifique-se de que voc6 sabe pelo menos o b6sico da linguagem antes de mergulhar neste livro. Dito isso, comegaremos com uma revisio para i refrescar a sua mem6ria sobreJava, caso tenha estado afastado da Jinguagem por algum tempo.
Revisio de fava
Um programa emJava principalmente uma colegdo de objetos falando com outros obf etos por meio da invocagio dos m6todos uns dos outros. Cada objeto 6 de um tipo, e esse tipo 6 definido por uma classe ou uma interface. A maioria dos programas emJava usa uma colegio de objetos de muitos tipos diferentes.
.
I I I I
Classe Um modelo que descreve os tipos de estado e de comportamento que os objetos do seu tipo podem ter.
ObietoNomomentodaexecugio,quandoaM6quinaVirtualJavaflavaVirtualMachine,ouJVlvf eflcontt^^p^l^.rrachave new, ela usa a classe aproprtadapara criar um objeto que seri uma instAncia dessa classe. Esse obieto ter6 o seu
pr6prio estado e ter6 acesso a todos os comportamentos definidos pela sua classe. Estado (vari6veis de instdncias) Cada objeto (instdncia de uma classe) ter6 o seu conjunto rinico de vari6veis de instAncias conforme definido na classe. Coletivamente, os valotes atribuidos is variiveis de instincias de um obieto compdem o estado do objeto.
classe, ele cria m6todos para essa classe. E nos m6todos que a l6gica da classe 6. armazentda. Nos m6todos, o verdadeiro rabalho rczLzado. E neles que os algoritmos sio executados e que os dados s6o manipulados.
ldentificadores e Palavras-chave
Todos os componentes deJava de que acabamos de falar - classes, vari6veis e m6todos - precisam de nomes. EmJava, esses nomes sio conhecidos como identificadores e, como seria de se esperar, existem regtas dizendo como devem ser os identificadoresJava permitidos. Independentemente do que 6 permitido, no entanto, os programadoresJava (e a Sun) cianmconveng6esparaafiome giodem6todos,vari6veiseclasses.Comotodasaslinguagensdeprogramagdo,Javatem um coniunto de palavras-chaves internas. Essas palavras-chave nio podem ser usadas como identificadores. Mais adiante neste capitulo, veremos os detalhes sobte essas regras e conveng6es de nomeagio, e sobre as palavtas-chaveJava.
Heranga
Fundamental pataJava e outras linguagens orientadas a objetos 6 o conceito de hetanga, que permite ao c6digo definido em uma classe ser reutilizado em outras classes. EmJava, voc6 pode definir uma supetclasse geral (mais abstract), e depois estend,3-la com subclasses mais especificas. A superclasse nio sabe nada sobre as classes que herdam dela, mas todas as subclasses que herdam da superclasse ptecisam declarar explicitamente a relagdo de heranga. Uma subclasse que herda de uma superclasse recebe automaticarnente as vari6veis de instAncias acessiveis e os m6todos definidos pela superclasse, mas 6 tamb6m livre para substituir m6todos da superclasse para definir comportamentos mais especificos. Por exemplo, :uma npercIasse Carro poderia definir m6todos gerais comuns Ferrari poderia substituir o m6todo acelerar ( ) .
a
Interfaces
Um poderoso companheiro da heranga 6 o uso das interfaces. Ainterface 6 uma esp6cie de superclasse 100% abstricE que define os m6todos que uma subclasse deve suportat, mas ndo como esse suporte deve ser implementado. Fm odtras pilavras,umainterfaceAnimal poderiadeclanr que todas as classes de implementagio de Animal devem ter um m6todo comer ( ) ,mas ainterfaceAnimalnlo fornecenenhumal6gicaparaom6todo comer ( ) .Isso significaque ftcaacargo das classes que implementam ainterface Animal a definigio do c6digo para como cada tipo particular de Animal se comporta quando o seu m6todo comer ( ) 6 invocado.
JAVA
Al_r
stat ic,
de instdncias e locais.
Ahn
de nomeagdo JauaBeans.
l.4Desenuoluercddigoquedularemdtodosstatic en1o-sLaLic'e,seapropriado,usarnomesdemdtodosqueobedegamaospadrdu Aldm disso, desenuo/uer nidigo que declare e t/se ama /ista de argamentos de extensio uai,iiel.
Lembre-se de que, quando listamos um ou mais Objetivos pata a Certtftcagdo no livro, como acabamos de fazer, isso significa que as seg6es a seguir abordario pelo menos parte desses objetivos. Alguns objetivos serio abordados em v6rios capitulos diferentes, de modo que voc ver6 o mesmo obietivo em mais de um lugar do livro. Por exemplo, esta segio cobre declarag6es, identificadores e nomeagioJavaBeans, mas o uso do que voc vai declant ser6.abordado em capitulos posteriores. Assim, comegaremos com os identificadotesJava. Os tr6s aspectos dos identificadoresJava que abordaremos aqui sio:
Conveng6es de C6digo Java da Sun As recomendag6es da Sun para nomeagio de classes, vari6veis e m6todos. Normalmente n6s obedecemos a esses padr5es em todo o livro, exceto quando estivermos tentando lhe mostrar como seria uma questio dificil do exame. Nio lhe ser6o feitas perguntas sobre as Conveng6es de C6digoJava, mas
recomendamos enfaticamente que os programadores as usem.
I I
Identificadores Legais As
I Padr6es de NomeagdoJavaBeans Os requisitos de nomeagio da especificagioJavaBeans. Nio 6 preciso estudar a especificagioJavaBeans pata o exarne, mas voc6 precisa saber algumas regras b6sicas de nomeagSoJ"rrrB.*, q.r. abordaremos neste capitulo.
ldentificadores Legais
Tecnicamente, os identificadores legais devem ser compostos apenas de caracteres Unicode, nrimeros, simbolos de moedas e caracteres de conexio (como underscores). O exame nio mergulha nos detalhes de quais falras do coniunto de caracteres Unicode qualificam como letras e digitos. Assim, por exemplo, vocd n6o precisar{ saber que os drgrtos em Tibetano v6o de \u0420 at6 \u0f29. Eis aqui as regras que voc6 precisa saber:
I I
Osidentificadoresdevemcomegarcomumaletra,umcifrio($)ouumcaracterdeconexdo,comoounderscore(_).Os
identificadores nio podem comegar com um nfmerol
DePois do primeiro c^r^cter,os identificadores podem conter qualquer combinagio de letras, caracteres de moedas, caracteres de conexio ou nfmeros.
I Na pr6tica, nio h6limite para o nrimero de caracteres que um identificador pode conter. I Nio se pode usar uma palavta-chaveJava como identificador. A Tabela 1-1 lista todas as palavras-chave Java. incluindo
uma novidade da versio 5.0, enum.
icador
ji
int
i ht
:Jr;
-A .
int
I nr
e#;
I .
anE. /9,.
4 Copftulo
Tobelo
1-l
abstract
char double
boolean
break
byte
^^nl_ i nlra
case
catch
do
class else
:Jvuv
const
extends
final
implements
default finally
import
float
instanceof
package
for int
hri rt^l-a
if
long
interface
protected
super
trans]-enE
enum
nati-ve
public
switch
Ery
strictfp
throws
asserE
staEic
throw
while
ftil
de padr6es e programiJo aiudaadiminuir o esforgo envolvido em testar, fazer amanutengio e melhorar qualquer c6digo. A Sun criou um con,unto de padr6es de programagdopanJavaepublicou esses padr6es em um
com um coniunto
documento inteligentemente chamado de "Convengdes de C6digoJ ava",o qualvoc6 pode encontrar em iava.sun.com. Trata-se de um 6timo documento, curto e f6cil de ler, que recomendamos enfaticamente.
as conveng6es de c6digo, devido is limitag6es do programa de provas que 6 usado para minisftar o exame internacionalmente. Uma das boas coisas sobte as certificag6es da Sun 6 que os exames sio administrados uniformemente em todo o mundo. Para se conseguir isso, as listagens de c6.ligos que voc ver6 no exame real freqiientemerite sio bem bagungadas, e nlo seguem os padr6es de c6digo da Sun. Panprepat|lo pam o exame, n6s freqtientemente iremos apresentar listagens de ssdigos com uma aParncia igualmente bagungada, usando apenas dois espagos depatdgnfo em vez dos quatro espagos do padrio Sun'
Dito isso, vocd ver6 que muitas das quest6es do exame nio seguem
N6s tamb6m bagungaremos nossas chaves de forma artificial, linha... oh nio! Por exemplo:
e,
1. class Wombat implements Runnable { private int i; 2, 3. public synchronized void runO i if (i*5 l= 0) { i++; i 4. for(int x=0; x<5; x++, i++) 5. 6. { if (x > 1) Thread.yield0 ; } 7. System.out.print (i + " ") ; 8) g. public st.atic void main(string[] args) t l-0. Wombat n = new wombat O ; 11. for(int x=100; x>0; --x) { new Thread(n).startO; L2. ) )
Considere-se avisado - voc ver6 v6rias listagens de c6digos, quest6es simuladas e quest6es de exames reais que serio doentias e incompreensiveis dessa maneira. Ningu6m quer que voc6 escreva seu c6digo desse ieito. Nem o seu empregador, nem os s..,s colegas de trabalho, nem n6s, nem a Sun e nem a equipe de elaboragdo do exame! Esse tipo de c6digo foi criado apenas para que conceitos complexos pudessem ser testados usando-se uma ferramenta de provas universal. O rinico padrio que 6 seguido tanto quanto possivel no exame rcaL6. o dos padr6es de nomeagio. Eis os padr6es de nomeagio recomendados pela Sun, e que usamos no exame e na maior parte do livro:
Classes e interfaces A primeira letra deve ser maifscula e, se v6rias palavras forem escritas iuntas para formar o nome, a primeira leta d e cadapalavrainterna deve ser mairiscula (um formato chamado em inglBs de "camelCase'). Para classes, os nomes devem normalrnente ser substantivos. Por exemplo:
Dog / /Cachorro
JAVA
Runnable //Execut6vel
Serializable
/ / Seria]-:-z5ivel
I M6todos A primeira letra deve set minriscula, e depois as regras camelCase normais devem ser usadas. Al6m disso, os nomes devem normaknente ser pares de verbo-substantivo. Por exemplo:
getBalance / /obterBalango doCalculat ion / / fazerC6lculo
setCustomerName / /de f inirNomeDoCl
iente
I VariSveis Como nos m6todos, o formato camelCase deve ser usado, comegando com uma letra minriscula. A Sun recomenda usar nomes curtos e significativos, o que nos parece uma boa id6ia. Alguns exemplos:
buttonWidth / / LarguraDoBotSo
accountBal ance / / balanqoDaConta
myString //minhaString
ConstantesAsconstantesJavasdocriadasmarcando-sevariiveiscomostatic efinal.Elasdevemsernomeadas
MIN_HEIGHT / /ALTURA_MINIMA
Padr6es favaBeans
A especificagioJavaBeans foiciadapanajudar os desenvolvedores a criarem componentesJava que possamser facilmente usados por outros desenvolvedores em uma ferramenta de Ambiente de Desenvofvimento Integrado ("Integtated . Development Environment, ou IDE), como o Eclipse ou o NetBeans. Como um programadorJava, voc6 desejard usar componentes daAPIJava, mas seria excelente se voc pudesse tamb6m comp?br o componenteJava que quisesse no "Mercado Beans", aquela loja de software queficana sua rua. E,-depois de enconffar os componentes, voc6 gostaria de poder acessi-los atrav6s de uma ferramenta de desenvolvimento de forma tal que nio precise escrever todo o seu c6digo do
zero.
Ao usar regras
de nomeagio, a especificagdoJavaBeans
ajuda
componentes criados por diferentes desenvolvedores. AAPIJavaBeans alguns fundamentos para o exame.
garantir que as ferramentas podetio reconhecer e usar 6 um tanto complexa, mas voce s6 precisar6 estudar
Primeiramente,JavaBeans sio classesJava que tem propriedades. Para os nossos prop6sitos, pense nas propriedades como vati6veis de instdncias private. Umavez que sdo private, a rinica maneira pela qual podem ser acessadas de fota da sua classe 6 atavs de m6todos da classe. Os m6todos que modificam o valor de uma propriedade sio chamados m6todos tetter, e os m6todos que obt6m o valot de uma propriedade s6o chamados m6todos geLter. As regtas de nomeagio JavaBean que vocd precisar6 saber par o exame sio as seguintes:
getSt.opped
ptopriedade for booLeana, o prefixo do m6todo getter 6 ou get ou is. Por exemplo, tanto ( ) quanto isstopped ( ) sio nomesJavaBeans vilidos pataum^ propdedade booleana.
deve ser
set.
Por exemplo,
setsize ( ) 6 o nomeJavzBeanv|Idopar^lma
I Pa:,a ter o nome completo de um m6todo getter ou settef, passe a primeira letra do nome da propriedade para mairiscula e depois anexe o prefixo apropriado (get, is ou set). I As assinaturas de m6todos setter devem ser marcadas como argumento que represente o tipo da propriedade. I
As assinaturas de mdtodos
public,
void
um
getter
ter
pan
ptopiedade em questao.
a especificagiloJavaBean tem suporte a euentos, os quais permitem aos componentes notificarem uns aos outros quando algo acontece. O modelo de eventos geralmente 6 usado em aplicag6es GUI quando urn evenro, como urn clique do mouse, 6 comunicado para muitos outros objetos que possam ter cgisas a fazet qtando ocore um clique do
6 Copftulo 1 : DecloroE6es
e Controle de Acesso
mouse. Os objetos que recebem ainfornagdo de que ocorreu um dado evento sio chamados de /isteners. Para o exame, voc precisa saber que os m6todos usados pata adicionar ou remover listeners de um evento devem tamb6m seguir padr6es de
nomeacio JavaBean:
Nomes de mdtodos listeners usados para remover ("desregistrar") um listener devem usar o prefixo remove, seguido do tipo do listenel (usando-se as mesmas regras que o m6todo add de registro). O tipo de listener a ser adicionado ou removido deve ser passado como o argumento para o m6todo.
aan
i cM\/ql-.1-rrc
public void addMylistener (MyListener m) public void removeMylistener (MyListener void setCustomerName (String s) public void modifyMyValue(int v) public void addXlistener{MyListener
oB SERYAQoBS pene O EXAME
m)
/
m)
I
/
I
n6.o se pode
eLLv
usar 'modify'
/ / crra
da l- inn d. l-iStenef
diqque uoci precisa saber os identifcadoru legais para nzmes de uaridueis, mas as regras s6o ar nermas para TODOS os Assim, lenbre-rc d.e que un identifcador legalpara ilma aariduel tanbdn d legalpara un nitodo ou uma classe. Entretanto, uocd deue distinguir entre os identifcadores legais e as conuengdes de norueagdo, tais como o: padrdet JauaBeafls, q//e indican cono
O objetiuo
sd componentes Jaua.
um determinado componente Jaua deue ser nomeado. En outras palauras, uocd deue ser capaqde reconheeer qae um dado identifcador mesml qile e/e ndo se conforme a padrdes de nomeapdo. Se a qaestdo do exame estiuer lhe perguntando sobre conuengdes de nomeapdo
tzmente se um dado identifcador
d legal
iri
e ndo
conpilar
os
Dentro
eistem
variiveis e m6todos (al6m de algumas outras coisas). O-- rSdq qq$o-vsc6 dgclara ag.qu?! 4g_q.q9!:.m(t9dgq 9 varj|y-etg cfsta.dramatic4lnente o qg4portamentadoseirc6digo. Pot exemplo, trlr!-lqeto.daJ:ublic pode set acessado a pattit do c6dig:o que. es-tep Sgdandg em qualqu-er p4-r19 da s.ua,apliesa.g No entanto, l9-ve*-narcar esse m6todo coma pdlf4le-rg]g &sapar*er?dg.pfo!_ggrAgh,res (94etoo ds glagpe qa qual f.oi-de.clarado). Para este objetivo, estudaremos as formas pelas quais vocd pode declarar e modificar (ou nio) uma classe. Voc perceber6 que abordaremos os modificadores em um nivel extremo de detalhe, e, embora saibamos que voc6 j6 es td famt\arizado com eles, comegaremos pelo b4sico. A maioria dos programadoresJava pensa que sabe como todos os modificadores funcionam,m s,ao examinar cuidadosamente a questao, descobre que nio sabem (ou pelo menos nio no nivel exigido pelo exame). Existem sutis disting6es em toda parte, entao rer ceftezzabsoluta de que domina totalmente todos os assuntos dos objetivos desta segZo antes de fazet o
::;:....O"
JAVA
I r
publ i c
Os comentirios podem aparecer no inicio ou no fim de qualquer linha no arquivo do c6digo-fonte; eles sio independentes de quaisquer regras de posicionamento diicutidas aqui.
f lsiaul,er-Jpa-clas,sepubli-cemumarquiv.o-o..-el^"rg"*odevesere.mesmodaclassepubfic.por exemplo, uma classe declandacomo public cl-ass Dos { } precisa esrar em rr- ".qrlirro'd. c6digo-fonte chamado Dog. j ava. I Se a classe ltzet panede um pacote, a declaragio package deve estar na primeira linha do arquivo do c6digo-fonte, antes de quaisquerdeclarag6es import que estejam presentes. r Se houver declarag6es import, elas devem frcar enhe a declangdo package (se houver) e a declaragio da classe. Se nio houver uma declatagdo package, entio a(s) declaragzo(5es) impoit deie(m) estar na(s) primeirals; Iinha(s) do arquivo do c6digo-fonte. Se n6o houvet declaragSes package nem import, a declatagiodu.t"i.. d.rr..sti na primeira linha do
arquivo do c6digo-fonte.
.,!
p
".\ \
\,
r I I
import e package aplicam-se a todas as classes denffo de um arquivo de c6digo-fonte. Em outras palavras' nio 6 possivel declarar multiplas classes em um atquivo e t6las em diferentes pacot;s, ou usar diferentes importag6es.
As declarag6es
nio-public. Arquivos que nio tenham classes pub 1 i c podem ter um nome que nio seja o mesmo de nenhuma
Um arquivo pode ter mais de uma classe
as regras
de
class Myclass { r I
}
de
Esse.c6digo iri compilat sem ptoblemas, mas yqgepqdelamblq adeio.nar rao-digga4tr-es antes da modificaderes ee dividemsnc duas..patsgp_r-ias : _!t_"-aiq..aores de acsso:
cla.r-ag,oda classe. Os
inal eabstract).
Examinaremos os modificadores de acesso ptimeiro para que voc6 aprenda como restringir ou permitir acesso a uma classe o controle de acesso emJava 6 um pon.o --plicado porque pusterrr q\la$a ea.rtrok;de acesso (niveis dg qgesso) f0olep r-H#fI(!!frkdrcde-ageccq. Qqpa4q nivpl de-coqtrsle de acesso (cha-mado de acesso def ault oudep)iote){o guq v-o-c oblim qual-{o ndo usa nenhunraostrl-modi-fic4do{qs de acesso. E,m'outras palavras, gggp13rr., m6todo ..' Vgrpy..el{g inst{gci4 quevo-g6 {eclatar tem um controle Jieacisrq -d.pqndentemente d;voc indi} um explicitamente ou 0.69' Embora tgd-g! 9-9^qF4trq gontrole; fg acesso (o que significa todos os trs modificadores) foncion emparaa maroria das declarag5es de m6todos e de variiveis, uma classipode.ser declarada.apenaS,.co5n,gcesso pubt"ic ou d,ef ault; os outros dois niveis de controle de acesso nio se aplicam paia classes, como voc6 ver6 adiante.
que criar'
AO TRABALHO
Jaua d uma linguagen cenlrada n\Epa.rote|; os derenuoluedoret asrumiram qae,para uma boa organiqagdo e controle do escopo de nomes, uocdpreferiria colocar todat as suas clasres empacotes. Eles estauam certoi, e iocd deuefaryr neino. Inagine o seguintepesadelo: trds diferentet progmnadorer' na flrerma efitprestT, mas traba//tando em diferentes partu de in prolen, escreuen ,oin o* una clasrc chamada Utlities' Se essas trfu classes lJtilities ndo ,iuerem sido deltyadas in nenhin pacot, ,^pbrito, e utiuerem no clasrpath, uoci ndo terd nenhana maneira de diler ao compilador ou a lwtL qual /as trds estd tentand) referencior. A Sun recomenda qae os desenuolaedoret usem n1mes de doninio reuerso, anexados colr o nlme da diuisdo e oa doprojeto. Porexeupl0, f ft 0 ltvne do siu doniniofor geeksanonltmous'cLm' e estiaer traba/hando no aidigo do clienlepara oprograna TwelaePoiitOStEt, aoc6 daria ao Jeil pacote ,/m //,me camo com'geeksan0nlm0us.rteps.client. Isso modifcaria o oori do su) classe pnra
i:i
astim, uocd poderia ter klisdes de nomer dentro da rila emprera, se ndo inuentai os uus pidprios ujor*^ de' nomeagdo, mar garantidamente ndo hausnl colisdes nm clasu duenuolaidas.fo* d: saa empreM lassinlido qrr)/o, ngn* a conuengdo de nomeagdo da Sury se e/as ndo o17(erem, bem, coisas bastante desagradriuiis poden aconticer). '
,o*.grr/"roronlroa1sEt.c/ient.(Jtilities. Ainda
if gl-stgilfisa-Su-eaclAS!94-p-oi9g:9r-r1!tl.dlsp.g',rniq9coie4q;*
8 Copftulo
a I
l-.i.a
variiveis.
da classe
pritica, acesso signific a uisibilidadp. Se. a c-lasse A nio puder uera classeB,o nivel de acesso dos m(lodos e variiveis dentro B n6o farS,dtfercnga; a classe A nio ter6 como acessar esses m6todos e vari6veis. Esse6o
ASr.SgD_ =faprll-Upaclagge-comaqggq-gdefaul-t naotemnenhummodificadorprecedendo-a{radeclaragio! iontrole de acesso que vo.e oUte- quando nio digrta um modificador na declaragdo daclzsse. Pense no acesso defaul-t como um acesso de nivel de pacote, porque ulna class-e-com acesso de f aul t s6 pode ser vista por classes de dentro do
rnesmopacote.Porexemplo,seaclasseAeaclasseBestiveremempacotesdiferentes,eaclasseAtiveracessodefault,a
classe B nio set6 capazdJ criar uma instAncia da classe A, e nem mesmo declarar uma varidvel ou tipo de retorno da classe A. Na verdade, a classe B precisa fingir que a classe A nem sequer existe, ou o compilad or ir6. reclamar. Observe o seguinte
arquivo-fonte:
package
cert;
class eeverage { i
Agora observe o segundo arquir,'o-fonte:
package exam.
stuff;
}
Como voc6 pode ver, a superclasse (Beverage) est6 em um pacote diferente da subclasse (Iea). A declaragio import no alto do arquivo Tea esti tentando (cruze os dedos!) importar a classe Beverage. O arquivo Beverage compila sem problemas, mas, quando tentamos compilar o arquivo Tea, obtemos algo como:
Can,t access class cert.Beverage. Class or interface must be public, in same package' or an accessible member c1ass. import cert.Beveraget Tezndo compila porque a sua superclasse, Beverage, tem acesso def ault e est6 em um pacote diferente. Fora usat nomes
de classes totalmente qualificados, o que abordaremos no Capitulo 10, existem duas coisas que vocd pode fazet pan consertar isso. Voc6 poderia colocar ambas as classes no mesmo pacote, ou poderia declarar Beverage como publ ic, como descrito na seg6o seguinte.
Dessa Quando v_oc_e yrgm? ques.t6o com lp"gga complexa,.certifique-se de olhar os modificadores de acesso primeiro. uma classe de f aul- t ,forma, se descobrir uma violagio de acesso (por exemplo, uma classe do pacote A tentando acessar do pacote B), yoc6 saber6 que o c6digo nao vai compilat, entio nio precisa nem se dar ao trabalho de tentar entender a fazer aptova.Simplesmente marque a resposta 'A compilagio I6gica. Afin"i,i;;ai; -as o que fLrr ro ..rr,.-po "o falha'e passe para a questao seguinte.
publ i c dd alo-das as classes, de todos os pacotes, acesso.d .{ge.sqg Pirblico Uma declaragio de classe com ^p^lavr^-chave pfbliC?. Em outras palavras, lg/a.s as classesdo p_-ni;qersoJava QU) tdm acesso a uma classe priblica. No entanto, ndo -.l"sS.e se esquega, de que, gg.ruLa-ela.s;g,pgbLq1.qqe estlyer terrta.ndo usar estiver em um pacote diferente do da classe que este
screrrendq vocgggd.U_ree!ca!--6 1r-nper!al?-@sp'$!9. No exemplo da segio anterior, talvez ndo queiramos colocar a subclasse no mesmo pacote que a superclasse. Para fazet o c6digo funciona4precisamos adtcionar apalavra-chave pu-b1 ic na frente da declaragdo da superclasse @everage), da
seguinte forma:
n: nlz:na narf
.
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.
strictfp funciona, entio nos concentfafemos apenas em modificar uma classe como final- ouabstract.Paraoexame,voc6s6precisasaberquestrictfp 6umapalavra-chavegguepodeserusadapara
significaquequa-lquet
Sem esse modificador, os
classecomostrictfp,aindaassimvoc6poder6obterumcomportamentostrictfp
declarando o m6todo como strictfp. Voc tem assuntos mais importantes para se preocupar.
comportar de forma variante conforme aplataforna.Se ndo declarat a param6todosespecificos, Se voc6 nio conhece o pa&io IEEE 754,agotanio6 o momento pam aprend6-lo.
gg[gper
ClassesFinaisQuandousadanadeclaragilodeumaclasse,ap.flV3;3;9bave-final significaqueaclasseemquestdonao subcla,ssificada' Em outras palavtas, ne*gblqggclr-g1a.ss-eppd-ejas.rar,s aslenJef @erdar de) uma clasie f ina1, 9gdWe1l9111aivade faz-lolhe dard um erlo de compilag{q
Entio por que voc sequer m arcaiauma classe como f inal ? Afinal de contas, isso n6o viola to da a nogd.ode heranga presente nas linguagens orientadas a obietos? !,oc s6-5!pv_g marc4r gp.qa.c,lasse como f ina] seprecisar de uma garantia . 4lselu-ta dequ.g.ngghurlr dos m6todos dessa classe jamais vai ser substituido. Caso ieo c6digo seja profundamente dependentedaimplementagiodecetosm6todos,usarfinal
irslegrent?g5g
.qem vo_qQ. s_4!e1.
lhedar6asegur"ogad.qoe-ningu6mpoder;,modtficata
V?.i n1i.U]ique
rr.rtls-gb:-q9g-4?s bibliotecas fuodamentaisJava s6o f ina1. !og*9,1emplo, a classe String"nio pode ser subclassificada. Imagine a confusio que ocoreria se vocd nio pudesse garantir fo.mi co-t um objeto String funcionaria " em qualquer sistema que executasse a sua aplicagdo! Se os programadores tivessem a liberdade de estender a clisse String (e assim colocar as suas novas instancias da subclasse String onde esperam-se instAncias de java.lang.Strin a civiltzagfuo ti
comoaconhecemosenttaiaemcolapso.$ssim,usefinal
classe
inal
paraseguranga,masapenasqo".rdotivercertezadequeasua
$,
EI?a-94 que a
su,a
de fato j6 disse tudo o que precisa ser dito nos seus m6todos. Marcaiuma.larr".orno f significa, na classe nunca ser6 aprimorada, ou mesmo modificada para uso mais especifico, por outro programador.
inal-
IJ-q1!-e1e{c!o de se ter.classe$nao--f;pa1 6 neste cgn6rio: imagine que voc6 encontrou um problema com um m6todo em 9$a,alasseque.qs?i usando, mas nio tem o c6digo.fionte. A;;!g1, vo;6 nio pode.mo-difiear a ionte para melhorar o m6todg, tr-3-sj9g9:s.t9,!der a-classe e substituir o m6todo em questio na sua nova rob.lur.., e simplesmenl llr". u subclasse em tg-,{1s31og;r-s10es em gue a superclasse original for esperada. No entanto, se a classe for f inal, entao nao h6 nada que voc6 pcissa fazer. Vamos modificat o nosso exemplo Beverage colocando
nadLrd6
Fsv.leJv
palavra-chave
inal
na declaragio:
^arf.
ve!
e,
Agora,
se
tentarmos compilar
,.
a subclasse Tea:
erage,.
}
Can't
{'eqe i5lgoteodidetqllbglalsificada). @epare, no entanto, que vocd pode compilar e executaruma classe abstract, desde que ni.o tente criar urnainst6nciq dela.) por que criar uma classeie voc nit pode criar objetos dela? porque a classe poderia ser simplesmente, bem, abstract. Por exemplo, imeging qu9 voqitgnh-a uma classe Car que tenha m6tpdo$ genericos comuns a todos os veiculos. Mas vocd n6o quer que]l-gq6- d. futo i.i. um objeto carge.r6ri.o, abst.r.act. t;ifro !d inici alzatia o seu estado? De que cor ele seria? Quantos assentos? Potancia do motor? bireg6o hidriulica ou nio? ou, mais imPortante, de que forma ele se comportaria? Em outras palavras, como os m6todos seriam implementados?
O que voc6 precisa 6 que os progtamadores instanciem tipos reais de carros, como BMWBoxster e SubaruOutback. Temos cefteza de que o dono de um Boxster lhe diria que o caffo dele 6. capaz de fazer coisas que o Subaru apenas ,.sonha em fazer". Observe a seguinte classe abstract:
'l
de Acesso
public abstract voj-d goFast ( ) ; public abstract void goupH]--Ll- (/; public abstract void impressNei.ghbors O ; / / Co1 odrrc o resfo do c6digo importante e s6rio aqui
/ / vv+vYqv
O c6digo acima iti compilar sem problemas. Entretanto, receber6 eros de compilagio como o seguinte:
se
abstract
com uma declaragio de m6todo que te"rmine com ponto-e-virgula, emvezde chaves. Se o m6todo estiver .o-Uniliaiq9,-9 $io em uma interface -, entaq tanto o m6todo como a classe devem ser marcados como abstract. Pode aparecer uma questao que lhe pergunte como consertar uma amostra de c6digo que inclui um m6todo que termina com p;nto-e-virgula, mas sem um modificador abstract na classe ou m6todo. Nesse caso, voc poderia ou rn rcar o m6todo e a classe como abstract, ou modificar o ponto- e-virgiapatao c6digo apropriado (um par de chaves, por exemplo). Lembre-se, se transformar um m6todo de abstrac E parando-abstract, n5o se esquega de trocar o ponto-e-virgula no final da d eclangdo do m6todo por um par de chaves! Examinaremos os m6todos abstract com mais detalhes mais adiante neste obietivo, mas lembre-se sempre de que, sq mesmo um s6 m6todo fqr abs,tract,.toda a classe dever6 ser declarada como abstract*Um -m6todo alQstracL clntamirra !o4a_a.!q!ma: Vocd pode,:ro entaoto, coloc-ar m6todos nio-abstract em uma classe abs-F-.ract' Por .*.-plo, rro.6 poderia ter m6todos com implementag6es que nio devem mudar de acordo com o tipo deCx,tais como
get|olorO
ousetPriceO.Aocolocarm6todosnZo-abstract emumaclasseabsEract,vocediatodasas concletas (e concreto significa apenas nio-abs!.5agt) implementagSes de m6todos herdadas. A boa noticia 6
.
preiiii-
(A prop6sito, se voc6 achou que usamos a expressio raison d'etre fora de contexto, anteriotmente, nio nos mande e-mail' de certificagio PM Progr madores') Queremos ver uoc6 colocarumra expressio dessas em um livro programar com tipos de classes
q..e voc6 tire vantagem do
abstract
e
polimorfismo,
(incluhdo interfaces, que serio discutidas mais adiante neste capitulo) permite lhe d6 o maior grau possivel de flexibilidade e extensibilidade. Voc6 aprender6
Nig pqssivl
Uf"C -.laeSe-abgLract-'p:ecisa-ser
mar:catrtm^classe como abstract e f inaf ao mesmo tempo. Elas t6m significados quase opostos' subclassificada, enquanto que uma classe f inaf nlo deve ser subclassificada. Se voc
efinal,usadosparaumadeclatzglodeclasseoum6todo,oc6digo
Exercfcio
chamada Fruit e urna subclasse concreta chamada Apple. A superclasse deve pertencer a um pacote um pacote chamado food e a subclasse pode pertencer ao pacote def ault (significando que ela ndo ser6 colocada em acesso def ault. expLicitamente). Torne a superclasse pubf ice d i subclasse
abstracg
1.
/* insira
JAVAS
II
class Apple extends Fruit{ ,/* insira qualquer c6digo que desejar */}
3. crie um diret6rio chamado food dentro do diret6rio configurado no seu class path. 4' Tente compilat os dois arquivos. Se quiser usar a classe Apple, certifique-se de colocar
subdiret6rio food.
o arquivo Fruit.class
no
l.l
e 1.2 do Exame)
de c/asses aninhadat),
1'l Desenuolaer aidigo qae declare clases (incluindo clasus abttract e todas asformas 4rEiado de dukmgdet package e inport (incluindo impo,tapdet utriticas). nttrfott
Desenuoluer aidigo que
o uso
nri ,l^n
Quando voc6 criar uma inte rfzce, estat6' definindo um contrato com o que a classe pode fazer, sem mencionar nada sobre como a classe o fad.Umalnterface 6 um conffato. Voc6 poderia escrevei uma interiace Bounceable, por exemplo, que
.rru
irt.riu..
precisa concordar em
uma interface Bounceable (Saltitante) for definida, qualquer classe que quiser ser ttatada como algo sal.ntante podet6 simplesmente implementar essa interface e fornecer oi6digo de seosiois m6todos.
Se
voce estara dizendo que as duas classes podem ser tratadas como "coisas saltitante-s", o qr..
gbi!9,uadadg-.tsltediferentes e-fortegaaelas.umacaracteristicaemiomum.Pore*emplJ,'vocpodequererquetantoa Ball quanto Tire tenham o mesmo comportamento, mas elas n6o compartilham nenhom^relacionamento de heranga; Ball.e stende Toy, enquanto Tite s6 estende iava.lang.Object. Por6m, ao frrer iom que Ball e Tire implementem Bounceable,
classe
As interfaces podem ser implementadas por qualquet clasEe, de,.quglguq 6rvore de heranEa. Isso permiur6 que voc use
quevocpodeusarparachamarosm6todosbounce(
relacionamento entre interfaces
e classes.
) esetBounceFor(
.-Jr.r"
traduzido por..coisas
)".AFigura1_1 ilustrao
O que vocd declara
interface Bounceable
frub].tc abrtract void bounce ( ) ; Dubtlc rJrttract void setBounceFactor(int bf),.
Oqueo
compilador
v6.
I
i
Class Tire implements Bounceable public void bounce( ) i... ] public void setBounceractor(int bf)t
l-l A Re/ogdo Entre /nferfoces e C/osses Considete uma interface como uma classe 100%o abstract. Como uma classe abstract, a interface define m6todos abstract com a forma, abstract void bounceo; // Termina com ponto-e-virgu1a, em vez de chaves Mas, enquanto uma classe abstract pode definir tanto m6todos abstract quanto ndo-abstract, r*najnferfacp gggg.dt ter mtodos abstr-aqt. outro ponto em que as interfaces diferem das classes abstract 6 que elas
Figuro
12 Copftulo 1 : DecloroE6es
e Controle de Acesso
s6o declarados. As regras s5o apresentam muito pouca flexibilidade em como os m6todos e vari6veis definidos na interface restritas:
I ,. ' I
Todososm6todosdeinterfacesioimpliciamentepublic eabstract.Emoutraspalavras'vocenaoprecisadigitar
realmente os modificadores
publ ic
ou
abstract,
PubIic eabstract.
Todasasvariaveisdefinidasemumainterfacedevemserpublic,
static
inal
-emoutraspalavras,as
; I Osm6todosdeinterfacesn6opodemser static' a Jaque os m6todos de interface sio abstract, nio podem ser marcados como f inal, native, strictfp synchronized. (Falaremos mais sobre esses modificadores a seguir) i I Uma interface pode estender uma ou mais interfaces diferentes. I f Uma interface nio pode estender nada que nio seja outra interface. 1 I Uma interface nio pode implementar outra intetface ou classe. f Uma interface deve ser declarada om apalavn-chave interf ace. \ I r Os tipos de interface podem ser usados polimorficamente (consulte o Capitulo 2paramais detalhes)'
c
ou
A linha
a seguir 6
public abstract interface RoIlable { } voce Digitat o modificador abstract 6 considerado redundante; as interfaces serio implicitamente abstract caso essas duas declarag6es sio vilidas e funcionalmente id6nticas: .ligite ou n6o abstract. 56 6 preciso saber que public abstract interface Rol1ab1e { } public interface Ro1lable { } g*+."di. 4S_ed"r pub 1 i c ser6 obrigat6rio se voc quiser que a interface tenha acesso priblico em Yez de padrig.
Examinamos z declaragdoda interface, mas agora nos aprofundaremos nos mdtodos de uma interface:
Public interface aounceable { public abstract void bounce ( ) ; cublic abstract void setBounceFactor(int bf)
i
por6m, digitar os modificadores public e abstract nos m6todos 6 redundante, i6 que todos os m6todos de interface slo implicitamente publ ic e abst,ract. Dada essa regta, vocd pode ver que o c6digo a seguir 6 exatamente
equivalente
a
interface antenor:
public interface Bounceable { void bounceO ; / / sem modificadores void setBounceFactor (int bf) ; / / sem modificadores
]
Vocprecisalembrarquetodesosrn6todosdeinterfaces6opublic
definigio daintetface.
eabstract
independentedoqueestivetoa
procure m6todos de interface declarados com qualquercombinaglo que envolvapublic ou abstract, ou sem vilidas e modificadores. por exemplo, as cinco declarag6ls de m6todo a seguir, se declaradas dentro de uma interface, serio
idnticas!
void bounce O ; .,, public void bounce O ; abstract void bounce O ; : Fubf ic abstract void bounce O abstract public void bounce O ;
,'
// f1-nal- e abstract jamais podem ser usados juntos' / /abstract j6 est6 imPlicito
JAVA
13
/ interfaces definem m6todos de instAncias / / os m1todos de interface sio sempre public / / (iden)
/
interface
Ao colocar
as constantes diretamente n ainterface,qualquer classe que impleme ntar aintefiace ter6 acesso direto is constantes, como se as tivesse herdado.
de-
Yo4-ef9gi.tilg lembrar
nrrhlin
uma reg,ra fundamental para constantes de interfaces. Elas devem sempte se1
et=f i^ +inal.
int-e-ttlqgrplas4ig.precig-arnsel.deg!4rqdascomopubflc,static oufinal.Flasdevemserpublic, g!flq-*i.c g-f inal- ma's voc6 n6o ptecisa declarS-las explicitamente dessa maneiri. Assim como os m6todos de interfacessiosemprepublic eabstract,independentementedevoc6indicarissoounionoc6digo.qualgref v"*gttf"dggde."9!9'-9.1F'4 tnre{-faqe-deJe sskgsg*4ltaBe-tlle 6 uma constante publ i c . veja t. -'o.e .onr.grre perceber o problema com o seguinte c6digo (assuma que sdo dois arquivos separados):
Isso parece simples, certo? Afinal, as constantes de interfaces nio sio diferentes de quaisquer outras constantes acessiveis publicamente, entio, obviamente elas precisam set declaradas como public, sLatic e f inal-. Mas, antes de pular o restante desta discussio, pense nas implicag6es:.pelo.f3r!o dg_ a.s.constantes de interfaces serem definidas em uma
l
Vocd nio pode alterar o valor de uma constante! I-lma vez que o valor tiver sido atribuido, nunca poder6 ser alterado.3! qqP"iflg gtgr+-e.{?-ngptpgsaintedacq(onde-a constante for de't'ua&), Rg!-tag-tofr-g1"... qlr. " .i1irr.., implementando ggdglgaceg.la;!9 e us6-.!g, mas como um valor somente de leirura. Assim,l-atritdgao geR = 27 rdo complar6".
// varece nao-static e n50-fina1, mas n50 6, // parece defaul-t, ndo-final e ndo-static, mas ndo 6! // Neo mostra final ou public // Ndo mostra static ou public
// Nao mostra final
/ Nao most.ra static // Nd,o mostra public // o que voc6 recebe implicitamente
/
.f
dos motlficadores necessriios (poriru in4licitos) d udlida, como tambdm o i o nlo artliqasio de modficadores! No exame' espere encontrar perguntas as quais ndo podeni responder coretamenle, a ntenos qae saiba, por exempl0, qae y.f a.u,,!!!,t!!,! dg-innface
final
enanrapodenireceberumualordarlasseqaeaestiuerimp/emenlando(oadeqaa/qaeroarrarlasse).
.i
Desenuoluer
e ase
primitiuos,
coma uaridueis
stat ic,
de instdncias e locais'
Aldn
l.4Desenuolueraidigoqaedeclaremdtotlosstatic
tle nomeapdl
enio-sLaLic
e,seapropriado,ilsarnomesdemdtodosqaeobedtpanaospadrdes
JauaBi^.
ZU,
tlisso, d.esenuoluer aidigo que declare e use ama lista de argunentos de extensio uaiduel. e agora
J6
vimos o que significa usar um modificadot em um a declangdo de classe, declatagdo de um m6todo ou uma vari6vel.
Os m6todos e as vari6veis de inst6ncias (nioJocais) sio conhecidos coletivamente como membros. Voc6 pode modificar um membro que tenha tanto modificadores de acesso como modificadotes que nio se referem a acesso, e vocd tem mais modificadorei para escolher (e combinar) do que quando est6 declarando uma classe.
Modificadores de Acesso
Pelo fato de os mtodos e vari6veis normalmente receberem controle de acesso exatamente da mesmas forma, abordaremos ambos nesta segio.
Enquantoumaclasrcs6podeusardoisdosquatroniveisdecontoledeacesso(default
podem usar todos os quatro:
oupublic),osmembros
r I I I
A proteg6o padrdo6 o que voc recebe quando nio digita um modificador de acesso na de clatagdo do membro. Os tipos de
E crucial que voc6 saiba tudo sobre o controle de acesso par o exzme. Haver6 uma boa quantidade de Perguntas pataas controle qoais voc6 dever6 usar o seu conhecimento sobre controle de acesso. Algumas quest6es testam v6rios conceitos de o desconhecimento de uma pequena parte que seja do assunto poder6lhe custar uma de acesso ao mesmo tempo, enrio questio inteira.
em uma classe ter acesso a um membro de outra classe? Por agora, ignore quaisquer diferengas entre m6todos e vari6veis. Se a classe A tiver acesso a um membro da classe B, isso significa que o membro da com voc6 classe B est6 visivel para a classe A. Quando uma classe nZo tem acesso a ouffo membro, o compilador vai brigar
O que signific
o fatode o c6digo
por tentar acessar algo que voc6 nio deveria nem saber que existe!
Voc6 precisa entender duas quest6es difetentes telativas ao acesso:
I I
Se Se
o c6digo de um m6todo em um classe pode acessarDm membro de outra classe uma subclasse pode berdarwm membro da sua superclasse
O primeiro tipo de acesso ocorre quando um m6todo de uma classe tenta acessar um m6todo ou uma vari6vel de outra .1"..., lrsr.rdo o operador ponto (.) para invocar um m6todo ou obter uma vari|veL Por exemplo:
class
Moo
nrrl.r'lin
Zoo
Moo
terS
acesso
JAVA
15
// d classe zoo / / Mas'.. . ser6 que tem acesso a coolMethodO ? System.out.println("A Zoo says, " + z.coolMethod() ); / / A linha anterior funciona porque Moo pode acessar
/ / mAraAn nrrl-r'] i a
l
O segundo tipo de acesso refere-se
aftavs da heranga.
a quais membros de uma supetclasse (se 6 que existem) uma subclasse pode acessar estamos querendo saber se a subclasse pode, digamos, invocar um m6todo para uma instincia da supetclasse (o que seria aPenas um exemplo do primeiro tipo de acesso). Em vez disso, queremos saber se a subclasse pode berdarum membro da sua superclasse. Lembre-se de que se uma subclasse herdaum membro, 6 exatamente como se a subclasse tive sse declarado o membro ela mesma. Em outras palavras, se uma subclasse herdaummembro, efltao ela tem
Nio
esse
membro.
class Zoo {
nrrhl i n (f ri na nnnl Morhnrl uvvrrrLuarvs
// \\
I t
return
l
"Wow
baby";
class Moo extends Zoo { public void useMyCoo1MethodO { / / Ser6, que uma instAncia de Moo herda coolMethod ( ) ? System.out.println("Moo says, " + this.coolMethodO ); / / A J-inha anterior funciona porque Moo pode acessar o / / m6todo public // Ser6. que uma instAncia de Moo pode invocar coolMethodQ / / wma instAncia de zoo? Zoo z = new ZooO; System.out.pri.ntln("Zoo says. rr + z.coolMethodO ); // coolMeuhodO 6 public. entao Moo pode invocd-Io em / / uma refer6ncia a zoo
) )
em
A Figura
1,-2
faz a comparagdo entre uma classe herdando um membro de outra classe, e acessando um membro de outra
classe usando uma referncia de uma inst6ncia dessa classe. se concentra em se as duas classes envolvidas estao no mesmo pacote ou em diferentes. N6o se esquega, no entanto, q,te se apnipria classe A nio puder ser acessada pela classe B, ent6o nenhum Pacotes membro da classe A poderi, ser acessado pela classe B.
Vocd precisa saber o efeito de diferentes combinag6es de acesso a classes e membros (por exemplo uma classe padrao com uma vari6vel pubJ- ic). Para descobrir issq primeiramente observe o nivel de acesso da classe. Se a pr6pria classe nio for visivel a outra, entio nenhum dos seus membros ser6 visivel, nem mesmo se forem declarados publ ie. Depois de confirmar que a classe est6 visivel, 6 uma boa id6ia observar os niveis de acesso nos membros individuais.
Membros Public
Quando um mtodo - ou vatiivel-membro - 6 declarado publ i c, isso significa que todas as outras classes, independentemente do pacote ao qual pertengam, podem acessar o membro em questao (assumindo-se que a pr6pria classe
esteia visivel).
dostuff
)
goFast
( ( (
goFast
Convertible doThings(
)
){
)t
Driver
doDriverSEuff (
){
car.goFast( );
)t
herdado
import cert.*; // tmporta todas as classe do pacote certo class Goo { public static void main (String IJ args) { Sludge o = new SludgeO; o.testIt O ;
)
i
Agora observe o segundo arquivo:
narkanp acrl.
Como vocd pode ver, Goo e Sludge estao em pacotes diferentes. Entretanto, Goo pode invocar o metodo em Sludge sem problemas, porque t^nto a classe Sludge quanto o seu metodo test.It ( ) est6o marcados como public.
Pan uma subclasse, se um membro da sua superclasse for declatado pub 1 i c, independentemente de se ambas as classes estarem no mesmo pacote ou nio:
a subclasse
JAVA
n:^Lrd6 ^arf.
17
public class Roo { public String doRooThings O { / / imagine o c6digo divertido que entra aqui
rafrrrn \fr1n/.
A classe Roo declara o membto doRooThings ( ) como publ i c. Assim, se criarmos uma subclasse de Roo, qualquer c6digo presente nessa subclasse Roo poderi chzmar o seu pr6prio m6todo doRooThings ( ) herdado.
package
notcert; / / NEo 6 o pacote em que import cert . Roo; class CIoo extends Roo { public void testcloo ( ) { System. out . println (doRooThings ( ) ) ;
l
]
Roo se encontra
Repare no c6digo anteriot que o m6todo doRooThings ( ) 6 invocado sem a necessidade de prefixi-lo com uma referdncia. Lembre-se de que se voc vir um mdtodo invocado (ou uma vad6.vel acessada) sem o operador ponto (.), isso sigrrifica que o m6todo ou a vari6vel pertence i classe onde voc6 l'ru esse c6digo. Tamb6m significa que o m6todo ou a vai6velest6 sendo implicitamente acessado(a) usando-se areferncia this. Assim, no c6digo anteior,acharnadaa doRooThings ( ) na classe Cloo poderia tet sido escrita como thi s . doRooThings ( ) . A refer6ncia thi s sempre se refere ao objeto sendo executado atualmente - em outras palavras, ao objeto que esteja rodando o c6digo quando voc6 v6 a referncia thi s. Pelo fzto de a rcfetdncia thi s ser impiicita, voc6 n6o precisa prefixar o seu c6digo de acesso a ela, mas se o fizer nio havet6 nenhum problema. Alguns progtamadores o incluem p ar^ torn t o c6digo mais f6ci1 de l er p^ta, programadores iniciantes ou desconhecedores deJava.
Al6m de poder invocar o m6todo doRooThings O para si mesmo, o c6digo de alguma outta classe pode chamar doRooThings ( ) para uma instincia de Cloo, da seguinte forma:
class roon { public static void main(StringtJ argrs) Cloo c = new Cloo0; System. out.println (c. doRooThings ( ) ) ;
Membros Private
Membros marcados como private ndo podem ser acessados por c6digo em nenhuma ouffa classe que nio aquela na qual foi declarado. Vamos fazer uma pequena modificagio na classe Roo apresentada em um exemplo o membro private
antedot.
cert; public class Roo { private String doRooThings ( ) { / / Imagine o c6digo divertido que entra aqui , / / a c]-asse Roo sabe disso
package
ratlrrn rrfrlnrr.
mas apenas
O m6todo doRooThings ( ) agora 6 private, entao nenhuma outra classe pode us6-lo. Se tentarmos invocar o m6todo a partir de qualquer outra classe, teremos problemas:
package
i mn^rf +rrryv!
notcert;
D^^.
e ^6rf
cl-ass useAr{oo t
tt
// Ate aqui, tudo bem; a classe Roo 6 prlblica (r.doRooThingsO ) i // Erro de compilaqdol
I )
.I
Se
cannot find symbol symbol : method doRooThings ( ) E como se o m6todo doRooThings ( ) nio existisse,
verdade. Um membro
private
e, no que diz respeito a qualquer c6digo fora da classe Roo, isso invisivel para qualquet c6digo fora da pr6pria classe do membro.
herdar um membro private da sua supetclasse? Quando um membro 6 declarado uma subclasse nio pode herdar dele. Pata o exame, voc6 precisa entender que uma subclasse nio pode ver, usar e nem sequer pensar nos membros private da sua superclasse. Voc6 pode, no entanto, declarar um mtodo cortespondenie na subclasse. Mas, nio importa asuaapai.nci^,t Ao se irqta de um mdtodo substitutolE simplesmente um m6todo que por acaso tem o mesmo nome que o m6todo private (de cuia existdncia voc6 nio deve sequer saber) da superclasse. As regtas de substituigio ndo se aplicam, de forma que voc6 pode fazer esse m6todo "rec6mdeclarado-que-por-um-mero-acaso-6-o-mesmo" declarar novas exceg6es, ou modificar o tipo de retorno, ou qualquer otrtra coisa que voc6 queira fazer com ele.
private,
nanlrana
rarf
public class Roo { private String doRooThings ( ) { // Imagine o c6digo divertj-do que entra aqui, / / orttra classe saber6 disso return "fun" .l
O m6todo
mas nenhuma
doRooThings
agora est6 fora do alcance de todas as subclasses, at6 mesmo aquelas que esteiam no
bem
/ Erro de compilaqdo
l
Se
tentarmos compilar a subclasse Cloo, o compilador tet6prazer em apresentar um erro parecido com este:
?javac Cloo.java Cloo. java:4 : Undefined method: doRooThings o System. out. println (doRooThings ( ) ) ;
1 error
AO TRABALHO
lhe s/a penaitido marcar uaiit'eis de instdnciat coma publ ic, napnitica qaase sempre d melhor nanter todas as uaridueis como private ou protect. Se as uaidueit precisarem vr modficadat, defnidas oa /idas, os programadores deuem usar nitodos de ausso public, para que ctidigos em quaisquer outras classes tenhan de pedirpara obter on defnir uma uariduel (passando atrauds de *m rudtodo),
Enbora
em ueqde acerd-/a diretamente. Os ndtodos de acesso conpatiueis con JauaBeans tm aforna get<noneDaPropriedade) ou, para booleanos, is<noneDaPropriedade> e set<nomeDaPropriedade>, efornecem um lugar onde uocd pode uerifcar e oa ua/idar antes de retomar ou
JAVA
modficar um ualar.
19
Sem usaprotepdo, a uari,iuel weight ('pesa') de an objeto Cat, por exempl0, poderia ur defnida nmo tlm nilmem negatiuo caso o cddigo in@npiado tenba acesso direto i uaiduel publ ic, coml em somecat . weight = -20. Mas un mdtodo dz acesto, setweight (int wt), podeia uerifcar se o nilmem d @ropiado. (Ok, tudo isso d especulagdo, mat estamos partindo do prina?io de qae un peso negatiuo poderia ser in@ropriado para am gato. Ou ndo.) O Capitalo 2 divutinl esta prutu(Ao de dadot (enc@ulanento) com mais detalhes.
E possivel um m6todo private ser substituido por uma subclasse? Essa 6 uma pergunta interessanre, mas a resposta, tecnicamente, 6 nio. Uma vez qve a subclasse, como vimos, nio pode herdar um m6todo private, ela, portanto, nao pode substituir o m6todo - a substituigio depende da heranga. Abordaremos as implicag6es disso com mais detalhes mais adiante nesta segio, bem como no Capitulo 2,mas,por agora basta lembrar-se de que um m6todo marcado como pri vate nao pode ser substituido. A Figura 1-3 ilustra os efeitos dos modificadores publi-c e private em classes de um mesmo ou de diferentes Dacores.
SportsCar goFast (
dosEuff ( ) {
goFast (
) {...} ),
Convertible
Subclasse
Driver
r'ffit"tt
con =
l'
nehr
convert.ible( );
herdado
membro de f aul t s6 pode ser acessado se a classe que o estiver acessando pertencer ao mesmo pacote, enquanto que um membro protect pode ser acessado (atrav6s da heranga) por uma subclasse rnesmo se e subclasse estiuer em urn
as duas classes
edefault
sioquaseidnricos,mascomumadiferengafundamental.Um
seguintes:
i f i z --- *--*JaEfon,.
20 Copftulo 1 : DecloroE6es
e Controle de Acesso
/ /
woiri festTr () { L
System. out
.
println ( "Othercl-ass"
package somethingElse
imnarf
+LLrFv! e
aarf
i f i nrf
i nr
ntharr-l
rae.
class AccessClass { static public void main(Stringtl args) Othercl-ass o = new OtherClassO; o. testIt O ;
j'
( ) do ptimeiro arquivo tem acessopddr1o (ot seja, de niveldopacote). Repare tambem que a classe OtherClass se encontra em um pacote diferente de AccessClass. Serl que AccessClass poder6 usar o m6todo t e s t f O ? Vai causar um erro de compilagdo? Ser6 que o Daniel vai se cas ar colr, aFrancesca? Nio perca os pr6ximos
testlt
capitulos.
No method matching
Pelosresultadosacima,vocpodeverqueAccessClassniopodeusarom6todotestlt
la, o compilador reclama, e n6s nao temos nem id6ia de quem sejam Daniel e Ftancesca.
Os comportamentos
protected
protect
heranga. N6o faz diferenga se a superclasse e a subclasse estao em pacotes diferentes, o membro da superclasse protect ainda estard visivel para a subclasse (embora visivel apenas de uma formabastante especiftca, como veremos mais adiante). Isso contrasta com o comportamento paddo,que nio permite que uma subclasse acesse um membro da superclasse, a nio ser que a subclasse esteia no mesmo pacote que a superclasse.
Enquanto que o acesso padrio nio estende nenhum considetagdo especial is subclasses (ou voc6 est6 no pacote ou nio esti), o modificador protected respeita a relagao parent-chjld, at6 mesmo quando a classe child se desloca (e iunta-se d um novo pacote). Assim, quando pensar em acessopadrdo,pense em restrig6es depacote. Sem exceg6es. Mas, quando Pensar em protect, pense em?acnte + kids.IJma classe com um membro protect esti marcando esse membro como tendo acesso de nivel do pacote pata todas as classes, mas com uma excegio especial para subclasses fora do pacote.
Mas o que significa uma subclasse de fora do pacote ter acesso a um membro (parent) da supetclasse? Significa que a subclasse herda o membro. Nio significa, no entanto, que a subclasse de fora do pacote possa acessar o membro usando uma refer6ncia a
protect da superclasse como se ele fosse publ ic. Assim, se a subclasse de fota do pacote obtiver uma refer6ncia i superclasse (cdando, por exemplq uma instAncia da superclasse em algum lugar no c6digo da subclasse), a subclasse nio pode usar o opetador ponto na refetncia i superclasse para acessar o membro protec. Para uma subclasse de fora do pacote, um membro protect poderia da mesma forma ser def aul-t (ou mesmo privado), quando a subclasse est6
o membro
usandoumarefernciaisuperclasse.Asubclasses6podeveromembroprotect
atrav6sdaheranga.
Est6 confuso? N6s tamb6m. Agriente firme e tudo ficar6 claro com a s6rie de exemplos segrintes. (E ndo se Preocupe, na verdade, nio estamos confusos. Estamos apenas tentando fazt-lo se sentir melhot caso voc6 esteia confuso. Sabe, tipo nio tem problema se voc estiver achando que nada faz sentido, e ndo 4 culpa sua. Ou serd que 6? <insira isada malvola aqui>)
Detalhes de
protect
protect
0embre-se de que uma vari6vel de instdncia 6 um
Vamos dar uma olhada em uma vari6vel de instincia membro) de uma superclasse.
JAVA
diferente, e tentar usar
a
21
package
imnnri-
carfi
class Child extends Parent { public void tesrlr ( ) { System. out . printl-n ( "x i_s \ + x) ;
O c6digo acima compila sem problemas. Repare, no entanto, que a classe Child estd acessando a vari6vel protect atrav6s dahetanga. Lembre-se, sempre que falarmos de uma subclasse ter acesso a um membro de uma superclasse, podetiamos estar falando de a subclasse herdar o membro, e nio simplesmente acess6-lo atrav6s de uma referdncia a uma ins tdtcia da supetclasse (que 6 a forma como qualquer ouua nio-subclasse o acessaria). Repare no que acontece se a subclasse Child (fora
do pacote da superclasse) tentar acessar uma variivel
protect
classe Parent.
package other,.
// Sem prdblema; Child / / herda x Parent P = new Parento; // Podemos acessar x usando // a refer6ncia a p? System. out.println ( "X in parent is " + p.x); // Erro de compilaqSol
System. out
l
O compilador alegtemente nos mostra qual
9'i:rr=n u -d . nl- ho- /alai fu. vurrLr/ Lrlf I .l i --'Jqva
6
o problema:
naranf
iq
rt r n v\.
^,u exceto
que um membro p ro t e c t tem, essencialmente, acesso de nivel do pacote ou padrio a todas as classes, vimos que as subclasses de fota do pacote podem herdar um membro prot.ect. Finalmente, j6vimos que as subclasses de forado pacotenao Podem usarumafefer6nciadi superclasse paraacessarum membropratecl. Pera uma subclnsse deforq do pacotq o membro protect stf pode ser acessado otraaes da heranqa.
;;:.*belecemos
as subclasses.J6
Ainda h6 mais uma questZo que nao consideramos... Q"ul 6 a aparncia de um membro protect para outras classes que tentem usar a subclasse de fora do pacote para obter o membro protect da superclasse que foi herdado pela subclasse? Por exemplo, usando as nossas classes Parent/Child anteriores, o que acontece se uma outra classe - digamos, Neighbor do mesmo pacote que Child (subclasse) tiver uma referncia a uma instincia de Child e queira acessar a vari6vel-membrox? Em outras palavns, como esse membro protect se comporta depois que a subclasse o herdou? Ele mant6m o seu status de protect, de forma tal que as classes no pacote de Child possam v6Jo?
que a subclasse de fora do pacote herda o membro protect, ele (conforme herdado pela subclasse) torna-se para qualquer c6digo de fotada subclasse, com a excegio das subclasses dessa subclasse. Assim, se a classe Neighbor instanciat um obieto Child, entdo mesmo se Neighbot estiver no mesmo pacote que Child, Neighbor nlo teri acesso i vari6vel x herdada (mas protect) por Child. Resumo da hist6ria: quando uma subclasse de fora do pacote herda um membto protect, esse membro torna-se essencialmente private dentro da subclasse, de forma tal que apenas a subclasseeassuassubclassespodemacess6lo.AFigural-4ilustraoefeitodoacessoprotect sobreclassesesubclasses no mesmo ou em diferentes pacotes.
Nio! Depois
private
Carambal Com isso terminamos protected, o modificador mais incompreendido emJava. Novamente, ele s5 6 usado em casos muito especiais, mas pode ter certezade que aparecer6 no exame. Agora que j6 abordamos o modificadorprotected, passaremos para o acesso padrio, uma molezacomparado a protect.ed.
22 Cqpitulo
Detalhes de Default
Vamos comegar com o comportamento padrd.o de um membro de uma superclasse. Modificaremos o membro x de Parent
panrorn6-lo def
ault. certif ication; public class Parent { int x = 9; / / Ausncia de modificadores de acesso / / indica acesso padrSo (de pacote)
package
)
Repare que nio colocamos um modificador de acesso na ftentedavai|vel x. Lembre-se de que, se voc nio di.grtar um modificador de acesso antes da decla ragdo de uma classe ou um membro, o conrole de acesso 6 o padtdo, o que significa de nivel do pacote. Agora tentaremos acessar o membro padrdo da classe Child que vimos anteriormente.
Se goFast$
for protegido
Pacote A
Pacote A
goFast( )t ]
Convertible
convergible
l--D'i'"'_l T^^t,
I er,"
t.
Pacote B
Convertible
[H-el *l
f *1"".
c;;ctb;l
E-tr-ll
Chave:
dofhings (
){
r------------1
l
Onde goFast 6
Declarado na mesma classe.
sc.goFast( );
It
L-.r-F:'=*[
I.
goFast$ foi
declarada.
Figuro
l-4
Efeitos
do ocesso
protect
Chi1d. j ava:4
6 declarado como private. A subclasse Child (em um pacote diferente do da superclasse Parent) ndo 6 capaz de ver nem usar o membro padrio x da superclasse! Agora, e quanto ao acesso padrio para duas classes do mesmo pacote?
package
certif ication
JAVA
23
package
certif ication ; class Child extends parent{ static public void main(StringlJ args) Child sc = new Chi_IdO; sc. testIt O
,.
i )
Sem
problemas
O c6digo-fonte acima compila sem problemas, e a classe Child roda e exibe o valor e x. Basta se lembrar de que os membros padrio ficam visiveis par:-as subclasses apenas se elas estiverem no mesmo pacote que a superclasse.
Nio
existe nenhum caso em que um modificador de acesso possa ser aplicado aumavailvel local, entio, cuidado com c6digo como o seguinte:
7;
Pode ter certeza de que qualquer vari6vel local declarada com um modificador de acesso fieo vai compilar. Na verdade. s6 existe um modificador que pode ser aplicado avari6veis locais f inal_. Isso termina a nossa discussio sobre modificadores de acesso de membros. A Tabela 1.-2 mostratodas as combinag6es de acesso e visibilidade; 6 uma boa id6ia passar algum tempo estudando-a. Em seguida, vamos passar para os outros modificadores (nio-referentes a acesso) que voc pode apltcar a declarag6es de membros.
Visibilidade
A partir da mesma classe A partir de qualquer classe do mesmo A partir de uma subclasse do mesmo
Pubtc Sim
pacote pacote Sim Sim Sim Sim
Protect
Sim Sim Sim
Sim,
Private
Sim
Nio
N6o
atrauis
Nio N6o
Nio Nio
da heranga
nio
seja
Nio
- inal
abstract -,
24 Coollulo
chroni
zed, nat
ive, strictf
ripida olhada em trans p, e depois uma longa olhada no grande modificadot - stat ic.
ient, syn-
Veremos primeiro os modificadores aplcados a m6todos, seguidos pelos modificadores aplicados a vari6veis de instAncias' Fecharembs esta segao com uma olhad" .- .orno stat ic funciona quando aplicado a vari6veis e m6todos.
M6todos Final
A palavra-chave f inal impede que um m6todo possa ser substituido em uma subclasse, e frequentemente 6 usada para ( forg"r os recursos API de om m6toio. Por exemplo, a classe Thtead tem um mdtodo chamado i sAl- ive ) que verifica se
om^ determin adathread atndz est6 airva. Se voc6 estender a classe Thread, no entanto, realmente nio h6 como vocd sozinho implementar corretamente esse m6todo (ele usa c6digo nativo, s6 para citar uma das taz6es), entao os elaboradores o to-"rrr., f inal-. Assim como nio 6 possivel subclassificar a classe String (porque precisamos confiar no comPortamento Essa de um objeto String), vocd nio poder6 substituir a matorizdos m6todos nas bibliotecas de classes fundamentais. mas voc6 deve us6-la com muito cuidado. Impedir que uma restrigio quanto a soUstitoigao propicia boa seguranga, atravds subclasse iubstitua um metodo invatida muitos dos beneficios da orientagao a obietos, incluindo a estensibilidade do polimorfismo. Uma declaragio de m6todo f inal tipica se pareceria com isto:
class SuperClass{ public fj-na1 void showSamPle O { System. out . println ( "One thing . " ) ;
)
E v6lido esrender SuperClass, umavez qwe a classe ndo esti marcada como f f inaf showsample ( ) , como o seguinte c6digo est|tentando f^zetl
inal-,
class SubClass extends SuperClassi public void showSampleO { // Tentando substituir om6todo / / f:-na:-- da suPerclasse System. out . println ( "Another thing . " ) ;
) Se tentar
?javac FinalTest.java
FinalTest.java:5: The method void showsampleO decfared in class subclass cannot override the final method of the same signature declared in cl-ass SuPerClass. Final methods cannot be overridden. public void showSample O { } 1 error
Argumentos Final
Os argumentos de m6todos sio as declarag6es de varidveis que aparecem entre parnteses na declatagio de um m6todo. Uma declaragdo de m6todo tipica, com multiplos afgumentos, se Parece com o seguinte:
}
as
recordNuniber seguem todas as regras aplicadas avari6veis locais. Isso significa podem ter o modificador f inal-: public Record getRecord(int fileNumber, final int recNumber) { }
Nesteexemplo,avartfivelrecordNumber 6declaradacomofinal,oquesignificaobviamentequeelanlopoder6ser
modificada ientro do m6todo. Neste caso, "modificar" significa atribuir um novo valor d vari6vel. Em outras palavras, um argumento f inal deve manter o mesmo valor que o pardmetro tinha quando foi passado para o m6todo.
um m6todo que foi declarado (como abstract) mas ndo implenentado. Em outras palavras, o m6todo nio cont6m nenhum c6digo funcional. E, se vocd se lembrar da segio "Classes abstract", uma declaraqio de m6todo abstract neo tem nem sequer chaves onde um c6digo de implementag6o pudesse ser colocado, terminando,
6
JAVA
25
emvez disso, com ponto-e-virgula. Em outras palavras, eIa ndo tem uru corpo de ndtodo. Voc6 marca um m6todo como quandoquerforgarassubclassesaforneceraimplementagloemquestao.Porexemplo,seescreverumaclasse Car com um m6todo goupHi 11 ( ) , voc6 poderia desejar forgai todos os subtipos de Car adefinir o seu pr6pdo comportamento de goupHill ( ) , especifico dquele tipo determinado de carro.
abstract abstract
classeinvilida:
public abstract void showSample O ; Repare que o m6todo abstract termina com ponto-e-virgula emvezde chaves. E, inv,i,lido ter um rinico m6todo abstract. que seja em uma classe que n6o seia declarada explicitamente como abstractl Observe a seguinte
publi-c class I1lega1C1ass{
classe
se
f11ega1Class. java:
abstract. It does not define void doftO from cl_ass I11ega1C1ass. public cLass I11ega1Class{ 1 error
voc6 pode, no entanto, ter uma classe compilar sem problemas:
abstract
{
abstract.
/ insira
um monte de
abstract.
nio
se trata cle
um
I I I
nio
abstract.
A declaragio do m6todo inclui chaves, em vez de terminar com ponto-e-virgula. Em outras palavras, o m6todo tem um
O m6todo inclui c6digo de implementagio.
ser que a subclasse tambdn seia
todos os m6todos
abstract
da superclasse. a
Aprimeirasubclasseconcretadeumaclasseabatraet
supetclasse.
deveimplernentattoda.sosm6todosabst,ract da
stract, a subclasse abst.ract nio precisa fornecerimplementag6es para os m6todos abstract herdados. Mais cedo ou mais tatde, no entanto, algu6m vai ctiat uma subclaise nio-abstract (em outras palavras, uma classe que pode serinstanciada), e essa subclasse teri de implementar todos os m6todos abstract de cima para baixo na 6rvore deheranga. O seguinte exemplo demonstra umaLrvorede heranga com duas classes abstract e uma concreta: public abstract class Vehicle { private String type; public absrract void goUpHitl O ; / / M6tod.o abst.ract public String gerType O { / / M6rodo neo-absrract return t)4)et
l
Concretosignificaapenasnio-abstract,entao,sevoctiverumaclasseabstract estendendooutraclasseab-
public abstract class Car extends Vehicle { public abstract void goUpHill O ; / / X:-naa abstract
nrrhl i a rrni r{ dan--TLirrrrrrgD v vvrq uvvqr yqvrf -^^
/\ \/
I t
public class Mj-ni extends Car i public void goUpHilI ( ) t / / c6digo especifico para o Mini subir ladeiras
i
]
getType O e doCarrhings O , porque eles ( ) ser abst.ract na superclasse Vehicle, e abstract, portanto), isso significa que a classe Mini - como a
os m6todos
primeiraclasseconcretaabaixodeVehicle-precisaimplementatom6todogoupHill O.Emoutraspalavras,aclasse
Mini nio pode deixar
a
implementagio do m6todo
abstract
abstract.
pa:.aapr6xjrr'a classe abaixo dela na 6rvote dehetanga, A Figura 1-5 ilustra os efeitos do modificador ab-
stract
absttact Car startEngine( ) abstract gaFor'ward( ) abstract reverse( ) stop( ) abstract turn(int whichWay)
absEracE SW
startEngine( ) // opcional rd( | // requerido reverse( ) // requerido turn ( int rdhichway) //requerido
) )
abst.ract gooffRoad(
I
//
rttrn{\
vsLLL
nin
.lJrtyrvttt.
imnlamenEado
Os m6todos
subclasse
abstract devem set implementados por uma nio-abstract. Se a subclasse for abstrata, ela n6o 6 obrigada a implementar os m6todos abstract, mas tem a
pemisseo de implementat qualquer um ou todos os m6todos abstract da superclasse. A classe AcmeRover 6 nioabs t rac t, entao ela precisa implementar o mdtodo ab -
declarado na sua superclasse, SUV e precisa implementar tamb6m turn ( ) , que nio foi implementado por SL]V
stract
abstracL
da superclasse. O seguinte
abstract herdado f oo O . Embora o m6todo implementagio do m6todo abstract da superclasse, na verdade f oo int I ) da classe B parega ser uma simplesmente um m6todo sobrecarregado (um m6todo que usa o mesmo identificador, mas diferentes argumentos)' enteo ele nio atende ao requisito de implementagdo do m6todo absLract da superclasse. Veremos as diferengas enre substituigio e sobrecarga com mais detalhes no Capitulo 2. stracL
e
private
abstract e f inal ao mesmo tempo, nem como ab- os m6todos abstract precisam ser implementados
(o
JAVA
27
praticamente opostos. Pelo fato de os m6todos private nio poderem nem mesmo ser vistos pof uma subclasse (_quanto mais herdados), eles tamb6m nio podem ser substituidoi, entio eles tamb6m nao podem ser marcados como
que na pr6tica significa serem substituidos por uma subclasse), enquanto que m6todos f e ndo podem jamais ser substituidos por uma subclasse. Ou, dizendo de outra forma, uma designagio significa que a superclasse nlo sabe nada sobre como as subclasses devem se comportar no m6todo Lm questio, enquanro que uma designagio f ina l- significa que a superclasse sabe tudo sob.r como todas as subclasses lpor -"1, afastadas qr.re estejam na 6rvore de heranga) devem se comPortarno m6todo em quest6o. Os modificadores ef
abst;act
sio
Finalmente,voc6precisasaberqueomodificadorabstract
Abordaremos os m6todos seria inv6lido:
stat ic
(
mais adiante
.r.rt. obl.ti-ro,
and
nized
tipica
se
s6podeseraplicadoamdtodos-ndoavari6viis,nemclasses,apenasam6todos.Umadeclarag6osynchronized
parece com a seguinte:
s)mchroni zed indica que um mdtodo s6 pode ser acessado por um thread de cada vez. N6s i exaustio no Capin lo 9, mas, por agora, tud; o que nos intereisa 6 saber que o modificador synchro_
public synchronized Record retrieveUserlnfo(int id) { } Voc6 precisa saber tambdm que o modificador synchroni zed. pode ser acompanhado
niveis de controle de acesso (o que significa que ele pode ser usado juntamente com
modificadoras de acesso).
qualqueiu-" d", t
indica que o m6todo est6 seodo implementado conforme aplataformz,freqtientemente e C. Voc6 n6o precisa saber como usar m6todos nativos pano etim.,basta saber qu. tr-ii.re um modificador (e, ponantq uma palavra-chave reservada) e-que nat j-ve s6 pode ser aplicado a mdtodos ndo a classes, nem avai6veo, a "p..rui m6todos. Repare que o corPo de um m6todo nativo deve ser ponto-e-virgula O (como m6todos abstraci), indicando que a implementagao foi omitida.
M6todos Strictfp
Vimos anteriormente o uso de strictfp como modificadot de classe, mas, mesmo que voc6 nio declare uma classe como str j-ct f p, ainda assim voc poderi declarar um m6todo individual como strictf p. Lembre-se de que Com
subjacente na qual aJ\M esti rodando. O inconveniente disso 6 que, se aplitaformasubjacente for capazde srrportar maior precisio, um mdtodo strictfp n6o poderd se beneficiar dessa capacidade. Voc6 s6 deseiati estudar o IEEE 754 se precisa r de algo para aiud6Jo a cak no sono. Para o exame, no entanto, voc6
strictfp forgaospontosflutuantes(equaisqueroperagoescompontoflutuante)aaderirem aopadriolEil,ET54. strictf p,6 possivel prever como os seus pontos flufuantes se comportarao,independentemente daplatafotma
11ma
strictfp.
I I
est6 inuocantlowm
m6todo:
dostuff("a", 2l;
rraid daQt-rrff
&
2 sao argumenros
patdmettos Aquilo na assinatura dom6todo indica o que o m6todo deve receber quando forinvocado:
I I I I
p"ia-.t.o
declara um pardmeftovar-arg, vocd deve especificar o tipo do(s) argumento(s) que esse do seu m6todo pode recebet. @ode ser um tipo primitivo ou um tipo de obieto.)
Sintaxe b4sica Para declarar um mdtodo usando um parAmetro vat-arg, voc escreve depois do tipo um sinal de reticncias (...), um espagq e depois o nome do array que ir6armazenar os parimetros recebidos.
Outfos pardmetros E v6lido tef outfos parametros em um m6todo que use um vaf-afg. Lirnites dos var-args O var-arg deve ser o riltimo parametro
por m6todo.
na assinatura do metodo, e voc s6 pode ter um var-arg
x) {
x)
t )
/ / sin1caxe incorreta void doStuff4(int x...) { } void doStuffs(int . x, char... y) { } //mais deumvar-arg void doStuff6 (String. . . s, byte b) { i / / var-arg tem de vir por rlltimo
Declarag6es de Construtores
EmJava, os obietos sio construidos. Sempre que voc cria um novo obieto, pelo menos um construtor 6 invocado. Toda toneladas de classe tem um construtor, e, se voc6 nio criar um explicitamente, o compilador vai criar um para voc. Existem regtas relativas aos construtores, e iremos deixar a discussio detalhada para o Capinrlo 2.Por agota,vamos nos concentrar flas regras b6sicas de declaragio. Eis um exemplo simples:
Foo
O {
rrilida
A primeira coisa
11rrl
a se reparar 6 que os construtores se parecem um bocado com m6todos. Uma diferenga fundamental 6 que n6o poie nonca, i"mais, ter um tipo de retorno.., Nunca! As declarag6es de construtores podem ter, no .orrrtr.rtor entanto, todos os modificadores de acesso normais, e podem usar argumentos (incluindo var-args), da mesma forma como os m6todos. A outra REGRA IMPORTANTE a se entender sobre os constmtores 6 que eles devem ter o mesmo nome que a classe no qual sio declarados. Os construtores nio podem ser matcados como s t at i c (afinal eles sio associados com instanciaminto de objetos), nio podem ser marcados como f inaL nem abstract (porque ndo podem ser
invalidos:
cJ-ass Eooz
/
/ consLrutores vSlidos
}
Foo2O {
v)
t)
JAVA
29
/ constTutores invSLidos
void Foo2 O { } / / 6 um m6t.odo, ndo um consrrur.or FooO { \ / / n5o 6 nem m6todo nem conscruuor Foo2 (short s) ,. / / se parece com um m6todo abscracc static Foo2(float f) { } // ndo pode ser static final Foo2 (long x) { } / / ndo pode ser fj_naI abstract Foo2 (char c) { I t t ndo pode ser abstract Foo2(int.. x, int t) { } tt sintaxe var-arg lncorreEa
Declarag6es de Variiveis
Existem dois tipos de vari6veis emJava:
I I
long, double
ou f
l-oat.
ser de oito tipos diferentes: char, boolean, byte , short , int , IJmavez declarado, o seu tipo primitivo nio pode nunca ser modificado, embota na
se
modificar.
se referir (ou acessar) um objeto. Uma variavel de referdncia 6 declarada como sendo de um tipo especifico, e esse tipo nio pode nunca ser modificado. Uma vari6vel de referncia pode ser usada para referit-se a qualquer objeto do tipo declarado ou de tm subtipo do ipodeclarado (um , tipo compativel). Falaremos muito mais sobre o uso de uma vari6vel de referCncia para referir-se a tlm subtipo no Capitulo 2, onde discutiremos o polimorfismo.
byte
l nf v
b,'
;
j_nt
Em vers6es anteriores do
para o maior) byte, short, int e long, e que doubles sio maiores do que floats.
exame, voc precisava saber como calcular intervalos para todos os primitivos ava. Para o exame J atual, voc pode pular alguns detalhes, mas ainda 6 impotante entender que, para os tipos intiiros, a seqtidncia 6 (do menot
Voc tamb6m precisar6 saber que os tipos num6ricos (tanto inteiros quaflto de ponto flutuante) sio todos assinalados, como isso afeta os seus intervalos. Pdmeiramente, vamos revisar os conceitos.
Todos os seis tipos num6ricos emJava sio feitos de um certo nrimero de bltes de 8 bits, e s2to assinalados,significando que podem ser negativos ou positivos. O bit mais i esquerda (o digito mais significativo) 6 usado para representar o sinal, em que 1 significa negativo e 0 sigmfica positivo, como mostrado na Figura 1-6. O resto dos bits ..p..r..rturn o valor. usando a
notaqao de base 2.
= negativo
ryi / \
I
bit de sinal
00100r.1
bits de valores:
byte: 7 bits representam 27 ou 128 valores diferentes: de 0 a 127 ou de -128 a -1
t__=\
bit
fe
valores
short
21
ou 327 68
-1,
Figuro 1-6
se
voc
Tobelo
l-3
Tipo b)'t'
short
1nt
Intervalo Minimo
Intervalo Miximo
21
-1
1
t6
5Z
oz+
)15 .r3r
163
a15
)3r
L
long
float double
a63_L I
JZ
oz+
n/d n/d
n/d n/d
^rmazen^ Para tipos booleanos nlohdum intervalo; um booleano s6 pode ser true ou false. Se algu6m lhe perguntar a profundidade de bits de um tipo booleano, olhe bem nos olhos da pessoa e diga "depen de da mdqutna vktual" . F,la ficar6 impressionada.
O intervalo para nimeros de ponto flutuante 6 complicado de determinar, mas felizmente voc6 nZo precisa sab6-los para o 64 bits, e um float armazena32). exame (embora 6 esperado que voc6 saiba que um double
O tipo char (um caracter) cont6m um s6 caracter Unicode de 16 bits. Embora o coniunto ASCII estendido conhecido como ISO Latin-1 precise de apenas 8 bits Q56 carzcteres diferentes), 6 necess6rio um intervalo maior pata rePresent^t car^ctetes encontrados em linguas diferentes do ingl6s. Os caracteres Unicode, na verdade, sdo representados por ndmeros inteiros de 16 bits nio-assinalados, o que significa 216 tipos possiveis, que vio de 0 a 65535 Q\ -1. No Capitulo 3, voc6 aprender6 que, pelo fato de um char ser na verdade um tipo de nrimero inteiro, ele pode ser atribuido a qualquer tipo de nfmero grande o 65535 (o que significa qualquer coisa maior do que um tipo short. Embora tanto chars quanto suficiente p^tz ^rm^zenar shorts sejam tipos de 16 bits, lembre-se de que um short usa l bitpara rePresentar o sinal, de modo que menos nfmeros positivos sio aceit6veis em um short).
Object o;
Dog myNewDogRe f erenceVariable
;
Variiveis de lnstincias
As varidveis de instdncias sio definidas dentro da classe, mas fora de qualquer m6todo, e s6 stro inrcia\zadas quando a classe 6 instanciada. As vari6veis de instincias sio os campos que pertencem a cada obf eto fnico. Por exemplo, o seguinte c6digo define campos (vari6veis de instAncias) par^name (nome), tide (tftulo) err:'ar'aget (gerente) para obf etos employee
(funcion4rio):
n l : cc E'mnl nrrao {
/ d.efine campos (vari5veis de instAncias) para instdncias de employee private String name; private String titl-e, private String manageri / / ouLros c6digos aqui, incluindo os metodos de acesso para campos privados
/
JAVA
5 3I
A classe Employee antetior diz que cada instAncia de employee saber6 qual 6 o seu pr6prio nome, titulo e gerente. Em ouras palavras, cada instAncia pode ter os seus valores irnicos para esses ff6s campos. Se voc6 vir os termos "campo", "vari6vel de instdncia", "propriedade" ou "atributo", eles significam praticamente a mesma coisa. (I.{a verdade, existem disting6es sutis, mas ocasionalmente importantes enfte os termos, contudo, elas nio sio usadas no exame.)
Parao exame,voc6 ptecisa saber que
as
varidveis de inst6ncias
de acerso
(o que significa que eles podem ser marcados com qualquer um dos
I Podem sermarcadas como f inal I Podem sermatcadzscomo transient I Nio podem sermarcadas como absLract. I N6opodem sermarcadas como sinchroni-zed I Nio podem sermatcadas como strictfp I Niopodem sermarcadas como native I Nio podem set marcadas como stat. ic, porque isso as transformatia sient
emvati|veis de classe.
J6 abordamos os efeitos de se aplicar controle de acesso a vari6veis de instincias (funciona da mesma maneira que para m6todos membros). Um pouco adiante neste capin:lo, veremos o que significa aplicar o modificador f inal oo t.ran-
zumavari|ve.Tdeinstincia.Primeiro,daremosumar6pidaolhadanadiferengaentrevari6veisdeinstAnciase
a
m6todos em contraste
Vari6veis locais
Varidveis (nioJocais)
Mtodos
final
finaL
nrrhf i ^ yuvf+e
tinaL
nrrl.r'l'i ysvrre hr^|-a-l-aA Fr vevv nrirr.f-a D LdLIU a ues
protected
abstract
synchronized
c|-ri al-fn
native
iguro l-7 ComporoEdo de modificodores pqro vori6veis x m6fodos
de Acesso
l
Na maioria dos casos, voc vai iticiahzat umavariivel local na mesma linha em que a declarar, embora voc6 possa ainda ter de rcintciall2|-la depois, no m6todo. A chave 6 se lembrar de que uma vari6vel local precisa s er iniciabzada antes de voc6 tentar us6-1a. O compiladot rejeitar6 qualquer c6digo que tente usar uma vari6vel local que ndo tenha recebido um valor, porque - ao conffario das vari6veis de instAncias - as vadiveis locais n6o recebem valores-padrio. Uma varidvel local nio pode ser referenciada em nenhum c6digo fora do m6todo no qual foi declztzdz. No exemplo de c6digo anterior, seria impossivel referir-se dvari|vel count em qualquer outro lugar da classe exceto dentro do escopo do mtodo logln ( ) . Novamente, nio queremos dizer com isso que o valor de count n6o possa ser passado pan fon do m6todo para comegar uma nova vida. Mas a vari6vel que armazena esse valor, count, nio pode ser acessada depois de o m6todo frnaltzar, como o seguinte c6digo inv6lido demonstra:
'...-', t count = i; // Ndo vai compilarl Nao 6 possivel acessar count // de fora do m6todo logino
dnenmafhina/int
i \
I )
)
,4
E possivel declarar uma.vari6vel local com o mesmo nome que uma vari6vel de instincia. Isso 6 conhecido como sonbreamento, como o seguinte c6digo demonstra:
class Testserver { int count = 9; / / Declara uma vari6vel de instAncia chamada count public void logInO { int count = 10; // Declara uma vari6vel 1oca1 chamada count System.out.println("1ocal variable count is " + count),'
I
)
i
O c6digo acimaproduz a seguinte saida:
10
9
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:
JAVA
hrr'|.\'l i IJu!fre ^ r'^.i A Deuer-s\frrL raf qi to vvfu (inf <.i zo\ ofzs/ I I
33
]
Entio vocd decidiu que - para melhor Iegibilidade
a
- voc qu er dx ^o parrametro o mesmo nome que a vari6vel de instincia para qual o seuvalor se destina, mas como resolver a cotseo dos nomes? Use a palavrz-chavethis. Apalavn-chave sempre, sempre, semPre se refere ao ob,eto sendo executado atualmente. O seguinte c6digo mosta isso na pretica:
this
class Foo { int size = 2'7 ; public void setsize(int size) { this. size = size ; / / L}ris. size significa a vari6vel de instAncia / / do objeto atual , slze. O valor de size // d, direita 6 o parametro
l
l
Declarag6es de Arrays
EmJava, os arrays sio objetos qve m mriltiplas vari6veis do mesmo tipo, ou varilveis que sio todas subclasses do ^rmazen mesmo tipo. Os attays podem arm^zeflar owprimitivos ou referdncias a obf etos, mas o pr6prio anay serS,sempre um obieto no heap, mesmo se o array for declarado paraarmzrzerrar elementos primitivos. Em outras palavras, nio existe um array primitivo, mas vocd pode criar um array de primidvos.
Para o exame, voc6 precisa saber ffes coisas:
I I I
Como
cizrwavai|vel
Como criar um objeto array (construir) Como preencher o array com elementos (inicializar)
Para este obietivo, voc6 s6 ptecisar6 saber como declarar um array; n6s abordaremos a construgio e airttciilrzagdode artays
no
Capitulo 3.
AO TRABALHO
Os
analt
sdo efcientes, e
ArrayList
/eitara
e assim
TreeSet). At
na*fuxzueis
por diante) e, ao contniio dos ara1s, podem se expandir ou contrair dinamicamente i medida que uoci adiciona ou remoae elementos. Existe un tipo Collection para ltma amp/a gama de necessidadu. Vocd precisa de una classifcagdo nipida? De /4n grupt de objetot sen dup/icatas? De uma maneira dn acessar um par de nome-ualor? O Capituk 7 os aborda com nais detalbes. Os arrays sio declarados informando-se o tipo de elementos que o alray seguido por colchetes em um dos lados do identificador.
Derlaranclo um
iri
Arral
de
Pinitiuot
int I J key; // Colchetes antes do nome (recomendado) int key I J ; / / colchetes depois do nome (v61ido, mas menos legivel)
Declarando am
Aray
de Refer1ncias
a Obietos
/ / Pccnmond:dn
declarar ama referincia a anq,\ uoci deue sempre co/ocar o: colchetet do aralt imediatamente depois do tipo du/arado, em ueqde depois do identfrcador (nome da uariduel). Dusaforma, qualqaer um qae leia o aidigo sabertlfaci/menh qaq por exenpl0, ke1 i uma referlncia a um objXo de arrEt int, e ndo um
pimitiuo int.
34 Copiiulo
Podemos tamb6m declarar arrays multidimensionais, que, na verdade, s6o arrays de arrays. Isso pode ser feito da seguinte maneira:
O primeiro exemplo
uocd
uoci podeni uer uma questdo ou duas que ineluam aidigo parecido com o seguinte:
que o tamanbo
fa1
dtferenga. e usar, e
No Capitulo 3, passaremos um bom tempo discutindo arrays, como os trnciahzar multidimensionais... Fique l-igado!
Variiveis Final
Declararumavari6velcom^palaw^-ch^vefinal
impossibilitaareutilizagiodessavari6veldepoisdeelatersido
iniciahzada com um valor explicito (repare que dizemos explicito, e nio padrio). Para primitivos, isso significa que, uma vez que avai|vel tecebeu um valor, esse valor n6o poder6 ser alterado. Por exemplo, se voc6 atribuit 70 d,vai|veI int x, entio x vai permanecer como 10 para sempre. Isso 6 bem simples para primitivos, mas o que significa terwmavai|vel de referdncia
inal- nSopode jamaisserrearibuidaparareferir-seaum objeto diferente. Os dados dentro do objeto podem ser modificados, mas a varidvel de referncia n6o pode set modificada. Em outras palavras, uma referdncia f inal- ainda lhe permite modificar o estado do objeto ao qual se refere, mas voc6 nio pode modificar avairdveldercfernciaparafaz-laserefeir a um obieto difetente. Decore isto: nio existem objetos f inal, apenas referdncias f inal. Explicaremos isso com mais detalhes no Capinrlo 3.
aobjeto f inal?Umavari6veldereferdnciamarcadacomo f
Agora jd estudamos como o modificador f inaL pode ser aplicado a classes, m6todos e vad6veis. A Figura 1-8 mostra as principais caracteristicas e diferengas das virias aplicag6es de final.
classe
classe final
Foo
a clasrc
f j-nal-
ndo
mdtodo
finrl
cfasse
rrnirl vvru
Baz
an/ Jv
\
o nrltodo
\ /
f inal
nio
Ba
rinaffid
variivel
so
a uariduelf
=
inal nio
pode receber um valor novo, depois de ter sido criado o m6todo inicial (a
,roi-ffi"rrgsize
auibuigio inicial de um
(
JAVA
35
Vari6veis Transient
marcar uma vari6vel de instdncia como transient, voc6 estar6 dizendo dJ\M para ignorar ess avaiilvelquando voce tentat seria\zar o objeto que a contem. A serializagio 6 um dos recursos mais legais deJava; ela lhe permite salvar (o que As vezes se chama de "flatten') um objeto escrevendo o seu estado (em outras palavras, o valor das suas vari6veis de instincias) em um tipo especial de stream de E/S. Com a serializagio vocd pode salvar um objeto em um arquivo, ou at6 enviilo affav6s de uma conexio para ser "re-inflado" (deseridtzado) do outro lado, em outraJ\M. A serializagio foi adicionada ao exame na vetsioJava 5, e falaremos dela com mais detalhes no Capitulo 6.
Se
importante que todo progtamadorJava a entenda. Mas, como ver6 no Capinrlo 9, voc6 provavelmente usar6 sincronizagio, em vez do modificador vol-at i l-e ,p^rz.torrr r seus dados i prova de threads. O
modift.cad.orvolaLile
static:
I I I I I I I I I I
M6todos
Vari6veis
Uma classe aninhada dentro de outra classe, mas n6o dentro de um m6todo (falaremos mais sobre isso no Capitulo 8).
Blocos de inicializagdo
at i c:
Construtores (nio faz senado;os constfutores somente s6o usados para criarinstAncias)
Classes (a
nio
Interfaces
Classes internas locais de m6todos (veremos isso no Capitrrlo 8)
vari6veis de instincias
Declarando Enums
A partit da versio 5.0,Java lhe permite restringir uma vari6vel para ter um de apenas uns poucos valores prd-definidos em outras palawas, um valor de uma lista enumerada. ( Os itens da lista enumerada sio chamados, sulpreendentemente, de enums.) O uso de enums pode ajudar a reduzir os bugs no seu c6digo. Por exemplo, na sua aplicagio de automagio de lanchonetes, voc6 poderia desejar reduzir os tamanhos de caf6s possiveis a BIG ("gande"), HUGE ("enorme') e OVERWHELMING ('absurdo'). Se voc6 deixar a possibilidade que um pedido de tamanho LARGE ("grande') seja feito, isso poderia causar um erro. Entram em agdo os enums. Com a simples declatagio a seguir, vocd poder6 garantir que o compilador o impedir6 de atribuir qualquer coisa a um Coffeesize que nio seja BTG, HUGE ou OVERWHELMING:
CoffeeSize { erc, HUGE, oVERwHELMING }; Dai em diante, a rinica maneira de se obter um Co f f e e s i z e ser6 com um a declaragdo parecida com esta: CoffeeSi-ze cs = CoffeeSize,BIG; Nio 6 obrigatdrio que as constantes enums estejam escritas totalmente em mairisculas, mas, tomando emprestado
enum convengio de c6digos da Sun que detetmina que
fazJo aqui.
as
da
de Acesso
Os componentes b6sicos de um enum sio as suas constantes (ou seja, BIG, HUGE e OVERWHELMING), emboravoc logo adtante que pode haver muito mais em um enum. Os enums podem ser declarados como as suas pr6prias classes separadas, ou como membros de classes, mas nlo podem ser declarados dentro de um m6todo!
v6 ver
enum
class Coffee
l
J
CoffeeSize size;
public class CoffeeTestl { public static void main(Stringtl args) { Coffee drink = new Coffee ( ) ; dri-nk. size = Cof feeSize.BIG; //
]
enum
fora da cl-asse
O c6digo acima pode fazer parte de um s6 arquivo. (Lembre-se, o arquivo deve set nomeado como CoffeeTestl.iava, porque esse 6 o nome da classe pfblica do arquivo.) A principal coisa a se lembrar 6 que o enum pode ser declarado somente
comomodificadorpublic ouodefault,assimcomoumaclassenio-interna.Eisumexemplodedeclaragiode
errum
dentro de uma classe:
c-Lass
oVERWHELMTNG }
CoffeeSize size;
I )
public class CoffeeTest2 { public static void main(Stringtl args) { Coffee2 drink = new Coffee2 O ; drink. size = Coffee2 . CoffeeSize . BIG;
)
nome
requerido
l
J
As principais coisas a se lembrar desses exemplos sio que: 1) enums podem ser declarados como as suas pr6prias classes, ou podem ser incluidos em outra classe; e 2) que a sintaxe para se acessar os membros de um enum depende de onde o
enum foideclarado.
O seguinte exemplo NAO
6
v6lido:
public class CoffeeTestl i public static void main(Stringtl argts) { enum coffeesize { erc, HUGE, oVERWHELMTNG }
I
)
Panfazer
colocagdo de
37
coffeesize { erc,
HUGE, OVERWHELMTNG
I;
/ .- o ponto-e-virgula
//
public statj.c void main(StringtJ args) Coffee drink = new Coffee O ; drink. si_ze = CoffeeSize.BIG;
) )
P"lT,o que 6criado quando voc6 cria um enum? O mais importante a se lembrar 6 que enums nlo sio Strings nem ints! CadaumdostiposenumeradosdeCoffeeSize 6naverdadeumainstinciadeCoffeeSize.Emou-tras palavras, BIG 6 do tipo Cof f eeSize. Pense em um enum como um tipo de classe, que 6 parecido (mas nio exatamente) com isto: ,// exemplo conceitual- de como voc6 / / pode entender os enums class CoffeeSize { public static final CoffeeSize public static flnal CoffeeSize public static final CoffeeSize
BTG =
0) ;
I)
I
{
public static void main(Stringtl args) System. out . println (CoffeeSize . BIG) ;
]
)
Repare como cada um dos valotes enumerados, BIG, HUGE e OVERWHELMING, 6 uma instAncia do tipo Cof f eeSize. EIes sio representados como static e f inal-, o que no mundo Tava corresponde a uma constante. Repare tamb6m que o valor de cada enum conhece o seu indice o.. poiigao... Em o.rtias palavras, a ordem na qual os
enumssdodeclaradosfazdiferengz.Vocpodepensarnosenums
do tipo Cof f eeSi ze, e, como ver6 em um capitulo postedor, voc6 pode iterar atrav6s dos valor de um enum invocando o mtodo val-ues ( ) em qualquer tipo de enum. Q.,Tio se preocupe com isso neste capitulo.)
deCoffeeSj-ze iomofazendopatedieumarray
Voc6poderia criar algtm tipo de tabela de busca, usando alguma outra estrutura de dados, mas isso seria um design ruim e dedificilmanutengio.Amaneiramaissimples 6ttataro.r."lo.e.dosseusenums (BIG,HUGE eOVERWHELMING) como obietos que podem ter as suas pr6prias vari6veis de instincias. Ent5o, voc poder6 atribuir esses valores no momento em que os enums forem inicializados, passando um valor ao construtor do enum. Isso precisa ser explicado com um pouco mais de detalhes, mas, primeiramente observe o seguinte 6fdigo:
enum
CoffeeSize
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;
)
/
/
uma
int
getounces
Oi
rrrn
nrrndac.
i
)
cJ_ass colIee
CoffeeSize size;
um
public static void main(StringIJ args) Coffee drinkl = new Coffee O ; drinkl . slze = CoffeeSize.BIG;
(
(
))
));
exibe exibe
16
]
Os principais pontos a se lembrar sobre os constflrtores de
enums sio:
6 possivel invocar um construtor de enum diretamente. Esse construtor 6 invocado automaticamente! com os argumentos que vocd define ap6s o valor da constante. Por exemplo, BIG ( I ) invoca o construtor Cof f eeSize literal 8 ao construtor. (I',los bastidores, 6 claro, voc6 pode imag1nar que BIG passando o que usa um tamb6m 6 passado ao construtor, mas nio precisamos saber - nem nos importarmos com - os detalhes.)
NUNCA
int,
int
Vocd pode definir mais de um argumento para o construtor, e pode sobrecarregat os construtores do enum, assim como pode sobrecarregar um construtor normal de classes. Discutiremos os construtores com muito mais detalhes no Capitulo 2.ParairuciaJtzar um Cof f eeType contendo ao mesmo tempo o nfmero de ongas e, digamos, um tipo de lid, voc6 passaria dois argumentos ao construtor, ta fotma BIG ( I , "A" ) , o que significa que voc6 tem um construtor em Cof f eeSize que usa tanto um int quanto uma string.
E, finalmente, voc6 pode definir algo realmente estranho em um enum, que se pafece com uma classe intema an6nima (sobre a qual falaremos no Capinrlo 8). E o chamado corpo de classe especifico da constate, e voce pdoe us6Jo quando precisar que determinada constante substitua um metodo definido no enum. Imagine este cen6rio: voc6 quer que os enums tenham dois m6todos - um para ongas e um para c6digo de registro (uma String). Agora imagine que a muorja dos tamanhos dos caf6s usa o mesmo c6digo, "8", mas o tamanho OVERWHELMING usa o tipo "A'. Voc6 pode definir um m6todo getlidcode ( ) no enum Cof f eesize que retorne "8", mas ..rr. ."ro rro.6 precisa de uma forma de substinriJo para OVERWHELMING. Voc6 nio quer colocar um c6digo if / then de dificil manutengio no m6todo getlidcode ( ) , entio a melhor saida poderia ser fazer com que a constante OVERWHELMING de alguma forma substitua o m6todo getlidCode O .
Isso parece esttanho, mas voc6 precisa entender as regras bisicas de declaragio:
JAVA
(-nffcaQ i za I
39
BIG(8),
HUGE (r_0) ,
OVERWHELMING
bloco de c6digo que defina / / o "corpo" para esta constante public String getlidcode O { // substitua o m6todo / / definido em Coffeesize
(
16
tt
// t,
ininie
rrm
return rrA";
)
private
j-nt
OUnCeS;
public int
)
get.Ounces
reEurn ounces;
public String
rafrrrh !rQrr.
get.LidCode
()
{ // este
/| / ^^1
m6t.odo
6 subsriruido
OVERWHELMING
/ pe!a consranre
Ap6s absorver o material d,este capitulo, voc dever6 estar familiarizado com algumas das nuances da linguagemJava. Voc6 poder6 talvez se sentir confuso sobre por que teve a id6ia de fazer este exame. Iiso 6 normal a esta altura. Caio esteia ouvindo a si mesmo dizendo "onde eu estava com a cabega?",basta se deitar e descansar at6 que isso passe. N6s gostariamos de poder dizer que fica mais f6cil, que este foi o capitulo mais dificil e que daqui em diante fica tudo menos
complicado... Vamos rever brevemente o que vocd precisar6 saber para o exame. Haverd muitas quest6es indiretamente relativas palawas-chave reais e quais ndo sio.
a
Embora as convengoes de nomeagio como o uso de camelCase nao caiam diretamente no exatne, ainda assim voc6 ter6 de entender os fundamentos da nomeagioJavaBeans, a qual usa camelCase.
Voc precisa entender as regras associadas com a criagio de identificadores v{-lidos, e as regras associadas com declarag6es de c6digo-fonte, incluindo o uso de declarag6es package e import.
Agora voc6 tem um bom entendimento do controle de acesso no que se refere a classes, m6todo e vari6veis. Voc6 j6 viu como os modificadores de acesso @ub1ic, protected e private) definem o controle de acesso de uma classe ou um membro.
Voc aprendeu que as classe,s abstract podem conter tanto m6todos abstract quanto nio-abstract., mas que se um s6 m6todo for marcado como abstract, entao a classe deve ser marcada como abstract. Nio se esquega de que uma subclasse concreta (nio-abstract) de uma classe abstract deve fornecerimplementagdes para t;dos os m6todos abstract da superclasse, mas que uma classe abstract nio precisa implerientar os m6todos abstract da sua superclasse . Uma subclasse abstract pode "passar a boli" paraapiimeira subclasse concreta.
Examinamos a implementagio de interfaces. Lembre-se de que as interfaces podem estender uma outra interface (ou mesmo multiplas interfaces), e que qualquer classe que implemente uma interface deve implementar todos os miodos de todas as interfaces da drvore de heranga da interface que a classe est6 implementando.
de Acesso
f inal-, abstract, synchronized e assim por Tamb6m vimos os outros modificadores, incluindo static, diante. Voc6 aprendeu como alguns modificadores nunca podem ser combinados em uma declangdo,pot exemplo, misfurar abstract com f inal- ou pri-vate.
Tenha em mente que nio existem obietos f inal ernJzva. Uma variivel de refer6ncia marcada como poder6 ser modificada, mas o objeto a que se refere pode ser modificado. Voc6 viu que
f inal- nunca
subclasse
nio
classe, a classe
final
nio poder6
ser subclassificada.
Lembre-se que, a partir d oJava 5,os m6todos podem ser declarados com um parimetro var- arg (que pode usar de zeto a muiros argumentos do tipo declarado), mas que voc s6 pode ter um var - arg por m6todo, e ele deve ser o ultimo parAmetro do m6todo. Certifique-se de estar famt\arizado com os tamanhos relativos dos primitivos num6ricos. Lembre-se de que, enquanto os valores de vad6veis nio- f i na l- podem ser modificados, o tipo de uma vari6vel de refer6ncia nio pode.
Voc aptendeu tamb6m que arrays s5o obietos que contdm muitas variiveis do mesmo tipo. Os arrays podem tamb6m
contef ouffos aftays. Lembre-se do que aprendeu sobre varidveis e m6todos static, especialmente que os membros static sio usados por-classe emvez de por-instincia. Nio se esquega de que um m6todo stat ic nio pode acessar diretamente uma vairivel de instincia apartu da classe onde reside, porque ele nio tem uma referdncia explicita a nenhuma instencia particular da classe. Finalmente, abordamos rrn recurso novo doJava 5, enums. Um enum 6 uma forma muito mais segura e fleivel de se implementar constantes do que era possivel em vers6es anteriores deJzva. Pelo fato de serem um tipo especial de classe, os enums podem ser declaiados de forma bastante simples, ou podem ser bem complexos - incluindo atributos tais como m6todos, varidveis, construtores e um tipo especial de classe interna chamada de corpo de classe especifico da constante. Antes de fazet o teste de treinamento, passe algum tempo com o otimistamente chamado "Exercicio Ripido". Volte a consultat esse teste freqrientemente, dL medida que for lendo este livro e especialmente quando estiver perto da prova e voc6 estiver tentando memorizar tanto quanto conseguir. Porque - e eis aqui o conselho que voc6 gostaia que sua mie tivesse lhe dito antes de voc6 ir p^tz^ faculdade - nio importa o que voc6 sabe, o que importa 6 quando voc6 sabe.
Para o exame, saber o que voc6 ndo pode fazer com a linguagemJava 6 tio importante quanto saber o que voc6 pode fazer-. Experimente as quest6;s de amostra! Elas sio bastante semelhantes i dificuldade e ) estrutura das quest6es do exame real, e deverio lhe abrir bs olhos para o quio dificil o exame pode ser. Nao se pre ocupe se errar vdrias delas. Se voc6 perceber que tem dificuldade em um t6pico especifico, passe mais iempo revisando-o e estudando-o. Muitos programadores precisam de duas ou tr6s leituras s6rias de um capitulo (ou um objetivo individual) antes de conseguirem respondet is quest6es com confianca.
Exercicio Ripido
Lembre-se de que quando falamos de classes neste capihio, estamos nos referindo a classes n6o-internas, ou classes de nivel mais alto. Dedicaremos todo o Capitulo 8 is classes internas.
ldentificadores (Objetivo | .3) E Os identificadores podem comegar com uma letra, um underscore, ou um caracter monet6rio. E Depois do primeiro car^cter,os identificadores podem incluir tamb6m digitos. E Os identificadores podem ter qudquer extensio. D Os mEtodosJavaBeans devem ser nomeados usando-se camelCase e, dependendo do prop6sito do m6todo, devem comegar com set ("define'), get ("obt6m'), i s("6'), add("adiciona") ou remove.
Regras de declaragSo (Objetivo
l.l)
priblica.
E E D E E O fl E
Um arquivo de c6digo-fonte
Se
o arquivo de c6digo-fonte tiver uma classe priblica, seu nome terA que coincidir com o dessa classe.
O arquivo s6 pode ter uma instrugio de pacote,porm,v6izs de importaqdo. A instrugeo de pacote (se houver) deve ficar na primeira linha (fora os comentarios) do arquivo de c6digo-fonte. A instruq6o de importaqio
Se nao
(se
e antes da
declaragio de classe.
JAVA
5 4I
Os arquivos que nio tiverem classes pfblicas nio apresentario restrig6es de nomeagio.
Modificadores de acesso a classe (Objetivo l.l) 0 ga ts modificadores de acesso: publ ic , protected e private. E H6 quatro niveis de acesso: public, protected, def ault e private. E As classes s6 podem ter acesso publ ic ou d.ef ault D A visibilidade das classes gira em torno de se o c6digo de uma classe pode: E Criar uma instdncia de outra classe E Estender (ou criar subclasses) outra classe E Acessar m6todos e vari6veis de outra classe
.
Modificadores de classe (n6o referentes a acesso) (Objetivo 1.2) E As classes tamb6m podem ser alteradas com f ina1, abstract ou strictfp. E Uma classe nio pode ser f inal- e abstract. E Uma classe f inal- n6o pode ter subclasses. E Uma classe abstract nio pode serinstanciada. E Uma classe com somente um m6todo abstract significa que a classe inteira deve ser abstract. E Uma classe abstract pode ter m6todos abstracts ou ndo. E Aprimeiraclasseconcretaaestenderumaclasseabstract ter6queimplementartodososm6todosabstracts.
E E
As interfaces podem ser implementadas por qualquer classe, de qualquer drvore de heranga.
A interface
abstract
caso
voc6.ligite ou nio o
na declaragd.o.
E Uma interface s6 pode ter m6todos abstracts, nenhum m6todo concreto 6 permitido. El Osm6todosdasinterfacessio,porpadrio,public eabstracts -adeclaragioexplicitadessesmodificadores6
opcional.
E Asinterfacespodemterconstantes,quesiosempreimplicitamentepublic, staticefinal. E Asdeclarag6esdaconstantedeinterfacecompublic,static efinal sioopcionaisemqualquercombinagio. E Uma classe de implementagio nio-abst.ract va)tdatefi.as propriedades a seguir: E Fornecer6 implementag6es concretas dos m6todos da interface. E Deve seguir todas as regras de sobrecarga v6lidas para os m6todos que implementa. E Ndo deve declarar nenhuma excegio nova do m6todo de implementagio. E Nio deve declarar nenhuma exceg6o que seja mais abrangente do que as declaradas no m6todo da interface. E Pode declarar exceg6es de tempo de execugio em qualquer implementagio de mdtodo da interface, independente do
que coostar na declarag6o da interface.
E Deve manter a assinatura (sio permitidos retornos covariantes) implementa (mas nio precisa declarar as exceg6es da interface).
E E E E
A classe
As interfaces podem estender uma ou mais interfaces. As interfaces nio podem estender uma classe ou implementar uma classe ou interface.
se as declaragSes de
de Acesso
Modificadores de acesso a membros (Obietivos 1.3 e 1.4) E Os m6todos e as vari6veis de inst6ncia (nio locais) sdo conhecidos como "membros". fl Os membros podem usar todos os quatro niveis de acesso: public, protected, def aul-t, private. E O acesso aos membros se d6 de duas formas: D O c6digo de uma classe pode acessar um membto de outra classe f,l Uma subclasse pode herdar um membro de sua superclasse. E Se uma classe ndo puder ser acessada, seus membros tambm ndo poderio. E A visibilidade da classe deve ser determinada antes da dos membros. D Os membros pub 1 i c podem ser acessados por todas as outras classes, mesmo de pacotes diferentes. D Se um membro da superclasse for publ i c, a subclasse o herdat6 - independente do pacote. fl Os membros acessados sem o operador ponto (.) t6m que pertencer i mesma classe. D tnis sempre referenciarS.o objeto que estiver sendo executado no momento. fl tnis.aMethod( ) 6omesmoquesimplesmentechamaraMethod( ). E Os membros private s6 podem ser acessados por um c6digo da mesma classe. D Os membros private n6o ficam visiveis p^r^ as subclasses, portanto, nZo podem ser herdados. E Os membros def ault e protect s6 diferem quando subclasses estio envolvidas. B Os membros def ault s6 podem ser acessados por outras classes do mesmo pacote. E Os membros protect podem ser acessados por outras classes do mesrno pacote, al6m de pot subclasses,
independente do pacote.
E protect = pacote + kids (kids significando subclasses). E Por subclasses externas ao pacote, o membro protect s6 pode ser acessado affavEs da heranga: uma subclasse externa ao pacote nio pode acessar um membro protect usando a refer6noa a uma instAncia da superclasse (em outras palavras,ahetangzb o rinico mecanismo para uma subclasse externa ao pacote acessaf urn membro protect
de sua superclasse).
Um membro
protect
herdado por uma subclasse de outo pacote nio pode ser acessado por nenhuma outra pr6prias subclasses dessa.
Vari6veis locais (Objetivo 1.3) D As declarag6es de varidveis locais (de m6todo, autom6ticas, de pilha) nio podem ter modificadores E f inal 6 o,inico modificador disponivelpzrzvzi|veis locais. E As vari6veis locais nio recebem r-alores padriq portanto, devem ser inicializadas antes do uso.
de acesso.
Outros modificadores - membros (Objetivo 1.3) E Os m6todos f inal nio podem ser sobrecarregados em uma subclasse. E Os m6todos absgract foram declarados, com runa assinarura, um tipo de retorno e uma cl6usula throws
mas
opcional,
E E
Os m6todos abs
E E E
E Aprimeiraclassenio-abstrata(concreta)aestenderumaclasseabstract deveimplementartodososmdtodosabstract dessa. D O modificador synchroni zed s6 6 aplicado a m6todos e a blocos de c6digo. O Osmdtodos synchronized podemterqualquercontroledeacessoetamb6mseremmarcadoscomo f inal. E Os mdtodos abstract devem ser implementados por rxna subclasse, porantq tem de ser herdados. Por essarzzdo: E Os m6todos absuract ndo podem ser private. E Os m6todos absLract nio oodem ser f inal.
JAVA
43
E D
O modificador
nat ive
Omodificadot
strictfp
M6todos com Argumentos Vari6veis (var-args) (Objetivo 1.4) E A partir de Java 5,os m6todos podem declarar um p ardmetro que aceita de zero avdriosargumentos,
m6todo var-arg.
o chamado
O E E
Um parimetrov^r-zrgedeclarado com
doStuff (int...
x) {
Um m6todo var-arg s6 pode ter um parim etro var'zlrg. Em m6todos com parimetos normais
e um var-arg, o var-arg deve
Declarag5es de Vari6veis (Objetivo 1.3) fl As vari6veis de instincia podem: E Ter qualquet tipo de contole de acesso E Seremmarcadas como finaL ou transl-ent D Asvari6veisdeinstAncianiopodemserdeclaradascomabstract, sychronized, nativeoustrictfp. D E valido declatar uma v ari|vellocalcom o mesmo nome de uma vari6vel de instincia; isso 6 chamado de
"sombreamento".
As variiveis
f inal
E E
Nao podem ser reinicializadas, uma vez que tiverem um valor atribujdo.
As vari6veis de refer6ncia
inal-
elas,
E Asvaridveisderefer6nciafinal devemseriniciahzadasantesqueaexecugiodoconstrutorsejaconcluida. E N6o existem obietos f inal-. Uma referncia a obf eto marcadacomo f inal- n5o significa que o obieto propriamente
dito seja inaltet6vel.
E o modificadot t rans ient s6 pode set aplic ado a vaifiveis de instdncia. D o modificador vol at i 1e s6 pode ser aplicado avzi|veisde instdncia.
Declarag6es de Arrays (Objetivo 1.3) D Os arrays podem arm^zerrat tipos primitivos ou objetos, mas o attay propriamente dito 6 sempre um objeto. O Quando voc declara um array, os colchetes podem ficar i esquerda ou i direita do nome davzridvel. fl Nunca 6 vdlido inclut o tamanho do anay na declaragdo. D Um zrfay de obietos pode armazenar qualquer objeto que passe no teste E-UM (ou instanceof) para o tipo declarado
attay.Por exemplo,
se
Horse estender Admal,entd,o um objeto Horse pode ser colocado em um arav di Animal.
do
Vari6veis e m6todos static (Objetivo 1.4) D Nio sio associados a nenhuma instincia especifica da classe. E Nio6necessiriaaexistdnciadainstinciadeumaclassepataqueosmembrosstatic destasejamusados. D 56 haveri um a c6pia da vaidvel ou classe s tat i c e todas as instdncias a compartilhario. E Os m6todos static nio tdm acesso direto a membros nio-static
Enums (Objetivo 1.3)
E Um enum especifica uma lista de valores constantes que podem ser atribuidos a um determinado bpo. D Um ertum ndo 6 uma String nem um int; o tipo constante de um enum 6 o tipo do pr6prio enum . por exemplo,
INVERNq PRIMAVER
T,
Q Um enum pode ser declarado fora ou dentro de uma classe, rnas ndoem um m6todo. E Umenum declarzdoforadeuma classeadopodesermarcadocomstatic, f inal , absLract, protected ou private.
de Acesso
E E E E
Os
As constantes enum podem enviar argumentos para o construtor enum, usando a sintaxe BIG(8), onde o l-iteral 8 6 passado ao construtor enum.
Os construtores Os construtores
int
irttcidtzado.
"
r':f
deum enum
Teste Individual
As seguintes quest6es o ajudardo a ava\ar sua compreensio do material apresentado neste capinrlo. Leia todas as opg6es cuidadosamente, porque poder6 haver mais de uma respostacorreta. Selecione todas as resPostas corretas para cada quest6o.
Mantenha o foco.
Caso tenha dificuldades com as perguntas no inicio, nio se desespere. Pense positivo. Repita boas afirmag6es para si mesmo do tipo "Eu sou inteligente o suficiente para entender enum" e "Tudo bem, aquele canaitentende mais de enum do que eu, mas aposto que ele nio consegue <insira algo em que voc6 defato seia bom) como eu."
4.
A. interface Base2 i-mplements Base { } B. abstract cl-ass Class2 extends ease { public boolean m1 O { return true,' } } C. abstract cl-ass Cfass2 implements ease { } D. abstract class Class2 j-mplements Base { public boolean mlO { return (true) ; } } E. cl-ass Class2 implements Base { boolean mlO {return false; } byte m2(short s) i return 42; ) ) 2. Qual das seguintes opg6es declara uma classe abstract compil6vel? (Marque todas as orretas.) A. public abstract cl-ass Canine { public Bark speakO; } B. public abstract cl-ass Canine { public eark speak O t i } C. public class Canine { public abstract Bark speak ( ) ; } D. public class Canine abstract { public abstract Bark speak O ; }
esti correta? (Marque todas as corretas.) A. "X estende Y" 6 Correto Se, e Somente se, X for uma classe e Y for uma interface. B. ..X estende Y" 6 correto se, e somente se, X for uma interface e Y for uma
3. Qual das seguintes afirmativas
^t ^a^^
5 45 C. "X estende Y" 6. correto se x e Y forem ambos classes ou ambos interfaces. D. "X estende Y" 6. correto para todas as combinaq6es d.e X e y sendo cl-asses e/ ou interfaces.
JAVA
4. Quais das seguintes sio declarag6es v6lidas? (Marque todas as corretas.) A. int gx; B. int 123;
5. Quais nomes de m6todos obedecem ao padreo favaBeans? (Marque todas as corretas) A. addSize B. getcust C. deleteRep D. isColorado E. putDimensions 6. Dado o c6digo: l-. cl-ass voop {
2. 3. 4,
Fl
public static
voi_d
main(String tJ args)
5.
/ insira c6digo
aqui
Qual destas opg6es, inseridas independentemente na l-inha 6, ir6 compilar? (N{arque todas as correras.)
doStuff(int... doArgs) { } doStuff (int [ ] doArgs) { } doStuff(inr doArgs...) { } doStuff(int... doArgs, int y) t i doStuff(int x, int... doArgs) { }
7. Quais das seguintes opg6es sao declarag6es v6lidas? (Marque todas as corretas.) A. short x [ ];
46 Copitulo
3. 4-
6. class TestEnum { 7. static Animals a; public static void main(StringtJ args) { 8. 9. System.out.println(a.DoG.sound + r\ * + a.FISH.sound) ;
r-0.
11.
)
Qual 6 o resultado?
naltnha 4
F.
um erro na linha 9
9. Dado o c6digo:
7. j
Quais das aEtrmaivas sio verdadeiras? (I\{arque todas as corretas.)
A. B.
C.
O c6digo compila.
Se apenas a Se apenas
ahnha3 for removida, o c6digo compila. linha 5 for removida, o c6digo compila.
D.
Se apenas a
E. F.
Se as Se as
linhas 1 e 3 forem removidas, o c6digo compi,la. linhas 1,3 e 5 forem removidas, o c6digo compila.
C e D estio coffetas. C esti correta porque uma classe abstract nio precisa implementar nenhum dos m6todos D esti correta porque o m6todo est6 implementado coretamente.
A est6 incoreta porque as interfaces nio implementam nada. B est6 incorreta porque as classes nio estendem interfaces. E est6 incorreta porque os m6todos de interfaces sio implicitamente publ ic, entao os m6todos sendo implementados precisam ser publ i c (Objetivo 1.1)
2. B est6 correta. As classes abstract nio precisam ter nenhum m6todo abstract. A est6 incorreta porque os m6todos abstract devem ser marcados como tais. C est6 incoreta porque n5o 6 possivel ter um m6todo abstract sem que a classe seja abstract. D est6 incorreta Porque apalzvra-chave abst.ract deve vir antes do nome da classe. (Obietivo 1.1)
JAVA
47
3. A 4.
C estd correta.
est6
incorreta porque
as classes
implementam interfaces, mas nio as estendem. B est6 incorreta porque est6 incorreta com base nas regras anteriores. (Objetivo 1.2)
as
interfaces
A, C
eG
B est6 incorreta porque um identificador nio pode comegar com um digito. D, E identificadores devem comegar com $ ou uma letra. (Obietivo 1.3) 5. 6.
B
e
D usam
os prefixos v6lidos
A, C e E estao incoffetas
de prefixosJavaBeans padr6es.
(Obietivo 1.4)
7. A
um array tridimensional.
ser que voc
C, D e F estao incoffetas, ndo 6 possivel incluir o tamanho do seu array em uma declaragdo a n7'o instancieoobjeto anay.E usaumasintaxedeinstanciamentoinv6lida. (Objetivo 1.3)
tambdm
8. 9.
vari6veis.
F estio incorretas; todas essas linhas usam sintaxe correta. (Objetivo 1.3)
5 6 a rinica que
os
ser locais a
um m6todo.
de Acesso
OrientaEio a objetos
Usoro Polimorfismo
Relocionor Modificodores e HeronEo Usor Conslrutores de Superclosses e Conlrutores Sobreco rregodos
individuol
50 Copitulo 2: Orientogdo
o objetos
Ser um SCJP I .5 signi{ico que voc6 tem de estor completomenie imerso nos ospectos orientodos o obieios de Jovo. Voc6 preciso sonhor com hierorquios de heronEo, o poder do polimo#ismo lem de fluir otrov6s dos suos veios, o coesoo e o ocoplomento
froco precisom se tornor t6o noturois poro voc6 quonto ondor, e o composiE6o preciso se lornor o seu feiioo com orroz. Esle copftulo ird prepord-lo poro todos os obietivos e quest6es relocionodos d orientoE6o o obletos que voc6 enconlrord no exome. Conhecemos muitos progromodores Jovo experientes que, no verdode, n6o s6o muito {luentes no utilizoq6o dos {erromentos de orientoE6o o obietos fornecidos por Jovo, portonto, comeeoremos pelo inicio.
\.roleTtvo poro
nl
. r.
..1. o centttcocoo
Suponhamos que voc6 escrevesse o c6digo de uma classe e virios programadores de sua empresa escrevessem programas que a usassem. Agora imaginemos que nio tivesse gostado da maneira como a classe se comportou, porque algumas de suas variiveis de instAncia estavam sendo configuradas (por outros programadores em seus c6digos) com valores que voc6 nlo previu. O c6digo deles resultou em erros no seu c6digo (relaxe, isso 6 apenas uma hip6tese...). Bem, trata-se de um programaJava, portanto, voc6 deve simplesmente langar uma versSo mais recente da classe, que eles poderio substituir em seus programas sem alterar nada no c6digo que criaram. promessas/beneficios da OO: flexibilidade e f6cil manutengXo. Mas os beneficios nlo surgem automaticamente. VocA tem quefaryralgo.Precisa escrever suas classes e c6digos de man eka que di sapore i flexibilidade e f6cil manutengio. Portanto, e reJava der suporte a OO? Ela nlo projetar6 szu c6digo para voc6. Por exemplo, imagine se voc6 criasse sua classe com variiveis de instAncia publ ic e os programadores citados acima as configurassem diretamente, como o c6digo aseguirdemonstra:
Esse cenario ressalta duas das
mas
ruim!!
Agora voc6 esti encrencado. Como modificar6 a classe de uma maneira que permita resolver os problemas que surgirem quando algu6m alterar a vari6vel s i z e para um valor inadequado? Sua rinica opgio 6 voltar ao script, escrever o c6digo de
umm6tododeajusteparasize
outros!
(umm6todosetsize(int
a),porexemplo)e,emseguida,protegeressavari6vel
essa alt eragdo
com, digamos, um modificador de acesso private. Por6m, logo que voc6 fizer
em
seu
c6digo, innnonper,l
o dos
A capacidade de fazrr alterag6es no c6digo de implementagio seminterromper o c6digo das outras pessoas que o estiverem 6 um beneficio essencid do encapsulamento. Voclpode ocultardetalltes da inplenmtapdoportnis de uma interface dc prugranEioprtblic. Por interface, querernos dizer o conjunto de m6todos que seu c6digo tornar6 disponivel para outros c6digos chamarem - em outras palavras, a API de sea cridigo. Com a ocultagio dos detalhes da implementaglo, vocA poder6 trabalhar novamente o c6digo de seu m6todo (podendo tamb6m alterar a maneira como as vari6veis serXo usadas por sua classe) sem forgar uma alteragio nos c6digos que chamarem o m6todo modificado.
usando,
Se
voc6 quiser obter f6cil manutengio, flexibilidade e extensibilidade (e 6 claro que voc6 quer), seu projeto deve Mantenha suas variiveis de instAncia protegidas (com um modificador de acesso, geralmente
I I I
privat.e).
Crie m6todos de acesso public, e exija que o c6digo chamador use diretamente a vari|vel de instAncia.
Para os m6todos, use a conveng1o de nomeagioJavaBeans de
esses
seLcsomeProperty>
get<someProperty>.
JAVA
5 5I
A Figura
2-1 ilustra o conceito do encapsulamento, forgando os chamadores do c6digo poderem acessar as variiveis diretamente.
capturadores e confgaradores.
as
modifcadorcs. (Pessoalmente,
ji
embora algumas pessoas prefiram os termos mais modfiear.) Independente da maneira como terio que usar para icessar suas varilveis de instincia. Slo de
B b = new BO;
Qretsize
()
setSize
()
St.rinq s = b.getName0;
b.setName( "Fred')
;
getName setName
()
()
Color c = b.getcolorO;
b. set.Color (b1ue)
;
getcolor
set.Color
() ()
Classe A nio 6 capaz de acessar os dados de vari6veis de instAncias da Classe B sem ser atrav6s de m6todos
Figuro
2-l A noturezo do
encopsulqmenfo
public class Box { // protege a variS.vel de inst.Ancia; somente uma instAncia / / a parEir de Box pode acessar .' d private int size; // Fornece capturadores e configuradores priblicos public int getsizeO { recurn st-ze;
]
i
Espereumminuto...quantodoc6digoanterior6ritil?Elenemmesmoexecutaalgumavalidagioouprocessamento!
beneficio pode haver em ter m6todos capturadores e configuradores que neo adicionem uma funcionalidade extra? A questeo 6 a seguinte, uocd pode mudar de idiia depoit e adicionar mais alguma codificagio a seus m6todos sem interromper a API. Mesmo se achar que nao precisari realmente de validagio ou processamento dos dados, um bom projeto de OO Preconiza o planejamento para o futuro. A fim de ficar seguro, exija um cddigo chamador que acere
nus mdtodos em ueqde pennitir o acesso direto
Que
is
uaridueis de insthnria.
as
oBSERVAQ6ES
pene O EXAME
Cuidado con cridigos que parepm abordar o cumpnftamentl de um mtitodo, ponim, com o pmblena real sendo afalta de encapsulamento. Examine o exerQ/o a seguiry e uela se clltsegtle detcobir o qae eshi acontecendo:
class Foo
n,rl-r"l in
{ ihf r6ft 9.
public int right = 3; public void setleft(int left = leftNum; right = leftNum/3;
)
IeftNum) i
Agora considere essaperganta: O ua/or da direita serd umpre ilm terp do ua/or da esquerda? Sua reposta senl sim, ati que perceba que os usudiot da classe Foo ndo precisam usar o mitodo setl,ef t ( ) ! Eles poden simplesnente ir direto ds uaridaeis de instincia e alteri/as com
qualqur ualor
int
aleahirio.
A heranga esti por toda pane emJava. E seguro dizer que 6 quase (quase?) impossivel escrever at6 mesmo pequenos programas em java sem usar a heranga. Para explorar esse t6pico, iremos usar o operador instanceof , o qual discutiremos com muito mais detalhes no Capitulo 4. Por agora, basta lembrar de que instanceof retorna tnre vari6vel de referAncia testada for do tipo ao qual est6 sendo comparada. Este c6digo:
se a
class Test { public static void main (String [ ] args) { TesL t1 = new Test ( ); Test t2 = new Test ( ); if ( !tl.equals (t2) ) System.out.println ( "they' re not equal" ) ; if (t1 instanceof Object) System.out.println ( "t1's an Object" ) ;
) )
i f tem
sucesso.
JAVA
53
ptt um minuto... como t1 pode ser uma instAncia do tipo Object, se acabamos de dizer que ela era do tipo Test? Tenho cerreza de que voc6 esti muito na nossa frente aqui, mas o que ocorre 6 que toda classe em Java 6 uma subclasse de Object, (exceto, 6 claro, a pr6pria classe Object). Em outras palavras, toda classe que voc venha a usar ou a escrever iri herdar da classe Object. Voc6 sempre ter6 um m6todo equals, um m6todo clone, notify, wait e outros, disponiveis para usar. Sempre que criar uma classe, voc6 automaticamente herdari
E
todos os m6todos da classe Obiect.
Por qu6? Examinemos esse m6todo equals, por exemplo. Os criadores de Java presumiram corretamente que seria bastante comum os programadores Java quererem comparar instAncias das iuas classes para verificar se sio iguais. Se a classe Object nio tivesse um m6todo equals, voc6 teria de escrever o seu pr6prio; voc6 e todos os outros pr,ogramadoresJava. Esse m6todo equals ji foi herdado bilh6es de vezes. (Para ser exaro, equals foi sobrescrito bilh6es de vezes, mas falaremos mais sobre isso no devido tempo)
Para o exame, voc6 ter6 de saber que pode criar relag6es de heranga em Java utendendo uma classe. Tamb6m 6 imponante entender que as duas raz6es mais comuns para se usar a heranga sio:
I r
Vamos comegar com a reutilizagio.Uma abordagem de projetos comum 6 criar uma verslo um ranto gen6rica de uma classe, com a intengio de criar subclasses mais especializadas que herdem dela. Por exemplo:
shape,, ) ;
class PlayerPiece extends cameshape { public void movepiece ( ) i System. out.println ('.moving game piece,, / / ma:-s c6digo
)
,.
);
]
)
displaying
shape
moving game
piece
-p.layllspiece herda o m6todo display ( ) gen6rico da classe menos especializada GameShape, e tamb6m adiciona o seu-pr6prio_m6todo, movePiece ( ) . A reutilizagio de c6digo atrav6s da heranga.significa que.os m6todos com funcionalidade gen6rica (como display ( ) - que podeiia- se aplicar a ) uma s6rie de tipos diferentes de formas em um jogg nio precisam ser reimplementadoi. Isio significa que todas _ as subclasses.especializadas.de GameShape garantidamenie terlo as capaciiades da superclass."*"ir gen6rica. Voc6.n6o vai querer que seja.necessirio reescrever o c6digo display (j em cada .rtn dor seus componenres especializados de um jogo online, por exemplo.
Repare que a classe Mas disso voce ji sabia. Voc ji passou pela dor de enconrrar c6digo duplicado ao f.azer uma modificaqeo em um lugar e ter de rastrear todos os outros pontos em que exista o mesmo c6digo (ou um muito semelhante).
54 Copitulo 2: OrienfoE6o
o obietos
O segundo (e relacionado) uso da heranga 6 para permitir que as suas classes sejam acessadas polimorficamente uma capacidade fornecida tamb6m pelas interfaces, mas falaremos disso em um instante. Digamos que voc6 tenha uma classe Gamelauncher que queira fazer tm loop atrav6s de diferentes tipos de objetos GameShape, e chamar display ( ) em cada um deles. No momento em que est6 escrevendo essa classe, voc6 nio conhece todos os tipos possiveis de subclasses de GameShape que ainda serlo escritos por outros programadores. E voc6 com certeza nio quer ter de ref.azer seu c6digo apenas porque algu6m decidiu criar uma forma chamada Dice seis
meses depois.
6 que voc6 pode tratar qualquer subclase de GameShape como se fosse uma GameShape. Em outras palavras, voc6 pode escrever c6digo na sua classe Gamelauncher que diga, "nio me importa que tipo de objeto voc6"6, desde que herde de.(estenda) GameShape. E, no que me diz respeito, se voc6 estender GameShape entio voc6 com toda certeza ter6 um m6todo display ( ) , entio eu sei
Imagine que n6s tenhamos agora duas subclasses especializadas que estendam as classes mais gen6ricas
GameShape,
PlayerPiece e TilePiece:
{
cl-ass GameShape
shape" ) ;
/ / mai s cridiag
vvv4Y
1
J
class PlayerPiece extends GameShape { public void movePieceO ( System.out.println ( "moving game piece"
)
GameShape {
1\ I
L
//
\
nais
c6dioo
Agora imagine que uma classe de teste tenha um m6todo com um tipo de argumentodeclarado GameShape; isso rifrtifi." qn'..Ia pode usar qualquer tipo de GameShape. Em outras palavras, qualquer subclasse de GameShape pode sei p"s"dr a trnm6todo co- ltrn atg,rmento do tipo GameShape. Este c6digo
public class TestShapes { public static void main (String[] args) { PlayerPiece player = new PlayerPieceO; TilePiece tile = new tilePiece ( ) ;
doghapes doshaDes
)
(player) ;
(tile) t
do9hapes(GanshaDe shape)
(
shape . displayShape
i
Gera a saida:
displaying displaying
shape shape
JAVA
55
O ponto principal 6 que o m6todo doShapes ( ) 6 declarado com um argumento GameShape, mas pode receber qualquer subtipo (neste exemplo, uma subclasse) de GameShape. O m6todo pode entio chamar qualquer m6todo de GameShape, sem nenhuma preocupagXo sobre o real tipo de classe de tempo de execugXo do objeto passado ao m6todo. Existem implicag6es, no entanro. O m6todo doShapes ( ) sabe apenas que os objetos sio um tipo de GameShape, uma vez que o parimetro foi declarado assim. E usar uma variivel de referAncia declarada como do tipo GameShape independentemsffs r{f se a vari6vel 6 um parAmetro de m6todo, uma variivel local ou uma variivel de instAncia - significa qu-e apenas os m6todos de GameShape podem ser chamados para ela. Os m6todos que voc6 chama p^t^i^ refer6ncia sio totalmente dependentes do tipo dularado da variivel para a qual a refer6ncia aponta, nio importando o que seja o objeto. Isso significa que voc6 nio pode usar uma vari6vel GameShape para chamar, digamos, o m6todo getAdjacent ( ), nem mesmo se o objeto passado for do tipo TilePiece. (Veremos isio novamente quando falarmos sobre as interfaces.)
nlo
E-um
Na OO, o conceito E-UU 6 baseado na heranga de classes ou implementagio de inrerfaces. O termo E-UM 6r.rma maneira de dizer, "esse item d un tipo desse outro'.?or exemplo, um Mustang 6 um tipo de cavalo, portanto, na terminologia da OO poderiamos dlzer, "Musta"g f-UIvt Cavalo". Subaru E-UU Carro. Broccoli f-'l-IM Vegetal (!io muito atraente, mas mesmo assim conta). O relacionamento E-UM 6 expresso emJava por meio das piavraschave extends (para heranga de classes) e implements (para implementagio de interface$:
public class
/
/ Coisas importantes de Subaru aq"ui / / Nd,o se esqueqa que Subaru herda membros acessjveis / / o qte pode incluir tanto m6todos quanto vari6vers
] Ocarro(Car)6umtipodeveiculoffehiclQ,pofianto,aArvoredeveterinicio
de Car,
apartirdaclasseVehiclecomoveremosabaixo:
public class Vehicle { ... } public class Car extends Vehicle { ... } public cl-ass Subaru extends Car { ... }
Na terminologia da OO, vod pode dizer o seguinte:
Vehicle Car
6 a zuperclasse de
Car.
6 a subclasse de
Vehicle.
Subaru.
Car
6 a superclasse de
derivado de Car.
as declaraE6es a seguir
sio verdadeiras:
56 Copitulo 2: Orientogdo
o obietos
"Subaru E-UU Veiculo" porque a classe seri considerada "um tipo do" item que estiver acima dela em sua irvore de heranga. Se a expressio (Foo instanceof ear) 6 true, enteo a classe Foo E-UM Bar, mesmo se Foo nio estender diretamenie Bar, mas, emvez disso, estender alguma outra classe que seja uma subclasse de gar. A Figura 2-2 ilustra a 6wore de heranga de Vehicle, Car e Subaru. A seta se rnove da subclasse para a superclasse. Em outras palavras, a seta de urna classe aponta em direglo a classe de onde foi estendida.
Figuro
2-2
TEM-UM
Os relacionamentos TEM-UM sXo baseados na utilizagio , em vez de na heranga. Em outras palavras, classe A TEM-UM B ocorreri se o aldrgo da classe A apresentar una referdncia a uma in$dncia da classe B. Por exemplo, voc6 pode dizer o seguinte,
Animal-
No c6digo anterior,
Horse tem uma variivel de instAncia do tipo Halter, Poftanto' voc6_pode dizer que "Horse ffU-UVt Halter". Em outras palavras, Horse aprercnta uma refeftncia a Halter. O c6digo de Horse.pode usar a refer6ncia a Halter para chamar m6todlos dessa classe e .tsat seu comportamento sem ter um c6di_go (-og{..9 relacionado a ela ni pr6pria classe Horse. A Figura 2-3 ilustra o relacionamento TEM-IIM entre Horse e Halter.
a classe
Os relacionamenros TEM-UM permitirio que vocA projete classes que sigam as boas Priticas da OO sem que sejam necess6rias classes monoliticas que eiecutem milhares de coisas diferentes. As classes (e, Portanto, os objetos instanciados a paftir delas) devem ser especialistas. Como diz o nosso amigo.Andrew, 'as classes especializadas r a redvzir bugs". Qiuanto mais especializada. a classe, mais prov6vel que possa ser reutilizada de fato podem "jnd, .* o.rt.o, aplicativos. Se voc6 inserir todos o. c6digoJrelacionados a Halter diretamente na classe Horse, terminar6 diplicando o c6digo na classe Cow, Unplid.Intern e em qualquer outra classe que Possa precisar do comportamento de Ftal ter. Mantendo o c6digo de Hal ter em uma classe especializada e separada, voc6 teri a chance de reutilizila em v6rios aplicativos.
Horce
Halter
tt"(""p" r)
classe Horse tem um Halter, porque Horse declara uma variivel de instincia do tipo Halter. Quando o c6digo chama tie( ) em uma instincia de Horse, o Horse em quest5o chama tie( ) na varidvel de inst6ncia
Figuro
JAVA
57
Os usu6rios da classe Horse (isto 6, um c6digo que chamar m6todos em uma instAncia de Horse), achardo que essa classe tem o comportamento de Halter. A classe Horse pode ter um m6todo tie (LeadRope rope) , por exemplo. Esses usu6rios nunca saberio que quando chamarem o m6todo tie ( ) , o objeto Horse delegari essa tarefa para sua classe Halter chamando myHalter . tie ( rope ) . O cen6rio que acabou de ser descrito ter6 um formato semelhante ao seguinte:
public class Horse extends animal { private Halter myHalter; public void tie(LeadRope rope) { myHalter.tie(rope) ; / / DeIega o comport.amento de tie para
// n nhiafn l{alfar
public class Halter { public void tie(LeadRope aRope) { / / Faz o trabalho propriamente dito de tie aqui
l
Na OO, nio queremos que os chamadores se preocupem com que classe ou objeto ser6 o que realmente executari a taref.a. Para que se d6 dessa forma, a classe Horse ocultar6 de seus usu6rios detalhes da implementaQio. Os usu6rios de Horse solicitario a esse objeto que execute tarefas (nesse caso, a si mesmo) . ^marrar ".lasse Horse o far| ou, como nesse exemplo, solicitarA a outrem parafaz6-lo. No entanto, para o chamador sempre pareceri qli;e 0 pniprio objeto Horse feqtado. Os usu6rios de Horse nio precisario nem mesmo saber que ha algo
chamado classe
Halter.
Na sala de aula
sio apenas a ponta do iceberg quando se rrara de projeto orientado a objetos.. Muito.s livros e.teses de graduaEio t6m sido dedicados a esse t6pico. A, razilo pari a Anfase no projeto apropnado 6 simples: dinheiro. O custo de distribuigio de um aplicativo tem sido estimado como 10 vezis mais caro para programas mal projetados. Tendo visto os resultados de projetos fracos, posso assegurar que essa esrrmauva nio 6 irreal. At6 os melhores projetistas que usam o modelo orientado
a
relacionamentos entre centenas, ou at6 milhares, de classes. Quando os erros sio descobertos durante a fase de implementagXo_(criagio do c6digo) de um projeto, a quantidade de c6digo a ser reescrita is vezes pode fazer com que as equipes de programagio tenham que comegar tudo novamente.
A indristria de software tem evoluido para auxiliar o projetista. As linguagens visuais de modelagem de objetos, como a Unified Modeling Language (UML), permitem que os projetistas criem e alterem facilrnente classes sem
ter que escrever o c6digo primeiro, porque os componentes orientados a objetos sio representados graficamente. Isso permite que o projetista crie um mapa com os relacionamentos de classe ajudando-b a reconhecer erros antes que a codificaglo comece. Outra inovagio recente no projeto orientado a objetos est6 relacionada aos padr6es de projeto. Os projetistas perceberam que muitos projetoi orientados a objetos sio aplicados de maneiraionsisrente de um projeto para outro, e que seria ritil aplicar os mesmos projetos porque isso reduziria a possibilidade de introdugio de novos erros. Assim, os projetistas usu6rios do modelo orieniado a objetos comig"ram a companilhar esses projetos entre si. Atualmente, hi muitos catilogos desses padr6es de projetos tanto na Internet quanto em livros.
Embora para passar no_exame de certificaglo em Java voc6 nio precise compreender o projeto orientado a objetos com esse nivel de detalhes, essas informag6es auxiliares o ajudario a entender melhor porqn. os criadores do teste optaram por incluir o encapsulamento e os relacionamentos d um e tem a?n no exame.
58
nnpikgdo
e quando sdo de
polimorfsno. Alin disso, deterrtinar quando a conuersdo senl necerdria tenpo de exuugdo n0 que re refere conuersdo de referdncias de objxo:.
kmbre-se de que qualquer objetoJava que possa passar em mais de um teste E-UM pode Fora os objetos do tipo Object, todotos objetosJava sio polim6rficos, no sentido de que em relaSo ao seu proprio tipo e em relagio ) classe Object.
Lembrese de que a rinica maneira de acessar um objeto imponantes a memorizar sobre as refer6ncias:
6 atrav6s de
ser
eles passam
I r r r I
Uma vari6vel de refer6ncia s6 pode ser de um tipo objeto que referencie posa se modificar).
e,
uma vez declarado, esse tipo nunca pode ser modificado (embora o
Uma referOncia 6 uma variivel, de forma que pode ser reatribuida para outros objetos declaradacomo f inal).
referenciando.
(a
nio
O tipo de uma variivel de refer6ncia determina os m6todos que podem ser chamados no objeto o qual Uma vari6vel de refer6ncia pode apontar para qualquer objeto do mesmo tipo que muito importante - pode se referir a qualquer subtipo do tipo declarado!
a
vari6vel est6
Uma variivel de referAncia pode ser declara& como um tipo de classe ou um tipo de interface. Se a vari6vel for declarada como um tipo de interface,ila pode referenciar qualquer objeto de qualqu er classe que impbmente a interface.
Anteriormente, n6s criamos uma classe GameShape que foi estendida por duas outras classes, PlayerPiece e Tilepiece. Agora, imagine quevoc6 deseje animar algumas das formas no quadro do jogo. Masnem todasasformas podem ser animadas, entio, o que voc6 faz com a heranga da classe?
Poderiamos criar uma classe com um m6todo animate ( ) , e fazer somente algumas das subclasses de GameShape herdar dela? Se pudermos, entlo poderiamos fazer PlayerPiece, por exemplo,estender tanto a classe GameShape quanro a classe Animatable, enqu-anto que TilePiece estenderia apenas GameShape. Mas nio, isso nio funciona! Javatem supofte a apenas uma heranga! Isso signi{ica que uma classe s6 pode ter uma superclasse imediata. Em outras palavras, se PlayerPiece for uma classe, nlo 6 possivel dizer algo como:
GameShape,
Arrimatable
t // Niot
IJma classe nio pode estendermais do que uma classe. Isso significa um parent por classe. lJma classe pode ter mriltiplos ancestrais,no.itttatrto,,r-avezqueiclasseBpoderiaestenderaclasseA,aclasseCpoderiaestenderaclas_seBeassimpor
diante. Entio, qualquer classe poderia ter mriltiplas classes acima de si na 6rvore de heranga, mas isso nio 6 o mesmo que
AOTRABALHO
Algurzas ltngaagens (cono C++) permitem qae ana
classe e$enda
classe.
Essa capacidade
criadoru de Jaua decidiram ndo permitir a beranga nilltipla d qae ela pode acabar bagungando o c,idigo. prob/ena i qae se uma clasv estender dttas oatras c/astes, e ambat as superc/asses tiuerem, digamoq um mitodo Basicaaente, o doStuf ( ) , qaal uersdo de doStuf ( ) a subclasse herdaria? Essa quut1o poderia leaar a un ceniio conhecido como o 'Dianante da Morte", por causa daforrna do diagmna dt clasm qae pode ser criado en pmjetot com heranga nilltipk. O dianante iformado qaando
ntiltipla".
raTdo
pela qual
os
tantoaclasseBquantrac/asseCestendemA,etantoBquantoCherdamummitododeA.Seac/asseDestendertantoBquantoC,e tanto B quanto C tiaerem sobrescito o mitodo de A, a claste D tenl, na teoia, herdado duas imp/erttentagdes dtferentes do mesmo mitodo.
Duenhada cumo ilm dngmma
de classes,
Assim, se isso nio funciona, o que mais voc6 poderiaf.azer?Poderia simplesmente colocar o c6digo de animate ( ) em GameShape, e depois desabiliiar o m6todo im classes que nio possam ser animadas. Mas essa 6 uma decisio ruim para um prorero por murras raz6es, incluindo a de que isso o torna mais propenso a erros, torna a classe GameShape menos coesa (falaremos mais sobre a coesio em instantes), e significa que a API de GameShape "anuncia" que todas as formas podem ser animadas, mas isso nlo 6 verdadeiro porque apenas algumas das subclasses de GameShape poderio rodar com sucesso o m6todo animate ( ) .
Entdo
o que mais
apenas ai subclasses
voc6 poderia fazer? VocA j6 sabe a resposta - criar uma interface, Animatable, e fazer com que di cameshape q.rc possam sei animadas implementem essa interface. Eis o seu c6digo:
JAVA
59
E eis a classe
PlayerPiece
game
piece" ) ;
jfr-F.l*/\r--AIlrlL@LfIrV, \
,,\;
Agora n6s temos uma classe PlayerPiece que passa no teste E-LIM tanto para a classe GaneShape quanto para interface Animatable. Isso significa que um PlayerPiece pode ser tratado polimorficamente com uma das quatro seguintes opg6es a qualquer momento, dependendo do tipo declarado da variivel de referncia:
r I I I
Um obj
ect
ect)
PlayerPiece
estende GameShape)
Um
PlayerPiece (umavez que 6 isso que realmente 6) Um Animatabl e (uma vez que Pl ayerP i ece implementa Animat.abl
e)
PlayerPiece player = new PlayerPiece ( ) ; ^ prayer; ^^+ uDJecE. o -= *1 --., ^Li Gameshape shape - player; Animatable mover - player;
56existeumobjetoaqui-umainstAnciadotipoPlayerPiece -mashiquatrotiposdiferentesdevari6veisde referdncia, todasreferindo,se a um objeto na *&n6.i". teste rapido: quais das variiveis'de refer6ncia acima podem chamar o m6todo displ-ay ( ) ? Dica: apenas duas das quatro declarag6es podem serusadas para chamar o m6todo display ( ) .
Lembre-se de que as chamadas a m6todos permitidas pelo compilador sio baseadas unicamente no tipo declarado da referAncia, independentemente do tipo do obj eto.Eitlo,observando os quatro tipos de refer6ncias novamente - obj GameShape, PlayerPiece e Animatable - quais desses quatro tipos conhecem o m6todo display ( ) ? VocA adivinhou
ect,
e PlayerPiece, como 6 de conhecimento do compilador, t6m um m6todo tipos de refer6ncias pode ser usado para chamar display ( ) . Lembre-se de que, para o compilador, um PlayerPiece E-UM GameShape, enteo o compilador diz'estou vendo que o tipo
display
as classes
GameShape
desses
(),
entio qualquer um
declarado6 elayereiece e,umavezque PlayerPiece e$endeGameshape,issosignificaque etayerpiece herdou o m6todo display ( ) . Ponanto, PlayerPiece pode ser usado para chamar o m6todo display ( ) ."
Quais m6todos podem ser chamados quando o objeto PlayerPiece e$6 sendo referido por meio de uma refer6ncia declarada como do tipo animatable? Apenas o m6todo animate O . E claro que o interessante aqui 6 que qualquer classe, de qualquer irvore de heranga, pode tamb6m implementar Animatatle; enteo isso significa qn., s.voc6 tiver um m6todo com um argumento declarado como do tipo Animatable, poder6 passar objetos PlayerPiece, objetos spinninglogo e qualquer coisa que seja uma instAncia dl uma classe que implemente Animatabl-e. E voc6 pode usar esse parAmetro (do tipo Animatable) para chamar o m6todo animate ( ) ,.mtr nio o m6todo display ( ) (que pode nem existir) ou qualquer outro que nio seja conhecido pelo compilador com base no tipo da refer6ncia. O compilador sempre sabe, nb entanto, que voc6 pode chamar os m6todos da classe obj ect em^qualquer objeto, entXo 6 seguro chami-los independentemente da iefer6ncia classe ou interface - usada para apontar para o objeto
Deixamos de fora uma grande pane deste assunto: o fato de !lue, mesmo que o compilador s6 conhega o tipo de refer6ncia declarado, a JVN[, em tempo de execugio, sabe o que o objeto iealmente 6. E isso significa que, mesmo que o m6todo displJy ( ) de PlayerPiece seja chamadb usando-se uma variivel de referTncia Gimeshape, a JVM chamari a verslo do m6todo display ( ) presente em PlayerPiece, caso PlayerPiece sobrescreva esse m6todo! A Jyry o!se_rv1 o objeto real do outro lado da refer6ncia, "v6' que ele sobrescreveu o m6todo do tipo da vari|vel de refer|ncia declarada, e chama o m6todo da classe verdadeira do objeto. Mas uma coisa a se ter eni
mente:
As chamadas de m6todos polim6rficos se aplicam somente a nitodos de in$6ncias. VocA sempre pode se referir a um objeto com um tipo de va?iivel de refer6ncia mais geral (uma superclasse ou interface), -"r, .- tempo de
60 Copitulo 2: Orientogdo
o obietos
execuglo, ONTCAS coisas que sio selecionadas dinamicamente com base no pr6prio objeto (em vez de no tipo "s da referincia) sio os m6todos de instincias. Nio m6todos uttiticos. Nio uaridueis. Apenai m6todos de instAncias sobrescritas slo chamados dinamicamente com base no tipo real do objeto. IJma vez que essa definigio depende de um entendimento claro da sobrescrigio, e da distingio entre m6todos estiticos e m6todos de instincias, falaremos sobre eles em seguida.
identifcar
M6todos Sobrescritos
Sempre que vocd tiver uma classe que herde o m6todo de uma superclasse, poderi sobrescrever esse m6todo (a menos que, como aprendeu anteriormente, ele tenha sido marcado com f inal). O beneficio chave da sobrescrigio 6 o recurso de definir um comportamento que seja especifico de determinado tipo de subclasse. O exemplo a seguir demonstra a subclasse Horse penencente i classe Animal sobrescrevendo a versio do m6todo
eat(
)dessaclasse.
public cl-ass animal { public void eat ( ) t System. out.println ( "Generic animal Eating Generically" ) ;
)
errv
]
)
Para os m6todos abstract que voc6 herdar de uma superclasse, nio hi escolha. E preciso implementar o m6todo na subclasse a menos que ela tambdm seja abstract. Os m6todos abstract devem ser inplementados , pela subclasse concreta, -as isio virtualmente 6 o mesmo que dizer que a subclasse concreta sobrescreae os m6todos como aqueles ot quair ser,iforpado a abst.ract da superclasse. Portanto, voc6 deve considerar os ndtodos
abstract
sobrescreuer.
O criador da classe Animal pode ter decidido que para fins de polimorfismo, todos os subtipos de Animal precisario de um m6todo eit ( ) definido de maneira .rp..ifi." e.exclusiva. Coq o polimorfismo, quando algu6m tiver uma referAncia a Animal que aponte nio para uma instAncia de Animal, mas para a instAncia de uma su-bclasse de Animal, o chamador deveria chamar eat ( ) na referAncia a Animal, mas o objeto real do tempo de
execuglo (digamos, uma instAncia de Horse) executari seu pr6prio m6todo eat ( ) especifico. Marcar o m6todo eaJ( ) como abstract 6 a maneira de o programador de Animal informar a todos os desenvolvedores de subclasses: "Nio tem sentido s.n novo subtipo usar um m6todo eat( ) gen6rico, portanto, voc6 teri que criar sua pr6pria implementagio do m6todo eat ( ) !". lJm exemplo (nlo-abstract) do uso do
public static void main (String [] args) t Animal a = new Animal0; Animal b = new lrorEe () t / / Refer6ncia Animal, a.eat\\; // Executa a versdo Animaf de eato b.eat (\; / / Executa a versSo Horse de eato
rnas
JAVA
6I
class animal { public void eat ( ) t System.out.println( "Generic Animal Eating Generically"
) )
class Horse extends Animal { public void eato { System.out.println("Horse eating hay, oats, and horse treats"),' i public void buck0 { }
) a classe de teste usa uma refer6ncia a Animal para chamar o m6todo em um objeto Horse. Lembre-se de que o compilador s6 permitir6 que os m6todos da classe Animal sejam chamados quando a referAncia a um objeto Animal for usada. O c6digo a seguir nio seria vilido dado o c6digo anterior:
No c6digo anterior,
chamar buckO;
asse m6todo
s6 verificari o tipo da referdncia e nio o da instdncia. O polimorfismo permitir6 que voc6 use a refer6ncia a um supeftipo mais abstrato (incluindo uma interface) para acessar um de seus subtipos (inclusive os implementadores da interface).
O compilador
voc6
ndopodertl ter um modficador de acesso mais restritiuo do que o m6todo que foi sobrescrito (por exemplo, nio pode sobrescrever um m6todo marcado com public f.azendo com que ele se torne protected). Pense bem: se a classe Animal apresentar um m6todo eat ( ) public e algu6m tiver uma referAncia a Animal (em outras palavras, uma referencia declarada com o tipo Animal), essa pessoa presumiri ser seguro chamar eat ( ) na referncia a Animal independente da instAncia real para a qual a refer6ncia estiver apontando. Se fosse permitido que uma subclasse se infiltrasse e alterasse o modificador de acesso no m6todo novo, enteo, repentinamente no tempo de execuglo - quando a JVM chamar a verseo real do m6todo no objeto ftIorse) em vez da versio do tipo da referincia (Animal) - o programa seria interrompido (sem mencionar o stress emocional sofrido por quem foi traido pela subclasse embusteira). Alteremos o exemplo de polimorfismo que vimos anteriormente:
O m6todo novo
public class TestAnimals { public static void main (String [] args) { Animal a = newAnimalo; Animal b = new Horse() i / | Refer6ncia Animal, nag 5 urn objeto a.eat); // Executa a versao Animal de eato b.eatO; // Executa a versdo Horse de eato
]
]
Horse
cl-ass Animal
{ {
);
nio
62
Animal b = new Horseo; // Referlncia Animal, mas 6 um objeto Horse, / / aL6 aqui. tudo bem // Falha no tsnpo de execug3,ol
b 6 do tipo enimal, que possui um m6todo eat ( ) public. Contudo, lembre-se de que no tempo de execugio,alinguagemJavausaachanadaaumnitodovirtaalparaselecionardinamicamenteaverseo realdom6todoqueser6 executado, com base na instAnciareal.IJmarefer6ncia aAnimal sempre poderiapontatparauma instincia de Horse, porque Horse E-UM Animal. O que torna possivel a essa superclasse refererr.i", r.r*" iortAncia da subcl asse 6 a certery dc qui) subcksse pode faqgr tuda que a superclasn pode faqer. Se a insdncia de Horse sobrescrever os m6todos herdados de Animal ou simplesmente herd6los, qualquer pessoa com uma refer6ncia de Animal ) instAncia de Horse poder6 chamar todos os m6todos disponiveis em Animal. Por essa razio, o m6todo novo deve seguir o contraro da superclasse.
A vari6vel
As regras para a sobrescrita de um m6todo sio as seguintes:
I I I I I
llsta de argumentot deae coincidir exatamente com a do m6todo sobrescrito. Se nXo coincidirem, voc6 poder6 acabar com um m6todo sobrecarregado que nio queria usar.
O O O
tipo dz retomo
niuel de
acesso
Os m6todos de instAncias somente podem ser sobrescritos se forem herdados pela subclasse. lJma subclasse dentro. do mesmo pacote que a superclasse da instincia 6 capaz de sobrescrever qualquer m6todo de superclasse que nio seja marcado com private ou f inal. Uma subclasse de um pacote diferente somente pode sobrescrever os m6todos nio-f inal marcados com public ou protecteA (uma vez que os m6todos protect.ed sio herdados pela subclasse).
I I
O m6todo sobrescritor PODE langar qualquer excegio (de tempo de execugio) nio-verificada, independentemente de o m6todo sobrescrito declarar ou nio a excegio. (Mais sobre isso no Capitulo 5.) O m6todo novo ndo deae langar excegdes ueifcadas flnuas 0a mais abrangentes que as declaradas pelo m6todo sobrescrito. Por exemplo, um m6todo que declare uma excegio FileNotFoundException nio poder6 ser sobrescrito Por um m6todo que declare uma excegio SQlException, Except.ion ou qualquer outra excegio que nio seja de tempo de execugio, a menos que ela seja uma subclasse de FileNotFoundException.
O ndtodo noao podeni langar excegdes nais restritiuas oil nefilr abrangentes. 56 por que o m6todo sobrescrito "se arriscou', nio quer dizer que a excegio da nova subclasse deva contemplar os mesmos riscos. Conclusio: O m6todo novo nio precisa declarar nenhuma excegio que nunca langar6, independente do que o m6todo sobrescrito
tenha declarado.
I I I
Voc6
f :-na]-.
Voc6 nio pode sobrescrever um m6todo marcado com static. Veremos um exemplo daqui a algumas p6ginas, quando discutirmos os m6todos static com mais detalhes.
u, mdtoda ndo puder rcr lterdado, uocd ndo poderi sobrewaiJo. Lembre-se de que a sobrescrigio implica que voc6 esti reimplementando um m6todo herdado! Por exemplo, o c6digo a seguir nio 6 vllido, e mesmo se voc6 adicionasse um m6todo eat ( ) a Horse, ele nio seria uma sobrescriqXo do m6todo eat ( ) de Animal:
Se
public class TestAnimals { public static void main (String [] args) i Horse h = new Horse0; h.eat l); / / Nio 6 w61ido, Dorque Horse nio herdou eat()
)
]
^1 -^^ L!d>D n-l--r rurltrdf t
JAVA
63
o m6todo e' em seguida, volte aqui e tirmine com o c6digo adicional d. mirrh" subclasse para 6 preciso que a versio 1y 3t$g"lf !:"* ressaltar qry :,.t?o usando a palavra-chave da superclassZ t.1" suDclasse)' t tacrl tazer lsso no codrgo super, como vemos a seguir:
p-a.ra.
chamando a versio da superclasse de um m6todo sobrescrito Geralmente, voc6 iri se. beneficiar de algum c6digo da versio da superclasse para um m6todo, ainda assim, sobrescrevendo-o para fornecer um comport"-.ito especifico adicional. Seri como dize., li"ecrrte a versio
superclasse
da
.".."r.J"";;;;i;;dt;;'d"
} /\ / \ / t
nrint-Vnrrrcalf rvstpsr!
/\ \/
/ I
/ Aproweita-se do c6digo de Animal, depoj-s adici-ona mais c6dioo super.printYourself O,. // Chama a supercfasse
/
/ /,/ // //
/
l
c6digo (Animal)
Depois volta e realiza
Observagio: IJsar super para chamar um m6todo sobrescrito somenre se aplica a m6todos de instAncias. (Lembrese de que m6todos static nio podem ser sobrescritos.)
sobretcritor, o conpiladar
ama refeftnciapolinilfica (do sapet'po)para apontarpara o objeto do subtipo com o m1todo cbamando a uersdo do ndnio do srpen;po.-Se o aeoAo do supet;po dul)rar uma exnpdo uerifcada, mas o mdtoda do subn'po ndo of7.er, o conpilador ainda assim pensani qie uoc6 uni chamando ,nao qae declara ama"excegdo
aocd
anr
arunini
que
uocd eshi
ni
class Animal i public void eat ( ) throws Exception / / Ianea uma Exceqd.o
)
class Dog2 ext.ends Animal { public void eatO { //sem Exceq6es } public static void main(String [] args) Animala=newDog2O; Dog2 d = new Dog2O; d.eatO;// ok a.eatO; ll erro de coogilagao I / Exceg6,o n6o relatada
) ) Este aldigo ndo coapilanl deuido exce\zo dularada no mdtodo eat ( eaL ( asado sela a uertdo de Dog a qual ndo dulara a excegdo.
de
Aninal.
Isso
64 Copitulo 2: OrientoE6o
o obietos
Exemplos de sobrescritas de m6todo v6lidas e nao-vilidas Examinemos a sobrescrita do m6todo eat ( ) de Animal: public class Animal { public void eat O { }
)
A Tabela
eat
Problema no c6digo
privatevoideat(
){l
}
public void eat ( ) throws lOException { public void eat ( string food) { publicStringeat( ){
}
nio
declarada
IJrru sobrecarga vilida, e nio uma subscrigiq poque a lista de a{gumentos foi aherada
Nio
}
6 uma subscriglo por causa do tipo de retorno, mas tamb6m nio 6 uma sobrecatga
porque
M6todos sobrecarregados
VocA deve estar
pergtrntando o que os m6todos sobrecarregados estio fazendo em um capido sobre OO, mas os p.lt fa:to de uma das coisas com as quais os deienvolvedoresJava novatos mais se confundem serem incluimos "q.ri sutis diferengas entre m6todos sobrecamgados e sobrescitos. justamente as
se
Os m6todos sobrecarregados permitirio que voc6 reutilize o mesmo nome de m6todo em uma classe, mas com ;g";;; dif.rentes (e Spciori"l*..rr., .or.r um tipo de retorno diferente). A sobrecarga de um m6todo geralmente ,ifnifi." q.r..,o.6.rt"ri r"ndo um pouco mais condescendente com as Pessoas que chamarem seus m6todos, po^rque razr ..iaig" *]"*r ,^^tirf.^d{idar coirrtipos de argumentos diferentes eri vezdeiorgar o rhamadorafaznr convers6es antes de
chamar seu m6todo. As regras sio simples:
I Os m6todos sobrecarregados deuem alterar a lista de argumentos. I Os m6todos sobrecarre gados poden alterar o tipo de retorno. I Os m6todos sobrecarreg adospodem alterar o modificador de acesso. I Os m6todos sobrecarregado pothm declarar exceg6es verificadas novas ou mais abrangentes. t Um mttodo podeser sobrecarregado na mesma classe ou em uma subclasse. Em outras palavras, se a classe A definirum m6todo doStuf f (int i), a subclasse B poderia definirum m6todo doStuf f (String s) sem sobrescrever a versio da superclasse que usa um int. Assim, dois m6todos com o mesmo nome, mas em
s
diferentes classes, ainda podem'r.r corrsid.rados como sobrecarregados, caso a subclasse herde uma versio do m6todo e depois decl^ri outr^versio sobrecarregada na sua definigio de classe.
Sobrecargas vilidas
Examinemos um m6todo que queremos sobrecarregar:
pattern)
)
:
{ }.
sobrecargas u,itidas
changeSize
name)
(
}
I
{
I
naftern)
name)
JAVA
65
{ f / i nr rr r, ctsri evL-ng } S) {
}
{ f frfu inr \
i
VocdpodefcartentadoaconsideraralOExcepLioncomooproblema,a0uerqueomdtodosobrevritodoStuff()ndodeclarou
um1
excegdo e ao saber que
subclasse
a excegdofoi uerifcadapelo compilador. Mas o mitodo doStuf f ( Bar o sobrepds, altemando a lista de argumentlr, portanto a excepdo lOExcept.i on
)
i
Quando.um m6todo for chamado, pode existir mais de um m6todo com o mesmo nome para o ripo de objeto em que voc6 o estiver chamando. Por exemplo, a classe Horse pode ter-tres m6todos com o ;esmo nbme, por6-, com listas de argumentos diferentes, o que significa que o m6todo foi sobrecarregado. com um argumento String, a versAo sobrecarregada que usar uma String ser6 chamada. Se chamar um m6todo com o mesmo nome' mas Passar Para ele um tipo f 1oat, a versio sobrecarregada que usar um tipo f loat ser6 executada. Se chamar um m6todo com o mesmo nome, mas passar para el=e um-objeto roo e nio houver uma versio.sobrecarregada que use esse objeto, enteo, o compi]xdel aviJar6 que nio est6 conseguindo encontrar uma coincid6ncia. A seguir temos exemplos de chamadas a m6todos sobrecarregados:
A decisio sobre qual dos m6todos coincidentes chamar ser6 baseada nos argumenros. Se voc6 chamar o m6todo
class Adder {
// Sobrecarrega o m6todo addThem para adi-cionar doubles public double addThem(double x, double y) { return x + y;
) )
em
vez de ints
/ A partir de outra classe, chama o m6todo public c1ass TestAdder { public stat.ic void main (String [] args) Adder a = new Adder0;
/
addThemo
int c = 3; int result. = a.addThem(b,c) ; ll euaL addTtren 6 chanado? double doubleResult = a.addThem(22.5,89.36) ; // euaL addlltrern?
] No c6digo
TestAdder
a
m6todo, portanto,
int
anterior, a primeira chamada a a. ad.dThem (b, c) passa dois tipos int para o primeira versio de addThem ( ) - a versio sobrecarregada que usa doii argumen^tos de tipo
-ser6chamada.Asegundachamadafeitaaa.addThem
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+
Animal animalObj = new animal Horse horseobj = new HorseO; ua.doStuff (animalObj ) ; ua.doStuff (horseObj ) ;
)
)
f ( animalRefToHorse
Qual das vers6es sobrecarregadas seri chamada? Voc pode estar querendo responder: "A ,9ge usa qm objeto
que est6 sendo passado parJo m6todo no tempo de execugio". Mas
nio
6 assim que
Sli*ll, a opgio por qual m6todo m6todo) nio 6 decidida dinamicamente no tempo de sobrecamgado chamar (em outras palavras, a assinatura do execugi6. Apenas lembre-se de q.te o tipo da referdncia (e ndo o tipo d9 objeto) d(emiry 4!al ndto(o sobrecamgado.unl chamado! Resumindo,^o m6todo sobresnito a chamar (em outras palavris, de qual classe da 6rvore de heranga)- 6 decidido.no tempo de exuipao com base no tipo do objeto, mas qual versio sobreearegado do m6todo chamar 6 baseado no tipo da referdnciapassado no rempo de tonp;kgi. Se voc6 chamar um mtodo passando a ele uma referdncia Animal a um oblrto Horr., o compilador s6 saberi do Animal, portanto, ele escolhe a. verslo sobrecarregada do m6todo que ,rr" rr* Animal. Nio impona, em tempo de execugio, que na verdade seja um Horse sendo passado.
Ainda que o objeto real no tempo de execugXo
seja
is descritas abaixo:
JAVA
)
67
public class Horse extends Animal { public void eat0 { System. out.println ( ..Horse eating hay .. ) ;
) .ia vvfq nrrh'l re rrniA
yslf
c\
o/
I I
Observe que a classe Horse tanto sobrep6s quanto sobrescreveu o m6todo eat ) . A Tabela 2-2 mostra que eat ) ser6 executada dependendo de como forem chamadas.
Iobelo
2-2
e sobrescrifos
Animala=newAnimal( ); a.eat( );
Horseh=newHorse( ); h.eat(
)
a2,eaX
Animal a2 = newAnimal (
("treats");
compilador nlo se preocupou com o fato de quetalvez o objeto real no tempo de e:<ecugio seja um objeto Hone.
Erro do compilador! O compilador conrinuou examinando somenre o tipo da refer6nciae viu que Animal nio tem um m6todo ea( )qtre use uma srring. O
pene O EXAME
sobruamgado,
e ndo robretcrito
A elasseBar tem dois mdtodot doStuf f ( ): a uersdo sem argamentls qae herdou deFoo (e ndo sobresmuel e a nbrecamgada doStuf f (String s) defnida na classe Bar. O aidigo con uma referncia ao objeto Foo pode chamar somente a aersdo sem argilnentLr' mN 0 que ten a referncia a am objeto Bar pode chamar qua/.quer uma das uersdes sobrecamgadas. A Tabela 2-3 resume a diferenga entre m6todos sobrecarregados e sobrescritos.
Iobelo 2-3 Diferengo enlre m6fodos sobrecoregodos e sobrescrifos. Mtodo sobrecarregado
lista de argumentos Deve ser alterada
Pode ser alterado
M6todo sobrescrito
Nio
tipo de retorno
Exceg6es
Nio
68
Nio
Chamadas
O tipo do
objeto
todo
instante.
chamado ain&ter6uma chama&virnral no tempo de excecu$o, a coincidAncia de argumentos ji teri sido definida, s6 faltando a classe real onde o m6todo reside.
Sobrescrito
Tree
Sobrecarregado
Tree
()
showleaves
setFeatures (String
name)
Oak
Oak
()
showleaves
Figuro
(5.4) aborda tanro a.sobre carga de m6todos quanto de construtores, por6m, a iltima ser6 abordada na proxlma segao, na qual tamb6m discutirernos os outros t6picos-relacionados a construtores que aParecerio no ."".n.. A figuia 5-4 ilustra a maneira como m6todos sobrecarregados e sobrescritos sio tratados em
O objetivo atual
relacionamentos de classes.
uto
do
de objetos J6 vimos que 6 possivel e comum usar tipos gen6ricos de variiveis de ref_9r6ncia pa?:.ap2+tar.para,tipos mais especifi.oi. kto forma a base do poli*orfir-o. Por exemplo, esta linha de c6digo lhe deveri Parecer natural a esta altura:
class
Dogr
extends Animal {
JAVA
69
void makeNoiseO {System.out.println(..bark,,) ; } void playDead ( ) i System. out.println ( ', roll over,, ) ;
]
class CastTest2 { public static void main(String IJ args; { Anima] tl a = inew Animal O , new DoSO , for(Animal animal : a) {
animal.makeNoise ( ) ;
new Animal
O );
um coq)orta.mnto de D,og?
cannot.
de c6digo
find
slzmbol
O compilador
if:
est6 dizendo:
'Ei,
a classe
()
O novo
E i-pon"ttt. saber que o compilador ser6 forgado a confrar em n6s quando fazemos uma conversio redutora, mesmo quando fazemos besteira:
Animal animal = new Animal ( ) ; Dog d = (Dog) animal; // corpila, nas falha depois
J
com esta:
NTNCA
inconvertible tlpes
Ao contr6rio da conversio redutora, a conversio generalizadora (convefter para cima na irvore. de heranga, de um tipo mais especifico para um mais geral) funciona-implicitamente (ou seja, voc6 nio precisa incluir n_o seg c{digo) porque q.rando faz ima conversio ge neralizadora, votA esti implicitamente restringindo o nimero de m6todos
que ilode chamar, ao contririo da conversio redutora, o que implica que, mais tarde, voc6 poder6 desejar chamar um m6todo mais espec{fco. Por exemplo:
^t ^^^ Ll45> n-i*-1 rurrrllal r I
J
class
class DogTest {
nrrlr]in c{-:fia
d = new Dogo; Anina1 a1 = d; / / converslo generalizadora ok sem nenhunr converEio e:rglicita Ani.mal a2 s (Animal) dt ll cornwergio generalizadora ok co umr conversio otrllicit,a
Dog
) )
Ambas as convers6es acima irio compilar e rodar sem exceg6es, porque um Dog n-UVt Animal, o que significa que qualquer coisa que um Animal possa fazer, um Dog tamb6m poder6. Um Dog pode f.azer mais, 6 claro, mas-a questao 6: qualquer um que tenha uma referAncia a Animal pode chamar, com seguranga, os m6todos de Animal em uma instincia de Dog. Os m6rodos de Animal podem ter sido sobrescritos na classe Dog, mas tudo que nos importa agora 6 que um Dog sempre pode tazer, no m(nimo, tudo o que um Animal puder. O compilador e a JVM tamb6m sabem disso, entlo a conversio generalizadora implicita 6 sempre v6lida para atribuir um objeto de um subtipo a uma referencia de uma das classes (ou interfaces) do seu supertipo. Se Dog implementar Pet, e Pet definir beFriend.ly ( ) , entio um Dog pode se converter implicitament. .tn n.tiPrt, mas o 6nico m6todo de Dog que voc6 poder6 chamar enteo ser6 beFriendly ( ) , que Dog foi forgado a implementar porque Dog implementa a interface Pet. Mais uma coisa... Se Dog implementa Pet, entXo se Beagle estender Dog, mas Beagle nio fuclarar que esti implementando Pet, Beagle ainda ser6 um Pet! Beagle 6 um Pet simplesmente porque estende Dog, e Dog jlt cuidou dos seus pr6prios comportamentos Pet, e os de todos os seus descendentes. A classe Beagle sempre pode sobrescrever quaisquer m6todos que herdar de Dog, incluindo m6todos que Dog implementou para satisfazer o contrato da sua interface. E s6 mais uma outra coisa... se Beagle de fato declarar que est6 implementando Pet, apenas para que as pessoas gue olharem a API. da classe Beagle possam ver facilmente que Beagle E-IIM Pet, sem ter de olhar nas superclasses de Beagle; Beagle ainda assim nlo precisarl implementar o m6todo beFriendly ( ) caso a classe Dog (a superclasse de Beagle) jS,tenha cuidado disso. Em outras palavras, se Beagle E-UM Dog, e Dog E-UM Pet, entio Beagle E-IIM Pet, e ji atendeu is suas obrigag6es de Pet de implementar o m6todo beFrien-dly ( ) , uma vez que ele [erda esse m6todo. O compilador 6 espirio o suficiente pira dizer, "Eu j6 sei que Beagle 6 UM Pet, mas nio tem problema em tornar isso mais 6bvio". Assim, nio se deixe enganar por um c6digo que mostre uma classe concreta que declare estar implementando uma interface, mas que nio implemente os mitodos da interface. Antes de poder dizer se o c6digo 6 vilido ou nio, vocA precisa saber o que as superclasses dessa classe concreta declararam. Se qualquer classe da sua irvore de heranla jitiver forneiido implementag6es concretas (ou seja, nio-abstract) doi m6todos, e tiver declarado que ela (a superclasse) est6 implementando a interface, enteo a subclasse nXo tem obrigagio nenhuma de
reimplementar (sobrescrever)
esses m6todos.
oBSERVAQoES
Embora
isso
pene O EXAME
que foran
t/a
forgadot a eo/ocar toneladas de aldigos em pequeills espapos 'por causa do sistema do exane". TAMBEM gwtam de ser obvums. O aidigo ngainte:
rlnnnacrrrff
/\ / \
por
e$e,
nuito nais
jlcil
de ler:
Ani-ma1
( (Dog)
a = new DogO;
()
a) .doDogStuff
;
esses
JAVA
71
Quando voc implementar uma interface, estari concordando em aderir ao conrraro definido nela. Isso significa que estari concordando em fornecer implementas6es v6lidas de cada m6todo definido na inrerface e que {ualquer pessoa que.souber como sio os m6todos da interface (nio a maneira como sio implementados, *"r .&.to irod6m ser chamados e o que retornam) poderi cham6-los na instAncia de uma classe sua que a implementar.
Por exemplo, se voc6 criar uma-classe que implemente aintertace Runnable (de modo que seu c6digo possa ser executado por um thread especifico), ter6 que fornecer o m6todo public void run ( I . Oo conlririo, o coitado do thread_ poderia ser informado para executar o c6digo de seu objeto Runnable e - surpresa - iria descobrirqueo objetoniopossui o m6todo run( ) !(Momentoemque, othreadseriainterrompidoeaJVM encerrado em uma finalizagi"o espetacular, por6m, horrivel). Felizmenle, a linguagem Java impedlr6 que isse dano ocorra pela execugio de uma verificagio do compilador em cada classe que tentaiimplementar uma interface. Se a classe informar que esti implementando uma interface, 6 melhor que tinha uma implementagio de cada m6todo
da interface (com algumas exceg6es que examinaremos em breve). Assumindo-se que temos uma interface Bounceable, com dois m6todos: seguinte classe ir6 compilar:
bounce ( ) e setBouneeFactor
()
public class Ball inplenents Bounceable { // palavra-chave.imp]ements' public void bounce O { } public void setBounceFactor(int. bf) t ]
)
Cefto, sabemos o que voc6 esti pensando: "Essa deve ser a pior classe da hist6ria das classes de implementagio". No entanto, ela ser6 compilada. E executada. O contrato di interface garante que uma classe tenha o m6todo (em outras palavras, classes diferentes poderio chamar o m6todo, sujeito a conirole de acesso), mas nunca garantirS, uma implementagio adequada - ou mesmo algum c6digo de implementaEio real no corpo do m6todo-O compilador nunca lhe dir6, "Desculpe, mas voc6 nlo quer mesmo inserir nada entre essas chaves? ATENQAO: que se trata de um m6todo, ele nio deveria executar algo?". As classes de implementagio devem estar sujeitas as mesmas regras de implementagio do m6todo como uma classe estendendo uma classe abstract. Para ser uma classe de implemintagio v6lida, uma classe de implementagio nio abstract deve fazer o seguinte:
ji
I Fornecer implementag6es concretas (nio abstract) de todos os m6todos da interface declarada. r Seguir todas as regras de sobrecarga vilidas. I Nio declarar exceg6es existentes em m6todos de implementagio que nio sejam as declaradas pelo m6todo
interface, ou subclasses que
da
nio
Manter
a assinatura e o mesmo tipo de retorno do m6todo da interface (por6m, nXo sendo preciso declarar as exceg6es existentes na declaragio do m6todo da interface).
hi mais! Uma_classe de implementagio pode ser ela pr6pria abstract! Por exemplo, o c6digo a seguir 6 v6lido para uma classe Ball que implemente a interface Bounceable:
Mas.espere_,
Notou algo faltando? Nio fornecemos os m6todos de implementagio. E isso esti certo. Se a classe de implementagio for abstract, ela pode simplesmente passar atarefa para sua primeira subclasse concreta. Por exemplo, se a classe BeachBall estender Ball e nio for abstract, entXo, reri que fornecer todos os m6todos de
Bounceable:
class eeachBall extends Ball { / / F;rnbora nao o digamos na declaragd.o de classe acima, // BeachBall implement.a Bounceable, uma vez que a superclasse abstract / / BeachBall (8a11) implementa Bounceable public void bounceO
/ / a6di an hnrrnna
de
t
i an rla
acnaaif
vePevflfvv
Ra:nhpr1
rr
I uqur amri
72
public void setBounceFactor(int bf) { / / c6digo bounce especifico de BeachBall aqui para definir
/
um
fator de bounce
de
/ se a classe Ball Liver definido quaisquer m6todos abstract, eles terao / / ser implementados aqui tamb6m.
)
Procure m6todos que informem implementar uma interface, mas nXo fornegam-as implementag6es de m6todo correras. A menos'que a classe de implementagio seja abstract, elaterS, que fornecer implementag6es de todos os m6todos definidos na interface.
VocA precisa conhecer mais duas.regras para que.possamos, entio, encerrar esse t6pico (ouIaz voc6 dormir sempre, pois nunca nos confundimos com uma dessas op96es):
vilido informar, por exemplo, o. seguinte: public class Ball implements Bounceable, Serializable, Runnable
...
VocA pode esrender somente uma classe, mas implementar muitas. Por6m, lembre-se de que a criaglo de subclassei define quem e o que 6 a classe, enquanto I implementagio define uma fungio que ela.poderi desempenhar ou algo que poderi usar, apesar do quanto possa ser diferente de outra classe que estiver implementando a mesma interface (por6m, apartir de uma 6wore de heranga diferente). Por exemplo, uma pessoa estenderia HumanBeing (embora isso possa ser discutivel para alguns). Mas tamb6m poderia implementar programmer, snowboarder, employee, parent ou personcrazyenoughtotakethisexam.
pode estende
}
a
classe concreta (nio abstract) de implementagio de Bouceable deve implementar todos os m6todos dessa interface, al6m de todos os m6todos de Moveable! A subinterface, como chimamos, simplesmente adicionari mais requisitos ao contrato da superinterface. VocA veri esse conceito aplicado em muitas 6reas da linguagem Java, principalmente no J2EE, onde geralmente temos que construir nossas pr6prias interfaces para estender uma das suas.
agoarde, porque 6 agora que comega a ficar estranho. Uma interface pode estender mais de uma interface! Pense bem por um momento. Voc6 sabe que quando se trata de classes, o que vemos abilxo nio 6 vlilido:
No entanto,
frublic cLass
{ , ||
I,rrvlLj-Aol
Java.
No entanto, uma
interface Moveable {
void moveft O ;
)
interface Spherical
)
void doSphericalThing(
Ball 6 necess6ria na implementagio de Bounceable, al6m de todos os m6todos das interfaces que Bounceable estende (incluindo qualquer interface que essas interfaces estendam, e assim por diante, at6 que vocb alcance o inicio da pilha - ou seria o fim da pilha?). Portanto, Ball teria que ter o seguinte formato:
public void bounceO { } // rmplementa os m6todos de Bounceable public void setBounceFactor(int bf) { }
JAVA
73
Se a classe Ball n5o conseguir implementar nenhum dos m6todos de Bounceable, Moveable ou Spherical, o compilador se move{6_para cima e para baixo incontrolavelmente, um pouco envergonhado, at6^que ela o faga. Isto 6, a menos que Ball.seja marcada.como. abstract. Nesse caso, ela poderia opiar por implementar qualquer um, todos ou nenhum dos m6todos de qualquer das interfaces, deixandoassim o restante das implem.ttt"g6.ip"r" uma subclasse concreta de Ball, como descriio abaixo:
abstract class Ball implements Bounceable { public void bounce0 | ... j / / Define o comportamento de bounce public void setBounceFactor(int bf ) { ... } // N6,o implemente o resto,. deixe para Lrma subclasse
)
class SoccerBal-l- extends Ball { // a classe SoccerBal-l precisa i-mplementar os m6todos da interface gue Ball
implemenLou
nao
public void moveTt ( ) { ... } public void doSphericalThingO { ... } / / SoccerBall pode decidir sobrescrever os m6todos de Bounceable // implementados por Ball public void bounce ( ) { ... }
I
interface Bounceable void bounce( ); void setBounceFacEor(int bf) abstract Ball implements
;
Bounceabl-e
^
I
/*ndo serSo implementados Ball quaisquer m6todos de Bounceable */ void beSpherical( ){}
em
class Tire implements Bounceable public woid bounce( ) { ) public void setBounceFactor (int bf) {
}
public void bounce( ){ } public woid setBounceFactor (int bf) { /*beSpherical n5o 6 abstract entao BeachBall ndo 6 solicitado para implementar isso */
Devido oo foto de BeochBoll ser o primeiro closse concreio poro implemenlor Bounceoble, elo deve fornecer implementog6es poro todos os m6todos de Bounceoble, excelo oqueles de{inidos no closse obstroct Boll. Como boll n6o forneceu implementoE6es dos m6todos Bounceoble, BeochBoll foi referido poro implemenlor lodos.
A Figuro 2-5 comporo o uso vdlido e o n6o volido de exlens6es e implementoq6es, tonto poro
closses quonlo poro inferfoces.
oBSERVAQ6ES
intet'aces e clastes:
pene O EXAME
As linhas a seguir
mostram exemplos de dulamgdu udlidas e ndo udlidat de
class foo {
ala<< R:r
} E'^^ f
J
//
oK
imnlamanfc
74
interface eaz { } interface Fi { i interface Fee implements Baz { interface Zee implement.s Foo { int.erface Zoo extends Foo { interface Boo extends Fi {
} }
} }
// oK // oK // Ndo! A interface ndo Pode / / impTementar uma interface // Ndo! A interface ndo Pode
/ / im9sTementar uma
c
//
}
uma
interface
Vroom extends
fi, Fee {
nas
// Ndo! A c-lasse ndo pode estender / /miTtiplas cl.asses // OK. A cTasse pode implementar miTtipTas / /interfaces // OK. A interface pode estender / /n67tip7as interf aces
petgilntar qae estiuerem n0 exame. IndEendente do que as perguntas parEam aualiar, o Antes de cair na arwadilha, digaruos, de acompanbar o fluxo de am thread mmplexo, ueifqae sepelo nenos o cddigo ser,l compilado. (Srlporessa dica,jd meruemls ettarem seu testamento!) (I'zoc6fcari impressionado com o empenho dos elaboradtres do exame en desuid-lo do pmblena real). (Cono as pessnar cznsegt'/iam redigir alg antes dos
ser a declaragdo da classe ou interface.
*m ndtodo
identifcar
para o mdtodo,
Este objetivo abordari dois aspectos dos tipos de retorno: o que voc6 pode declararcomo um tipo de retorno e o que pode realment e returnar como um valor. O que pode ou nio ser declarado 6 muito simples, mas tudo depender6 de voc6 estar sobrescrevendo um m6todo herdado ou simplesmente declarando um novo m6todo (o que inclui os m6todos sobrecarregados). Examinaremos rapidamente a diferenga entre as regras dos tipos de retorno para m6todos sobrecarregados e sobrescritos, porque j6 abordamos isso neste capitulo. Entraremos um pouco em uma 6rea nova, no entanto, quando examinarmos os tipos de retorno polim6rficos e as regras para o que 6 ou nio v 6lido re torn ar realmente.
void go0 {
)
JAVA
75
O_bserve que a versio da classe Bar para o m6todo usa um tipo de retorno diferente. Isso 6 perfeitamente adequado' Contanto que voc6 tenhi alterado a lista de argumentos, esrari sobrecarregando'o m6todo, porranto, o tipo de retorno nio precisar6 coincidir com o da versio da superclasse. O que voc6 n?o pode fazer 6 isto:
public class Bar ext,ends Foo { String go0 { // Inv6lidol Ndo 6 possivel modificar return null;
)
apenas
o tipo de rerorno
A Sobrescrigio e os Tipos de Retorno; e Retornos Covariantes 9y4o uma.subclasse quiser alterar a implementagio de um m6todo herdado (uma sobrescrigio),
ter6 que
definir um m6todo qrre coincida exatanente com a verslo herdada. Ou, a partir do Java 5, voc6 tem a possi-bilidade de modificar otipo de retorno no m6todo sobrescritor, desde que o novo tipo de i.totno seja um subiipo do tipo de retorno declarado do m6todo sobrescrito (da superclasse).
public class Bar extends Foo { String goO { // sobrescrlgdo return nu11;
)
] Com oJava 5, esse c6digo compilari sern problemas. com o flag source, desta forma:
Se
que estiverem sobrerreuendo outros sri poden fa$-/o dentro dot linitu voce conseguiri responder v6rias perguntas do exame.
Retornando um Yalor
VocA ter6 que lembrar de apenas seis regras para o retorno de um valor:
1.
null
2. O array 6 um tipo de retorno perfeitamente v6lido. public String tl goo { return new St.ring[] {"Fred", "Barney", "Wi1ma"};
3.
Em um m6todo com tipo de retorno primitivo, voc6 pode retornar qualquer valor ou variivel que possa ser
76 Copitulo 2: Orientoq6o
o obletos
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.
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
um
public interface chewable { public class Gum implements public class TestChewable
/
{
Chewable
M6Lodo com um
Chewable getChewable
return
]
)
new Gum();
trac t
E-UM
(erz outras
pa/awar,
desse
- por exemplo:
public abstract class Animal { } public class Bear extends animal { } public class Test { public Animal go ( ) { return new Bear (\ ; / / OK, Bear
] ]
Esse aldigo
$a!-um/' Animal
ini
um subtipo.
JAVA
77
5.4 Dado um nndrio, desenuo/ueraidigo que declare efou chame nitodos sobrescritos ou sobrecanegados,
cznJtratlres de superc/assu, con$rutoret sobrescritot ou sobrecanegados.
efou cbane
Os objetos sio construidos. Voc| ndo pode criar am nouo o[eto sem chamar am clnstratzn Na verdade, nio pode criar um novo objeto sem chamar nio s6 o constnrtor do tipo de classe real do objeto, como tamb6m o construtor de cada ana de suas superclassetlConstrutores sio o c6digo que serl executado sgTple. q.Ye voc6 usar a palavra-chave new. OK, para sermos um pouco mais precisos, pode haver tamb6m blocos de inicializagio que executem quando voc6 usar new, mas iremos abordiJos (os blocos de inicializagio), e as suas contrapartes estiticas, no pr6ximo capitulo. Temos muito que discutir aqui - examinaremos como os construtores sXo codificados, qaem os codifica e como funcionam no tempo de execugXo. Portanto, pegue seu capacete e um martelo e executemos a construgio de alguns objetos.
class Foo
)
a classe
Foo Foo
f f
vai compilar,
nao h5 um
construtor correspondente
//
6 muito comum (e desejivel) que uma classe tenha um construtor sem argumentos, independente de quantos outros construtores sobrecarregados existam nela (sim, os construtores podem ser sobrecarregados). Voc6 nno conseguiri fazer com que isso funcione sempre em suas classes; ocasionalmenrc terh uma classe em que nio far6 sentido criar uma instAncia sem fornecer informag6es para o constnrtor. IJm objeto j ava. awt.Color, por exemplo, nio pode ser criado com uma chamada a um construtor sem argumentos, porque isso seria o mesmo que dizer iJVM: "Crie um novo objeto Color para mim e nio vou me preocupar com a cor real que ele ter6,...Vocd escolhe". Voc6 realmente quer que a JVM tome as decis6es est6dcas no seu lugar?
Portanto,
Cadeia de construtores
Sabemos que os construtores serXo chamados no tempo de execugio quando voc6 digitar classe como vemos abaixo:
de
Horseh=newHorseo;
78 Copitulo 2: OrientoEdo
o obietos
Mas o que ocorreri realmente quando voc6 digitar Animal estende Object.)
new Horse
) ? (Assuma que
1. O construtor
de Horse ser6 chamado. Todo constnrtor chama o construtor da sua superclasse com uma chamada (implicita) a super ( ) , a nlo ser que o construtor chame um construtor sobrecarregado da mesma classe (falaremos mais sobre isso em instantes).
2. 3.
O construtor
de
6 a superclasse de Horse).
O construtor de Object ser| chamado (Object 6 a superclasse final de todas as classes, portanto, a classe Animal estenderi Object ainda que voc6 nio digite realmente "extends Object" em sua declaraEio. Estari implicito). Nesse ponto estaremos no inicio da pilha.
de Object receberio seus valores explicitos. Por explicitos, queremos dizer os valores que slo atribuidos no momento em que as varilveis sio declaradas, como "int x = 27", onde "27" 6 o valor explicito (e nio um vaTor padrio) davariSvel de instAncia.
4. As vari6veis de instAncia
5. A execuEio do construtor de Object ser6 concluida. 6. As variiveis de instAncia de Animal receberio seus valores explicitos (se houver). 7. A execuglo do construtor de Animal ser6 concluida. 8. As vari6veis de instAncia de Horse receberio seus valores explicitos (se houver). 9. A execugio do construtor de Horse seri concluida.
A Figura
2-6 mostra como os construtores funcionam na pilha de chamadas. 4. Object
3.
o
calls
Animal O
(
super
2. Horse
calls
super
() ()
l. main ( )
calls
new Horse
Figuro
Regras dos construtores A lista j.g"lf re^sume as que voc6 teri que conhecer .regras
para faze.r o exame (e para compreender o restante " cesta segao). v oce preasara se lembrar-se delas, portanto, estude-as mars de uma vez.
Os construtores podem usar qualquer modificador de acesso, inclusive private (um construtor private significaque somente o c6digo que estiner dentro da pr6pria classe poderi inJtanciar um objeto desse tipo, ionanto, se a classe do construtor private tor permitir que uma instincia dela seja usada, deve fornecer uma varilvel ou m6todo static que conceda acesso a uma iistAncia ciiada dentro da classe).
O nome do construtor deve coincidir com o da classe.
Os construtores nio devem ter um tipo de retorno.
E valido (mas inritil) ter um m6todo com o mesmo nome da classe, por6m, isso nio o tornar6 um construtor. Se houver um tipo de retorno, seri um m6todo em vez de um construtbr. Na verdade, voc6 poderia ter um m6todo e um construtor com o mesmo nome - o nome da classe - dentro da mesma classe, e isso nlo 6 um problema paraJava. Cuidado para nlo achar que um m6todo 6 um constnrtor e vice-versa - pro*i. ,.*pre um tipb de retorno.
Se voc6 nlo inserir um construtor no c6digo de sua classe, um constnrtor padrio seri gerado automaticamente pelo compilador.
I I r
r I I
sempreum
voc6 quiser um construtor sem argumentos e tiver inserido algum(n$ outro(s) no c6digo de sua classe, o compilador nio fornecer6 esse constirtor (ou qualquer outro). Ein outras palavias, se uori"tiaerinseido am clnthatlr clrt aryt/rlettlr, nZo teni tlm sem argumentli a nenlJ que o insira por conta pnipia!
Todo construtor deve ter como sua primeira instruEXo a chamada a um construtor sobrecarregado (this ou ao constnrtor da superclasse (super ( )), mas lembre-se de que essa chamada pode ser inserida pelo compilador.
Se
))
digitarachamadaasuper(
T Uma chamada
zuperclasse.
voc6 inserir um construtor (emvez de ficar esperando pelo construtor padrio gerado pelo compilador) e ndo
)ouathis(
),icon?iladirinseini,automaticamente,irztachanadarsuper(')
sen
super
IJm construtor sem argumentos nio ser6 necessariamente o constnrtor padrio (ou seja, o fornecido pelo compilador), apesar de ele nunca ter argumentos. O coushzrtorpadrio i o que o nntpikdorfomecelEmborio
JAVA
79
seu pftipit
t I I r r
podeni,fazer uma chamada ao m6todo de uma instAncia, ou acessar uma vari6vel de instAncia, at6 que Y?: executado o tenha construtor da superclasse.
ndo
. (Exemplo:
classes
super (Animal
ndo
static
.
p9{eqr s9r
NAME
))
acessados como pafte da chamada a super ( ) ou this v6lido, porque NAME 6 declarada como uma variivel static. s serupre que
As
abstract
As interfaces
voc
$i1 maneira pela qual um constmtoS pode ser chamado nio pode escrever um c6digo que chame
class Horse {
Horse0{}//construtor
rroid dnQirr+Fl\ I
HorseO; //
] ]
chamando
o construt.or - inv6.lidot
a classe acima?
Nio!
Agora o compilador
E para
esta classe?
class
Horse
no ponto exato. O compilador gerarS,tmconstnrtor padrXo para {Bpr3,chegamos celrnroo nennum construtor para ela.
a classe
classe?
1
void Horse( ) {
i
Pode paruer que o compilador nlo crrari um construtor, porque \-rDserve novamente a classe Horse anterior.
ji
Oque hi de errado com o constnrtor Horse( )?.Ele nio 6 de forma alguma um consrrutor! E simplesmente um m6todo que por acaso tem o mesmo nome da classe. Lembre-se de que o tipo de retorno 6 uma fista certa de que estamos olhando para um m6todo, e nio um constnrtor.
Como voce pode ter a certeza de que um construtor padrio seri criado?
Isso ocorreri quando
aocd
ndo criar
nenhum
construtor em sua
classe.
I I I
te
ri
mesmo
modfirador dt
acesso da classe,
(super
).
80 Copitulo 2: OrientoE6o
o obietos
sua classe.
24
cfass Foo {
Eulrer )
)
nrr].'linalaceFnn
{l
F^^/qfrinn
q\
auper( );
]
Nenhum , o
cfass Foo {
(void
Foo
6 um m6todo, nao um
construtor.
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)
JAVA
8I
Assim, se o construtor de sua superclasse (isto 6, o constnrtor de sua superclasse,/parent imediata) tiver argumentos, voc6 teri que inserii a chamada a super ( ) , fornecendo os argumenros apropriados. Ponto crucial: sesua suPerclasse ndo tiver um constnrtor sem argumentos, voc6 tenl qte ins#. rr* .orrt-ior em sua cl"rse (a
subclasse) Porque precisard de um local para inserir a clianado ao nnstrutor da s'upockss, cvm 0r atgamentus @ropiadot.
O c6digo
^l Lfq-r^^^
a seguir 6
rulrrrrqa ^61*-l
um exemplo do problema:
1
Anima]
)
(String name) t
) { super0; // Problernal
(
Horse.
java:7: cannot resolve symbol symbol : constructor Animal_ ( ) location: class Animal superO; // Problema!
)
Se voc6 tiver sorte (e for lua cheia), seu compilador talvez seja um pouco mais explicito. Mas novamente, o problema ser6 o.fato de nlo haver uma corrispondAncia para o q.ri.rt"*os tentando chamar com super ( um construtor de Animal sem argumentos.
super
( j sem arg,rmerrios,
}
E simples assim.
voc6
Ji
-.r-o
compilar;lg"
.;;; ; lafii.
"--
IJma.tentativa de compilar esse c6digo nos traria o mesmo erro que obtivemos quando inserimos um construtor na subclasse com uma chamada i versio sem argumentos de super ( ) :
Na verdade, o c6digo anterior de cloching e TShirt 6 implicitamente o mesmo mostrado a seguir, no qual fornecemos um construtor para TShirt que 6 id6ntico ,o .onrt*tb, padrlo fornecido pelo compilador: "
/ f ornaai
dn nal n anmni
^^^-
Tshirt ( ) { supero; // j // j //
vai funcionar! Chama um construtor sem argumentos Clothing( mas esse construtor ndo existel
Ndo
Um. riltimo ponto relacionado. a toda essa po.lAmica sobre o construtor padrio (e que provavelmente 6 muito obvro' mas. temos que mostre-lo ou nos sentiremos culpados por anos), 6 que ar constratores nunca sdo herdados. EIes nlo sio m6todos. Nio podem ser sobrescritos (porque nio sio m6todos, e s6 os m6todos podem ser sobrescritos).
am
"rgrr*.ntot
Construtores sobrecarregados
Sobrecarregar um consrruror significa inserir v6rias vers6es dele, cada uma tendo uma lista de argumentos diferente, como nos exemplos a seguir:
class Foo
{ } }
roo0 {
)
Foo(String s) {
A
classe
idAntica ao construtor padrio. que o compilador fornece."Mas, lembre-se de que como j6 existe um construtor nessa classe (o que usa uma string), o .o*pil"dor nio fornecer6 um construtor padrXo. Se quiser que um construtor sem argumentos sobrecarregu.e a lr.rrio com argumentos que voc6 j6 tem, tir6 que inseii-lo por sna conta, exatamente como no exemplo de Foo.
que
Ji
de um construtor normalmente 6 usada para fornecer maneiras alternativas de os clientes animal, poderi pass6-1o para instanciareir objetos de uma classe. Por exemplo, se o-cliente souber o nome d9 um construtor de Animal que use strings. Mas se ele nio souber o nome, poderi chamar o constnrtor que nio usa
A sobrecarga
".-
n* tto-.
{
3. 4.
s. )
7. Animal O { this (makeRandomName 8.
10.
O)
11. Etatic String makeRandomNameo { 1,2. int x = (int) (Math.random(1 * 5); 1-3. String name = new Stringi] {"Fluffy", "Fido"' "Rover", "Spike", "Gigi"] [x] ; L4. return name; 15. )
]-6.
17. public static void main (String [] args) i 18. Animal a = new animal0; L9. System.out.println(a.name) ; 20. Animal b = new animal("zeus"); 21. System.out.println(b.name) ; 22. ] 23. \
A execuglo
desse
Zeus
JAVA
83
t java Animal
Rover
I java Fluffy
Zeus
Animal-
Muita coisa aconteceu no c6digo anterior. A Flgur_a 2-7 mostra a pilha de chamadas de construtores quando um constnrtor 6 sobrecarregado. Examine a pilha de chamadas e, em seguida, percorreremos o c6digo desde o inicio.
deinstincianane.
r,inha
T P ^qy;que fica divertido. Suponhamos que cada animal precise de um nome, mas o cliente (o c6digo chamador) pode nio saber qual deve ser usado, porta.rto, voc6 attuir6 um nome aleat6rio. O construtor seir argumentos gerarS, vm nome chamando o m6todo makeRandomName( ).
4. 3.
object (
Animal
(
(Strinq
)
) chama super (
,r
2. Animal
l.main( )
Figuro 2-7
Construfores sobrecorregodos
8 O construtor- sem argumentos chamar6 o constnrtor que o sobrec arrega e usa strings, da mesma maneira que seria chamado se o c6digo-cliente estivesse executando o comando new para instinciar um objeto, passando para ele uma string relacionada ao nome. A chamada sobrecarregada nsa a palavra-chave tJris, empregando-a como se fosse o nome de um m6todo, this ( ) . Portanto, a linha 8 esi6 simplesmente chamando o constrtrtor da linha 3, passando para ele uma string selecionada aleatoriament , emviz de um nome escolhido pelo c6digo-cliente.
Linha
pode chamar um m6todo de instAncia (em outras palavras, nio-static) ou acessar uma vari6vel ie instAncia, at6 que o constnrtor da superclasse tenha sido exicuta do. E que esse construtor seri chamado a partir do construtor da linha 3, emvez de usar o da linha 7, alinha 8 s6 poderi empregar um m6todo para
static!
ji
gerar o nome. Se quis6ssemos que todos os animais sem nomes especificidos pelo chamador tivessem o mesmo nome padrXo, digamos, 'Fred", enteo, a linha 8 poderia apresentar thls ( "Fred" ); em vez de chamar um m6todo que retorne uma string com o nome escolhido aleatoriamente.
static
r r
Linha 12 A linha 12 nio tem nada a ver com construtores, gera um nfmero aleat6rio entre O e 4.
Linha 13 Sabemos que 6 uma sintaxe estranha. Estamos criando um novo objeto String (apenas uma instincia de String), mas. queremol gue a string seja selecionada aleatoriamente em uma-lista. 56 {ue nio temos a lista, portanto, precisamos cri6-la. Assim, apenas nessa linha de c6digo:
1. Declaramos uma vari6vel de String, nane.
3. Recuperamos a string no indice [x] (sendo x o nrimero aleat6rio gerado na linha 12) do array de String rec6m-criado.
4. Atribuimos a string recuperada no array i variivel de instAncia declarada, nama Poderiamos rer tornado a leitura mais f6cil se tiv6ssemos escrito apenas:
String [ ] namel.ist = { "F1uf fy", "Fido" , "Rover" , "Spike", ,.ciqi,'} String name = namelist [x] ;
Mys
o.ndefc-a a diuersdo?Inserir uma sintaxe incomum (principalmente par^ um c6digo que nio esteja totalmente relacionado ao cerne da questio) f.az pane do espirito do exame. Nlb fique (ceno, fique assusrado, mas "rsustlado entAo apenas diga para si mesmo: "Calma", e d prosseguimento).
Linha
18 Estamos chamando a versio sem argumentos do construtor (fazendo com que um nome aleat6rio da lista seja selecionado e passado para o outro construtor).
Linha
20
Estamos chamando o constnrtor sobrecarregado que usa uma string representandQ o nlme.
desse exemplo de c6digo esta na finha 8. Emvez de chamar super ( ) , estamos this ( ) que nmpre tWtf* una chinad.a a uatro cunstrator da mesma classe. Certo, mas o que aconteceri chimando depoisdachamada a this ( )i CJo outarde o construtor super ( ) ser6 chamado, nXo 6? L6gico..Uma. cfr"-"d" a this ( ) significa apenas que vocA esti retardando o inevit6vel. Algum construtor' em algum local, ter6 que Iazer a chamada a super ( ) . Regra chave: a primeira linha de um construtor deve ser uma chamada a super ( ) ou a thig ( ).
Sem exceg6es. Se voc6 nXo tiver nenhuma dessas chamadas em seu construtor, o compilador inserir6 a chamada
semargumenrosasuper( ).Emoutraspalavras,seoconstrutorA( )tiverumachamadaathis( ),o compiLdor saberi que ndo seri esse construtor que chamari super ( ) . A regra anterior quer dizer que um construtor nunca pode ter tanto uma chamada a super ( ) quanto a this
vilida
I . J6 que essas chamad"r p.eiim* ^.onrtrutor.
as duas
per ( )
Issb tamb6m significa que o compilador no -.r-o 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:
siirplesment. r.
.orrit-tor.r
E claro que sim. Apithafoi exndida!Elaficou maior e maior, a!6 qu9 . e o i6dig" do m6todo foi deiramado, esvaindo-se parafora daJVM e.caindo no chio. Dois robrecarregados chinando this, sio dois construtores chamando um ao outro. Repetidamente, resultando em
ibtin
* java A
Exception in thread \\main" java. Iang. StackOverflowError
O beneficio de ter consrrutores sobrecarregados 6 que voc6 oferecer6 maneiras flexiveis para a instanciagio de objetos de sua classe. A vantagem de um construtor que chame outro construtor_sobrecarregado 6 evitat a duplicaglo do c6digo. No exeLplo de Animal, nio hlvia nenhum c6digo a16m da co_nfiguragio do nome, mas i*agine se depois d-a linha 4 houvesse ainda mais trabalho a ser feito no construtor. Pela insergio de tod-as as
t"raLt
um constnrtor e, em seguida, fazendo 9om qge outros construtores o chamassem, voc6 nio teria "ttr "p6tt"r a manutengio de v6rias vers6es do c6digo desse construtor imponante. Basicamente, os que escrerrei e fazer .b.rrt*to.., que nio fossem ,.iarr"rrt., chamariam esse outro constnrtor sobrecarregado, passando para ele os
dados que precisasse (dados que o c6digo-cliente
nio forneceu).
Os construtores e a instanciagio se tornarXo ainda mais interessantes (agora que vocA achou que estava livre) quando chegarmos )s classes internas, mas sabemos q-ue voc6 s6 poder6 suportar tanta diversXo em outro capitulo, ponanro, esramos guardando o resto da discussio sobre instanciagio de classes internas para o Capitulo 8.
_
JAVA
85
1.3
do Exame)
1.3 Desenaoluer nidigo que dulare, inicialiry e use tipos primitiuos, arraJs, entlmr e objetos como uaridueis eshiticas, tle instdncias e locais. disso, usar identifcadores utilidos para nomes de uaritiaeis.
static
membrostatic
funciona,examinaremosp-rimeiro arazioparausarum. Imaginequeioc6tivesseumaclasseutilit6ria com um m6todo que sempre fosse executido da mesma mineira; sua rinica"fungio seria retornar, digamos, um nrimero aleat6rio. Independente de que instAncia da classe execure o m6todo - ile sempre se compoitari ' exatamente da mesma f-orma..Em ouiras palavras, o comporramento do m6todo nio depende do Jstado (',ralor., da variivel deinsA.ncia) de um objeto. Portanto, por que, entio, voc6 precisa de um objeto, j6 que o m6todo nunca ser6 especifico da instAncia? Por que nio apenls soii.it"t a pr6pria classe para ."...rt"r'o m6todo? Imaginemos outro cen6rio: suponha-que voc6 quisesse ter uma contagem ininterrupta de todas as instAncias criadas _a partir de uma classe ispecifi-a. Onde irmazenaria essa variivel? Nio funcionar6 mant6la em uma vari6vel de instAncia dentro da Classe cujas instAncias voc est6 registrando, porque a contagem ser6 reinicializada com um valor padrlo a cada nova instAncia.
utilitirio,
classe, emvez de a qualquer instAncia especifica. Na verdade, vocA pode usar um m6todo ou variivel sem ter absolutamente nenhuna in$incia dessa classe. 56 precisa ter a classe disponivel para poder chamar um m6todo ou acessar uma variivel As variiveis tamt6tn ier acessadas sem ter a instincia de uma classe. Mas se houver instAncias, avari|vel dessa classe ier6 companilhada por todas as instAncias da classe; s6 haveri uma c6pia.
static
sempre executado da mesma forma, quanro para a contagem As variiveis e m6todos marcados co"m
static.
static
static
static.
static static
poi.-
O c6digo
static
de contador:
class Frog
static int frogCount = 0; // Decl.ara e inicializa a vari6vel static public Frog0 { frogfcount += 1; / / Modifica o valor do const.rutor
)
frogCount 6 configurada com zero, quando a classe Frog 6 carregada pela ' a)aat (A prop6sito, ioc. nilo precisard rellmente " inicializar uma vari6vel static com zero; as variiveis est6ticas iecebem ot -"r*or-rralores padrlo que as varilveis de instAncia). Sempre que uma instAncia de Frog for criada, o construror ser6 executado e arrmlentari o valor da vari6vel est6tica f rogCount. Quando esse c6digo for executado, tr6s instAncias de Frog serio criadas
instdncia de Frog rc1a
No c6digo anterior, a vari|vel static priqgira vez pela JVM , antes que qualqaer
emmain( ) e o resultadoser6:
Frog count
esse
is
now
se
ndofosse
unidc):
c6digo for executado, ainda criari tr6s instAncias de Frog em main ( ) , mas o resultado seri... Um Quando erro do compilador! Nunca poderemos fazer esse c6digo ser executado, porque nem ele mesmo ser6 compilado.
class Frog
i nf nrrhlin
{
\ / /L r,1. r, n.
// DecTara e inicializa
a vari6vel
de instAncia
fr^d/l^rrnf rrvvvvsrrL
)
1
86
Frogo;
new FrogO;
AJVM nio sabe que objeto Frog de frogCount voc6 est6 tentando acessar. O problema 6 que opr6prio m6todo main ( ) E estitico ., po.t*to, nio e# sendo"executado em relagio a lenhuma initAncia espegiTil" 4 classe, em vez disso est6 relacionadb apenas a classe. Um m6todo static nXo pode acessar uma vari6vel (de instincia) nlo static,
porque
ndo b,l ana instincialSem
falar que nio h6 instincias da-classe ativa na mem6ria e, mesmo se houvesse, o m6todo O mesmo se aplica a m6todos de instAncia; um m6todo static nio pode "trti. chamar diretamente um m6todo nio staLic. Considere static : classe, nlo stat.ic : instlncia. Tornar o m6todo chag{9 pelaJVM-(main ( ..)) static significa que aJVM nio teri que criar uma instAncia de sua classe apenas para iniciar a execugio do c6digo.
nio
oBSERVAQ6ES
pene O EXAME
cometidos
aaiiaelndostatic) apartirdomitodomain( )
i
um exenpk
de
tenlar
acessar
una uarihuel
de
(quendotennenhamainfomag1osobrein$incias,prrtantz,ndopodeaeessara acesso inudlido de ama aaidael ndo sLaLic a partir dt um mitodo s tat i c.'
class Foo { int x = 3; public static void main (String [] args) System.out.println("x j-s " + x) ;
)
bon qae aoc6 saiba qae use aidigo nunca uri compilado, porque n6o 6 possiuel
acessar
sEaLic
(de instdnciQ
patir
de um mitodo
static.
a
exibir!"
I-,embre-rc de qae
mitodomain
( |
'Ei,
perglnta
a
sLatic
paftir
6bria quanto o c1digo anterior. O problena sobre o qual uocd estari sendo aualiado acesiar tlma senl. canuflado no aidigo qle pareceni aaa/iar oatra qautdo, Por exempk, seria de am mitodo
static
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
x ey
ndo
de
static
Jriquevocnioprecisaterumainstinciaparachamarumm&odostatic ouacessarumavai|velstatic,entio, iomo chamar6 ou usar6 um membro st;tic? Qual 6 a sintaxe? Sabemos que para um m6todo de instAncia comum, voc6
a
uma instAncia:
int frogSize =
nrrhlia vgvf!v+fr9Yv9rrvVv*!v\, in{-
0;
I
aat-FranQizaI\
return frogSize,'
JAVA
87
public static void main (String [] args) { Frog f = new Frog(25); System.out.println(f.getFrogsizeO);
)
getFrogsize ( )
na instdnciaFrogque acabartos
Mas essa abordagem (usar a refer6ncia a um obieto) nio 6 apropriada para acessar um m6todo static. Doroue ' pode nio haver absolutamente nenhuma insdncia da classei Portanto, a maneira de acessarmor .rm -6ioldo static (ou vari6vel static) serl usar o operador ponto n0 nome da classe, e nio na refer6ncia a uma instAncia, como vemos abaixo:
c]ass Frog { static int frogCount = 0; // Dec]ara e inicializa a vari6vel static public rrog O t frogCount += !; / / Modifica o valor do construt.or
]
c]ass TestFrog { public static void main (Stri_ng [] args) { new FrogO; new FroqQ; new FrogO; System.out.print("frogCount: "+Froq.frogCount.); //Acessa a vari5vel static
l
Mas apenas. p ar.a.tornar isso realmente confuso, a linguagem Java tamb6m permite que voc6 use uma uai,iuel de referncia de objeto para acessar um membro static:
Acessa o m6todo
est6tico getFrogCount
usando
esse novo objeto a variivel de refer0ncia f e, em seguida, usamos a referAncia I para charnar um m6todo Mas mesmo que tenhamos usado uma instAncia especifica de Frog.para acessar o m6todo static,-as^regras nio.foram alteradas. Isso 6 simplesmente um truque de sintaxe para permitir que voc6 ase rrma uariduel de refer6ncia de objeto (mas nXo o objeto que ila referencia) pari acessar uma variivel ou m6todo mas o membro stat.icainda nio tem conhetimento da instAncia especifica usada para cham6lo. No exemplo, o compilador sabe que a refer6ncia 6 do tipo Frog e, porranro, o m6todo da classe Frog 6 executado sem conhecer ou se preocupar com a instAncia na outri exremi&de da refer6ncia f. Em outras palavras, o compilador s6 se preocupari com o fato de a referdncia ser declarada com o tipo Frog. A Figura 2-8 ilustra os efeitos do modificador sobre m6todos e variiveis.
static!
static,
static
stat.ic
Outro ponto
a lembrar 6 que os n,itodos ndopodem sersobrecarregadar! Isso nXo significa que eles ser redefinidos em uma subclasse, mas redefinir e sobrecarregar ndo sio a mesma coisa.
static
nio possam
static
88
/
;
System.out.print ( "d
)
")
public static void main(string [] args) { Animal tl a = {new Animal O , new DoSO ' new Animal for(int x = 0,' x < a.length; x++) alxl.dosuuf,f Ot | / cli;ama o m6todo static
)
)
};
Lembre,
sintaxe a
disso,algocomoAnimal
[x] .doStuf f ( ) 6 apenas um atalho (o truque da sintaxe)... O compilador usar6' emvez .doStuff O.Reparequenlousamosaquioloop for apimoradoloJava1.5
t6lo feito. Espere ver uma mistura
(abordaJo no Capitulo 5), embora pud6ssemos pr6ticas deJava 1.4 eJava 5 no exame.
de estilos de programaglo e
classe Foo int size = 42; slatic void doMore( ){ int x = sVe;
]
variivel de inst6ncia
(nio-static)
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 .
de cara. As definig6es do exame da Sun para coeslo e acoplamento gi9 u-m tanto subjetivas, de 6 do ponto de,vista do exame, que nio 6 de forma nenhuma a verdade absoluta sobre esses dois principios OO de projetos. Pode nio ser exatamente a forma como voc6 os aprendeu, mas 6 o que vocA precisa entinder para responder as quest6es. Haveri bem poucas quest6es sobre acoplamento e coesio no exame real.
JAVA
89
t6picos, acoplamento e coesio, t6m a ver c.om a qualidade de um projeto oo. Em geral, o bom projeto e evita o fofte, e pede tamb6m aha coetdo e evita a baixacoesio. ComJ na maioria ias' drscuss6es sobre projetos OO, os objetivos para a aplicaqio sio
r I r
Acoplamento
Vamos comegar f.azendo uma tentativa de definigio
do_
as classes 6 mais forte... E isso nlo 6 bom. Em outras palavras, se qual B foi implementada, entio A e B t6m acoplamenio forte.
conheceoutraclasse.Seorinicoconhecimentoque.aclasseAtemsobreaclasseB6oqieaclasseBexp6satrav6s dasua interface, entio diz-se das classes A e B qui-elas t6m acoplamento fraco... E isso 3 bom. Se, por o^utro lado, a classe A,depende de panes da classe B quc nib fazemparte da interface da classe B, entio o
lJsandocste segundo cenirio, imagine o que acontece quando a classe B 6 aprimorada. E bem possivel que o desenvolvedor que esteja aprimorando.a classe B ne* saib" da exist6ncia da classe A, afinal po. qrr. dev'eria? O desenvolvedor da classe B deve panir do principio que quaisquer melhorias que nio danifiqfuem a interface da classe deverlo ser seguras, entio.ele pode modificar pirte da classe que nlo se refira ) interface, o que
entio
f.az a classe
ser danificada.
"lg,rm"
Opiorcasopossivel6ahorrivelsituagioemqueaclasseAsabedecoisasnio-relativas)APlsobreaclasseB,ea B sabe de coisas nio-referentes i API sobre a classe A... Isso 6 MUITO RUIM. Se qualquer uma das claises for modificada, 6 possivel que a outra seja danificada. Vejamos um exemplo 6bvio de ..opl"-.rrto fone, que
classe
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
) )
| oh nAo, de novo
Todas as aplicag6es OO nietriviais slo uma mistura de muitas classes e interfaces rabalhando juntas. O ideal seria que todas.as interag6es entre objetos em um_sistema OO usassem as APIs, ou seia, os contratos, das respectivas'classes
dos objetos. Teoricamente, se todas as classes de uma aplicagio tiverem APis bem elaboradas, entXo deveria ser possivel que todas as interag6es interclasses as usassemtxclusivamente. Como discutimos anteriormente neste capitulo, um aspecto do bom projeto de classes e de APIs 6 que as classes devem ser bem encapsuladas.
exemplos realmente 6bvios de acoplamento forte; nio lhe ser6 pedido que faga julgamentos sutis sobre o assunto.
Coesio
Enquanto que o acoplamento tem a ver com a forma como as classes interagem umas com as ouuas, a coesio se refere a como uma determinada classe foi elaborada. O termo coudo 6. usado para indicar o grau em que uma classe tem um rinico e
'ld;ri:':::T*::::.i.
{
void saveToFil-eO { void print0 { }
j } }
Agora imagine que o seu gerente chegue e diga "Ei, sabe aquela aplicagio de contabilidade em que estamos tribalhand6t Oiclientes icabaram dJdecidiique eles tamb6m vio querer gerar um relat6rio de projegio de receitas, ah, e eles tamb6m querem fazer alguni relat6rios de inventirio._Mas eles gostaram dos nossos recursos de relat6rios, entio certifiqu.-r. d. que todos-esses relat6rios permitam a eles escolher um banco de dados, escolher uma impressora e salvar os relat6rios gerados em arquivos"... Oh, nXo.
Em vez de colocar todo o c6digo de impressio em uma s6 classe de relat6rios, provavelmente ser6 melhor usar o seguinte projeto desde o comego:
classe que faz tudo, dividimos o sistema em quatro classes principais, ca& .rm papel bastante especifico, ort clero. Uma vei que n6s construimos essas classes esp eirafizadas e reuttlrzl.veis, serl muito rnaii f6cil .t..err.i um novo relat6rio, vmavez que j6 temos a classe para a conexio ao banco de dados, a classe para impressXo e a classe que salva os arquivos, e isso significa que elas podem ser reutilizadas Por outras classes que possam querer imprimir um relat6rio.
tr-" iom
a sobrecarga ,o
e os
constnrtores'
a
Abordamos E-UM e TEM-IIM. n-UVt 6 implementado usando-se variiveis de instAncias para se referirem a outros objetos.
O polimorfismo veio em seguida. Embora o tipo de uma variivel de refer0ncia nio possa ser modificado, ele pode ser cujo tipo seja um subtipo do seu pr6prio. Aprendemos como determinar quais m6todos sio invociveis para determinada variivel de referOncia.
JAVA 5 Examinamos. a diferenga entre m6todos sobrescritos e sobrecarregados, aprendendo que o m6todo sobrescrito ocorre quando umasubclasse herda o m6todo da superclasse, e, entio, o reimpleme ni^ p^r^adicionar um comPortamento mais especializado. Aprendemos que no tempo de execugio, a JVM chamar6 a versio da subclasse em uma instAncia dessa subclasr. . .rr.rr^io da superclass" .* u*" instAncia da superclasse. Os " m6todos abstract deuem. ser.sobrescritos (ncnicaruente os m6todos abstract devem ser ifihnentados, endo
9I
Vimos que os m6todos novos devem manter a mesma lista de argumentos e tipo de retorno (ou, do Java 5 em diante,, eles podem retornar um.subtipo do tipo de retorno decllrado do m6todo sobrescrito da srp.rclasr.f do m6todo sobrescrito e que o modificador de acesso nio pode ser mais restritivo. O m6todo nono t"-b6* nio pode langar nenhuma excegio verificada nova ou mais abrangente que nlo tenha sido declarada no m6todo ,obr.rcrito.
Voc6 tamb6m aprendeu que o m6todo sobrescrito pode ser chamado com o uso da sintaxe
super.doSomething(
;.
Os m6todos sobrecarregados permitem que voc6 reutilize o mesmo nome de m6todo em uma classe, mas com argumentos diferentes (e op.cionalmente, um tipo deretorno diferente). Enquanto os m6todos q,a,e sobrcsTeuem outros ndo devem alterar a lista de argumentos, os m6todos sobruanegaiot preiso, faz|-lo. Por6m, diferente dos m6todos novos, os sobrecarregados podem variar o tipo de retorno; o modificador de acesso e as exceg6es declaradas da maneira desejada. Aprendemos o funcionamento da conversio (em geral redutora), das vari6veis de referdncia, quando ela necess6ria e cemo usar o operador insLanceof .
6
A implementagio
de interfaces veio em seguida. As interfaces descrevem um contrato que a classe implementadora deve segu.ir. As regras para s implementar uma interface sio semelhantes )quelas p".a i. estender rr*" .lass. abstract. Lembre-se tamb6m de que uma classe pode implementar mais d. n*" interface, e que as interfaces
Tamb6m examinamos os tipos de retorno dos m6todos, e vimos que voc6 pode declarar o tipo de retorno que quiser (supondo-se. que tenha acesso a uma classe para usar um tipo de retorno de refer6ncia a objeto), *.not que esteja sobrescrito um m6todo. Com a excegio de um retornocovariante, um m6todo novo deve ier" o mesrrro tipo de retorno do m6todo sobrescrito da superclasse. Vimos que enquanto os m6todos novos ndodevem alterar o tipo de retorno, os sobrecarre gados poden fai-lo (contanto que tanbi) alterem a lista de argumentos).
Para concluir, voc6 aprendeu que 6 vilido retornar qualquer valor ou variivel que possa ser implicitamente convertido no tipo-de retorno declarado. Portanto, pbr eiemplo, short pode ier ietornado quando o tipo de retorno declarado for um int. E uma referAncia a Horse pode ser retornada quando o tipo de-retorno declarado for um objeto Animal (supondo que Horse estenda Animil).
Abordamos os constftrtores em detalhes, aprendendo que, se voc6 nio fornecer um construto r para a sua classe, o compiladorinserir6um. O construtorgeradopelo compilidor6 chamado de consrrutorpadrio, e6 sempreumcon$ruror sem argumentos com uma chamada sem argumentos a super ( ) . O construtor padrionunca seri gerldo se houver um s6 construtor que seja na sua classe (independentemente dos argumentos que ele r.rse), entio, se voc6 lrecisar de mais de um constnrtor na sua classe e_quiser usar um sem argumentos, ter6 de escrevA-lo voc6 mesmo. Tamb6m vimos que os constnrtores nio sio herdados, e que voc6 pode se confundir com um m6todo que tenha o mesmo nome da classe (9 lue_6 vilido). O tipo de retorno indica que um m6todo nio 6 um consrruror, uma vez que este riltimo nio tem tipos de retorno. N6s vimos como todos os construtores da 6rvore de heranga de um objeto serio sempre chamados quando o o.bjel^g 6 instanciado usando-se new. Tamb6m vimos que os construtores podem ser sobrecarregados, o que significa definir construtores com listas de argumentoi dife.etrt.r. Um construtor pode chamaioutro dimesma classe com a palavra-chave this O , como se o constnrtor fosse um m6todo chamado this O . Vimos que todo construtor precisa ter ou this ( ) ou super ( ) como a sua primeira instrugio.
Vimos os m6todos
e variiveis static. Os membros static se associam ) classe, e nio a uma instAncia, de modo que s6 existe uma c6pia de cada membro static. lJm erro comum 6tentar referenciar uma variivel de instancia a partir de um m6todo static. IJse o nome da classe com o operador ponto para acessar membros
static.
a objetos, que sio o acoplamento e a coesio. O acoplamento fraco,6 o estado desejivel para duas ou mais classes que-interajam rrriras.orn as outras atrav6s das zuas_respectivas APIs. O acoplamento fone 6 o estado indesej6vel para duas ou mais classes que conhegam detalhes internos sobre outra classe, detalhes nio revelados na API da classe. A alta coesio 6b estado desei6vel para uma classe cujos prop6sitos e responsabilidades sXo limitados e bem focados.
E, s6 para lembrar, vocA aprendeu que o exame inclui perguntas ambiguas, elaboradas basicamerite para restar sua habilidade no reconhecimento do quanto elas podem ser enganosas.
Exercicios r6pidos
Aqui
estXo alguns dos pontos-chave de cada objetivo para certificagio deste capitulo.
92 Copitulo 2: OrientoE6o
o obietos
E tr
O encapsulamento
tris
API)'
E E E E E tr
private).
) heranga.
extends.
de outra classe, ou a outra
de" e "6 um subtipo de" sio todas express6es equivalentes. a instincia de uma classe
D A heranga 6 um mecanismo que permite que uma classe seja uma subclasse de outra,
variiveis e m6todos da superclasse.
D A heranga 6 um conceiro
sobrecarga e da conversio.
fl
ob-
E U E E E E
D O
um objeto do subtipo.
Um mesmo objeto pode ser referido por vari6veis de instAncias de muitos tipos diferentes sejam do mesmo tipo ou de um supenipo do objeto. O tipo
da
variivel
de refer6ncia
ser chamados!
abstrac L
a
deuerz
(nio
abstract).
E D
O
Deve ter
subclasse
Deve ter o mesmo tipo de retorno, exceto pelo fato de que, em Java 5, o tipo de retorno pode ser uma isso 6 conhecido como um retorno covariante.
tr Nio pode langar exceg6es verificadas novas ou mais abrangentes; tr Pode langar exceg6es verificadas mais restritivas ou menos abrangentes,
verificada.
E tr E fl
Os m6todos f
inal
nio podem
ser sobrescritos.
private
da superclasse de um
EJ Sobrecarga significa reutllizar o mesmo nome de m6todo, mas com argumentos diferentes.
Os m6todos sobrecarregados:
D fl
El
JAVA
93
E tr
Q
os m6todos de uma
O polimorfismo
O tipo de objeto
cte execugao.
(e
6 aplicivel
sobrescrigio e
nio )sobrecarga.
determina qual m6todo sobrescrito seri usado no ternpo
ser6 usado no tempo de compilaglo.
nio o tipo
da vari6vel de referncia)
tr E E 0
Conversio redutora: se voc6 tiver uma vari|vel de referAncia que aponte para um objeto de um subtipo, poder6 atribui-la a uma vari6vel de refer6ncia do subtipo. Voc precisa f^ie, u iconversio explicita p"." iso, I o resultado 6 que voc6 pode acessar os membros-do subtipb com essa nova vari6vel de referAncia. Conversio ampliadora: voc6 pode atribuir uma vari6vel de referAncia a uma varibvel de referAncia de um supenipo explicita.ou implicitamente. Essa 6 uma operagio inerentemenre segura porque a atribuigio restringe as capacidades de acesso da nova variivel.
fl tr E fl E D E tr tr E E E E
Voc6-implementa uma interface ao sobrescrever apropriada e concretamente todos os m6todos definidos pela interface.
nul-L
Para m6todos com tipos de retorno primitivos, pode ser retornado qualquer valor que possa ser converrido implicitamente para o tipo de retorno.
Nada pode ser retornado
a partir de um void, mas voc pode decidir nXo retornar. E permitido que voc6 use em qualquer m6todo com um tipo de retorno void, para inierrornper um m6todo antes da sua finalizagio. Mas nio 6 possivel retornar nada a panir de um m6todo com um tipo de retorno nio-void.
simplesmente
return,
M6todos com um tipo de retorno que M6todos com um tipo de retorno que
6 6
uma referOncia
Toda superclasse da 6rvore de heranga de um objeto chamari um construtor. Toda classe, mesmo
as classes
abstract,
D Os construtores devem ter o mesmo nome da classe. E Os constnrtores nio t6m um tipo de retorno. Se houuer,entio, seri simplesmente um m6todo
da classe e
nio um construtor,
da maneira a seguir: de sua superclasse, que chamar6 o
e assim
por
E O construtor de Object seri executado, retornando em seguida ao construtor chamador, que ser6 processado at6 sua -eqii6nCia conclusio, e por sua vez retornar6 ao construtor que o chamou; dando prosseguimento a essa at6 a execugio
do construtorda instAncia que estiver sendo criada.
E E E E
private!).
super
O compilador criar6 um co nfirutor padraose voc6 nio criar nenhum construtor em sua classe.
O construt or padrdo
wconstrutor
de
).
A primeira instrugio
super
) (um construtor
sobrecarregado) ou
).
tr
D E D B
),a
).
Os membros de instAncia s6 podem ser acessados dqoir de o construtor da superclasse ser executado' As classes
possuem constnrtores que sio chamados quando uma subclasse concreta 6 instanciada.
D tr E
Um constnrtor
rhis (
s6 pode ser chamado diretamente por outro constnrtor (usando uma chamada a
super
( ) ou
)).
this (
):
tr B
O
O A lista de argumentos
Os construtores podem chamar outros construtores que podem chamar-ainda ourros eassim por diante; mas, cedo ou iarde, 6 melhor que un deles chame super ( ) ou a pilha excederi o limite.
Chamadas a
nunca os dois.
que
nio
i instAncia - s6 existiri uma static. E Todos os membros static pertencem i classe, e nio a uma instAncia. tr Um m6todo static nio pode acessar uma vari6vel de instincia diretamente. E Use o operador ponto para acessar membros esteticos, mas lembre-se de que usar uma,variivel de refer6ncia
paraarmazonar dados que sejam especificos ) classe, em vez de Use variiveis c6pia de uma vari6vel
static
o op.t"dor na verdade
variivel
de referAncia pelo
d.doStuff O ; se torna:
Dog.doStuff ( ) ;
M6todos
static
nlo podem
D O acoplamento refere-se ao nivel em que uma classe conhece ou usa membros de uma outra classe. fl O acoplamento fraco 6 o estado desejivel para classes bem encapsuladas, que minimizam as referAncias umas is outras e
limitam a extensio do uso
da
API.
indesejivel de
se
E D E
D
O acoplamento forte
6 o estado
A coesio refere-se ao nivel em que uma classe tem um rinico A alta coesio
6o
estado desej6vel de uma classe cujos membros dio suporte a um rinico e bem definido papel ou
de uma classe cujos membros
responsabilidade.
Teste individual
l. Quais afirmativas sio verdadeiras? (Marque todas as corretas) A Os relacionamentos Tem-Um sempre dependem da heranga.
B.
Os relacionamento Tem-Um sempre dependem das vari6veis de instAncias.
JAVA
95
E. Os relacionamento Tem-Um
2. Dado:
public class Clidlets extends Clidders { public void flipperO { System. out.println ( "Flip a Clidlet" ) ; super. flipper O ;
]
E. A compilagio falha
3. Dado:
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 {
{ }
E. public class Frob implements Frobnicate public void twj-dd1e(String i) { } public void twiddl-e(Integer s) { }
96 Copitulo 2: Orientogoo
4. Dado:
o obietos
pubfic class Bottom2 extends Top { public Bottom2 (String s) { System.out.print("D") ; public static void main(String [] args) {
new Bottom2 ( "C" ) ;
] Qual 6 o resultado?
falha.
5. Selecione as duas afirmativas que melhor indiquem uma situagio com baixo acoplamento. (Marque duas)
,4.
Os atributos da classe sio todos privados.
refere-se
a
B. A classe
D. O objeto 6 referido
de m6todos.
E. Avari6veldereferAncia6declaradaparaumtipodeinterface,enioumaclasse.Aintertacef.orneceumpequenonimero
E
F
14.
improvivel
{
}
private final- void flipperO { System.out.prj-ntln(..C1idder,'l; public class Clidlet extends Clidder { public final void flipperO { System.out.println("C1idlet"); public static void main(String [] args) { new Clidlet ( ) . flipper( ) ;
)
)
Qual6 o resultado?
,{. Clidlet
B. Clidder
JAVA
97
7. Usando os fragmentos abaixo, complete o seguinte c6digo de forma que ele compile. ObseruagSo, talvez nio seja preciso preencher todos os espagos em branco.
C6digo:
public Kinder(int x)
j
)
o;
Fragmentos: Use cada um dos seguintes fragmentos quantas vezes for preciso, ou deixe sem uso: AgedP
(
this
)
8. Dado:
1. class Plant { 2. String getNameO { return "p1ant"; 3. Plant getTlpeO { return this; } 4. ) 5. cl-ass Fl-ower extends Plant i 6. // insira o c6digo agui 8. class Tulip extends Flower {
Quais instrug6es, inseridas na linha 6,
}
irio compilar?
(Marque todas
as
corretas)
,{. Flower getTlpe| { return this; } B. String getTlpeO { return "this"; } getTypeO { return this; } C.Plant D. tulip getTlpe0 { return new Tulip0;
9. Dado:
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.
6-umWoop.
1. class Programmer { 2. Progranmer debugrO { return this; } 3. ) 4. class SCJP extends Programmer { 5. // jtnsira o c6digo aqui 6. ) Qual op91o, inserida na linha 5, iri compilar? (Marque todas as corretas) A. Programmer debug ( ) { return this,' } B. SC.fP debugfo { return this; } C.object debugr0 { return this; } D. i-nt debug ( ) { return 1; } E. int debug(int x) { return l-; } F.Object debug(int x) { return this; }
I
l. Dado:
class Uber {
class Minor extends Uber i Minor0 { super(y) ; y = y + 3; } public static void main(String [] arqs)
na\^t Mi nnr 1\
.
System.
out.println (y)
])
Qual6 o resultado?
A coesio
6o
principio
da
implementa$o.
B. A coesio
6 o principio da programagio OO mais intimamente associado com o ato de certificar-se de que as classes s6 conhecerlo outras classes atrav6s da" suas APIs.
coesXo 6 o
de que a classe
foi
permitir
que um mesmo
JAVA
99
13. Dado:
DoS
4. class Kennel { 5. public static void main(String [] arfs) Beagrle b1 = new Beagle ( ) ; 6. 7. Dog dogl = new DogO; Dog dog2 = b1-; 8. 9. // insira o c6digo aqui 10. ) )
Qual opgio, inserida na linha 9, ir6 compilar? (Marque todas
as corretas)
A. Beagle b2 = (Beagle) dogl; B. Beagle b3 = (Beagle) dog2; C. Beagle b4 = dog2; D. Nenhuma das instrug6es acima irl compilar.
14. Dado o seguinte c6digo,
4. class Chrome { 5. public static void main(String [] args) X x1 = new XO; 6. X x2 = new yO; 7. Y yl = new YO; 8. 9. // inslra o c6digo aqui 10. ) )
Qual opgXo, inserida na linha 9, ir6 compilar? (tr4arque todas
as corretas)
Respostas
1
Best6correta.
A e D descrevem outros t6picos relativos ) programagXo OO. C est6 incorreta porque uma classe pode ter uma instAncia de simesma. E estiincorretaporque, enquanto relacionamentostem-umpodemlevar aum acoplamento forte, nio 6 sempre que isso ocorre. (Objetivo 5.5)
3.
B estl correta, uma classe abstract nio precisa implementar quaisquer m6todos de uma interface.
E esti correta, a classe implementa o m6todo da interface e, adicionalmente, sobrecarrega o m6todo
twiddle
()
abstract
nio
as estendem.
D
4.
5.4)
E est6 correta. A chama implicita a super ( ) no construtor de Bottom2 nlo pode ser satisfeita, porque nio hL um constnrtor sem arg.rmentos em Top. lJm construtor padrlo, sem argumentos, 6 gerado pelo compilador somente se a classe nio tiver nenhum construtor definido explicitamente.
base
E e F estio corretas. O fato de se ter acesso a um pequeno nrimero de m6todos implica um acoplamento limitado. Se o acesso 6 feito atrav6s de uma referAnia do tipo interface, pode-se argumentar que existem ainda menos oponunidades para o acoplamento , umavez que o pr6prio tipo da classe nio se encontra visivel. Dizer que modificag6es em uma parte de um programa provavelmente nio causario conseqiiOncia em outra, 6 realmente a essncia do acoplamento fraco. Nlo existem variiveis an6nimas. Referir-se apenas a um pequeno nrimero de outros objetos poderia implicar um acoplamento fraco, mas se cada objeto tiver muitos m6todos, e todos forem usados, entio o acoplam-nto seri forte. As vari6veis (atributos) de uma classe devem normalmente ser private, mas isso descreve o encapsulamento e nXo o baixo acoplamento. E claro que um bom encapsulamento tende a reduzir o acoplamento, como conseqii6ncia.
base na tese de
A esti correta. Embora um m6todo f inal nio possa ser sobrescritos, neste caso o m6todo 6 private, portanto, escondido. O efeito 6 que um novo e acessivel m6todo f lipper 6 criado. Assim, nXo ocorre
B, C, D
e
polimorfismo neste exemplo; o m6todo chamado 6 simplesmente o da classe-child, e neo ocorre nenhum erro.
E estio incorretas com base no exposto acima. (Objetivo 5.3)
Como nio existe um tile descan6vel para avari|vel x e os par6nteses (no constnrtor Kinder) j6 estio no seu lugar e estio vazios, nio 6 possivel criar uma chamada ao construtor da superclasse que usa um argumento. Poftanto, a rinica possibilidade restante 6 criar uma chamada ao construtor sem argumentos da superclasse. Isso 6 feito assim: super ( ) ;. A linha nio pode ser deixada em branco, uma vez que os par6nteses j6 estio no lugar. Al6m disso, uma vez que o construtor da superclasse chamado 6 a verslo sem argumentos, esse construtor precisa ser criado. Ele nio seri criado pelo compilador porque jl existe um outro construtor. (Objetivo 5.4)
A, C
subtipos de
Plant.
Flower
Tulip
sio ambos
B est6 incorreta,
String
1.5)
herda um
Hmpf
de
zing.
5.5)
l0.A,B,EeFestiocorretas.AeBsioexemplosdesobrescrigXo;especificamente,B6umexemplode
sobrescrigio usando-se um retorno covariante. E e F sio exemplos de sobrecarga.
sobrecargas
argumentos nio
se
lL
base no
A resposta C est6correta.
A
13.
refere-se ao
A e B estio corretas. Entretanto, no tempo de execugio, A langari uma ClasscastException porque refere-se a um objeto Dog, o qual nio necessariamente s ericapaz de realtzar tarefx deBeagle.
C
e
dogl
14. C est6 correta. Para poder chamar o m6todo do2 de v, voc6 precisa converter x2 para que ele se torne do tipo Y. A instrugio B parece ser uma conversio correta, mas, sem o segundo conjunto de pardnteses, o compiladorpensari que se trata de uma instrugXo incompleta.
A, B
AtribuiE6es
individuol
Pilha e Heap
Para
a
- Uma Revisio
virias partes (m6todos, variiveis
e
maioria das pessoas, entender os fundamentos sobre a pilha e o heap facilita bastante a comPreensio de t6picos passage* d. o polimorfismo, threads, exceg6es e coleta de lixo. Nesta segio, nos limitaremos a uma "rg.r*.ntos, visio geral, mas expan&remos esseJt6picos virias vezes ao longo do livro. como
a
No gerd,
objetos) dos programas emJava residem em um dos dois seguintes lugares da riem6ria, a pilha ou o heap. Por agora, nos preocuparemos apenas com tr6s tipos de coisas: varilveis de instAncias,
as
I r
Asvarilveislocaisresidem napilha.
e
7.
B.
Dog d; / / vari1vel 1oca1: d 9. l-0. d = new DogO; i-1. d.so(d); 1.2. ] 13. void go(Dog dog) { // vari6veL Local: dog L4. c=newCollaro; 1-5 . dog. setName ( "Fido" ) ; 16. ) I7. void setName(String dogName) { / / variSvel local: dogrName 18. name = dogName; 19. / / faz mais coisas 20. ) 21.. j
A Figura 3-1 mostra o estado da pilha
alguns pontos principais:
e
linha
19.
Em seguida, apresentamos
objeto
String
dogName
name
dog
main
()
pbleto co11ar
Figuro
3-l
JAVA
IO3
Depois que a Linha 19 fnal:.aa, setName ( ) termina e 6 removido da pilha. Nesse ponto, avari6vel local dogName tamb6m desaparece, embora o objeto String ao qual ela se referia ainda esteja no heap.
I r r I r r r r I I I
LinhaT-main ( ) 6colocadonapilha.
Linha 9 - a variivel de referAncia
d
6
10
1
criado,
de referAncia
go
()
13 14
criado no heap,
Dog.
- a variivel
de
se
re{ere ao objero
String.
aiko.
Repare que duas vari6veis locais difermtesreferem-se ao mesmo objeto oo9r. Repare que uma vari6vel local
e
e use
e objetos romo
e locais.
Ahm disn,
os de
atribaigdo (initados a
=, *=, -=)...
// char literal 42 // inE literal false // booTean literal 2546789.343 // double literal
-b'
Literais inteiros
tr6s maneiras de representar nrimeros inteiros na linguagemJava: decimal (base 10), octal (base 8) e hexadecimal (base A maioria das perguntas do exame que envolve literais inteiros usa representag6es decimais, mas vale a pena estudar para as poucas que usam a representagio octal ou hexadecimal. Mesmo com as chances de voc6 algum dia usara representagXo octal no mundo real, sendo extraordinariamente pequeni$, elas foram incluidas no exame apenaspor dversao.
16).
Hi
Literais
Os inteiros decimais nio precisam de explicagio; voc6 os tem empregado desde a primeira s6rie escolar chances de que os esteja usando, j6 que voc6 nio preenche seus cheques em notagio hexadecimal. (Se exiuerfaqgndoisso, nlo se preocupe, h6 um grupo de Nerds An6nimos (NA) pronto para ajudar). Na linguagemJavao eles sio representados da maneira tradicional, sem prefixo de nenhum tipo, como descrito a seguir: ou at6 antes disso.
decimais
Hi
int length =
Literais
inclusio
343;
6
octais
de
Os inteiros octais usam somente digitos de 0 a7 .Emlava, o inteiro um zero na frente do nrimero. como vemos abaixo:
class Octal { public static void main(String [] args) t int six = 06i // Igual ao 6 decimal int seven = 07; / / Igual ao 7 decimal int eight = 010; // IguaI ao 8 decimal int nine = 011; / / Igual- ao 9 decimal
Observe que quando passamos do sete e nio temos mais digitos para usar (s6 podemos usar os digitos de 0 a 7 nos nrimeros octaii), voltamos ao ponto de partida,ewznro 6, adicionado ao inicio do nrimero. Voc6 pode ter at62t digitos em um n6mero oaal, nio incluindo o zero inicial. Se executarmos o programa anterior, ele exibiri o seguinte:
Octal 010 =
is (hexnaabreviatura) slo construidos com o uso de 16 simbolos distintos. J6 que nunca foram inventados simbolos num6ricos unit6rios para os algarismos que vlo de 10 a L5, usamos
Literais hexadecimais Os nrimeros hexadecim
caracteres alfab6ticos para representar esses digitos.
A contagem
0L23456'789abcdef
A linguagemJava aceita letras mairisculas ou minrisculas para os digitos adicionais (um dos poucos momentos em que nXo diferencia mairisculas de minusrohr!). Voc6 pode us ar fie 76 didtos em um ndmero hexadecimal, nlo incluindo o prefixo Oxou a extensio do sufixo opcional I. que serlo explicados depois. Todas as atribuig6es hexadecimais a seguir sio vilidas:
class HexTest { public static void main (String [] args) int x = 0X0001-; int v = }xlfffffff; in|' z = 0xDeadCafe; System.out.println("x = " + x +
) )
A execu$o
de
HexTest produziria
a saida
abaixo:
x = 1 y = 21,4'1483647 z = -559035650
Nio
se
deixe enganar por alterag6es nas letras maiusculas de um digito hexadecimal ou do 'x' que o preceder6. 'Tanto
0xcafe
siov6lidos.
especificados como
literais inteiros (octal, decimal e hexadecimal) sio definidos como int por padrXo, mas tamb6m podem ser long com a inclusio de um sufixo L ou 1 depois do nrimero:
double d = 11301-874.9881-024:
No exemplo anterior,
double
f
loat
o nime ro I1,3QI87 4.9881024 6 o valor literal. Os literais de ponto flutuante sio definidos como (64 bits) por p adrio, ponanto, se vocA quiser atribuir um literal de ponto flutuante a.umavariSvel do tipo (32 bits), tenl que anexar o sufixo F ou ao nimero. Se nio o fizer, o compilador reclamar6 de uma possivel
falta de precisio, porque voc6 estari tentando inserir o nrtmero em um "contAiner" (potencialmente) menos preciso. O sufixo F fornece uma maneira de voc6 informar ao compilador: "Ei, sei o que estou fazendo e correrei o risco, muito
obrigado".
float f = 23.467890; // zrro de compilador, possivel perda da precisdo ffoat s = 49837849.029847F; // ox; possui o sufixo "F"
Opcionalmente, voc6 tamb6m pode anexar um D ou
d a literais double,
mas
nio
6 necess6rio,
pois esse 6 o
compoftamentopadrio.
double d = 110599.995011D; // opcional, n5o 6 obrigat6rio double S = 987.89'7; // Ndo 6 um sufixo 'D', mas est6 OK, pois 6 um literal- double
Procure literais num6ricos que incluam umavirgula, por exemplo,
int x = 25,343; //
Nd.o
JAVA5 IO5
Literais booleanos
Os literais
definido como
booleanos sio a representaglo do c6digo-fonte para valores boolean. Um valor boolean s6 pode ser true ou f alse. Embora em C (e algumas outras linguagens) seja comum o uso de nrimeros para
rePresentart.rue oufalse,isondofuncionaniemJaua.Novamente,repitacomigo,Javanio6C++".
simples.
chara=0x892; //literalhexadecimal char b -- 982; // literal inteiro char c = (char) 70000; // A conversS.o 6 necess6ria; 70000 est6 fora do intervalo char char d = (char) -98; // Absurdo, mas v61ido
E
as
produzirlo erros
de
compilador:
// Possivel perda de precisSo; precisa de uma conversSo // Possivel perda de precisSo; precisa de uma conversSo
se quiser representar um caractere que nio possa ser digitado como um literal, alimentaglo de linha, nova linha, tabulagio horizontal, backspace e aspas simples e duplas.
Agora que voc6 est6 familiarizado com os tipos de dados primitivos e seus intervalos, precisa ser capaz de identificar o tipo de dado apropriado a ser usado em uma situagio especifica. A seguir serio apresentados alguns exemplos de quantidades no mundo real. Tente selecionar o tipo primitivo que melhor represente a quantidade.
Valores literais para strings Um literal de strng| arepresentagio do c6digo-fonte para o valor de um objeto String. Por exemplo, abaixo vemos
exemplo com duas maneiras de representar um literal de string:
um
strings nio sejam primitivas, foram incluidas nesta segio porque podem ser representadas com valores literais em outras palav.ras, digitadat dnetanente no aidigo. O rinico outro tipo nio primitivo que possui uma representagio literal 6 o array, que examinaremos mais adiante neste capinrlo.
Thread
Operadores de atribuigio
Atribuir um valor a uma variivel parece bem simples; simplesmente insira o valor i direita do s tnd, variivel que estar6 i esquerda. Bem, certo, mas nio espere ser avaliado com algo do tipo:
para atribuilo
x=6;
NXo, voc6 nio ser6 avaliado com atribuig6e s que selarnfchinha (termo t6cnico). No entanto, ser6 avaliado em atribuig5es mais ambiguas que envolvam conversio e express6es complexas. Examinaremos atribuig6es primitivas e de vari6veis de
O que i uma
int, umdouble,
um Butron e at6 um-dep6sito Stiing [ ] . Dentro desse dip6sito, teriamos um conjunto de bits representan{o g v.alor. Para tipos primitivos, o1 bits representam um valor num6rico (embora nio saibamos qual o formato desse padrio de bits p"r" o tipo noolean, mas nlo achamos isso importante). Um tip o futte devalor igual a 6, por exemplo, significa que o
padrXo de bits davariivel (o dep6sito de tipos @t)
6
igual
a 000001.1.0,
representando os
bits.
objea?
Sevoc|escrever:
Buttonb=newButtono;
o que estar6 dentro do dep6sitg Bgaon blseria,o.objeto Button? N;o/Uma vari6vel referenciando um objeto seria exaramenre rs so - ono ,oidatl de refeftncia. O dep6sito de bits de uma vari6vel de refer6ncia cont6m bits que representam uma maneira d.e acessar o objeto.Nio iabemos qual-6 o formato; a maneira pela qual as referAncias ao objeto sio armaz.enadas 6, especifica de miquinas virtuais (6 um ponteiro para algt, apenas nio sabemos o que esse algo 6 realmente). Tudo que podemosdizer,iomcerteza,6 que ovdordavari6velnio 6 o objeto, masemvezdisso, umvalorrepresentar'dov.ggQea itoecifuo danentiria. Ou ovalornull. Se umvalor nio tiversido atribuido avariivel de referAncia ou tiver sido atribuido expiicitamente um valor nu11, a vari6vel armazenarL bits que representario - voc6 adivinhou - o valor nul1. VocA pode
Button b = nu1l;
da seguinte
Portanto, agora que sabemos que um avar:iilel|, apenas um pequeno dep6sito de bits, podemos dar prosseguimento e trabalhar com a altera$o desses bits. Examinaremos, primeiro, a atribuigXo de valores a tipos primitivos e terminaremos
com
as
Atribuig6es primitivas
O sinal de igualdade ( = ) 6 usado para a atribuSno de umvalor a uma variivel e foi chamado adequadament e de Eeradar dz atribuigdo.Naverdade, h6 12 operadores de atribuigio, mas apenas os cinco mais freqiientemente usados caem no exame, e eles serio abordados no Capitulo 4.
o c6digo a
int x = 7;
/ /
/ / aurflqrvqv arri1-rrlinin
ffLE!4f
I ifar-1
com uma
literal)
int.
Se
lembrar
6 que
Capitulol,vocAlembrar6queotipoint 6umvalorde32bits.Niohaveriproblemasevoceestiveratribuindoumvalor a uma vari6vel int. ou long, mas, e se estiver arribuindo a uma variivel uyte? Afinal, um dep6sito do tamanho do
tipo fote nlo pode armazenar tantos bits quanto um dep6sito com o tamanho do tipo ficar estranhas. O c6digo a seguir 6 v6lido,
int.
Aqui,
as coisas
comegam a
byLe b = 27;
mas somente porque o compilador compafiaautomaticanenrao valor literal para o tamanho de um tipo palavras, o compilador executa a conuersdo. O c6digo anterior 6 id6ntico ao seguinte:
byte. Em outras
k,,F^ ' vrus h -- /L,-r^\ ! \!rus/ 27; // Converte explicitamente o valor literal inteiro para um tipo byte
compiladorlhe deuumachance e permitiu quevod tomasse um atdho com atribuig6es avari6veis inteiras menorel que um tipo int. (fudo que estamos dizendo sobre o tipo byte se aplica igualmente a char e short, ji que os dois sio menores do que um tipo int). A prop6sito, ainda nio entramos realmente na parte estranha.
Parece que o
inteiro literal 6 sempre um tipo int, mas o que 6 mais importante 6 que o resultado de uma expresseo que envolva qualquer item do tamanho de um tipo int, ou menor, ser6 sempre um tipo int. Em outras palavras, some dois tipos byce e vocd ter6 um tipo - mesmo se esses tipos byte forem muito pequenos. Multiplique um tipo Certo, agora por um byte e ter6... Um tipo por um e ter6 um tipo int. Divida um tipo chegamos )pane estranha. Veja isto:
Sabemos que um
int
short
int
short
int.
problemas, 3 cabe em um byt.e / / Sem problemas, 8 cabe em um byte / / xeo deveria ter problemas, a soma dos dols bytes / / cabe em um tipo de byte
Sem
//
JAVA5 IO7
bytec="lo'
Tentamos atribuir a uma vari6vel do tipo byte a soma de dois @tes culo resultado (11) foi pequeno o suficiente para caber em um tipo byte, mas o compilador nio aceitou. Ele conhece a regra aplicivel a express6es "int ou de tipos menores" sempre resultando em um tipo int. A compilagio teria sido executada se tMssemos feito a conversio explicita:
byte c = (byte) (a + b) ;
primitivos
de
um tipo em outro. Examinamos a converslo de tipos discutiremos com mais detalhes. A conversio
As convers6es podemser implicitar ou explicitat.Uma conuersdo inpliatasignifica que.voc6 nio precisa escrever um c6digo para elE a conversao ocorTera automatrcamente. I\onnalmente, unVI conversao lmplrclta ocorre quancto lazemos uma transformagio que envolva anpl)agno.Em outras palavras, quando inserimos'um item menor (digamos, um tipo byte) em
umcontein-ermaior(comoumtipoint).Lembradaqueleserrosdecompilador"possintiloss of freci-' sion" que vimos na secio de atribuiE6es? Eles ocorrem quando tentamos inserir um item maior (digamos, um tipo long) emumcont6ineimenor (comoumtipo sho.rt). Atransformaglo "valormaioremumcontdinermenor"6
conhecida como compactaglo e requer uma c onversio.explhita,em que voc6 esari informando ao compilador que conhece o perigo e aceita toda a r?:sponsabilidade. primeiro, exarunaremos uma conversio implicita:
Conversdo
implicita,
a
um
valor int
seguir:
um
tipo de float
como
Os valores inteiros podem ser atribuidos a uma variivel double sem a conversio explicita, porque qualquer valor inteiro pode ser inserido ein um tipo double de 64 bits. A linha a seguir demonstra isso:
//
ConversSo
implfcita
Na instrucio anterior. um tiDo double 6 inicializado com um valor do dpo lonq (como indicado pelo L depois do valor num6rico). Nenhuma ionversio 6 necessiria nesse caso porque um tipo dgu5le po{e ar.mqzenir todas ai informag6es que um tipo l ong poderia conter. Se, no entanio, q-uisermos atribuir um valor do tipo doubl e a um tipo
eo
]
Se
Sjavac Casting.java Casting.java:3: Incompatible tlpe for declaration. Explicit cast needed to convert doub]e to int. int x = 3957.229; // nd.o 6 v51ido 1 error
No c6digo anterior, um valor
de ponto flutuante este sendo atribuido a uma vari6vel inteira. Ji que um inteiro nio consegri armazer,tar casas decimais, um erro ocorrer6. Para fazer isso ftmcionar, converterem6s o ndmero de ponto ilutuante emum lntero:
class Casting i public static voj-d main(String [] args) { int x = (int)3957.229; // conversSo v5lida System.out.println("int x = " + x);
POntO
um um Quando voc6 rconverter r rnrimero de ponto flutuante, em ,l tipo inteiro, o valor perder6 todos os digitos depois do I r. I ' a 1 . ^ decmal. A execugao do coctrgo antenor proctuara a sarch a seguf:
Bjava Casting
int x = 3957
Tamb6m podemos converter um tipo de nrimero maior, como long, em um menor, como b1te. Observe o c6digo abaixo:
nla<c l-acfina I
public static void maj-n(String [] arqs) { long 1 = 56L; byte b = (byte)1; System.out.println("The byte is " + b);
)
se
valor
long
fosse
muor
que
t27
maior nrimero que um byte pode armazenar)? Alteremos o c6digo para descobrir:
public static void main(String [] args) { long 1 = 130L; byte b = (byte)1; System.out.println("The byte is " + b);
]
O c6digo
O; --.tJovd
ser6
compilado adequadamente,
seguir:
l ud>Lf119 -^-^r
The
byte is -126
Voc nio vera um erro de tempo de execugio, mesmo quando o valor que estiver sendo compactado for grande demais para o tipo. Os bits ) esquerda do 8 inferior simplesmente... desaparecerlo. Como vimos na seglo de atribuig6es, se o bit da extrema esquerda do tipo byte, por acaso , agora,for t, ele nio far|mais parce do vatorl emvezdisso se tornari o bit de sinal do novo tipo byte.
Exercicio 3- |
Convertendo tipos primitivos
Crie um tipo de nrimero f
1. Declare
loat
de qualquer
valor
atribua-o
um tipo
short
usando a converseo.
umavariivel f
2.Atribuaotipo
Atribuindo nirmeros
de ponto flutuante Os nrimeros de ponto flutuante apresentam um compoftamento de atribuigio um pouco diferente dos tipos inteiros. Primeiro, voc precisa saber que todo lberal depontoflutuante d implicitanenteantipodouble @abit)endoantipofloat.Portanto,oliteral 2.3,porexemplo,6consideradoumtipo double. Se voc6 tentar atribuir um double a um f loat, o compilador saberi que nio h6 espago suficiente no cont6iner do tipo float de 32 bits paraarmaenar aprecisXo do tipo double de 64 bits, e ele lhe informarl isso. O c6digo a seguir parece adequado, mas nio ser6 compilado:
float f = 32.3;
VocApode achar que 32 .3 deveria caber satisfatoriamente emumavari6vel com o tamanho de um tipo f 1oat, mas o compilador nio permitir6 isso. Para atribuir um literal de ponto flwuante a uma variivel f 1oat, voc6 precisa converter o valor ou acrescentar um f ao final do literal. As atribuic6es abaixo serlo compiladas:
floatf=
(f1oat) 32.3;
JAVAs 109
Atribuindo um literal que
atribuir um valor literal que
seia
avariivel
se
renrarmos
bvtea=
(bYte) 128;
Mas entio qual seri o resultado? Quando vocA compactar um tipo primitivo, aJava simplesmente descartar6 os bits de ordem superior que nio se enquadrarem. Em outras palavras, ele perder6todos os bits ) esquerda dos que voce estiver conveftenoo.
Examinemos o que aconteceri no c6digo anterior. Nele, 128 6 o pa&io de bits 10000000. Esse pa&io usa exatamente bits para representar o nfmero 128. Mas j6 que o literaJ,I2S 6umtipo int, na verdade, obteremos 32 bits, estando o nrimero 128 nos 8 bits da extrema direita (ordem inferior). Portanto, 128 seria realmente igual a:
000000000000000000000000L0000000
Vocd tem nossa palavra; hL 32bits
u.
Para compactar os 32 bits que representam o nrimero 128, a linguagemJava simplesmente elimina os 24 bits da esquerda (ordem superior). Ficamos apenas com 10000000. Mas lembrese que um byte tem sinal e o bit da extrema esquerda
representa esse sinal (e nio pane do valor da vari6vel). Ponanto, terminamos com um ntimero negativo (o nrimero 1 que usamos para representar llS,agorarrepresentao bit do sinal negativo). Nio se esquega: para descobrir ovalor de um nrimero negativo usando a notagio biniria complementar, inverta todos os bits e, em seguida, adicione 1. Ao inverter os oito zeros ficaremos com 011111 1 1 e adicionando L a esse resultado obteremos 10000000 ou novamente 128! E quando aplicarmos o bit do sinal, terminaremos com -128.
VocA precisa usar uma conversio explicita para atribuir 128 a um tipo byte e a atribuigio resultar6 no valor -1.28. Uma converseo nada mais 6 do que sua maneira de dizer ao compilador, "Confie em mim. Sou um profissional. Assumo total
ocorrer quando
esses
byte b = 3; //
e
Sem
equivalente a:
em um tioo
int
O operador de atribuigio composto + = permitir6 que voc6 adicione o valor ) b, sem incluir uma conversio explicita. Na verdade, * =, - : r'r e / usario todos uma conversio implicita.
por exemplo,
int a = 6; intb=a;
O c6digo anterior pode ser lido como: "Atribui o padrio de bits do ntmero padrio de bits de a e insere a c6pia na variivel b.
Portanto,
IJsamos
a
I variivel
int
a. Em seguida, copia o
vari6veis, agora, contem o padrio de bits do nrimero 6, mas nio apresentam outro relacionamento. vari6vel , somente para copiar seu conterido. Nesse momento, as duas vari6veis possuem conteridos id6nticos
as duas
(emoutraspalavras,uakresidnticos),massealterarmososconteidosdea
Examine o exemplo abaixo:
oub,aoutravari6velnloser6afetada".
class Val-ueTest { public static void main (String ll args) { int a = 1-0; // Atribui-se um valor a a
l0 Copfiulo 3: Atribuig6es
System.out.println("a = " + a); intb=a; System.out,println("a = " + a + "after change to b");
)
a permaneceu igual a 10. O ponto chave a lembrar 6 que mesmo depois que voc6 atribuir a a b, as variiveis nio referenciario o mesmo local da mem6ria. As vari6veis a e b nio companilham apenas um valor; elas
t|m aipiasid|nricas.
atributum objeto
I I r
Button.
Criaumnovo obieto
Atribui
o objeto
Button
namem6ria.
zutcon
Voc6 tamb6m pode atribuir o valor nul1 vari6vel nio referenciar6 nenhum obieto:
Button c = null;
A linha anterior cria um
espago para gera realmente um objeto Buuon.
a
nio
Como discutimos no Capinrlo anterior, voc6 tamb6m pode usar uma vari6vel de referdncia para referenciar qualquer objeto que seja uma zubclasse do tipo declarado para a vari6vel, como descrito a seguir:
{ /\ I r
nrrlrlin
rzniA
AnFnncfrrff vveLBLL\/
i
publj-c class Bar extends Foo i public void doBarStuff O { }
]
)
class Test { public static void main (string [] args) { Foo reallyABar = new BarO; // V6lido, pois Bar 6 uma subclasse de Foo Bar reallyAFoo = new FooO; / / Ndo 6 v6lido! Foo ndo 6 uma subclasse de Bar
)
A regra 6 que voc6 pode atribuir uma subclasse do tipo declarado, mas neo uma zuperclasse desse tipo. Lembrese de que um objeto Bar , com cfrtez4pode fazer o mesmo que Foo, portanto, qualquer pessoa que tiver uma refer6ncia a Foo poder6 chamar m6todos Foo, mesmo se o objeto na verdade for um objeto Bar.
f ) , que algu6m com uma refer6ncia a essa classe poder6 tentar chamar. Se o objeto referenciado pela variivel Foo for realmente um objeto Foo, nXo haverl problemas. Mas
No c6digo anterior, vimos que Foo possui um m6todo doFooStuf
tamb6mniohaver6problemasseeleforumobjetoBar,jiqueBarherdouom6tododoFooStuff
).Voc6niopode
JAVA fazer isso funcionar de maneira inversa, no entanto. Se algu6m tiver uma refer6ncia aBar, poderi chamar doBarStuf f ) , mas se o objeto referenciado na verdade for um objeto Foo, ele nio saber6 como responder.
'I1I
Escopo Vari6vel
Depois que vod declarou e inicializou uma variivel, uma questlo naturd 6 "por qwmto tempo essa vari6vel vai existir?" Essa_ 6 uma,pergunta que se refere ao escopo das vari6veis. E o escopo nXo 6 ipenas uma coisa imponante & se entender de modo geral, mas ele tamb6m tem um papel imponante no exame. Comecemos examinando um arquivo de classe:
alaqc T.2\r^rrf I
/ // // // // // // //
/
classe
]
Como acontece com
escoPo:
as
as deste
e z)
t6m todas um
I I I I I I
s 6 umavariivelstatic. x 6umavariiveldeinstAncia. y 6 uma vari6vel local Qs vezes chamada de vari6vel "local de m6todo").
z E.umavariiveldebloco.
x2
x3
|umavarilvel
6
de bloco
init, um tipo
de
variivel local.
Para o
prop6sito de explicagio do escopo das vari6veis, podemos dizer que existem quatro escopos bisicos: t6moescopomaislongo;elassiocriadasquandoaclasse6carregada,eduramportodoo
6
I Asvari6veisstatic r I I
As vari6veis locais v0m em seguida; elas existem durante todo o tempo em que o seu m6todo permanecer na pilha. Como veremos em breve, no entanto, as variiveis locais podem estar vivas e ainda assim estar "fora de escopo". As vari6veis de bloco s6 existem durante o tempo em que o bloco de c6digo esti sendo executado.
Os erros de escopo t6m muitos tamanhos e formas. IJm engano comum acontece quando umavarihvel| sonbreadaedois escopos interferem um com o outro. Veremos o sombreamento com detalhes daqui a dgumas p6ginas. A razio mais comum Para acontecerem erros de escopo 6 quando vod tenta acessarumavariivel que nio est6no escopo. Vejamos tr6s
Tentaracessarumavari6veldeinstAnciaapartirdeumcontexto
static
(normalmenteapartirdemain
()
).
partir
de
um m6todo aninhado.
Quando um m6todo, por exemplo go ( ) , chama outro m6todo, por exemplo so2 O, 9o2 ( ) nio ter6 acesso is vari6veis locais de go ( ) . Enquanto so2 ( ) esr6 rodando, as vari6veis locaii de go O ainda estXo atiuar, mas estio fora
deescopo.Quando
I 12 Copitulo 3: AtribuiE6es
de
go ( ) anteriormente
class ScopeErrors { pubfic static void main(Strj-ng [] args) ScopeErrors s = new ScopeErrorsOi s.go();
)
rrniA wvls an/\ \ / Yv IL
]
vvrv vv!
y++;
)
t/ / /
Ltav ^<^
LUrttIJf ^^-^il-
Jqr
,,;'lnaal rvuqt y E
: q
nn/\ \ / vv
jA
terminou
de executar.
a
E bastaote co-n- declarar e usar uma variivel dentro de um bloco de c6digo, mas cuidado para neo tentar usar depois que o bloco finalizou:
vari6vel
void so3 O { for(int z=0; z<5; z++l boolean test = false; if(z == 3) { test = true;
break;
]
)
System.
out.print (test
);
maneira de o compilador dizer "aquela vari6vel que voce tentou usar? Bom, ela pode ter sido vllida no passado remoto (por exemplo, urna linha de c6digo atris), mas estamos na era da Internet, baby, nio tenho nenhuma lembranga
dessavari6vel".
oBSERVAQ6ES pnne
Tenba um caidado eEecial cum
o E)GME
efflr
de escEo de blocos de aidigo. Vocd podeni ai-los em
swiLches,
try- catctres,
em
:.oops
for,
do
rwhife.
inicializado e atribuido
A linguagemJavanos fornece aop$o de inicializarumavari6veldeclarada oudeix6-lasem serinicializa<la. Quandotentarmos usmalaiive[nloncialuadarpoderemos obterumcomportamento diferente dependendo dotrpo devariivel ou arraycom o qual estivermos lidando (primitivos ou de objeto). O comportamjntg tamb6m depender6 d9 niyel (eryopo) no qual estivermos declarando nossa variivel. Um a umhfunl de inrt4ncia6 declarada dentro da classe, por6m, fora de qualquer m6todo ou con$ruror, en qtrxnotmauarititvl bca/6declaradadentro de um m6todo (ou na lista de argumentos do m6todo).
As vari6veis locais, )s vezes, sio chamadas de variiveis de pilha, tempor6rias, autom6ticas ou de m6todo, mas as regras aplicadas a elas serio as mesmas, independente do nome dado. Embora possamos deixar umavari6vel local nXo inicializada, o compilador reclamar6 se voc6 tentar usar uma vari6vel local antes de inicializ6la com um valor, como veremos em breve.
JAVA5 I13
umidueis de instdncia (tarnb|mchamadas de vari6veis membros) sio vari6veis definidas no nivel da classe. Isso significa que declaragio da variivel rrio 6feita dentro de um m6todo, construtor ou qualquer outro bloco incializador. As vari-6veis de instAncia sio incializadas com um valor padrio sempre que uma nova instAniia 6 criada, embora possam receber um valor explicito depois de os superconstrutorei do objeto ierem fin ahzado o seu trabalho. A Tabela 3-i lista os valores padrio para
os
tipos primitivo
e de
objeto.
um membro da
classe,
nio
nas chaves de
um m6todo:
public class BirthDate { int year,' / / Yari6vel de instdncia public staLic void main(String [] args) BirthDate bd = new BirthDate ( ) ;
bd. showYear O ;
)
nfmeros.
Iobelo
3-l
Tipo de variivel
Vari6vel de refer6nciade obieto
Valorpadrio
0.0
-f !4Abe ^^
'\u0000'
nesnl
se estiuer
pmgramadores
qtre precisarem
faryr
atribaindo a elas o ualor padrdo. Sea cr6digo fcanl nais fricit de ser lido; os uoc6 ganbar na loteria e mudar para o Taiti) fcardo gratos.
return t.it1e;
1
public static void main(String [] args) { Book b = new Booko; System.out.println("The title is .. + b.getTitleO );
]
I4
Copitulo 3: AtribuiE6es
Esse
inicializada com a atribuigio de uma string, portanto, o valor da Lembre-se de que nu11 nio 6 o mesmo que uma stringvazia (""). IJm valor nu1l significa que a variivel de referdncia nao foi atribuida a nenhum objeto da pilha. Sendo assim, a alteragio abaixo no c6digo da classe Book apresentari problemast
nuII.
public class Book { private String title; / / vari6vel de refer6ncia de instAncia public String getTitle ( {
)
ratrrrn
|. if16.
public static void main(String [] args) { Bookb=neweook0; String s = b.getTitle0; // Ser6 compilado e executado String t = s.tolowercaseO; // Exceqdo de tempo de execuqSol
)
J
a classe
seguir:
Exception
at
Recebemos esse erro porque a variivel de referAncia nio esti apontando (referenciandg) para um objeto. Podemos verificar se urn objeto foi irstanciado com o uso da palavrachave null, como o c6digo revisado abaixo demonstra:
public class Book { private String title, / / vari6vel de refer6ncia de instAncia public String getTitle( ) {
r6t-11rh t i t- l a '
public static void main(String [] args) { Book b = new Booko; String s = b.getTitle(l; // Ser6 compilado e executado if (s != nu]I) { String t = s.tolowercase0;
)
)
O c6digo anrerior verificou se o objeto referenciado pela variivel s nio 6 nulo antes de tentar us6Jo. Fique atento p"r" ..i6rior do exame em que voc6 tenha q.te procrrrat no c6digo se a referAncia a um objeto possui.o valor nul-1. No c6digo anterior, por exemplo, examinamos a declaraglo da variivel de instAncia title, vimos que nio houve inicializigio explicita, confirmimos que avai|vel title recebeu o valor padrXo nu11 e, em seguida, vimos que a vari6vel s tamb6m apresentari o valor nul-I. Lembre-se, o valor de r 6 um1 c6pia do de title
(como retomado pelo m6todo
gretiitte (
)), portanto, se
title
nulI, s
tamMm
ser5"
de instAncia de array que for declarada, mas nio explicitamente inicializada,teri'o valor nu11, exatamente como qualquer outra variilelde instAncia de referAncia a objeto. Por6m, se o array forinicializado, o que acontecer6 aos elementos contidos nele? Todos os elementos do array receberio seus valores padrio - os mesmos valores padrio que os elementos desse tipo recebem quando sio variiveis de instAncia. Conclusio: Os elementos do analt receberio iemPre sempre nnpre uakret padrdo, independente de onde o
oa in$anciado.
Quando inicializarmos um array, os elementos de refer6ncia ao objeto serio iguais a nuI1, se nio forem inicializados individualmente com valores. Se houver tipos primitivos em um array, eles receberio seus resPectivos vdores padrio. Por exemplo, no o6digo abaixo, o array year ter6 1@ inteiros todos iguais a zero por padrio:
JAVA5 I15
public class BirthDays i static int [] year = new int[100]; public static void main(String [] args) f or ( int i.=0; j-<l-00 ; i++ ) Syst.em.out.println("year[" + i + "]
) )
+ rrarrIi]\.
' Jve+
L1J '
a saida
pene O EJGME
'Automdtico" i apenas niltrr tennl para "aariduel local". Ndo :igntfca qrc um ualor d atribuido automaticanente a uaritluel automdtica! O
oposto 6 qae d uerdadeiro; um ualor deue rcr atribuido a uma uai&uel automitica no cddigo; do contnlrio, o conpilador reclamani.
tempo
seguir, o inteiro
year
esr6
dentro
um m6todo.
public class TimeTravel { public static void maj-n(String [] args) t int year = 2050; System.out.println("The year is .' + year),.
)
As uaidueis kcais, incluindo w tipos prinitiuos, senprq nmprq sempre deuem rcr iniciali4adas antes de aocd tentar rcd-las (embora nXo necessariamentenamesmalinhadec6digo).AlinguagemJavaniofome,aalsvariiveislocais,umvalorpadrio; wcdtenlque infuiali4i-las explicianntecom um valor, como no exemplo anterior. Se tentar usar um tipo primitivo nlo inicializado em
seu c6digo, receber6
um erro do compilador:
public class TimeTravel { public static void main(String [] args) { int year; / / YariSvel local (declarada, mas nao utilizada) System.out.println("The year is '* + year) i // E,rro de compilaqSo
)
TimeTravel.java:4: Variable year may not have been initialized. System.out.println("The year is " + year); l- error
corrigir seu c6digo, precisamos fornecer um valor para o inteiro uma linha separada, o que 6 perfeitamente vilido:
Para
year.
public class TimeTravel { public static void main(String [] arqs) { int year; / / DecLarada, mas n5o inicializada int day; / / DecTarada, mas nio j-nicj-alizda System. out . println ( "You step into the port.al . ,, ) ; year - 2050; // Inieialj-zada (nm valor foi atribuido explicitamente)
AO TRABALHO
O compilador
ndo
or
rcm
un
podeni irforrnar sempre se uma uaiduel localfoi inidaliqada antes do uto. Por exempl0, n uoci inicialiqti-la dentro de um (en outras palauras, am bloco de aidtgo que pode ndo ser executado, como o bloco de uma instrugdo , ou }oop ualor literal ou f a l- s e como altematiua), o conpi/ador saberd que a inicialiTgjdo talueq nio ocorra e podeni produ{r
true
if
l-nt x/' if (arqs [0] l= nu11l { //suponhamos que voc) soubesse que este resuitado seja <amore Erue x ='J; / / o compilador ndo poderd informar se esta instrugdo ser1. executada
)
inf LLLv ar t v' ^t
uoc
tentar compi/6-/o:
problena do conpilador
ndo
condiriona/, cpenat para deixar o conpilador satisfeito, Voci compilador n1o eshi mtisfeito,
poder infomar com cerieqa, em algamat situagdes uoci ter,i que inicialiTar saa uaiduelfora do bloco sabe porque isso d importante seji uiu o adesiuo de pdra-cboqae: "puando o
ninguin ufli".
TimeTravel.java:5: Variable date may not have been initialized. rf (date == nu11) 1 error
JAVA
117
As refer6ncias de vari6veis de instAncia recebem sempre um valor padrio igual a nu1l, at6 serem inicializadas explicitamente- com outro valor. No entanto, as refer6ncias locais nio recebem um valor padrXo; em outras palavras, ndo sdo nwII. Se voc6 nio inicializar uma vari6vel de refer6ncia local, enteo, por padrio,ieu valor ser6... Bem 6 ai que est, todo o problema - ela nio teri absolutam ente nenham valor! Portanto, simplilcaremos a questeo: configure o item incompleto com null explicitamente, at6 que esteja pronto para inicializi-lo com outro valor. A vaii6vel local a seguir ser6 compilada apropriadamente:
a vari6vel
de referancia
1oca1
//
Arrays locais
Exatamente como em qualquerorrtra refer6ncia aobjeto, deve-se atribuirumvaloris referncias de arrays declandasdentro de um m619d9 ante; que sejamusadas.Isso significa apenas que voc6 precisadeclarar e constnriro nio ser6 "o"y.Irio.ntanto, necessirio.inicializar explicitamente os elementos de um array.J6dissemos iso antes, mas 6 imponante o srficiente para que seja repetido: Elementos de arrE recebem seas ualorespadrio (0, fa1se, nu11, ' \u0000 e asimpordiante) indepentte;tu d0;ffq terida &ckrarlo como umauaitluel local oa de instincia. O proprio objeto de affay, contudo, nio ser6 inicializado se for declarado localmente. Em outras palavras, vod ter6 que irnci.altzar exphcitamente a referAncia a um array, se ela for declarada e usada dentro de um m6todo, mas, no momento em que construir um objeto de array, todos os elementos receberio seus valores padrio.
'
class ReferenceTest { public static void main (String [] args) Dimension a = new Dimension(5,10);
SvStCm ottf nrinFlh/\\eJeuerlr.vqury!rlrurrr\ 1-'^i^Lf q.rrsIVIIu -
\\ _, a hoiahf + 4.rrurVrrL/,
Dimension b =
vi4re+Y11u Jv,
a,-
L^.i-L+ a.rrcr9lrL
tr +: q.rrsfvrrL hoinlrt ,
r
I
Pense Por
a?
Bjava ReferenceTest
Por essa saida, podemos concluir que as duas vari6veis referenciama mesmainstAncia do objeto Dimension. Quando fizemos a alteragio em b, a propriedade de altura tamb6m foi alterada em a Encontramos uma exceglo ) maneira como as referncias a objetos sXo atribuidas no objeto String. EmJava, esses objetos recebem-tratamento especial. Em primeiro lugar, os o\etor.stringtdo inalteniueir,vocA nlo pode alter:ar o ,ralor de um objeto String. Mas is so parece ser realmente possivel. Examine o c6digo a seguir:
class Strinqs { public static void main(String [] args) { String x = "\Tava"; ,// Atribui- valor a x af ri na eulfrrv // Agora, y e x referenciam o mesmo objeto String ! - ^t
qtri Svstem orrf nri nl- l n 1"\/ ru!+lry nn -= \\ + \/lI t' \ J J '
'18
Copftulo 3: AtribuiE6es
/ Agora, o objeto foi alterado / /referlncia a x System.out.println("y string = " + y); x = x + " Bean"i
/
)
VocA pode achar que o objeto String armaz.enar| os caracteres as strings sXo objetos. Examinemos qual seri a saida:
9'i:rr: cf ri nft
com
o uso da
Java Bean
depois que
variivel
aheraruma$ring:
r I
A referAncia usada para alterar o objeto String (ou em vez disso, para criar um novo objeto String pela alteragio
c6pia do original) seri atribuida ao novo objeto String.
de
uma
1. Strind s = *Fred"; 2. String t = s, // Agora, t e s referenciam o mesmo objeto String 3. t.touppercase0; / / Chama um m6todo String que altera o objeto String
na verdade, neo ter6 alterado o objeto String original criado na linha 1. Quando a execugio da linha 2 for conclui&' tanto quanto s referenciarXo o mesmo objeto Stiing. Mas quando a linha 3 for executadao em vez de alterar o objeto referengia{9 por (que 6 o rinico objeto String at6 esse mo-.trto),.tm novo objeto String seri criado. E, em seguida, abandol{tg Ji. que o n&o objeto String nio 6 atribuido a uma variivel String, esse objeto rec6m-criado (que armazena a string "FRED") 6
eiquecido. Portanto, embora dois objetos String tenham sido criados no c6digo anterior, somente um ser6 realmente referenciado e tanto t quanto s o referenciario. O comportamento das strings 6 extremamente importante no exame, de modo que o abordaremos com muito mais detalhes no Capitulo 6.
e sobre os
ualoru
pimitiuos quando
realilam atribuipdes
Os m6todos podem ser declarados para usar refer6ncias primitivas e/ou de objetos. Voc6 teri que saber como (o9 se) a valiavel do chanadorpoderi ser afetada pelo m6to do chanadt. A drlerenga entre variiveis primitivas e de refer6ncia de obieto, quando passadas para m6todos, 6 grande e importante. Para compreender esta segio, voc6 teri que estar familiaizado coma segXo de atribuig6es abordada naprimeirapane deste capinrlo.
JAVA
5 I'I9
2. class ReferenceTest { 3. public static void main (String [] args) { 4. Di-mension d = new Dimension(5,10) ; 5, ReferenceTest. rt = new ReferenceTest ( ) ; 6. System.out.println("Before modifyO d.height = " + d.height); 7. rt.modify(d) ; 8. System.out.println("After modifyO d.height - " + d.height); f. i 10. void modify(Dimension din) { 1-1. dim.height = dim.height + 1; 1,2. System.out.println("dim = " + dim.height) ; l-3. ) 14.j Quando executarmos essa classe, poderemos ver que o m6todo modi fy ( ) realmenre conseguiu
Dimension originat
C:\ (e
alterar o objeto
Raf^r6
dim =
11 11
Observe que a paftir do momento em que o objeto Dimension da linha 4 for passado para o m6todo modi fy ( ) , qudquer alteragXo que ocorrer dentro do m6todo estari sendo feita no objao cuja refer6ncia foi passada. No exemplo anterior, tanto a variivel de refer6ncia d quanto d.im apontam para o mesmo objeto.
da resryito
alinguagemJavapassaobjetos usando avariivel de refer6ncia, isso significa queempregaaparsagempnrrcfefinciano que a objetos? N5o exatamente, embora seja comum ouvirmos falar e vermos em livros que ela fazisso. Na verdade, elapassanlpor aakr todas xvariiveis que forem executadas dentro do mesmo VM. Passar por valor significa passar por valor da uai,luel. E isso quer di zer, pa$arpnr aipia da uaiiuel (eis apalavra "c6pia" novamente) !
se voce est6 passando vari6veis primitivas ou de refer6ncia, sempre estari passando uma c6pia dos bits da vari6vel. Portanto, no que diz respeito a uma variivel primitiva, vocO estari passando uma c6pia dos bits qrr. i.pr.s.nt"m o valor. Por exemplo, se vocd passar uma vari6vel de valor 3, estari passando um a adpia dosbitsque representam 3. Assim, o m6todo chamado obteri sua propria c6pia do valor, para fazer com ela o que quiser.
int
se voc6 estiver passando uma vari6vel de refer6ncia de objeto, estari pas sando wa aipiados bits que represenram a refer6ncia a um objeto. Assim o m6todo chamado obter6 sua propria c6pia da variivel & refer6ncia e far6 com ela o que quiser. Mas j6 que duas variiveis de refer6ncia id6nticas referenciam exatamente o mesmo objeto, se o m6todo chamado dteraro objeto (chamando m6todos de configuragio, porexemplo), o chamadorperceber|,qteo o$eaque suavariivel origind referenciou tamb6m ter6 sido aherado. Na pr6xima segfo, examinaremos iomo o cenirio se ahera quando falamos sobre tipos primitivos.
A conclusio sobre a passagem por valor 6 a seguinte: o m6todo chamado nlo pode alterar a uairlaeldo chamador, embora no que diz resp eito avariiveis de reter|ncia deobjeto, o m6to do chamado pdc aherar o objao que avari|velreferencia. Qual a diferengaentre alterar l variivel e alterar o objao? Quanto )s referAncias a objetos, significa que o m6todo chamado nio pode reatribuir avariivel de referAncia original do chamador e fazer com que ela referencie um objeto diferente ou ovdor
'120
Copfiulo 3: Atribuig6es
q.setName("Boo");
9 = new FooO;
)
reatribuir g nio reatribuir6 f ! Quando a execugeo do m6todo bar ( ) for concluida, dois objetos Foo terio sido criados, um referenciado pela vari6vel local f e outro pela vari6vel local (vari6vel de argumento) 9r. J6 que o m6todo doStuf f ( ) possui uma c6pia davari|vel de referAncia, tem uma maneira de acessar o ob)eto Foo
( ). Por6m, doStuf f ( ) ndotemc0m0acessarauariduelde ( ) pode alterar o que f estiverreferenciando, mas nio o conterido real (padrio de bit$ deste. Em outras palavras, dostuf f ( ) pode modificar o estado do objeto a que f se refere, mas nio pode fazer com que f se refta a um objeto diferente!
original,porexemplo parachamar om6todo setName
referlncia
f.
Assim,
doStuf f
para um m6todo:
class ReferenceTest { public static void maj-n (String [] args) int a = l-;
ReferenceTest rt = new ReferenceTest
rF mnr{ i frz /\a); r*..,.-*--f
Nesse programa simples, avariivel 6 passada para um m6todo chamado uma unidade. A saida resultante teri este formaro:
modify
) , que a
aumentari em
Refnremndifvll
rllvgf
!J
a=l
number =
depois que foi passada para o m6todo. Lembre-se de que somente uma alpia de a m6todo. Quando uma vari6vel primitiva 6 passada para um m6todo, ela 6 pasadapor ualor, o que significa "passar por c6pia dos bits davari|vel,.
foi
Na sala de aula
O mundo sombrio das variiveis
No momento em que vod pensou que havia decifrado tudo, viu um trecho que, na sua opiniio, deveriam estar. VocA pode ter encgntradg c6digo
manerras; examinaremos apenas
-um
a
de c6digo com
.com
variiveis que nlo estavam se componando da maneira variiveis sombreadas. E possivel sombrear uma variSvel de v6rias
omltaruma uarihnl fu iutdncia sombreanda-a
com ama uarirhnl locaL
O sombreamento envolve redeclarar uma vari6vel que j6 tenha sido declarada em algum outro local. O efeito do sombreamento 6 a ocuha$o &variAveldeclaradaanteriormente, detalmodo quepossaparccerqlrevod estiusando avariiveloculta, mas o queestar6realmenteusando ser| avai|vel de sombreamento. VocA pode encontrar raz6es para sombrear uma variAvel intencionalmente, mas normalmente ocorre por acaso, causando erros dificeis de detectar. No exame, vocA pode esperar perguntas nas quais o sombreamento teri uma
panicipagio.
VocA pode sombrear uma variivel de instAncia declarando uma variivel local com o mesmo nome, diretamente ou como parte de um argumento, como vemos abaixo:
class Foo
JAVA
5 I2I
static int size = 7; static void changelt(int size) { size=size+200; System.out.println(..size in changelt is .. + size);
)
public static void main (String [] args) Foo f = new FooO; System.out.println("size - " + size);
changelt (size)
;
O c6digo anterior parece alterar a variivel de instAncia size, no m6todo changert ( ) , mas ji que changert ( ) possui um parimetro chamado s i z e, a variivel local s i z e ser6 alterada enquanto a vari6vel de instAncia a1e permaneieri intocada. A execu$o da classe Fooexibirl
Sjava
Foo
vari6vel sombreada
6a
28;
class Foo
public static void main (String [] arqs) { Foo f = new t'ooo; System.out.println("f .myBar.barNum is " + f .myBar.barNum)
changelt (f.myBar)
;
f.myBar.barNum
myBar.barNum
is 28 in changelt is
99
122 Copftulo
3:
AtribuiE6es
myBar.barNum
Como voc pode ver, a variLvel de sombreamento (o parAmetro local myBar de changel t ( ) ) ainda po der5. afetar a variivel & instAncia myear, porque o parlmetro myBar receberl uma refer6ncia ao mesmo objeto Bar. Por6m, quando ) vari6vel local myBar for atribuido um novo objeto Bar, que em seguida modificaremos alterando seu valor barNum, avariivel de instAncia myear original de Foo permanecerl intocada.
\-/oleTrvo po ro
Al
,.1. o cenrTrcocoo
unpimitiuos, affEtq
/orais.Akn
EmJava, os arrays sio objetos que armazenam diversas variiveis do mesmo tipo. Eles podem conter variiveis de refer6ncia primitivas ou de objeto, mas o array propriamente dito sempre ser6 um objeto da pilha, mesmo se for declarado para armazenarelementos primitivos. Emoutraspalavras, nXo exise algo comoumarrayprimitivo,mxvoc|podccriarum array de elementos primitivos. Para esse objetivo, vocd teri que conhecertr6s itens:
I r I
Como criarumavariivel de nfunciade xray (declaraio) Como criar um ofrxo de array (consrugXo) Comoprymcheroarraycomelementos (inicializagXo)
dessas tarefas e voc6
teri
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
jd
rcr expandidat ou mnhaidas dinamieamente quando uocd adicionar ou remouer elementos (na H,i am tipl Cnlkctinn para ama grand.e uariedade de neces$dades. Vocd
precisa de ama classficagdo nlpida? De un gwpo de objetos rcm repetigdu? Uma maneira de acersar um
encadeada?
plr
nomef ualor?
Una lista
O Capitalo 7
os
Declarando um array
tipo primitivo, seguido
Os arrays sio declarados atrav6s da descriglo do tipo de elemento que armazenario, os quais podem ser um objeto ou um de colchetes ) esquerda ou direita do identificador.
Quando declanr avanivelde refer6ncia de um affry, insira sempre os colchetes do array imediammente ap6s o tipo declarado, em vez de depois do identificador (nome da variivel). Dessa forma, qualquer pessoa que ler o c6digo pod."6 perceber que, por exemplo, key 6 uma variivel de referAncia do objao de array int e nio um tipo primitivo int. Tamb6m podemos declarar arrays multidimensionais, que, na verdade, sio arrays com outros arrays armazenados. Isso pode ser feito da maneira a seguir:
JAVAs I23
O primeiro.exemplo 6um_array tridimensional (um aray com outros arrays tamMm alrrrra?.Enrerrdo arrays) e o segundo 6 um-array bidime-rsional. Observe que no segtndo exemplo, temos um colchete antes do nome davariivei eum delois. Isso perfeitamente v6lido para o compilador, o que prova mais vnavez que fipaque,t t,t/ida nao signfu que 6 eio. Nunca 6 considerado vilido incluir o tamanho do array na declaraEio. Sim, sabemos que voc6 pode fazer isso em algumas outras linguagens, e 6 por isso que poder6 se deparar com uma ou duas perguntas que incluam um c6digo
semelhante ao seguinte:
6
int[5]
scores;
a
O c6digo anterior nio conseguir6 passar pelg compilador. Lcmbre-se de.que voc6 instancie realmente o objeto de array. E ai que o tamanho importari.
JVM nio
Construindo um array
Construir vm array significa criar o objeto de array na pilha (onde todos os objetos residem) - em outras palavras,
alocar na pilha, ponanto, voc6 precisa especificar o tamanho do array na hora da const^glo. Esse tama.rho seri igud a quantidade de elementos que o array armazenar|.
int:
tipo o array
armazenarS.
O c6digo anterior insere um novo objeto na pilha - um objeto de array contendo quatro elementos - com cada elemento contendo um tipo int de valor padrio igual a 0. Considere esse c6digo como se ele dissesse ao comPjlaior: "Crie na pilha um objeto de array que armazenar6 quatro tipos inJ primitivos e atribua-o i vari|vel de refer6ncia declarada anteriormente chamada Lestscore=. E ..tq.t".rt o fizer isso, aproveite paraconfigurar cada elemento int com zero. Obrigado". (O compilador aprecia boas maneiras). A Figura 3-2 mostra como o array testscores aparecer| na pilha, depois da construglo.
varidvel de
referncia do
array int[ ]
FFT;T;I
0123
Valores Indices
Figuro 3-2
Voc6 tamb6m pode declarar e construir
lma
Nio
pene O EXAME
napilha, dtpois que uma instrugdo ou
por exenpk, qae o aidigo anteriorpmduq@enas
bloco do aidigofor exuutado, No exame seri objxo (o aral atribuido a uaiiuel de referncia cbamada
objetoTbreadfoi criado ou
Lembre-se de que os arrays devem senpreterum tamanho atribuido no momento em_que forem construidos. de array. Nunca 6 JVM precisa do tamanho a fim de alo."r o espago apropriado na pilha para o novo objeto considerado vilido, por exemplo, fazer o seguinte:
int[] carlist
Portanto, nlo o faga,
= new
int[]; //
Ndo
um tamanho
e se voce
ver isso no teste, nio hesite em marcar a resPosta "A compilagio falhar| '
oBSERVAQAO
Voc pode uer as
pene O EXAME
e
'Un
pilha;'. Essas pilanas tanbdm inplicam qae 0 cunstrutor do objeto senl executado, como resultado d.o aidigo de nnstragdo/triaydo/ -instanciagdo. itodeno, di7,er con cirteqa, ltor exenplo, qae qua/.quer aidigo que use a palawa-chaue r,ew (se for exuutado eon sucesso) fanl
com qae o construtor da classe e todot os clnstrxttores de saperr/asses sqiam exeratados.
Al6m de ser consrruido com new, os arrays tamb6m podem ser criados com o uso de um tipo de abreviatura na sintaxe que gerari o array, ao mesmo tempo em que inicializari seus elementos com valores fornecidos no c6digo (e nlo com valores
iadrXo) Examinaremos
isso com detalhes na segio sobre inicializagXo. Por enquanto, memorize que, Por causa desses atalhos tra ritttaxe, os ob.ietos ainda poderio ser criados mesmo que voc6 nXo use ou veja a palavra-chave new.
inttl[] ratings
= new j-ntt3l
tl;
a
Observe que apenas os primeiros colchetes possuem um tamanho. Isso 6 aceitivel em Java, i6 que saber somente o tamanho do obieto atribuido avariivel ratings.
JVM precisa
][]
rnyArraylO] = new
myArray[0] myArray[0]
intt l[ ]
rnyArray = new
[0] = 6; t]-l = 7; myArrayll] = new intt3l; mYArraYlll I0l = 9; rnyArray [1] l1l = 8; mYArraY[1] [2] = 5;
intt2l;
inti3lt
1;
JAVA
I25
Inicializando um array
lniciel i"x1'
itens n ele. Os iterc (Srorque, sim, esse /um rermo t6cnico) do array sio seus elemenros,
osquaispoderioservaloresprimitivos(2,'x',fa1se eoutros)ouobjetoscitadospelasvariiveisdereferniradoarray.
Se voc6 tiver um array de objetos (e nXo de tipos primitivos), na verdade , ele nilo armaTenar,ios objetos, exatamente como nenhuma outra vari6vel que nio seja primitiva, nunca cont6m realmente o ofiea, mas, em vez disso, armazenavma r{erncia a ele. Por6m, nos referimos a arrays como, por exemplo, "um array de cinco strinp", embora isso, na realidade, signifique, "um array de crnco refernciat a objetos String". Portanto, a grande pergunta p"srJa ser s. essas refer6ncias estio riesm^o ou nlo apontando (opa, issodJava, q-ueremos drzer refercnciando) pariobjetos Siring reais ou se sio simplesmente null. Lembre-se de que uma referAncia ) qual nio tenha sido atribuido um objeto seri uma refer6ncia nuil. E se voc6 tentar usar essa referOncia nu11, digamos, aplicando o operador ponto para chamar um m6todo com ela, receber6 a detestivel exceglo Nu1 1 PointerExcept i on .
Os elementos individuais do array podem ser acessados com um ntmero de indice. O nrimero de indice sempre comega no zero' Portanto' Para um array de dez objetos os nrtmeros de indice irio de 0 a 9. Suponha que cri6ssemos um .lrray com tr6s Animais como descrito a seguir:
peES:
Temos_um objeto de array na pilha, com tr6s refer6ncias nu11 do tipo Animal, mas ainda nio temos nenhum objeto ser6 criar alguns objetos Animal e atribuir a eles posig6es de indice no array relerenciado por
pets[0] = new Animalo; Pets [1] = new animal ( ) ; Pets [2] = new Animal O ;
Esse
e os
OBSERVAQ6ESPARAOE)(AME
Procure aidigos qae tentem acetsar um indice de
elemento
pl
exerup/0, re am
affal
knpani a
excegdo
ArraylndexOutOfBoundsExcept ion,
as
pois em ltm
affal
para
uer a tentatiua de utiliqagdo de um nilmero negatiuo clmo am indice do anE. seguir, temos exenplot de tentatiuat ud/idas e inud/idas de acesso ao affaJ. Certfique-w de reconhecer quando elas causam exagdes de tempo de
os indices serdo
exuagdo e ndo erms de nmpilador! puase todas compilador como re spostas possiueis.
int[] x = new int[5]; x[4] = 2; / / OX, o riltimo elemento est6 no indice 4 x[5] = 3; // Exceqd.o de tempo de execuqSo. Nao h5. nenhum elemento no indice int [] z = new int[2]; int Y = -3' zlyl = 4; / / ExceqSo de tempo de execugSo. y 6 um nfmero negativo
F las dos
5!
poden ser dfrceis de loca/iqar em um kop complexo, mas ese seri o momentr mais prouiuel em que suryirdo problemas con
de
os indiees
anals
inicializado da maneira
seguir:
inttl tl scores = new int[3] []; / / Declara e cria um array contendo tr6s refer6ncias a arravs int scores[0] = new int[4]; / / o primeiro elemento do array scores estii em um array int de quatro elementos int scores[1] = new int[6]; / / o segundo elemento do array scores est6 em um array int de seis elementos rnt scores[2] = new int[1]; / / o terceiro elemento do array scores est6 em um array int de um el-emento int
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
)
length nos informa quantos elementos o array cont6m, mas n6o se esses elementos foram inicializados. Como veremos no Cipitulo 5, a partir do Java 5 n6s poderiamos ter escrito o loop f or sem usar a vari6vel length:
A variivel
for(Dog
d:
myDogs)
d = newDog( );
Declarando, construindo e incializando em uma linha
VocA pode usar dois atalhos de sintaxe especificos de arrays tant o para ainciahza$o (atribuir valores especificos aos elementos de um array) quanto para a construgio (instanciar o proprio objeto de array) em uma rinica instru$o. O primeiro
ser6 usado para declarar, criar e
I I I I
int
chamada
dots.
Cria um array
int
de
Atribui
Atribui
dots.
as
O tamanho (extensio do array) 6 determinado pela quantidade de itens separados por virgulas entre funcionalmente equivalente ao mais longo descrito a seguir:
chaves.
O c6digo
int[] dots;
dots = new int[3];
intx=9;
dots[0] = 6; dots[1] = x; dots[2] = B;
Issotraz apergunta: "Por que algu6musaria aformamais longa?" Uma razXo vem )mente. VocA pode nio saber- no momeruo em q.r. .rr", o ,ir"y --os ,ralores que serlo atribuidos aos elementos. 56 esse atalho de array vale o prego deste livro (bem, isso combinado com amaravilhosa apresentagio).
Com refer6ncias
Dog PUPPY = new Dog("Frodo"); Dog[] myDogs = {PuPtry, new Dog("Clover"), new
oog("Aiko")};
O c6digo anterior cria o array Dog, referenciado pela variivel myDogts, com um tamanho de tr6s elementos. Ele atribui o objeto Dog criado anteriormente (atribuido ) vari6vel de referAncia puppy) ao primeiro elemento do array e tamb6m cria dois novoJobjetos Dog ("clover" e "Aiko") atribuindo as duas instAncias rec6m-criadas aos dois riltimos elementos &variivel de referAnciaDog, do arraymyDogs. AFigura 34 mostrao resultado.
Vodtamb6mpode usarasintaxe
de atalho
objao {ue
JAVA
I27
rsr. Oog{'Aiko"}};
orroyde Dog
[ ] re{erenciodo
pornyDogs
[1
]e
myDoss
2 ]
Figuro 3-4
Declorqndo, construindo
e iniciqlizondo um arroy de obletos O tamanho de cada um dos tr6s arrays int 6 derivado da quantidade de itens dentro das chaves internas corresPondentes. Por exemplo, o primeiro array tem um tamanho igual a quatro, o segundo array 6 igual a dois e o terceiro tamb6m 6 igual a dois. At6 agora, temos quatro objetos: um array contendo arrays int (cadi elemenro 6 uma referAncia a umar:rey int) e tr6s arrays int (cada elemento dos tr& arrays int 6 um valor int). Para concluir, os tr6s arrays int foram inicializados com os valores int reais das chaves internas. Portanto, o primeiro array int cont6m os valores 5, 2 ,4 e7 . O c6drso a seguir mostra os valores de alguns dos elementos desse ariay bidimensional:
t}l / / um array de quatro ints scores 1Ll / / Lrm array de 2 ints scores t2l / / um array de 2 ints scoresl0l t1l // o valor int igual a 2 scores t2l l1l / / o va]-or int igual a 4
scores
AFigura3-5 mostrao resultadodadeclaragio, consruglo einicializagXo deum arraybidimensionalemumainstruso.
atribuiu o novo array i variivel de refer6ncia testscore s do array int declarado anteriormente. Chamamos essa operagio de criagio le array an6nimo, porque com essa sintaxe, voc nem mesmo precisa atribuir algum valor ao novo array. Voc6 pode estar pensando, "Qual a vantagem do array, se ele nXo for atribuido a umivari6vel de refer6ncia?" Ele pode_ser usado na criagio de um array just-in-tine a ser empregado, por exemplo, como argumento de um m6todo que use lm arr^y como parAmetro. O c6digo abaiio demonstra um argumento de array
,u$-rn-ume:
int
em segu^ida,
public class Foof { void takesAnArray(int [] someArray) / / usa o array como pardmetro
)
[]
{1
,'7,8,2,5});
objeto Cat
objeto Cat
][]
][
cat[ ][ ] myCats = {tnewCat("Fluffy"}, newcat('zeus")}, {new Cat("Bilbo"), new Cat("Legolas"), new Cat("BerE") }}
56o criados oito obietos:
obieio orroy
2-D Cat t
I t
OBSERVAQ6ESpeneoE)(AME
Itmbre-se de ndo especifcar am tarnanho quando usar a intaxe da criagdo de arral an6nimo. O tamanho d deiuado da quantidade de itens (separadot por uiryu/a) existentes entre as cbauer. Preste bastante atengdo na intaxe de arals usada nas pergantar do exame (e bauer,i ntuitas). Vocd pode aer xtrta czmo essa nar^r f\lrioal-f ?l Inrr'l'l trrufrr naur nl-rian|rlvvv vvJvvL\r, /l row Oh'iccl{)}:
Ltsv : varauq; /| // '^x^ s --<r I r^, o tamanho nao deve ser especificado
vm arlay
int
int[] weightlist
= new
int[5];
JAVA5 I29
byte b = 4; char c = 'c'; short s = 7; weightlisttOl = b' // OK, byte 6 menor do que int weightlisttll = c' // OK, char 6 menor do que int weightlist[2] = si // OK, short 6 menor do que int
class Car { } class Subaru extends Car { } class Ferrari extends Car { }
Car [] myCars = {new Subaru0, new CarO, new Ferrario};
E bom lembrar que os elementos do array Car nXo sio nada mais do que varilveis de refer6ncia Car. Portanto, qualquer item que possa ser atribuido a uma variivel de refer6ncia Car poderi ser concedido de maneira v6lida a um elemento do array Car.
Se
que implementem
o array for declarado como um tipo de interface, seus elementos poderAo fazer refer|ncia a qualquer instAncia das classes a interface declarada. O c6digo a seguir demonstra o uso de uma interface como tip o de auay:
);
l-raannrtrr/\
vvvyv! ef
) )
class GolfClub { } class festsportyThings { public static void main (String [] args) { Sportyl] sportyThings = new Sporty [3]; sportyThinss[0] = new Ferrari); // OK, Ferrari implementa Sporty sportyThings [1] = new Racingplats ( ) ; / / OIr., RacingFlats implementa Sporty sportyThinSs[2] = new GolfClubO; / / I{Eo 6 v6l.ido; GolfClub (clube de golfe) ndo implementa Sporty / / Nao importa se as pessoas n5o me considerarem moderna por causa disso
I30
Copftulo 3: AtribuiE6es
A conclusio 6 a seguinte: qualquer objeto que passe no teste "E-MEMBRO" aplicado ao tiPo de array declarado
pode ser atribuido a um elemento desse array.
(de qualquer tamanho), mas ndo a um item que ndo seja um array inL, podeni ser reatribuida a qualquer array lnclusive valores Lembre-se de que todos os arrays sXo objetos, portanto, uma aaiduel de reueftncia de atral nio pode ser atribuida a um tipo primitivo int. O c6digo a seguir demonstra atribui$es vilidas e inv6lidas de arraln primitivos:
int.
inL
infIl
<nlafc.
int[] dats = new int[4]; char[] letters = new char[5]; splats = dats; / / Ox, dats se refere a um array int splats = letters; / / NAo ESTA coRRETo, letters se refere a um array char E tentador presumir que j6 que uma variivel de tipo byte, short. ou char pode ser promovida e atribuida explicitamente a um tipo int, um array de qualquer &sses tipos poderia ser atribuido alum array int. Voc nio po&.
fazer isso emJava, mas seria bem pr6prio deises elaboradores de exame maldosos e impiedosos (por6m, interessantes) inserir perguntas ambiguas sobre atribuig6es de arrays no exame. Os arrays que podem conter referdncias a objetos, e nio a tipos primitivos, nio slo tio restritivos. Da mesma forma que voc6 pode inserir um objeto Honda em um array Car (porque Honda esten& a classe Car), pode atribuir um aray detipo Hondaaumavariivel de refernciado array Carcomo descrito abaixo:
Car
cars,.
Hondal] cuteCars = new Honda[S]; cars = cutecars; / / OK, poi-s Honda 6 um tipo de Car Beerl] beers = new Beer [99]; cars = beers; // llAo nsrA conReTo. pois Beer nao 6 um
tipo de Car
Apliqueotest.ti-l,tgUnnOparalhe ajudaradistinguiro que6vilidodo quenio 6. HondaII-MEMBROdo grupo Car, portanto, um arrayHondapodeseratribuido aum array Car. A assertivaBeerE-MEMBRO do grupo Carnio est6correta; Beer ndo estendea classe Car (para nio mencionar o fato de que nio tem sentido l6gico, a menos que voc6 j6 tenha bebido
bastante).
oBSERVAQoESPARAOE)(AME
portanto, te
Un anal Car nio pode ser atibuido ao anal Honda. Nem todo carro i da marca Honda, an aral Honda, ele ndo comportaria o arral Car atribaido a aai,iael de refer1ncia Honda. Pens bem: am anal Carpodeia conter ama referdncia a Fenari, e algudm qae achasse ter am arral de Hondas se depararia repentinamente com a Fenai. L.cmbn+e qae o teste E-MEMBRO pode ser executado no nidigo, atrauds do operador instanceof .
Vocd ndo pode inuerter at atribai{6e! udlidas.
uoc6 tiuesse
dtclarado
de atribui$o de arrays se aplicam tanto a interfaces quanto a classes. IJm array declarado como um tipo de interface pode referenciar um array de qualquer tipo que implemente a interface. le mbrese de que qualquer objao de uma classe que implemente uma interface especifica passari no teste E-MEMBRO (instanceof) dessa interface. Por exemplo, se Box implementar Foldable, o c6digo a seguir ser6 v6lido:
A regras
foldingThings = boxThings; / / oK, Box implementa Fo1dab1e, portanto. Box f-MeMeRo de Foldable
int[] blots; inttl tl squeegees = new intt3l tl; blots = squeegees; // NAo ti v:furoo, squeegees 6 um array bidimensional int[] bl-ocks = new int[6]; blots = blocks; / / OK, blocks 6 um array int
de arrays
int
JAVA
5 I3I
Preste.atengao elpgcialmente nas atribuig6es de arrays envolvendo dimens6es dif".ente". VocA pode, por exernplo, ser i.r.rdagado se 6.vilido atribuir um array int ao primeiro elemento de um array composro de arrays int, c&no
nas linhCI a seguir:
int[] tl books = new inr[3] []; int[] numbers = new intt6l; int aNumber = 'l i books[0] = aNumber; //NA.o 6 vdlroo, espera-se um array books[0] = nunbers, //vALrDo, numbers 6 um array int
A Figura
r-nt. em vez de um
valor int
Blocos de Inicializageo
E
falamos sobre dois lugares de uma classe onde voc6 pode colocar c6digo que realize operag6es: m6todos e contrutores. Os blocos de inicializagio.sio o terceiro lugar, em um programaJava, onde as operag6ei poi.- t.t r."lir*I"r. Os blocos de y".ldrye.- t"fap quando aclasse garregadapeQprimelavez (umbloco deitticializ"gio esrfuico) ouquandouma insdncia6 criada (um bloco de inicializagio de instAncia). Vejamoi um exemplot
Cat obj6to
aluffy
-n r a o .loato uh a.r.y 8m pdo- .. t.f.stE Cat t-D . u
Variavel de referencia ao
ArayCatllll2-D
o .loato
cahtl r.l.rlr
inv6lidos
Arrays
|
I
um array 1-D a uma I refer6ncia a array 2-D I B mycats = myCats [0] tOl ; | N5o 6 possivel atribuir um objeto ndo-array a // I uma refer6ncia a array 2-D I c mycats [1] = mycats [1] l2l; | possivel atribuir um objeto ndo-array a I / / Nl,o 6 uma referncia a array 1-D D myCats [0] [1] = morecats' / / N5o 6 possivel atribuir um objeto array a uma refer6ncia n5o-array // qats [0] [1] s6 pode se referir a um objeto Cat
"*,r,
----------*
v61.ido
---"-"--'--">
Inv6lido
a sintaxe dos
. ,rio ,.iorrram
class rnit
rnit(int x) { system.out'println("1-arg const"); } InitO { System.out.println("no-arg const") ; } static { System.out.println("1st static init"); }
nl- ln("1st { efrullr!vuu.yt4.Ae+ I Slzstem.orri-nri
insl-a.nce init");
} } }
Static
init");
I r I I
Osblocosde'tncialuagXoest6ticosrodamumavez,quandoaclasre.6.carregadapelaprlmeiravez.
Os blocos de inicializagio de instincias rodam sempre que uma instl.ncia de classe 6 criada. Os blocos de inicializagio de instAncias rodam depois da chamada que o construtor faz a super ( )
essas regras
.
Com
em mente, a seguinte
sai
da deverifazer sentido:
class hitError { static int [] x = new i-nt[4]; static { xt4l = 5; } // indice de array inv6.1ido! public static voj-d main(String [] args) { }
JAVA5 I33
J
Exception in thread *main" j ava. 1ang. Exceptionrnrnitial_izerError Caused by: java. lang.ArraylndexOutOfBoundsException: 4
3)
Porconuengdo, os b/ocos de inicialiqagdo nonzalmente aParecempertt do inicio do arquiuo da c/asre, en algum lugarpefto rlot construtores. Entretanto, utamosfalandn do exame SCJP aqui. Itfdo se surpreenda se acharum bloco de inicialiqg4do esconditlointre alguns ndtodos, di$argado de um en'o de nmpilapao prlnta para acontecer!
nl
r. \,roleTtvo poro
..f. o cefitttcocoo
Fornecer um mecanismo para "empacotar" valores primitivos em um objeto de modo que possam ser incluidos em atividades reservadas a obietos, como ier adicionados a coniuntos on retornadbs de um m6todo que tenha como valor de retorno um objeto. Observagio: com a adigio do autoboxing (e unboxing) emJava 5, que veremos- daqui a algumas p6ginas, muitas das operag6es de wrapping que os programadores costumavam fazer mantalmente agora sio feitas de forma autom6tica. Fornecer um conjunto de fung6es utilitirias para tipos primitivos. A maioria dessas fung6es esti relacionada com v6rias convers6es: de-tipos primitivosem.objetbs Siring e vice-versa, de tipos primitivos e objetos String para bases (ou radicais) diferentes - como binirias, octais e hexadecimais, e viie-virsa.
NumberFormatException se a String fornecida nio puder ser converrida no ripo primitivo apropriado. Por exemplo, "dois" nio pode ser convertido em "2". Os objetos wrapper sio inaltir6veis. lJma vez que receberem um valor, ele nio poderi ser alterado. Falaremos mais sobre a imutabilidade dos wrappers quando estivermos discutindo o boxing, daqui a algumas p6ginas.
saber as tr6s abordagens mais comuns para a criaglo de objetos wrapper. Algumas abordagens usam a representagio em String de um tipo primitivo como argum.nto. Ar qrre .tram Strings lanEario
Os construtores wrapper
Todas as classes wrapper exceto Character fornecem dois construtores: um que usa como argumento o tipo primitivo que esta sendo criado e outro que usa uma representagio em String do tipo sendo Jonstruido. Pbr
exemplo,
fntegfer
ou
i1 hteger i2
Fl-oat f1
E
(3.IAf\
roaL
12
Tipo primitivo
Classe wrapper
Argumentos do construtor
Boolean
Boolean
booleano ou String
Byte
Char
Byte
byte
char
ou
String
ou
Character
Double
Double
String float ou String Float Float int ou String Int.eger Int long ou String Long Long short ou String Short Short A classe Character fornece s6 um construtor, que usa o tipo char como argumento. Por exemplo, Character c1 = new Character('c'); Os construtores da classe wrapper Boolean usam um valor booleano true ou f a1se, ou uma String que nlo
double
diferenciamaiusculasdeminisculascomovalortrue oufalse.AntesdeJava5,umobjetoBooleanniopodiaser
usado como expressio em um te$e
booleano - por exemplo, Boolean b = new Boolean("fa1se") ; // ndo compila com Java 1.4 ou anterior
i f /h\
ApartirdeJava5,umobjeto Boo:.earropodcserusadoemumtestebooleano,porqueocompiladorir6,f.aznr
automaticamente o unboxing do objeto para um na pr6xima seglo - entio fique alena!
boolean. Iremos
Os dois (bem, geralmente dois) m6todos estiticos valueof ( ) fornecidos na maioria das classes wrapper lhe proporcionario outra abordagem paraacriaglode objetos wrapper. Os dois m6todos usam uma Stringpara representar o iipo apropriado de seu primeiro argumento, sendo que o segundo m6todo (quando fornecido) usa um argumento a&cional, int radix, que indica em que base (como 6in6ria, octal ou hexadecimal) o primeiro argumento foi representado. Por exemplo,
Os m6todos valueOf( )
/ / nbi'ero
I vv)Yvv
Tnfcacr
i2
m<Value( )
Quando voc6 precisar converter o valor de um objeto wrapper num6rico em um tipo primitivo, use um dos muitos m6todos xxxValue ( ) . Todos os m6todos dessa familia sio m6todos sem argumentos. Como voc6 pode ver na Tabela 3-3, existem 32 m6todos xxxValue ( ) . Cada uma das seis classes v/rapper num6ricas possui seis m6todos, de modo que todos os objetos wrapper num6ricos podem ser conveftidos em qualquer tipo primitivo num6rico. Por exemplo,
JAVAs 135
/
/
vm
Aa sv
/ / / ,
Taraaar
/ mais
um m6todo
xxxValue
/ / Aa 'rnranar
out.println
(s ) ;
/ // // // //
/
objeto wrapper converxe o valor de i2's em um primitivo short o resultado 6 3 (truncado, nao
um novo
cria
arredondado)
n=excegeoNFE
ByeVdue
doubleValue FloatVdue IntValue IongVahre ShortMue
ParseX:o<42
Boolean
Byt
Character
Double
Float
Integer
Iong
Short
valueOf. s,n
valueOf
s,n
(com abase)
Tosfting
toStringi(primitivQ x
toString
s
(primitivo,
as
base)
Resumindo,
pansexuO e valueOf( ) Os seis m6todos parsexxx ( ) (um de cada tipo wrapper num6rico) estio intimamente relacionados com o m6todo va]ueof ( ) que existe em todas as classes wrapper num6ricas. Tanto parsexxx ( ) quanto valueof ( ) usam
uma String como argumento, langamuma excegio NuberFonnatException se o argumento Stringnio estiver no formato apropriado e podem convener objetos String de diferentes bases (radicais), quando o tipo primitivo subjacente for qualquer um dos quatro tipos inteiros (consulte a Tabela 3-3). A diferenga entre os dois m6todos 6 que:
136 Copitulo 3: Atribuiqoes double d4 = Double.parseDouble ("3.14") System.out.println("d4 = " + d4); Double d5 = Double.valueOf ("3. 14" ) ;
;
System.out.println(d5 instanceof Double long L2 = Long.parselong("101010", 2); System.out.println("L2 = " + L2) ; Long L3 = Long.vafueOf("101010", 2t; System.out.println("L3 value = " + L3);
/ converte um Strinq em um primitivo // o resul_tado 6 "d4 = 3.14" / / cria um objeto Double // o resultado 6
/
Os exemplos abaixo envolvem o uso da base como argumento (nesse caso, biniria):
/ // // //
/
bin6ria para um primitivo o resultado 6 "L2 = 42' Strrng bin6ria para objeto Longl o reswLtado 6 "L3 value = 42"
S:uring
toString( )
A
classe Object, que 6 a classe primordial, o item superior, possui um m6todo toString ( ) . Como sabemos que todas as outras classes Java sXo herdadas da classe Object, tamb6m sabemos que todas elas t6m um m6todo
toString(
). Oobjetivodom6todo
toString( ) 6permitirquevoc6obtenhaalguma
toString ( toString (
representagdosrgnficatiua
de determinado objeto. Por exemplo, se voce tiver um conjunto de v6rios tipos de objetos, poderi percorrA-lo e exibir alguma forma de representagio significativa de cada objeto usando ) , que com cefteza pode ser encontrado em todas as classes. Discutiremos mais o m6todo ) no capitulo sobre Conjuntos, mas, por enquanto, enfocaremos como esse m6todo est6 relacionado com as classes wrapper que, como sabemos, ) sem sio marcadas com f ina1. Todas as classes wrapper possuem a versio de uma in$6ncia de
toString (
atgamentls
ndo-sLaLic.
Esse
m6todo retorna uma String com o valor do tipo primitivo encapsulado no objeto.
Por exemplo,
System.out.println("d= " +d.tostring0 l; // o resuLtado6 "d= 3.14" Todas as classes wrapper num6ricas fornecem um m6todo static toString ( ) sobrecarregado que usa o tipo num6rico primitivo apropriado (oouble. toString ( ) usa um double, Long. toString ( ) usa um
long,
e assim
por diante)
e, 6
Stri-ng d = Double.toString(3.14)
/ d = "3.t4"
Para concluir, as classes Integer e Long fornecem um terceiro m6todo toString ( ) . Ele 6 sLatic, seu primeiro argumento 6 o tipo primitivo apropriado e o segundo 6.luma bas, O argumento da base informa ao m6todo p^r^ peg r o primeiro argumento (que, por pa&io, estari na base 10 ou teri o radical 10) e convert6Jo para a base fornecida, retornando, em seguida, o resultado como uma String. Por exemplo,
String s3 = Integer. toHexstring(254) ; / / converLe 254 para hexa system.out.println("254 in hex - " + s3); // o resultado 6 "254 in hex = fe" String s4 = Long.tooctalstring(254); // converLe 254 para octal System.out.println("254 in octal = "+ s4); // o resul-tado 6 "254 in octal =
Estudar a Tabela 3-3
376"
as
diferengasentre
6.
melhor maneira de
se
Se
),devesesairbemnessapartedoexame.
Autoboxing
Introduzido emJava 5, este recurso 6 conhecido por vlrios nomes: autoboxing, auto-unboxing, boxing e unboxing. IJsaremos os termos boxing ("encaixotar") e unboxing ('desencaixotar'). Boxing e unboxing tornam mais conveniente o uso de classes wrapper. Antigamente, no mundo pr6-Java 5, se voc6 quisesse criar um w rapper, abriJo, usiJo e depois
fech6lo novamente, vocA poderia fazer algo como:
/ cria / / abre
/
/ / rrca aql-a
JAVA
I37
y = new fnteger(x),'
Svstem orrl- nrinf
vgu.yt4rrUJlr\f_
/ / fecha novamente
= " + it. / / exibe
lnI"rr
/ // // //
exlbe
Y=568
E sim, voc6 leu corretamente. O c6digo parece estar usando o operador de p6s-incremento em uma vari6vel de referdncia a objeto! Mas isso 6 simplesmente uma conveniAncia. Nos bastidores, o compilador faz o unboxing e a reatribuigio para voc6. Anteriormente, n6s mencionamos que os objetos wrapper sio imut6veis... Este exemplo parece contradizer isso. Com certeza parece que o valor de mudou de 567 para 568. Mas o que realmente aconteceu foi que um segundo objeto wrapper foi criado, e o seu valor foi definido como 568. Se pelo menos n6s pud6ssemos acessar aquele primeiro objeto wrapper, poderiamos provar isso...
Integer Y =
T- | rllLeljer ^-^e ^ -
567;
y,
System.
out.println
(y==x)
Y++ i
/ // // // // //
/
verifica se elas estao se referindo ao mesmo objeto abre, usa, fecha novarnente
exibe os valores verifica se elas estao se refcri ndn : ntrietos diferentes
Erue
567 568
false
Assim, nos bastidores, quando o compilador chegou
int x2 = y.intValue0 ;
x2++;
y = new Integer(x2);
Boxing, ==requalsQ
parafaznr uma pequena exploragio dos wrappers. Vamos dar uma olhada com mais detalhes em como os wrappers trabalham com : : , ! : e equal s O . Falaremos muito mais sobre o m6todo equal s O em capitulos posteriores. Por agora, tudo o que temos de saber 6 que a intengio do m6todo equals ( ) 6 determinar se duas instAncias de uma dada classe slo "significativamente equivalentes". Essa definigSo 6 subjetiva de prop6sito; fica a cargo do criador da classe determinar o que significa "equivalente" para os objetos da classe em questio. Os desenvolvedores da API decidiram que, para todas as classes wrapper, dois objetos sio iguais se forem do mesmo tipo e tiverem o mesmo valor. Nio deve ser surpreen&nte que
Acabamos de usar
::
Integer i1 = 1000; Integler i2 = 1000; if (i1 != i2) System.out.println("different objects") ; if (i1. eguals (i2) ) System. out.println( "meaningfully egual" ) ;
valor
int,
true.
E quanto a
isoaqui:
Integer i3 = 10; Integer i4 = L0; if (i3 == i4) System.out.println("same object") ; if (i3.equa1s (i4) ) System.out.print.ln( "meaningfullv
Este exemplo produz a saida:
equa1" ) ;
diiendoqueil- ei2
sXoobjetosdiferentes,quando:: est6dizendoquei3
economizar mem6ria, duas instAncas dos seguintes objetos wrapper foremo mesmo:
: : s : Por que razio : est6 nos ei4 sioomesmoobjeto?Para. . serio sempls : : quando os seus valores primitivos
! ? !
I I r I
Boolean
Byte
emdecimal)
class UseBoxing { public static void main(String [] args) UseBoxing u = new UseBoxingO ; u.go(5);
]
boolean go(Integer i) { // encapsula o int que recebeu Boolean ifSo = true; // encapsula o literal Short s = 300; // encapsula o primitivo
if (ifso)
i
t
.
System. out
println
++s ) ;
novamente
return !ifSo;
J
nat queplssan
lanprumaNullPointerException.'
JAVA5 I39
Pzrqae
Ette aidigo conpila unproblemas, mat aJI/M knga umaNullPointerException quando tenta ehamardoSXuf x nio se refere a um oQeto Integec pnftantl, ndo hi nenbum ualor para abir.
(?<),
um mitodo eshi sobresmuendo oa sobncamgando comtanente ouho mitodo, para o mitodo en questdo.
identifcar
5.4 Dado un ceniio, dueruolueraidigo que dulan ef or ebame mdtodat sobrescritos ou sobrecamgados...
Embora ji tenhamos abordado algumas regras para a sobrecarga de m6todos no Capitulo 2, neste capitulo n6s adicioaaremos alguns itens ) nossa caixa & ferramentasJava. Nesta segio, daremos uma olhada em ti6s fatores que podem difi cultar um pouco a sobrecarga:
- Correspondncia
de M6todos
r I f
Ampliago
Autoboxing Var-arp
Quando umaclassetem m6todos sobrecarregados, umadastarefas do compilador6 determinar qual m6todo usarsempre nlo usanenhumrecurso novo deJava5:
class EasyOver { static void go(int x) { System.out.print("int "); } sLatic void go(long x) { System.out.print("1ong "); } static void go(double x) { System.out.printl"double "); public static void main(String [] args) t byte b = 5; short s = 5; long 1 = 5; float f = 5.0f;
go (b) ; go (s)
; ;
so (1)
go(f );
)
se
encontrada,
JVM
VocA pode verificar que, se houver apenas uma versio do m6todo go ( ) , e ele usar um double, essa versio todas as quatro chamadas a go ( ) .
se
r|usaAapara
class AddBoxing { static void gro(Integer x) { System.out.println("Integer"); static void go(1ong x) { System.out.println("1ong"); }
public static void main(String [] args) int i = 5; 9o (i) ; / / q)al go O ser6 chamado?
]
]
permitiria que go ( )
se a tnica versio de go ( ) fosse a que usa um Integer, o recurso de boxing de Java 5 fosse chamado com sucesso. Da mesma forma, se apenas a verseo long existisse, o comPilador a usaria para lidar com a cham adaago ( ) . A questXo 6, dado que ambos os m6todos existem, qual deles ser6 usado? Em outras palavras, seri que o compilador pensa que ampliar um parAmetro primitivo 6 melhor do que realizar uma operaEio de autoboxing? A resposta 6 que o compila dor preferirlaampliagio, entio a saida seri:
long
Os elaboradores deJava 5 decidiram que a regra mais imponante deveria ser que os c6digos pr6existentes devem continuar funcionando como antes, entio, uma vez que o recurso de ampliagio j6 existia, um m6todo chamado por meio da ampliaglo n5o deveria ser trocado por um m 6todo rec6m-criado que depende do boxing. Com base nessa regra, tente prever a saida do seguinte c6digo:
class Addvarargs { static void go(int x, int y) { System.out.println("int,int");} static void go(byte... x) { System.out.println("byte... "); public static void main(String[] args) {
byte b = qo{b,b);
)
5;
chamado?
a saida 6
int, int
Porque, mais uma vez, mesmo que cada chamada requeira algum tipo de conversio, o compilador escolher6 o estilo antigo em vez do estilo novo, mantendo os c6digos existentes mais robustos. At6 aqui, vimos que:
r r
A ampliagio A ampliagio
as
6 6
Neste ponto,
class BoxOrVararg { static void gro (Byte x, Byte y) { System.out.println("Byte, Byte") ; } static void go(byte... x) { System.out.println("byte...
");
JAVA
5 I4I
public static void main(StrinS [] args) { byte b = 5; qo (b, b) ; // qoaT go$ ser6 chamado?
) )
E a saida 6
Byte, Byte
IJma boa maneira de memori zar essa regra t.perceber que o m6todo var-args 6 mais "solto" que o outro m6todo, no sentido de que ele pode lidar com chamadas contendo qualquer nrimero de parAmetros int. Um m6todo var-args funciona mais como um m6todo de captura total, em termos & quais chamadas ele pode lidar; e, como veremos no Capitul o 5,faz mais sentido que recursos de captura total sejam usados c omo vm illtimo recurso.
Animal_
Mantendo
a = new DogO;
mesmo raciocinio, uma chamada poderia ser:
esse
void go(Animal a) {
)
Sem problemas! O m6todo go ( ) precisa de um Animal, e Dog3 f-UM Rni*al. (I-embre-se de que o m6todo go ( ) pensa que est6 recebendo um objeto Animal, entXo ele lhe pediri que faga apenas coisas referentes a Animal, as quais, 6 claro, qualquer coisa que herdar de Animal tamb lmpoderifazer.) Assirn, neste caso, o compilador amplia a referAncia Dog3 para
um Animal,
e a chamada tem sucesso. A principal questlo aqui 6 que a ampliagio da refer6ncia depende da heranga" em outras palavras do teste E-IJM. Por causa disso, nio 6 vilido ampliar de uma classe wrapper para outra, porque as classes wrappersXo semelhantes entre si. Porexemplo, NAO 6 vfido dizerque Short E-UM Integer.
oBSERVAq6ESpeneoE)(AME
E
tentadorpensar que
uocd poderia
0 seguinte exemp/o
I\AO
rcrrpilar,i:
class DagL { pubfic static void main(String [] args) { Dog4d=newDog4O; d. test (new Integer (5) ) ; ,/,/ impossivel ampliar
| / / / ^^-^ IJAL q ..* UrL T ^6!V1r9
um
Inteqer
I--embre-sedequenenhartadasclasseswr@perpodeseamp/iardeumaparaoutralByLes
ndo
se
ndoseampliamparashorts,Shorts
ampliamparaLongs,
etc.
class WidenAndBox { sLatic void go(Long x) { System.out.println("Long"); } public static void main(String [] args) { byte b = 5,' go (b) ; / / preclsa ampliar e depois fazet boxing - inv6lido
)
Isso 6 &mais para o
compilador:
gto
(
WidenAndBox.
Mas o 6 estranho que o compiladorPODE fazerumaoperagio de boxingseguidaporumaopera$o criar uma corresponddncia entre chamada e m6todo. Este exemplo podera lhe deixar confuso:
um
objeto Byte
public static void main(String [] args) t byte b = 5; go(b); // este byte pode ser transformado
) )
Esse
em um
Object?
a saida:
1. O byte b foi encapsulado com boxing em um Byte. 2. A referncia Byte foi ampliada para se tornar um Object (uma vez que Byte estende Object). 3. O m6todo go ( ) recebeu uma refer6ncia Object que, na verdade, aponta para um objeto Byte. 4. O m6todo so ( ) convefteu a referOncia Object de volta para uma refer6ncia Byte (embre-se, nunca
um objeto do tipo Object neste cenirio, apenas um objeto do tipo Byte!).
houve
5.
de
Byte.
Porque o compiladorniotentouusaral6gicaboxingdepois-amplia$o quando tentoulidarcom aclasse WidenAndBox? Pense nisso... Se ele tentasse fazer boxing primeiro, byte seria convertido em um Byte. E ai estariamos de volta i situagio & tentar ampliar um Byte para um Long e, 6 claro, o teste E-UM falha.
class Vararg { static void wide-vararq(1ong. . . x) { System.out.println("1ong. . . " ) ; } static void box_vararg(Integer. . . x) { System.out.println( "fnteger. . . " ) ; public static void main(String [] args) t
wide-varars(5,5); box_vararg(5,5) ;
// precisa ser ampliado e usa var-args / / preclsa ser encapsul-ado com boxing e usa var-args
JAVA
'143
]
Esse
long.
Integer...
Como podemos ver, 6 possivel combinar com sucesso var-args corn ampliagio ou com boxing. Eis uma revisio das regras para m6todos sobrecarregados que usem ampliaglo, boxing e var-args:
r I r r I
A ampliagio de primitivos
usa o
sobrecarga.
NAO
possivel ampliar de um tipo wrapper para outro. possivel ampliar e depois fazer boxing.
@-tnt frlha.;
nlo pode se tornar um Long)
se
NAO
(Jm
int
E possivel fazer boxing e depois ampliar. (Um args com ampliagio ou com boxing.
int
pode
Existem aspectos mais complexos relativos i sobrecarga, mas, tirando algumas poucas regras referentes aos gen6ricos (que abordaremos no Capinrlo /), isso 6 tudo o que voc6 percisarl saber para o exame. Caramba!
Esta 6
da mem6ria 6 um elemento crucial em muitos tipos de aplicativos. Considere um programa que leia grandes quantidades de dados, digamos, em algum local de uma rede e, em seguida, os grave em um banco de dados na unida& de disco rigido. Umpro.ieto tipico serialeros dados em algumtipo de conjunto namem6ria, executar algumas operag6es com eles e grav6Jos no banco de dados. Depois que os dados fossem gravados, o conjunto que os armazenou temporariamente precisaria eliminar os dados antigos ou ser excluido e recriado antes do processamento do pr6ximo lote.
O gerenciamento
+,queniooferecemacoletaautom6ticade Essaopera$opodeserexecutadavAiuvezns,eemlinguagenscomoCouC+ lixo; uma pequena falha na l6gica que ewazie ou exclua as estruturas de &dos do conjunto pode permitir que pequenas quantidades da mem6ria sejam inadequadamente recuperadas ou perdidas. De maneira definitiva. Essas pequenas perdas sXo chamadas de uaTamentot de memriia, e depois de virias iterag6es podem tornar inacessivel uma quantidade suficiente de mem6ria para finalmente causar a interrupgio dos programas. A criagio de um c6digo que execute o gerenciamento manual da mem6ria de maneira limpa e completa 6 uma tarefa complicada e nio trivial, e embora as estimativas variem, 6 discutivel se esse gerenciamento manual pode dobrar o esforgo de desenvolvimento de um programa complexo. O coletorde lixo dalinguagemJavaforneceumasolugio automhticaparaogerenciamento damem6ria. Namaioriados casos ele o livrari de ter que adicionar alguma l6gica de gerenciamento da mem6ria em seu aplicativo. A &wantagem da coleta de lixo autom6tica 6 que voc6 nlo poder6 controlar exatamente quando ela ser6 ou nio executada.
colaade lixo.
heap
Un
irzplesaente am he@. No exane rcni inportantu saber que uocd pode chaad-lo de be@, de heap
de cokta de
lixo,
de
bi
um
beap.
Portanto, todo o assunto da coleta de lixo gira em torno de assegurar que o heap tenha tanto espago disponivel quanto possivel. Para os fins do exame, isso se resume em excluir qualquer objeto que nAo possa mais ser alcangado pelo programa Java que estiver sendo executado. Discutiremos melhor o que significa "poder ser alcangado", mas antes nos aprofundaremos no assunto em questao. Quando o coletor de lixo for executado, sua finalidade ser6 encontrar e excluir objetos que nio possam ser alcangados. Se voc6 imagina o programa Java em um ciclo constante de criagio dos objetos que precisa (o que ocupa espago no heap) e, em seguida, descartando-os quando nio forem mais necess6rios, criando novos objetos e descartando esses objetos, e assim por diante, a pega perdida do enigma 6 o coletor de lixo. Quando ele for executado, procurari esses objetos descartados e os excluiri da mem6ria para que o ciclo de uso e liberagio da mesma possa continuar. Ah, o fant6stico ciclo vital!
Com base neisa definigio, o coletor de lixo executa algumas operag6es desconhecidas e quando descobre um objeto que nlo pode ser alcangado por nenhum thread ativo o considera qualificado para a exclusio, e pode at6 exclui-lo em algum momento. Ou tamb6m pode nio exclui-lo nunca. Quando falamos sobre alcanparum objeto, na verdade estamos falando sobre ter uma variivel de referncia ahangiuel que aponte para o objeto em questao. Se nosso programa Java tiver uma variivel de refer6ncia que aponte para um objeto, e se ela estiver disponivel para um thread ativo, entio, esse objeto ser6 considerado alcanp,iuel. Discutiremos mais sobre como os objetos podem se tornar inalcang6veis na segio seguinte.
Um aplicativo Java pode ficar sem mem6ria disponivel? Sim. O sistema de coleta de lixo tentarS.remover os objetos da mem6ria quando eles nio forem usados. No entanto, se voc6 tiver muitos objetos ativos (objetos referenciados por outros objetos ativos), o sistema poder6 ficar sem mem6ria disponivel. A coleta de lixo nio pode assegurar que haja mem6ria suficiente, somente que a mem6ria disponivel ser6 gerenciada tio eficientemente quanto possivel.
removidos da mem6ria.
que possam ser alcangadas. E claro que se nlo houver refer6ncias alcang6veis, nio diz respeito, ele ficar6 apenas flutuando no espago, sem ser utilizado ou acessado,
torna qualificado para a coleta de lixo quando nlo h6 mais referAncias a ele imponari o destino do objeto. No que nos nio sendo mais necessirio.
a refer6ncia a um objeto 6 configurar com estiver apontando para ele. Examine o c6digo a seguir:
nulf
avari|vel
de refer6ncia que
JAVA
I45
1. public class GarbageTruck { 2. public static void main(String [] args) { 3. StringBuffer sb = new StringBuffer ( "hello" ) ; 4. System.out.println(sb) ; 5. // O objetoStringBuffer nao esta qualificado para coleta 6. sb = nul1; '7. / / Agora o objetostringBuffer est.6 qualificado para coleta B. ) 9. ] A variivel de refer6ncia sb foi atribuida ao objeto StringBuffer de valor hell-o na terceira linha. Para torn6-lo qualificado (ptara a coleta), configuramos a variivel de refer6ncia sb com null, o que remover| a inica refer6ncia ao objeto StringBuf f er que existia. IJma vez executada a linha 6, nosso objeto StringBuf f er
he11o
estar6 condenado, qualificado para a coleta de lixo.
class GarbageTruck { pubLic static void main(String [] args) { StringBuffer s1 = new StringBuffer("hel]o"); StringBuffer s2 = new StringBuffer("goodbye")
q\rql- am nrrf
vJ s ev.'r.
// Neste ponto, o StringBuffer "hell-o" nao est5 qualificado s1 = s2; // Redireciona s1 para refer6ncia ao objeto "goodbye" / / Agora o StringBuffer "hel1o" est5 qualificado para coleta
)
i
Os objetos criados em um m6todo tamb6m precisam ser considerados. Quando um m6todo for chamado, qualquer vari6vel local que for criada s6 existir6 durante a execugio do m6todo. Uma vez que o m6todo tiver sido concluido, os objetos criados nele estario qualificados para a coleta de lixo. H6 uma excegio 6bvia, no entanto. Se um objeto for retornado do m6todo, sua refer6ncia pode ser atribuida a uma variivel do m6todo que o chamou; assim, ele nio estari
Date
t
I
fl:rl-r:naE'ani-nrrz
();
System.out.println("d = " + d) ;
return d2;
] ]
) que retorna um objeto Date. Esse m6todo cria dois objetos: um objeto Date e uma StringBuffer contendo as informag6es sobre a data.li que o m6todo retorna o objeto Date, ele nio esterS, qualificado para a coleta mesmo depois que o m6todo for concluido. O objeto StringBuffer, no entanto, estar6 qualificado, ainda que nio tenhamos configurado explicitamente a variivel now
com
null-.
classe que tivesse uma vari6vel de instAncia que fosse a variivel de refer6ncia de outra instAncia & mesma classe. Agora imagine a exist6ncia de duas instAncias desse tipo referenciando uma a outra. Se todas as outras referAncias a esses dois objetos forem removidas, entio, embora cada um dos objetos ainda tenha uma referdncia v61ida, nio haveri como algum thread ativo acessar um deles. Quando o coletor de lixo for executado, ele descobrir6 esas ilhas de objetos e as remover6. Como voc6 pode imaginar, as ilhas podem se tornar bem grandes, contendo teoricamente centenas de objetos. Examine o c6digo a seguir:
i4.i
nrrl l :A - nrr'l I.
mem6ria
Quandooc6digoalcangar I / realiza tarefas. . .,ostr6sobjetoslsland(antesconhecidoscomoi2, i3 ei4) terio variiveis de instAncia para que apontem um para o outro, mas seus vinculos com o ambiente externo (i2, i3 e i4) terio sido anulados. Esses tr6s objetos estarAo qualificados para a coleta de lixo.
Abordamos tudo que voc6 precisa saber sobre tornar objetos qualificados para a coleta de lixo. Estude aFigara3-7 para refor7ar os conceitos de objetos sem referOncias e ilbas de inlanento.
As rotinas de coleta de lixo que a Java fornece sio membros da classe Runtime. A classe Runtime 6 uma classe especial que possui somente um objeto (o objeto Singleton) para cada programa principal. O objeto de Runtime fornece um mecanismo de comunicagio direta com a m6quina virtual. Para capturar a instAncia de Runtime, voc6 pode usar o m6todo Runtime. getRuntime ( ) , que retornari o objeto Singleton. Assim que tiver o Singleton, voc6 pode chamar o coletor de lixo usando o m6todo gc ( ) .
Alternativamente, vocA pode chamar o m6todo da classe System, cujos m6todos static sio capazes de obter o objeto Singleton para voc6. A maneira mais simples de solicitar a coleta de lixo Qembre-se: 6 apenas uma
solicitaEio) 6 atrav6s de:
Qa'cf6m nI I
JAVA
I47
Teoricamente, depois de chamar System. cg ( ) , voc6 ter6 tanto espago livre na mem6ria quanto possivel. Dissemos teoicamente porque essa rotina nem sempre funciona assim. Primeiro, a JVM que voc6 estiver usando pode nXo tAJa implementado; a especificagio da linguagem permite que essa rotin^ nilo tenha absolutamente
nenhumafungio.
Island n; public static void main(St.ring [] args) Island i2 = new IslandO; ls1and i3 = new IslandO: Tsland i4 = new Island(): l-l.n = t-J i3.n = i4 i4.n =i2 i2 = nul1; i3 = null; i4 = nu11; doCourlexstuff O;
m@
til
ma
lndicava uma
-} .@.,
public class LosE { public static void rnain(Strinq {} args) Lost x = new tost O: x = nul1;
docomplexstuff ( ) :
)
apagada
Com isso, nio queremos dizer que Sytem. gc ) 6 um m6todo inrltil - 6 muito melhor que nada. Mas 6 que voc6 nio pode confiar em system. gc ) para liberar um espago suficiente na mem6ria de modo que nXo precise se preocupar com a execugeo da coleta de lixo. O exame da certifica$o estari interessado em um comportamento garantido, neo num
prov6vel.
Agora que estamos um porlco familiarizados com a maneira como isso funciona, .f".E1"gr alguns testes para ver se conseguimos constatar os efeitos da coleta de lixo. O programa a seguir nos permitir6 saber quanto espago total na mem6ria a J\&I tem disponivel para ele e quanto desse espago esti livre. Em seguida, ele cria 10 mil objetos Date. Depois disso, nos informa quanto espago sobrou na mem6ria e chama o coletor de lixo (que, se for executado, deve interromper o programa at6 que todos os objetos nio utilizados sejam removidos). O resultado final do espago livre na mem6ria deve indicar se ele foi executado. Examinemos o programa:
f . import java.util.Date; 2. public class Checkcc { 3. public static void main(String [] args)
4.
5.
Runtime
System.
7.
8.
q
l_0.
Memory
"
+ rt.totalMemoryO ); rt.freeMemoryO );
11.
1,2.
13. L4.
out.println ( "After Memory = r' + rt. freeMemory ( ) ) ; rt.gc(\; // uma alternativa a System.gco System.out.println("After GC Memory = " * rt.freeMemoryO );
System.
15.
1-6. ]
verificaremos os resultados:
Total
J\,rM
memory: 1048568
After
cC Memory = 8L8212
Como podemos ver, o VM realmente decidiu coletar (isto 6, excluir) os objetos qualificados. No exemplo anterior, sugerimos I JVM que executasse a coleta de lixo com 458.048 bytes de mem6ria restantes e ele atendeu nossa solicitaglo. Esse programa s6 tinha o thread de um usuirio sendo executado, portanto, nio havia nada mais acontecendo quando chamamos rt. gc ( ) . Nio se esquega de que o comportamento quando gc ( ) 6 chamado pode ser diferente em JVMs distintos, de modo que nio haver| garantias de que os objetos nXo utilizados serlo removidos da mem6ria. A rinica coisa garantida 6 que se voce estiver ficando com muito pouco espago na mem6ria, o coletor de lixo ser6 executado antes que uma exceglo outofMemoryException seja langada.
Exercfcio 3-2
Experimente modificar o programa CheckGC colocando nem toda a mem6ria 6 liberada com uma passada de GC.
as
o m6todo finalize( )
executado imediatamente antes que um objeto seja
seja
finalize( ) quetodasasclassesherdamda Object. A primeira vista parece uma grande idliutilvez reu objeto tenha abeno alguns recursos que voc6 gostaria de fechar antes que ele fosse excluido. O problema 6 que, como vod jl deve ter deduzido, nlo 6 possivel contar com o coletor de lixo para excluir o objeto. Portanto, nenhum c6digo que voc6 insira no m6todo f inalize ( ) sobrescrito de sua classe teri a execugio garantida. O m6todo f inalize ( ) de um objeto especifico pode ser executado, mas nio hi como contar com ele; enteo, neo insira nenhum c6digo essencial nesse m6todo. Na verdade, recomendamos que voc6 nlo sobrescreva de forma alguma f inalize ( ).
excluidopelocoletordelixo.Essec6digoficar6emumm6todochamado
I r
Chamar
inalize ( ) seri chamado apenas umavez (no maximo) f inalize ( ) pode resultar em salvar um objeto da exclusio.
Examinaremos essas declarag6es com mais detalhes. Em primeiro lugar, lembre-se que f inalize ( ) 6 um m6todo e qualquer c6digo que voc6 puder inserir em um m6todo conum poderi inserir em f inalize ( ) . Por exemplo, no m6todo f inalize ( ) voc6 poderia escrever um c6digo que retornasse uma refer6ncia ao objeto em questio para outro objeto, duqualficando efetivamente o objeto para a coleta de lixo. Se em algum momento posterior esse mesmo objeto se tornar novamente qualificado para a coleta de lixo, o coletor ainda poderi processar e exclui-lo. No entanto, ele lembrar6 que f inalize ( ) jLf.oi execttado paraesse objeto, e nio processar6 o m6todo mais uma vez-
e as
vari6veis de
Revisamos os literais v6Llidos para tipos primitivos e Strings, e depois discutimos os fundamentos da atribuigio de valores tipos primitivos e a vari6veis de refer6ncia, al6m das regras para conversXo de primitivos.
Em seguida, discutimos o conceito de escopo, ou "por quanto tempo esta vari6vel viver6?" Lembre-se dos quatro escopos bisicos, do maior para o menor tempo de vida: static, instance, local, block.
JAVA
I49
as implicag5es de se usar variiveis nio-inicializadas, e a imponincia do fato de que as vari6veis locais receber um valor explicitamente. Falamos sobre alguns dos aspectos complicados de se atribuir uma variivel de referAncia a outra, e alguns dos detalhes sobre a passagem de variiveis para m6todos, incluindo uma discussio
Abordamos
deaem
do "sombreamento".
O t6pico seguinte foi
a
multidimensionais.
Continuamos o capitulo com uma discussio das classes wrapper, usadas para se criar objetos imut6veis que armazenem um tipo primitivo, e usadas tamb6m para fornecer capacidades de conversio para primitivos: memorize valueof ( ) ,
xxxValue ( ) eparsexxx
Falamos sobre um novo
()
e importante recurso deJava 5, que e$a intimamente relacionado aos wrappers: o autoboxing. Boxing 6 uma maneira de automatizar o uso de wrappers, e abordamos alguns dos seus aspectos mais complexos, tais como a forma como wrappers trabalham com : : e com o m6todo equals ( ) .
Tendo adicionado o boxing I nossa caixa de ferramentas, passamos a dar uma olhada com mais detalhes na sobrecarga de m6todos e como o boxing e os var-args, em conjunto com convers6es ampliadoras, tornam a sobrecarga mais complicada. Finalmente, nos dedicamos ) coleta de lixo, o recurso de gerenciamento automitico de mem6ria deJava. Aprendemos que 6 no heap que os objetos residem, e 6 tamb6m onde toda a interessante atividade de coleta de lixo se realiza. Aprendemoi que, no fim das contas, a JVM far| a coleta de lixo quando ele quiser. VocA (o programador) pode pedir que seja feita uma coleta, mas nio pode forgiJa. Falamos sobre a coleta de lixo aplicar-se apenas a objetos que estio qualificados, e que qualificados significa "inacessiveis para qualquer thread ativo". Finalmente, discutimos o raramente rltil m6todo f inalize ( ), e o que vocA precisari saber sobre ele para o exame. No fim das contas, um capitulo fascinante.
EXERCICIO RAPIDO
Eis alguns dos pontos principais deste capitulo.
Pilha e Heap
E E
D D D E fl
de
ouhexadecimais(p.ex.Ox3d).
longs
terminam com
L ou 1.
ou com d.
alse.
Os literais para
chars
E E
O escopo refere-se
ao
E 0 fl
D
as suas classes.
As vari6veis de instAncia vivem pelo mesmo tempo que os seus objetos. As vari6veis locais vivem pelo mesmo tempo que os seus m6todos na pilha; entretanto, se o m6todo chamar outro m6todo, elas ficam temporariamente indisponiveis. As vari6veis de bloco (p.ex. em um f
or
ou em um
if)
Atribuig6es B6sicas (Objetivos 1.3 e 7.6) tr Os literais de integers sio implicitamente ints.
E B
As express6es integer sempre geram um resultado com o tamanho de Os nrimeros de ponto flutuante sio implicitamente doubles (64 bit$.
int,
nunca menor.
E Diminuir um tipo primitivo causa o corte do.s bits de ordem mais alta. D Atribuig&s compostas (p.ex. + =) realizamumaconversio autom6tica.
El
Uma vari6vel de refer6ncia armazena os bits que sio usados para se referir
As varilveis de refer6ncia podem referir-se
a subclasses a
um objeto.
E E
E B tr
tipo Button
Cria-seumnovo obietoButton
Atribui-se o objeto Button )variivel de refer6nciab
Usando uma yari6vel ou elemento de array que nao tenha sido inicializado ou atribuido (Objetivos 1.3 e 7.6)
Quando um array de objetos for instanciado, os objetos do array nio serio instanciados automaticamente, mas todas refer6ncias receberio o valor padrio nul1. Quando um array de tipos primitivos for instanciado, todos os elementos receberio seus valores padrio.
As vari6veis de insAncia serio sempre inicializxlas com um valor padrlo. As vari6veis locais/autom6ticas/de m&odo nunca recebem um valor padrio. la, receberiumerro do compilador.
Se
as
tr tr E
D D D 0 tr E
Os m6todos podem usar tipos primitivos e/ou referAncias a objetos como argumentos. Os argumentos dos m6todos sio sempre c6pias. Os argumentos dos m6todos nunca sio objetos reais (podem ser referncias a objetos)
O sombreamento ocoffe quando duas vari6veis com diferentes escopos companilham o mesmo nome. Isso leva a bugs
dificeis de encontrar, e a quest6es do exame dificeis de responder.
Declaragio, construgio e inicializagilo de arrays (Obi. 1.3) O Os arrays podem conter tipos primitivos ou objetos, mas o array propriamente
dito
sempre
ser|umobjeto.
D tr E
esquerda ou
direita do nome.
Nio
anorumo.
E fl fl 0 B tr E E E
Os elementos de um array de objetos nio sio criados automaticamente, embora os elementos de arrays primitivos
recebam valores
padrto.
se
Voc receber6 uma excegio NullPointerException referenciar um objao reai. Os arrays sio indexados comegando pelo zero.
e esse
elemento
nio
ArraylndexOutOfBoundsException ocorre
Os arrays possuem umavariivel
se
vod
invilido.
length,
O ultimo indice que voc6 poder6 acessar seri sempre uma trnida& menor do que o tamanho do array.
Os arrays multidimensionais sio apenas arrays compostos por outros arrays. As dimens6es de um array multidimensional podem ter tamanhos diferentes.
de tipos prirnitivos aceitar6 qualquer valor que possa ser promovido implicitamente ao tipo declarado para o array. Por exemplo, uma vari6vel pode ser inserida em um array
Um array
q6e
int.
E
E
Um array de objetos pode conter qualquer objeto que passe no teste E MEMBRO (ou instanceof) aplicado ao tipo declarado para o array. Por exemplo, se Horse estender a classe Animal, entio o objeto Horse poderi ser inserido em um
arraydeanimais.
Se
vod atribuir um
array
ji
&
refer6ncia ao
'I5I
Voc6 pode atribuir um arruy de um tipo a uma refer|ncia de array j6 declarada de um de seus supertipos. Por exemplo, um array Honda pode ser atribuido a um array declarado como tipo Car (supondo-se que Honda estenda a classe Car).
D Os blocos de inicializagio es6ticos rodam uma vez, quando a classe 6 carregada pela primdravez. E Os blocos de inicializagXo de instAncias rodam sempre que uma nova instAncia 6 criada. Eles rodam depois de todos os
supercon$rutores
e antes de ser
Se
aparecem no arquivo-fonte.
E E
As classes wrapper e$io correlacionadas aos tipos primitivos. Os wrappers t6m duas fung6es principais:
0 E
U
Encapsular tipos primitivos para que possam ser manipulados como objetos;
Os construtores wrapper podem usar uma String ou um tipo primitivo, exceto para Character, que s6 pode usar um tipo char. As trs familias de m6todos mais importantes seo:
E xxxValue ( ) Niousaargumentos, retornaumtipoprimitivo; D parseXxx ( ) Usa uma String, retorna um tipo primitivo, 6 static e langa a exceEio NFE; E valueof ( )UsaumaString, retornaumobjeto encapsulado,6 static elangaaexcegioNFE. D
O argumento do radical referencia
16.
bases
oed,:
8e
hex
tr
D
de
Usar
:-
com wrappers 6 complicado; v/rappers com os mesmos valores baixos (normalmente os menores
: :,
nlo serio
::.
D 0
Cl
A ampliagio
de
primitivos
usa o
sobrecarga.
D O tr
Voc6
pode
int nlo pode se tornar um Long.) (Um int pode se tornar um Object, atrav6s de um Inreger.)
Vod
E tr J
EmJava,
A finalidade
56
a
ser alcangados.
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.
tr Solicite a colea de lixo com System. gc ( ) ; (recomendado). E AclasseObjectpossuiumm6todo finalize ( ). tr Om6todofinalize( )temsuaexecugiogarantidaumavez,esumenre,/maae1antesdeocoletordelixoexcluirum
objeto.
E B
J6queocoletordelixoniotemexecugiogarantida,
Voc6 pode desqualificar um objeto para
a
finalize (
) podenuncaserexecxtado. ).
coleta usando f
inal ize (
Teste Individual
l.
Dado:
a'laq< Qcnnn {
static int throwero throws Exception { return 42; public static void main(String [] args) { try { int x = thrower0; ) catch (Exception e) i
x++;
]]]
Qual6 o resultado?
E. O c6digo
cb) i
cb = nul1;
r6f r!rh ^h.
public static void main(String11 args) CardBoard c1 = new CardeoardO; CardBoard c2 = new CardBoard0; CardBoard c3 = c1 .go(c2); c1 = null; / / faz algo
]]
Quando a execugXo chegar a /
AO
B.
1
JAVAs I53
c.2
D. A compilagio falha.
E. Nio
F. *r
6 possivel saber.
r
3. Dado: class alien { String invade(short ships) { return ..a few,.; } String invade(short... ships) { return ..many,'; i class oefender { public st.atic void main(String [] args) { System. out.println (new Alien ( ) . invade (7) ) ;
)
Qual6oreruhadol
4. Dado: 1. class Dims { 2. public static void main(String[] args) 3. inrtJU a= {{1,2,}, {3,4}}; 4. int[] b = (inttl) atll; 5. Object 01 = a, 6. inttl tl a2 = (inrt] [] ) o1; 7. inttl b2 = (int[]) o1; 8. System.out.println(bt1l ) ;
10.
Qual6 o resuhado?
L2
B.4
C f langda uma exce$o em rempo de exeor$o. D A compila$o falha devido a um erro na linha 4.
E. A compilaglo
falha devido
a
um erro na linha 5.
E A compilagio falha devido a um erro na linha 6. G A compilagXo falhadevido aum erro na linha 7.
5. Dado: class int int int
Eggs { doX(Long x, Long y) { return 1-; } dox(Iong. .. x) { return 2; }
54 Copitulo 3: AtribuiE6es
void go0 { short s ='7; System.out.print(dox(s,s) + " "); System. out.println (doX (1, I | ) ;
))
Qual6 o resultado?
,d11
8.21,
c31D.4
r-
public static void main(string[] argrs) Mixer m2 = new Mixer0; Mixer m3 = new ytixer (m2 ) ; m3 . go ( ) ; m4. go ( ) ; Mixer m4 = m3 .m1; m5.goo; Mixer m5 = m2.m1;
)
Qual6 o resultado?
A"
hi B. hi hi
\- nl- n]nl_
D. Acompilaglofalha
E. hi,
seguida de
umaexcegio
E hi
hi,seguidadeumaexcegAo
7. Dado: 1. class zippy t 2. String[] x; 3. int[] a [] = {LL,2}, {1}}; 4. Object c = new long[4]; 5. Objectl] d=x; 6. )
Qual6 o resultado?
apenas na linha 4.
5.
3 e 5.
F. A compilagio
falha devido
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
E. Acompila$ofalha.
ry | E r.: '4rrangaoa uma excegao no tempo de execu$o.
public static void main(stringll args) System.out.print(tooth + " "); final long tooth = 340L; new KnowinS ( ) .dolt (tooth) ;
Qarcram eJ u uvrrr. vuu ^rrf hFl . ^ri rrruf Pr n I f^^th \ .
]
)
Qual6 o resultado?
A. 343 340 340 B. 343 340 342 c 343 34L 342 D. 343 341, 340 E. 343 341, 343
E
\r
Acompilagofalha.
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
B. Quando uma variivel da pilha sai de escopo, ela se torna qualificadapara coleta de lixo. C. Algumas variiveis de refer6ncia residem na pilha, e algumas residem no heap.
D. Apenas objetos que nio tenham variiveis de refer0ncia apontando para
de lixo. eles podem ser qualificados para coleta
E. E possivel requisitar a coleta de lixo atrav6s de m6todos das classes j ava . 1ang. Runtime ou j ava. 1ang. System. I
l.
Dado:
{
1. class Convert { 2. public static void main(String[] args) 3. Long xL = new Long(456l); 4. long x1 = Long.valueOf("123"); Long x2 = Long.valueOf("L23"); 5. long x3 = xl,,longValue$; 6. 7. Long x4 = xl,.longValue0; 8. Long x5 = Long.parselong:("456"); 9. long x6 = Long.parselong("123"); 10. )
l_1. ]
Qual ir6 compilar usandose
laval,mx
as
corretas)
A. Linha4 B. Linha
5
C. Linha6 D. LinhaT
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. )
JAVA
I57
da linha 8. da linha 9.
a execugXo da
linha
10.
3. Dado: 1. class Bigger { 2. public static void main(Stringl] args) 3. // insira o c6digo aqui 4. )
q1
"l
Qual op@o, inserida independentemente na linha 3, ir6 compilar? (Marque todas as corretas)
,{.Faster f = Faster.Higher; B. Faster f = Better.Faster.Higher; C Better.Faster f = Bett.er.Faster.Higher,' D. gigger.Faster f = Bigger.Faster.Higher; E. Better.Faster f2; f2 = Better.Faster.Longer; E BetLer b; b.Faster = f3; f3 = Better.Faster.Longer;
14. Dado:
class Bird { { system. out.print (,'bL " ) ; } public BirdO { System.out.print("b2 ");
)
class Raptor extends gird { static { System.out.print("r1 "); } public RaptorO { System.out.print("r2 "1,
{ q\rql- am 611l- nri t vtsLe!.r. hf f \\r?
\\
\ I. } t J
new HawkO;
System.
out.println ( *hawk tt ) ;
Qual6 o resultado?
,4.
14
b1 b2 b1 b2
b2 bI b2 bl-
da saida
I. A compilagio
falha.
Respostas
I
D esti correta,avari|vel x s6 est6 no escopo dentro do bloco de c6digo try, mas nXo quando catch ou f inal1y. (Para o exame, acostume-se com esses fechamentos horriveis com
A, B, C e E estio incorretas com
base est6
) )
) .)
Cardnoard
c1
ele
tipo shorL,
de
modo que
conversio,
resposta 6 B,
'a
f el'/.
int
um
int [ ] [ ] , e nlo a um
5. G esti correta.
Duas regras se aplicam i primeira chamada a doX ( ) . Nio 6 possivel ampliar e depois fazer boxing de uma s6 vez, e os var-args sio sempre escolhidos por ultimo. Portanto, vocd nio pode ampliar shorts para ints nem longs, a fim de fazer boxing deles para Integers ou Longs depois. Mas voc6 pode fazer boxing de shons para Shorts e depois ampli6-los para Numbers, e isso tem prioridade em relagio a usar um m6todo com var-args. segunda chamada usa um simples boxing de int para Integer.
base
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.
base
7. A
essas declarag6es
B, C, D, E
este
8. Aest6
final
correta.
AsrefernciasfL,z
ef3
apontamtodasparaamesmainstAncia deFizz. Omodificador nio poderi ser transferida para um objeto diferente, mas f inal
base
tr0s variiveis long diferentes chamadas tooth. Lembre-se de que voc6 pode aplicar o modificador f inal a vari6veis locais, mas neste caso as duas vers6es de tooth marcadas com f inal nXo sio modificadas. O rinico tooth cujo valor se modifica 6 o que nio est6 marcado com f ina1. Este programa demonstra uma mA pritica conhecida como sombreamento.
e
A, B, C, E, F
10.
base
JAVA5 159
A est4 incorreta porque se o objeto for salvo da coleta de lixo na primeira vez que o seu m6todo f inalize ( ) forexecutado,enteo,nasegundavezqueoobjetoestiverprestesasercoletado, finalizeO nlorodar6.B esr6 incorreta - a coleta de lixo nXo lida com variiveis de pilha. D est6 incorreta porque os objetos podem residir em "ilhas de isolamento" e serem qualificadas para coleta de lixo. (Objetivo 7.4)
11.
A, D
B, C
essas
compilar.
e
12.
definida como
os
e2 f.oi Gest6correta. IJmerronalinhal0fazcomquesejalangadaumaNullPointerExcept.ion,porque nulL na linha 8. Se a linha 10 fosse colocada entre as linha 7 e 8, entio F estaria correta, porque at6 que a ultima referncia seja anulada, nenhum dos objetos estari qualificado, e, depois de anulada a ultima referAncia, todos
tr& estario qualificados.
base
paftir
de
outra classe.
Desticorreta.Blocosinit
static
sloexecutadosnomomentoemqueaclasse6carregada,eosblocosinit
de instAncias rodam logo ap6s a chamada a super ( ) em um constmtor. Quando existem diversos blocos um mesmo tipo dentro de uma classe, eles rodam ordenadamente, de cimapara baixo.
ini t
de
A, B, C, E, F, G, H e I estio incorretas com base no exposto acima. Observagio: voc6 provavelmente nio ter6 nenhuma questao no exame real com tantas opg6es assim! (Objetivo 1.3)
,rffi
.:,.
:. :.
Operadores
ffi,'
':
.;
I
,'
individuol
i.i
l:ri
,"
':,,
outras. Neste capinrlo, voc6 aprender6 como fazer tudo isso emJava. Adicionalmente, voce aprender6 como fazer coisas mundo reil, mas que 6 quase certo de estafem no exame.
7.5 Escreuer aidigo que @lique czffetamente os operadores @rEiados, inc/uindo os de atibuigdo (linitadot a =, *=, -=), os operadoret )=, ==, !=), o operador insanceoJ a -, +, /, 0k, ++, - -), os operadores de comparagdo (initadw a 1, 1=, n, os operadores llgicos (linitados a &, l, !, &&, l) e o operador condicional (?) para produ{r un resuhado duelado. Esreuer cddigo que
i,
),
Os operadoresJava produzem novos valores apattt de um ou mais operandos (apenas par^ que fique rudo bem claro, os operandos silo itens i esquerda ou direita do operador). O resultado damuonadas operag6es 6 um valor booleano ou num6rico. E como voc6 j6szbe qweJaaa ndo d C**,ndo ftcar| suqpreso com o fato de seus operadores nio poderem ser sobrecarregados. No entanto, h6 alguns operadores que j6 v6m sobrecarregados:
r I
O operador * pode ser usado para adicionar um primitivo num6rico concatenagio se um dos operandos for uma String.
Os operadores
as suas
&, I e ^ podem todos eles ser usados de duas maneiras diferentes, apesar de que, nesta verslo do exame, funcionalidades pa:aopengdo com bits nio sio cobradas.
Fique alerta. A parte do exame referente aos operadores e atribuig5es normalmente 6 aquela em que os candidatos conseguem menos pontos. Al6m disso, operadotes e atribuig6es acabam entrando em muitas quest6es de outros t6picos... Seria uma pena voc6 conseguit destrinchar uma questio realmente complexa sobre threads, s6 para ertar a resposta por causa de uma instrugio de prd-incremento.
Operadores de Atribuigio
Abordamos
a
I I I
Ao
se atribuir um valor a um primitivo, o tamanho faz drfetenga. Certifique-se de saber quand ir6 ocorrer, quando a conversio explicita 6 necessiria, e quando poderao ocoffer cortes.
Lembre-se de que uma variivel de referdncia nio 6 um obf eto; 6 uma maneira de se chegar a um obieto (Sabemos que todos os leitotes que sZo programadores de C++ estao loucos para nos ouvir dizer "6 um ponteiro", mas nio iremos fazer isso).
Ao
se
atribuir um valor aumavai|vel de referncia,o tipo faz diferenga. Lembre-se das regras para supertipos, subtipos
e arTays.
Em seguida, abordaremos mais alguns detalhes sobre os operadores de atribuigio que caem no exame e, quando chegarmos no Capitulo 7, veremos como o operador "=" trabafhacom Strings (que s6o imut6veis).
e se
da
APL Muitos
tripicos da uersd.o
utqam mais no exanel Resumindo, o exame Jaua 5 difere do exame / .4 por e 1 .4 relacionados a lperadzres flram remouidos do exame, de modo qile neste
I I I I
Complementosbindrios
Assuntos referentes
i divisio porzero
d @enas qae e/es ndo caem
mab n0 exane,
e nosso objetiuo
JAVA
163
Y = Y - 6; x = x +2 * 5;
E agora com operadores compostos:
Y-=6; x+=2*5;
As duas ultimas atribuigSes d6o o mesmo resultado que as duas primeiras.
z).
x*=2+5;
fosse aualiada duta
forna:
x = (x * 2) + 5; // precedncia incorreta
uma ue<que a nuhiplicapdo tdn precednda sobre a adigdo. Pordrz, em ueTdisso, a exprer1o ti direita senQre
aualiada destafonna:
6 cokcada entrc paftnleses.
x = x * (2 + 5);
Operadores de comparagao
O exame aborda seis operadores de comparagio ((, <=, ), )=, == e l-) Os operadores de comparagio sempre resultam em um valor booleano (true ou f alse). Esse valor booleano 6 usado com mais freqri6ncia em testes if , como vemos a seguir:
al-go
\ )
mas o valor resultante tamb6m pode ser atribuido diretamente a um tipo
bool-eano primitivo:
class CompareTest { public static void main(String [] args) t booleanb=100>99; System.out.printl-n("The value of b is " + b) ;
]
Java tem quatro operadores de comparagio que podem ser usados para comparar qualquer combinagio de inteiros, nrimeros de ponto fluruante ou caracteres:
I > maior que I >= maior ou igual a I < menor que t <= menot ou igual a
Examinemos algumas comparag6es v6lidas:
class GuessAnimal { public static void main(String [] args) String animal = "unknown",. int weight = 7OO; char sex = 'm' ; doubl-e colorwavelength = 1.530;
if (weight >= 500) animal = "elephant"; if (colorWavelength > 1.627) animal = \'gray " + animal if (sex <= 'f ') animal- = "female " + anj.mal-; System.out.println("The animal is a " + animal);
,'
No c6.ligo anteriot, usalnos um operador de comparagio entre caracteres. Tamb6m 6 v6lido comparar um tipo primitivo de c ractere com qualquer nrimero (embora nio seia um estilo de programagio adequado). A execugio da classe anterior exibfu6
o seguinte:
The animal
is a gray elephant
Mencionamos que os caracteres podem ser usados com operadores de comparagio. Quando compara um caractere com outfo ou um caractete com um nrimerq a linguagemJava usa o valor Unicode do caractere como o valor num6rico e compara os nrimeros.
Operadores de
operadores sio
igualdade
J^v^tem tamb6m dois operadores de comparagio (chamados de "operadores de igualdade') que compa:-arndois itenr semelhantes e retofnam um valor booleano que representa o que 6 verdadeiro sobre os dois itens serem iguais. Esses
I == g"al (tamb6m conhecido como "igual a') I != difetente (tamb6m conhecido como "diferente de")
Cada compatagio pode envolver dois nfmeros (incluindo o tipo char), dois valores booleanos ou duas vad6veis de teferdncia de objeto. Voc nio pode comparar tipos incompativeis, no entanto. O que significaria perguntar se um tipo booleano igoal,aum tipo char? Ou se um objeto Button 6 igual String? (Exatamente, neo tem
I I I I
Nrimeros
Caractetes
class ComparePrimitives { public static void main(String, [] args) { System.out.println("character 'a' == 'a'? " + ('a' == 'a')); System.out.println("character'a' =='b'? " + ('a' =='b')); system.out.println("5 != 6? 't + (5 t= 6)) ; System. out.println ( "5. 0 == 5L? " + (5. 0 == 5L) ) ; System.out.println("true == false? " + (true == false) );
I
Esse progtama ptoduzir6. a saida abaixo:
character 'a' == 'a'? true character 'a' == 'b'? false 5 l= 6? true 5. 0 == 5IJ? Erue true == false? false
Como podemos ver, se um nrimero de ponto flutuante for comparado com um inteko e os valores forem os mesmos, o operador == tetotnard true como esperado.
JAVA
165
l]-.booleanb=false; L2. if (b = Lrue) i System.out.println("b is true"); l-3. i else { System.out.println(.,b is false,,) ; } Olhecuidadovmente! Voc6podtfcartentadoapensarqaeauidarcni'b ts faIse", matexamineote$ebooleanodatinha2.A aari,iuel booleanab ndo eshi sendo nmparada com lcr:ue, e$d sendo confgtrada com true, portanto, prinEJ.n nri execatado e obteremos 'b i s t rue ". O resultado de qaalquer expressdo de ahibuSdo i igaal ao aahr da uariiael apris a atribuQdo. Essa ub$ituigdo d0 inal = Pell nperador = = sdfxndona com uaridaeisbooLeanas, jd qile 0 terte if pode vrfeito apeltar em expresrdu booleanas.
Portanto, o aldigo abaixo ndo senl conpilada:
7.intx=1; 8.if(x=o)
Jd qw
i) (x = vr
(= =)
i um inteim (e ndo un booleano/, o resultado de A) ser,i 0 (o resuhado da aaibtig1o) Os inteimt ndo pod.em trvdos onde ttm aalor booleano i esperado, portanto, o aidigo da linba 8 ndofuncionanl a menlr qile sgja aherado de una ahibuigdo (=) para
rm tette
de tgualdade como uemot a segxir:
8. if (x == 0) i
Depois que esse c6digo for executado tanto avai|vela quanto b referenciario o mesmo obieto (um obietoJButton com o r6nrlo Exit). As vari6veis de refer6ncia podem ser testadas com o operador == para sabermos se estao referenciando um obieto em comum. kmbre-se de que o operadot == estar6 examinando os bits da vari6vel, portantq com relagio is vari6veis de referdncia, se os bits das duas variiveis forem id6nticos, elas estario referenciando o mesmo obieto. Examine o c6digo
abaixo:
import java. awt. Button; class CompareReference { *,,Lli^ ^r^el1,uurru euaurc void main(String IJ args) { Button a = new Button (.,Exit" ) ; Button b = new Button("Exit") ; Button c = a; System.out.println("Is reference a == b? " + (a == b)); System.out.println("Is reference a == c? " + (a == c));
I
s$digo cria trs vari6veis de referncia. As duas primeiras, a e b, sio objetosJButton diferentes, que por acaso tem o mesmo nome. A terceira r,zri6vel de referdncia, c, 6 inicializadapatarcferenciar o mesmo objeto que a esta referenciando. Quando esse prograrna for executado , a seida a seguir ser6 produzida:
Bt..
Is reference a == b? false Is reference a == c? true Ela nos mostra que a e c esteo referenciando a mesma inst6ncia
de um objeto ,JButton. O operador == nio testar6 se dois objetos sio "significativamente equivalentes", um conceito que veremos com muito mais detalhes no Capitulo 7, onde abordaremos o m6todo equals ( ) (nio confundfu colr:;, o operadorde igualdade que examinamos aqui).
class
EnumEqual
^-
// ; e Opc]-ona1 public static void main(StringtJ args) { Color c1 = Color.RED; Color c2 = Color.RED,' if (c1 == c2) { System.out.println("==") ; } if (c1.eguals (cz) ) { system.out.println("dot equals") r
[r-:E.rJ, F--
anrrm (-nl
}JLUE]
)i
O"Oj:"r
o quanto
) i
preparando voc
pa:ir-
dot equals
Operador de comparageo instanceof O operador instanceof 6 usado somente com vari6veis de referdncia
de objeto, e voc6 pode empregiJo para verificar se um objeto 6 de um tipo especifico. Por tipo, queremos dizer tipo de interface ou classe - em outras palavras, se o obfeto referenciado pela vari6vel i esquerda do operador passaria no teste E-MBMBRO do tipo de interface ou classe do lado direto do operador (o Capinrlo 2 abordou os relacionamentos E-MEMBRO com detalhes). O exemplo abaixo:
/ ,
|^ \E
edbeisto:sisaString
Mesmo se o objeto testado nio for realmente uma instanciagio do tipo de classe que estiver do lado direito do operador, instanceof ainda retornari verdadeiro se o obfeto puder ser atribuido a esse tipo.
O exemplo
a seguir demonstra o teste em um obf eto com o uso de dos seus subtipos, antes de se tentar urna conversio "redutora":
um
public static void m2 (A a){ if (a instanceof B) ( (B) a) . doBstuff ( ) ; / / convertendo uma refer6ncia / / em ttma refer6neia B
] t
]
O c6digo acima compila
e
'a' refers to a B
Emexemploscomoesse,ousodooperadorinstanceof
invdlida. Voc6 pode testar a referencia a um objeto confrontando-a com seu pr6pdo tipo de classe ou com qualquer uma de suas superclasses. Isso significa que quaQaerreferdncia a um obieto seriavahada como verdadeira se voc6 usar o operador instanceof junto ao tipo Obj ect, da seguinte forma,
protegeoprograrnacontraatenativadetentarumaconversio
JAVA
167
b is definitely an Object
oBSERVA9oSS pARA O EXAME
Pron'm perguntas eom instanceof que testem
indiretamente.
um objeto
a instincia de
lma
Una implenentagdo indinta ocore quando ma institcia ndo ofaq- por exenplo,
una intetface,
for implenentada
,^
i pnlpio
classe
da
(igfieando
que
pasuni
no te$e
lnsEanceof)
se algama de suas
aI se,
nu11
6a
class InstanceTest { public static void main(String [1 args) String a = null; boolean b = nul1 instanceof String; boolean c = a instanceof String; System.out.println(b + " " + c) ;
)
se
f al- se
Nio
Erro de Compilagio de instanceof 6 possivel usar o operador instanceof para testar em duas hierarquias class cat { } class Dog { public static void main(String tl args) Dogd=newDogO; System.out.println (d inst.anceof Cat) ;
) )
A compilagio fdha
d iamais poder6
se
referir a um
Cat,
ou a um subtipo de
Cat.
aralr
qae
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
instanceof
}
presumindo-se o seguinte:
interface face { } class Bar implements Face{ class Foo extends Bar { }
instanceof
Resultado
null
instincia de Foo instincia de Bar instincia de Bar Foo[ ] Foo[ ] Foo[1]
false
Foo
Foo, Bar, Face
false false
Object
Operadores aritm6ticos
Temos certeza de que vocd est6 familiaizado com os operadores aritrn6ticos b6sicos.
I I I I
+ adiglo
x /
subtragio
multiplicagio
divisio
11
Um operador com o qual vocd pode n6o estar familiaizado 6 o operador de rcstooh. O operador de resto divide o operando esquerdo pelo direito com o resultado sendo o resto, como o c6digo abaixo demonsffa:
class MathTest { public static void main (string il args) { int x = 15; intY=x*4; Swstem.ouf nrint-ln/"fhe rcsuft of L5 ? 4 is the remainder of L5 divided by 4. The remainder is " + y) ;
1
JAVA
169
A execugSo
da classe MathTest
exibiri
linha a seguir:
3
(I-embre-se: As express6es sio avaliadas da esquerda p an dlteita,por padrio. Voc6 pode modificar essa seqriencia, ou pmceddncia, adicionando parenteses. Lembre-se tamb6m de^que os opetadores *, / e %o tdm maior precedncia do que os operadores * e -.)
tornari interessante quando voc6 combinar nirmeros com obietos String. Vedfique o c6digo
seguit:
String a = "String";
inll.r ?.
somar as vari6veis int de b + c? Ou ftatara 3 e 7 como caracteres e os concatenard individualmente? O resultado ser6 Stringl O ou St.ring3 7? Certo, voc teve tempo suficiente para pensar sobre isso. Os valores int foram simplesmente tratados como caracteres e acrescentados i direita da string. Portanto, o resultado 6:
i-nt c = 7,' System. out.println (a + b + c) O operador * atuafi, como um sinal de adigZo quando
,.
String3
De forma que poderiamos ler o c6digo anterior assrm: "Comega com a String a, "String", e adiciona o caractere 3 (o valor de b) aela,pataproduzir uma nova string, "String3",adicionando,ent6o,ocaractereT (ovalordec)aoresultadoparaproduziroutastri.ng,"string3?",e exibi-la em seguida".
No entanto,
se
int,
System.out.println(a + (b + c) );
obter6:
String1O
O uso de parenteses fat6 com que @ + c) seja tratado primeiro, portanto, o operador 'l fancionat6 como o operador de adigio, dado que os dois operandos sio valores int. O ponto chave aqui 6 que, dentro dos pardnteses, o operando da esquerda nio 6 uma String. Se fosse, o operador I execttaiaaconcatenag6o de Strings. O c6digo anterior pode ser lido da seguinte forma: "Soma os valores de
b +
c, em seguida, converte
a soma em
uma
string
vai|vela".
A regra
a
string
da
lembrar
6:
String,
o operador
atuari
SLrings,
Se ot dois @erandot
Em algumas situag6es voc6 poderi ter problemas para descobrir se, digamos, o operador da esquerda 6 ou nio uma String. No exame, nio espere que isso seja 6bvio. (I.{a verdade, i6 que mencionamos nisso, nunca espere que seja 6bvio).
Examine o c6digo a seguir:
System.out.println (x.foo O + 7) ;
Voc6nioter6meiosdesabercomoooperador*
Se
seri concatenado a string retornada. Mas se f oo ( operador* serdusadoparasomaro algarismo 7 comovalorretornadopor foo ( ). retornar uma
est6sendousadoat6quedescubraoqueom6todo
SLring, entio,T
Finalmente, voc ptecisa sabet que 6 v6lido mistutar o operador aditivo composto
= \\A23"i
L234567
I Z0 Copitulo 4: Operodores
oBSERVAQoTSpeneTXAME
Se aocd ndo compreendtr eomo a couatenaj1o de Stringsfunciona, principalmente dentm de ma instrufio de saida, podeni realmente ser mal sucedido tt7 examq mesmo y soaber o retto da reposta i pergunta! Ji que tantas petglntat indagam, "pual rcni o resultado?", uoc| ptvcisa mas tambdm c0m0 esse resultado rcni. exibido. Mesmo bauendo pelo menot taber tdo s6 qual a saida do ctidigo que eftiuer
rcndo
neia
peryuntas que nriarAo diretamente seu conhecimento em strings, a eoncatenagdo de ftrings @ancenl em outras petguntas cada objetiuo. Faga um teste! Por exenpk, uoc6 pode aer uma linha como
di{a
d.e
de
int b = 2;
System.out.print.ln(*\r + b + 3);
qae
exibiri
z5
para
System.out.println(b + 3) ;
entdo, o resultado serti 5.
Acr6scimo e decr6scimo
A linguagemJava possui dois operadores que aumentario ou diminuirio uma vari6vel em exatamente uma unidade. Esses operadores sAo compostos por dois sinais de adi96o (++) ou dois sinais de subtraglo ( -):
1. class MathTest i static int PIaYers = 0; 2. public static void main (String [] args) { 3. System.out.println("players online: " + players++); 4. System.out.println("The value of players is " + players); 5. System.out.println("The value of players is now " + ++players); 6. 7. ) 8. ) Observe que na quarta linha do progtam ,o operador de incremento esta depois d^v^i6vel players. Isso significa que estamos usando o operador p6s-fixado, o que far6 com que a variivel players seia aumentada em umavnidade, mat
sonente dEois que
nu aabrfor uvdo na expresdo. Quando executarmos esse Programa, ele exibir6 o seguinte:
?java MathTest
Espere por perguntas que combinem os operadores de incremento e diminuigio com outros operadores, como no exemplo abaixo:
irlLx=2; int Y = 3t if ((Y -= x++) | (x < ++Y) ) { System.out.println(<x = < + x + < y = < + y);
)
JAVA
17]
Oc6digoanteriorexibirix = 3
y =4
Voc6 pode ler o c6digo assim: "Se 3 for'rgoaIa2 OU menor do que 4..."
Aprimeiraexpresslocompar^x ey,eoresultado6false,potqueoacr6scimodex n6ooconer6antesqueotestedo operador == seia executado. A seguir, aumentamos x e agora ele .igad,a 3. Depois verificamos se x 6 menor do que y, msailmentamlroualordey antesdecompari-locomxlPortanto,osegundotestel6gico6(3<4).Oresultado6t,rue,de
modo que a instrugZo de saida ser6 executada.
aheradas, os operadoret de inmmento e dininuQdo ndo poderdo ser asados com eks compilador. O aidigo a nguir ndo nni co@ilada,
i na I
wvltari
em am
ero do
qautdo uhi testando o seu conhecimento sobre um conplexo operador aitmitico, quando, na aerdade, estd testando
inal.
Operador condicional
Ooperadorcondicional
6umoperadortemirio(temtrsoperandos)usadoparaavaliarexpress6esbooleanas
semelhante iinstrugio if, exceto por,emvezde executar um bloco de c6digo se o resultado do teste for true, atdbuir um valor i vari6vel. Em outras palavras, o objetivo do operador condicional 6 decidir qual dos dois valores atribuir a uma variivel. Ele 6 constnrfdo com os simbolos ? (ponto de interrogagio) e : (dois pontos). Os pardnteses sio opcionais. Sua estrutura 6 a seguinte:
demodo
x = (expressdo
booleana)
valor
atribuir
se
true:
valor
atribuir
se
f al se
class Salary i public static void main(String IJ args) { i-nt numOf Pets = 3; String status = (numOfPets<4)?,,Pet limit not exceeded,,:,,too System.out.println(.'This pet status is '. + status)
,.
many
pets,,;
Voc6 poderia
l.r
"Configura numOf Pets igual a 3. A seguir, atdbui uma String avati|vel starus. Se numOf 4, atibur6"Pet limit not exceeded"; do contr4rio, atibwrd"too many pets".
Pets
O operador condicional comega com uma operagdo booleana, seguida de dois valores possiveis paraavai|veld,esquerda do opetador (=). O primeito valot (que fica i esquetda dos dois pontos) set6 atribuido se o teste condicional @ooleano) tiver um resultado true e o segundo valor seri atribuido se o resultado do teste for f al-so. Voc6 tamb6m pode aninhar operadotes condicionais em uma insrugio:
class AssignmentOps { public static void main(String [] args) { int sizeOfYard = 10; int numofPetss = 3; String status = (numOfPets<4) ?,,Pet count OK,, : (sizeOfYard > 8)? ,,pet limit on the edqe,,
:
"too
many pets",.
Nio
espere muitas perguntas que usem operadores condicionais, mas lembre-se de que, is vezes, os operadores condicionais sio confundidos com as instrugSes assertivas, portanto, certifique-se de poder diferenci6los. O Capinrlo 5 abordari as assertivas com detalhes.
Operadores L6gicos
Os objetivos para o exame especificam seis operadores "l6grcos" (&, | , ^, !, && e | | ). Alguns documentos oficiais da Sun usam outra terminologia para esses operadores, mas,parz.os nossos prop6sitos, os "operadores l6gicos" sio os seis listados acima e nos objetivos para o exame.
015
""
1 6
isto:
.*"-.i
deles? Se cair nas suas mios um livro antigo de preparagio para o exame, ou se encontrar alguns simulados que ainda nio foram devidam ente atualizados, voc poder6 se deparar com quest6es envolvendo operag5es bitwise. A nio ser que se sinta tio culpado a ponto de achar que merece esse tipo de punig6o, pode ignorar esse tipo de questeo simulada.
r && Edeabreviagio I | | OU de abreviagio Eles sio usados p^t iunt?Lrpequenas express6es boOleanaS a fim de formar express6es bool-eanaS maiotes' Os operadores && e | | ava1am somente valores booleanos. Para uma expressio E (&&) ser verdadeira, ambos os operandos ptecisam ser true - pot exemplo, if ((2 < 3) && (3 < 4)) { } A expressio anterior s6 6 true, porque tanto o operando um (2 < 3) quanto o operando dois (3 < 4) slo true.
O recurso de abreviagdo do operador && consiste no fato de ele ndo perder sea tempo em aua/iapder inilteis. O operador de abrcviagdo && avalar|o lado esquerdo da operagio primeiro (operando um) e se esse operando tiver um resultado f a}se, ele nio examinar6 o iado direito da equagio (operando dois), ]6 que o operador saber6 que a expressio completa neo ser6 u! uc.
uI4>D lUYrUAf I
public static void main(String boolean b = true && fal-se,' s\/qram nrrt-.println("bool-ean l
)
[] args)
b = " + b)
JAVA
I73
boolean b = false
O operador | | 6 semelhante ao operador &&, exceto p or ele avaliar como t rue se qualquer tm dot operadoret for t rue. Se o primeiro operando de uma operagio OU for true, o resultado tamb6m ser6, portanto, o operador de abreviagio | | nio perder6 tempo examinando o lado direito da equaglo. No entanto, se o primeiro operando for f alse, o operador tera que avaliar o segundo operando para saber se o resultado da operagio OU ser6 L rue ou f a l- s e. Pteste bastante atengao no exemplo a seguit; voc6 veri algumas pefguntas como esta no exame:
1. class TestOR { public static void main (String [] args) 2. 3. if ((isrrsmall(3)) ll (isrrsmall(7))) { 4. System.out.println("Rqsu1t is true");
J
6. 7. 8.
e.
10.
l-1. public static boolean isltSmall(int L2. if (i < s) t 13 . System. out .println ("i < 5" ) ]-4. return true; r_5. J erse t l-6. System.out.printLn("i >= 5"); L7. return false; 18. )
,.
i)
t-e.
20.
)
? java
1<5
TestOR
( ) foi executado:
1. 2 3. 4. 5. 6.
linha 3, o pdmeiro operando da expressio | | (em ouuas palavras, o lado esquerdo da operagio
O m6todo
isltsmallisItSmall
(3
foichamado, exibiu
"i <
5" eretornou
uerdadeiro.
"i >=
5", que teria sido exibida caso o segundo operando fosse avaliado
|.
(chamando
(7 ) ).
Om6todo
true, se o segundo operando for avaliado como true. 7. O mdtodo isItSmall (9 ) 6 chamado e exibe "i >= 5". 8. Om6todoisItSmall (9) retornafalse,portanto,aexpressiodalinha66false eahnirraT nuncaser6
operando; ainda h6 uma chance da expressio ser
executada.
&&e
ll
sdfuncionamcomoperandosbooleanos.
Oexamepodetentarengand-lo,usandointeiroscrtltesseroperadoret;
if (s && 6) t
onde parece
Tresmo
seni compilado.
fio
sdo de abreiagdo.
I I
&Endo-abreviado
I OU nio-abteviado
Esses operadores s6o usados em expressdes l6gicas, assim como os operadores && e | ; por6m, j6 que ndo sdo os operadores de abreviagio, aualiardo os dois ladw da exprusdo, semprclBles serio ineficientes. Por exemplo, mesmo se o primeiro operando (ado esquerdo) de uma expressio & for f al se, o segundo tamb6m seri avahado - ainda que agora tenha n tonado impossiuel o resultado serErue/E o operador I ser6 ineficiente na mesma medida; se o primeiro operando for ele a;nda dati prosseguimento e avahatS" o segundo operando, mumo quando souber q*e a expressdo seri Erue.
true,
No exame, voc veri muitas perguntas usando tanto operadores l6gicos de abrciagdo quanto os que nio usam a abreviag6o. Voc ter6 que saber exatamente quais opetandos sefao avaliados e quais ndo serlo, jique o resultado variar|se o segundo opetando da expressio for ou n6o avaliado:
OperadoresL6gicos
^ e!
produz asuda;
como
xor false
al se
porque TANTO o primeiro operando (2 < 3) quanto o segundo (4 > 3) avdtam
crue. booleano:
}
if ( l (? == 5) ) { Sysfem.out.println("not equal") ;
not egual
Eis um ouuo exemplo usando
pode ser lido como "se nio for verdade que 7 == 5", e a instrugio produz esta saida:
booleanos:
boolean boolean
t = true; f = false;
! true false
No exemplo anterior, repare que o teste & teve sucesso (exibindo modificou, de modo que ela exibiu f alse.
true),
booleana f
n6o se
Se
voc6 estudou este capinrlo atentamente, deve tet obtido uma compreensio s6lida sobre os operadoresJava, e dever6 saber o que significa igualdade, quando seu conhecimento sobre o operador == for avaliado. Recapitr:lemos os Pontos
I75
Os operadores l6gicos (&& e I l) s6 podem ser usados para avaliar duas express6es booleanas. A difetenga entre && e & 6 que o operador && n6o se preocupari em testar o operando direito, caso o esquerdo for avaliado como f aI se, pois o resultado da expressio && nunca pode ser true. A diferenga entre | | e | 6 que o operador | | n6o testar6 o operando nesse momento. direito se o esquerdo for avaliado como true, porque o resultado i|setkrcconhecido como
true
O operador -- pode ser usado p^r comp^rar valores de tipos primitivos, mas tamb6m pode ser empregado para determinar se duas variiveis de refer6ncia referenciam o mesmo objeto.
Ooperadorinstanceof
teste
Ooperador* 6sobrecarregadopanteahzartatefasdeconcatenaglodeStrings,epodeconcatenartamb6mStrings
com tipos primitivos, mas curdado
essa
O operador condicional (tamb6m conhecido como "operador temirio') tem uma sintaxe incomum, com tres operandos
assert complexa.
e
Os operadores s - - sereo usados em todo o exarne, 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 de objetos e tipos primitivos, e assim por diante.
,/
Exercfcios r6pidos
Aqui estlo alguns pontos-chave de cada segio deste capitulo.
E
El
booleano (t.rue
ou f
alse).
fl
E Quatro tipos de itens podem ser testados: nirmeros, caracteres, booleanos, vari6veis de referdncia. E Hi dois operadores de igualdade: == s l=. Q Ao comparar vai|veis de referncia, == retotna true somente se ambas as referncias apontatemparao
objeto.
mesmo
Operador instanceof (Objetivo 7.6) E instanceof s6 6 usado com variiveis de refer6ncia e verifica se o obieto 6 de um tipo especifico. EI O operador instanceof s6 pode ser usado par^testr objetos (ou valores nuI1) confrontando-os
classe que esteiam na mesma hieratquia da classe.
instanceof
.
se
E
El
O operadot de testo
(o/o)
As express6es sio avaliadas da esquerda p ata a dtreita,a n6o ser que voc adicione par6nteses, ou que alguns operadores na expressio tenham maior preceddncia do que outros. Os operadores *,
f,l
e %o
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.
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.
booleana
ser
true
ou f
alse.
rue
Operadores l6gicos (Objetivo7.6) E O exame aborda seis operadores l6gicos: &, l, ^, !, && e | | D Os operadores l6gicos trabalham com duas expressSes (exceto ! ) que devem resultar em valores booleanos. fl Os operadores && e & retornario Erue somente se os dois operandos forem uerdadeiros. E Os operadores | | e I retornario true se um ou os dois operandos forem uerdadeims. Q Os operadores && e | | sio conhecidos como operadores de abreviagio. D O operador && ndo avahard o operando direito se o esquerdo for f a 1 se. E O operador | | ndo avahat6ooperando direito se o esquerdo for true. fl Os operadores & e I sempre avallamos dois operandos. Q O operador ^ (chamado de "XOR l6gico') retorna t rue se exatamente um operando for verdadeiro. E O operador I (chamado de operador de "inversio'), retorna o valor contr6rio do operando booleano que o precede.
.
Teste individual
l. Dado:
class uexy
-,,L1 I ^ ^!-+i
{
^ -
"roi-d main
(Srring [] args)
Integer i = 42; String s = (i<40) ?"1ife": (i>50) ?"universe" t"everything"; System. out.prinLln (s) ;
i
)
Qual 6 o resultado?
A. null B. life
C. universe
2. Dado:
JAVA
5 I77
4. 5.
o. l
Boolean b;
7.
A.
Qual opgio, inserida indepentemente na linha 5, ir6 compilar? (I\zlarque todas as corretas)
b = (Number instanceof s) ; B. b = (s instanceof Short); C. b = s. instanceof (Short) ; D. b = (s instanceof Number); E. b = s. instanceof (Object) ; E b = (s instanceof String);
3. Dado: 1. cl-ass Comp2 i
2. 3. 4. s. 6. 7. 8.
ol
public st.atic void main(Stringtl args) t fl-oat f1 = 2.3f ; floar n il f2 = {{.42.0f1 , {t.tt, 2.3tll , {2.6f., 2.tf}} float tl t: = {z.tt} ; Long x = 42Li // insira o c6digo aqui System.out.println("true");
)
10. i
E os cinco seguintes fragmentos de c6digo:
O que
verdadeiro?
,{.
true. C. Dois deles compilario, dois serio true. D. Trs deles compilardo, apenas um ser6 true. E. Tt6s deles compilario, exatamente dois serio true. F. Trs deles compilareo, exatamente tres sereo true.
B. Dois deles compilario, 4. Dado: crass lorK
public static void main(stringlJ args) t if(args.length == 1 I args[1J.equals("test")) t System. out.println ( "test case" ) ; ) else { System.out.pri-ntln("production " + args [0J ) ;
)
) )
AC.
test
case
B. production
D. Acompilaglofalha.
5. Dado:
class Foozit { public static void main(String[] args) fnt.eger x = 0; Integer y = 0; for(Short z = 0; z < 5i z++) if( (++x > 2) I | (++y > 2) )
x++
r.
System.out.println(x + s \ + y) ;
) )
Qual 6 o resultado?
A-51 8,5 2
c.s3
D.81 882 883 G.102 rL10 3
6. Dado:
class Titanic { public static void main(StringlJ args) { Boolean b1 = true; boolean b2 = false; boolean b3 = true; if ((br- & b2) | (bz e b3) & b3) System. out .print (..alpha ., ) if ((b1 = false) | (b1 & b3) (b1 | b2)) System.out.print ("beta *) ;
,-
) )
Qual 6 o resultado?
,{.. bet,a
JAVA
5 I79
D. Acompilagdofalha.
E E
saida.
7. Dado:
class Feline { public static void main(StringlJ args) { Long x = 42L; Long Y = 44Li System.out.prlnt(\\ \\ + 7 + 2 +.. ..),' System.out.print(fooO + x + 5 + ,' .,); System.out.println(x + y + fooO);
]
Qual 6 o resultado?
A" 9 foo47 86foo 8.9 foo47 4244foo C. 9 foo425 86foo D.9 foo425 4244foo E 72 foo47 86foo n 72 foo47 4244foo G. 72 foo425 86foo I+ 72 foo425 4244foo
I.
Acompilagdofalha.
8. Coloque os fragmentos no c6digo para produzar a saida 33. Obseryagio: voc6 deve usar cada fragmento exatamente uma vez. class Incr i
System.
out.println (x) ;
FRAGMENTOS:
Y
v x
x
*= *=
I80
Copitulo 4: Operodores
9. Dado:
1. class Maybe { 2. public static void main(Stringtl args) { boolean b1 = t.rue; 3. 4. boolean b2 = false; system.out.print(!fatse ^ fatse) ; 5. system.out.print(* $ + (!b1 & 1bz = true))); 6. 7. system.out.println(' " + (b2 ^ b1)) ; 8. )
q]
'.
O que
6
verdadeiro?
,d
true. B. A linha 5 produz false. C. A linha 6 produz true. D. A linha 6 produz false. E A linha 7 ptodtz true.
A linha 5 produz
E AlinhaTproduzfalse.
10. Dado:
class Sixties { pubtic static void main(StringtJ args) int x = 5; int y = 7; System.out.print(( (y * 2) Z x)) ; System.out.print(" " + (y ? x) ); i
)
Qual 6 o resultado?
H.
Respostas
1.
D
est6 correta. Este 6 um ternirio aninhado dentro de um ternario com um pouco de unboxing funto. Ambas as express5es tern6rias slo falsas.
A5
B, C, E
e
F estio incortetas com base no exposto acima. (Objetivo 7.6) juntos. incorreta. F estl errada
2.
B A
estd incorreta porque os operandos est6o invertidos. C e E usam sintaxe instanceof porque Short nio est6 na mesma 6rvore de heranga que String. (Obietivo 7.6)
3.
true.
JAVA
5 I8I
4 4.
B' C, E e F estio incorretas. F1 esti incorreta porque nio 6 possivel comparar um tipo primitivo com um anay.F4
(Obietivo 7.6)
a abteiragdo ( | | ) neo ter sido usada, ambos os operandos sio avaliados. Uma vez que {e args[1] esta^l6mdoslimitesdoanayargs,6,langadaumaArraylndexQutOfBoundsExr':ention
B, C
7.6)
se
5.
vezes em que o teste i f 6 execuadq tanto x como y sio incementadas uma vez (s6 alcangax++ natercekaitetagno).Apartirdatercaraiteragdodoloop,y nuncamais6usadqporcausadooperadorde
4 6.
B, C, D, F, G
E est6 cotteta. No segrrndo teste i f , a expressio mais i esquerda 6 uma aribuigio, e nio uma comparagio. Depois que b1 foi definido como f al-se. os demais testes sdo todos f al-se.
B, C, D
7.
G est6 correta. A concatenagio roda da esqu erdz pata z dtreita e, se algum dos operandos for uma S t r i ng, os opetandos s6o concatenados. Se ambos forem nrimeros, eles sdo adicionados um ao outro. O unboxing funciona em coni unto com a concatenagdo.
A
8.
class Incr
--,,h1 l^ ^r-rl^
x*=x;
rr
*-
r, - rr.
Y*=Yi x_=y;
System. out
.
println (x)
,'
Sim, sabemos que isso 6 complicadq mas voc poder6 encontrar algo parecido no exame real. (Obietivo 7.6)
9. ADeFestiocorretas.O^(xor) tetorn true seexatamenteumoperandofortrue.O !inverteovalor booleano do operando. Na linha 6,b2 = true 6 uma atribuigio, e nio uma comparagdo, e n6o 6 avaliada
& nlo serve
B, C
e
d
potque
10. F est6 correta. O opendoroh (resto, tamb6m conhecido como m6dulo) retorna o resto de uma operagio de divis6o.
B, C, D, E, G
estAo
Controle de fluxo,
excesoes e assertivas
individuol
.|84
imaginartentando escreverum c6digo com umalinguagem que.n|g fornepauma maneira de executar insru96es clondicionimente? O controle de fluxo 6 uira parte chave de quase ioda linguagem de programaXg qil , e alava oferecl virias maneiras de execut4-lo. Algumas, como asinstrug6es i f i loops f or, iio comuns i maioria das linguagens. Mas aJava tamb6m introduz algon, ,e.rriror de controle de fluxo que voc6 pode nlo ter usado antes - exceg6es e assenivas'
se
As instrug6es
ma.reira
e swi tch sio tipos de controles condicionais/de decisio.que permitirio aseu pro gramaagt de em uma "bifurcaglo do caminho", dependendo do resultado de um teste l6gico. A linguagemJava fornece tr|s estruturas de loop difeientes - f or, whi Ie e do - portanto, voc6 poderi executar o mesmo c6digo -As exceg6es the proporcionario,uma maneira simples e repetidamente ar6 que o res"hrao ae Agu-a condigio seja true. limpa de organizarts c6digos e de lidar com ot proble*as que poss-am surgir no tempo de execugio. Para concluir, o *"i*ir*o"d" asserrivas, aJicionado a linguagem na versXo 1 .4, lhe fornecer6 um meio de executar verificag6es de depura$o -o em condig6es que vod queira expor durante desenvolvimento, quando nio quiser ou precisar gerar a sobrecarga no temPo
iif..enre
de execugXo associada
i manipulagio
de exceg6es.
essas ferramentas, vocA poder6 desenvolver um programa robuso, capaz de manipular qualquer.situaglo l6gica com sofisticaglo. Espere virias pergunras no exame que incluam o controle de fltrxo como pane de seu c6digo' at6 mesmo aquelas que nio estiverem avaliando especificamente seu conhecimento sobre esse asstrnto.
Com
Obietivo poro o certificoc6o Escrevendo o c6digo usando instrus6es if e switch (Objetivo 2. I do exame)
2./
Escreuer cfidigo qae inplenente ama instrugdo
para
essas in.rtrapda.
As instrug6es i f e swi tch geralmente sio conhecida s como inshwpdes d.e decisd.o. Quando voc6 usar instrug6es de decisio em seu programa, estar6 solicitando a ele que avalie uma expresslo especifica a fim de determinar que curso de a$o tomar. Examinaremos primeiro a instrugio i f .
Ramificagio if-else
O formato bisico
de
uma instrugio
if
6o
seguinte:
ou f alse. Normalmente voc6 testari es deaeter corrro resultado um valor booleano algo para sabe r se 6, uerdadeiro e, em seguida, executar6 um bloco de c6digo (uma ou mais instrug6es) se o resultado for mesmo uerdadeim e (opcionalmente) outro bloco de c6digo se nio o for. O c6digo a seguir demonstra uma instrugio i
true
vAlida:
if (x>3)
System.out.println("x is greater than 3"); ) else { System.out.println("x is not gfreater than 3");
]
O bloco e1 se
6
if (x>3)
]
z La.
if (x > 3l / /
JAVA
I85
Y=2i z += 8; a-y+x,.
A Sun considera como boa pr6tica colocar blocos dentro
"Se
de chaves, mesmo que s6 haia uma instrugio no bloco. Seja cuidadoso com c6digos como esse, porque voc6 pode pensar que ele deve sei lido assim:
xfor
!8
comJlx".
Contudo, as duas riltimas linhas serio executadas de qualquer forma! Elas nio {azempane acharia ainda mais confirso se estivesse recuado como vemos abaixo:
dofltxo condicional.
VocA o
();
dontBuyProduct ( ) ;
J
Issonostrazaooutroconstrutorif-else,oif,e1se if,else.Oc6digoanteriorpoderia(edeveria)serreescrito
como:
) else
]
{
();
dontBuyProduct
se
de
el s e i f :
I r I
if.
if
paraumdadoif,eelesdevemvirantesdoelse (opcional).
else i f ou else
ser6 testado.
O segqnte glemplo mostra um c6digo horrivelmente formatado para o mundo real. Como vocA provavelmente j6 adivinhou,_6bastante prov6vel que encontre ese tipo de formatagio no exame. De qualque r f.orma,o codigo dernonstra o
uso de
mriltiplos
lse i f
int x = 1; if(x==3){} el-se if (x < 4) {System.out.println("<4"); else if (x < 2) {System.out.println("<2"); else { System.out.println("e1se") ; }
} }
exceE6es e qssertivos
(R.epareque,mesmoqueosegundoelse
exemplo:
sejaverdadeiro,aexecugionuncachegaaele.)
Emalgunscasos,voc6podeterdificuldadesemdescobrircomqualif
oseuefse deveserpareado,comoneste
if if
/
(exam.doneO
/ A qoa\ if isto
pertence?
;
Intencionalmente neo usamos o recuo nesse trecho de c6digo, portanto, ele nXo fornece pistas sobre a que instrugio i f a cliusula else perrence. VocA conseguiu descobrir? As normas da linguagemJava determinam que uma cl6usula else pertencerl ) initrugXo i f mais pr6ima a qual ela possivelmente pertenga (em outras palavras, i instrugio i f anterior mais pr6xima que nio tenha uma cl6usula Llse). No caso do eximplo anterior, a cl6usula else pertencei segudn instruglo i f da listagem. Com o recuo apropriado, a instrugio teria e$e formato:
if lavam Aana/\\
if (exam.getscoreO < 0.61) System. out.println ( "Try again. // A gual if isto pertence?
el-se System.
");
");
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
apropriadamente recuados. Alguns candidatos tm at6 uma frase de efeito para a maneira como apresentadas: tudo que puder ser feito de maneira mais confusa, assim seri.
Esteja preparado para perguntas que al6m de
perguntas sio
nio recuarem os c6digos apropriadamente, o fario intencionalmente de maneira confusa: preste bastante atengio em distragSes como a do exemplo a seguir:
if
(exam.done O
");
Hmmmmm.'.
onde?
E claro que o c6digo anterior 6 exatamente o mesmo dos dois rlltimos exemplos, exceto pelo seu formato.
Express6es v6lidas para instrug6es if As instrug6es i f s6 podem avaliar valores booleanos. Qualquer expressio que tenha como resultado um valor booleano seriadequada,masalgumasdelaspodemsercomplexas.SuponhamosquedoStuff ( )retornetrue,
&& (y <
nrinf
2)) | aostuttt)) i
lnl"rrrra/1.
JAVA5 187
)
queodbiri
anterior assim: "Se tanto (x > 3) quanto (y < 2) forem t rr-re ou se o resultado de dostuf f ( ) true, entio 'true" seri exibido. Portanto, basicamente, se apenas d.oStuf ( ) for true, ainda obteremos true. !or6ln,sedoStuff ( ) forfalso,(x>3)e(y<2)terloquesertrue paraquetruesejaexibido".Oc6digoanterior ficariundamais complexo se voc6 nio inserir um conjunto de par6ntese, .orrro lr.rrro, "t"i*o, int y = 5' int x = 2; if ((x > 3) && (y . 2) I aostutro ) { System. out.println ( "true,, ) ;
VocO pode ler o c6digo
tor
]
Agora ele exibir6... Nada! Porque o c6digo anterior (com um conjunto de par6nteses a menos) far6 a avaliagio como se estivesse dizendo, "Se (x > 3) for true, e (y < 2) ou o resultado de oostuf f ( ) tamb6m o for, true ser6 exibido. Portanto, se (x > 3) nlo for true, nio haveri por que verificar o resto da expressio". Por causa do operador && de abreviagio, a expressio ser6 avaliada como se houvesse parnreses enfeixando ( lv.z I dostuf f ( )). Em outras palavras, 6 avaliada como uma rinica expressio antes do Er& e como uma 6nica expressio depois do Ec&.
Lembre-se de que o rinico argumento v6lido para um teste
false,e1==
int'i
if
um valor
nl-
if if if if if if
/ // // // // //
/
inv6lido
inv5aido
inv6lido
inv6Tido
v6lido
v6Lido
oBSERVAQ6ESpeneOE)(AME
Um ero clmtlm qtle os programadoru cometea teshl-la. Cuidado com aldigot como o seguinte:
(e que pode ser
dficil
de
1., pae
o aidigo
rcni nnpikdo
e executado adeqaadamente,
if
f also.
(em
2, pue o aidigo ndo senl nmpilado porque uoci est,l asando uma atibuigdo (: ), t, ueTde um teste de igualdade (: : ). 3. pae o aldigo senl conpilado e executado adzquadamente, e o teste if seni bem sandidn porque boo foi confgurado com Lrue
ueTde estar sendo aualiado se d uerdadeiro) n0 argunentl da insrap1o Bem, a oppdo 3 estti correta.
if!
E inilrtl, mas rctr?ta. Dado que o resultado de qualquer atibaQdo i igual ao ualor da aai,iuel incluido @rir essa atibuigdo, a expressdo (boo = Lr:ue) turA como resaltado Erue. Portantz, 0 teste iffoi ben ncedido. Mas a ilnica uariduel que pode ser atribaida (en ueqde aaaliada com relagdo a algo) d um ualorbooleano; todas as outrar atibuipdes resultardo erzt algum ualor ndo
booleano de modo qae ndo serdo udlidas, rcmo nas linhas a seguir:
intaxe
uocd
precisa ter um conhecimento srilido tanto sobre os operadoret ldgicos qaanto sobre a
e remdntica do teste
if
Instrug6es svvitch
lJma maneira de simular o uso de virias instrug6es
if
if
if 6 com a instrugXo switch. Observe o c6digo do bloco aninhados, mesmo com apenas alguns niveis:
else-
1" ) ;
el-se
)
tch:
System.
out.println
"x is equal to
1,"
\;
break; case 2:
System. out
.
2" ) ;
break; case 3:
Q\rc|- 6m vuu rJ p uelr r nrrF y! fIIurrr . nrinr'ln / \
break;
default:
System.
)
out.println
ObservagXo: arazXo pelaqual essa instrugio switch emula os i f s aninhados listados anteriormente 6 devido )s instrug6es break que foram colocadas dentro do switch. Em geral, as instrug6es break sio opcionais e, como veremos daqui a algumas piginas, a inclusio ou excluslo delas causa grandes mudangas na forma como a instrugio swi tch seri
er<ecutada
instrugio
switch
{
switch (express6o)
case constantel: bloco de c6digo case constante2: bloco de c6digo default: bloco de c6diqo
i
A expressio
que, se voce de
byte, short,
ou, a panir do Java 5, um enum. Isso significa puderem ser promovidos automaticamente (em serio aceitos. VocA nio conseguiri compilar se usar algum tipo
int
O rinico argumento que uma instrugXo case poder6 avaliar seri aquele que apresentar o mesmo tipo que a instruSo
JAVA
I89
swi pode u.ar, com uma restrigio adicional - e re/euante: o argumento de case tem que wr uma constante tlc tenpo de conpikgdo! Ele precisa ser resolvido no tempo de compilagio, portanto, isso quEr dizer q,r. vo.6 ipode usar uma variivi f constante com um valor literal. Nio 6 o suficiente ser f ina1, ela deve ser uma constante no tempo de compila$o. Por
tch
inai
e><emplo:
f i-a] ihf . 1.
umiipo
int.
out.println
"length is
two" ) ;
break; case 3:
Syst.em.
out.println
"length is three"
break;
match" ) ;
do que um tipo
Oura regra que voc6 poderia nio esperar envolve a pergunta: "O que aconteceria se uma variivel menor int fosseusadanainstrugloswitch?"Examineoexemplodeinstrugioswitch aseguir:
bYte g = 2'
switch(g)
implicitamente em um tipo
compilador sabe disso!
Se
int. - o segundo
argumento de
case
byte
seguir
int
temp = 90;
I
nd.o compila!
-c
varoo
tt't
se
oBSERVAQ6ESpeneOE)(AME
Procure alguma uiolagdo nas regras dos argumentos de
como os
swiLch, case.
Por exenp/0,
uocd pode
tr*
trecbos abaixo:
{ {
switch (x)
o: {
1: {
) No
} }
exemplo, a inshag1o
case
pakwa-chaae
case.
As
con$antes
case
para baixo,
ea
pineira
clnrtafite
case
swi
tch
serri
ponto
de enlrada da exuupio.
se encontrar uma correspond6ncia para uma constante case, a JVM executar6 o bloco de c6digo associado e tamb6m TODOS os blocos de c6digo subseqiientes (fora uma instrugio break) ! O seguinte exemplo usa um enum em uma instrugio case.
anrrm
('nlar
IraA
dra6n
].r'lrral
class SwitchEnum { public static void main(String [] args) { Color c = Col-or.gfreen; switch(c) { case red: System.out.print ("red ") ; case gfreen: System.out.print("green ") ; case blue: System.out.print ("b1ue ") ; default: .qvstem-otrt nri nf ln( "done"),'
] Neste exemplo, case green: teve uma correspondencia, entio aJVM executou esse bloco de c6digo e todos os blocos subseqiientes paru produztr a saida:
break
case
durante
swj-tch, o
processamentopassar6imediatamentedoblocoswitch
programa simplesmente continuar6
a
paraainstrugioposterioraele.Seapalavra-chaveforomitida,o
at6 que uma palavra
break
seja
encontrada na
JAVA
191
instrugio
seguir:
"x is three"
)
;
out.println
break;
System.
out.println
"x is
two" ) ,'
]
naca ?. I
System.
) )
break;
completa
B:
1O. t
nio
6 necess6ria;
tch
j6 ter6 sido
atingido.
como: /
Observagio: pelo fato de a passagem completa ser pouco intuitiva, a Sun recomenda que voc6 adicione um coment6rio, / pas sagem compl eta, quando usar essa l6gica em seus Programas.
is an odd
nrimeros pares) fosse satisfat6ria? VocA nlo poderia inserir o resultado depois da instrugio
adicionar
agora que ela 6 empregada com uma finalidade completamente diferente) a instrugio case ao c6digo anterior:
default
OBSERVAQoESPARAOH(AME
instrag1o
nofnal
da inshagdo
switch.
l-/\rarr\. z
It
);
default
;
E
se a alteramtos de modo qae
{
(rrefom arrf sJ-Lsrrrivuu.PrrrrLrLL\nrihfln/\r/\. L t,
JAVA5 I93
default :
na<a ?.
4
System.
out.printl-n ( "defaulL"
r nri tsr
);
Qrrcl- am
vse
^11t-
);
default
Aregraalembrar,iqaeainstrugdodefault fancionaexatanentec0m0qtlalqilerzutrainstril(Aocase
conpleta!
fiaparsagem
I I I
Al . t.
Cenifique-se
char ser satisfat6rio. de que umavariivel char seja declarada antes da instrugio switch.
case
deve ser seguida de uma
Cada instrugio
instrugio break.
O valor
default
L/OleTrvo poro
..f. o centttcogoo
OsloopsdalinguagemJavav6memtr6svers6es:while,doefor(e,apanirdoJava5,oloopfor temduas
variantes). Todas as tr& permitem que voc repita a execugio de um bloco de c6digo at6 que determinada condigio seja uerdadeira ott durante uma quantidade especifica de iterag6es. Voc deve estar familiarizado com os loops de outras linguagens, portanto, mesmo se for iniciante emJava, esses loops nio serio dificeis de aprender.
repeti{o,masquiserqueiuaexecugiocontinueit6quealgumacondig{o*jauerdadeira.Ainstruglow}rile temoformato
asegur:
while (expressSo) {
/ / faz al-go
i
ou
,.
]
valor booleano. O corpo do loop rdser6executadoseaexpressfo(tam66mchamadade"condigio") resultaremumvalortrue. lJmavezque entrarmos no loop, seu conterido ser6 repetido at6 que a condigio nio possa mais ser_atendida e seja avaliada como f a1se. No exemplo anteiior, o fluxo do programa entrari ,ro corpo do loop p-orque x 6 igual a 2. No entanto, x serl aumentado
while
Nesse caso, como em todos os loops, a expressio (teste) ter6 que resultar em um
alse
e a execugeo do
while
avalia&. Em outras
false naprimeiravezqueoloopwhile
forverificado,ocolpodoloopser6ignoradoeoprogramacomegareaser
seguir:
1oop" ) ;
x=10;
)
produziri
Usando loops do
O loop do 6 semelhante ao loop whi 1 e, exceto pelo fato de que a expressao nlo 6 avaliada at6. que o c6digo do loop do tenha sido executado. Ponanto, 6 garantido que o c6digo dentro de um loop do ser6 executado pelo menos uma vez. O c6digo abaixo mostra um loop do em ageor
do{
System. out.
] while(false);
)seriexibidaumavez,aindaqueaexprusdos/aaualiadacomofalse.Lembre-se loop do serrpre execvt^o c6digo de seu conterido pelo menos umaaal. Nio esquega de observar o uso do ponto e virgula no final da expressio while.
de que o
AinstrugioSystem.out.println(
oBSERVAQ6ESpeneOE)(AME
Como nos tettes
if
procure loops
whil-e
(e testes
while
de loops
do
booleano.
Examine
os exenplos
ndo-udlidar
/ Nao compila; x nio 6 booleano / / Ni,o compila; resolve como 5 (resultado da atribuiqSo)
/
.i vaLLwt A^ // // rr.<l
F^df ue>Le ^
/{a uL
i nrra l rvqqrsqseda^o
/ / var)-do
or
bisico",
or- each). Dependendo de qual docum enta&o vocA' usar (incluindo a da Sun), ver6 ambos os termos, junto comfor-in.Ostermosfor-in,for-eache"for aprimorado"referem-setodosaomesmoconstrutorJava.
O loop f or b6sico 6 mais fleivel do que o aprimorado, mas
iterag6es atrav6s de arrays
e de
or
se
refira
programagio de
conjuntos.
JAVAs I95
ritil para o controle do fluxo quando voc ji souber quantas vezes teri que executar as instru96es do bloco do loop. A declaraEio do loop f or possui tr6s partes principais, al6m do corpo do loop: O loop
r I I
Declara$oeinicializa$odevariiveis
A expressio booleana
Aexpressiodeiteragio
(teste
condicional)
Cada uma das tr6s partes da declaragio do loop f or 6 separada por um ponto e virgula. Os dois exemplos a seguir demonstram o loop f or. O primeiro mostra as partes de um loop f or em forma de pseudoc6digo e o segundo exibe a sintaxe tipica do loop:
{ " + i).
for. E enquanto as outras duas partes - o teste booleano e a expressio de iteraglo - sio executadas a cada iteragXo do loop, a declaraSo e ancialbaSo ocorrem apenas uma terminajanto com o loop!O vez, logo no inicio. VocA tamb6m precisa saber qwe o ucopo das aaiiueis dularadat no loop f c6digo abaixo demonstra isso:
dularagdo e inicialiTagdo ocorrem antes de qualqaeroutra coisa em um loop
or
System.out.println(x);
Se
voc6
Test. java:
: cannot regolve symbol : variable x location: class Test System. out.println (x) ;
---
?\ \.
| |
vrr\
; x++) {
exprerrao de teste.
uma
for (int x = 0; x < 1; x++) i / / c6digo do corpo que n6o modifica o valor
]
de x
O loop anterior ser6 executado apenas uma vez. Na primeira vez em que entrarmos no loop, x seri configurado com 0 e testado para sabermos se 6 menor do que 7 (e seri), paraque depois o corpo do loop seja executado. Ap6s a execugXo do corpo do loop, a expressio de iteraglo ser6 processada, aumentando x em uma uni&de. A seguir, o teste condicional seri
verificadoej6queoresultadoagoraserlfalse,aexecugiosaltar|parabaixodoloopfor edariprosseguimentoapaftir
dd.
Tenha em mente que, fora uma saida forgada, as avaliag6es da expressio de iteragio e, posteriormente, da expressio condicional, sio sempre as duas tltimas coisas a ocorrer em um loop for!
Exemplos de saidas forgadas incluem um break, um return, uma excegio, ou uma instrugio System. fazem com que o loop seja encerrado repentinamente, sem executar a expressio de iteragSo. Examine o c6digo
exit (
a
),
todas
seguir:
static boolean dostuff ( ) { for (int x = 0; x < 3; x++) i System.out.println ( "in for
return t.rue;
]
loop" ) ;
return true;
)
A execugio
desse c6digo
produzir6
in for
loop
O resultado da instrugio ser6 exibido apenas umavez, porque a instruglo return far6 com que a execugXo saia nio s6 da iteragio atual do loop, mas de todo o m6todo. Portanto, a expresslo de iteragio nunca seri executada nesse caso. A Tabela 5L lista as causas e resultados da finalizaglo repentina dos loops. Tobelo
5-l
C6digo do loop
O queacontecer5
A execu$o saltari imediatamente para a primeira instru$o ap6s o loop
break
reE,urn System.
for.
ao
m6todo chamador.
exit (
A execugio do programa
ser6encerrado.
ser6
completamente interrompida; o
VM
Loop for B6sico: Caracteristicas do loop for Nenhuma das tr6s seg6es da declaragio do loop f or sio necess6rias!
nio
seja necessariamente uma
boapritica):
JAVA
i-f i n. {
I97
for (;i<10;)
i++;
/
]
O exemplo abaixo demonstra um loop for com diversas variaveis. Umavirgula separa as variiveis e elas precisam ser do mesmo tipo. Lembre-se de que as vari6veis declaradas na instruglo f or slo todas locais do loop, e nio po&m ser usadas
fora desse escopo.
for (int i = 0, j = 0; (i<l-0) && (j<10),- i++, j++) SysLem.out.println("i is " + i + " j is " +j) ;
)
PREPARAQAOPARAOE)HME
O ucopo das uaidueis terd unafungdo abrangente n0 exama Vocd ter,i que saber que ama uaidael declarada no loop f ndo podeni ser usadafora dele. Pordn, ama uariduel apenas inicialiTada na inthwgdo f (rzat dularada anteriormente) pode ser usadafora do loop. Por exempk, o cddigo abaixo d uilido,
or
or
ndo
d,
for (i-nt. x = 3; x < 20; x++) { }System.out.println(x) ; A riltima coisa que deve ser ressaltada 6 qu e todas as trts rcgdes do lnop f or sdo independrntes uma da outra. As tr6s express6es da instrugio f or nio precisam operar sobre as mesmas vari6veis, embora normalmente o fagam. Por6m, at6 a expressao de
intera$o, que muitas pessoas chamam erroneamente de "expressio de incremento", nio precisa incrementar ou configut"r algo; vodpode inserirvinualmente qualquerinstru$o que qlreiraa(ecutar acadaiten$odo loop. Observe o c6digo aseguin
iterate iterate
PREI'ARAqAOPARAOE)(AME
Maitat perguntas do nouo exame (5) apruentam 'A nnpikgZofalhari" e 'Una excegdo oconeri ilo tenpl de execapho" c0m0 pzssiaeis respostar. Isso o tomanl na* difcil porque uocd ndo podeni simplesmente analisar o comportamento do aldrgo. Pineiro uocd terd que se certifcar se o aidigo ndo uti uiolando alguma regmfundamenta/ que leaani a //m elro d0 corQilador, en segaida teri qaepmcurarpossiueis excegdes, e fi dEois que tiuer satisfeito uses doit requititos podenl se aprofundar na hgica e fto flilxr do aidigo da pergunta.
or
or
or
or
aprimorado t em
dois.
int [] a = {1,2,3,4};
for(int x = 0; x < a.length; System. out.print (a Ix] ) ; for(int n : a)
x++)
/
for aprimorado
out.print
(n)
esta saida:
for
or
sio:
I Declarag6o I Expressio
A vari6vel de bloco rudm-dularada, de um tipo compativel com os elementos do array que voc6 esti acessando. Essa vari6vel estari disponivel dentro do bloco f or, e o seu valor ser6 o mesmo que o do
elemento atual do array.
ou uma chamada contendo arrays.
Estadeveavaliarcomooaffayatrav6sdoqualvocequerfazeroloop.PodeserumavariAve|dearray m6todo que retorne um array. O array pode ser de qualquer tipo: primitivo, objeto, at6 mesmo array
Usando
as
r-nt x; long x2; Long [] ta = {4L, 5L, 6L}; ]ong Jl 1a = {7L, BL, 9L};
int [][] twoDee = {{1,2,3}, {4,5,6}, {7,8,9}}; String [] sNums - {"one", "two", "three"}; enimal [] animals - {new DosO, new CatO};
/ / Aar]: r: rr ln nAac . Ia T.a\ I f nr \ .
.
'
v6lidas
fnrllnnn Farllann
for(Animal a : animal-s) i
/ // // // // // // // // //
/
loop atrav6s de um array de longs fazendo autoboxing dos objetos Long para dentro de longs faz um loop atrav6s do array de arrays faz um loop atrav6s do 3e. sub-array faz um loop atrav6s do array de Strings define uma referncia Object para cada String deflne uma refer6ncia Animal para
um
faz
cada elemento
/ / declarae6es "for" INVALIDAS for(x2 : la) ; / / x2 j6 foi declarada for(int x2 : twoDee) ; /,/ impossivel colocar um array dentro de um int fnrlinf v? . la\ // impossivel colocar um longr dentro de um int. for(Dogd: animals) ; / / vocd poderia receber um gato! O loop for aprimorado assume que, nio havendo uma saida inesperada do loop, voc6 sempre desejari que o loop seja feito atrav6s de todos os elementos do array. As discuss6es seguintes sobre break e continue aplicam-se tanto ao loop for b6sico quanto ao aprimorado.
JAVA
I99
oBSERVAe6rspeneoErreME
Lembre-r de que as inshagdet
break
.
_A
deuem
deuem ser inseridat dentw do loop; do contuiio, uocl uerti am erm do conpilador. At inshagdu ter usadat denho do kop ou de uma in$rugdo swi tch. Oburuagdo: Iso ndo v aplica a insturgdetbreak mtuladas.
continue
instruglo brea.k fari com que o programa encerre a execuglo do loop atual e inicie
o processamento na
linha de
A ingtrugio continue far6 com que s omente a iteragioatual do loop s elaencerradaeque a pr6xima iteragio do mesmo loop seja iniciada se a condiglo deste for atendida. Quando usar uma instrugio coniinuJem um loop ior, vocA teri que considerar seus efeitos na iteragio do loop. Examine o c6digo a seguir, que ser6 explicado logo depoil.
]
A pergunta 6: Esse 6 um loop infinito? A reposta 6 nio. Quando a instrugio continue for atingida, a expressio de itera$o ainda ser6 executada! Ela ser6 executada exatamente como se a itera$o anral terminasse "de maneira naturd". Portanto, no exemplo anteri or, ainda aumentanio seu valor antes da condigio (i < 10) ser verifica& novamente. Geralmente, instrugio continue 6 usada dentro de um teste i f como vemos abaixo:
1oop" ) ;
/ mais c6digo do 1oop, que ndo ser6 executado quando o t.este if / / for verdadeiro
/
acima
break quanto continue podem ser nlo-rotuladas ou rotuladas. Embora seja muito mais comum break e continue nio rotuladas, no exame ser6 esperado que voc6 saiba como as instrug6es break e conEinue rotuladas funcionam. Como mencionado antes, a instrugio break (n1o-rotulada) sairi da estrutura do
Tanto
a
instrugio
loop atual e prosseguir6 na linha de c6digo posterior ao bloco do loop. O exemplo abaixo demonstra uma instrugio
break:
boofean problem = truei
whife (t.rue)
r f lnr^h
{
{
I aml
continue nio
um
arquivo
6m\ I
nr^hl
continue;
)
/ passa para
o campo
seguinte do arquivo
com
campo
Nesse exemplo, os campos de um arquivo esteo sendo lidos um de cada vez. Quando um erro for encontrado, o para voltar ao loop (t.."1o programa ffr.."{ p"r" o ."*po r.g.tittt. do. arquivo e usari a instrugXo outros campos. Se o comando break fosse usado,.o c6digo estiver no ?inal do arquivo) . .o.tti-ttrr"r a leituri dos encerraria a leitura do arquivo quando um erro fosse encontrado e passaria para a pr6xima linha de c6digo. A instrugio conti-nue 6 ima maneira de dizer: "Essa iteragio espeLifica do loop precisa ser encerrada, mas nXo o
continue
loop inteiro. Apenas nio quero que a execugio do resto do c6digo dessa iteragXo seja terminada' portanto, processe a expressio da iteraglo i, em seguida, reinicie no teste nXo se preocupando com o que est6 abaixo da
instrugio
continue".
Instrug6es rotuladas
Embora muitas instrug5es emJava possam ser rotuladas, 6 mais comum usar r6tulos com instrug5es loop tais como f or e whi 1e, em conjunto com instrug6es break e continue. Uma instruEio de r6tulo deve ser colocada logo antes da instrugio sendo rotulada, e consiste de um identificador vllido que termina com dois pontos 0.
Voc6 precisa entender a diferenga entre instrug6es break e continue rotuladas e nio-rotuladas. As rotuladas serio ,r...ss6rias somente nas situag6es em que voc6 tiver um loop aninhado e precisar indicar qual quer encerrar ou a panir de qual deseja continuar a pr6xima iteragio. Uma instrugio break sair6 do loop rotulado e nio do loop atual, se a palavrachave break for combinada com um r6tulo. IJm exemplo do formato de um r6tulo se encontra no c6digo abaixo:
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:
for(int 1=6; i<5; i++) { while (isTrue) { System. out .println ( "Hel1o" ) ; break outer; j / / fim do loop for interno
Swst-em-out nri nfln(\'Orrt-er eJsLerrr.vuu.y-rrrurrl\ vsevr
"l
+vvy.
nnn t'\:
// n5o seri
exibido
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,
break
por
continue:
outer:
for (int j=0; j<5; j++) { System. out.println ( "He11o" continue outer;
JAVA
5 20]
Nunca 6
exibido
]
System.
out..println
desse
(..Good-Bye,, ) ;
A execugio
c6digo produzir|:
Hello
Hel1o
HeIfo
He11o
Helfo
cood-Bye
Nesse exemplo, a palavra
Hel1o
instrugio
fluxo continuare com a pr6xima iteragio do loop identificado pelo r6tulo. Para concluir, quando a condigio do loop externo fior avaliada como fal-se, o loop ser6 encerrado e a palavra Good-Bye ser6-exibida.
Exercfcio 5-2
r I
O r6tulo
outer
while
comegar.
ou
nlo.
Certifique-se de que a variAvel age seja declarada fora do loop uft i 1e.
continue e break
rotuladas deuem ficar dentro do loop que tiaer o mesmo rotulo; cato contririo, o aldigo ndo seni
combilado.
At \JoleTrvo poro
o centttcocoo
.ctc
clduvlat
nhb,fnalfi)
e declarar mdtodos
nio,
os
2.5 Rcconbecer o efeito de ama exnpdo lanpada em um ponto etpufrn dofragwento de an cddigo.
tenpo de exuugdo, uerifcada oil um etro.
excegdo
pode ser de
80 por cento do trabalho sio usados em 20 por cento do temp_ o. Os 80 por cento se referem ao esforgo necessirio para identificar e manipular erros. Em muitas linguagens, escrever o c6digo-de programas que procure e lide com erros 6 mon6tono e transforma o c6digo-fonte do aplicativo em um emaranhado conftrso. Ainda assim, a detecgio e manipulagio de erros podem ser os ingredientes mais importantes de qualquer aplicativo robusto. A linguagemJava fornece aos desenvolvedores um mecanismo sofisticado para manipulagio de erros que produz c6digos de manipulagio eficientes e organizados: a manipulagdo de excegdes.
A manipulagio de exceg6es permite que os desenvolvedores detectem erros facilmente sem escreverum c6digo especid para testar valores retornados. Melhorainda, nos permiJe manter um c6digo de manipulagio de exceg6es nitidamente separado do c6digo que gerariaexcegio. A16m disso, permite que o mesmo c6&go de manipulagio de exceg6es lide com as diferentes exceg6es possiveis.
O exame tem trs objetivos relativos ao tratamento de exce96es. Abordaremos os dois primeiros nesta segXo e, na pr6xima segio, abordaremos os aspectos do tratamento de exceg6es que foram introduzidos no exameJava 5.
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
ncia da execugio d. yT programa para um manipulador de. exceg5ei apropriado quando uma excegio ocorrer. Por exemplo, se voc6 chamar um m6todo-que abra um ar.quivo, -o *"t nio puier ser aberto, a execugXo desse m6todo seri encerrada e o c6digo que foi escrito para lidar "rqrrirro .orn .ss"iitnagio seri processado. Portanto, precisamos de uma maneira para informar ) JVM que c6digo executar quando determinada excegio ocotrei. Para f.azer isso, usamos as palavras-chaye_ try- . ge.t"l. A palavra try 6,tsid" pat" indicar um bloco de c6digo no qual possam ocorrer exceg6es. Esse bloco de c6digo 6 chamado de regido protegida (que na verdade significa: "Aqui enlrari um c6digo arriscado"). IJma ou mais cliusulas catch assoJi"rio uma excegio especifica (ou classe di exceg6es - veremos mais sobre isso posteriormente) a um bloco de c6digo que a manipularZ. Abaixo podemos ver o formato em pseudoc6digo:
1. try { 2. // F-ssa 6 a primeira linha da "regido protegida" 3. / / q)e 6 control-ada pela palavra-chave try. 4. // Insira um c6digo agui que possa causar algum tipo de exceqao. 5. // Podemos ter muit.as linhas de c6digo aqui ou apenas uma. 6. ]
'7 aalrh lMrrE'irrves.l E'v.ahf r<l\rrJr i ^h\ {
8. 9. 10.
1-1. ]
1)
// Inslra um c6digo aqui que manipule essa exceq6o. / / Essa 6 a linha seguinte do manipulador de exceeao. / / F,ssa 6 a riltima linha do manipulador de exceqao'
c:l-ctr aM\rqa.^ndEynonfi
\.rJ vvvv^.gg
nn\
13.
1.4. j
15.
// Insira
um
16. / /
Algum
(comum, ndo
Nesse exemplo de pseudoc6digo, as linhas 2 a5 constituema regiio protegida que ser6 controladapela cl6usula try. A linha sete 6 o manipulador para uma excegio do tipo MyFirstException. A Linha 12 6 um manipulador para uma excegeo Isso 6 um do tipo MySecondException. Observe que os blocos catch aparecem imediatamente ap6s o bloco Al6m disso, todos os blocos requisito; se uocd tiuer um ou mait blocos catchi, eles deuem @arecer imediatamente @d: o bkco forem precisam ficar um ap6s o outro, rcm nenhuma instrugdo ou bloco entre elet A ordem na qual os blocos
try.
calch
catch
A execu$o ini ciari naIinha2. Se o programa for processado at6 a linha 5 sem nenhuma excegio lanqada, a execugio seri transferida para a linha 15 e continuar6 dai em diante. No entanto, se em algum momento entre a linha 2 e 5 (o bloco try) uma excegao do tipo MyFirstException for lanQada, a execugXo ser6 imediatamente transferida para a linha 7. Em seguida, f linhas 8 a 10 serio processadas para que todo o bloco catch seja executado e depois o processamento passar6 para a linha 15 e dari prosseguimento.
se uma excegao ocorresse, digamos, na linha 3 do bloco try, as outras linhas desse bloco (4 e 5) nunca seriam executadas. Uma vez que o controle do flrxo salar para o bloco catch, ele nXo retornar6 para concluir o restante do bloco ttt. pt.ndoc6digo: try. No entanto, isso dexatamenre o que queremos. Imagine se seu c6digo fosse parecido
Observe que
&*
try
{ i \roNaRedg
.anl- rrraAr-r
I ei aArmr i \/nePreenchaTabela
)
catch (NdoPodeCapturarArquivoNaRede )
rrseArmrirrnT.ocaf
)
O pseudoc6digo anterior demonstra como geralmente as excegSes sio usadas. O c6digo que depende de uma operaEXo arriscada (como o preenchimento de umi tabela com dados de arquivo depende da captura do arquivo na rede) foi
JAVA
5 203
try de uma maneira que se, digamos, a primeira operagio falhar, vocA nio dari prosseguimento na,tentativa de executar outro c6digo que com cenezatamb6m falhar|. No exemplo do pseudoc6digo, voc6 nio conseguir6 ler o arquivo se nio puderprimeiro capturiJo narede.
agruPado em um bloco
Um dos beneficios
que Poss, ocorrer
de us.1r a manipulagio de exceE6es 6 que o c6digo de manipulagio de alguma excegio especifica ser escrito somente vmavez. Voltando rroiso c6digo anterior, pode "o haver tr6s locais diferentes-no bloco capazes de gerar uma exceglo MyFirstException, mas o.rJ. qr.r q.t. .1" ocorra seri manipulada pelo mesmo bloco (da linha Z). Discutiremos ourros-beneficios da manipulaglo de exceg6es peno do fim deste capitulo.
Lry
catch
fornecem um 6timo mecanismo de captura e manipulagi,o de exceg6es, mas ainda ficamos com o problema de como nos organizar depois. J6 que a execugio 6 transferida pari fora do bloco assim que uma excegio 6 langada, nio podemos inserir nosso c6digo de limpeza no final desse blocoi esperar que seja executado se uma excegio ocorrer. lJma id6ia quase tio inadequada quanto essa seria inserir o c6digo de limpezi nos blocos catch.
try
Os manipuladores de excegio representam um local inapropriado para a limpeza depois da execuglo do c6digo do bloco porque cada manipulador precisari de sua pr6pria c6pia do c6digo de limpeza. Se, por exemplo, voc6 alocasse um socket de rede ou abrisse um arquivo em um algum local & regiXo protegida, cada manipulador & excegXo teria que fechar o arquivo ou liberar o socket. Isso tornaria f6cil esquecer a inclusio da limpeza e levaria a um c6digo redundante. Para resolver esse problema, a linguagemJava oferece o bloco f ina11y.
try
Oblocofinally
langada ou
enfeixar6oc6digo,quevnpreserS,exesfiadoemalgumpontodepoisdobloco
Lry,vunaexcegdofor
ndo.Mesmo se houver uma instrugio de retorno no bloco t.ry, o bloco f ina11y seri executado logo ap6s essa instrugio!Esse 6 o local certopara fecharseus arquivos,liberarseus sockets de rede e executar qualquer outralimpezaque seu c6digo necessitar. Se o bloco for executado sem exceg6es, o bloco f ina11y ser6 processado imediataminte ap6s o
try
!2:
1?. L4:
1
finally { // Ponha aqui o c6digo para liberar qualquer recurso / / |'enhamos a]ocado na c15.usu1a trv.
que
langada, a clausala f inal1y tamb6m ser6 executada. Posteriormente examinaremos alguns cen6rios nos quais f pode nio ser executada ou concluida.
dequefinally
sempreseriexecutada.seaexcegioforlangada,a&iiukfinally seriexecutada.Seaexcegionaofor
ina11y
kmbrese de que as cl6usulas f ina11y nlo sio obrigat6rias. Se voc6 nio quiser escrwer uma, seu c6digo ser6 compilado e executado da mesma maneira. Na verdade, se vocA nio tiver recursos a liberar depois que seu bloco for concluido, provavelmente nio precisari& umacl6usula f inally. A16m disso, ji que o compilador nXo exige nem mesmo cl6usulas catch, em algumas situag5es voc6 se deparard com c6digos com um bloco imediatamente seguido porum bloco f inal ly. Um c6digo dese tipo 6 6til quando a excegio 6 retornada para o metodo chamador, como explicaremos na pr6xima seglo. O uso de um bloco f permitiri que o c6digo de limpeza seja executado at6 mesmo quando nXo houver uma cl6usula catch.
try
try
inalIy
try
com f
inally,
por6m, sem
catch:
trY
/
/ faz aTgo
]
O c6digo v6lido
a
try, catch
inally:
try
/
faz a limneza
O c6digo
inudlido {
try,
sem
catch
ou f
ina11y:
LrY
/
/ faz algo
/ 5 preciso um catch ou finally aqui System.out.println("out of try block") ; O c6dtgo inu,itidna seguir demonstra um bloco catch inserido trY { / / faz a1-go
/
)
erroneamente:
/ nd.o se pode ter c6digo entre trylcatch System.out.println( "out of try b1ock" ) ; catch(Exception ex) { }
/
em um etro do conpilador.
cldusula
catch
ow
cllaula f
inall-v,
oBSERVAQ6ESpeneOE)(AME
V'oci ndo pode conpilado:
inseir nenham
try
catch
(oa
try
f inal-l-y).
trY
/
/ faz
al-go
Propagando exceg6es
nio capturadas
Por que as cliusulas catch nio sio necessirias? O que acontecerA a uma excegao que for langada em um bloco try quando nio houver nenhuma cl6usula catch esperando por ela? Realmente, nio 6 um requisito a codificagio de uma cliusula catch paracada excegio que possa ser langada no bloco try correspondente. Na verdade, hi drividas se 6 possivel conseguir tal proezal Quando um m6todo nio fornece uma cl6usula catch para uma excegio especifica, diz-se que esse m6todo est6 "passando" a excegio (ou "passando a responsabilidade").
JAVA
205
EntXo, o que acontecer6 a uma excegio transferida? Antes de discutirmos isso, precisamos revisar rapidamente o conceito de pi/ba de rbanadar A maioria das linguagens apresenta o conceito de uma pilha ie m6todos ou de chamadas. Colocando de maneira simples, a pilha de chamadas 6 a cadeia de m6todor qn. r.,r programa executari para chegar ao m6todo atual. Se seu -a ) e este chamar o m6todo Programa comeqar no m6todo main ) , que chamari b m6tod6 U ) que, por s uavez,
chamar6om6todoc( ),apilhadechamadaspoder6serrepresentadadamaneiraaseguir:
lr
rtde ser representada em ordem inversa (embora tamb6m possa ser visualizada na ordem correta). Como voc6 pode ver, o riltimo m6todo chamado est6 no inicio da pilha, enquanto o primeiro m6todo que fez uma chamada est6 no final. O primeiro m6todo do rastreamento de pilha serla o que voc6 estivesse executando atualmente. Se nos movAssemos para baixo na pilha, passariamos do m6todo atual para o m6todo chamado anteriormenre. A Figura 5-1. ilustra uma maneira de representar como a pilha de chamadas funciona emJava.
"-;il"
Agora examinaremos o que acontece )s exceg6es transferidas. Imagine um pr6dio, digamos, de cinco andares tendo em cada andar uma varanda ou sacada. Agora imagine que em cada varanda, uma pessoa est6 vestindo uma luva de baseball. As exceg6es sio como bolas passadas de uma pessoa a outra, comegando do riltimo andar. Primeiro a excegio 6 langada do inicio da pilha (em outras palavras, pela pessoa do riltimo andar) e se nio for capturada pela mesma pessoa que a langou (a pessoa do riltimo andar), elacirS.paraom6todo anterior da pilha de chamadas, que seri a pessoa qui estivei um andar abaixo. Se nio for capturada ai, pela pessoa do andar de baixo, a exce gdo/bola carhnovamente para o m6todo anterior a esse (a pessoa do pr6ximo andar de baixo) e assim por diante at6 que seja capturada ou alcance o final da pilha de chamadas. hso 6 conhecido coma prnpdga$o de excegdo.
Se a exceglo alcangar o final da pilha de chamadas, seri como chegar ao fim de uma longa descida; a bola arrebentar6 assim como seu programa. lJma exceEio que nio for capturadafaricom que seu aplicativo pare de ser executado. A descriglo (se houver uma disponivel) da excegio seri exibida e a pilha de chamadas "eliminada". hso o ajudari a depurar seu aplicativo ao lhe informar que excegio foi langada, de que m6todo e qual era o formato da pilha no momento.
z
I
A pilha de chamadas enquanto method3$ esti sendo executado. A execugio volta para method2Q I T methatQ I method2Q vai finalizar
2)
2 [ method$-l t [:"3ajn"-o*J
method
l()
vai finalizar
5-l
OBSERVAQ6ESpeneoE)(AME
Vocd pode langar
ama
excegio
da
pilba. Mas,
e quando cbegar ao
ruitodo
main ( )
no
fnal?
resltani
em uma interrupgdo da
);
x= 5/0; //
rmpossivel
)
qrc exibinl o rartreaneflto
da
Pilha,
Sjava TestEx
by zero at TestEx. doMoreStuff (TestEx. java : 10) at TestEx.doStuf f (TestEx. java : 7 ) at TestEx.main (TestEx. java : 3 )
inally
I r I I
) , que
Em
reverse, verifique se a string tem um comprimento igual comprimento for igual a 0, ele langar6 uma nova excegXo.
usando o m6todo
String . length (
) . Se
Agora incluiremos o c6digo para inverter a ordem da string. J6 que ess e nlo 6 o t6pico principal deste capitulo, forneceremos o c6digo de inversio, mas sinta-se lvontade parate$6lo como quiser.
return reverseStr,'
Agora, no m6todo main ( ) tentaremos chamar esse m6todo e manipular qualquer excegio em potencial. Al6m disso, incluiremos uma instruglo f inal 1y que nos informar6 que a execugio foi concluida.
Definindo excec6es
J
as exceg5es como um conceito. Sabemos que elas sio langadas quando um problema de algum tipo ocorre efeito terio sobre o flrxo de seu programa. Nesta seEio desenvolveremos os conceitos um pouco mais e usaremos as exceg6es em um c6digoJava frrncional. Anteriormente dissemos que a exceglo 6 uma ocorr6ncia que altera o fluxo normal do programa. Mas, ji que estamos falando deJava, tudo que nlo for um tipo primitivo deve ser... Um objeto. As exceg6es emsua nSosio,bem,vmaexcepioaessaregra.Todaexcegio6ainstAnciadeumaclassequepossuiaclasseException hierarquia de heranga. Em outras palavras, as exceg6es sio sempre alguma subclasse de j ava . lang . Exception.
Temos discutido
e que
Quando uma excegXo 6langada, o objeto de um subtipo Exception especifico 6 instanciado e inserido no de exceg6es como um argumento para a cliusula catch. Uma cllusula catch real tem este formato:
manipulador
try
)
catch (ArraylndexoutofBoundsException e)
e )
.
printStackTrace
();
JAVA
Nesse exemplo,
207
6 a instAncia de
Hierarquia de exces6es
Todas as classes de exceE6es sio subtiFos da clase Exception. Essa classe 6 derivada da classe derivada da classe obj ect). A figura 5-2 mostra a hierarquia das classes de exceg6es.
de
Throwable
(que 6
Como voc6 pode ver, hiduassubclasses que derivam de Throwable: Exception e Error. As classes que derivam Error rePresentam situag6es incomuns que nio sio causadas por errot tro prog.ama e indicam coisas que nio ocorreriam normalmente durante sua execuglo, como a JVM Ticar ..tra mem6ria. Geralmente, os "rp"gJ aplicativosrrio conseguem se recuperar de-um erro, ponanto, nio precisarnos manipul6-los. Mesmo se seu c6digo nio os manipular (e geralmente eles nlo o fazem), ele ainda seri compilado sem probl.-.t. Embora freqiientemente considerados como condig6es excepcionais, o, .rror^t..nicamente nlo sio exceg6es porque nio derivam da classe Exception. No Ambito geral, uma excegio representa algo que ocorre nio como o resultado
disso, porque algum recurso
de
nio-isti disponivel ou por alguma outra condigio requerida para .".ltgao i"rreta nio esrar " Presente. Por exemplo, se seu aplicativo tivesse que ie com.tnica. com outro aplicativo ou computador que nio estiver respondendo,.essa 6 uma excegio que nio:er6 causada por urn erro. A Figura S-Z tamb6m mostra um iubtipo de Exception chamado RuntimeException. Essas exceg6ei sio um caso esp.iial potqne, ls vezes, indicam realm.rrt. "rrorno Programa. Elas tamb6m podem representar condig5es excepcionais r-aras e dificeis de manipular. As exceg6es de tempo
de execugio
classes de exceg6es, a maioria delas tendo nomes bem descritivos. Hl duas maneiras de obter informag6es sobre uma excegio. A primeira 6 sobre o tipo_da propril exceglo. A outra 6 sobre as informag6es que voc6 pode obter do objeto de.exceglo. A classe Throwable (no topo da 6rvoie de heranga de exceg6es) fornece aos seus descendentes alguns m6todos que slo riteis em manipuladores de exceg6es. Um deles 6 piintstacktrace ( ) . Como j6 era espelado, se voc6 chamar o m6todo printstackTrace ( ) de um objeto de excegio, conforme fizemos no exemplo anterior, ser6 exibido o rastreamento de pilha do local onde a excegXo ocorizu
Vimos que uma pilha de chamadas 6 criada em ordem inversa com o rlltimo m6todo chamado inserido no inicio. Voc6 veri que o m6todo printstackTrace ( ) exibir6 o m6todo inserido mais recentemente primeiro, e dar6 prosseguimento, exibindo o nome de cada m6todo ao percorrer a pilha de chamadas (isso 6 ch arnado de dr:ronknento fupiiba) piri. do " inido.
oBSERVAQ6ESpeneOE)(AME
No exam4 nio seni
Senl esperado que
necessdrio conhecer nenham dot ndtodos contidot nas c/asvs
uocd
tion).
throw
Error.
Excep-
e que podem
s/a un snbtipo
Figuro
poi. ."itnt". nais de um tipo de exceglo .- ,rttt" rinica cliusula catch. Se a classe de excegio que _v_oc6 .rp..ifi."t na cl6usula catch nio tiver subclasses, entio, somente a classe especificada ser6 capturada' No
entanto, se a classe especificada na clAusula especifcada mmb6m seni c@tarado.
a palavra-chave
catch
permite
a especificagXo do
tipo
catch
tiver
.rabclasses
da
classe
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
uma excegao
de limites
catch (IndexOutOfBoundsException e)
e )
Se
.
printStackTrace
);
excegio seri capturada e manipulada. Isso pode ser conveniente, mas deve ser usado moderadamente. Ao especificar a superclasse de uma classe de excegio em sua cl6usula catch, voc6 descartari informag6es valiosa, sobre ,^.xcegio. E claro que voc6 pode descobrt exatamente que classe de excegio foi gerad4 mas se quiser fazer isso, ser6 melhor escrever uma cliusula catch separada para cada tipo de excegio que lhe interessar.
a
Stringlndexoutof Bound.sExcetion,
ou
AOTRABALHO
Resista
i
/
tentagdo de esreaer somente um rzanipa/ador que captilre todas as excepdes encontradas como o descrito abaixo:
trv
)
/ o c6digo
{
();
catch (Exception e)
e
)
Esse aidtgo uai c@turar todas
.
printstackTrace
at
excegdu geradas.
nanipular indiuidualmente
de maneira
@mpiada
feita
dessa maneira
prejadicani o objetiuo
do
pnyta Ot manipuladoru
reda{rdo a confabilidad.e
de rea pmgrama Porque d possiuel que c@turem uma excegdo que ndo saibam
Correspond6ncia de exceg6es
voc6 tiver uma hierarquia de exceg6es composta de uma superclasse e virios subtipos, e estiver interessado em manipular um dos subtipos de maneira especial, manipulando todos os outros juntos, ter6 que escrever somente duas cl6usulas catch.
Se
Quando uma excegio for langada, Java tentar6 encontrar (procurando nas cl6usulas catch disponiveis, de cima para baixo) uma cliusula catch para o tipo da exceglo. Se nlo encontrar, ir6 procurar um manipulador para um supertipo da
excegio.Senzoencontrarumacliusulacatch Examinemosumexemplo:
quecorrespon&aosupertipodaexcegio,entAo,aexcegioser6propagada
de excegdes.
1: import java.io.*; 2: public class ReadData { 3: public static void main(String arqs[] ) { 4: try { 5: RandornAccessFile raf = 6: new RandomAccessFile ( "myfile. txt", "a"; 7: byte b[] = new byte[1000]; 8: raf.readFully(U, 0. 1000);
JAVA
5 209
catch(fOException e)
printstackTrace
,.
20: 21 : j
Esse
tipo
ler alguns dados nele. A abenura e leitura de arquivos podem gerar muitas roException. Suponha que nesse program; estiv3ssemos'inreressados ^Caso foi rileNotFoundnxceition. contr6rL, nio nos importar6saber qual
e
de
FileNotFoundException
catch.
determinarse
6 r'ltemotFbundException. Emvezdisso, codificamos um maniputdorde exceg6es eqpecialpara Fi leNotFoundException e um manipulador separado para todos os outros subtipos de toException. Seessec6digogerarumaexcegioFilelJotFoundException,elaserimanipuladapelacliusulacatch quecomega nalinha 10.Se geraroutra excegeo roException-talvezEoFException, que 6 uma subclasse de loException-
6 uma subclasse de roException. Porranto, poderiamos manipuli-la na cl6usula cuja finalidade 6 capturar todos ossubtipos de roExcep_tion, mas ter?amos que tesrar Jexcegio p"ra
elaser6manipuladapelacl6uzulacatch
de
chamadas.
loException.
Isso
importantelSe
FileNotFound.Exception, foi inserida acimado manipuladorde for feito de maneira inversa, o programa nio sericomplado. Os nanipuladores sempre ser inseridos acima dos de exngdu gerais. O c6digo a seguir nio ser6 compilado:
de
try
/
/ faz
) catch (IOException e) t / / traLa loExceptions qerais ) catch (Fil-eNotFoundException ex) { / / Lrata apenas FileNotFoundException
)
TestEx. java:
15
has
pensarmos nas pessoas com luvas de baseball (da segio "Propagando Exceg6es Nio-Capturadas'), suponha que as luvas mais abrangentes sejam as mais largas e, portanto, possam caprurar muitos tipos diferent.i de bol"s.'Uma luva roException 6 grande e flexivel o bastante para capturar qualquer tipo di roException. Assim, se a pessoa do quinto andar (digamos, Fred) tiver uma grande luva lOException, nio poder6 evitar a caprura de uma bola
FileNotFoundException com ela. E se o sujeito (digamos,Jimmy) do segundo andarestiverusandoumaluva Fi leNotFoundException, essa bola nunca chegari a ele, ji que sempre ser| aparada por Fred, no quinto andar, que estar6 de guarda com sua luva grande o bastante para capturar todas asixceg6is roExcepCion.
Portanto, o que voc6 far| com exceE6es que sejam irmXs na hierarquia da classe? Se uma classe Exception nio for o subtipo ou supeftipo da outra, enteo, a ordem na qual as cl6uiulas catch serio inseridas n1o imponar{.
exceg6es do tipo declaraquelangaumaexcegeoniosignificaquesemPreo MyExceptionl eMyuxception2 (s6porqueom6todo fani. Ele ap enas inf o rma qu e p o fu faz|-lo).
void,
que
Suponhamos que seu m6todo nio langasse diretamente uma excegXo, mas chamasse um m6todo parafa{-lo. Voc6 pode priferir nio manipular a excegio e, em vez disso, apenas declarA-la, como se fosse rz m6todo que realmente tivesse langado a ixcegio. Se vocA declarar a excegio que seu m6todo capturari de outro m6todo e nlo fornecer um bloco try/catch para ele, entlo, o m6todo propagariaexcegio devoltapara o m6todo que o chamou e elasericaptwradaai.oucontinuarS'aser transferida atrav6s do flrxo, para ser manipulada por um m6todo mais abaixo na pilha.
_
Qualquer m6todo que pude r kngarwaexcegio (a menos que ela seja uma subclasse de RuntimeExcepLion) deue otransferindo'e deixando a declar-ila. Isso inclui os m6todos que nio estiverem langando-a diretamente, mas que estiverem excegXo passar para o pr6ximo m6todo da pilha. Quando voc6 "passar" uma excegio, ser6 como se a tivesse langado. As subclasses de runtimeexception nXoistXo incluidas ai, portanto, o compilador nio verificari se voc6 as declarou. Por6m todas as exceg6es que nio pertencerem a RuntimeException serXo consideradas "verificadas", porque o compilador far6 uma checagem parater certez.ade que voc6 sabe que "algo inadequado pode acontecer aqui".
Lembre-se do seguinte:
Todo mdtodo deae ou tratar todat as excepdu ueificadag fomecendl ama cl,iusula que ndo tiuer recebido tratamento c0m0 tlma exegdo langada. Essa regra 6 conhecida
catch,
como o requisito "tratar ou declarar'deJava (is vezes chamado tamb6m de "captvrar oudeclarar').
throw
@ntenta
dois grandes
void doStuff O i
doMore ( ) ;
)
void doMoreO
]
{
(
( )
langa uma excepdo uerifcada, mas ndo a dulara! Ponim, suponha qae o mdtodo
doMore
O throws lOException { ... i OnitododoStuff ( ) ainda@re-rentardproblemasporqueeletanbimprecindeclararaexcegdolOException,amenlrqilea nanipule por meio do fomecimento de am bloco Lry f caLch, com una cllasala catch que posta tratar a exregio
doMore
JUE;XCe1)C.r_On.
void
dessa regra. Um objeto do tipo RuntimeException pode ser m6todo sem ser especificado como parte da interface priblica do metodo (e um manipulador nlo {e Walquer precisari estar presente). E mesmo se um m6todo declarar realmente uma excegio RuntimeException, o m6todo que o chamar nio ser6 obrigado a manipul6-la ou declar6-la. As exceg6es RuntimeException, Error ndo uerifcadas, e as excegdes ndo ueifcadas ndo precisam
nr
especifcadas ou nanipaladas.
JAVA
5 2I I
public int myMethod2 ( ) throws EOFException { // Ponha aqui algum c6digo para fazer o lanqamento da exceqdo return 1;
]
)
ExaminemosmyMethodl( ).J6queaexcegioEoFException 6subclassedeToException,que,porsuavez,6 dg o<ception, elaser6,verificadaedeve serdeclaradacomoumaexcegeo quepode ser langadaporlsse m&odo. Mas rybclasse
de onde realmente vir6 a exce$o? A interface priblica do m6todo mlzMethod2 ( ) cliam-ada aqui, declara que uma exce$o das5stipopodeserlangda. Se esse m6todo realmente langar6 aexceSo ouchamar6outro m6todoparalang6-14 nlotemimportAncia; apenas sabemos que temos de captlrar a exce$o ou declarar que a lanEamos. O m6todo myzt{ethodl ( ) nio captura a excefro, portanto, decl ara que alanprL Agora examinemos outro exemplo vilido, qilethod3 ( ) .
//
)
Ponha
uma
NullPointerException
RuntimeException 6asuperclasseimediatadeNul-lPointerException,ela6umaexcegao
m6todopode langaruma excegioNullPointerException.J6que nioueifcadaenio declarada. Podemos ver que myMethod ( ) nio declarou nenhuma excegio.
As exceg6es de tempo de execugio sio conhecidas como excegdu ndo uerifcadas. Todas as outras exceg6es, ou seia, todas aquelas que nio sio derivadas de j ava. 1ang. RuntimeException, sio excegdu ueifcadas.A exceglo verificadaterS, que ser capturada em algum local de seu c6digo. Se voc6 chamar um m6todo que lance uma excegio verificada, mas nio capturar elsa e*cegio em algum local, seu c6digo nio seri compilado. E por isso que elas sio chamadas de exceg6es veri{icadas; o compilador verifica para se cenificar se elas foram declaradas ou manipuladas. Virios m6todos das bibliotecas Java 2 Standard Edition langam exceg6es verificadas, portanto, voc6 geralmente estari escrevendo manipuladores para rratar de exceg6es geradas por m6todos que nlo escreveu.
Voc6 tamb6m pode langar uma exceglo, que j6 exista na API Java ou que tiver criado. Para criar sua pr6pria excegio, simplesmente crie uma subclasse de Exception (ou uma subclasse a partir das subclasses de Exception) da maneira a seguir:
}
a
seguir:
; //
verificada
i nn I \
oBSERVAQ6ESpeneOE)(AME
puando o objeto de um subtipo /a
for langado, ele teni que ser manipulado oa declarado. Esses objetos sio chamados excetl as que sio rubtipor /e RuntimeExceptiort, consideradas exupdes nio uerifcadat Estla preparado para identifcar mitodos que ndo sigan a regra da ruanipulagdo ou declaragdo, coml em
excegdes uerifcadas e incluem todas as excegdes,
Exception
de
trY
)
{ narrr MlrFv^ani i nn / )
.
fhrat^t
catch(MyException me)
throw
)
me,'
]
Vocd terd que
Eror e exceg6es verificadas e nio verificadas. Objetos do tip o Error embora representem condig6es excepcionais. Tanto Exception quanto Error compaftilham uma superclasse em comum, Throwable, portanto, os dois objetos podem ser langados com o uso da palavra-chave throw. Quando um objeto Etror, ou uma subclasse de Error , 67angado, nio 6 verificado. Nio 6 preciso capturar obietos ou subtipos de nrror. VocA tamb6m pode langar um objeto Error por sua pr6pria conta (embora talvez nunca queira fazer isso) e capturar um objeto desse tipo, mas, provavelmente, nio irl fazA-lo. O que, por exemplo, voc6 faria se recebesse um objeto ouLofMemoryError? Nio poder6 informar ao coletor de lixo que inicie a execugio; pode apostar que a JVM lutou desesperadamente para se safar (e consumiu toda a mem6ria que p6de) no momento em que voc6 recebeu o erro. Em outras palavras, nio espere que a essa altura a JVM diga: "Executar o coletor de lixo? Oh, muito obrigado por me solicitar isso. Nunca teria me ocorrido. Certo, o farei imediatamente...". Ou melhor, o que faria se surgisse um virtualMachineError? Seu programa ji estaria danificado no momento em que voc6 capturasse o erro. Portanto, nXo hi realmente por que capturar uma dessas gracinhas. Apenas lembre-se de que voc6 pode faz|-lot O c6digo abaixo seri compilado adequadamente:
Voc6 teri que saber
nXo sXo objetos
a
Exception,
Ndo 6 necess6ri-o
declarar
um
erro
Ndo
6 necess5rio declarar
um
erro
);
f6ssemos langar uma excegio verificada em vez de run erro, enteo, o m6todo doStuf f ) teria que declarar a excegio. nio 6 um subtipo de Exception, nio ter6 que ser declarado. Voc6 est6livre para Mas lembre: Ji que o objeto declari-lo se quiser, mas o compilador simplesmente neo se impoftar6, de uma maneira ou de outra, quando ou como o erro w6,7angado, ou ainda por quem.
Se
nrror
JAVA
5 2I3
AO TRABALHO
Jd que a linguagen Jauapwsui
excegdes uerifcadat, narnalmente diq+e qae elaforga ot dercnuoluedores a manipular erros. Sim, a linguagem Jaua nosforga a esmuer manipaladores para cada excegdo que possa oeornr dilrante a operapilo nomtal, mas 6 nossa responnbilidadcJaTer qot
f#f*"t try
{
ilril.
Conhecemos gerentet de
callBadl"Iethod
);
} manipuldJa realmente. Voc6 nem newo podeni informar qae a
excegdo
pi/ha.
catch, tamb6mpodelangara
mesma
catch(IOException e) { / / paz coisas, e se voc6 decidir depois que ndo vai fazer o tratamenEo. . . throw e;
]
Todas as outras cl6usulas catch associadas ao mesmo bloco serio ignoradas, um bloco f ina11y, se existir, seri executado e a excegio ser6langada novamente para o m6todo chamador (o pr6ximo m6todo na pilha de chamadas). Se voc6 langaruma excegio verificada a partir de uma cl6usula catch, tamb6m t er|, que dzclararessa excegio! Em outras palavr as,ter|
try
quemanipularedeclarar,eniomanipular
oudeclarar.Oexemploaseguirnio6v6lido:
try
/
] catch(fOException ex) { // impossivel tratar throw ex; / / Impossivel lanqar a ndo ser que voc6 a declare
]
suficiente.
Se
excegio
loB<ception
que capturou,
teri
que declariJa!".
I I I I
ser6
chama& de eadFoodException.
e
Essa
Crie uma
enquanto.
classe de
inclusio chamada
MyException
um m6todo main
Crie um m6todo chamado checkFood ( ) . Ele usar6 uma string como argumento e langari nossa excegio se nio achar aceit6vel o alimento que for fornecido. Do contr6rio, nos informari que o alimento 6 aceit6vel. VocA pode adicionar i lista qualquer alimento de que nio gostar especificamente.
checkFood
( )
( ) , vocA extrair6 o argumento de linha de comando do array de strings e, em seguida, m6todo checkFood ( ) . J6 que se trata de uma excegio verificada, om6todo precisa declar6Ja e o m6todo main ( ) teri que manipuliJa (usando um bloco trylcatch).
main
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.
2.5
6 outra 6rea que a equipe de criagio do exame decidiu expandir para o exame SCJP 5 . Esta seglo discute os.aspectos dasexceg6es que foram adicionadas para e$a nova vrsio. A intengXo do Objetivo 2.6 6 certificar que voc6 est6 familiarizado com alguns dol erros e exceg6es mars comuns que rra encontrar como programadorJava.
O tratamenro de exceg6es
OBSERVAQ6TSpeneOF)(AME
As Ao
questdes desta sepio prouauelmente ser6o algo do tipo longo de exame, as questdes apretenturAt
essas
:'Eh
excegdo ser,l
langada?"
algun aldigo
e lhe pedird.o
se serd lanpada
una
excegdo.
Uma ueTque
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.
I r
Exceg6es da JVM As exceg6es ou erros que sXo ou exclusivos ou mais logicamente langados pela JVM.
Excegdes Program6ticas As exceg6es langadas explicitamente pelo aplicativo e ,/ ou pelos programadores da API.
Mas 6 claro que o compilador perceber6 o problema com esse pequeno programa, certo? Errado - voc6 vai ter de se virar sozinho. O c6digo compilari sem problemas, mas aJVM langarS, uma NullPointerExcept.ion quando tentar chamar o m6todo length ( ) .
Anteriormente neste capitulo, n6s discutimos a pilha de chamadas. Como voc6 deve se lembrar, usarnos a convengio de qye main ( ) estaria no final da pilha, e de que, )-medida que main ( ) chamar outro m6todo, e este chamar um outro m6todo, e assim por diante, a pilha ciesc. p"t" citna. E claro que a pilha residre na mem6ria, e mesmo que o seu SO lhe dA um grgabFi de RAM p"r" o t.r, pro gt^*a,ainda 6 uma qu"nti" fittit". E possivel que a pilha fiqui tXo grande que o SO acabe ficando sem espago par^ armazen6Ja. Quando isso acontece, voc6 recebe (suspense...) um
JAVA
5 2I5
stackoverf lowError. A maneira mais comum de isso acontecer 6 criando-se um m6todo recursivo. lJm m6todo recursivo 6.aqrrele que.chama a si mesmo no corpo. Embora isso possa parecer esquisito, 6 rlma t6cnica bastante comum e util para coisas como busca e classificagio de algoritmoi. D6 uma olhadi neste c6digo: void go0 900;
)
{
Como pode voc6 ver, se vocd algum dia cometer o erro de chamar o m6todo go ( ) , o seu proqrama cairi em um buraco negro; gro ( ) chamando go ( ) chamando go ( ) at6 que, nio importa quanta mem6ria voc6 tlnha, voc6 receber6 um
Stackoverf lowError.
erro.
Novamente, apenas
desse
JVM
sabe
quando
esse
momento ocorreri,
ea
JVM
ser6 a fonte
ejamos agora
as
algocomo:
ou por um desenvolvedor de
ApI.
Por exemplo, muitas classes na APIJava tm m6todos que usam argumentos string, convertendo essas strings em primitivos num6ricos. Um bom exemplo dessas classes sio as chamidas "classes wrapper" que estudamos no Capitio 3.
H6 muito tempo, algum prog{amador escreveu a classe j ava . lang . rnteger e criou m6todos como parsefnt valueof ( ) ' Esse programador decidiu sabiamente que,-se um desses m6todos recebesse uma string que nlo pudesse ser convenida em um nrimero, o m6todo deveria langar uma NumberFormatException. O16'A9o
se
parecercom o seguinte: {
int parselnt(String s) throws NunlcerFormatException boolean parseSuccess = false; int result = 0; / / faz um parsing complicado if ( tparseSuccess) / / se o parsing tiver falhado
throw new NunlcerFormatException ( ) ;
return resul-t;
]
Outros exemplos de exceg6es program6ticas incluem um AssertionError (ok, nio se trata de uma excegio, mas erro E langado Prograrnaticanente), elangaruma 11legalAr$unentException. Naverdad., o nosso nritico
esse
desenvolvedordaAPlpoderiaterusadolllegalArgumentException paraoseum6todoparselntO.Mas ocorrequeNumberFormatException estendelllegalArgumentException e6umpoucomaisprecisa,de forma que, neste caso,.usar NwnlcerFormatException acomoda a nogio que Jiscutimos arrt.iior-.rrr.r L q"" '
quandovod temumahierarquia
de exceg6es, deve usar a excegio mais precisa
qui puder.
"
E claro que, como discutimos anteriormente, voc6tamb6m pode criar as suaspr6prias exceg6es especiais, personalizadas, e lang6-las sempre que quiser. Essas exceg6es personalizadas tamb6m recaem n"."t.gori" dr "e*ceE6is langaias
Programaticarnente'.
Descrigio
Normalmente
Langada
(Capitulo 3, "Atribuig6es")
Langada ao se tentar acessar um array com um valor de indice invilido (ou negativo ou maior do que a extensio do array),
Pela
JVM
21
Langada ao se tentar converter uma vari6vel de refer6ncia em um tipo que nio passa no teste E-UM.
LanQada quando um m6todo recebe r.r* irg,r-..rto formatado de forma
Pela
JVM
Programaticamente
Programaticamente
PelaJVM
nuI1.
Langada quando um m6todo que converte uma String em um nimero recebe uma String que nio consegue converter. Langada quando o teste booleano de
Programaticamente
Programaticamente
ExceptionlnlnitializerError
(Capitulo 3, "Atribuig6es") StackOver{lowError @ste Capitulo)
Normalment e Tangada quando um m6todo faz recurs6es profundas demais (Cada chamada 6 adicionada i pilha).
Pela
JVM
Langadaquando aJVM nio consegue encontrar PelaJVM uma classe de que precisa, por causa de um erro de linha de comando, uma questao relerente ao classpath ou um arquivo . class que esteja faltando.
un
nio poderievitilas
as
ll Y)
com elas:
JAVA
217
System.out.print("ff
wrong");
]
we
Adicionadas ) linguagem Java n? verseo 1.4, as assertivas permitireo que voc6 tesre suas suposig6es duranre o e.xceg6es.quesestpaenanvlcorrerdo,umavezqueoprog?amativersaidoda'faseiedlsettrolrri-.rrtoefortoialmente' distribuido.
desenvolvrmento, sem o desgaste (tanto de seu tempo quanto de sobrecarga no programa) de escriver manipuladores para
A p1{r-do exame 31G035 (versig 1.4 do exame dgProgramadorJava Certificado pela Sun), e continuando com o exame at ull 31G055 fava5), ser6 esperado que v.oc6 conhega Js aspectoi bisicos de .o-o (emJava) furrcioo"rrr,", ^r.nivas incluindo como ativi-las, usl-lxe naus6-las.
qryupula{oresdeexcegiodetempodeexecugiooutestesif/else-quandotiverconiluidooiesenvoL'i*.nto.boi6*,'
deixar todos esses recursos inseridos trar6, no minimo, um impacto no desempenho. E ai que as asseftiv.. ajudar. Observe o c6digo a seguir:
..*o
) nunca ser6
ver irstrug6espint,
*r"*
p"r"
if
/
(num >=
0)
/ faz al-go ) el-se { / / nt:m deve ser < // Nunca chegaremos a este cddigol System.out.println(..yikes! num is a negative numberl " + num);
O
]
J6 que voc6
esti tio. certo de sua suposigio, nio guer perder tempo (ou trazer um impacto ao desempenho do programa) escrevendoumc6digodemanipulagiodeexceg6es.Enotempodeexecugio,nSodisejarestesif/Lrse insirid6spoique se rvalnmte chegar i.condigio el sFr_isso significari que sua l6gica anterior (o que quer que estivesse sendo e*.c.rt"do^*tes
desse
As assertivas permitem que voc6 teste suas suposig6es durante o desenvolvimento, por6m, seu c6digo - efetivamente des@arece quando o programa 6 distribuido, nio deixando nenhum c6digo de depuragio ou que causl sobrecarga a ser identificado e removido. Reescreveremos methodA ( ) para validar se-o argomento nio foi negativo:
private void methodA(int num) { assert (num>=O) ; / / lanqa um AssertionError // se este teste n6o for verdadeiro rrc6I\Trrm /nrrn , + xr;
]
As assertivas
escnto assrm:
nio s6 permitem que seu c6digo permanega mais limpo e menor, mas, como elas ficam inativas, a menos que seram especilicamente "postas em agio" (ativadas), o c6digo ser6 executado como se tivesse sido
x),
//
testamos
isto;
]
As assertivas funcionam de maneira bem simples, Voc6 sempre assumiri qu e algo 6. uerdadeiro. Se realmente for, nio haveri Problemas. O c6digo continuar6 a ser exeiutado. Mas, se sua assertirrlr r. irortr", errada (false), eniio, seri langado um erro (que vocA nunca, jamais deve manipular!) imediatamente,'de modo que voc6 possa corrigir a falha na l6gica que levou ao problema.
AssertionError
Existem duas vers6es das assertivas: simples e muito simples, como podemos ver abaixo:
Muito simples
private void doStuff ( ) { assert (y > x): tty ig o + Y \r s x ig " +:t; /,/ mais c6digo assumindo-se que y seja maior do gue x
)
A diferenga entre elas 6 que a versXo simples adiciona uma segunda exPressao, seParada da primeira (a expressio algumas informag5es a mais ao ra$rearnento da pilha. As duas vers6es booleana) por dois pontor, q,r. ".r.rienta la.rg"mrr*assertionError imediatamenti, mas averslo simples lheforneceri.umpouco mais de aiudana depuraglo, enquanto a verslo muito simples apenas informar6 que sua suposigio 6 fdsa.
AOTRABAI}IO
Norwalmente, as assertiaas sdo atiuadas quando an @licatiuo uttl sendo testado e depurado, porin, sd.o duatiuadas quando ele i distribuido. Elas ainda estardo no cridigo, enbora s/an ignoradas pek JI/M, portanto, se uocl tiuer am aplicatiuo distibuido qae cLnece a a?resentar um cornportamento tnadequado, senpre poderui optar por atiuar as assertiuas no cartpo para testes adicionais.
AssertionError.
A segundaexpressio,
um rialor. Lembre:
naversio simples de umainstrugio assert, pode ser qualquercoisa.que resulte em expressio 6 usada para gerar uma mensagem com Strings' a qual ser6 exibida no rasrreamento dapilhaplra he fornecer mais algumas-informag6es de depuraglo. Ela funciona de maneira semelhante a
usada somente
a segunda
System.out.printl-n(
uma representagio com
Strings.
pa ra anrbar as panes de uma instruglo assert. Lemb_re-se, a exPression2 6"usada apenas com a instrugXo assert sirnples, em que a segunda expresseo existe somente para lhe dar mais algumas informag6es para a depuragio:
/ as
segwj-ntes
/.. -\^ -th\
.
1\. J/
assert true,'
^^^^rr :ccarl-^^^e! oD-erL\^
/.. lv
/-.
--
1\
. .
. .
== 1 \
--1\ f/
^^^^e! a>-s!Lt^
assert (x)
assert
ac<arl-
0;
lv == 1 'l
.
nenhrrma del
as retorna
um val-or
assert(x == 1) assert(x == 1)
:
:
noReturn { ) ;
ValidAssert va;
JAVA
2'I9
oBSERVAe6rspaneoEl<eME
Se uoc6 se dtparar cam
a
palawa "expressio"
exprusio booleana) ou i rcgunda (o ualor a ser exihido n0 rastreamentl da pilhQ, entdo, ir$re prenna exprusio, o teste boo/eano. Por exemp/0, se /he pergmtanzos o rcguinte,
n esti
se
refeindo i
se
pineira
express1o (a
quiuti
,tj'triuao i prineira
ndo apenas
ambooleano.
Ativando assertiyas
essas asseftivas
Sevoc6quiserusarassertivas,teri.queconsiderarprimeiro comocompilarcomelasemseuc6digoecomoser|aexecupdocom ativadas. As duas situag6es.requerem aversio 1.4 ou iuperior e isso nos conduiao primeiro problema:
como o c6digo seri compilado com asserdvas.
ldentificador x Palavra-Chave
Antes da versio L.4, vocd poderia muito bem ter escrito um c6digo como
esse:
assert
Nio
assert
rt
"assert"
AOTRABALHO
SeporalgummotiuoaociestiuerusandoumconpikdorJaua/.4,eettiuerutantloassert comoumapa/aara-chaue(enoutraspa/atras, estiuer realmente tenlando nnfrrnar algo en seu aidigo), entdo, teni que atiuar explicitaaente o recofihecimento de assertiuas no ienpo de
rorpi/agio, como descrito abaixo:
assin: 'bonpila a
ti
classe
uersio
unapalawa-chaue".
Compilando um C6digo Atento is Asertivas O compiladorJava 5 usari a palavra-chave assert por padrio. A nio ser que voc6 o instrua do conrrd.rio, o compilador rra gerar uma mensagem de erro se encontrar a palavra assert sendo usada como identificador. Entretanto, rroc? pode
a ele um .giligo aittlSg para compilar, e que ele deve fingir que 6 um compilador^antigo! (Mais sobre comandos do compilador no C"ptt"lg 10) pig?rnos que voc p_ricise fazer um ieparo ripido em^um c6digo" antigo da versio 1.3 que use assert como um identificador. Voc6 pode digitar na linha
deio**iot
usada como identificador, mas o c6digo iri compilar e executar. Suponha que voc6 diga ao compilador que o seu c6digo 6 da versio 1.4 ou posterior, por exemp"lo:
javac -source 1.3 CodiqoAnti_go. java O compilador emitiri avisos quando descobrir a palavra assert
assert
identificador.
quiser dizer ao compilador para usar regrasJava 5, voc6 pode fazer uma das trAs seguintes coisas: omitir a opgio
source, que 6 o padrio, ou adicionar uma das duas seguites op96es de source: -source 1.5 ou -source 5. (Vi,rcomodclaraadistinglodaSunentre 1.5e. 5?)
como identificador no seu c6digo, vocA PRECISA Se quiser usar A Tabela 5-3 resume a forma como o compilador java5 reagir|a 1.
i.
assert
assert
palavra-chave. Tobelo 5-3 Usondo Jovo 5 poro Compilor C6digo que use Assert como ldenti{icodor ou como Polovro-Chove
UnhadeComando
Se assert
Se assert
A compilagio
javac -source 1. 5 TestAsserts. java AcompilagXofalha. javac -source 5 TestAsserts.java javac TestAsserts . java
A compilagio falha.
A compilaglo falha.
com
java -ea
ou
com. geeksanonymous.
TestClass
JVM para
java -da
ou
com. geeksanonymous.
TestClass
*o
os switches de desativag5" q"+ parccer desnecess6rio. De fato, o dor switches, da maneira que mostr-amos no exemplo anterior, lhe fornecer6 simplesmente o comPortamnto , padrlo (em ouras palavras, vod obteri o mesmo rgsultado independente do uso dos switches & desativagio). Por6m, -cle modo que- elas figuem ati.vadas para.algumas vocp tamb6m pode ativar e desativar as assertivas seletivamente, classes e/ou p"aot.r e desativadas para outros, enquanto um programa especifico estiver sendo executado.
I I I
Sem argumentos (como nos exemplos anteriores) Ativa ou desativa assertivas em todas as classes, exceto Para as classes do sistema.
pacote Ativa ou desativa assertivas no pacote especificado e em qualquer Pacote abaixo dele na mesma hierarquia de diret6rio (veremos mais detalhes sobre isso em breve).
Com o nome de um Com o nome de uma classe Ativa ou desativa
assertivas na classe especificada.
Voc6 pode combinar switches para, digamos, desativar assertivas em somente uma classe, por6m, mantendo-as ativadas para todas as outras classes, como descrito abaixot
java -ea
A linha
de comando anterior informa ) JVM para ativar assertivas no Ambito geral, por6m, desativando-as na classe com. geeksanonymous . Foo. Voc pode ter a mesma seletividade para um pacote como vemos a seguir:
I ^--^ lava t- - ^. -ea -od:com.geeksanonymous. . .
JAVA
221
A linha
ele
nio
O"
ativar asserrivas no imbito geral, por6m desativando-as no pode nio estar familiarizado com o termo ubpacote, ji que era muito usado antes da exist6ncia das assertivas, O nbpacote pode ser qualquer pacote de um subdiretorio mencionado. Por exemplo, observe a 6wore de diret6rio abaixo,
os yus^
i JVM para
tubpac.oteslVoc6
:::*
apalrcan
I
i nr
.)rmous
_Foo
_twelvest.eps
_StepOne
_StepTvo
Essa
geeksanonymous
twelvesteps
e tr6s c]asses:
com. geeksanonymous com. geeksanonlzmous
. .
Foo
twelvesteps. Stepone
subpacote de com.
geeksanionymous
com. geeksanonymous.
os pacotes acima dele (nesse
6 o pacote twelvesteps. Lembre que emJava, 6tratado como umpacote completamente distintosem relacionamento com exemplo, o pacote com. geeksanonl.mous), exceto por compartilharem alguns diret6rios.
twelvesteps
de switches de
5-4
O que significa
Ativa assertivas
java -da
j ava -disableassertions
Desativa assenivas (o comportamento padrlo da versio 1.5)
java -ea:com.foo.Bar
com.foo e
Ativa assenivas no Ambito geral, por6m desativando,as Ativa assertivas no Ambito geral, por6m desativando-as
todot os sets subpacotes
pacote
comrfoo
em
catch etentarumarecuperaglo.Quantolvalidade,noentanto,AssertionError
fhrowal>1e,
6umasubclassede
o que significa quepofuser capturada. Por6m, nio o faga! Se voc6 quiser tentar alguma recuperagio, faga-a com uma exceglo. Para &sencoraji-lo de tentar substituir uma assertiva por uma excegio, o erro nlo concede acesso ao objeto que o gerou. Tudo que voc6 vai conseguir ser6 uma mensagem de
AssertionError String.
Entio, quem decide o gue 6 ou nio @ropiado? A Sun. Tanto o exame quanto esta segio, usam a documentaEi.o sobre assertivas "oficial" da Sun para deterrninar o uso apropriado e nio-apropriado.
"apropriado", ndo a confunda cont "u,l/ido". Apmpiado :empre se refere d maneira cono algo deue oa com as pniticas ofcialnente adotadas pela Sun. Se u\cA enc\ntrar a palaura pa/at'ra "cyrreto" n0 cyntex,tg das assertiaas, c0n0 en, 'A tinba 3 apretenta un uto cunetr para aJ assertiuas", tambim deue presamir qae essa comopodeiam ser zudas dc maneira adlida. uni v refeindo a como as assertiaas deaem ser xsadas em aeqde
exame, se uocd se fuparar com
d.e a
pakna
do-nian*no
Umm6todopublic podeserchamadoapartirdeumc6digoquevoc6niotenhacontrole(ouquejamaistenhavisto).
J6queosm6todospuniic fazempartedeiuainterfaceexpostaloambienteexterno,6precisogarantirquenenhuma
?ertrigio
seja imposta pelo pr6prio m6todo. Por6m, como.nio 9e pgde as-segurar que-as assertivas sejam "rgumentos " e*I*tadas (normal-.ote .sao deiativadas em um aplicativo distribuido), a imposigio nio ocorrer6 se elas nio ,.dmlrrr. forem ativadas. Voc6 nXo ir6 querer um c6digo de acesso priblico que s6 funcio ne condicionalmente, dependendo das
assertivas estarem ou
Se
nio ativadas.
publ ic,
eo
fomecido antes dele 6 o modificador de acesso. Portango, impgnha E claro q.te yod pode compilarum c6digo de assertivas com
"^ irnaaZ"napropnadzdea{gumentospublic,mas,noorame(enavidareal)6precisosaberqueniadewfaz&lo. Nio use asseltiyas para validar argumentos de linha de comando
publ ic'1 5" ,r, prbgr* a preitsar i"
para forgar sua utilizaglo.
Na verdade,
esse 6 apenas
um caso especial da regra: "Nio use asseftivas para validar argumentos de um m6todo de linha de comando, voc6 poderi ,tt"t o tttecattismo de exceg6es
"tgu*rttios
Nio use assertiv.ilr, mesnro em m6todos Public, para procurar instrug6es c.rse que sabe gue nunca ocorrereo Isso pode incluir blocos de c6digo que provavelmente nunca serio alcangados, como o bloco def ault de uma instrugio switch que poderia ser a descrita abaixo: swit.ch (x) { case 2: Y = 3; case 3: Y = ]-7; case 4| y = 27; defautt: assert false; /,/ N5o deveriamos nunca chegar at6 aquil
]
Se
voc6 presumir que um bloco de c6digo especifico nio ser6 alcangado, como no exemplo anterior, no qual assume que
temqueserigualiZ,lou4;poder6usiraisert falseparafazercomqueumAssert.ionError sejalangado imediatamenie se em algum momento isso chegar a acontecer. Portanto, no exemplo de swi tch, nio estamos executando um teste booleano - ji iseguramos que nunca chegaremos 16, de modo que simplesmente atingiresse ponto seri uma
falha autom6tica em sua assertiva/suposigio.
JAVA
223
Nio
O c6digo
muito inadequado:
))
rrra.
A regra 6:
Uma exprufio atserfiua deue deixar o programa no metno estado em que estaua antes da exprusdolPense nisso. Nio h6 garaffia de que as express6es assertivas sejamsempre executadas, ponanto, voc6 nio ir6 querer que seu c6digo se compone dilerentemente caso as assertivas sejam ativadas. As asseftivas nio devem causar nenhum efeito colateral. Se elas forem ativadas, a rinica alteragio na maneira como seu programa ser6 executado 6 que um AssertionError pode ser lanEado se uma das assertivas (ou npmgde) se mostrar falsa.
AOTRABALHO
Usar assertiuas capaTu de causar efeitot colaterais pode leuar a a/guns dos bugs mais enlouquecedoru e dficeis de encontrar ! puando um analista de controle de qualidade esquentado utd ubrau/andoporque 0 sea cddigo ndofunciona, a uelha devupa de "bom, elefunciona na MINHA nAauina" ndo uai adiantar.
VocA tamb6m aprendeu que a instrugio switch 6 usada para substituir virias instrug6es i f -else. A instrugeo swi tch pode avaliar tipos primitivos inteiros que possam ser conveftidos implicitamente em um tipo (esses tipos
slo
int
de execugio, a JVM tentar6 encontrar uma coincid6ncia entre o argumento da instrugio swi tch e o argumento de uma instrugio case correspondente. Se a coincid6ncia for eniontrada, a execugio comegar6 com a.instrugio case correspondente e continuarA apaftir daiat6 que uma instrugio break surja ou que ocorra o final da instru$o swiLch. Se nio houver correspondncia, a instrusio case default ser6 executad4 caso haja uma.
No tempo
VocA conheceu as trs estruturas de loop disponiveis na linguagem Java. Essas estruturas slo os loops f or (incluindo o for bisico e o for aprimorado que foi introduzido emJava 5), while e do. No Ambito geral, o loop for 6 usado quando sabemos quantas vezes ser6 preciso percorrer o loop. O loop whi 1e 6 usado quando nio sabernos quantas vezes precisaremos percorrer o loop, enquanto do 6 empregado quando temos que Percorrer o loop pelo menos uma vez. Nos loops f or e whi1e, a expressio terl que ser true para entrl$ no vez. O principal beneficio do loop f seus valores na definigio do loop.
bloco e ser6 verificada a cada iteragio do loop. O loop do nio verifica a condigio antes de percorrer o loop uma or 6 o recurso de iniciahzar uma ou mais vari6veis e aumentar ou diminuir
As instrug6es break e continue podem ser rotuladas ou nio-rotuladas. Quando nio 6 rotulada, a instrugio forga o programa a interromper o processamenro da estnrtura mais interna de loop e prossegue na linha de c6digo posterior ao loop. O uso de um comando continue nlo-rotulado [ar|,com que o programa interrompa a execugio da iteragio atual do loop mais interno e prossiga com a pr6xima iteragio. Quando uma instruglo break ou continue for rotulada, ela seri executada da mesma maneira, com uma exceglo. A instrugio nio ser6 aplicada ao loop mais interno, emvez disso, ser6 aplicada ao loop com o r6tulo. A instrugio break geralmente 6 mais usada junto com a instrugio switch.
break
Quando houver uma correspond6ncia entre a expressio switch e o valor de case, o c6digo posterior a case a execugio do c6digo, seri preciso introd:uzir a instrugio break.
Voc6 viu como a linguagem Java fornece um mecanismo sofisticado de manipulagio de exceg6es. A manipulagio
de exceg5es permite que vocd isole seu c6digo de corregio de erros em blocos separados, de modo que o c6digo principal nXo fique confuso por causa dele. Outro recurso interessante permite que voc6 manipule erros iemelh"ntes .o* ,r* rtnico bloco de manipulagio de erros, sem a duplicaglo do c6digo. Al6m disso, a manipulagio de erros pode ser transferida para m6todos mais embaixo na pilha de chamadas.
Voc6 aprendeu que a palavra-chave try da linguagem Java 6 usada para especificar uma regiio protegida - um bloco de c6digo ,ro q,r"l os iroblemas podem r.r d.tect"dos. Um manipulador de exceg6es 6 o c6digo executado 9_uando ocorre uma excegio. b manipulador 6 definido com o uso da palavra-chave catch da linguagemJava. Todas as cl{usulas catch devem seguir imediatamente o bloco try relaironado. A linguagem Java tamb6m fornece a palavra-chave f inal1y. Ela 6 usada para definir um bloco de c6digo que sempre ser6 executado, imediatamentg ap6s uma cl6usula catch ser concluida on logo depois do bloco try associado, caso nenhuma excegXo seja langada (ou se houver um bloco try, mas nio um bloco catch). Use blocos f inally para liberar recursos do sistema e executar qualquer limpezarequerida pelo c6digo do bloco try. O bloco f inal Iy nlo 6 obrigat6rio, mas, se
houver,umteiAquevirap6sobloco.atch(Seniohouverumblococatch,oblocofinally
imediatamente depois dobloco
deverivir
try).
try
O objeto
poderio ser
langadas.
As exceg6es de tempo de execugio sio do tipo RuntimeException (ou de uma de suas subclasses). Essas exceg6es sio um caso especial porque nio precisam ser manipuladas ou declaradas e, portanto, sio conhecidas como exceg6es nXo verificadas. Os erlos ilo do tipo j ava . 1ang. Error ou de suas subclasses e, como as exceg6es de tempo de execugio, nio precisam ser manipulados ou declarados. As exceg6es verificadas incluem qualquer tipo de exceglo que nio seja do tipo RuntimeException ou Error. Se seu c6digo nlo manipular uma excegio verificada ou declarar que ela serilangada, ndo serA compilado. Por6m, quanto )s exceg6es nio veificadas ou objetos do tipo Error, nio importa para o compilador se voc6 os declarou ou manipulou, se fez algo com eles ou criou alguma combinagXo de declaragio e manipulagio. Em outras palavras, voc6 pode declar6los e manipuliJos, mas o compilador nlo se imponar6 se fez uma ou outra coisa. No entanto, nio 6 boa priticamanipular um erro, ji que raramente vocO poderi {azer algo para se recuperar dele. As exceg6es podem ser geradas pela JVM ou pelo programador.
na versio 1.4, slo uma nova ferramenta ritil de depuragio. Voc6 aprendeu como por6m, mantendo-as desadvadas quando o aplicativo for distribuido. Se voc6 tiver pode us6Jas em testes, ativando-as, um c6digo Java mais antigo, o qual use a palavra assert como identificador, nio poderi usar assertivas e teri que recompilar esse c6digo usando o flag padrio -source 1.3. Lembre-se de que a panir deJava 5, as assertivas sio compiladas como palavras-chave por padrio, mas devem ser habilitadas explicitamente em tempo de execugio.
As assenivas, adicionadas
i linguagem
Voc aprendeu que as instrug6es assert sempre incluem uma expressXo booleana e que, se a expressXo for true, o c6digo prosseguir6 com a execugio, mas se ela for f a1se, um AssertionError ser6 langado. Se voc6 usar a instruglo assert de duas express6es, a segunda expressio serl avaliada, convenida para uma representagio em String e inserida no rastreamento da pilha para fornecer mais algumas informag6es de depuragio. Para concluir, voc6 viu por que as assertivas nio devem ser usadas para impor o uso de argumentos aos m6todos priblicos, e por que as express6es assert nio devem apresentar efeitos colaterais!
',/
Exercicios ripidos
Aqui estio algtrns dos ponroschave
de cada
objetivo para certificagio deste capinrlo. VocA pode percorrA-los virias vezes,
se
Escrever o c6digo usando instrug6es if e switch (Obi. 2.l) E A instrugXo i f deve ter todas as express6es enfeixadas por pelo menos um par de parOnteses. O O rinico argumento vAlido para uma instrugio i f 6 um valor booleano, em outras palavras,
tenhacomo resultado umvalor ou umavariivel booleana.
Cuidadocomatribuig6esbooleanas(:)quepodemserconfundidascomtestesdeigualdadebooleanos
(==):
boolean
x = false; if (x = true) { } / /
uma
atribuiqdo, entdo x
sempre ser6
true!
fl
if
5 225
As instrug6es
escreven
switch
char.
VocA
nio pode
E E
O argumento
Se a
de case deve ser umavariivel literal ou f ina1, ou uma expressio constante, incluindo um nio pode ter uma instrugio case que inclua uma variivel que nio seja final ou um intervalo de valores.
enurn" Voc6
condigio de uma instrugio switch coincidir com o valor de uma instrugio case, todo o c6digo da instrugio swi tch que estiver ap6s a instrugio cas e coincidente, ser6 executado at6 que uma instrugio break ou o final da instrugio switch seja alcangado. Em outras palavras, a instrugio case coincidente ser6 apenas o ponto de entrada para o bloco case, por6m, a menos que haja uma instrugio break, a instrugio case coincidente nio ser6 o rinico
c6digo do bloco
case
a ser
execurado.
D Apalavra-chavedefault deveserusadaemumainstrugioswitch
nenhum dos valores das instrug6es
sevoc6quiserexecutarumc6digoquando
tr Oblocodefault podeserinseridoemqualquerlocaldoblocoswitch,portanro,senenhumainstrugiocase aPresentar correspondAncia, o bloco de f aul t ser6 executado, e se ele nlo tiver uma instrugio break, continuard a
ser executado (passagem completa) at6 o
final da instrugio
switch
break
seja
encontra&.
E fl E B
D D E
UmainstrugXofor b6sicaposzuitr6spartes:adeclaragioe/ouniciahzaglo,aavaliagiobooleanaeaexpressi.ode
itnado.
Se uma variivel for incrementada ou avaliada dentro de um loop f dentro da declaragXo do loop f or.
or
(e
nio
for
nio poder6
us
ser acessada
fora
Voc0 pode inicializar mais de uma variivel na primeira parte da declaragio do loop ser separada por uma virgula.
for
b6sico; cada
inicializaSo de
or aprimorada (uma novidade doJava 5) tem duas panes, parasefazerloop atrav6s de arrays ou conjuntos.
declaragio
ea
for aprimorado, a expressio 6 o array ou conjunto atrav6s do qual voc6 dese jafazer oloop. Com um f or aprimorado, a declaraglo 6 avari|vel do bloco, cujo tipo 6 compativel com os elementos
affay ov conjunto, e essa variivel cont6rn o valor do elemento para aiteraglo em questio.
do
tr tr
Voc6 nXo pode usar um nfmero (antiga estrutura de linguagens do estilo C) ou outro item que nXo resulte em um valor booleano como a condiglo de uma instrugio i f ou estrutura de loop. Nio pode, por exemplo, escrever: if (x) , a menos que x seja uma vari6vel bool-eana.
O loop
do-while
se a
atendida.
Usando break e continue (Objetivo 2.2) E Uma instrugio break niorotvladafaricom que a interagio atual &
ea
E E
Uma instrugio continue nXo-rotulada fari com que a iteragio atual do loop mais interno condigio desse loop seja verificada, se ela for atendida, o loop ser6 executado novamente.
Se a
interrompida
ea
instruglo
break
ou
continue
far6,
E E B
nXo verificada.
que estendem
RuntimeException.
As exceg6es verificadas esio sujeitas I regra de manipulagio ou declaragio; qudquer m6todo que puder langar uma excegio verificada (incluindo os m6todos que chamem outros m6todos c p^zes de realizar essa tarefa) deve
throws ou manipul6-la com um bloco trylcatch apropriado. E Os subtipos de Error ou RuntimeException nio sio verificados, portanto, o compilador nio imp6e
declari-lausando a palavra-chave
regra de manipulagio ou declaragio. Voc6 pode manipuliJos e tamb|m declar6-los, mas o comPilador imponari se uma ou outra coisa ocorreu.
a se
nio
E tr
Se
try
ina]Iy, ele sempre ser6 chamado, independente de uma excegio do bloco correspondente ser ou nio langada e de uma excegio langada ser ou nio capturada.
i
regra do bloco f
Isso
inally ser sempre chamado seri quando a JVM for encerrado. poder6 acontecer se o c6digo do bloco try ou catch chamar system. exit ( ) . D 56 porque f inally seri chamado nlo significa que seri concluido. O c6digo do bloco f inally pr6prio langar uma excegio ou emitir um System. exit ( )
A rinica excegio
.
pode ele
As exceg6es nio capturadas serXo propagadas para baixo na pilha de chamadas , a partir do m6todo em que a excegio foi langada e terminando no primeiro m6todo que tiver um bloco catch correspondente a esse tipo de excegio ou com o encerramento da JVM (que ocorreri se a excegio chegar a main ( ) e esse m6todo passar a exceglo declarando-a).
Voc6 pode criar suas pr6prias exceg6es, geralmente estendendo Exception ou um de seus subtipos. Ela seri considerada uma excegio verificada e o compilador fiorgarS. a aplicagio da regra de manipulagio ou declaragio a essa excegio.
tr E
Todos os blocos catch devem ser ordenados do mais especifico ao mais geral. Se voc6 tiver uma cliusula catch tanto para lOException quanto para Exception, ter6 que inserir o bloco catch de TOException primeiro em seu c6digo. Do contr6rio, a excegio roException seria capturada pelo bloco catch (nxception e), porque um argumento catch pode capturar a excegio especificada ou qualquer um de seus subtipos! O compilador o impedir6 de definir cl6usulas catch que nunca poderio ser alcangadas. Algumas exceg6es slo criadas pelos programadores, outras pela JVM.
fl E E E E fl E
D
como uma palavra-chave (na versio 1.4) ou um identificador, mas nio como ambos. Para asserL como um identificador (por exemplo, o nome de um m6todo), use o flagdelinhadecomando -source 1. 3 em javac.
assert
As assertivas sio desativadas no tempo de execuglo por padrio. Para ativi-las, use o flag de linha de comando
-ea
Se
ou
-enabl-eassertions.
-da ou -disableassertions.
no Ambito geral. E possivel combinar switches de ativagio e desativagio para ter algumas classes e/ou pacotes, mas nXo em outros. Voc6 pode ativar ou desativar assertivas por
classe, usando a sintaxe a seguir:
voc6 ativar ou desativar assertivas usando o flag sem nenhum argumento, estar6 ativando ou desativando-as as assertivas ativadas em
VocA pode ativar ou desativar assertivas por pacote, e qualquer pacote que especificar tamb6m incluir6 todos os subpacotes (pacotes abaixo na hierarquia do diret6rio).
tr Nlo use assertivas paravalidar argumentos de m6todos priblicos. tr Nio use express6es asserrivas que causem efeitos colaterais. A execugio das assertivas nio 6 sempre
portanto, nlo seri bom rer um compoftamento que
garantida,
fl
Use assertivas * mesmo em m6todos public- para garantir que um bloco de c6digo especifico nunca seja alcangado. VocA pode usar assert false; para um c6digo que nunca deve ser alcangado de modo que um erro de assertiva seja langado imediatamente se a instrugio assert for executada.
Teste individual
l. Dado
o seguinte c6digo:
JAVAS 227
T+=X;
r+=4*x;
) r += 5 * v. r.
roi. rrrn
public static void main(String [] args) { OrtegorumFunction o = new OrtegforumFunction( ) ; System.out.println( "OF(L1) is : .. + o.computeDiscontinuous
)
(11) ) ;
]
Qual6 o resultado?
A. oF(11) is: 45 B. oF(11_) is: 56 c oF(11-) is: 89 D. oF(11) is: LL1" E. Acompilagofalha.
E ir
E Iangada uma excegio no rempo de execugio.
2. Dados dois arquivos: 1. class One { 2. public static void main(SLrinq[] args) 3. int assert = 0; 4. )
ql
A\
javac -source 1.3 javac -source 1.4 javac -source 1.3 javac -source 1.4 ,d
B.
corretas)
Apenas uma compilaeeo teri sucesso. Exatamente duas compilag6es tereo 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 ) ;
]
/
]
QualopgXo,inseridaindependentementeem
(Marque todas
as
// insira o c6digo
aqui,iricompilareproduzirasaidab?
corretas)
doFileStuff O { return "b"; } doFileStuff O throws IOException { return "b"; } doFileStuff(int x) throws loException { return "b"; } doFileStuff O throws FileNotFoundException { return "b"; } doFileStuff O throws NunberFormatException { return "b"; i doFileStuff ( ) Lhrows NumberFormatException, FileNotFoundException { return "b"; }
{
Tnhrrl-
s += "t ";
]
// Iinha
finally
)
))
E
as
corretas)
JAVA
5 229
A. A linha
C. A linha
6 6 executada exatamente
vezes.
vez.
vezes.
E. O bloco
G. Ambas
finally
F. O bloco f ina11y
as chamadas
6 executado exatamente
2vezes.
produzem
as mesmas exce96es.
5. Dado: 1. cl-ass Crivitch { 2. public static void main(String [] args) 3. int x = 0; 4. // insira o c6digo aqui 5. do { } while (x++ < y; t 6. System.out.println(x);
t1
8.
)
a s atd^ 12?
,{"inty=x; B.inty=10; CintY=It; D.inty=12; E. int Y = 13; E Nenhuma das anteriores permitiri
que
System. out
println
s);
void
s2 ( )
s3O; s3O;
)
void
) )
s3
) throws Exception {
Qual6 o resultado?
A"-
7. Dado:
}
as
Qual opgio poderia ser usada para se criar um bloco catch apropriado? (&Iarque todas
corretas)
8. Dado: 1. class Ping extends Utils { 2. public static void main(String [] argrs) Util_s u = new Ping0; 3. 4. System.out.print(u.getlnt(args[0]));
int setrnt(strins ars) t ;. return Integer.parselnt (arg) ; 7. B, } 9. ) 10. class Utils { 11. int getlnt(String x) throws Exception { return 7; t2. j
E
as
) langauma Exception. C2. Declarar que Ping . getlnt ( ) langa uma Except ion. C3. Encapsular a chamada de getrnt ( ) em um bloco try / catch.
C1. Declarar que
main
as
coretas)
B.
C2 sozinha 6 suficiente.
C2 sozinha
6
C
D.
suficiente.
C1 e C2 sio obrigat6rias.
E. Cl
sio obrigat6rias.
JAVA
23I
default:
] System. out
) )
s case PST: s
.
println
s);
-c B. -x
.4"
-cm
D. -cmp E. -cmXp
E
G
a
Acompila$ofalha.
3r t E langada uma excegeo no tempo de execugio.
10. Dado:
class Circus { public static void main(String[] args) intx=9; intY=6' for(int z = 0; z < 6; z++, y--) { if (x > 2) x--i label: if(x>5) { System.out.print(x + " "). --x; continue label-;
)
Y--.
Qual6 o resultado?
A"8
B.87 c876
D. Acompila$ofalha.
E.
exeor$o.
.4. Eapropriadousarassertivasparavalidarargumentosparam6todosmarcadoscompublic.
B. li apropriado
C D
E,
li apropriado
Nna 6
vod alcang um
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
]
as
corretas)
y : x) { int y) t 0; for(y : x) { y=0, z=0; z<x.length; z++l { y = xlzli y=9, int z=0; zcx.length,' z++) { y = xLzJ; 6r for(int z=0; z<x.length; z++) { y = x[z];
3. Dado: 1. class Ring { 2. f inaL stat.ic int x2 = '7 ; 3. final static Integer x4 = 8; 4. public static void main(StringlJ args) Integer xl- = 5; 5. 6. SLring s = "ao,' 7. if (x1 < 9) s += ttSrt 8. switch(x1) t 9. case 5: s += \'c",' 1-0. case x2: s *= t'd"; LIcase x4: s += "e";
LZ. j
L3.
14 ]
)
SysLem.out.println(s);
1s.
Qual6 o resultado?
E. A compila$o
JAVA5 233
F. A compilagio
virias linhas.
14. Dado:
class Hnu { static String s = \-" i public static void main(String[] args) try {
Exception( ) ; ) catch (Exception e) {
ne\^/
throw
try { try { throw new Exception0; ] catch (Exception ex) { s += "ic "; throw nehr Exception0; ) catch (Exception x) { s +- *mc \r } fina11y { s += "mf "; } ) fina11y { s += "of "; } system. out.println (s ) ;
Qual6 o renrltado?
,{.
-ic of
B. -mf of C -mc mf
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?
null null
6. Quais das seguintes opg6es normalmente seo langadas pelo desenvolvedor da API ou do aplicativo, em vez de serem langadas pelaJVM? (Marque todas :$ corretirs) A. ClassCastException B. rllegalstateException
|
C. NurilcerFormatExcept ion
D. r1 I egalArgumentException E. ExceptionlnlnitializerError
Respostas
1
2.
Eest6correta.Ainstrugio
resultariaem OF ( 11
it |invllda.Oif-else-else
111.
base no exposto acima.
(e
devesermodificadoparaif-else
if-else,oque
6:
(Objetivo 2.1)
- 3 , e a dasse
o flag
L.4.
A, C, D e E estlo incorretas com base no exposto acima. (Objetivo 2.3)
3.
as
ou
B est6 incorreta porque o m6todo subscritor est6 tentando langar uma excegio mais ampla.
C est6 incorreta. Este m6todo nio subscreve , portanto, a suda 6 A. (Objetivo 2.a)
4.
A, F e H estio corretas. lJma vez que ambas as chamadas langm o<ceg6es, a linha 6 nunca 6 atingida. Uma vez que ambas as exceg6esocorreramdentrodeumbloco try, o bloco fi-na11y sempre ser6exmrtado. Aprimeiracharnadalangauma
ArraylndexOutOfBoundsException,easegundalangaumaarithmeticException
dedividirporzero.
B, C, D, E e G e$eo incorretas com base no exposto acima. (Objetivo2.5)
porcausadatentativa
println
6entloincrementada(depoisdoteste
) roda. alangaparaslO,emaisnenhumc6digodes2Oseri
base
6. Besticorreta.Depoisques3Olangaaexce$opa$s2$,s2O
A, C, D, E, F, G e FI estio incorretas com
base
7,
IllegalArgumentException
CeDestiocorretas. Integer.parselntpodelangarumaN'umlcerFormaLException,e
6asuasuperclasse(ouseja,umaexcegi.omaisampla).
classe de
rrrumberFormatException. (Objetivo
2.5)
polim6rfica, de forma que o compilador implementada, a excegio ter6 sido declara& & forma suficiente, e se C3 for implem entada, a excegio terisido manipulada de forma suficiente. C2 nlo 6 necessiria em nenhum dos casos.
de que ahrtha 4 est6fazendo uma chamada
sabe que uma exceglo poder6 ser langada. Se C 1 for
9.
E est6 correta. E v6lido usar enums em um switch, e , nesse caso, aplica-se a l6gica de passagem completa normal dos swi tch; ou seja uma vez encontrada uma correspond0ncia, significa que o swi tch foi iniciado, e que todos os
235
nio
A, B, C, D
10.
Dest6correta.Umcontinue rotuladofuncionaapenasparaloops.Nestecaso,emboraor6nrlosejavilido, nio 6 um r6tulo em uma instrugio loop, 6 um r6tulo em uma insrrugio i f .
A, B, C e E estio incorretas com base no exposto acima . (Objetivo2.2)
corretas.
label
lL C, D e E sio instrug6es
A
est6
private.
vod nio
o
aprimorado.
DeFsioexemplosdoloop
for
bisico.
B esti incorreta porque os selrs operandos estXo trocados. C esti incorreta porque o for aprimorado deve declarar o seu primeiro operando. E usa sintaxe incorreta para declarar duas variiveis em uma instru$o f or. (Objetivo 2.2)
tl. F esti correta. Uma instrugio switch exige qge as suas express6es
de caso sejam consrantes, e variiveis wrapper (mesmo as que forem final static) nio sio consideradas como constantes. O resto do c6digo esti correto.
catch
em aninhar blocos trylcatctr- Como de costume, quando uma excegio 6 executado, e depois o c6digo do bloco f ina11y 6 execuiado.
nul1 nul1.
A e E sio
langadas
pelaJVM. (Objetivo
2.6)
iovo.io
I I
individuol
li,r'
E,/S,
FormotoEdo e Porsing
Este capitulo enfocari os virios t6picos relacionados ) API que foram adicionados na versXo Java 5 do exlge: O J2SE 1em com uma enorme API, e bo" p"ne do r..t trabalho como programado rJavateriaver com o uso dessa API. A equipe do exame decidiu se concentrar nas APIs de E/S, formatagio e paning. Cada um desses t6picos poderia preencher um livro inteiro. Felizmente, voc6 nXo precisar6 se tornar um guru completo de E/S ou de regex para sair-se bem no exame. A intengio da equipe do exame foi incluir apenas os aspectos b6sicos dessas tecnologias e, neste capitulo, iremos ab ordar nais do que voc6 precisa para atender aos objetivos referentes a Strings, E/S, formataglo e parsing do exame.
Tudo que voc6 precisava saber sobre Strings no exame 1.4, continua tendo de saber para o exame SCJP 5... Al6m disso, a Sun incluiu a classe StringBailfurna API, para fornecer recursos de Stringp mais ripidos e nlosincronizados. A classe StringBuilder possui exatamente os mesmos m6todos que a antiga StringBuffer, mas StringBuilder 6 mais ripida porque os
seus
as classes
imutabilidade).
A Classe String
Esta segXo abordar6
a classe -
String,
eo
principal conceito
a se
poderi
ser
modificado
bits que
de caracteres sofisticado e
EmJava, as strings sio ob.ietos. Exatamente como acontece com outros objetos, voca pode criar com apalavra-chave new, como vemos abaixo:
linha de c6digo cria um novo objeto da classe String e atribui a vari6vel de referncia parecem iguais aos outros objetos. Agora, daremos um valor a String:
ele.
At aqui
os objetos
String
s = "abcdef";
Como talvez vocA
jA soubesse, a classe
String possui virios construtores, portanto, podemos usar um atalho mais eficiente:
;
poderi
at6
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:
At6 aqui tudo bem. Os objetos Stringparecem e$ar se comportando exatamente como os outros objetos, portanto, por que toda a confrsio? Inalterabilidade (que diabos 6 inalterabilidade?) ! Uma vez que voc6 tiver atribuido valor a uma String, esse valor nunca poderi ser alterado - ele 6 in alterivel, sticongelado, nio se mover6, acabou-se, esta concluido - tamb6m discutiremos as raz6es posteriormente, nio nos deixe esquecer. A boa nova 6 que embora o oletoStingseja inalterivel, sua uariduel de r@nciando o 6,rpo.rtanto, continuando com nosso exemplo anterior:
JAVA
"acr6scimo ao final da string"? Boapergunta; examinemos o que aconreceu realmente...
239
stuf f " que foi concatenado 6 por si s6 um novo objeto String. Contudo, 'abcdef " (referenciado por s2) e "abcdef more stuf f " (referenciado por s).
literal "more
E se ni.o tMssemos
a
visi,o ou
antes
de
chamarmoss
ainda existiria na mem6ria, mas seria considerada "perdida". Nenhum c6digo de nosso programa teria como referencii-la estaria perdid aparan6s.E bom observar, no entanto, que a String "abcdef" original nio foi alterada (nio pode ser, lembre.se: ela b inalter,hnl; s6 a vari6vel de refer6ncia s foi alterada para referenciar uma String diferente. A F tgara Gt mostra o que acontecer6namem6riaquando voc reatribuirumavariivel de referAncia. A linhatracejada indicaumarefer6ncia o<cluida
Para recapinrlar nosso
primeiro exemplo:
String s = "abcdef"; // cria um novo objeto String, com o val-or "abcdef", / / faz s apontar para ele String s2 = s; / / cria uma seg,unda vari6vel de refer6ncia apontando para // a mesma String s = s.concat(" more stuff"\i // cri.a um novo objeto String, com o valor // "abcdef more stuff", faz s apontar para ele. // (modifica a referOncia de s, da antiga / / String para a nova. ) ( Lembre-se de que / I s2 ainda est6 se referindo d // SLring "abcdef" original).
Examinemos outro exemplo:
Aprimeiralinha6 simples: criaumnovo objeto Stringcom ovalor "Java" e apontax paraele. O queocorredepois? O VM cria um segundo objeto String com o valor "Java Rules ! ", mas sem algo que o referencie!!! O segundo objeto
String
perdido instantaneamente; ningu6m jamais poderi alcang6Jo. A variivel de referOncia x continuar6 referenciando o objeto String original de valor "Java". A Figura G2 most raacriagio deum objeto String sem a atribuigio a uma refencia
6
x. toUpperCase O ;
ele
foi perdido
,e
x ainda relerencia a
Passol: String
Passo3: s = a,concat.
Vari6vel de
Yariivel
de
referncla String
6-1
ji
chamamos v6rios m6todos do objeto String para criar uma nova String alterando i Sting recim<iada uma vaiivel derefer6ncia.
+ x)
VM executar a segunda linha, um novo ob.ieto String ser6 criado com o valor Java Rules!" e x ser6 configurado para referenci6-lo. Mas espere, ainda hi mais: agora o objeto String original, Java", foi perdido e ningu6m o esti referenciando. Portanto, nos dois exemplos criamos /aar objetos String e someite smavariivel de refer6ncia, & modo qug um d9s dois objetos String foi abandonado. Consulte a Figora63 par:r ver uma representaglo gr6fica desa triste est6ria- A linhatracejada indicauma refer6ncia excluida
Examinemos
esse
+ )<);
System.out.println( \x = \ + x);
x = x.tolowerCaseO
,-
// a saida 4: x = Java Rules! / / sem atribuiqdo, cria uma nova String / / sem atribuiqdo, a saida ainda 6: // x = Java Rules / / cria uma nova String, atribuida a x
abandonada
JAVA
24I
Passo
l: Slring
Strinl__\
r------r
q-Y
tl
Yariivel de
refer3ncia String
System.out.println("x = " + x) ;
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, dve conseguir acenar 80 por cento das perguntas sobre objetos String do exame.
Abordaremos mais detalhes desses objetos a seguir, mas nio se engane: em termos d beneficios para seu objetivo, o que i6 discutimos6 de longe aparre mais imponante dacompreenslo de como osobjetos Stringfuncionam emJava. Terminaremos esta segio apresentando um exemplo com o tipode pergunta maldosa sobre objetos String quevocO pode esperar no exame. Nio se apresse e udlizr um papel para pensar (dica: tente manter um controle de quantos objetos e variiveis de refer6ncia existem e quais se referem aqu).
st.concat("fal1 ");
s2.concat (s1) ; s1 += "wi"nter " ;
println?
s1
e
Resposta:.O resuhado desse fragmento de c6digo 6 "spqg_winter spring summer". H6 duas variiveis de refer0ncia, sz.^No toral foram criados oito objetos String comoisti descrito a seguir: "sprhg",."Surnmer" (p.t{{o), tptin8
summer", "fall" (perdido), "springiall" (perdido), "springsummerspring" (perdido), "winter" (perdido)' "springwinter" (nesse ponto 'spring" foi perdido). 56 dois dos oito objetos String nio foram perdidos nesse Processo.
estio
de qualquer linguagem de plogramaglo sofisti cada|faznr vneficiente da mem6ria. Com o crescimento dos .plicatinos, 6 muito iomum que strings literais ocupem grandes espagos da mem6ria, e que geralmente haja muita redgndAncia dentro do universo das strings literais de um programa. Para tornar a linguemJava mais eficiente no
uso da mem6ria,
String alterado. Voc6 pode estar pensando: "Bem, est6 tudo muito bom, mas e se algu6m sobrescrever a funcionalidade da classe String; isso nio poderia causar problemas no pool?". Essa 6 uma das principais raz6es por que a classe String 6 marcada com final. Ningu6m pode sobrescrever os compoftamentos de nenhum dos m6todos do objeto String, Portanto, pode estar certo de que esses objetos em cuja inalterabilidade estl confiando sio, realmente, inalteriveis.
Variivel de
referGncia String
Passo2: x
x. concat
Vari{vel de
referncia String
",Java Rul-es
!
Repare, no Passo 2, que nilo h6 nenhuma referGncia v6lida i String'Java"; esse objeto foi "abandonado", e foi criado um novo objeto.
1 - String s = 'abc";
Nesse caso simples,
'abc"
ser6
j5 que-usamos
no pool) e
o referenciari.
palavra-chave new, a linguagem JavaciarS,umnovo objeto String na mem6ria comum (e nio Al6m disso, a string literal "abco seri inserida no pool.
r I
charAt(
) concat( )
Retornaocaracerlocalizadonoindiceespecificado
JAVA
243
equalslgnorecase(
Determina
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
Esse m6todo retorna o caractere localizado no indice especificado da classe String. Lembre-se de que os indices de String t6m inicio no zero. Por exemplo,
// asaida6'r'
m6todo retorna um objeto String com o valor da string que foi passada para ele
)t
do m6todo
concat
) . Por exemplo,
/ a saida 6 "Atlantic
ocean"
Observe no exemplo anterior, cuja saida foi "Atlantic ocean", que o valor de x i realmente alteradollembre-se de que o operador + : 6 um ope rador de aaibuSdo, poftanto, a linha 2, na verdade, esti criando um novo objeto String, "At1antic ocean",eatribuindo-oavari6velx.Depoisquealinha2forexecutada,astringoriginalquex estavareferenciando, "At I ant i c ". ser6 abandonada.
publicbooleanequalslgnoreCase(Strings)
Essem6todoretornariumvalorboof eano
(true
ou
baseado na coincid6ncia entre o valor da String do argumento e o usado para chamar o m6todo. O m6todo retornari mesmo quando os caracteres dos objetos String que estiverem sendo comparados tiverem caixas diferentes. Por exemplo,
false) true
String x = "Exit"; system.out'print]-n(x.equa1sIgrnoreCase(..EXrT,,));//retorna System.out.println( x.equalslgnoreCase("tixe") ) ; // retorna "false" public int length$ Esse m6todo ret ornara a extensio da String usada para chamar o m6todo. Por exemplo, String x = "01,234567"; Svstem.orrt.nrinfln( x Iencth() l: // reLorna "S"
vJ v evrLr. vg u t yr +r.e+
OBSERVAQ6ES
pene O EXAME
un ndtodo), chamado length. Vocdpode encontrarperguntas n0 exame que tentett asaro mdtodo length ( ) en tlm atEt ou o atributo length em um objeto Sting. Os dois casos causardo envs do compikdor, Por exentpk, Strj-ng x = "test"; System.out.println( x.length l; / / erro de compilaqSo
Os arrals tdm um atribato (e n6o ou
Esse m6todo retornari um objeto String cujo valor seri o da String public String replace(char old, char new) usada para chamar o m6todo, aatalizado de modo que qualquer ocorrncia do tipo char do primeiro argumento seja sobrescrita pelo do segundo. Por exemplo,
244
'x') );
O m6todo
/ a saida 6
"oXoXoXoX"
zubstring) dJobjeto Strilg empiegado na clramada do m6todo. O primeiro argumento representa o local onde a substring .o*.9" (L*itri.io no r"ti. S..clamadas6tiverum argumento, isubstringraornadainiluir6os caracteres.mfq*"1h at6 o fini d. String original. Se a chamada tiver dois argumentos, a substring retornada terminar6 com o caractere localizxlo na en6sima posigi6 dabtring original, em que n 6 repr-esentado pelo segundo argumento. In felizmente, o argumento final nlo teri iniiio tro zero, pon-"ntol se o segwdo argumento for 7, o rihimo caractere da String retornada seri a posi$o 7 da String original, que 6 o indice 6. Examinemos alguns exemplos:
end)
substring
/ como num passe de m6gina, o valor de cada char // 6 o mesmo que o seu indicel // asaida 6 "56789" System.out.prinLln ( x.substring (5) ) ; // asaida6"567' System.out.println( x.substring(5, B) ) ; String x = "0123456789";
/
O primeiro exemplo 6 f6cil: comeEa no indice 5 e retorna o restante da String. . O segundo exemplo deve ser lido da forma a seguir: comega no indice 5 e retorna os caracteres at6 (e incluindo) a oitava posigio (indice 7).
public String
tolnwerCaseQ Esse m6todo retorna um objeto String cujo valor 6 a String usada para chamar o m&odo, por6.-m, com os caracteres que estiverem em letras mairisculas agora convertidos para minusculas. Por exemplo,
String x = tr6 New Moon"; System.out.println( x.t.olowerCase( ) ) ;
/
/ a saida 6 "a
new moon"
public String
toStringQ
Esse
m6todo retorna o valor da String usada para chamar o m6todo. Qu6? Por que
precisariamosdeumm6todoqueparece niofaz-ernada?TodososobjetosemJavadevemterumm6todotoString(
normalmente retornando uma String que de alguma maneira significativa descrwe o objeto em q-uestio. No caso de um objeto String, o que seria mais significativo que seu valor? Para que isso fique mais claro, aqui estS um exemplo:
),
String x = "big surprise"; System.out.println( x. toStrinS ( ) ) ; / / a saida 6 - tente descobrir! public String toUpperCaseS Esse m6todo retornaum objeto Stringcujovalor6 aStringusadapara String x = "A New Moon"; System.out.println( x. toUpperCase O
public String
chamar o m6todo, por6m, com os caracteres que estiverem em letras minfsculas agoraconverddos paramairisculas. Por exemplo,
/ a saida 6 "A
NEW MooN"
Esse m6todo retorna um objeto String cujo valor 6 a String usada para chamar o m6todo, por6m, com qualquer espato em branco precedente ou interno removido. Por exemplo,
trimQ
-
c+'.in^v-\1^.i\\. vLlfrry
^
hi
xn
StringBufier x StringBuilder
A classe StringBuilder foi adicionada emJava 5. Ela tem exatamente a mesma API que a classe StringBuffer, exceto pelo fato de que StringBuilder nio 6 segura em relagio aos threads. Em outras palavras, os seus m6todos nio sio sincronilados. (Filaremos mais sobre a seguranga de threads no Capitulo 9.) A Sun recomenda que voc6 use
JAVA
245
StringBuilder semPre que possivel, porque essa classe roda mais rapidamente (e talvez pule mais alto. tamb6m). Asstm, tirando a sincrolizagio, tudo. que dissermos sobre os m6todos de StringBuildei6 verdadeiro iamb6m Para os m6todos de StringBuffer, e vici-ve-rsa. O exame poder.i usar essas classJs na criagio de aplicativos com threads seguros, e n6s veremos como isso funciona no Capitulo 9.
/ a saida ! $x = abc"
concat ( ) foi
foi gerada, o novo objeto String criado com o m6todo abandonado instantaneamente. Tamb6m vimos exemplos como este:
// a saida 6 .x = abcdef"
Obtivemos um objeto String novo a panir da operagio, mas a desvantagem 6 que a string "abco anterior foi perdida no pool de strings, ocupando, poftanto, espago na mem6ria. Se estiv6siemos usando um objeto StringBuffer emvez de um objeto String, o c6digo ficaria assim:
StringBuffer sb = new StringBuffer("abc"); sb.append("def") .reverse() .insert (3, "---") ; System.out.println( sb ) ; // asaida 6 "fed---cba"
R.p.o
nio criamos nenhum objao adicional.
que, em cada um dos dois enemplos anteriores, houve uma s6 chamada a new, de forma qtre, nos dois Cada exemplo precisou de apenas um objeto String)Gx par-arodar.
*emplos, n6s
oBSERVAQoBS
nr
pene O EXAME: w
nbn a diferenga entre objetos Stringe StringBtlfer. Jd que os objetos StringBtfferpodea oSetos Shing alteradoq ofragnento de cddigo a segair se comportari dfenntenmte de amfragnento de aidigo semelbante qrc
System.out.println( sb ) ;
Nesse caso, a saida
public synchronized StringBuffer append(String s) Comovimos anteriormente, ese m6todo atualizar6 ovalordo objao que o chamou, tendo ou nio o vdor de retorno sido atribuido a uma variivel. O m6todo usari muitos argumentos
diferentes, boohattot, String.Poro<emplo,
char,
furbla,Jkat, int, longe outros, por6m, o mais prov6vel de se encontrar no exame seri um objeto
Strj-ngBuffer sb = new StringBuffer("set "); sb.append("point") ; System.out.println( sb ) ; StringBuffer sb = new StringBuffer("pi = ");
sb.append(3.14159f);
System.out.println( sb ) ;
FormotoE6o e Porsing
Este m6todo retorna um objeto StringBuilder e atualiza o public StringBuilder delete(int start, int end) ialor do objeL StringBuilder'que chamou o m6iodo. Nos dois casos, uma substring 6 removida do objeto ori,ginal. O indice incial da su6string a ser removida 6 definido pelo primeiro argumento (que comega pelo zero), e o indice
final da substring a ser rem"ovida 6 definido pelo segundo argumento (mas este comega pelo um)! Estude o seguinte exemplo com cuidado:
("0L23456789" ) ;
// asaida6"0\236789"
s) Esse m6todo retorna um objeto StringBuilder e atualiza o valor do objeto StringBuilder que chamou o m6todo. Nos dois casos, o objeto String passado para o segundo argumento ser6 inserido no StringBuilder original comegando pelo local de deslocamento representado pelo primeiro_ argumento (o deslocamento tem inicio no zero). Novamente, outros tipos de dados podem ser passados pelo segundo argumento (booleano, char, double, f 1oat, int, long e outros), mas o argumento String provavelmente ser6 o que voc6 mais ver6:
Strlngeuilder sb = new StringBuilder ("0L234567 " ) ; sb. insert (4, "---" ) ; System.out.println( sb ) ; // a saida 6 "01,23---4567"
public synchronized StringBuffer reverse$
Esse m6todo retorna um objeto StringBuffer e atualiza o valor do objeto StringBuffer que chamou o m6todo. Nos dois casos, os caracteres do.objeto StringBuffer sio invertidos, com o primeiro caractere se tornando o riltimo, o segundo se tornando o penriltimo e assim por diante:
man
Esse m6todo retorna o valor do objeto StringBuffer que chamou o m6todo como
oBSERVAQ6TS
pene O EXAME
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:
2.
Use
chanari
o segando ndtodo (a
exhvma esquerda rctomani (cbamaremos ase aa/or dc x). partir da uqaerda). Se hoauer somente dois ndtodos encadlados, o rualtado da
o
3. Se houuer am terceiro mdtldo, o res/tado da seganda chamada de mdtodo seni asado para chamar o terceim mitodo, culo reuhado senl
resultado da expressio, Por exeuplo,
String x = "abc"; String y = x.concat("def"),toUpperCaseO.replace('C','x'l; //m6todo concatenado system.out.println("y= " +y); // o resultado 6 "ABXDEF"
Exaninemos 0 qt/e nczrrerl. O ualorliteral "def "1ki concatenado a "abc", niando um objeto Shinginarnedidio terzporiio (qre bgo seriperdido),comoualor "abcdef ". Omitodo toUpperCase( ) criouumnouoobjetoStringtenponirio(qotlososeniperdido) comoualor 'ABCDEF'1 Omitodoreplace( ) criozamobjetoStringfnalconoaalor"ABxDEF"erelferencioay aele.
arquiuo; a kitura
de
arqilalr
JAYA
cln'eta atandl ar seguinter
5
e
247
cksu ()s
PrifiIYriter.
O hipico referente a E/ S ten un bishirico estranho com a certifcagdo SCJP. Estaua incluido nat uendet do exame at6 remoyido na aersio 1 .4 e depois incluido nlaamefite na uersdo Jaua 5.
a /.2, depo*foi
Felizmente para n6s, os t6picos de E/S incluilos no exameJava 5 se restringe"m aE/S piaciacreres
E/S 6 um t6pico imenso, de forma geral, e as APIsJava que lidam com E/S de uma forma ou de outra sio tamb6m imensas. Uma discussio geral de E/Spoderia incluir t6picos como E/S de arquivos, E,/S de conrrole, E/S de threads, E/S dealto desempenho, E/Sorientado a.6ytes, E,/S orientalo a caracreres, filtragem e wiapping de E/S, serializaglo, e outros.
e
serial
dEi".
Eis um resumo das classes de E/S que voc6 precisari entender para o exame: A {PI diz que a classe File 6 "uma representagio abstrata de nomes de caminho de arquivos e diret6rios". A classe File nlo 6 usada para ler ou escrever dados, propriamente; 6 usada para trabalhar em um nivel mais alto, criar arquivos vazios, procurar por arquivos, apagar arquivos, criar diretorios e trabalhar com caminhos.
I F{:.
FileReader Esta classe 6 usada para ler arquivos de caracteres. Os seus m6todos read ( ) sXo de nivel relativamente baixo, permitindo que voc6 leia caracteres isolados, todo o stream de caracteres ou um nrlmero fixo de caracteres. Os FileReaders normalmente slo mcapuladw (wrapped) por objetos de nivel mais alto, como BufferedReaders, os quais melhoram o desempenho e fornecem meios mais convenientes de se trabalhar com os dados.
r BufferedReader Esta classe 6 usada para tornar classes Reader de nivel mais baixo, como FileReader, mais eficientes e ficeis de rfar. Comparados com FileReaders, BufferedReaders l6em pedagos relativamente grandes de dados retirados do arquiv-o de uma s6 vez, e mantAm esses dados em um buffer. Quando voc0 pede o caracter ou linha seguinte, ele 6 retirado do buffer, o que minimiza o nirmero de vezes que as demoradas operaE6es de leitura de arquivos serlo realizadas. Al6m disso, BufferedReader fornece m6todos mais convenientes, como readline ( ) , que lhe permite obter a pr6xima linha de caracteres de um arquivo.
Esta classe 6 usada para escrever em arquivos de caracteres. Os seus m6todos ( ) lhe permitem escrever caraderes ou Strings em um arquivo. Os File\Triters geralmente sio encapsulados por objetos \Triter di nivel mais alto, tais como Buffered$Triten ou Print'\0riters, que fornecem melhor desempenho e m6todos de alto-nivel mais flelveis para escrever dados.
r FileVriter
write
r BufferedVriter Esta classe 6 us adaparatomar classes de baixo-nivel, como FileIflriters, mais eficiernes e ficeis de usar. Comparados com Filetilflriters, Buffered\0(riters escrevem pedagos relativamente grandes de dados no arquivo de uma s6 vez, minimizando o nimero de vezes que as demoradas operag6es de leitura de arquivos serio realizadas. Al6m disso, a classe BufferedVriter fornece um rn6todo newline ( ) que facilita a criagio autom6tica de separadores de linhas especificos i plataforma.
PrintVriter Esta classe foi melhorada significativamente emJava 5. Devido aos novos m6todos e construtores (por exemplo corstruir um PrintVriter com um File ou String), voc6 poderi perceber que poder6 usar Print\(/riter em lugares onde, anteriormente, precisava que um \Triter fosse encapsrlado com um FilerilTriter e /ou um BufferedlVriter. Novos
m6todoscomo
OBSERVAQ6ESpenaOH(AME
As
fio usadas para /er e etcreuer b1tes, e os Rcadert e lVriters sdo utados para ler e esmuer caratteres. (Jma ueqqae todos S de arquiuot do exane se relacionam a caracterer, caso uoci uqfa nones de c/asses API contendo a palaura "Shvam", por exefirPll DataOutputStream, entdo a questio prouauelmente se refere d nialiqagio, ou a algo qae ndo tem a aer clm o objeto de E/ S
elases de stream
de
os
aipins
E/
propianente dito.
em
public statj-c void main(String [] args) { File file = new File ( "fileWritel. txt,, ) ;
// um arquivo!
propn)nede, File, uoci ndo estti criando um arqaiao"*'"r'q"i"o e$ri ciando @enas um nome de _arquiuo. A.panir.do momento em que voc6 tem um lbjetlFile,existem diversai m'aneiras de se criar um arquivo propriamente dito. Vejamos o que podemos fazer com o objeto File que acabamos de criar:
imnar| irrra in JsYs.rv. *.
;br.il;;;;i;"""h"*"
e rodar
i"di."ia.3.
esse
programa, quando observar o conterido do diret6rio atual, voc6 nio descobriri chamado f ilewritel . txt. Quando cria uma nova instAncia da
class Writerl- { publj-c static void main(String [] args) { / / aviso: possiveis exceg6es Ery { boolean newFlle = false; / / 6 anan:q rrm ntr'iefn File fi-le = new File ("fileWrite1.txt" ); / / procura por um arquivo real System. out.println ( f i1e. exists ( ) ) i / / Lalvez crie um arquivo! newFile = fiIe. creaLeNewPile ( ) ; / / iA aviqr'a? System. out . println (newFile ) ; // olhe novamente system. out.println (file. exists ( ) ) i ] catch(fOException e) { }
v syerrqs srr vvJ v ev
i
Isso produz a saida
false
E.rue
t n:"* t.*b6m
Se
quenew
FileO
exists
nlocriaumarquivoemdisco! Om6todocreaLeNewFileO,essesim,criouumarquivoe
retornou true, indicando que o novo arquivo fora criado, e que antes dele nio havia nenhum. Finalmente, n6s chamamos existsO novamente,edestavezeleretornoutnre,indicandoqueagoraexisteoarquivoemdisco. primeira execugio. Depois, achamadaacreateNewFile ( ) retorna false, umavezqtrc o m6todo nio criou um arquivo desta vez. E, 6 claro, a riltima chamada a exi sts ( ) retorna true.
Aconteceram algumas outras coisas novas nesse c6digo. Primeiramente, repare que tivemos de colocar o nosso c6digo de criaEio de arquivos em um bloco trylcatch. Seriassim para quase todos os c6digos de E/S de arquivos que voc6 escrever. E/S 6 uma daquelas coisas inerentemente arriscadas. Estamos mantendo a simplicidade por enquanto, e ignorando as exceg6es, mas ainda precisamos seguir a regra de tratar-oudeclarar, uma vez que a maioria dos m6todos de E/S declaram exceg6es verificadas. Falaremos mais sobre exceg6es de E/S posteriormente. N6s usamos dguns dos m6todos de File nesse c6digo:
I boolean exists ( ) Estem6todo retorna true se conseguirencontraro arquivo. I bootean creatlilevrFile ( ) Este m6todo cria um novo arquivo caso ele ainda nio exista.
oBSERVAQ6ESpeneOE)(AME
I-znbre-se
de
qw
JAVA
249
newFile = file.createNewFile
System. out
.
();
println (newFile ) ;
i
mais
Voci poderia uer algo como a seguinte linba de aldigo so{nha, o que
difcit
muma coisa:
Syst.em.
));
arquivo semwrapping:
at
import java.io.d; class writer2 { public static void main(String [] args) { charl] in = new char[50]; // para armazenar a ent.rada int size = 0; trY { File file = new File( // aper'as um objeto "fileWrite2.txt") ; FileWriter fw = new FileWriter(fi1e) ; / / cria um arquivo propriamente dit.o fw.wrj-te("howdy\nfolks\n,'); / / escreve caracteres no I / arqurvo fw. flush( ) ; / / Timpa antes de fechar fw.close0; / / fecha arcruivo ao terminar FileReader fr = newFileReader(file) ; // FileReader / / objeLo size=fr.read(in); //16o arquivoint.eiro! System.out.print(size + " "); // quantos bytes lidos for(char c : in) // exibe o array System. out.print (c) ; fr.c1ose0,. // novamente, sempre fecha i catch(IoExcept.ion e) { }
)
o que produz a saida: 1-2 howdv
folks
Eis o que acaboude acontecer:
feztr6scoisas:
b c
atribuiu
(e
a fi/4/.
2.Escrevemost2caracteresnoarquivocomom6todowriteO,erealizamosumf}ushO
4. O m6todo
eumcloseO.
3. Criamos um novo objeto FileReader, que tamb6m abriu o arquivo em disco para leitura.
colocouem
5. Exibimos o nfmero de caraaeres cujotamanho ('size") foi lido, e fizemos um loop atrav6s do alray caracter que tenhamos lido, e depois fechamos o arquivo.
Antesde avangarmos,vamosfalarsobre
flush( ) e close( ). Quandovoc6 escreve dados emumstream, certa buffer, e nunca 6possivel sabei ro^rrtt":.aqug{o lyfimaparte dos dados seri quantidade de &dor r.ri"r*azenadaem ,ealmerrt. en',riada. VocA pode iareaLzar mtttas operag6es & escrita emum stream antes de fech6Jo, e chamar o m6todo f lush ( ) garante que a ,lltima parre dos dados seja de fato escrita no arquivo. Sempre que terminar de usar um arquivo, seja lendo Ju escrevendo nele, vtc6 deve chamar o m6todo close ( ) . Ao realizar E/S de arquivos, voc6 est6 usando recursos preciosos e limitados do sistema operacional; portanto, quando tiver terminado, libere esses recursos chamando
close ( ).
Agor4
de
voka ao nosso rikimo exemplo. Aquele programa ceftantente funaonarl" mCI ele 6 inadequado por alguns motivos:
os separadores de
1.
2. Quando
est{vamos lendo de volta os dados, os colocamos emum array decaracteres. Por se tratar de um array, tivemos de declarar o sen tamanho antecipadamente, de modo que teriamos problemas caso nio o ti#ssemos.feito_grande o suficiente! Poderiamos ter lido oi d"dos .t* caracter de cada vez, procurando pelo fim do arquivo ap6s cada read ( ) ,
mas isso 6 bem inadequado
tamb6m.
a essas limitag6es, normalmente n6s sempre usaremos classes E/S de nivel mais alto, como BufferedWriter ou BufferedReader, em combinafro com FilelVriter ou FileReader.
Devido
foram elaboradas paraserem combinadas entre si de inrimeras formas, para lidar com uma ampla gama de situag6es.
java.io, tentando Quando chegar a hora de trabdhar com E/S na vida real, vocA ceftamente se ver6 debrugado sobre a API juntas. Para o exame, vocA ter|, delazer o mesmo, mas n6s descobrir de quais classes ir6 precisar, e como faz&las trabalhar reduzimos artificialmente a A?I. Em termos de estudar para o Objetivo 3.2 do exame, podemos fazer de conta que todo o pacote java.io consiste das classes listadas no Objetivo 3.2 do exame e resumidas na Tabela6-t,a nossa mini API de E/S.
Tobelo
6-'l
Classe de iava.io
Mtodos Principais
t r-l-e
Obj
ect
k1t6 r +:v,
qrrrnd v er +++y
createNewFi-1e
SLring
String, String
mkdir
renameTo
FileWriter
Buf
Wri-ter
F'AIC
close
String
Wrr-ter
f 'l rrqh /
(
wrrte
feredWriterWriter
flush
newline
()
cl-ose o
flush
format
nrini/\
Y!:frg \ /
)
,
nrint-fl\* yrr:ru!
rr
\, \ /
Writer
FileReader
Bu
write
read
nri-r1n/\ f rref v!
Reader
t are
()
String
f f eredReader Reader
Reader
read( ) readline
() * Discutidos posteriormente
JAVA
5 25I
Ago1a, di8amos 9ue guis6ssemos achar uma maneira mais f6cil de escrever dados em um arquivo e ler o contetdo desse *lta para a mem6ria. Comegando com a tarefa de escrever dados no arquivo, eis um processo para se determinar Tq*"9 classes rremos de quars precisar, e como as colocaremos para trabalhar juntas:
1.
Sabemos que queremos' em ultima instincia, trabalhar com um objeto File. Entio, quaisquer que sejam que usarmos, uma delas precisa ter um constnrtor que use um objeto do tipo File. 6-1, podemos ver que
as
outras classes
2. Encontre
um m6todo que, pelo nome, parega ser a forma mais poderosa eflclde reahzar atarefa.Observando a Tabela Buffered\Triter tem um m6todo newline ( ) . Isso soa um pouco melhor do que ter de colocar manualmente um separador depois de cada linha, mas, se olharmos mais adiante, veremos que Print$riter tem um m6todo chamado println ( ) . Essa aparenta ser a abordagem mais ficil de todas, entio eicolheremos essa.
se
3. Quando
observamos os construtores de Print\7riter, vemos que podemos construir um objeto Print\Triter um objeto do tipo File, entio, tudo o que precisamos fazer para criar um objeto Print\Y/riter 6 o seguinte:
tivermos
File f ile = new FiIe (..f ilewrite2 . txt.') Printwri-ter pw = new Prj-ntWriter(fi1et
; ;
/ // // //
I
cria
Ok, hora de um pequeno teste. Antes deJava 5, Print\Triter nio tinha construrores que usassem nem String nem File. Se voc6 estivesse escrevendo um c6digo de E/S emJava 1.4, como faria um Print\flriter iscrever dado. ,r- Fil.? Dica: voc6 pode descobrir a respo$a estudando a mini API de E/S na Tabela G1.
.-
Eis uma maneirapossivel de resolver o problema: primeiramente, n6s sabemos que iremos criarum objeto File em das pontas da cadeia, e que queremos um objeto Printtlflriter na ourra ponta. Podemos ver na Tabela GL que um
uma
Print\(/ritertamb6mpodesercriadousando-seumobjeto\friter.Embora'Writernio
seilaumachssepresintenatabela,
podemos v_ er que diversas outras classes estendem S7riter, a qual 6 igualmente adequada par" os nosos prop6sitos; e qualquer classe que estenda Writer 6 uma candidata. Olhando mais adiante, podemos ver que File\Triter tem os dois atributos pelos quais estamos procurando:
I
2.
Estende\7riter.
Dadas essas informag6es, podemos escrever o seguinte c6digo (lembre.se: este 6 um exemplo deJava 1.4):
/ // // // // // //
/
FileWriter que enviarS. a sua saida para urn File cria um PrintWriter qre enviarii a sua saida para um Writer
um
cria
escreve os dados
esta dtura, dever6 ser relativamente ficil produzir o c6digo para ler mais facilmente a partir do arquivo, enviando as informag6es para a mem6ria. Novamente, olhando na tabela, vemos um m6todo chamado readline ( ) que aparenta ser uma forma bem melhor de ler dados. Passando por um processo semelhante, chegamos ao seguinte c6digo:
File file
new
|;
/ abre "filewrite2
txt."
FileReader fr
new
FileReader(fife);
=
(
BufferedReader br
fr),-
/ cria
um BufferReader para
pene O EXAME
poden ter encadeadas. quase garantido qae aoci encontrari quutdu flo exame que testardo o seu conhecinento de cono as classes de E/ S St)tto ,;iA*n ngdi ndo lhe tiuerfcado-clara, recoruendamos que uoci use a Tabela 6-1 cono referdncia e etcreua aldigos parafaTgr
e
ao
clar a$o
;
File file
= new rile(..foo,,)
Sempre cria um objeto File, e em seguida faz uma das duas seguintes coisas:
L Se " f oo " NAO existir, nio 6 criado nenhum arquivo, 2. Se " f oo " exittir, o novo objeto File refere-se ao arquivo existente. ReparequeFile file = ne\^/ File (*foo"); NUNCAcriaumarquivo.Existemduasmaneirasdesecriarum
arquvo:
Chamaro m6todo
createNewFile ( ) em um objeto
;
CriaumReader, ouumVriterouumaStream. Especificamente, criaumFileReader, umFile\flriter, umPrint\(riter, um FilelnputStream, ou um FileOutputStream. Sempre que cria uma instAncia de uma dessas classes, voc6 automaticamente cria um arquivo, a nio ser que ji exista um, por exemplo:
/ /
um
arguivo
/ 'pvr'
ao PrintWriter
A criagio de um diret6rio 6 semelhante I de um arquivo. Novamente, usaremos a convengio de nos referirmos a um obieto do tipo File, que represente um diret6rio real, comb um objeto Directory File, com D mairirculo (mesmo que seja do tipo Filej E chamaremos os diret6rios reais, presentes em um computador, simplesmente de diret6rio. Caramba! Assim como na criagXo de um arquivo, criar um diret6rio 6 um processo de duas etapas; primeiramente n6s criamos um objeto Dlrxtory (File), e em seguidalriamos um diret6rio real usando o seguinte m6todo mkdir ( ) :
/ | rri:
rrm nlriol-n
/ cria
um
diret6rio real
esses
Assim que tiver um diret6rio, vocd pode colocar arquivos nele e trabalhar com
arquivos:
JAVA
253
f );
,,
nio existaum,
Cuidado ao criarnovosdiret6rios! Comovimos, construirumReaderou \trfritercriariautomaticamenteumarquivo, caso mas nio acontece o mesmo com diret6rios:
File myDir = new File("mydir',) ; //myDit.mkdir0; File myFile = new File( myDir, "myFile.txt"); myFile.createNewFileo;
Isso
//
chamada
amkdiro omitida!
existingDir, no qud reside um arquivo linhas de texto. Quando voc6 roda o seguinte c6digo,
subdiret6rio chamado
existingDirrile . txl,
// atribui
File existingDir = new File("existingDir,,); System. out . println ( exist j-ngDir. isDirectory ( ) ) , File existingDirfile = new File( existingDir, "existingDirFile.txt"); System. out.println (existingDirFile. isFile ( ) ) ; FileReader fr = new FileReader (existingDirFile) BufferedReader br = new BufferedReader(fr); String s; while( (s = br.readline0) != nul1) System. out.println (s) ; br.closeO;
a
um
diret6rio
/ aluribu!
um arcrurvo
/ cria
um Reader
// 16 dados
Al6m
de criar arquivos, a classe File tamb6m lhe permite fazer coisas como renomear e apagar arquivos. O seguinte c6digo demonstra alguns dos recursos mais comuns referentes a apagar arquivos e diret6rios (via derete ( ) ), e renomear arquivos e diret6rios (via renameTo ( ) ):
File delDir
/ crLa um diret6rio
/ adiciona
um
arquivo ao diret6rio
de1Filel- . createNewFile ( ) ; File de1Fi1e2 = new File( delDir, "de1Fi1e2. txt") de1Fi1e2 . createNewrile ( ) ;
Aal Fi I a1 Aal afa / \
aE:aga um
arquivo
"
File
newName
delFi1e2 . renameTo (newName ) ; File newDir = new File("newDir"); defDir. renameTo (newDir) ;
Isso gera a saida:
delDir is false
e nos deixa com um diret6rio chamado que podemos deduzir desse resultado:
newDir
I delete ( ) Nio 6 possivel apagar um diret6rio se ele nio estiver vazio, que 6 o motivo pelo qual a chamada delDir. delete ( ) falhou. I renarneTo ( ) VocA precisa dar ao objeto File existente um novo objeto File vilido com o novo nome desejado. (Se newName fosse nu1 1, teriamos recebido uma Nu I 1 Po int erExc ept i on.) I renaneTo ( ) E permitido renomear um diret6rio mesmo se ele neo e siler vazio.
H6 muito mais a aprender sobre o uso do pacote java.io, mas, no que se refere ao exame, s6 temos mais uma coisa para discutir, que 6 aformadeprocurarporum arquivo. Panindo doprincipio quetemos umdiret6rio chamado searchThis no qual queremos fazer a busca, o seguinte c6digo usa o m6todo File . list ( ) paracrtar vmarray String de arquivos e diret6rios, nos quais usamos o loop f or aprimor ado paraiterar e exibir:
String[] files = new String[1-00]; File search = new File("searchThis"); files=search.listo; //criaalista for(String fn: files) // iLera atrav6s dela System.out.println( "found " + fn) ;
No nosso sistema, obtivemos
a
seguinte saida:
found dirl found dir2 found dir3 found file]. txt. found fi1e2 . txt
Os seus resultados quase cenamente serlo diferentes! Nesta segio, n6s vimos o bisico sobre o que esd disponivel no pacote java.io.l|foram escritos livros inteiros sobre esse pacote, de modo que, obviamente, estamos cobrindo apenas uma pequena (mas freqiientemente usada) pane da API. Por outro lado, se voc6 entendeu tudo o que abordamos nesta segio, estarl bem preparado para lidar com quaisquer perguntas referentes a java.io no exame (exceto no que se refere d senaltza$o, que serA abordadana seg6o seguintQ.
255
Imagine que voc6 queira salvar o estado de um ou mais objetos. Se Java nlo tivesse a serializagio (como nio tinha, naprimeira versio), voc6 teria de usar uma das classes E/S para escrever o estado das variiveis de instAncias de todos. os objetos.que quisesse salvar. A pior parte seria tentar reconstruir novos objetos que fossem praticamente idAnticos aos objetos que voc estava tentando salvar. VocA precisaria ter o seu pr6prio protocolo pira a maneira pela qual escreveria e restauraria o estado de cada obleto, caso contririo poderia aiabafdefinindoiari6veis com os valores errados. Por exemplo, imagine que voc6 tenha armazenado um objeto que tenha vari6veis de instAncias para altura e Peso. No momento em que silvar o estado do objeto, voc6 poderia .screvet a altura e o peso como dois ints em um arquivo, mas a ordem em que voc6 os escrevesse seria crucial. Seria muito f6cil recriar o
objeto, mas trocar os valores de altura
e de peso
- usando a altura
salva
vicevena-
A serializaglo lhe permite simplesmente dizer "Salve este objeto e todas as suas variiveis de instAncias". Na verdade, 6 um pouco mais interessante do que isso, porque vocd pode adicionar'...a nio ser que eu tenha marcado explicitamente uma vari6vel como translent, o que significa que nio 6 para incluir o valor da vari6vel transiente como parte do estado serializado do objeto".
ectOutputstream. writeobj ect ( ) // serial-iza e escreve Obj ectinputstream. readObj ect ( ) // AOe deserializa As classes j ava. io . Obj ectoutputstream e j ava . io . Obj ectlnputstream sio consideradas como
de alto nivel no pacote java.io, e, como aprendemos anteriormente, isso significa que voc6 os usari para
encapsular classes de n(vel mais baixo, tais como java.io.FileOutputStream e java.io.Filelnputstream. Eis um pequeno programa que cria um objeto (CaQ, o serializa, e depois o deserializa:
i mnnrl.
"i
arra
i n *
class Cat irylenentg Serial-izalcle | | ll t public class SerializeCat { public static void main(String[] args) { Cat c = nevr c,aE(lt ll 2 try { FileOuLputStream fs = new FileOutputstream( "testser. ser"
ectOutputstream os = new ObjectOutputstream(fs),. os.writeobject (c) ; t/ 3
Obj
os. close O ;
) catch (Exception
e)
{ e.printstackTraceO ;
trv
FilelnputStream fis = new Fil-elnputStreann( "testser. ser" Objectlnputstream ois = new Objectfnputstream(fis) t c = (Cat) ois.readObject(), ll 4 ois.closeO; ) catch (Exception e) { e.printstackTraceO; }
)
1. N6s declaramos que a classe Cat implementa a interf.ace Serializable. Serializable 6 uma interface marcadtra; ela nlo tem nenhum m6todo para implementar. (Nas pr6ximas segSes, falaremos de virias regras sobre quando
voc6 precisa declarar as classes como Serializable.)
2. Criamos um novo objeto Cat, o qual, como sabemos, 6 serializ6vel. 3. Serializamos o objeto Cat chamando o m6todo writeobj ecL ( ) . Foi preciso alguma preparagio antes que
pud6ssemos de fato serializar nosso Cat. Primeiramente, tivemos de colocar todo o nosso c6digo relativo a E/S dentro de um bloco trylcatch. Depois, tivemos de criar um FileOutputStream no qual escreveremos o objeto. Em seguida, encapsulamos o FileOutputStream em um ObjectOutputStream, que 6 a classe que possui o m6todo migico de serializagio de que precisamos. lembre-se de que a chamada de writeobj ect ( realba duas tarefas:
Formoioq6o e Porsing
4. Deserializamos o objeto
Esse 6
retorna um
Object, de modo que precisamos convener o objeto deserializado de volta em um Cat. Novamente, tivemos de passar pelos passos tipicos de E/S para configurar isso tudo. um exemplo simplificad o da serializagno na prhtica. mais complexas associadas com aserializagio.
Ao longo
das
Gr6ficos de Objetos
O que significa realmente salvar um objeto? Se as varilveis de instAncias forem todas tipos primitivos, 6 bem simples. Mas, e seas vari6veis de instAncias forem elas mesmas refer6ncias a oQetos? O que 6 que acaba sendo salvo? Claramente, nXo faria sentido emJava salvar o valor real de uma varilvel de refer6ncia, porque o valor de uma refer6ncia emJava s6 tem significado dentro do conrexto de uma rinica instlncia de umJVM. Em outras palavras, se voc6 tentasse restaurar o
objeto em outra instincia daJVM, mesmo que rodando no mesmo computador em que o objeto foi originalmente serializado, a refer6ncia seria inritil.
Mas, e quanto ao objeto para o qual a referAncia aponta? Observe esta classe:
nrirrafa nrrhl in
/-allarlinf
colLarSize = size; ]
I I r^fr1rn nnl I arQi zo.
I
Agora crie um Dog... Primeiramente, voc6 cria um Collar (*coleira") para o Dog:
a ele
o Collar:
se voc6 salvar Dog? Se o objetivo 6 salvar e depois restaurar um Dog e se o Dog restaurado for uma duplicata erata daquele que foi salvo, entlo o Dog precisa de um Collar que seja uma duplicata qrata do Collarr que estava atribuido a Dog no momento em que ese riltimo foi salvo. Isso sigpifica que tanto Dog quanto Collar devem ser salvos.
E se o pr6prio Collar tivesse referAncias a outros objetos - talvez um objeto Color, por exemplo? Isso fica bem complicado rapidamente. Se fosse responsabilidade do programador conhecer a estrutura interna de cada objeto que Dog se referisse, para que o programador pudesse salvar o estado de todos os objetos que com certeza estivessem relacionados a Dog... Isso daria trabalho. Seria um pesadelo, mesmo com os objetos mais simples.
Felizmente, o mecanismo de serializagilo Java cuida de tudo isso. Quando voc6 serializa um objeto, a seralizaglo Java salva todo o "grifico do objeto". Isso significa uma c6pia detalhada de tudo de que o objeto salvo precisa para ser restaurado. Por exemplo, se voc serializar um objeto Dog, o Collar seri serializado automaticamente. E se a classe Collar contiver uma referencia a um outro objeto, esse outro objeto tamb6m seri serializado, e assim por diante. E o rinico.objeto que voc6 precisa de-preocupar em salvar e testaurar 6 o Dog. Os outros objetos lggueridos para se reconstruir completamente o Dog slo salvos (e restaurados) automaticamente, por meio da serializagio.
Mas lembrese de que vod precisa decidir ativamente se vai criar objetos qtre se6o antertace Seridizable. Se quisermos ulvar objetos Dog por er<emplo, rcremos de modificar a classe Dog da seguinte forma
serializiveis,
cfass Dog implenenLs SerLalizable { / / resxo do c6digo id6ntico ao anterior / / SeriaTizabl-e ndo tem m6todos para implementar
]
E agora podemos salvar o Dog com o seguinte c6digo:
JAVA
257
public class SerializeDog { public static void main(StringlJ args) 1 Co11ar c = new Co11ar(3); Dog d = new Dog(c, 8); trY { FileOutputstream fs = new FileOutputstream( "testser.
ObjectOutputstream os = new ObjectOutputstream(fs),. os.writeObject (d) ;
os. close O
)
,.
ser,, ) ;
Por6m, quando executarmos esse c6digo, receberemos uma exceEio de tempo de execuEio parecida com esta
java. io.NotSerializableException: Co1lar O que foi que esquecemos? A classe Collar TAMBEM deve ser Serializable. Se modificarmos a classe Collar
tornarmos serializ6vel, enteo neo haverh problemas:
ea
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
]
))
private int dogSize; public Dog(Co11ar col1ar, int size) theCollar = col]ar; dogSize = size;
)
class Collar implements Serializable { private int coflarSize; public Co11ar(int. size) { collarSize = slze;
nrrl-'] in yuv+re )
rrre
} l
inf
aat-(-nllareiual\ Yvuvvrrs!er-v\/
It !eusrrr rafrrrn
an1l:reiza.
nio
Obviamente, n6s poderiamos criar uma subclasse de Collar, marcar a subclasse como Serializable, e usar a subclasse emvez da classe Collar. Mas isso tamb6m nio 6 sempre uma opgio, por virios motivos potenciais:
1..
OU
A pr6pria classe Collar poderia referir-se a outros objetos nlo-serializ6veis e, sem conhecer a estrutura interna de Collar, voc6 nlo ter6 como fazer todos esses reparos (panindo do principio que voc6 sequer iria querer TENTAR esse caminho). OU
2.
3. Se criar uma subclasse
ao seu projeto.
li
ai q.te entra o modificador transient. Se vocd marcar avari|velde instAncia Collar de Dog como trransient, a serializaglo ir6 simplesmente ignorar o Collar durante o processo: class Dog implements Serializable { private Uransient Col1ar theCollar; // adicionamos transient / / resto da classe id6ntica i ancerror
class Collar
I
Agora n6s temos um Dog serializivel, com um Collar nlo-seializivel, mas o Dog marcou o Collar como
sient; asuda6 before: collar size is 3 Exception in thread *main" java. lang.NullPointerException
Usando writeobiect e readObject
tran-
Considere o problema: n6s temos um objeto Dog que queremos salvar. O Dog tem um Collar, e o Collar tem um estado que deve tamb6m ser salvo como parte do estado de Dog. Mas... O Collar nda |Sefializable, de forma que precisamos marc6-lo como transient. Isso significa que, quando o Dog for deserializado, ele voltar6 com um Collar nulo. O que podemos fazer para nos certificarmos de que, quando for deserializado, o Dog receba de al-guma forma um novo Collar com as mesmas caracteristicas daquele que estava atribuido a Dog quando este
dltimo foi
salvo?
JAVA
259
A serializagio Java possui um mecanismo especial para esse caso - um conjunto de m6todos privados que vocQ pode.implementar na sua classe que, se presente, ser6 chamado automaticimenre durante a sirializagi6 e a dese{*izaglo. E quase_ como se os m6todos fossem definidos na interface. Serializable, excero pelo fato de que nXo sio! Eles fazem parte de um contrato de callback especial que o sistema de serializagio lhe oferece, o qual ' basicamente diz "se voc6 (o programador) tiver um par de m6todos que batam .o* Lrt" exata assinatura (voc6 veri isso logo adiante), estes m6todos serio chamados durante o p.ocesso de serializagio/deserializagio,
m6todos lhe permitem interferir 19 processo de serializagio e des-serializagdo. Assim, eles sio perfeitos para.resolver o.problema com Dog e Collai: quando um Dog esti sendo sdvo, vot6 pode interferir no meio da serializaglo e dizer ,"A prop6silo, eu gostaria de adicionar o estado da vari6vel (int) de Collar ao stream quando o Dog for serializado". VocO adicionou manualmente o estado do Collar i representagio serializada de Dog, mesmo que o pr6prio Collar nXo seja salvo.
Esses
E claroqne vod precisari restaurar o Collar durante adxializa$o, interferindo no processo e dizendo: "Eu vou ler aquele int extra que sakei no stream de Dog e us6Jo para criar grn novo Collar, e depois airibuir esse novo Collar ao Dog que e$6
sendo deserializaclo". Os dois m6todos apeciais que
vod
private void writeObject (ObjectOutputstream os) { / / aqvi entra o seu c6digo para salvar as vari6veis de Co11ar
]
private void readObject (ObjectfnputSt.ream os) { / / aqur entra o c6digo para ler o estado de Collar, criar / / e atribui-lo ao Doq
]
um novo
Col]ar,
Sim, n6s vamos escrever m6todos que t6m o mesmo nome daqueles que estivemos chamando! Onde sio colocados esses m6todos? Vamos modificar a classe Dog:
class Dog implements Serializable { transient priwate Collar theCollar; | | nilo private int dogSize,. public Dog(Co11ar col1ar, int size) { theCollar = collar; dogSize = size;
]
Dodmos
geriaLizar ieto
public Co1lar getCollarO { return theCollar; } Drivate void writaObject (ObjectorltDutstrearn oF) l / / Ianqa loException try { os.defaultwriteobject ( ) t os . writelnt (theCollar. getcol-l-arSize ( ) ) ; ) catch (Exception e) { e.printStackTraceO; }
)
// r
// //
2
3
Drivate voidt readObj ect (Obj ecthDut,st,ream ie ) { / / l-anqa IoException, ClassNotFoundException trY {
is.defaultaeadObject
()
//
;
}
// s
//
6
No noso cenirio,
n6s concordamos que, por qudquer que seja o motivo no mundo real, nio podemos serializar um objeto Collar, mas queremos serializar um Dog. Para isso, iremos implementar writeObj ect ( ) e readObj ect ( ) . Ao implementar esses dois metodos, voc esri dizendo ao compilador: "se alguem chamar writeobj ect ( ) ou readobj ect ( ) em rela$o a um objao Dog use ese c6digo como parte da leitura e da escrita".
1. Como a maioria dos m6todos relativos a E/S, ou tratar, mas recomendamos que as trate.
2.QuandovocdchamadefaultWriteobjectO
o processo normal de seri"liz4is no obieto em queitio. Ao implementar writeOb j ecE ( ) voc6 normalmente ' rra pedir o processo normal de senahzaglo, e tambtm realbar alguma escrita e leitura personalizadas.
um int (o tamanho de Collar) no stream que est6 criando o Dog serializado. Voc6 pode escrever esses dados extras antes e /ou depois Qye chamar def aultWriteobj ect ( ) . MAS... Quando frzer aleitura deles, vocA teri de ler os dados extras na mesma ordem em que os escreveu.
4. Novamente, decidimos tratar as exceg6es, emvez de declari-las. 5. Quando chegar a hora de deserializar, se voc6 nXo implementar um m6todo
6. Finalmente, criamos um novo objeto Collar paru o Dog usando o tamanho que serializamos manualmente. atpolt de te.mos cha=mado def aultRea-aoni ect ( ) , ou os dados streamed ffivemos de chamar
readlnt (l
sairiam de sincronia!)
Lembre-se de que o morivo mais comum para se implementar writeobj ect ( ) e readobj ect ( ) ocorre quando voc6 tJm de salvar uma pafte do estado de um objeto manualmente. Se preferir, voc6 pode escrever e ler TOOOS os seus dados voc6 mesmo, mas isso 6 bem raro. Assim, quando quiser fazer apenas parte da serializaglo/ deserializagio manualmente, voc6 DEVE chamar os m6todos def aultReadobj ect ( ) e defaultWriteobject O para fazer o resto.
O que suscita uma outra pergunta - por que nio fazer todat as classes em Java serializiveis? Por que a classe Object nio 6 serializ6vel? Existem algumas coisas em Java que simplesmente nXo podem ser serializadas, porque sio especificas do tempo de execuEXo. Coisas como streams, threads, o pr6prio tempo de execugio, etc., e at6 mesmo algumas classes GUI (que se conectam ao SO subjacente) nio podem ser serializadas. O que 6 ou nio 6 serializivel
em Java
pnnn O EXAME
ar regrat nornais de interfaceJaua, todas at ubclasses dela automaticanente inplenmtardo Seialiqable inplicitanente. Em outrat palauras, uma subclasse de uma clasn marcada cono Seialiqabh parsa fio teste E-UM para Serialiqable, e, portanto, pode ser salaa sen qae se precisa marcar explicitanente a subclase como seriali4luel. E sinplesnente inpossiuel vber se arzta claxe d niali4iuel ou ndo, A NAO SER$(JE uoci possa uer a drvore de heranga da clase para uerifcar se alguma das superclasset implementa Seialiryble. Se a classe ndo utender explicitamente nenbama oatra, e ndo implenentar Seialirybk, entdo uoc ube COM CEKTEZA que a classe ndo i seriali4luel, porque a elasse Object NAO implementa Seialiqabk.
Se uma superclasseforSeialiqable, entdo, de aeordo com
Isso nos traz a outra que$eo importante a respeito da serializagio... O que acontece se uma superclasse nio for marcada como Serial i zable, mas a subclasse for? Ser6 que a subclasse ainda poder6 ser serializada, mesmo que a sua superclasse nXo
implemente
class Animal { } class Dog extends Animal implements Serializable // restante do c6diqo de Dog
]
Agora voc6 tem uma classe Dog serializ6vel, com uma superclasse nio-serializ6vel. E funciona! Mas existem algumas implicag6es potencialmente drias. Paraentender completamente essas implicag6es, vamos voltarever adiferengaentre um objeto oriundo & deserializagio e um objeto criado com new. Lembre.se de que quando um objeto 6 construido comnew (em vez de ser deserializado), acontece o seguinte (nesta ordem):
1.
Todas
as
2. O
construtor 6 chamado, o que imediatamente chama o constnrtor da superclasse (ou algum outro construtor sobrecarregado, at6 que um dos construtores sobrecarregados chame o construtor da superclasse). finnliz.urr.
4. As vari6veis de instAncias que sio inicializadas como parte das suas declarag6es recebem os seus valores iniciais (em vez dos valorespadrXo que recebem antes de os construtores das superclasses finalizarem as suas tarefas).
5. O construtor finaliza.
JAVA
Mas esrat
26I
coisas NAO acontecem quando um objeto i deniali7atlo. Quando uma instAncia de uma classe serializivel 6 deserializada, o construtor n-o roda, e as vari6veis di instlncias NAO recebem os seus valores iniciais! pense nisso - se o construtor fosse chamado, e / ou as variiveis de instAncias recebessem os valores contidos nas suas decla.raE6e-s, o objeto que voc6 esti tentado restaurar voltaria ao seu estado original, emvezde voltar refletindo as modificag6es que ocorreram ao estado.eT 4gur" momento depois da sua cria[io. Por exemplo, imagine que voc6 tenha uma classe que declare uma variivel deinstAncia e atribua a ela o valor int 3, e inclua n* mEtodo qr're modifique o valor da variivel de instAncia para 10:
class Foo implements Serializable 1nt num = 3; void changeNumfl { num = 10;
J
voc6 serializar uma instAncia de Foo tlepoh que o m6todo changeNum ( ) rodar, o valor da de Foo foi des-serializada,voc| quer que avari|velnum ainda seja 10! Otviamente, voc6 nio quer que ainicializagio (neste caso, a atribuigio do valor 3 i vari6vel num) alontega_. Pense nas atribuig6es de construtores e de variiveis de instAncias junras, como parre de um s6 processo de inicializagio de um objeto (e, na verdade, elas DE FATO se tornam um s6 m6todo diinicializacio em bytecode). A questXo 6 que, quando um objeto 6 deserializado, n6s NAO queremos que a inicializigio normal acontega. Nio queremos que os construtores rodem, e nio queremos que os valores explicitamente declarados sejam atribuidos. Queremos apenas que os valores sejam salvos como parte do estado serializado do objeto a ser
se
Obviamente,
reatribuido.
E claro que, se voc6 tiver vari6veis marcadas como transient, elas nio serio restauradas aos seus estados originais (a nio ser que voc6 implemente defaultReadobj ect ( ) ); em vez disso, elas receberio o valor padrio par^ o tipo de dados em questeo. Em outras palavras, mesmo se voc6 disser
transientintx=42;
)
quando a instAncia de Bar for deserializda, avari|vel x sera definida como um valor de 0. As referncias a objetos marcadas como transient. serio sempre resetadas como nu11, independentemente de se elas foram inicializadas no momento da declaragio na classe.
EntXo,6 isso o que acontece quando o objeto 6 deserializado, e a classe do objeto serializado estende object diretamente, ou tem APENAS classes serializiveis na sua irvore de heranga. Fica um pouco mais complexo quando a classe
serializivel tem uma ou mais superclasses nio-seializiveis. Voltando ao nosso exemplo da classe Animal nio-serializ6vel com uma subclasse Dog seriaJizAvel:
class Animal
nrrhl i c
v
Pelo fato de AnimalNAO serse ialtzbvel,qualquere$ado mantido naclasse Animal, mesmo que avari6velde estado seja herdada pelo Dog, nio seri restaurado com o Dog quando este {or deserializado! O motivo 6 que a parte (nio-serializada) Animal deDogir6 serreinicializadaexatarrrcnte como sevoc6 estivese criando um novo Dog (emvezde deserializando um). Isso significa que todas as coisas que acontecem com um objeto durante a construgio irio acontecer - mas apenas is panes Animal do Dog. Em outras palavras, as variiveis de instAncias da classe de Dog serio serializadas e deserializadas corretamente, mas as vari6veis herdadas da superclasse Animal, ni.o-serializ6vel, voltario com os seus valores-padrio/ iniciais atribuidos, emvez de com os valores que tinham no momento da serializaEio.
Dada uma classe serializivel, rnas com uma superclasse NAO serializivel, quaisquer variiveis de instincias que a primeira HERDAR da superclasse sereo resetadas aos valores que receberam durante a construgeo original do objeto. Isso ocorre porque o constnrtor da classe nio-serializivel IRA rodar!
Na verdade, todo construtor ACIMA do construtor da primeira classe nio-serializixeltamb6m rodar6, de uma forma ou de outra, porque, depois que o primeiro construtor for chamado, ele obviamente chama o seu super construtor, e assim por diante na Lrvore de heranga.
Para o exame, voc6 dsver6 ser capaz de reconhecer quais vari6veis serlo restauradas com os valores apropriados, e quais nio serio, quando um objeto for deserializado, entio, certifiqtrese de e$udar o seguinte c6digo de o<emplo e a sua saida:
FormotoE6o e Porsing
"
try
os.writeobject (dr
os. close O
;
FilelnputStream fis = new Filelnputstream( "testser. ser" Objectlnputstream ois = new ObjecLlnputStream(fis) ;
A v /n^^\ \uvvt r^a^.th-iaat-l\, vrD.rsqsvvjevur/ ^ic
/
" + d.name + * \
;
+ d.weight)
class
Serializable
)
nl aqc Anim:] I
/ ndo serializ6ve-
int weight =
]
que produz esta saida:
42;
35 42
seu
O ponto principal aqui 6 que, pelo fato de Animal nio ser serializ6vel, o weight de Dog, herdada de Animal, quando Dog foi deserializado.
variivel
oBSERVAQ6ES
pene O EXAME
Se uoci seialiqar am conjunto 0u afll affE6 todos os elementos deuen ser seiali4lueis! Un sd elemento ndo-seiali4luel que sfafar,i a seialiqapdo falhar. Obsene tambim que, enqaantl as interfaces dos conjuntot ndo sdo serialiqiueis, o sdo as classes conmtas dos conjantot
naAPIJaua.
JAVA
seria
263
problema?
lsado para substituir aquele atualmente presente na (rinica) classe Dog atualmente
carregada? Entendeu o
As vari6veis est6ticas NLINCA sio salvas como parte do estado do objeto, porque elas nio perrencem ao objeto!
oBSERVAQ6ES
E
pene O EXAME
quanto a DatalnpatStream e DataOulputstream? Elas utdo nos objetiuos! Ocorre qae, enquantt o exane estaua sendo criado, decidiu+e qile eiJas duat c/assu ndo caiiam flaPrlaa, mas a/gudm se esqueceu de retini-/at tlos objetiuos. Portanto, uocd consegaiu unafo/ga. E ana coisa a menos com qae re preoillpar.
AOTRABALHO
Por mais que s/a
un objxo Dog
flcil ucreuer aidigo de rcrialiqagdo, poden ocotrer problemas referentes is uersdes das clasxs, no mando real, Se uoed sahar usando uma uersdo da clare, mas tentar dueialiqti-/o usando uma aertio dferente, mais noua, o procero poderdfalhar. Consalte a API Jaua para nais detalhet sobre questdet e solugdes rgferentes a uercb-et de clasw.
no pacote jaua.text parafonnatar ou exibir conetanente datas, nilmeros e ualores monetdrios para uma /ocalidade espufrca; e, dado um nndrio, deterrtinar os mdtodos propriados caro uoci qaeia usar o local padrlo ou algum outro local
propdtito
eo
an da classe jaua.fiil.L.ocale.
A APIJava fornece um conjunto extenso (talvez extenso um pouquinho demais) de classes para$td6-lo a trabalhar com datas, ntimero e moedas. O exame testari o seu conhecimento das classes e m6todos bisicos que voc6 usar6 para trabalhar com datas e que tais. Ao terminar esta seqio, voc6 dever4 ter uma base s6li& em tarefas, como: criar novos objetos Date e DateFormat, convener Strings em Dates e vice-versa, realizar fung6es de calend6rio, exibir valores moneterios corretamente formatados, e fazer tudo isso para qualquer localidade do planeta. Na verdade, um dos principais motivos pelos quais esta seglo foi adicionada ao exame foi para testar se vo c6. 6 capaz de realizar
internacionalizagno (ds vezes abreviada como "i18n') bisica.
usem classes que nio foram mencionadas especificamente no objetivo da Sun. Eis as quatro classes relacionadas
voc precisad entender:
datas que
j ava . ut i I
Dat,e
classe
I java.util.Calendar
Estaclasseforneceumagrandevariedadedem6todosquelhe $ltdama converter e manipular datas e horas. Por exemplo, se quiser adicionar um m6s a determinada data, ou descobrir em que dia da semana vai cair 1o de janeiro de 3000, os m6todos da classe Calendar estio ai para isso. como "01/01 /70" ov"January
loacis em todo o mundo.
Esta classe 6 usada paraf.ormatar datas nio apenas fornecendo virios estilos 1970", mas tamb6m paraformatar datas para diversos locais em todo o mundo.
Esta classe 6 usada em conjunto com DateFormat e NrunberFornrat para formatar datas, nri.meros e moedas para locais especificos. Com a ajuda da classe Locaf e vocd poderi converter uma data como "10/08/2@5" para "Segunda-feira, 8 de Outubro de2@5" instantaneamente. Se quiser manipular datas sem produzir output formatado, vod poderi usar a classe Locale diretamente com a classe Calendar.
uso relacionados a datas e n/rmeros, al6m de solug6es usando-se essas classes. A Tabela 6-2 com certeza suscitari dfvidas especificas sobre determinadas classes, e iremos mergulhar nos detalhes de cada classe em seguida. Depois de ler as explicag6es detalhadas sobre as classes, voc6 dever6 perceber que a Tabela 6-2 oferece um bom resumo.
Tobelo 6-2 Cosos de Usos Comuns oo se Trobolhor com Dolos e N0meros Caso de Uso
Etapas 1. Crie um Date: orte d = new DaE.e ( ); 2. Obtenha o seu valor: String s = d.toStrj.ng0i
1..
lhepermita
Crie um Calendar:carendar
2. IJse
c.aaa(.
hora.
Calendar. getlnstance
()
) e c.ro11 (.
de data e
1.
CrieumLocale:
esse
local:
3.Usec.aaa(. .)ec.ro11 (.
de data e hora.
Calendar c = CaLendar.getlnstance(1oc);
.)
parareahzar manipulag6es
1.
CrieumCalendar:
Calendar c = Calendar.getlnstanceO;
2. Crie uml-ocale para cada local:
com
.);
Date d = c.getTime0;
4.
CrieumDateFormat
paracadaLocale:
DateFormat df = DateFormat.getDatelnstance
(sty1e, loc)
5. Use o
String s = df.format(d)i
Obterum objeto que lhe permita formatar nrimeros ou moedas em diversos locais.
Localeloc
Y
1.
newl,ocale(. . Ji
tt
String s = nf.format(alqunNfmero);
A Classe Date
classe Date tem um passado nebuloso. O projeto da sua API nXo fazia um bom trabalho ao lidar com situag6es de ^est jdo internacionalizagio e de localizagio. No seu atual, a maioria dos seus m6todos foram depreciados e, pari a maioria das situag6es, vocA usari a classe Calendar em vez da classe Date. A classe Date est6 no exame por v6rios motivos: voc6 poder6 encontr6-la em c6digos antigos; ela 6 bem ficil de usar, caso tudo o que voc6 queira seja uma forma ripida de se obter a data e a hora atuais; 6 ritil quando voc6 quer uma hora universal que nio seja afetada por fusos horirios e, finalmente, voc6 a usar6 como uma ponte temporiria para formatar um objeto Calendar usando a classe DateFormat.
Como mencionamos rapidamente acima, uma instAncia da classe Date representa uma s6 data e uma s6 hora. Internamente, data e hora silo armazenadas como um tipo long primitivo. Especificamente, o long e 10. de janeiro nimero de milisegundos (voc6 sabe, sio 1000 deles por segundo), entre a data sendo representada ^rmazenao det970.
J6 parou para pensar em como os nrimeros sXo grandes? Vamos usar a classe Date para descobrir quanto tempo demorou para passar um trilhio de milisegundos, comegando em Lo. de janeiro de 1970:
'imnnrla1:ec i:rra rrl- i l { { *.
m6ern=f66
JAVA
265
Na
nossa
JVM, que
MDT 2001
a cada 3L e
2/3
anos.
embora, como veremos em breve, seja um pouco inadequado. Vamos adicionar uma hora ) nossla instAncia de Date, a panir do exemplo anterior:
imnnyf frrrvvrL -.i-r',,!il Jqvo.uLft. *, ,
setrime,
6.
aceitllelusar os m6todos
getrime
class Test.Dates { public static void main(String[] arqs) { Date d1 = new Date(1000000000000L) ; / / um trilhdo! System.out.println("1st date ,, + d1 .tostrinSO ); dl.setTLne(dl.getTime() + 350000O); /| 3600000 milisegundoE / hora Sygtem.out.printLn($new time .' + dl.toString() ) ;
)
MDT 2001
now.
getrime
(),
dois trilh6es.)
A Classe Calendar
Acabamos de ver que manipular datas usando a classe Date 6 complicado. A classe Calendar foi elaborada Dara tornar a manipulagio de datas maii f6cil! (Bem, pelo menos mais f6cil que Date.) Embora a classe Calendar tenha^milh6es de campoi e m6todos, depois que'ttocA pegai o jeito de algumas delis as outias tendem a funcionar de forma semelhante.
Quando t_entar usar a classe Calendar pela primeira vez, poderi perceber que ela 6 uma classe abstrata. possivel dizer
Nio
Calendar c = new
dafTncfanno I \.
no exemplo acima, a variivel da sua referncia Calendar na verdade est6 se referindo a uma instAncia de uma subclasse concreta de Calendar. Nio 6 possivel saber com certeza qual subclasse voc6 receberi (muito provavelmente, se-ri j ava . 1 . GregorianCalLndar), mas isso nio lhe {arA diferenga. Voc6 estar6usando a API de Calendar. (A medida queJava continua a se espalhar peio mundo, p aramanter a coesio, voc6 poder6 encontrar novas subclasses de Calendai especificas para diferentes locai$.
Calendar ca1 = Calendar.getlnstanceO ; Quando voc6 obt6m uma refer6ncia Calendar, como cal
uti
Certo, agora que n6s temos uma instAncia de Calendar, vamos voltar ao nosso exemplo anterior e descobrir em que dia da semana caiu o nosso trilion6simo milisegundo, e depois vamos adicionar um mAs a essa data:
imnnrliarra rrf i l *-
\. r,
Calendar c = Calendar.getlnstanceO
Porsing
e.setTine(d1);
ll ll
#L
if (c. SITNDAY == c. getFirstDalofWeek ( ) ) System.out.println("Sunday j-s the first day of the week"); mi1li day of week is " System.out.println("trillionth
+ c. get (c.DAY-OF-WEER) c.add (Calendar.MONTH,
1)
#2
Date d2 = c.getTime()t
/l *3 ll *4 il*s
1st dafp sef serl 0B 19:46:40 MDT 2001 Sunday is the first day of the week trillj-onth mi1lj- day of week is 7 new date Mon Oct 08 20:46:40 MDT 2001
Vejamos os detalhes deste programa, concentrando-nos nas cinco linhas salientadas:
1.
Atribuimos a Data
d1 I instAncia c
de Calendar.
_
2. Usamos o campo strNDAY de Calendar para determinar se, para a nossaJvM, suNDAY ("domingo") 6 considerado cbmo o primeiro dia da semana (em alguns locais, MoNDAY -"segunda-f.eira"- 6 considerada o primeiro dia da semana). A classe Calendar fornece campos semelhantes para dias da semana, meses, o dia do m6s, o dia do ano e assim por diante. 3. IJsamos o campo DAY-OF-WEEK para descobrir o dia da semana em que caiu o trilion6simo milisegundo.
4. At6 aqui, usamos m6todos serter e getter que lhe devem ser de f6cil entendimento. Iremos agora usar o m6todo add ( ) de Calendar. Esse m6todo bastanie poderoso lhe permite adicionar ou subtrair unidades de tempo
apropriadas para qualquer campo de Calendar que voc6 especificar. Por exemplo:
c.add(Calendar.HOUR, -4)
// // // //
subtrai 4 horas do valor adicj-ona 2 anos ao valor subtrai dois dias do valor de c
de de
O outro m6todo de Calendarquevoc6 devericonhecerparao exame6 ro11( ). O m6todo ro11( ) agecomo o m6todo add ( ) , exceto pelo fa^to de que, quando uma pafte de um Date 6 incrementada ou diminuida, panes maiores do Date em queltio nlo serlb inirementadas bu diminuidas. O qu6? Por exemplo:
//
Date d4 = c.getTimeO;
new
date Fri
.Tu1 0B
19:46:40
MDT 2001,
Repare que o ano nio mudou, embora tenhamos adicionado 9 meses a uma data de outubro. De forma semelhante, chamar ro11 ( ) com HOUR nio modifica a data, nem o m6s e nem o ano. Para o exame, voc6 nio teri de memorizar os campos da classe Calendar. Se precisar deles para ajud6Jo a responder uma pergunta, eles serio fornecidos na pr6pria pergunta.
A Classe DateFormat
Tendo aprendido como criar e manipular daras, vamos descobrir como format6-las. Para estarmos todos sincroniiados, eis um exemplo de como uma data pode ser formatada de diferentes maneiras:
JAVA
267
cl-ass Dates3
{
{
DateFormat[] dfa = new DateFormat[5]; dfa [0] = DateFormat. getlnstance ( ) ; dfatll = DateFormat.getDat.elnstance( ) ; dfa[2] = DateFormat.getDatelnstance (DateFormat.
SHORT) ;
;
(DateFormat.MEDIUM)
;
;
nl- l n ldf
f nm:f
/Al \ \
\sr/ /,
PM
Sep
8,
2001
Septemlcer
8,
2001
getDatelnstance ( )
Em seguida, usamos campos estiticos da classe DateFormat para personalizar as nossas virias instlncias de DateFormat. Cada um desses campos e$6ticos representa um estilo de formataglo. Neste caso, parece que a verseo sem argumentos de getDatelnstance ( ) nos d6 o mesmo estilo que a verseo MEDIUM do m6todo, mas essa nio 6 uma regra geral. (Mais sobre isso quando discutirmos os locais.) Finalmente, usamos o m6todo f ormat ( )
para criar Strings representando as vers6es devidamente formatadas daData com que estamos trabalhando.
O riltimo m6todo com o qualvoc6 deve se familiarizar6parse O. O m6todo parse ( ) usauma String formatada no estilo da instAncia de DateFormat sendo usada, e converte a String em um objeto Date. Como voc6
pode imaginar, essa 6 uma operagio arriscada, porque o m6todo parse ( ) poderia facilmente receber uma String mal formada. Por causa disso, parse ( ) pode langar uma ParseException. O seguinte c6digo cria uma instAncia de Date, usa DateFormat. f ormat ( ) para convertd-la em uma String e depois usa DateFormat . parse ( ) para transformi-la de volta em Date:
trv
Date d2 = df.parse(s);
))
Porsing
)
perdemos alguma precisio quando convertemos o Date em uma String. Essa per& de precisio surgiu quando convertemos de volta para um objeto Date, e a hora passou de 7:46 para mela-norte.
d1 = Sat Sep 08 L9:46:.40 YIf,lT 2001 9/8/01 parsed = Sat SeF 08 00:00:00 MDT 2001 Repare que, pelo fato & e$armos usando um estilo sHoRT,
AO TRABALHO
A API para DateFormat.parse(
expeilncia, parseQ ndo
explica que, porpadrio, o mdtodo parse ( ) d ben to/erante ao faqerparsing de datat. Pela nosa tdo tolerante a retpeito daforraatagdo de Strings que insere com Jilcestl em datas; cuidado ao usar esse nitodo!
A Classe Locale
Anteriormente, n6s dissemos que uma das raz6a principais para a exist6ncia deste obj eilo era paratestar a sua capacidade de realizar algumas tarefas bisicas de internacionalizagio. A sua espera acabou: a classe Locale 6 a sua passagem para a dominagio do mundo. Tanto a classe DateFormat quanto a NumberFormat (sobre a qual falaremos em segurda) podem usar uma instincia de Locale para personalizar uma saida formatada para que ela se adapte a determinado local. Voc6 poderia perguntar, comoJava define um local? A API diz que um local 6 "uma regiio geogrifica, politica ou cultural especifica". Os
dois corutrutores de Locale quevocA precisari conhecerparao exame
sio
Vamos voltar ao modo de usar esses c6digos. Se voc6 quiser representar o italiano bisico no seu aplicativo, tudo de que precisa 6 o c6digo dessa lingua. Se, por outro lado, quiser representar o italiano usado na Suiga, voc6 indicaria esse pais (sim, o c6digo de pais para a Suiga 6 "CH"), mas que a lingua 6 o italiano:
"CH");
// Italiano / / Suisa
dois locais em uma data poderia nos dar uma saida como estai
,.
Date d2 = c.getTimeO; Locale Locale Locale Locale locIT = locPT = locBR = l-oclN =
new Locale("it", new Locale("pt"); new Local-e("pt", new Locale("hi",
\\pDnI. \ T\TZ I
f Laffa
Portugaf
Brasil India
JAVA
269
DateFormat
DateFormat . FULL ) ;
);
dffT = DateFormat.getDatelnstance(
DateFormat.FULL, l-ocfT)
;
DateFormat.FULL, l-ocPT)
n1.'p^rfrraal '. + rlfp.n f^.lm^l-//lrl\v-t
I t
)
DateFormat.FULL, l-ocBR)
(d2) ) ;
dfIN = DateFormat.getDatelnstance(
DateFormat.FULL, locIN)
;
System.out.println("India "
+ dfTN.format (d2))
(
'
US 1,2/14/1,0
3:32
PM
US
ful1 Sunday, December l-4, 20L0 Italy domenica 14 dicernbre 2010 Portugal Domingo, 14 de Dezembro de Rrazil T)omincq, 14 de Dezembro de
Tnr{i: 2}2a?? 21 2?22?? t2?2
2010 2010
Japan
2010?12?1,4?
Opa! A nossa m6quina nio est6 configurada para dar suporte a locais da india ou do Japio, mas o obietivo do exemplo era mostrar com um mesmo objeto Date pode ser formatado para funcionar par^ v6rios locais.
nlnentl
que
da fapa isso!
Existem mais alguns m6todos em Locale (getnisplayCountry ( ) e getDispl-aylanguage ( ) ) que voc6 precisari conhecer para o exame. Esses m6todos lhe permitem criar Strings que representem o pais e a lingua de determinado local em termos tanto do local padrio quanto de qualquer outro local:
Locale locBR = new Locale("pt", "BR"); Locale l-ocDK = new Locale("da", "DK"); Locale loclT = new Locale("it", ., IT,,);
270
System,out.println("def " + focDK.getDisplaylanguage( ) ) ; Sysbem.out.println( "1oc " + locDK. getDisplaylanguagle (locDK) System.out.println( "Dtr " + 1ocDK.getDisplaylanguage (locrT)
Isso produz, em nossaJVM,
) )
; ;
Brazil
Brasi-1
Danish
dansk
D>I danese
Dado que o local da nossaJVM (o padrio, para n6s) 6 us @stados Unidos), o padrio pan o Brasil 6 "Brazil", e o padrio para a lingua dinamarquesa 6 "oanish". No Brasil, 6. claro, o pais se chama "Brasil " e, na Dinamarca, a lingua 3 chamada de "dansk". Finalmente, s6 por diverslo, descobrimos que, na Itilia, alingua
dinamarquesa 6 chamada de
"danese".
A Classe NumberFormat
Terminaremos este objetivo falando sobre a classe NumberFormat. Assim como a classe DateFormat, NumberFormat 6 abstrata, de modo que normalmente voc6 usar6 alguma versio ou de getlnstance ( ) ou de
getcurrencyf ns tance ( ) para criar um objeto NumberFormat. formatar nrimeros ou valores monetArios:
Nio
fLoat f1 = L23.4567f:
Locale locFR = new Locale('fr"); NuniberFormat[] nfa = new NumberFormat[4]; nfa [0] = NumberFormat. getrnstance ( ) ; nfa [1] = NumberFormat.get.Instance (locFR) ; nfa12) = NumberFormat.qetcurrencylnstance ( ) ; nfa [ 3 ] = NunlcerFormat . getcurrencylnstance ( locFR) for(NumberFormat nf : nfa)
qlrqlam arrf nrintlnlnf fnmal /f1 ) ). / / Er^rra
L23 .457
t23 ,45'7
>J_ZJ
.40
rz5 ,40 !
Nio
se preocupe se, como no nosso caso, o seu sistema nio estiver configurado para exibir os simbolos do franco, da libra esterlina, da rupia, do yen, do baht ou do dracma. Nlo ser6 esperado que voc6 conhega os simbolos usados para moedas: se voc6 precisar de um, ele seri especificado na questAo. Voc6 poder6 encontrar m6todos
diferentesdeformat noexame.Eisumpequenoc6digoqueusagetMaximr:rnFractionDigits(), setMaximurnFractionDigits ( ),parse ( ) e setParseTntegerhly( ) : float f1 = L23.45678f; NumberFormat nf = NunberFormat.getlnstance( ) ; System.out.print(nf .getMaximumFractionDigtits ( ) + " ") ; System.out..print(nf .format(f1) + " ";;
nf . setMaximrunFract ionDigits
(5
"1
JAVA
271
try
System.
("1234.567,, ) ) ;
nf . setParselntegeronly ( true ) ; System.out.println (nf .parse ( "1234. 567" ) ) ; ) catch (ParseException pe) { System.out.println( "parse exc" ) ;
J
3 I23.457 L23.45678
t234.567
t234
Repare que, neste caso, o nfmero inicial de digitos fracion6rios para o NumberFormat padrio 6 de trs, e que o m6todo format O arredonda o valor de f 1, emvez de simplesmente descaftar as casas decimais excedentes. Depois de modificar os digitos fracionirios de nf , o valor inteiro de f 16 exibido. Em seguida, repare que o m6todo parse ( ) deve rodar em um bloco try/caLch e que o m6todo setParserntegeronly ( ) usa um valor booleano e, neste caso, f.az as chamadas subseqiientes a parse ( ) retornarem apenas a parte inteira das Strings formatadas como nrimeros de ponto flutuante.
Como vimos, v6rias das classes abordadas neste objetivo sXo abstract. Al6m disso, para todas essas classes, a frrncionalidade principal de cada instAncia 6 estabelecida no momento da cria$o. A Tabela 63 resume os construtores ou m6todos usados para criar instAncias de todas as classes que discutimos nesta segio.
Tobelo 6-3 CrioEdo de lnstdncios poro os Principois Closses de iovo.text e de iovo.util
Classe Principais
ji
util
Date
new DateO; new Date (lonq milisegnrndosDesdeOlOl70) Calendar. geLlnstance ( ) t Calendar. getfnstance (Locale ),
Local-e
Locale. getDefault ( ), new locale (St.ring lingua) ; Ql-r'ina frrY new locale(String 'I inarra
naiq\ Y\4Av,
'
text . DateFormat
DateFormat. getlnstance ( ), DateFormat . getDatelnstance ( ) ; DateFormat . getDatelnstance ( estif o ) ; DateFormat. getDatefnsLance (esti1o, Loca]e)
NumberFormat. getlnstance ( ) NumberFormat . qetlns tance ( Locale ) NumberFormat . getNumberlns tance ( ) NumberPormat . getNumberf ns tance ( Local e ) NumberFormat . getcurrencyTnstance ( ) NumberFormat . getcurrencylnstance (Locale
text
NumberFormat
dos
pacotesjaua.atil e jaua.uti/.regexparafotwatar oufaryrparcing de $ings ou e Matcher e o mdtodo String.s?lxt, Reconhecer e asarpaddes de exprusdu
regularesparacorresponddncia(linitadosa:.(ponto),x(asteisco),+(nais),?,\/,\1,\r,[],0).Oasode+,*e?serilimitadoa
qaantifcadoresgananciosos, e o operadorpar4nteses serd audo @enas coml am mecanismo de agruparuento, e ndopara c@tararconteildo dtrante a determinagdo da correspond1ncia. Para streams, escreuer cddigo usando as classes Foraatter e Scanner e os mdtados
PrintViter.format/prinf.
Reconhecer e usarpardmetros
o/oc,
%d,
ohs)
en Stingt deformatos.
Formoioqdo e Porsing
Comegaremos com mais um aviso: esta pequena segio regex. Nesta segio, abordaremos tr0s id6ias bisicas:
de
I Encontrar coisas VocA tem montes de texto onde precisa procurar algo.Talvez esteja fazendo uma selegio de tela, talvez esteja lendo de um arquivo. De qualquer modo, voc6 precisa de maneiras ficeis para encontrar agulhas textuais em um palheiro tixtual. IJsaremos as classes java.regex.Pattern, java.regex.Matcher e java.util.Scanner para nos ajudar a encontrar coisas.
Tokenizar coisas VocA tem um arquivo delimitado do qual deseja extrair alguns dados riteis. VocA quer transformar um pedago de texto que se parece com "1500.00,343.77,t23.4" em algumas vari6veis float individuais. N6s iremos lhe mostrar os fundamentos do uso do m6todo String. split ( ) e da classe java.util.Scanner para
tokenizar os
seus dados.
r Formatar coisas VocA precisa criar um relat6rio e transformar uma variivel float com um valor de 32500.000f em uma String com um valor de "$32,500.00". N6s lhe apresentaremos a classe java.util.Formatter e os m6todos printf ( ) e format ( ).
Um Tutorial de Busca
pelo bisico.
Esteja voc procurando por coisas ou tokenizando coisas, muitos dos conceitos sio os mesmos, enteo comecemos Nio importa linguagem que voc6 esteja usando, mais cedo ou mais tarde provavelmente iri se deparar com a necessidade de realizar buscas em grandes quantidades de dados textuais, procurando por coisas especificas.
As express6es regulares (abreviadas como regex) sio um tipo de linguagem dentro da linguagem, elaboradas para ajudar os programadores nessas tarefas de buscas. Toda linguagem que fornece fung6es regex usa um ou mais mltnres regex. Os motores regex f.azem buscas atrav6s de dados textuais usando instrug6es que sio programadas em expressdu.IJma expressio regex funciona como um pequeno programa ou script. Quando voc6 chama um motor regex, voc6 passa a ele os dados textuais que quer processar (em Java, ser6 normalmente uma String ou um stream), e passa tamb6m a expressio que deseja usar para procurar nos dados.
E apropriado pensar em regex como uma linguagem, e nos referiremos a ela dessa forma ao longo desta segio. A linguagem regex 6 usada para criar express6es e, i medida que formos avangando nesta segio, sempre que falarmos sobre express6es ou sobre a sintaxe das express6es, estaremos falando sobre a sintaxe da "linguagem" regex. Ah, e mais um aviso: sabemos que os leitores especialistas em regex sio capazes de criar express6es melhores do que as que iremos apresentar. Tenha em mente que, no geral, estaremos criando essas express6es usando apenas uma parte do conjunto total de instrug6es regex, muito obrigado.
Buscas Simples
Para o nosso primeiro exemplo, gostariamos de buscar na seguinte Stringfonte
abaaaba
por todas
ab
as ocorrAncias
(ov con'eEondincia) da
expressdo
Em todas
as explicag6es, assumiremos que as nossas fontes de dados usam indices que comegam no zero, de modo que, se aplicarmos um indice )s nossa string fonte, obteremos
fonte: indices :
abaaaba 0i-23456
Podemos ver que temos duas ocorr6ncias da expressio ab: uma comegando na posigXo O e outra comegando na posigio 4. Se envi6ssemos esses dados-fonte e essa expressio para um motor regex, ele responderia nos dizendo que encontrou correspondncias nas posig6es 0 e 4:
imnarf iarr: rrt. i l .
regex.
{
x;
cl-ass Regexsmall
/ a expressdo / / a fonLe
/
JAVA
273
]
Isso produz:
04
iremos explicar esse c6digo imediatamentg. Daqui a algumas p6ginas, iremos lhe mosrar muitos outros c6digos reger, mas, primeiramente, queremos passar alguma sintaxe regex. Depois que voc6 entender um pouco mais sobre regex, os c6digos de e<emplo fario muito mais sentido. Eis um exemplo mais complicado de uma fonte e uma e4pressio:
Nio
fonte:
l_n(I]-ces
abababa
urz345b
express5.o: aba
Quantas ocorrencias teremos neste caso? Bem, claramentehi uma ocorr6ncia comegando na posigXo O, e outra comegando na posiEio 4. Mas e quanto )quela que comega na posigio 2? Em geral, no mundo regex, a string aba que comega na posigio 2 nio serh considerada uma ocorrdncia v6lida. A primeira regra geral de busca regex 6
Emgera/, uma basca regex roda da uquerdapara a direita
pode ser reatiliqado.
e,
e/e ndo
Assim, no nosso exemplo anterior, a primeira correspondAncia usou as posig6es 0, I e 2 para bater com a expressXo (outro termo comum para isso 6 que os tr6s primeiros caracteres da fonte foram consumidor). Pelo fato de o caracter da posigio 2 ter sido consumido na primeira correspondncia, ele nio p6de ser usado novamente. Entio o motor seguiu em frente, e nio achou outra ocorrAncia de aba at6 chegar i posigio 4. Essa 6 a maneira tipica como um motor de correspond6ncia regex funciona. Entretanto, daqui a algumas p6ginas, veremos uma excegio ) primeira regra que escrevemos acima.
exatas, mas o que fariamos se quis6ssemos encontrar algo um pouco mais dinimico? Por exemplo, e se quis6ssemos encontrar todas as ocorr6ncias de nrimeros hexadecimais, ou nrimeros de telefone. ou CEPs?
\d
Se modific6ssemos o
\d i
!,2,
o argumento
adiante.)
"\d"
do m6todo
compile,
transformando-o em
4, 6,7 e 8. (Se quiser tentar isso em casa, voc6 teri de "escapar" "\ \d", mas falaremos mais sobre isso logo
Regex fornece um rico conjunto de metacaracteres que vocA pode encontrar descritos na documentagio API para .|ava.util.regex.Pattern. Nio os discutiremos todos aqui, mas descreveremos aqueles de que voc6 precisari para o exame:
\d \s
\w
Umdigito
Um caracterde espago em branco
(Jm caracterde palavra (letras, digitos
ou
"-"
(underscore))
intervalos de caracteres a
fal-rcl Procrrra
:ncnas
[a-f] procura apenas pelos caracteres a, b, c, d. e ou f Al6m disso, voc6 po* procurar em diversos intervalos de uma s6 vez. A seguinte expresslo a- f ou A- F, mas NAO procura por uma combinagSo fa:
busca
por ocorrOncias
das
letras
a- fA-F
AO TRABALHO
Aldn
das
uocd
'^"
de
conjantos. Embora esrr,s clnstratlres ndo caiam flo exane, a c/asse jaua. ati /. regex.Pattern.
deles
txxl t0-9a-fA-Fl
seja
*f
um "0", o segundo
ser descrita como: "encontre um conjunto de caracteres no qual o primeiro caracter ou um 'x" ou um "xo, e oterceiro seja ou um digito de "0" a "9", ou uma letra de "a" o ou uma letra mairiscula de "A" a'F". tlsando a expressio anterior, e os seguintes dados,
(Observagio:
hexa v6lidos.)
se quis6ssemos apenas que regex encontrasse ocorrncias de nrimeros inteiros? Os inteiros podem ter um ou mais digitos, entio seria 6timo se pud6ssemos dizar "rrm ou mais' em uma expresslo. H6 um conjunto de construtores regex chamado de quantificadores, que nos permitem especificar conceitos tais como "um ou mais". Na verdade, o quantificador que representa 'um ou mais" 6 o caracter " + ". Veremos os outros em breve.
6 que,
quando estamos buscando por algo cuja extensio seja vari6vel, obter apenas uma
posigio inicial como valor de retorno tem pouco valor. EntXo, al6m de retornar posig6es iniciais, uma outra informagio que um motor regex pode retornar 6 a correspond6ncia inteira, ou o grupt, que encontrar. Modificaremos a forma como falamos sobre o que regex retorna, especificando cada retorno na sua pr6pria linha, lembrando que agora, para cada retorno, receberemos de volta a posigio inicial E depois o grupo:
01
J IZ
6 234
VocA pode ler isso como "na posigio 0 hi um numero inteiro com o valor de 1; depois, na posigao 3, hi um nrimero inteiro com um valor de 12, e depois, na posigio 6, h6 um nrimero inteiro com um valor de 234".Yoltando agora ao nosso problema com hexadecimal, a riltima coisa que precisamos saber 6 como especificar o uso de um quantificador para apenas uma parte de uma expresseo. Neste caso, precisamos ter exatamente uma ocorrAncia de 0x ou 0X, mas podemos ter de uma a muitas ocorr6ncias dos "digitos" hexa que se seguem. A seguinte expresseo adiciona par6nteses para limitar o quantificador '+ " a apenas digitos hexa:
0
[xx] ( t0-9a-fA-Fl
)+
Os parOnteses e " + " ampliam a expressio anterior ao dizer, na priltica "Depois que acharmos o nosso 0x ou 0X, voc6 poder6 encontrarde uma a muitas ocorr6ncias de digitos hexa". Repare que colocamos o quantificador "+" no final da expresslo. E 6til pensar nos quantificadores como estando sempre quantificando a parte da expressio que os Preceoe.
*
?
JAVA
275
Digamos que voc6 tenha um arquivo de texto contendo uma lista, delimitada por virgulas, de todos os nomes dos arquivos- em um diret6rio que contenha virios projetos importantes (a prop6sito, nio 6 assim que n6s organizariamos nossos diret6rios!). VocA deseja criar uma lgta de todos os arquivos cujos nomes comecem com pro j 1. Voc6 poderi e.ncontrar arquivos .tYE, .java,.pdf, quem sabe? Que tipo de expressio regex n6s poderiamos criar paraencontrar esses diversos arquivos proj 1? Primeiramente, vamos daruma olhada em.o-o poJeria ser uma parti desse texto:
. . . "proj3.
txt,projlsched.pdf ,projI,proj2,projl .
1ava" . . .
Para resolver esse problem4 iemos usar o operador regor ^ (circwrflexo), o qual mencionamos anteriormente. O operador regex nlo cai no exame, mas ele nos ajudari a criar uma solu$o ideal para o nosso problema. O ^ 6 o simbolo de negaSo em rego<. Por o<emplo, se quiser encontrar nrdo, exceto letras 4 b e c em um arquivo, voc poderia usar
[
^abc
Entio, armados com o operador ^ e o quantificador * (nenhum ou mais), podemos criar o seguinte:
projl([^,])*
Se
aplicarmos
lll nr^r
essa
expressio apenas ao pedago do arquivo de texto que listamos acima, o regex retorna
ndf
le.ha.l
25
projl
A principal parte dessa expressio 6 a que diz"me retorne zero ou mais caracteres que nio sejam urna virgula." O riltimo exemplo de quantificador que iremos ver 6 o ? (um ou nenhum). D,igamos.que.a nossa tarefa agora se1.a . procurar, em um arquivo de texto, por qualquer coisa que possa ser um nimero de telefone local, com sete digitos.
Iremos dizer, arbitrariamente, que, se encontrarmos ou sete digitos em seqiiAncia ou tres digitos seguidos de um hifen (ou um espago) seguido de outros quatro digitos, entio temos um candidato. Eis alguns exemplos de
nrimeros de telefone "vilidos":
r234567
),23
456'7
123-4567
A chave para
se criar essa expressio 6 perceber que precisamos de "uma ou nenhuma ocorr6ncia ou um espago ou um hifen" no meio dos nossos digitos:
\d\d\d( [-\s]
?\d\d\d\d
vimos, voc6 tamb6m precisar6 entender o metacaracter "." (ponto). Quando vir esse caracter em uma expressio regex, ele significa "qualquer caracter serve". Por exemplo, a seguinte fonte e o seguinte padrio
3 abc 7 ac
O "." foi
capaz de
encontrar tanto o
"b"
guanto o
"
Quantificadores Gananciosos
Quando voc6 usa os quantificadores '!, + e ?, 6 possivel ajust6Jos mais detalhadamente para produzir um comportamento que 6 conhecido como "ganancioso", "relutante" ou "possessivo". Embora voc6 precise entender apenas o quantificador ganancioso para o exame, iremos apresentar tamb6m o quantificador relutante para servir de base para comparagio. Primeiramente a sintaxe:
?6
ganancioso,
?? 6
+ 6 ganancioso, + ? 6 relutante,
padrio: . *xx
Primeiramente, estamos {azendo algo um pouco diferente aqui, ao procurarmos por caraceres que ajam como prefixo da pane est6tica 0o<) da expresslo. Acreditamos que estamos dizendo algo como: "encontre conjuntos de caracteres que
276
terminem com xx". Antes de lhe dizermos o que acontece, queremos que voc6 pelo menos considere que existem
dois resultados plausiveis... ser6 que voc6 consegue dizer quais sio eles? Lembre-se de que dissemos anteriormente que, em geral, os motores regex atuam da esquerda para a direita e que eles consomem os caracteres ) medida que os usam. Assim, trabalhando da esquerda para a direita, poderiamos prcver que o motor buscaria os quatro primeiros caracteres (0 - 3), encontraria xx comegando na posigio 2, e teria ai a sua primeira correspond6ncia. Entio, seguiria em frente e encontraria o segundo xx comegando na posigio 6. Isso nos levaria a um resultado como este:
0 yyxx 4 xyxx
lJm outro argumento plausivel 6 que, uma vez que pedimos um conjunto de caracteres que termine com xx, poderiamos receber um resultado como este:
yyxxxyxx
A maneira como pensamos nisso 6 considerando o adjetivo ganancioso. Par.a Qye. a segunda resposta esteja correta, o motor regex teria que olhar (gananciosamente) em todo o conjunto-fonte de dados para poder determinar que havia um xx no final. Entlo, na realidade, o segundo resultado 6 o correto, porque, no exemplo original, n6s usamos o quantificador ganancioso 's. O resultado que encontra dois conjuntos diferentes pode ser gerado usando-se o
quantificador relutante *?. Novamente:
com o resultado
0 llzxxxyxx
Se
fonte:
l44xxxyxx
padrSo: . *?xx
agora estaremos usando o quantificador *?, e receberemos o seguinte:
0 yyxx
4 xyxx
O quantificador ganancioso de fato 16 todo o conjunto-fonte dos dados, e depois volta (procuradadireitaparaa esquerda) at6 achar a corresponddncia mais i direita. Nesse momento, ele inclui tudo o que existir nos dados-fonte at6 (e incluindo) os dados que fazem pane da correspond6ncia mais ) direita.
AO TRABALHO
Exixem maitos outms
para o exame.
aspectos referentes a quantifcadores regex do qlrc 0s qtle discutimos aqut, rzasj,i abordamos mais do qae o rufciente Sun ten diuersos tutoriais que lbe ajudardo a aprender mais sobre os quantificadoru e a tomd-/o o guru em quantficadores
linhade c6digo nio vai compilar! O compiladorvO a barra\ e pensa "ok, 16vem umaseqii6nciade escape ,talvezseja uma nova linha!" Mas nio 6 isso, em seguida vem o d e o compilador diz 'nunca ouvi falar de uma seqiiAncia de escape \d'. A maneira de satisfazer o compilador 6 adicionar uma outra barra invertida na frente de \d:
um
A primeira barra invertida dv ao compilador que tudo o que vier em seguida deve ser interpretado literalmente, e nio como uma seqiiAncia de escape. E quanto ao metacaracter ponto Q? Se quisermos usar um ponto na nossa expressio como um metacaracter, sem problemas, mas e se estivermos lendo alguns dados-fonte que por acaso usem ponros como delimitadores? Eis uma outra forma de estudar as nossas opg6es:
Stringp=\\.',;//oregexv6issocomoometacaract
ef-.i-^ vulJrrY h v \r\ \.
uma
JAVA
277
/,/ seqr.i6ncia de escape invelida em \lava // o compilador fica feliz, e o regex ve um // ponto, e nao um metacaracter
passar metacaracteres a um programa Java por meio de argumentos de linha de comando. Se quisermos passar o metacaracter \d para o nosso programa java, a nossa JVM faz a coisa certa se dissermos
AO TRABALHO A
linguagen Jaua defne diuersas seqii1ncias de uc@q inclaindo
\n = \b = \t =
E
linerted (que
backspace
uocd
poderi enczfrtrar no
exame)
tab
ndo precisard
oilras, que uocd poderi encontrar na Etpecifcagdo da Linguagen Jaua. Fora uma euentual apaipdo dc um v preocupar com seqi.i4ncias de ucape Jaaa no exame.
\n
dentro de
Neste ponto, ji aprendemos o suficiente sobre a linguagem regex para comegar a us6-la em nossos programasJava. Comegaremos e$udando o uso de express6es regex para encontrar coisas, e depois passaremos para um t6pico intimamente relacionado, que 6 o de tokenizar coisas.
vod
(Matcher)
public static void main(String [] args) Pattern p = Pattern.compile (args [01 ) ; Matcher m - p.matcher(args [1] ) ; boolean b = false;
q\rcl-6m
vJ v eer!! t
drrl-
nrinl-lrl\DAl-l-arn
i<
\ +m
nal-tarnl\\.
]
programa usa o primeiro argumento de linha de comando (args t 0 J ) para representar a expresslo regex que voc6 deseja usar, e usa o segundo argumento (arqs [ 1 J ) para representar os dados-fonte em que voc6 deseja procurar. Eis uma execugeo de teste:
Esse
FormotoE6o e Porsing
(Lembre-se de se voc6 quisesse ter essa expressio representada em uma String, use \ \d\ \w) . Pelo fato de que. ireqiientemente ter6 car"cte.es especiais ou espago, .m bmnco como parte dos setrs argumentos, provavelmente 6 uma boa id6ia que voc6 se habitue a sempri colocar seus argu-entos entre aspas. Vamos dar uma olhada no c6digo com-mais detallres. Primeiramente, perceba que nio estamos usando new para cri ar umPattern: se voc6 verificar a API, nio encontrar6 quaisquer conitrutoreJlistados. Voc6 usarl o m6todo est6tico sobrecarregado.compile ( ) (que usaString e>pressio;) para criar uma instAncia de Paftern. Para o exame, tudo o que voc6 precisari saber para criar um Matcher 6 usar o m6todo Pattern . matcher ( ) (que usa String sourceData)'
Om6todomaisimportantedesteprograma6tinaO.Esse6om6todoquedefatoiniciaomotorregexerealizaa busca. O m6todo f inO ( ) retorna true caso ache uma correspondAncia, e memoriza a posigio inicial dessa correspondAncia. Se f ind O retornar true, voc6 pode chamar o m6todo start ( ) para obter a posigXo inicial da correspond6 ncia, e pode chamar o mbtodo group ( ) para obter a string que representa o pedago propriamente dito dos dados que foi encontrado como correspondOncia.
AO TRABALHO
(Jm motiuo clmum para
exame,
uoc deueni
nber que a
appendReplacement
),
i para realiqar operagdes de busca e substitaipdo. Embora as operagdu de nbstitaipdo ndo caiam no Matcherfomece diuersos ndtodos qae realiqan operagdu de busca e de substituipio. Consulte os mitodos appendTail ( ) e O na API d.e Matcberpara nais detalbes.
replaceAll
a classe
que falaremos em seguida), ela pode tamb6m ser usada para encontrar coisas, assim como as classes Pattern e Matcher. Embora Scanner nio fornega informagSes de localvaglo nem recursos de busca e substituigio, vocA pode us6-la para aplicar express6es regex a dados-fonte para the dizer quantas instAncias de uma expressio existem em determinado conjunto de dados. O seguinte programa usa o primeiro argu.mento de linha de comando como uma expressio regex, e depois pede
por input usando System . in. Ele exibe uma mensagem sempre que uma correspond6ncia| encontrada:
imnnrliarra rrf il *.
System. out
flush
Lrv
Scanner
ql-ri
s = new Scanner(System.in)
.
hd t-^Lah
do{
token = s.findlnl,ine(args[0] ); System. out.println ( "f ound " + token) ,' ) while (token t= null); ) catch (Exception e) { System.out.println("scan exc");
]
Achamadaeoinput
.i
nnrrts.
1l^t^"aqf456
produzem o seguinte:
Tokenizagio
A tokenizagio
6 o processo de se pegar grandes pedagos de dados-fontes, dividi-los em pedagos pequenos e armazenar esses pedagos pequenos em variiveis. Provavelmente, a situagao mais comum de tokenizagio 6 a leitura de um arquivo delimitado para se ter o contefdo do arquivo movido para dentro de lugares iteis, tais como
JAVA
279
2bjetgs' (usando
o mtodo
arrays ort conjuntos. Estudaremos as duas classes da A?I que fornecem recursos de tokenizagio: String split ( )) e Scanner, que possui muitos m6rodbs tteis para a tokenizagio.
Tokens e Delimitadores
Quando-falamos em tokenizagio, estamos falando de dados que, no inicio, sio composros de duas coisas: tokens e delimitadores. Os tokens sio os pedagos propriamente ditos dos^daios, e os deiimitadore^s sio as express6es q ve rfiaram os tokens uns dos outros.. Quando. muitas peisoas pensam em delimitaiores, elas pensam em caractires ir"l"ior, Jo*o dtCT, 9" ba'as invertidas, ou talvez em 6nico espago em branco. Na-v-erdade, co^mo dro*"t i*pli.ii;d;;; fiA d;;r, os delimitador,es godeq ser qualquer coisa que seria capaz de qualificar como uma expressi6 ,.g.*."V"*oi prg"i um contunto de dados-lonte e realizar tokenizagio nele, usando diversos delimitadorei:
fonte:
Se
24,,
dissermos que o nosso delimitador 6 uma virgula, enrao os nossos quatro tokens serio
ab
cd5b
6x
z4
Se usarmos a mesma
fonte, mas declararmos nosso delimitador como sendo \d. obteremos tr6s tokens:
ab. cd
]a
x,z
Em geral, quando tokenizamos dados-fonte, os delimitadores sio descartados, e tudo o que nos resta sAo os tokens. Assim, no segundo exemplo, definimos os digitos como delimitadores, de forma-qu e 5, 6 e 4 nio aparecem nos tokens finais.
Tokenizando com String.splitQ O m6todo split ( ) da classe String usa uma expressio regex como
o seu argumento, e rerorna um array String preenchido com os tokens produzidos pelo processo de divisio (ou tokenizagio). Essa 6 uma forma ritil de tokenizar pedagos relativamente pequenos de dados. O seguinte programa usa args [ 0 ] para armazenar uma string-fonte, e args [ 1] para armazenar o pa&io regex a ser usado como delimitador:
imnnrf
Jsws.sLfr.
iarzr
rrtsi I
x.,
class SplitTest { public static void main(String[] args) { String[] tokens = argst0l.split(args[]-l ); System.out.println( "count " + tokens. length) for(String s : tokens) System.out.println(s>/ + s + "<"),'
]
Tudo acontece de uma s6 vez quando o m6todo split ( ) 6 chamado. A string-fonte 6 dividida em pedagos, que sio carregados no array de Strings chamado tokens. Todo o c6digo depois disso s6 estSli para verificar o que a
operaglo de divisio gerou. A seguinte chamada
t java SplitTest
produz
count
>ab<
>ccc<
>@<
"\\\\d".)
(ObservagXo: lembre-se de que, para representar "\' em uma string, voc6 poderi ter de usar a seqii6ncia de escape do seu SO, o seu segundo argumento poder6 ter de ser "\ \ d" ou at6 mesmo
voc6 desejarl ver os tokens no ter criado os momento em que est1o sendo produzidos, e, possivelmente, interromper uma operaEio grande arquivo-. Se esse nrimero tokens de que p*.ir". Po, ex.mplo, .ro.6 pod"ri" buscar um nrimero de telefone em um seu nimero' 1ogo ,ro inicio do arquivo, voc6 gistaria de poder fin alivar o processo de tokenizaElo logo que obtiver
IJm inconveniente de
o m6todo
de tokenizagXo ap6s
oBSERVAQ6ESpeneoE)(AME
Pelofan /e
rcrumdo com lantafeqiilncia no examq uoc|podenl uerexenplos de rcqiidncias de escape nisimdas en qawtdes de praticamente qualquer t6pico, inclaindo regex. Itmbre-u fu que, n precisar criar uma String qae contenba aspas
System. out.printJ.nO
de adicionar
un
caracter de ur@e
pimeiro:
En
uociprecisarpmwrarpnrpontos (.) nls seus dados-fonte? Se sinp/esmente co/ocar o ponto na exprvssdo regex, aod obteri o comportuhentu "quolqar ioroitrr". E se uoc6 tentar\.,-entdo? Agora o compiladnr Jaua acba que uocl estd tentando criar ana teqiidncia
etcape qae ndo existe.
de
java.util.Scanner
essa
Scanner-
String . split
( ) , a classe
r r r
Scanners podem ser construidos usando-se arquivos, streams ou Strings como fontes.
AtokenizaEio|reahzadadentrodeumloop,paraquevocOpossafinalizaroprocessoaqualquermomento.
Os tokens podem ser convertidos automaticamente para os seus tipos primitivos apropriados.
Vejamos um programa que demonstra diversos m6todos e fung6es de Scanner. O delimitadorpadrlo de Scanner 6 o espago em branco, que 6b que este programausa. O programa cria dois objetos Scanner: s1, sobre o qual6 feita umaiteragio com o m6todo mais gen6rico next ( ) , o que retoina todos os tokens na forma de String, enquanto que s2 6 analisado com v6rios dos m6todos especialidos nextxxx ( ) (onde xxx 6 um tipo primitivo):
import java. uti1. Scanner; class ScanNext { public static void main(String [] args) boolean b2, b; int i; String s, hits Scanner s1 = new Scanner(args[0] ); Scanner s2 = new Scanner(args[0] ); while(b = sL.hasNextO) { s = sl.next0; hits += \s"-
i while(b = s2.hasNextO) { if (s2.hasNextlntO) { i = s2.nextfntO; hits += !\i"; ) else if (s2.hasNextBooleanO) { b2 = s2.nextBooleanO; hits += *b"; 1 else { s2 .next ( ) ; hits += \\s2" ;
)
JAVA )
28I
Se esse
produziri
hits ssssibis2
E claro que nio estamos fazendo nada com
sio convenidos para os
os tokens depois de os obter, mas voc6 pode ver que os tokens de s2
seus respectivostipos primitivos-. lJm ponto fundamental 6 m6todos "q"i chamados hasNextXxx ( ) testam o valor do pr6ximo token, mas neo o obtm realmenti, nem se movem para o pr6ximo token nos dados-fonte. Todos os m6todos nextxxx ( ) realizam duas fung6es: obtdm o pr6ximo t6ken, e
q.tt
A classe Scanner tem m6todos nextxxx o (por exemplo nextlong o ) e hasrexLxxx o (por exemplo hasNextDouble ( ) ) para todos os tipos primitivos exceto char. Al6m disso, a classe Scrnn.r te* .rh m6todo useDel imi ter ( ) que lhe permite definir o delimitador como qualquer expressio regex v6lida.
Nosbastidores,om6todo
formatO usaaclassejava.utif .Formatterpar^f.azerotrabalhopesadode a classe Formatter diretamente se quiser, mas, para o exame, tudo o que precisari
saber 6 a sintaxe b6sica dos argumentos que vocA passa ao m6todo f ormat O . A documentagio parJesses argumentos de formatagio pode ser encontrada na API de Formatter. Iremos apresentar brevemente a sintaxe para formatagio de Strings, o que ser6 mais do que suficiente para permitir que voct realize diversas tarefas de formatagio E gabarite todas as quest6es de formatagio do exame.
Vamos comegar parafraseando a documentagio API para formatagio de strings (para uma abordagem mais completa, muito mais completa do que voc6 precisa para o exame, consulte a API de java.util.Formarter):
argumento (s) ) ;
se voc6
A string de formatagio pode conter tanto informag6es de strings literais dados de formatagio especificos de argumentos. A dica para determinar
nXo-associadas com argumentos quanto esti olhando para dados formatados 6 que estes sempre comegam com um simbolo de porcentagem (o/o). Vejamos um exemplo, e nlo entre em pAnico, explicaremos tudo o que vem depois do o/o em seguida:
456 + ]-23
Vejamos o que acabou de acontecer. Dentro das aspas duplas hi uma string de formatagio, depois um +, e depois uma segunda string de formatagio. Repare que misturamos literais com as strings de formatagXo. Vamos agora mergulhar um pouco mais fundo e observar a construgio das strings de {ormatagio:
obrigat6rios de uma string de formatagio sio o 7o e um caracter de conversio. No exemplo acima, os rinicos valores opcionais que usamos foram para indexagiodeargumentos.O2grepresentaosegundoargumento,eo 1$ representaoprimeiroargumento(reparequenio tem problema em trocar a ordem dos argumentos). O d depois dos argumentos 6 um caracter de conversio (mais ou menos o tipo do argumento). Eis um resumo dos elementos das strings de formatagXo que voc precisari conhecer
Para o exame:
* larg_index$] [flags] [width] [.precision] conversion char Os valores dentro de [ ] sio opcionais. Em outras palavras, os rlnicos elementos
arg-index
nessa posigio.
flags
282
r "-" Justifica o argumento ) esquerda ! "+" Inclui um sinal (+ ou -) com este argumento I '0" Preenche os vazios deste argumento com zeros I '," lJsa separadores de agrupamentos especificos do local (ou seia, a virgula em 123,456) I "(" Coloca nfmeros negativos entre parnteses width Este valor indica o ndmero minimo de caracteres a serem exibidos (se quiser ter colunas
organizadas e bonitas, voc6 usari este valor o tempo todo).
bem
precision
,r,t*..or,
Para o exame, voc6 s6 precisar6 disto ao formatar um nimero de ponto flutuante e, no caso desses precision indica o ndmero de digitos a serem exibidos depois do ponto decimal' que voc6 est6 formatando. Os que voc6 precisa conhecer:
I I f r I
System.out. format ( ">%+-7d< \n", j.2) ; System.out.printf(">%2$b + t1$5d< \n", i1-, false);
Isso produz:
>
(123)<
<
>01,2,345<
>+12345
>false +
-123<
( para ajudar a demonstrar como funcionam as larguras minimas, os Q.,l6s adicionamos os literais ) e preenchimentos com zeros e o alinhamento). Finalmente, 6 importante lembrar que, se voc6 definir tipos diferentes para o tipo especificado no seu caracter de conversio e para o seu argumento, receber6 uma excegio de tempo de execugio:
System.out. format ( "%d", L2.31
Isso produz algo como
;
. 11
legalFormatConversionEx-
Strings
classe StringBuilder foi adicionada em Java 5. Ela tem exatamente os mesmos m6todos que a antiga classe StringBuffer, exceto pelo fato de os m6todos de StringBuilder nlo serem seguros em relagio aos threads. Por esse motivo, os m6todos de StringBuilder tendem a rodar mais ripido do que os de StringBuffer, portanto, escolha StringBuilder sempre que os threads nio forem uma preocupagio. Tanto os objetos StringBuffer quanto os StringBuilder podem ter os seus valores modificados virias vezes, sem que se precise criar novos objetos. Se voc6 estiver manipulando muitas strings, esses objetos serio mais eficientes do que objetos String imutlveis, que sXo mais ou menos "usados uma vez, mantidos na mem6ria para sempre". Lembre-se de que esses m6todos senptt modificam o valor do objeto chamador, mesmo sem nenhuma atribuiglo explicita.
JAVA
283
Lembre-se de que os objetos do tipo File podem representar arquivos ou diret6rios, mas, at6 ou mkDir ( ) , ;inda n{o tericriado nada ,ro i.., disco rigido. As classes do java.io foram elaboradas para serem encadeadas. Raramente voce utilizar| um FileReadei ou File\Triter Pacote sem os "encapsular' em um objeto BufferedReader ou Buffered\7rirer, o que the d6 acesso a m6todos mais poderosos, de nivel mais alto. Em Java 5, a classe Print\X/riter foi aprimorada com m6todos append. ( ) f or, mat ( ) e printf ( ) mais avangados, e quando voc0 os usa em combinagio com os novos construtores, os quais lhe-permitem criar PrintrVriters diretamente do nome de uma String ou de um objeto File, 6 possivel qrr" .rro.6 rrr" Buffer\(riters com bem menos freqiiAncia. que voc6 chamg
E/S de
arquivos
createNewFile ( )
Serializagio A serializagio lhe permite salvar, distribuir e restaurar tudo o gue vocd precisa saber sobre um objeto ativo. E quando o seu ob.ieto aponta para outros objetos, eles sio salvoi tamb6m. As classes java.io.ObjectOutputStream e java.io.ObjectlnputStream sio usadas para serializar e deserializar objetos. Normalmente voc6 os encapsulari em instlncias de FileOutputstream e FilelnputStream, respectivamente.
O principal m6todo que voc6 chama paraserializar um objeto 6 writeobj ect ( ) e,par^deserializar o objeto, use readMethod ( ) . Para serializar um objeto, ele precisa implementar a intertace Serializable. Marque as vari6veis de
instlncias com transient caso voc6 nio queira que o estado delas entre no processo de serializagio. Voc6 pode ampliar oprocesso de serializagloparaasuaclasse implementandowriteobject O e readobject O. $ ofrzcr, uma chamada a def aultReadObj ect O e a d.efaultWriteobj ect O inserida ir| curdar das tarefas normais de serializagio, e voc6 poderi ampliar essas chamadas com leituras e escritas manuais no stream.
Se
uma superclasse implementar Serializable, entao todas as suas subclasses tamb6m o fazem. Se uma superclasse nio implementar Serializable, entXo, quando um objeto da subclasse for deserializado, o construtor unserializable
da superclasse 6 executado - tenha cuidado! Finalmente, lembre-se de que a serializagio diz respeito ls instAncias, de modo que as variiveis estiticas nio sio serializadas.
e que voc6 terA de entender os fundamentos de cinco classes relacionadas: java.util.Date, iava.util.Calendar, java.util.Locale, java.text.DateFormat e java.text.NumberFormat. Um Date 6 o nrimero de milisegundos desde 1o. de janeiro de 1970, armazenado em um long. A maioria dos m6todos de Date for depreciado, entio use a classe Calendar para as suas tarefas de manipulagio de datas. Lembre-se de que, para criar instAncias de Calendar, DateFormat e NumberFormat, vod precisa usar m6todos esr6ticos de fibica, como getlnstance ( ) . A classe Locale 6 usada com DateFormat e NumberFormat para gerar uma drie de estilos de saida que sio especificos a uma lingua e / ou um pais.
Parsing, Tokenizagio e Formatagio Para encontrar panes especificas de dados em grandes fontes, Java fornece
diversos mecanismos que usam os conceitos de express6es regulares (regex). As express6es regex podem ser usadas com as classes Pattern e Matcher do pacote java.util.regex, e tamb6m com java.util.Scanner e com o m6todo ( ) . Ao criar padr6es regex, voc6 pode usar caracteres literais para a combinagio ou pode usar metacaracteres, os quais lhe permitirio achar corresponddncias para conceitos como "encontre digitos" ou "encontre espagos em branco". regex fornece quantificadores que the permitem emitir comandos como "encontre uma ou mais destas coisas em seqii6ncia". Voc6 nio precisar6 entender os m6todos de Matcher que facilitem a substituigio de strings nos seus dados.
String. split
Tokenizar 6 dividir dados em pedagos delimitados. Os delimitadores normalmente sio simples virgulas, mas podem ser tao complexos quanto qualquer outro padrio regex. A classe java.util.Scanner fornece capacidades completas de tokenizaglo usando-se regex, e permite que voc6 tokenize em um loop, para que possa interromper o processo a qualquer momento. String. split ( ) permite o uso de padr6es regex completos para tokenizagio, mas esse processo 6 feito em um passo, de modo que grandes fontes de arquivos podem levar um longo tempo para serem processadas.
A formatagio
novosm6todosdePrintStream, formatO eprintf O. Lembre-sedeque formatO eprintf Ose componam de forma similar. Para usar esses m6todos, voc6 cria uma string de formatagio que 6 associada com
todos os dados que voc6 deseja {ormatar. VocA precisari entender o subconjunto de conveng6es de strings de formatagio que abordamos no capitulo, e teri de lembrar que,se a sua string de formatagio especificar um caracter de conversXo que nio corresponder aos seus dados, ser6 langada uma excegio.
de dados para saida pode ser feita usando-se a classe Formatter, ou mais comumente usando-se os
Exercicios rdpidos
Aqui estio alguns dos pontos principais dos objetivos para certificagio
deste capitulo.
E E E
El
as
voc redirecionar a referAncia a uma String para uma nova String, o objeto String anterior pode ser perdido.
Os m6todos String usam indices iniciados em zero, exceto para o segundo argumento de
substring (
classe String 6 f
fl fl tr
ao pool. Quando uma String literal for encontrada pela VM, ela seri adicionada As Strings tpm um m6todo chamado length ( ) e os arrays tem um atributo chamado
lengLh.
A API
API
D E Todos os seguintes itens aplicam-se a StringBuffer e a StringBuilder: E Os StringBuffers sio alteriveis - eles podem ser alterados sem a criaglo de um novo objeto.
El
Os m6todos StringBuffer atuam sobre o objeto chamador, mas os objetos podem ser alterados sem uma atribuigio explicita na instrugXo.
StringBuilder nXo s5o sincronizados Para seguranga de threads. Os m6todos de StringBuilder deverio rodar mais ripido do que os de StringBuffer.
tr E E
D
O m6todo equals
( ) de StringBuffer
encadeados
nio 6 sobrescrito;
ele
M6todos String que voc6 deve memorizar: charAt O , concat O, equalslgnoreCase O length O, replace ( ) , substring ( ) , tolowerCase ( ) , toString ( ) , toUpperCase ( ) e trim ( ') .
MdtodosdeStringbufferquevocdevememorizar:appendO,
toString
deleteO,insertO, reverseO
().
As classes de java.io que vod precisa entender sXo File, FileReader, BufferedReader, File\7riter, Buffered\(/riter e
PrintVriter.
D Um novo objeto File nio significa que h6 um novo arquivo no seu disco rigido. tr Objetos File podem representar um arquivo ou um diret6rio. D A classe File lhe permite gerenciar (adicionar, renomear e apagar) arquivos e diret6rios. O Os m6todos createNewFile ( ) e mkDir ( ) adicionam entradas ao seu sistema de arquivos. fl File\Writer e FileReader sio classes de E/S de baixo nivel. VocA pode us6-las para escrever em arquivos e 16los, mas normalmente elas devem ser encapsuladas.
fl E E E
O
(esse 6
eader em
bastante comum'encapsular" um BufferedVriter em um FilelW'riter, para se ter acesso a mdtodos de nivel mais alto (mais convenientes).
de Java 5 eles
PrintVriters podem ser usados para encapsular outros \ilflriters mas, a partir diretamente apartir de Files ou Strings. OsPrintrVritersdeJava5t6mnovos m6todos appendO, format ( )
eprintf
O.
Serializagio (Objetivo 3.3) D As classes que voc6 precisa entender esteo todas no pacote java.io;
incluem: ObjectOutputStream e ObjectlnputStream principalmente, e FileOutputStream e FilelnputStream, porque voc as :utilizar| para criar streams de baixo nivel para serem usados pelas classes ObjectXxxStream. As
classes
E tr E E E 0
precisam implementar a interface Serializable para que os seus objetos possam ser serializados. objetos, e o m6todo
O m6todo
Se
transient.
ela
VocA pode ampliar o processo automitico de serializagio de uma classe implementando os m6todos
writeObjectO ereadObjectO.Seofizer,aschamadasinseridasparadefaultWriteObjectO
defaultReadObject
Se
),respectivamente, cuidarlodapartedaserializa$oqueacontecenormalmente.
as suas subclasses
tamb6m
implementam automaticarnente.
Se uma superclasse nio implementar Serializable, entio, quando um objeto constnrtor da superclasse sera executado.
da subclasse
JAVA
285
E E D tr fl D tr E
DatalnpudtreameDauOutputStream,naverdade,nlocaemnoenamgapaardoqueatiescritonosobjetivos&Stm.
java.text.NumberFormat e java.util.Locale.
Os objetos Date sio uma esp6cie de ponre entre as classes Calendar e Locale. Calendar fornece um poderoso conjunto de m6todos para manipulagio de datas, para realizar tarefas como obter dias da semana, ou adicionar determinado nirmero de meses ou anos (ou outros incrementos) a uma data.
(getrnstance ( )).
Os m6todos de Calendar que voc6 deveri entender slo add ( ) , que lhe permite adicionar ou subtrair virias partes (minutos, dias, anos e assimpordiante) dedatas, e ro11 O, guefuncionacomo ad.d ( ), masnio incrementa as partes maiores de uma data (por exemplo: adicionar 10 meses a uma data de outubro modi{ica o m6s para agosto, mas nio incrementa o valor do ano de Calendar).
InstAncias de DateFormat sio criadas usando-se m6todos estiticos de fibrica
E B E tr D E E
(getrnstance
getDatelnstanceO ) .
Existem diversos "estilos" de formatagio disponiveis na classe DateFormat.
Os estilos de DateFormat podem ser aplicados a diversos Locales para se criar uma s6rie de saidas para determinada data.
6 usado para se
classe
Tanto objetos DateFormat quanto NumberFormat podem ser construidos com um Locale especifico
imutivel.
Para o exame, vocA deveri entender o processo de criaglo de Locales usando-se linguas ou uma combinagio de
lingua e pais.
D
f,l Q
regex 6 uma abreviaEio de express6es regulares, que sio padr6es usados para se procurar por dados dentro de grandes fontes de dados. regex 6 uma sublinguagem existente em Java e em outras linguagens (como Perl). regex lhe permite criar padr6es de busca usando caracteres literais ou metacaracteres. Os metacaracteres lhe permitem procurar por dados ligeiramente mais abstratos, como "digitos" ou "espago em branco". Estude os metacaracteres
em seqiincia".
E fl E E
D D
(ponto).
regex fornece quantificadores que lhe permitem especificar conceitos como: "Procure por um ou mais digitos Estude os quantificadores gananciosos ?, 't e Lembre-se de que os metacaracteres e Strings
String s = "\\d";
As
classes
),patternO, findO,
J tr
Voc6 pode usar java.util.S canner patafazcr buscas regex simples, mas o objetivo original dessa classe
tokenizagio.
f,l A tokenizagio 6 o processo de se dividir dados em pequenos pedagos delimitados. D Na tokenizaglo, os dados que vocA deseja dividir sXo chamados tokens, e as strings que separam os tokens seo
chamadas de delimitadores.
0 tr
a classe Scanner
ou com
String. split ( ).
Os delimitadores sio caracteres rinicos, como virgulas, ou entAo complexas express6es regex.
lhe permite tokenizar dados de dentro de um loop, o qual lhe permite interromper a operagio sempre que quiser.
classe Scanner
E I
D
O m6todo String. split ( ) tokeniza toda a fonte de dados de uma s6 vez, de modo que grandes quantidades de dados podem levar um longo tempo para serem processadas.
Existem dois m6todos novos em Java para formataglo de dados. Esses m6todos sio f ormat ( ) Eles se encontram na classe PrintStream, da qual o out de System. out 6 uma instlncia. Os m6todos f
e
print f O
ormat ( )
O A formataglo O O
printf ( ) tAm funcionalidades indAnticas. de dados com print.f ( ) (ou f ormat ( )) 6 realizada usando-se
e
sio
primitivos ou strings.
as suas
O m6todo f ormat
( ) lhe
strings de formatagXo.
es
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:
4.234
B. 334
c.2334
D.01-23456
E. 01-234456 F. 12334567
G. A compilaglo falha.
PlayerO { System.out.print("p") ; l
)
JAVA
287
class CardPlayer extends player implements Serializable { CardPlayerO { System.out.print.(..c,,) ; } public static void main(Stringtl args) { CardPlayer c1 = new CardplayerO; trY I FileOutputstream f os = new Fileoutputstream(..p1ay.txt,') Objectoutputstream os = new Objectoutputstream(fos) ; os.writeobject (c1) ;
os. close O ;
FilelnputStream fis = new FilelnputStream(..play.txt,,) Objectlnputstream is = new Object.InpuLStream(fis) ; CardPlayer c2 = (CardPlayer) is.readObjectO;
Qual6 o resultado?
A.pc
B. pcc
c.pcp
D. pcpc
E. A compilagio.
F. r4r E langada uma excegio no tempo de execugio. r { t
3. Dado que bw 6 uma refer6ncia a um BufferedWriter v6lido. E o seguinte fragmento: 15. BufferedWriter b1 = new BufferedWriter(new File("f") ); 16. BufferedWriter b2 = new Bufferedwriter(new Filewriter("f1-") ); 1,'7 . Bufferedwriter b3 = new BufferedWriter (new PrintWriter ("f2" ) ) ; 1-8. BufferedWriter b4 = new BufferedWriter (new Bufferedwriter (bw) ) ;
Qual6 o resultado?
sucesso.
erro nalinha
17.
E. A
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 ";
Short s1 = (short) ((new Short((short)343)) / (new Short((short)49))); 5 += "=5 "; if(s1 == 7) if(s1 < new fnteger(7+1) ) s += "fly "; System. out . println ( s ) ;
j
Quais das seguinres opg6es serXo incluidas na String de saida s? (A4arque todas as corretas)
A. . e]B. .e2
C. =s
D.fly
E. Nenhuma
n 3r I
das anteriores.
F. A compilagio
falha.
n | .
5. Dado: f. import java.text.*; 2. class Dateone { 3. public stacic void main(string[] args) i 4. Date d = new Dare(11-23631685981L) ; DateFormat df = new DateFormat ( ) t 5. 6. System. out.println (df . format (d) ) ; 7. ] 8. ]
E dado que 112363I68598IL 6 o nirmero de milisegundos entre L". de janeiro de 7970 e algum momento em9 de agosto de 2005, qual 6 o resultado? (Observagio: a hora do dia na opgio A poderi variar.)
A.8/9/05 5:54PM
B.
n
1123631685981L
4r r r
E. A compilagio
6. Dado: import java.io.*; class Keyboard { } public class Computer implements Serializable private Keyboard k = new KeyboardO; public static void main(String[] args) {
LvrrrPuLs! ^^6^"F^a cl-nraTf la\
.
a^n6rrf6rt\. vurrrPuus!\/,
writeObj ect
c);
JAVA
289
os.closeO;
System. out.prj_ntLn (..done,, ) ;
falha.
6
D. Exatamente um obieto
serializado. serializados.
7. Usando a menor quantidade de fragmentos possfvel (e preenchendo a menor quantidade possivel de espacos dm branco), comElete o c6diso abaixo de forma que a classe trie um diret6rio chamado "dir3" e ciie tanib6m um arqlivo chamado "f i143" dentro de "dir3". Observe que vocC pode usar cada fragmento no m6ximo uma vez, ou deixS-lo sem uso.
C6digo:
import java.io.
al acc M:lrar I
Fragmentos:
FileDescriptor,'
Di ranf
nnr.
trY
createNewDir ( ) ; createNewFile O ;
t)
f i I ^
(Exception x)
.
dir ] catch
r-re
= new File
nra:faFila/\ '
File file
8. Quais afirmativas s6o verdadeiras? (Marque todas as corretas) A. DateFormat. getDate ( ) 6 usado para converter uma String em uma instAncia de Date. B. Tanto os objetos DateFormat quanto os NumberFormat podem ser constnildos para ser especificos a um l-ocale. C. Tanto os objetos Currency quanto os NumberFormat devem ser construidos usando-se m6todos est6ticos.
D.
Se
o Locale de um instancia de tqumnerFormaE for diferente do arual, ele deve ser especificado no momento dacia{ao.
se
E. Uma mesma instAncia de NumberFormat pode ser usada para para criar nimeros formatados a partir de nrimeros.
9. Quais opg6es compilarao e rodareo sem exceg6es? (Marque todas :N corret,rs) A. System.out.format("?b", I23l ; B. System.out. format("%c", "x") ; C. System. out.printf ( "ta" , ]-23) ; D. System. out.printf ( "tt" , t23) ; E. System.out.pri-ntf ("td" , 1,23.45) ; F. System.out.printf ( "8f " , 1,23 .45) ; G. System.out. format(\ts", new Long("t23") ) ;
| 0. Quais das afirmativas sobre as tr6s classes de java.lang, String, StringBuilder e StringBuffer sdo verdadeiras? (Marque todas as corretzr)
A
B.
Todas
as
length
()
append ( ) sobrecarregados.
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
API.
da
I l. Dado que I I 19280000000L 6 aproximadamente o n0mero de milisegundos de 1". de janeiro de 1970 at6 20 de junho de 2005, e que voc6 deseja exibir essa data em alemao, usando o estilo LONG tal que " ,June " ser6 exibido como ".Juni " , complete o c6digo usando os fragmentos abaixo. Observagio: vocC pode usar cada fragmento no m6ximo uma vez ou entao deix6-lo sem uso, e pode ser que n6o precise preencher todos os espagos.
Code:
import java. import java. class DateTvro { public static void main(Strinq[] args) Date d = new Date(1119280000000L); DateFormat. df =
);
System. out
.
println
] Fragmentos:
new DateFormat
Locale.
LONG
DateFormat..getfnstance ( DateFormat.getDatelnstance (
util.reg,ex,' df.format(d));
in *.
d.format(df));
class Directories { static String [] dirs = 1"dirl", "dir2"]; public static void main(String [] args) { for (String d : dirs) {
iAVA
291
// insira o c6digo L aqui File fi-f e = new File(path, args [0] ) ; // insira o c6digo 2 aqui
e que a chamada
emitida a partir de um diret6rio que tem dois subdiret6rios, "dir1" e "dir2", e que "dir1" rem um arquivo "fi1e1 .tit"e'dir2"temumaiquivo"file2.tlt",easaida6"false true'iquaisconjuntosdefragmentos
as
corretas)
A String path = d; System.out.print(fi1e.exists() + " B. String path = d; +\ System.out.print(file.isFileO C. String path = File.separator + d; System. out.print (f i1e. exists ( ) D. String path = File.separator + d,. +" System.out.print(file.isFile()
13. Dado:
n'l ace Dnl i <h I
")
")
t')
")
public static void main(String[] args) { int x = 4; StringBuffer sb = new StringBuffer(". . fedcba") sb.delete(3,6) ; sb.insert(3, "az"); if(sb.lengthO > 6) x = sb.indexof("b") ; sb.delete( (x-3), (x-2) | ; System. out . println ( sb) ;
])
Qual6 o resultado?
. . fezba
falha.
i Ar I
F. A compilaglo
de execugio.
2. cfass Brain { 3. public static void main(String[] args) 4. // lnsira o b1oco de c6digo agui
s.
6.
)
]
e
produz
a saida
"I23
A.Scanner sc = new Scanner("123 A 3b c,45, x5x,76 82 L"); while(sc.hasNextIntO ) System.out.print(sc.nextlntO + \ ") ; B. Scanner sc = new Scanner("123 A 3b c,45, x5x,76 82 L").
useDelimiter(" "); while(sc.hasNextIntO ) System.out.print(sc.nextIntO ") ; C. Scanner sc = new Scanner("123 A 3b c,45, x5x,76 82 L"); while(sc.hasNext O ) { if (sc.hasNextfntO ) System.out.print(sc.nextlntO + N ") ; else sc.nextO; ) D. Scanner sc = new Scanner("123 A 3b c,45, x5x,76 82 L"). useDelimiter(" "); while(sc.hasNextO ) { if (sc.hasNextlnt() ) System.out.print(sc.nextTnt() + " ") ; else sc.nextO; ) E. Scanner sc = new Scanner("L23 A 3b c,45, x5x,76 82 L"); do{ if (sc.hasNextIntO ) System.out.print(sc.nextfntO ") ; ) while ( sc.hasNextO ); F. Scanner sc = new Scanner("i-23 A 3b c,45, x5x,76 82 L"). useDel-imiter(" "); do{ if (sc.hasNextlntO ) System.ouE.print(sc.nextlntO + " ") ; ] while ( sc.hasNextO );
|
5. Dado:
i mnnrf i:rra in -.._.*-. * ;
public class Testser { public static void main(String[] args) { SpecialSerial s = new SpecialserialO; try { Objectoutputstream os = new ObjectOutputstream(
new Fileoutputstream( "myFi1e" ) ) ;
$\.
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"); }
) )
JAVA
)
293
A. A compilagdo B. Asaida610
f.alha.
09 C.Asaida6to o ro
D.AsaidaEto t g E. Asaida6ro z ro F. Para dterar o processo
SpecialSerial.
Respostas
esi correta. O \d estA procurando por digitos. O * 6 um quantificador que procura por zero ou mais ocorrAncias do padrio que o precede. Por termos. especificado 'r, .o m6todo group ( ) retorna Strings vazias at6 que digitos
E
consecutivos sejam encontrados, de forma que o rinico momento em que group ( ) retorna um valor 6 quando retorna 34, quando o matcher encontra digitos comegando na posigio 2. O m6todo start ( ) retorna a posigio inicial da correspond6ncia anterior porque, novamente, n6s especificamos a busca por zero ou mais ocorr6ncias.
base
C esti correta. E vilido que uma classe implemente Serializable mesmo que a sua superclasse nio o faga. Entretanto, quando voc6 deserializar esse tipo de objeto, a superclasse nio-serializavel deve rodar o seu construtor. Lembre-se de que os construtores nio rodam em classes deserializadas que implementem Serializaf[s.
base no
eredwriters somente podem ser constru(dos encapsulando-se um rVriter. As linhas 16, lTet9esteocorretasporqueBufferedWriter,Filewriter ePrintWriter estendemWriter.
base no
(Observaglo: Buffered\Triter 6 uma classe decorator. As classes decorator sio usadas extensivamente no pacote java.io para lhe permitir estender a funcionalidade de outras classes)
4.
true
de integers somente
retornario
seosdoistiposprimitivoseosdoisvaloresforemiguais.ComC,6validof.azerunboxingeusar::.EmD,6
expresseo, 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 tentar comparar dois tipos diferentes) (Objetivo 3. 1)
equals ( ) para
base
do tipo Computer ("computador") Tem-Um Keyboard ("teclado"). Pelo fato de Keyboard nio implementar Serializable, qualquer tentativa de serializar uma instAncia de Computer cuasari o
B, C, D e E estio incorretas com base no exposto acima. objetos teriam sido serializados. (Objetivo 3.3)
7.
Se
try
Fil-e dir = new File("dir3") ; dir.mkdirO; File file = new File(dir, "fi1e3"); file.createNewFile ( ) ; ) catch (Exception x) t )
new File nio criam arquivos ou diret6rios, apenas objetos. VocO precisa dos m6todosmkdir O e createNewFile ( ) parade fato criar o diret6rio e o arquivo no disco. (Objetivo 3.2) 8. B, C, D e E estio corretas.
Observag6es: as instrug6es
est6
incorreta, DateFormat
true
B esti incorreta, o caracter de conversio 8c (caracter) espera um caracter, e nio uma String. D esti incorreta, o caracter de converslo I f (ponto flutuante) nio promove automaticamente um tipo integer. E est6 incorreta, o caracter de converslo o/od (integral) nio 6. capaz de usar um nrimero de ponto flutuante. (Observagio: Os m6todos f ormat ( ) e prinLf ( ) se componam de forma idntica.) (Objetivo 3.5)
l0.AeBestlocorretas.
C esti incorreta porque String nio tem um m6todo "append". D
est6 incorreta porque somente objetos String podem ser manipulados usando-se operador sobrecarregado " + ". E esti ao contririo, StringBuilder normalmente 6 mais rApida por ndo ser segura em relagSo a threads. F esr6 incorreta porque objetos String sio imut6veis. Uma referOncia String pode ser alterada para referir-se a um objeto String diferente, mas os pr6prios objetos sio imut6veis. (Objetivo 3. 1)
11.
i mnnrf i mnart-
i:rrr i :rzr
rrt- i I
* *
I avt-
class DateTVo { public static voj-d main(Strinq[] args) { Date d = new Date(1119280000000L); Dat.eFormat df = DateFormat.qetDatelnstance(
DateFormat. LONG, Locale.
System. out.println (df . format (d) ) ;
GERMANY) ;
ObservagSes: Lembre-se de que voc6 deve construir objetos tamb6m de que voc6 deve esp ecrticar umLocale paraum objeto m6todo getrnstance ( ) nio usa um Locale. (Objetivo 3.a)
12.
de voc6
base
C est6 correta. Lembre-se de que os m6todos StringBuffer usam indices que comegam pelo zero, e que os indices finais normalmente sio exclusivos. A, B, D, E, F e G
usando
esteo incorretas com base no exposto acima. (Objetivo 3.1)
14.CeDestlocorretas.Oespagoembranco6odelimitadorpadrio,eoloopwhileavangaatrav6sdaString
nexLlnt ( ) ou next ( ).
A e B estio incorretasporqueo loop while nilovaial6mdo primeironio-int. E eF estSoincorretas. O loop do farium loop infinito uma vez encontrado o primeiro nio-int, porque hasNext ( ) nio avanga atrav6s dos
dados. (Objetivos 3.5)
15.
C e F estio corretas. C esti correta porque vari6veis um objeto o 6. F 6 uma instrugio vilida.
static
transient
base no exposto acima. G este incorreta porque voc6 nio sobrescreve o m6todo def aultReadobj ect O , mas o chama apaftir do m6todo sobrescrito readObj ect O , junto com quaisquer
::
UsorVers6es Gen6ricos de Coniuntos Incluindo Set, List e Mop Usor Por6metros de Tipos, Escrever M6todos Gen6ricos Usor iovo.util poro Clossificor e Fozer
Buscos
ndadot
upbma
difrrwqa mhe
==
e o
mfitudo Euals-
Vod 6 um
de conseguir um aumentario depois que passar no exame). Se excluirmos os tipos primitivgs, rudo_eqJava 6 um objeto. Nio s6 ,rm oSjeto, rns um Objeto .orn 'O' mairisculo. Cada exce$o, cada wento, cada arny 6 derivado dg pacgte java.lang.bbject. No exame, vocd nlo precisar6 saber cada m6todo de Objea , mas tufti qlre conhecer os listados na Tabela 7-1.
Vod tem um
Portanto, nesta seElo examinaremos apenas os m6todos hashcode ( ) e equals ) , nlo? Ceno, falaremos sobre ele agora mesmo porque s6 levar6 dois segtrndos.
OCapinrlogabordar6wait(
Tobelo
M6todo
Decide se dois objetos sio significativamente equivalentes. Chamado pelo coletor de lixo quando este percebe que o objeto n1o pode ser referenciado. Retorna o valor
int
hashCode
int
que
esse
pr.gu.*
objeto possa ser usado em classes Collection que o hashing, incluindo Hashtable, HashMap e HashSet.
desse
Notifica
desse
todot os
obieto.
notify ounotlfyAll
Faz com que o thread atual aguarde at6 que outro thread chame nesse obieto.
O metodo toString( )Sobrescrwa toString ( ) qtrando quiser que simples mortais consigam obter um resultado iffeligivel ,elacionio'aos objetos de zua class". U* .^odigo po& chamar tostring ( ) ernryu objeto quando precisar de detalhes riteis sobre ele. Por exemplo, quando vod passar a referncia a um objeto para o m6todo System. out . println ( ) , o m6todo toString ( ) dese objao seri chamado e retornat6 o que vemos exibido aqui:
A execugio
%
java
HardToRead
HardToRead@a47e0
saida anterior 6 a que voc6 obter6 quando nio sobre*rever o m6todo toString ( ) da classe Objea. Ela forneceri o nome da classe (pelo-menos zira ten rlanlncia) seguido do simbolo @ e da representagio hexadecimal nXo assinalada do c6digo de hashing do objeto.
JAVA
297
Talvez o fato de ter visto ese resultado o motive a sobrescrever o m6todo exemplo;
toString
public class BobTest { pubfic static void main (String[] args) Bob f = new Bob("GoBobGo", 19);
System.
out.print.ln ( f ) ;
public String toString O { return ("I am a Bob. but you can call me " + nickName ". My shoe size is " + shoeSize) ;
)
)
me GoBobGo. My shoe
size is
l-9
Algumas pessoas se referem afetivamente a toString ( ) como "o m6todo da revelagio total", porque suas implementag6es mais comuns simplesmente revelam o estado do objeto (em outras palavras, os valores atuais das vari6veis de instAncia imponantes).
Sobrescrevendo equals( )
Voc6 conheceu o m6todo equals ( ) em capitulos anteriores, ao examinarmos as classes wrapper. Discutimos como a comparaglo de duas referancias a objetos com o operador : : retornar^ Lrue se elas apontarem para o mesmo objeto (porque : : avalia apenas os bits da vari6vel que podem ser id6nticos ou nio). VocA viu que a classe String e as classes wrapper sobrescrevem o m6todo equals ( ) fterdado da classe Object), de modo a podermos comparar dois objetos diferentes (do mesmo tipo) para saber se seus conteildos slo significativamente equivalentes. Se duas instincias diferentes de Integer armazeflarem o valor int 5, elas poderio ser consideradas iguais. O fato do valor 5 existir em dois objetos separados nio importa.
pnipriw oQetw (e
: . Mas quando tiver que saber se os se duas referdncias slo id6nticas, use referAncias) sio iguais, use o m6todo equals( ). Para cada classe que escrever, voc6 teri que as decidir se fari sentido considerar iguais duas instAncias diferentes. Em algumas classes, voc6 pode definir que dois objetos nunca serio iguais. Por exemplo, imagine uma classe Car que tenha vari6veis de instAncia para itens como marca, modelo, ano, configurageo - com certezavocA nio iri gostar se seu carro comegar a ser tratado como o mermr carro de outra pessoa que possui ahibutos id^4nticos. Seu carro 6 seu carro e voc6 nio ir6 querer que seu vizinho Billy saia dirigindo nele s6 por que, 'bem, na verdade 6 o mesmo carro; o m6todo equals$ informou isso". Portanto, dois canvs nunca deuen ser considerados exatamente iguais, Se duas referdncias apontarem para to// carro, entio, vocA saberi que ambas estio relacionadas a am carro, e nio a dois que tenham os mesmos atributos. Assim, no caso de uma classe Car talvez voc6 nunca precise, ou queira, sobrescrever o m6todo equalsQ. Sabemos, por6m, que a est6ria nio termina aqui.
Quando voc6 tiver que saber realmente
nio
se voc6 nio sobrescrever o m6todo equals ( ) , ndo ?odeni usar o objeto como provavelmente neo obteri Sets precisos, de forma tal que nlo haja duplicatas conceituais.
O m6todo equals
sobrescreva
eguals
( ) de Object usa somente o operador : : p^racomparag6es, portanto, a menos que vocA ( ) , dois objetos s6 serlo considerados iguais re as duas ryferncias apnntarcm para o metno objeto.
Examinemos o que significa nio poder usar um objeto como a chave de uma tabela de hashing. Suponhamos que voce
riar
usdJo
na
puqaiv.
A conclusio
6 essa: se voc6 quiser que os objetos de sua classe sejam usados como chaves de uma tabela de hashing (ou como elementos de qualquer estrutura de dados que use a equivalAncia para procurar - e/ov recuperar - um objeto), teni que sobrescreuer equ'al-s ( ) para que daas instdncias diferentes pwsam ser consideradas iguais. EntXo, como corrigiriamos o exemplo do carro? Voc6 pode sobrescrever o m6todo equals ( ) , a fim de que use o VIN (Vehicle Identification Number) exclusivo como base da comparagio. Dessa forma, poderi empregar uma instAncia quando adrcionS-La aum conjunto e essencialmente criar outra id6ntica quando quiser fazer uma pesquisa baseando-se nesse objeto como chave. E claro que sobrescrwer o m6todo equals ( ) de Car tamMm permitir6 o surgimento da posibilidade de mais de um objao representando um carro exclusivo existente, o que pode nlo ser seguro em seu projeto. Felizmente, as classes String e wrapper firncionam bem como chaves em tabelas de hashing - elas sobrescrevem o m6todo equals ( ) . Portanto, emvez de usar a irstAncia real do carro como chave no par carco/propriet6:io, vod poderia empregar simplesmente uma String que representasse o identificador exclusivo do carro. Assim, nunca ted mais de uma instAncia representando um carro especifico, mas ainda podera usar o
am dc seus alributos
- como
a chave da pesquisa.
equals
a seguir:
moofval-ue;
l {
moofValue = val;
)
public boolean equafs(Object o) if ( (o instanceof Moof) && ( ( == this.moofValue)) { return crue; ) efse { return fafse;
(Moof
)o
) . getMoofValue
]
Analisaremos os detalhes desse c6digo. No m6todo main ( ) de EqualTest, criamos duas instincias de Moof, passando o mesmo valor (e) para seus constnrtores. Agora examinemos a classe Moof paraver o que ela f.az com o argumento desse construtor - ela atribui o valor avariLvel de instAncia moofValue. Suponhamos que voc6 definisse q,ri dois objetos Moof serio iguais se suas vari6veis moofvalue forem idAnticas. Ent-io, voc6 estiri sobrescrevendo o m6todo equals ( ) ao comparar as duas variiveis moofvalue. E simples assim. Por6m, analisemos o que ocorre no m6todo equats ( ) :
JAVA
299
public boolean equals(Object o) { 2. if ( (o instanceof Moof) && ( ( (Moof)o).getMoofValueo == this.moofValue) ) { return truei 3. 4. ) else { return false; 5. 6. ) 7. j
1.
Em primeiro lugar, voc6 drue observar todas as regras da sobrescrigio; e na linha sobrescrigio v6lida do m6todo equals ( ) que herdamos de Object.
L estamos
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
precisa que ele passe por um teste instanceof . Ter dois objetos de tipos de classe diferentes sendo considerados iguais geralmerfie nal 6 uma boa id6ia, mas 6 uma questio relacionada a projeto, sobre a qual nio discutiremos aqui. Al6m disso, voc| ainda teria que execurar um teste insLanceof simplesmente para se assegurar de que poder6 converter o argumento do objeto para o tipo correto, de modo a poder acesar seas rudtodos ou vari6veis e faqer realmente a comparagio. Lembre-se de que se o objeto nio passar no teste instanceof, entio, voc6 veri uma excegio de tempo de execugio ClassCastException. Por exemplo:
pubfic boolean equals(Object o) { if ( ( (Moof)o).getMoofValueO == this.moofValue) { // a Linha anterior compila, mas 6 ma1-escrita! return E.rue; ] else { return false; )
)
se a
vari6vel
segundo lugar, conrparar os atibutos releuantes (nesse caso, apenas moofValue). 56 os desenvolvedores podem decidir o que torna duas instAncias iguais (por raz6es de desempenho, ser6 melhor verificar a menor quantidade possivel de
atributos).
Aprop6siro,casovocAtenhaestranhadoasintaxede ((Moof)o)
simplesmente convertendo
a
.getMoofValue( )comoumtodo,estamos
variAvel de refer6ncia de objeto, o, simultaneamente ) tentativa de chamarmos um m6todo que esti na classe Moof, mas nlo em Object. Tenha em mente que, sen a conversio, voc6 nio conseguir6 compilar porque o compilador veria o objeto referenciado por o simplesmente como um tipo Object. E j6 que a classe Object nio possui um m6todo moofvalue ( ) , o compilador iria berrar (termo t6cnico). Por6m, como dissemos anteriormente, mesmo com a conversio o c6digo falhari no tempo de execugio se o objeto referenciado por o nio for algo que possa ser convertido em um objeto Moof. Portanto, jamais se esquega de usar o teste instanceof primeiro. Ai estA outrarazio paravalorizar o operador de abreviagio && - se o teste instanceof falhar, nunca chegaremos ao c6digo que executa a conversio, de modo que sempre estaremos seguros no tempo de execugio escrevendo o seguinte:
if
((
(Moof)o).getMoofValue(
Entio,
isso encerra
eguals
) ...
Calma...
dann vocA
conhato especlficado
ser segridas se
) . Um nnran Java 6 um conjunto de regras qrc dnrm rer *eurdas, ou melhor, wd qtiserfomecer una intplenmh1do "mmta" coruo as ouhas ?essnar esfurao etpranda, Ou para colocar de outra forrna, se
a classe
nlo
compila$o
ea
e Coniuntos
OBSERVAQ6TS
pene O EXAME
eqwal-s
l-.embre-sedequeosmdtodosequals(
sobrucrigdo udlida do mdtodo
),hashCode( )rLoString(
)
) tiotodospilblicu.Ocddigoaseguirndoseriauma
embora padesse parecer qile sim te uocd n6o o/hasse com bastante atengdo durante 0 xat//:
do mdtodo
equals
( ).'
(Boo
b) {
}}
Certifque-u de estar ben faniliaiqado com ar regras da sobrescrigdo para qtle posw identifcar se um nitodo de Objut utti sendo sobrescrito, sobrecamgado ou inaalidamente redalarado em t/ma c/asn. O mitodo equaLs da clare Boo a/tera o argumento de Objutpara Boo, se tornando, portanto, um mdtodo sobruarregado, e ndo senl cbamado a menlt qile 0 setl nidigo, o qua/ conbece ese mdtodo nouo e diferente qtle Plr acanl tambdn se cbama equa1 s ( ) , sda o chamador.
( )
O contrato de equals( )
Extraido diretamente da documentagloJava, o contrato de
equals
( ) diz:
f a I
( ) deve retornar true. de x e y, x. equals (y) deve retornar true se, e somerue se,
(y)
retornar
E transitizso:Para qualquer valor de referAncia de x, y e z, se x. equal-s tamb6m retornar true, enteo, x. equals (z) deve retornar true.
true e y. equals
(z
) E consistenteiP^ra I
qualquer valor de referAncia de x e y, mriltiplas chamadas de x. equals (y) retornario consistentemente true ou consistentemente f alse, contanto que nenhuma informaqio usada nas comparag6es do objeto de eguals tenha sido alterada.
Paraqualquervalorderefer6nciadex
E voc6 ainda nem chegou e hashCode ( ) estio vinculados por um contrato de associagio que especifica qtue se dois olensforen condderados iguais peb ndtodo equal s ( ) , entdo, Precisardtt ter uakres de hasbing iddntint Poftanto, para estar realmente seguro, voc6 deve adotar a regrapriticaque diz para se submuerequals ( ) , deue-se sobresmuerhashCode( ) tanbin. Agorapodemos passar para hashCode ( ) e ver como esse m6todo esti associado a equals ( ) .
queniosejanull,x.equals(nu11) deveretornarfalse. perto de estar seguro. Nlo examinamos o m6todo hashCode ( ) , mas eguals ( )
Sobrescreyendo hashCode( )
Os c6digos de hashing normalmente sio usados para melhorar o desempenho de grandes conjunros de dados. O valor de hashing de um objeto 6 usado por algumas classes de conjuntos (examinaremos os conjuntos posteriormente neste capitulo). Embora voc6 possa consider6-lo como um tipo de nimero identificador do objeto, elJnlo 6 necessariamente exclusivo. Conjuntos como HashMap e HashSet usam o c6digo de hashing de um objeto para determinar onde ele deve ser armarynado no conjunto, i o c6digo 6 empregado novamente como auxflio na localizagio do objeto dentro do conjunto. No exame voc| nio rcrA que conhece. muitos detalhes sobre como as classes do conjunto que usam hashing sio implementadas, mas precisari saber quais conjuntos as empregam (por todos usarem hasb no nome voc6 precisa ser realmente astuto nesse ponto). Tamb6m teri que reconhecer uma implementagio @npriada ou comta de hashCode ) . Isso nlo significa udlida e nem mesmo efciente. E perfeitamente vilido ter um m6todo de c6drgo de hashing absolutamente ineficiente em sua classe, contanto que ele nio viole o contrato especificado na documentagio da classe Object (examinaremos esse contrato em breve). Portanto, no exame, se lhe for solicitado que selecione o uso apropriado ou correto do c6digo de hashing, nlo confunda apropriado com a,ilido ov efciente.
Imagine um conjunto de baldes alinhados no chio. Algu6m passa para voc6 um pedago de papel com um nome nele. Voc6pegaonome ecalculaapartirdeleum c6digocujo resultado6umvalorinteiro, usandoaconvengio Abigua|a
1, B igual a 2, e assim
resultani do mumo aidigo;
por diante, e somando os valores num6ricos de todas paraver um exemplo, consulte aFigaraT-1,.
as letras
do nome. (Jm
Nio introduziremos nada aleatoriamente, simplesmente temos um algoritmo que sempre seri executado da mesma maneira, dada uma entrada especifica, portanto, a saida serl sempre idAntica para duas entradas tamb6m id6nticas. At6 aqui tudo bem? A maneira como voc6 usa esse c6digo (e passaremos a cham6-lo de aidigo de hashin! ir6 determinar em que balde o pedago & papel deve ser inserido (suponhamos que cada balde represente um nri.mero diferente de c6digo que possa ser obtido). Agora imagine que chegue ,1gtr6-, mostre a voc6 um nome e diga: "Por favor, recupere o pedago de papel
JAVA
3OI
que coincida com esse nome". VocA olhari para o nome que esti sendo mostrado e executar6 o mesmo algoritmo de geragio do c6digo de hashing. Esse c6digo lhe informar6 em que balde deve olhar para encontrar o nome.
No entanto, voc6 deve ter notado uma pequena falha em nosso sistema. Dois nonu diferentespodem resltar no ruesmo ualor. Por exemplo, os nomes Amy e tuay t6m as mesmas letras, portanto, o c6digo de hashing ser6 id6ntico para os dois.
Isso 6 aceitivel, mas significa que quando algu6m lhe pedir (o vendedor de balde$ o pedago de papel no qual se encontra o nome Amy, voc6 teri que procurar no balde de destino lendo cada nome at6 encontrar Amy emvez de May. O c6digo s6 lhe informar6 em qtre bolth prwrrar,mas nlo como localizar o nome trma vez que tenha chegado a esse balde.
Chave
Alex
Bob
Algoritmo A(f) +
do
C6digo de
C6digo de
L(12) + E(s) +X(24) B(2)+o(15)+B(2) D(4) +l(e) + R( 18) + K( | l) F(6) + RilS)+ E(s) + (D)
=42
= le
= 47 = 33
Dirk
Fred
Conjunto
Baldes com os
C6digos de Hashing
T*\l
Llr]
Figuro
7-l
oBSERVAQ6ES
pene O EXAME
raro ter mafu
de uma entrada em
En
am procesto de duas etapas: / . Encontrar o deprisito certo (usando hashcode ) /. 2. Procurar no dEdsito o elemento mto (anndo equals
( )
).
Porranto, para obter efici6ncia, seu objetivo ser6 distribuir os pap6is da maneira mais regular possivel por todos os baldes. O ideal seria que voc6 pudesse ter apenas um nome por balde para que quando algu6m solicitasse um papel fosse possivel simplesmenre calcular o c6digo de hashing e apanhar esse papel individualmente no balde especifico (sem que seja preciso ir abrindo todos os pap6is desse balde at6 localizar o que esta sendo procurado). Um gerador de c6digo de hashing menos eficiente (por6m, ainda funcional) retornaria o ///esmt c6digo (digamos, 42) independente do nome, de modo que todos os pap6is seriam inseridos em um mesmo balde, com os outros Permanecendo vazios. O vendedor teria que ir at6 esse balde e olhar cada um dos nomes at6 que o correto fosse encontrado. E se funcionasse realmente assim, ele tamb6m poderia nunca usar os c6digos de hashing, e emvez disso ir at6 o balde grande, escolher como comegar e olhar cada papel at6 encontrar o desejado.
de distribuigio por baldes 6 semelhante I maneira como os c6digos de hashing sio usados em coniuntos. Quando voc6 inserir um objeto em um conjunto que use c6digos de hashing, o conjunto usari o c6digo do obieto para decidir em que dep6sito/slot ele deve ser inserido. Em seguida, quando voc quiserpraclrraresse objeto (ou, em uma tabela de hashing, recuperar o valor associado a esse objeto), ter6 que fornecer ao coniunto uma referdncia a qual ele comparar com os objetos qae utiuer annarynandt. Contanto que o objeto (armazenado no conjunto, como o papel no balde) que voc0 estiver tenrando encontrar tenha o nurzto aidigo de hashirgdo objeto que estiver usando na pesquisa (o nome mostrado ) pessoa que esrava trabalhando com os balde$, ele ser6 encontrado. Mas... E esse 6 um grande Por6m' imagine o que aconteceria se, voltando ao nosso exemplo dos nomes, voc6 mostrasse ao vendedor de baldes um nome
O exemplo
vi
porque nXo procuraria no balde correto! Agora voc6 consegue perceber por que se dois objetos sio considerados iguais, seus c6digos de hashing tamb6m devem ser iguais? Do contr6rio, voc6 nunca poderia encontrar o objeto j6 que o m6todo padrio de c6digo de hashing da classe Object virtualmente sempre 6 usado com um nrimero exclusivo para cada objeto, uumo qaando o mitodo equals O d sobrescrito de uma maneira erz que dois oa nafu o@etos sdo considerados igaais. Nio impona quanto sio iguais os objetos se seus c6digos de hashing nio refletem isso. Portanto, repetiremos: se dnis objetosforcm igaait, reur c6digos de basbing
tambim terdo que ser.
lmplementando hashCode( )
Como ser6 que um algoritmo real de c6&go de hashing se parece? Algumas pessoas obt6m seu grau de PhD em algoritmos de hashing, portanto, do ponto de vista da ci6ncia da computagio, isso esti al6m do escopo do exame. A parte relevante aqui 6 a questio de seguir o contrato. E para seguir o contrato, Pense no que fez no m6todo equals ( ) . Vzd cv//patoa anibutos. Porque essa compara$o quse sempre envolve valores de vari6veis de instAncia (embra-se de quando examinamos dois objetos Moof e que os considerariamos iguais se os valores int das vari6veis moofvalue fossem os
hashCode
Aqui
est6
um exemplo:
class HasHash
yuvf ^'.1-li^ fe i-f
{
-.
public boofean equals(Object o) { HasHash h = (HasHash) o; / / Nao tente isso em casa // um teste instanceof if (h.x == this.x) { return true;
1 01e6
r
return false;
]
)
Ji
qu9 o m6todo equals ( ) considerar6 dois objetos iguais se eles tiverem o mesmo valor x, temos que nos certificar de que os objetos de mesmo valor x retornem c6digos de hashing iddnticos.
un
mdtodo utllido
atd
tgua/ a
dexiguala/2
todos ot objetos
eoouhvcom um uakriguala-920.
8 terdo o mesmo aidtgo de hathing. Pordn, 0 metmr aconteceria con dofu nbjetls dferenter, um com o aalor EsemdtolahashCode ( ) rimaitoinefciente; lenbre+e disso,porqaefardcomque
depiitl
usandrt
s/an innidos no mesmo depdsito, mas, meJmr assim, o objeto podeni ser encontrado depois que o conlanto uascu/har no inico eqoaT.s ( ) -, tentando desesperadaante knliryC @6s muita puquisa, o objeto correto. En oatrat palatras, o aldigo de
hashing ndo @ttdou em nada a aalerar a pesqlis4 embora afnalidade do hashtng :e1a obter etsa uelocidafu! No entanto, esse adtod.o qae returflla someflte um cddigo de basbing seria conidtrado @npriado e atd comto porqae ndo tiola o contrato. Rqetirei nais xtma ae<r correto ndo ignfica necessariamente bom.
( ) que usario alguma combinagio de ^ (XOR) exclusivo envolvendo vari6veis de instAncia, junto com, digamos, sua multiplicageo por um nrimero primo. Independente do caso, embora o_objetivo seja obter uma distribuigio abrangente e aleat6riados objetos nos dep6sitos, o contrato (e o fato de um objeto poder ou neo ser encontrado) s6 requer que dois objetos iguais tenham c6digos de hashing id6nticos. Nio seri esperado no exame que voc6 avalie a eficiAncia de um m6todo hashCod.e ( ) , mas 6 preciso conseguir reconhecer quais funcionario ou nio (funcionar significando "fazer comque o objeto seja encontrado no conjunto").
Normalmente, voce ver6 m6todos hashCode
as
Agora que sabemos que dois objetos iguais devem ter c6digos de hashing iddnticos, o inverso tamb6m 6 verdadeiro? Dois objetos com c6digos de hashing idAnticos t6m que ser considerados iguais? Pense nisso - voc6 poder6 ter virios objetos no mesmo dep6sito porque seus c6digos de hashing sio id6nticos, mas a menls que eles tambdn passen no teste de equals ( ) , nlo serio considerados coincidentes em uma pesquisa no conjunto. Isso 6 exatamente o que voc6 conseguiria com nosso m6todo ineficiente que fornece a todos os objetos o mesmo c6digo de hashing. E v6lido e correto, apenas muito lento.
Ponanto, para que um objeto seja localizado, tanto o objeto pesquisado qtranto o existenre no conjunto devem ter valores de hashingid6nticos rretornar true parao m6todo equals ( ) . Demodo quen5oMoutramaneiraanio sersobrescreveros dois m6todos para estar absolatammte mto dz que seas o$etus poderdn ser asados en n@unfos que eruprcguern hasting.
O contrato de hashCode( )
Agora direto da fabulosa documentagXo da API Java referente tambores) o contrato de hashCode ( ) :
classe
Sempre que for chamado no mesmo objeto mais de vmavez durante a execueeo de um aplicativo Java, o m6todo ) ter5, que retornar consistentemente o mesmo inteiro, contanto que nenhuma informagio usada nas comparag6es de equals ) envolvendo o obleto tenha sido aherada. Esse inteiro ter6 que permanecer constante de uma execugio a outra do mesmo aplicativo.
hashCode
Se
hashCode
dois objetos forem iguais de acordo com o m6todo equals (obj ect ) , entio, a chamada do m6todo ( ) nos dos dois objetos deve produzir como resultado o mesmo inteiro.
JAVA
303
NXo 6 obrigat6rio que quando dois objetos forem diferentes de acordo com o m6todo equals (java.lang.object), a chamada ao m6todo hashCode ( ) nesses objetos produza resultados inteiros distintos. No entanto, o programador deve ficar aJertapara o fato de que produzir resultados inteiros distintos para objetos diferentes pode melhorar o desempenho das tabelas de hashing.
Condigio permitido)
Obrigat6rio
Nio 6 obrigat6rio
==
(mas
x.hashCode( )
rz .A4ssrrvvsv hr chl^nr{o J / \
\ |
==
x.equals(y) == true
Sem requisitos
de
hashCode
x. hashCode y. hashCode
( (
\
)
r-
x.equals(y) == false
Portanto, examinemos o que maispode causar uma falha no m6todo hashCode ( ) . O que aconteceria se voc6 incluisse uma vari6vel transiente em seu m6todo hashCode ( ) ? Embora seja v6lido (o compilador nio reclamari), sob algumas circunstAncias o objeto que voc0 inserir em um conjunto nio seri encontrado. Como voc6 sabe, a serializagio salva o objeto de maneira que ele possa ser reativado posteriormente pela sua desserializaElo, voltando a ser um objeto totalmente v61ido. Mashhpeigo,lVillRobinnn - lembre+e de que uaidueis hansientet ndo sdo saluar qwando un objeto i
niakqado. IJm mau cen6rio poderia ser o seguinte:
x = xVal; y = yval_;
)
public boolean equals(object o) { SaveMe test = (SaveMe)o; if (test.y == y && test.x == x) t // Valido,
1611r7n rrrr6.
mas ndo
correto
Aqui
I I I I I
Fornecimento de algum estado para o objeto (atribuigXo de valores Insergio do objeto em um HashMap, sendo o objeto a chave.
variiveis de instAncia).
Salvar o objeto em um arquivo usando a serializagio sem alterar nada em seu estado.
Opa. O objeto do coniunto e o supostamente mesmo objeto reativado nio slo mais id6nticos. A vari6vel transiente do objeto retornarS. comum valor padrio emvez do valor que tinha no momento em que foi salva (ou inserida em
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.
utadot
para
se
implemennr adequadamente
pmjeto, inclaindo
Voc6 consegue imaginar escrever aplicativos orientados a bbjetos sem usar estruturas de dados como as tabelas de hashing ou listas encadeadas? O que voc6 faria quando prgcisasse ter uma lista classificada com, digamos, todos os membros de seu fi-clube dos Simpsons? E claro que podeda faz6-lo por sua conta; a Amazon.com deve ter milhares de livros sobre algoritmos que vocA poderia comprar. Mas cofn o tipo de prazos aos quais os programadores estao submetidos atualmente, chega a ser incoerente demais parf que possa ser considerado.
de conjuntos da linguagemJava, que tomou fofma com o lanEamento daJDk1.2 e se expandiu na versio 1.4 e novamente em Java 5, fornece listas, conjuntos, mapas e filas que satisfario a maioria de suas necessidades em
A estrutura
a I I I I
No
Adiaonar
objetos
ao
conjunto.
Remouer objetos
do conjunto.
no conjunto.
Renperarum
objeto
um ap6s o outro.
n base em um reouisito declarado. A API de coniuntos virias classes .orr.r.t"r. As principais interfaces q.te voc6
a segurr:
Col-f
ection
Ll-st
Queue
As principais classes concretas de implementagio que outras, mas o exame nio as abor& especificamente): mapas
ft6
coniuntos
istas
rr-r-T !!aylfDL i ^l
Utilitirios
.ClleCtiOnS
HashMap
HashSet
Hashtable
TreeMap
LinkedHashSet
Arrays
TreeSet
Linkedlist
LinkedHashl.{ap
Nem todos
os
conlantos passam no
coniuntos da estrutura implementam realrnente a interface Collection. Em outras palavras, nem todos os tute E-(JM se @licado o C)tktrioo. Especificamente, nenhuma das classes e interfaces relacionadas a maPas
JAVA
305
sio derivadas de Collection. Portanto, embora SonedMap, Hashtable, HashMap, TreeMap e LinkedHashTable sejam todas consideradx confuntoq nenhuma 6 realmente derivada de Collection. Para tornar as coisas um pouco mais confusas, na verdade hi tr6s empregos simultlneos para apalavra"conjunto":
<<interhce>>
Set
<<interfuce>> Queue
<<interhce>>
SortedSet
t *T:*]
F-"-.,"'E
['."y1 tr'.til
i,.*,',,1
I r I
conjunto, que representa qualqaerumadas estruturas de dados nas quais os objetos sio armazenados
iterag6es.
e Passam
Por
Colleaion (C' mairisculo), que, na verdade, 6 aintertacejava.util.Collection da qual Set, List e Queue sio derivadas (est6 certo, deriuadar, e nio implementadas. Nio h6 implementag6es diretas de Collection.)
Collections
(C'
maiusculo e com 's' no final), que, na verdade, 6. a clastejava.util.Collections, a qual armazena static para serem usados com os collections.
pene O EXAME
tome cuidado. I--embre-se de que Collections d ma classe, con mitodos utilitdrios ruuhof,lcil nnfandir "Collections" cum "Co//ection" utdtims, enquantr Collection d una interface com as declaragdes dos mitodos comans i maioria dos conjuntos inclusiae add( ),
re-
).
Listas
Coniuntos
Listas de itens (classes que implementam List). Itens exclusivos (classes que implementam Sed. Itens com uma identificagio exclusiva (classes que implementam Map). Itens arranjados na ordem em que serio processados.
Mapas Queues
A Figura
7-3
Nio.ordenada (Unordered)
classe de implemena$o pode ser nioclasificada e nioordenad4 ordenadae nioclassficada ou or&nada e dassificada Mas uma implementa$o nunca pode ser classficada e nioordenad4 porqu a classifica$o 6 um tipo especifico de ordenamento, comovocivedem breve. Por exemplo, F{ashset 6umconiunto nloordenado e nioclassificado, enquanto LinkedHashser 6 um conjunto orrdenado (rnas nioclassificadQ que maff6m a ordem na qrul os objaos foram inseridos.
e Coniuntos
fimmffi[il'ffi[il
Lisc
O itineririo do vendedor
(duplicatas
sio
permitidas)
E'-.spr{l
ffi
,rt
Eq WA | ]
E@
Valores
Gancho
,/
Chave
HashMap: Os produtos do vendedor (Chaves geradas a partir das lDs dos produtos)
Mop
Talvez precisemos ser explicitos com relageo ) diferenEa entre classificado e ordenado, mas primeiro temos que discutir o conceito de iteragdo. Quando pensamos em iteragio, podemos considerar a iteragio em um array usando, digamos, um loop f or para acessar cada elemento em ordem ([0], [1], [2], e assim por diante). Iterar em um coniunro geralmente significa percorrer os elementos um ap6s o outro comegando no primeiro elemento. No entanto, )s vezes, at6 mesmo o conceito de pineirc 6 um pouco estranho - em um objeto Hashtable nio h6 a nogio de primeiro, segundo, terceiro e etc. Nesse objeto, os elementos slo inseridos em uma ordem ca6tica (at6 onde sabemos) com base no c6digo de hashing da chave. Mas, algo tem que vir primeiro quando iteramos; portanto, quando voc6 iterar em um Hashtable, na verdade, haveri.uma ordem. Mas at6 onde podemos saber, ela 6 completamente arbitririae pode ser alterada de maneira aparentemente aleat6ria com modificag6es no conjunto.
Quando um conjunto 6 ordenado, significa que vocA podeiterar em seus elementos em uma ordem nio 6 ordenado. Embora ele tenha uma l6gica interna para determinar a ordem (com base nos c6digos de hashing e na implementagio do pr6prio conjunto), voc6 nlb ver6 nenhuma ordem quando iterar pelo coniunto. O conjunto Arraylist, no entanto, mant6m a ordem estabelecida pela posigio do indice dos elementos (exatamente como um xray).LinkedHashSet mantlm a ordem estabelecida pela insergXo, portanto, o rlltimo elemento inserido ser6 o riltimo do conjunto (diferente de Arraylist, no qual voc6 pode inserir um elemento na posigio especifica do indice). Para concluir, hi alguns conjuntos que mant6m uma ordem conhecida como ordem nataral dos elementos, e eles nio sio apenas ordenados, mas tamb6m classificados. Examinemos como a ordem natural funciona em coniuntos classificados.
especifica (nio aleat6ria). Um conjunto Hashtable
dasufcado significa que a ordem do conjunto estl determinada por alguma(s) regra(s), conhecida(s) como ordem de classificagio. IJma ordem de classificagio nio tem nada a ver com o momenro em que o objeto foi adicionado ao conjunto, nem com a riltima vez em que foi acessado, nem em que "posigio" foi adicionado. A classificagio 6feitacom base em propriedades dos pr6prios objetos. Voc6 coloca objetos no conjunto, e o conjunto descobriri em que ordem coloc6-los, com base na ordem de classificagio. Um coniunto que mantenha uma ordem (por exemplo qualquer List, que usa a ordem de insergio), na verdade, nio 6 considerado classfcado a nio ser que use algum tipo de ordem de classificagio. Na maioria das vezes, a ordem usada 6 algo chamado de ordem natural. O que isso significa?
Ordenado
Classificado Um conjunto
VocA sabe como classificar alfabeticamente - A vem antes de B, F vem antes de G, e assim por diante. Em um conjunto de objetos String, a ordem natural 6 alfab6tica. Para objetos Integer, a ordem natural 6 por valor num6rico - 1 antes de 2, e assim por diante. E para objetos Foo, a ordem natural6,hX, ndo sabemos. Nio h6 ordem natural par Foo, a menos ou at6 que seu desenvolvedor fornega um4 por meio de uma interface (Comparable) que defina como as instAncias de uma classe podem ser comparadas entre si (a instAncia vem antes de b, ou vem antes de a?). Se o desenvolvedor decidir que os objetos Foo devem ser comparados entre si com o uso do valor de alguma varilvel de instAncia (digamos que haja uma chamada bar), um conjunto classificado ordenar6 os objetos Foo de acordo com as regras da classe Foo de como usar a vari6vel de instAncia para determinar a ordem. E claro que a classe Foo poderia tamb6m herdar uma ordem natural de uma superclasse emvez de definir a sua pr6pria ordem, em alguns casos.
bar
Afora
a ordem namral especficada pela interface Comparable, 6 possivel tamb6m definir outras ordens de classifica$o diferentes usandose runa outra interfacs Comparator. Falaremos sobre como usar Comparable e Comparator paradefinir
JAVA
as
307
ordens de classificagio mais adiante neste capitulo. Por agora, basta ter em mente que a ordem de classificagio (incluindo a ordem natural) ndo 6 a mesma coisa que ordenar por insergio, acesso ou indice.
Agora que conhecemos o ordenamento e a classificagio, examinaremos cada uma das tr6s interfaces e, em seguida,
nos aprofundaremos em suas implementag6es concretas.
A Interface List
No conjunto List o indice tem relevAncia. A rinica coisa encontrada em List que conjuntos diferentes nio tAm sio virios m6todos relacionados ao indice. Entre esses m6todos principais esteo, por exemplo, get (int index) , ind.exOf ( ) , add ( int ind,ex, Obj ect obj ) , e outros. Todas as tr& implementag6es de List sio or&nadas atrav6s
da posiSo do indice - uma posiglo que wd deterrnnailrconfigurando um objeto em um indice especifico ou adicionandoo :en especificar a posigio, quando o objeto 6 inserido no final. As tr6s implementag6es de Lis serio descritas na pr6xima se$o.
Considere esse conjunto como um array que pode crescer. Ele proporciona iterapdo e acesso aleat,rio com rqideT,Declaraglo 6bvia: 6 um conjunto ordenado (por indices), mas nAo 6 classificado. VocO pode vAJo a partir da verslo 1..4, e atualmente ele implementa a nova interface RandomAccess - uma intedace marcadora (o que significa que nio possui m6todo$ que informa' "Essa lista di suporte ao acesso aleat6rio r6pido (geralmente de forma ininterrupta)". Prefira essa lista a Linkedlist quando precisar de iteragio r5rpida e n6o pretender executar muitas inserg6es e exclus6es.
Arraylist
Vector
E,r'trn re-anescente dos prim6rdios daJava; Vector e Hashtable sio dois coniuntos originais, os outros foram adicionados nas vers6es I.2 e I.4 dalava2.Umconjunto Vector 6 basicamente igud, a LrrayList, mas os m6todos Vector sio sincronizados para a seguranga dos threads. Normalmente 6 preferivel usar Arraylist em vez de Vector, ji que os m6todos sincroniiados .ansam um impacto no desempenho que pode ser desnecessirio. E se vocA realnmte precisar de seguranga para os threads, h6 m6todos utilitirios na classe Collections que podem ipdar. Vector 6 a 6nica classe al6m de Arraylist que implementa RandomAccess.
Linkedlist
Linkedlist 6 ordenado pela posigio no indice, como Arraylist, exceto pelos elementos serem duplamente encadeados entre si. Esse encadeamento fornece novos m6todos (a16m dos obtidos na interf_ace List)_ para a insergio e remogio do inicio ou final, o que o torna uma opglo adequada ) implementagio de uma pilha ou fila. Lembre-se que um conjunto Linkedlist pode ser mais lento na iteraglo do que Arraylist, mas ser6uma boa opgXo quando voc3 precisar de inserE6es e exclus6es ripidas. No Java 5, a classe Linkedlist foi aprimorada para implementar
atntertacejava.util.Queue.Assim,elaagoraoferecesuporteosm6todosdefilascomuns:peek(
),po11( )eoffer(
).
A Interface Set
O conjunto
i exclusividade - ele nio permite duplicatas. O m6todo equals ( ) determinari (situagio na qual s6 um poder6 ficar no conjunto). As tr6s implementag6es de Set serio dois objetos sio id6nticos descritas nas se96es seguintes.
Set d6 relevAncia
se
HashSet Hashset
6 um conjunto Set nio-classificado e nlo-ordenado. Ele usa o c6digo de hashing do objeto que esti ) melhor seri o.desempenho sendo inserido; portanto, quanto mais eficiente for sua implementagio de hashCode obtido no acesso. lJse essa classe quando quiser um conjunto sem duplicatas e nio precisar de ordem na iteragio.
LinkedHashSet LinkedHashSet 6 uma versio ordenada de HashSet que mant6m uma lista com encadeameflto duplo para todos os elementos. IJse essa classe em vez de HashSet quando a ordem da iteragio {or imponante. Ni iteiagio em HashSet a ordem 6 imprevisivel, enquanto LinkedHashSet permitir6 que voc6 itere pelos elementos na ordem em que foram inseridos.
oBSERVAQoES
Ao
ndtodt padrAl Ob
pene O EXAME
ec
hashCode
d.e
uocd
adicionar a
hashCode
) . Se ndo o fTgrem, o
"tluplicatas
pennitidas".
Treeset
preta
(e
TreeSet 6 um dos dois conjuntos classificados (o outro 6 TreeMap). Ele usa uma estrutura de irvore vermelha e voc6 sabe disso), e garante que os elementos fiquem em seqiiAncia ascendente, de acordo com sua orden natural. Qp.i"naL"*t , vod pode criar TreeSet com um construtor que the permita fomecer ao conjunto suas pn;prA rqras e qrul deve ser a onleu w*rat (emvez de &pender da orrdem definida pela clase dos elementos), usandose um Comparable ou Comparator.
A Interface Map
Para Map os identificadores exclusivos 6 que sio relevantes. lJma chaue exclusiva (o identificador) ,6 napeada para um uakrespecifico, em que 6 claro que tanto i cboue quanto o uakrsio objetos. E provivel que voc6 esteja bem familiarizado oi coniuntos Map, ji que muitas linguagens dio suporte a estnrturas de dados que usam pares thauef uabr ou nomef uakr. As.implementag6es de M1n permitirio que voc6 faga coisas como procurar um valor com base na chave, solicitar ) um con;unro apenas com os valoris ou somente com as chaves. Como Sets, Maps depende do m6todo equals para determinar se duas chaves sio as mesmas ou se slo diferentes.
.o-
HashMap
conjunto Map
HashMap fornece um conjunto Map nio-classificado e nio-ordenado. Quando voc6 precisar de um e nio estiver preocupado com a ordem (na iteraEio), enteo, FlashMap seri sua melhor opgio; os outros
Como Vector, Hashtable existe desde os prim6rdios daJava. 56 por diversio, nio esquega de observar a inconsist6ncia na nomeagio: HashMap versus Hashtable. Onde esti o "t" mairlsculo? Bem, nio esperarnos que esse detalhe entre na pronrincia. De qualquer forma, assim como Vector 6 uma contrapartida sincronizada do conjunto mais sofisticado e avangado Arraylist; Harhtable d a contr@artida incroniqada de Ha:bM@. Lembre-se de que nio se pode sincronizar uma classe, portanto, quando dizemos que Vector e Hashtable sio sincronizados, queremos dizer apenls que os mitodot chave da classe sio sincronizados. Outy difercnga, no entanto,6 que enquanto HashMap permite que vocO tenha tanto valores quanto uma chave nla, Hasbtabb nio perwitini a existincia de algun componente na/0.
Hashtable
LinkedHashMap Como sua contrapartida Set, LinkedHashSet, o conjunto LinkedHashMap mant6m a ordem de insergio (ou, opcionalmente, a ordem de acesso). Embora seja um pouco mais lento do que HashMap para adiironar remover elementos, pode-se esperar uma iteragio mais r6pida com LinkedHashMap.
TreeMap
um conjunto Map
clcxstfcado.
ji
elementos". Como TreeSet, TreeMap permitir| que voc6 introduza suas p.pi^ regras de comparaglo (por meio de um Comparable ou Comparator) no momento da criagio do TreeMap, para especificar como os elementos devem ser comparados entre si quando forem ordenados.
A Interface
A fungio
Queue
de Queue 6. armazenar uma lista de "coisas afazor", ou itens a serem processados de alguma forma. Embora outras ordens sejam possiveis, as filas normalmente sio consideradas como do tipo FIFO (em que o primeiro item a entrar.6 o primeiro a sair). As filas oferecem suporte a todos os m6todos-padrio de Collection, e tamb6m adicionam m6todos para acrescentam e subtrair elementos e revisar elementos da fila. Esta classe 6 uma novidade de Java 5. Uma vez qlre a classe Unkedlist f.oi aprimorada, para implementar a interface Qugue, as filas bisicas podem ser manipul-adas com uma Linkedlist. O prop6sito de uma PriorityQueue 6 criar uma fila com ordenamento "prioridade de entrada-prioridade de saida", em vez do sistema FIFO. Os elementos de PriorityQueue sio ordenados ou naturalmente (em cujo caso os elementos que forem os primeiros na ordem serio acessados primeiro) ou de acordo com um Comparator. Em qualquer urrrdos casos, a ordenagXo dos elementos representa a prioridade relativa deles.
PriorityQueue
reconhecer que,
ser
classe escolhida
quandofor
11
M4 i arua interface,
rvdapda do exame
classe que a
explicita qaando
iro
impnrta,
putantq
ea ueqde uma
uerdadtiro
se lhe solicitarem
un
tipo de interface.
A Tabela 7-2
Arrays
e os
resume 11 das 13 classes concretas relativas a conjuntos que voc6 precisari conhecer para o exame. (Os a seguir!)
Iobelo
Classe
7-2
Mapa
Conjunto
Lista
Ordenado
Classificado
Hash-l.{ap
Nio Nio
X
Classificado
Nlo Nio
ordem natura/ ouregras de comparagio personalizadas N"ao
TreeMap
Por
LinkedHashMap X
Porordem
de
insergio ou
acesso N*ao
ultimo
HashSet
N"ao
TreeSet
Classificado
Por
ordem
natara/
LinkedHashSet
Por ordem
de insergio
Nio
JAVA
309
Arraylist
Vector
X X X
Linkedlist
Dri nri
+ lef
r;f'lrrarro Ysvsv
precisarntos /istar
as pegas
por nilmero
uti/iniio.
pacotelaua.utilpara umuer
eru uma
conuertendo-a
burca bindria oa
e arrqys.
arE
lista. (Jsar at intufacesjaua.util.Comparator elaua.kng.Conparablz para inflaenciar a classifcag1o dt l$as o efeito da "ordrnapdo natural" das classes atr@perprinitiuas e dejaua.kng.Stringsobre a classficagdo.
Fundamentos de Arraylist
A
6
classe java.util.Arraylist 6 uma das mais freqiientemente usadas de todas as classes da Estrutura dos Conjuntos. EIa como um array anabolizado. Algumas das vantagens que Arraylist tem em relagio aos arrays sio:
I I
Vejamos como se usa um Arraylist que contenha Strings. Um dos principais objetivos do projeto da Estrutura dos Conjuntos foi oferecer uma rica funcionalidade no nivel das principais interfaces: List, Set e Map. Na pritica, voc6 geralmente instanciari um Arraylist polimorficamente, desta forma:
r 'i ^F lIDL h.'r'i rrryufr af nar^r Arr:rzT.i d!!qj!rru\/, qj- / \ .
tipo de declaragio segue o principio da programaEio orientada a objetos de "programar para uma interface", e faz uso de gen6ricos. Falaremos muito mais sobre os gen6ricos mais adiante neste capitulo, mas, por agora, basta saber que, aparrirdoJava 5, asintaxe (String> 6amaneiracorreta de se declararo tipo de uma colegio. (Antes deJava5 nao hivia nenhuma maneira de especificar o tipo de uma coleglo e, quando abordarmos os gen6ricos, falaremos sobre as implicag6es de se misturar coniuntos Java 5 (digitados) e pr6-Java 5 (nio-digitados.)
De virias maneiras,
capaz de
Arraylist.<String> 6 semelhante a String ] , no sentido de que declara um container zen^r apenas Strings, mas que 6 mais poderoso do que um String J . Vejamos alguns dos recursos ^rm que um Arraylist possui:
il
*.
rl6ctArr^\rT.i
<f
e Coniuntos
(
test.
l-aqf
add
"string"
);
add/c\.
test.add(s+s); System. out.println System. out.println System. out . println test . remove ( "hi " ) ; System. out.println
(test. size ( ) ) ; (test. contains (42l, | ; ( test . contains ( "hihi " ) ) ; (test. size
(
));
])
o que Produz:
3
rda5e
true
2
H6 uma s6rie de coisas acontecendo nesse pequeno programa. Repare que, quando declaramos o Arraylist, nio demos ele um tamanho. Em segurda pudemos pedir que o Arraylist nos informasse o seu tamanho, pudemos pergu.ntar se ele continha determinados objetos, removemos um objeto que estava presente nele, e depois verificamos novamente o
tamanho.
List mylnts
int
podemos usar
mylnts.add(42)
Neste riltimo exemplo, ainda estamos adicionando um objeto rnteger o que acontece 6 que o autoboxing reaJizao encapsulamento para n6s.
myrnts
(e
nio um
int
primitivQ;
mas
i classificagio e busca foram adicionados ao exame paraJava 5. Tanto con untos quanto arrays podem ser classificados e busiados usando-se m6todos da API.
Classificando Coleg6es
Vamos comegar com algo simples, por exemplo, classificar um Arraylist de Strings alfabeticamente. Acha que isso deve ser ficil demais? Cino, esperaremos enquanto voc6 vai procurar o m6todo sdrt ( ) de Arrayl-ist... Entendeu? Araylist nio lhe fornece nenhuma maneiride classificar o ieu conterido, mas 6 claro que a classe iava.util.Collections fornece um:
import java.util.*,' class Testsortl { public static void maj-n(Stringll args) { ArrayList<String> stuff = newArrayliEt<String>()r
ct- rrf f
//
#1-
);
\
stuff
qfrrff
add ( "Boulder" ) ;
arirl /\\Iai
1
/ \
,l ;
JAVA
3I I
;
;
l/
#2
unsorted IDenver, Boulder, Vai]-, Aspen, Telluridel sort.ed [Aspen, Bou]der, Denver, Tellurj_de, Vaill
A linha 1 esti
declarando_ um Arraylist de Strings, e a linha 2 est6 classificando o Arraylist alfabeticamente. Falaremos mais sobre a classe Collections,.iunto com a classe Arrays, em uma segio posterior. Por ora, vamos nos ater i classificagio.
a melhor aplicagio de automagio de casas j|f.eita. Hoje, estamos nos concentrando no home theater, e mais especificamente no centro de controle do DVD. J6 temos o software de E/S paraler e screver dados entre o arquivo dvdrnf o . txt e as instAncias da classe ovornf o. Eis aqui os principais aspectos da classe:
class uvu-Lnto
C+e;Fp!rrrrv
.i Fl fLrLrs, ^.
String genre;
Strj-ng leadActor; DVDInfo(String t, String g, String a) { title = t; etenre = g; leadAct.or = a;
)
"
+ leadActor + \\\n"
Eis os dados de
Raiders of the Lost Ark/action/Ford, Harrison 200L/scL-fi/?? Caddy Shack/comedy/Murray, Bil-1 Star Wars/sci-f i/Ford, Harrison Lost in Translation/comedy/Murray, Bilt Pat.riot Games /action/Ford, Harrison
de automaqio de casas, queremos criar uma instAncia de D\rDrnf o Dara cadalinha de dados oue dvdinf o. txt. Para cada instAncia, faremos parsing dr linhr de dados (embra-sle de st.ring. split ( ) ?) e preencheremos as trAs variiveis de instAncias de ovbrnto. Finalmenre. oueremos colocar todas as instincias de nvntnto em um Arraylist. Imagine que o m6todo populatel,ist (') (abaixo) faga ' tudo isso. Eis um pequeno fragmento de c6digo do nosso aplicat'ivo:
No nosso aplicativo
tivermos lido
a
panir doarquivo
Arraylist<DVDfnfo> dvdlist = new Arraylist<DVDInfo> ( ) ; popul-atelis:uO; / / adiciona os dados do arquivo ao Arraylist System. out. println (dvdlist ) ;
Voc6 poderi receber uma saida como esta:
lDonnie Darko sci-fi Gy11enha11, .fake , Raiders of the Lost Ark action Ford, Harrison , 200L sci-fi ??
, Caddy Shack comedy Murray, Bill , Star Wars sci-fi Ford, Harrison
e Coniuntos
, Lost in Translat.ion comedy Murray, Bill , Patriot Games action Ford, Harrison
l (Observagio: N6s sobrescrevemos o m6todo
tostring )
(
;
toString ( ) de DVDInfo,.portanto,
para cada uma das instAncias.)
quando chamamos
println
TestDVD. java:13
j6 descobriu qual 6 o problema, n6s chutariamos que voc6 o fez sem a ajuda da obscura mensagem de erro airma.. Afinal, .o-o ,. classificam as insdnciai de DVDrnf o? Como 6 que n6s conseguimos classificar ^oxr^d^ de String? instAncias Quando voc6 consulta Collections. sort ( ) na API, a suaprimeirareagio poderia ser entrar em pAnico. Mas nio se desespere. Mais vmavez, a seglo dos gen6ricos lhe.ajudari a ler. a estranha assinatura desse m6toio. Se voc6 ler a descrigio do m6todo sort ( ) de um argumento, ver6 que esse m6todo usa um argumento List, e que os objetos em List precisam implementar umainterface chamada_Comparable. Ocorre que String implementa Comparable, e 6 por isso que-fomos capazes de classificar uma lista de Strings usando o m6todo
Se vocA
Collections. sort
A Interface Comparable
A interface Comparable
para classificar
e arrays de objetos, respectivamente..Para implementar Comparable, a classe precisa implementar apenas um m6todo, compareTo ( ) . Eis uma chamada de compareTo ( ) :
Lists
Cof
int x = thisObject.compareTo
O m6todo compareTo ( ) retorna um
(anotherObject)
int
com
as segu.intes caracteristicas:
I negativo Se thisobject < anotherobject I zero SethisObject == anotherObject I positivo Se thisObject > anotherObject
O m6todo
Como voc tem a opgio de implementaicompareTo ) crit6rios que desejaipara classificar as instAncias das suas classes'
(
ou o array de objetos deve ser classificado. para as suas pr6prias classes, poderi usar quaisquer
e usar a
Voltando ao nosso exemplo anterior para a classe DVDInfo, podemos optar pela solugio mais ficil implementaEio da classe String de compareTo ( ) :
// +r
//
+2
inf
nnmn:r6rlr^tf)\iT)Tnfn v vvrrwu!
d\
{
()
return title.coqrareTo(d.getTitle
])
DVDInfo implementa Comparable de uma forma tal que objetos DVDInfo objetos DVDInfo. Na linha 2, impllmentamos compareTo ( ) ao.compararmos os podem ser comparados ourros titulos dos dois objetos DVDInfo. IJmaurzque sabemos que os tirulos sio Strings, e que String imo_lementa Compirable, essa 6 uma maneira f6cil de classificar oi nossos objetos DVDlnfo: por titulo. Antes da introdugio dos gen6ricos, em Java 5, teria sido necess6rio implementar Comparable de uma forma parecida com esta:
Na linha 1, n6s declaramos que
a a classe
nexi stcnte
{
//
um
tipo especifico
JAVA
3I3
= return tit1e.
DVDInfo d
(DVDInfo)o;
compareTo (d.
gretTitle
));
]]
vilido, mas vocA.pode ver que nio s6 6 complicado como tamb6m arriscado, porque vocA precisa fazer uma conversio, e precisa verificar se a conversio nio vai falhar antes de tenti-la.
Isso ainda 6
oBSERVAQAO
pene o EXAME
Einpoftante/embrarque'quandosobresrezaequals O,uociprecisailsartlmargamentodotipoObjecL,ma!,quantlosobrescreae compareTo O , uocl deue lltar tlm argumento do tipo qae utd clatsfiundo.
Juntando tudo,
Qfrinn a|-rinn (t-rinn
a nossa classe
DVDInfo deveri
se
"+leadActor+"\n";
()
),
obteremos
[2001 sci-fi ?? , Caddy Shack comedy Murray. Bill , Donnie Darko sci-fi Gyllenhall, Jake
, , , ,
l
Lost in Translation comedy Murray, Bill Patriot cames action Ford, Harrison Raiders of the Lost Ark action Ford, Harrison Star Wars sci-fi Ford, Harrison
Viva! Nosso Arraylist foi classificado por titulos. E claro que, se quisermos que o nosso sistema de automagio de casas fique realmente bacana, provavelmente iriamos q.terer classificar coleg6is de DVDs de v6rias formas diferentes. Uma.vez que classificamos nosso Arraylisiimplementando o m6todo compareTo ( ), parece que estamos em um beco sem saida. 56 podemos implementar compareTo ( ) uma vez emuma classe,intlo como fazemos para classificar nossas classes em uma ordem diferente daquela que especificamos em nosso m6todo compareTo ( ) ? Boa pergunta. Por sorte, a resposta vem logo em seguida.
( ) , vocA deve ter reparado que existe uma versio soblecarregada de q9r_t (_) qre usa um List E algo chamado de Comparator ('comparado4. A interface Comparator lhe fornece a capacidade de classificar uma dada colegio de uma s6rie de formas difirentes. A outra coisa ritil sobre a interface Comparator 6 que voc6 pode uslJa para classificar insdncias de qualquer classe - at6 mesmo classes que voc6 nio pode modificar -, ao contr6rio de interface Comparable, que lhe iorgi a modificar a classe cujas instincias voc6 deseja classificar. A interface Comparator tamb6m 6 Eastante f6cil de implementar, rendo apenas um m6todo,
31
compare
g6nero.
().
Eis uma pequena classe que pode ser usada para classificar um List de instAncias de DVDInfo, por
import java.utiJ-.*; class Genresort implements Comparator<DVDlnfo> { public int compare(DVDInfo one, DVDfnfo two) t return one. getcenre ( ) .compareTo (two. getcenre ( ) ) ;
)
cujo significado 6 o mesmo do valor de retorno do m6todo Comparable. compareto i. Neste caso, estamos tirando vantagem disso ao pedir que compareTo ( ) faga o trabalho de comparaglo para n6s. Eis um programa de teste que nos permite testar tanto o nosso c6digo Comparable quanto o nosso novo c6digo Comparator:
int
imnnrf 'imnnrt-
iarrr i:rr:
rrfil in *.
*.
//
diStO
public cl-ass
TestDVD
{
(
Arraylist<DVDInfo> dvdlist = new Arraylist<DVDlnfo> pubLic static void main(Stringll arqs) i new TestDVDO.goO;
]
n"].'lia vuvfru nnnrrl vvrs "^.iz{ afaT.i aal\ \ / Yv c|- I I .
.
println ( dvdlist
I\ I
);
]
vgv+4vwvfgyvyg4l4
nrrl.rlin
rrnid
nnnrr'lat-6T.icl-
/ 16 o arquivo, cria j-nstAncias de DVDInfo e // preenche o Arraylist dvdlist com essas instAncias
]
)
VocA
ji viu as duas primeiras listas de saidas, eis a terceira: IPatriot Games action Ford, Harrison , Raiders of the Lost Ark action Ford, Harrison
,
a:rtdrr vusvJ
ehaaL
nnmadrr
vvrrresj
M11rr^\/ r eJ
rrsr
Ri l
, , , ,
l
Lost in Translation comedy Murray, Bill 200L sci-fi ?? Donnie Darko sci-fi Gyll-enhall, Jake Star Wars sci-fi Ford, Harrison
Pelo fato de as interfaces Comparable e Comparator serem tio parecidas, estera atento para o fato de que o exame poderi tentar lhe confundir. Por exemplo, poderia ser pedido que voc6 implementasse o m6todo compareTo ( ) na lnterf.ace Comparator. Estude a Tabela 7-3 para memorizar as diferengas entre essas duas interfaces.
JAVA
3I5
iava.lang.Comparable
java.util.Comparator
int
int
compare
(objOne,
objT\ryo)
< objTwo
Vod
cujas
a classe
irstincias
deseja classificar.
Podem sercriadas muitas seqiiAncias Elaborada para ser implementada com o obietivo de classificar instAncias de outras classes.
&
classificaglo.
Collections. sort O . I Arrays. sort (arrayToSort) I Arrays. sort (arrafloSort, Comparat.or) Al6m disso, o m6todo Arrays . sort ( ) 6 sobrecarregado zilh6es de vezes para fornecer alguns m6todos de classificagio para todos os tipos de primitivos. Os m6todos Arrays . sort i ) qn classificam tipos primitivos
s.emPle o com base na ordem natural. .fazem de primitivos usando um Comparator.
Nio
se engane
vm array
sort ( ) tanto para a classe Collections quanto para a classe Arrays sio que eles alteram os objetos que esteo chssificando, emvez de retornar um objeio classificado de iorma
pene O EXAME
diferente.
oBSERVAQoTS
l{isfalamos um bocado nbre a clastifcapdo por ordem nataral e nbre o aso de Comparatorc para classficar. A r)ltina regra qae uocd preasani memoriTar 6 que, tempre qile quiser classificar ilm affal oa um coiunto, os elementos contidos nesses objetos deuem vr todos
mataamente companiueis.
Em oatrat pa/atras,
se uocd tiuer
un Obj ecL
e colocar obietor
CaE e Dog
clasfici-k. Em geral,
vr
considerados cono
NAO
nio
I I r
binarySearch
()
int do elemento sendo procurado. Buscas mal-sucedidas retornam um indice int que representa o ponto de insergdo. O ponto de insergio 6 o lugar no conjunto/ array onde o elemento seria inserido para manter o conjunto / array corretamente classificado. Pelo fato
de valores de retorno positivos e O indicarem buscas bem-sucedidas, o m6todo binarySearch ( ) usa nrimeros negativos para indicar pontos de insergio. lJma vez que 0 6 um resultado vilido para uma busca bem-sucedida, o primeiro ponto de inserglo disponivel 6 -1. Assim, o ponto de insergio 6 realmehte represenrado como (-(ponto de insergio) -1). Por exemplo, se o ponto de insergXo de ,rma busca estiver no elemento 2, o valor real do'fonto retornado ser6 -3.
r O conjunt o/ anay onde esti sendo feita a busca deve ser classificado antes que voc6 possa procurar nele. I Se voc6 tentar procurar em um array ou conjunto que ainda nio foi classificado, os resultados da busca nXo serio
prevrsrvers.
Se
nessa mesma
o conjunto/array em que voc6 deseja-procurar tiver sido classificado na ordem natural, a busca deve ser feita ordem. (Isso 6 feito ao NAO se enviar um Comparator como argumento para o m6todo
3l6
binarySearch
( ) .)
Se
o conjunt o/array em que voc deseja procurar tiver sido classificado com um Comparator, a busca deue ser feita usando-se o mesmo Comparator, que 6 passado como o segundo argumento ao.m6todo binarySearch ( ) ' Lembre-se de que Comparators nio podem ser usados ao se buscar em arrays de tipos primitivos.
binarysearch
()
import java.util.*; class SearchObjArray { public static void main(String [] args) String [] sa = {"one" Arrays.sort(sa) , for(String s : sa) System.out.print(s + " ");
q1r<fam nrrf nrinjlnl\r\nnno ='\
,,
Ot
+Arrays.binarySearch(sa,"one"));
System.out.println("now reverse sort") ; ReSortComparator rs = new Resortcomparator0; Arrays . sort ( sa, rs ) ; for(String s : sa) System.out.print(s + " ")'
q\/qfam nrrinrinlln{"\nonc = "
//
#2
+3
+Arrays.binarySearch(sa,"one"));
Qrr<l-om rf r ue.rL. ^rrf vqL
,
//
/
#4
^-i-ts]h/\^FA P! IIf L If I \
vrlE
Arrays.binarySearch(sa,"one".rs)) ;
#5
I t
// //
#6
returnb.compareTo(a);
)
#7
]
)
four one three two one=1 now reverse sort two three one four one = -1 one=2
Eis o que aconteceu:
Linha
1. Classifica o
Linha2 Procura
Linha
*um", que 6 1.
3 Cria uma
binarySearch ( ) o Comparator
que
o arr^y,
e,
binarySearctr
( ) . Desta
permitido que
interna.
JAVA
5 3I7
na chamada a
compareTo
),
pene O EXAME
reto/uer quesldes sobre busca e classifcap1o, os dois errot mais cotzuns tdo:
l.
2. Usar um Comparator
Procurar em tlm an"El ou conjunto que ndo tenha sido c/assficado. oa sd na classifcagdo ou sd na basca, mas ndo em ambas.
possuem
O m6todo Arrays . aslist ( ) copia um array para dentro de um List. A API diz, "retorne uma lista de tamanho fixo baseada no array especificado (modificag6es feitas na lista retornada sio escritas diretamenre no array)." Quando
voc6 usa o m6todo
outro
asl,ist
como
se fossem
String[] sa = {"one"
List slist = Arrays.aslist(sa); System.out.println("size " + s],ist.sizeO System.out.println( "idx2 " + sl-ist .geL(2)
qT,iqtqal- /? "qiv.\
/
)
;
/ cria
um
List
|;
sa[1] = "five";
fnrlQfrind c . <al
(1) ) ;
produz
sj-ze
Agora vamos dar uma olhada no m6todo toArray ( ) . Nio hA nada de muito espetacular acontecendo com o m6todo toArray ( ) ; ele tem dois tipos: um que retorna um novo array Object, e um que usa o array que voc6 envia para ele como o xray de destino:
Object[] oa = iL.toArray(]; Integerll taz = new Integer[3]; ia2 = iL. toArray (ia2) ;
Usando Lists
/ /
tri
rrm
*--*r =rrarr
:rr:\/
Al _JlecE.
/ /
rri
rrn
Tnf
6ft6r
Lembre-se de que os objetos List sio usados normalmente para manter as coisas em ordem, de alguma forma. Voc6 pode usar um Linkedlist para criar uma fila no estilo primeiro-a-entrar-primeiro-a-sair. Voc6 pode usar um Arraylist paru manter registro dos locais que visitou, e em qual ordem. Repare que, em ambos os exemplos, 6 perfeitamente nzoAvel pressupor que possam ocorrer duplicatas. Al6m disso, os Lists lhe permitem modificar manualmente a ordenagio dos elementos, ao fornecer a capacidade de adicionar ou retirar elementos usando-se os seus indices. Antes deJava 5, e do loop f or aprimorado, a maneira mais comum de se examinar um List "elemento por elemento" era usando-se um Iterator. Voc6 ainda encontrarilterators sendo usados em c6digosJava que encontrar, e 6 possivel que encontre alguns deles no exame. Um Iterator 6 um objeto associado com um conjunto especifico. Ele lhe permite fazer um loop atrav6s do conjunto, um passo de cadavez. Os dois m6todos Iterator que vod precisa conhecer para o exame sio:
e Coniuntos
I boolean
haelilext
Retorna
true
se
houver pelo menos mais um elemento no conjunto em que esta o foco para o pr6ximo elemento do conjunto.
I object next ( )
imnnrti:rra
Este m6todo retorna o pr6ximo objeto do conjunto, E move o foco para o elemento que vem depois daquele que acabou de ser retornado.
cfass
yuvrfv ^"1-'1
Dogr {
ia efrinn n:ma.
Dog(String n) { name = n;
]
class rtTest { public static void main(String[] args) List<Dog> d = new Arraylist<Dog>O; Dog dog = new Dog("aiko");
d :Ari ldnn\
.
ll cria un Lteragor
/
System.out.println("size " + d.size() ) ; System.out.println("getl- " + d.get (1) .name) ; System.out.println("aiko " + d.indexOf (doS) ) ;
d. remove (2 ) ;
produz
aiko
clover
magnolia
oa aiko
oa clover
Primeiramente, n6s wamos a sintaxe dos gen6ricos para criar o Iterator (um Iterator do tipo Dog). Por causa disso, quando usamos o m6todo next O , nlo precisamos converter o Object retornado por next O em um Dog. Poderiamos ter declarado o Iterator desta forma:
Dog d2
(DoS)
i3.next
JAVA
319
O restantedo c6digodemonstraousodosm6todos
). Nloh6nadade
novo em nenhum desses m6todos. Daqui a algumas piginas, a Tabela 7-5listaritodos os m6todos de List, Set e Map com os quais voc6 dever6 estar familiarizado para o exame. Como um riltimo aviso, lembre-se de que List 6 uma
interface!
Usando Sets
Lembre-se de que os Sets slo usados quando voc6 nio quer ter nenhuma duplicata no seu conjunto. Se tentar adicionar um elemento a um Set que j6 exista nele, o elemento duplicado nio ser6 adicionado, e o m6todo add ( retornari false. Lembre-se, HashSets tendem a ser bastante ripidos porque, como vimos anteriormente, eles usam c6digos de
hashing. Voc6 pode tamb6m criar um TreeSet, que 6 um Set cujos elementos sio classificados. E preciio rer caurela ao se usar um TreeSet (6 explicaremos o porqu6):
imnnrli:rra rrf il *.
class SetTest { public static void main(String[] argrs) boolean[] la = new boolean[5.t ; // insira c6d.igo aqui
bat01 = s.add("a"); ba[1] = s.add(new Integer(421); ba[2] = s.add("b");
h:f?l = c aAdlse/\.
ba[4] = s.add(new ObjectO ); for(int x=0; x<ba.length; x++) System.out.print(ba[x] + " "); System. out.println ( " \n" ) ;
fnrt0h'ioat n . <\
true true true false true e iarra I:nc. Ohiect@e09713 42 b E i*pon.nt. saber que a ordem dos objetos exibidos no segundo loop for nXo 6 previsivel: Hashsets e LinkedHashS.S garantem nenhum.tipo & ordenagio. Al6m disso, repare que a quarta chamada a add ( 1 falhou,
""g porque tentou inserir uma entradaduplicada (uma String com o valor a) no Set.
Se
Exception in thread "main" java.lang.ClasscastExceptlon: java. 1ang. String at j ava. lang . Integer . compareTo ( Integer . j ava: 3 5 ) at java.util-.TreeMap. compare (TreeMap. java : 1093 ) at java.util.TreeMap.put. (TreeMap. java: 465) at java.util.Treeset.add(TreeSet. java: 210)
A questio
6 que, sempre que voc6 quiser classificar um conjunto, os seus elementos deverlo ser mutuamente compariveis. Lembre-se !e que, a nio ser que seja especificado o contr6rio, objetos de tipos diferentes nio sio mutuamente comPaf avers.
e Coniuntos
Usando Maps
Lembre-se de que, quando voc6 usa uma classe ftIash) que implementa Map, quaisquer classes que usar como. parte questio deverio sobrescrever os m6todos hashCode O e equals O . @em, voc6s6 das chaves pari o ^apaem precisa sobrescrev&los se tiver interesse em obter informag6es do Map. Mas falando s6rio, 6 vilido usar uma classe que nlo sobrescreva equals ( ) e hashCode ( ) como chaves em um Map; seu c6digo iri compilar e rodar, voc6 s6 nio conseguir6 obter informaglo nenhuma.) Eis algum c6digo demonstrando o uso de um HashMap:
imnarr iarra { rrfil *.
cl-ass Dog
public Dog(String n) { name = n; } public String name; public boolean equals(Object o) { if ( (o instanceof Dog) aa ( (DoS)o).name == name) ) { reEurn true; ) else return false; i
1
public int
)
hashcode
(return
name.lengTthO
; l
class Cat {
enum
Pets
al
acc
ManrFact
new
Pets.DOG)
m.put (Pets.CAT, "CAT key" ) ; Dog d1 = new Dog("clover"\; // vamos manter esta refer6ncia m.put(d1 , "Dog key"); m.put(new CatO , "Cat key") ;
System.out.println(m.get("k1") ) ; / / #1, String k2 = "k2"; System. out.printLn (m. get (k2) ) ; / / #2 Pets p = Pets.CAT,. System.out.println(m.get (pl ) ; / / #3 System,out.println(m.get (dI) ) ; / / #a System.out.println(m.get(new Cat O ) ) ; / / System. out.println (m. size (l ) ; / / #6
]
o que produz algo como isto:
Dog@1c
DOG
#5
JAVA
32I
CAT key
Dog key
nul-l5
Vamos estudar a saida. O primeiro valor obtido foi um obieto Dog (o seu valor poderi ser diferente.) O sezundo valor obtido foi um valor enurn-(DOG). O terceiro valor obtido foi umJStrine: reDara oue a chave 6 um vilor erium. Teste r6pido: qual 6 a implicagio'do fado de rermos conseguido usar enum .orio ,rrn. chave?
A implicagio disso 6 que enums sobrescrevem equals O e hashCode ( ). E, sevoc6 consultara classe java.lang.Enum na API, ver6 que, de fato, esses m6todos foram sobrescritos.
saida 6 uma String. O ponto mais imponante sobre essa saida 6 que a chave usada para obter a String 6 composta de um objeto Dog. A quinta saida 6 nu 1 1 . O ponto imponante aqui 6 que o m6todo Se t ( ) nio conseguiu encontrar o objeto Cat que fora inserido anteriormente. (A riltima linha da saida confirma que, de fato, exisrem cinco pares de chaves,/ valores no Map.) Por que nio conseguimos achar a String com chave Cat? Por que foi possivel usar uma instAncia de Dog como chave, enquanto que usar uma instAncia de Cat como chave nio teve sucesso?
A quana
Eficl.rer
equals
()e
hashCode
(),
Vamos dar uma olhada r6pida nos c6digos de hashing. IJsamos uma f6rmula de c6digo incrivelmente simplificada na classe Dog - o c6digo de um objeto Dog 6 do tamanho do nome da instAncia. Assim, neste exemplo, o c6digo = 4. Vamos comparar os dois seguintes m6todos hashCode ( ) :
// //
+1,
#2
Hora de mais um teste r6pido: os dois hashcodes acima sio v6lidos? panir de um Map? Qual deles ser6 o mais r6pido?
As respostas para
terio
sucesso em
obter objetos
as duas primeiras perguntas sio Sim e Sim. Nenhum desses c6digos de hashing ser6 muito eficiente (na verdade, eles seriam ambos incrivelmente ineficientes), mas ambos sio v6lidos, e ambos funcionario. A resposta ) riltima pergunta 6 que o primeiro c6digo seri um pouco mais ripido do que o segundo. Em geral, quanto mais singulares os c6digos criados por uma f6rmula, mais r6pida ser6 o obtengio de dados. A primeira f6rmula acimairi gerar um c6digo diferente para a extensio de cada nome (por exemplo, o nome Roberto ir| gerar um c6digo, e o nome Pedro i-r.6gerar um c6digo diferente). A segunda f6rmula iri sempre produzir o mesmo resultado, 4, e,por isso, serl mais lenta do que a primeira.
O nosso ultimo t6pico relacionado a Map 6 sobre o que acontece quando um objeto usado como chave tem os seus valores modificados. Se adicionarmos duas linhas de c6digo ao MapTest . main ( ) anterior,
d1.name = "magnofia"
vJ
q1/<|-6m
e LvfrL
^rr|vsv
. yr
nrirt4rf
e+
lnlm
nat. ld'l\\.
CAT key
Dog key
nul1
5
nu11
usada para ser encontrado. Pelo fato de a variivel Dog . name ser criar o c6digo de hashing, modificar o nome causa a modi{icaglo do c6digo. Como um rtltimo teste relacionado aos c6digos, determine a saida das seguintes linhas de c6digo, caso elas sejam adicionadas ao final de
MapTest.main
()
d1.name = "magnolia";
System.out.println(m.get(d1 ));
d1.name =
dl- . name
//
/
#L
"clover"; / /
#2
System.out.println(m.get(new Dog("clover") ) );
#3
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
Tendo achado a gaveta correta (a gaveta "tamanho de name : 6"), o m6todo equals ( ) 6 chamado e, uma vez que o m6todo equals O de Dog compara nomes, equals O tem sucesso, e a saida 6 oog key. Na terceira chamada a set O, ot.rr.doc6digo temsucesso, mas otestede equals O falhaporque arthur NAO 6 igual a clover.
a algumas paginas, a Tabela 7-5
Daqui
exame.
resumir6 os m6todos
os quais vocA
i mnnrf
i:rz: {
rr
I i 'l
class PQ static
class PQsort implements Comparatorclnteger> { public int compare(Integer one, fnteger two) return two - one;
)
/
{
ordem inversa
rrnl-rnvina
/ /
();
/ usa a
aarranz:
//
for(int x : ia)
System.out.print(pq1 .poll() + " ");
System. out
.
// revisa a fila
(
println
"");
PQsort pqs = new PQsort ( ) ; Prj-orityQueue<Integ'er> pq2 = new PriorityQueue<Integer> ( 10, pqs ) ; for(int x : ia) // carrega a fila
na? nffar 1v\
obL6m um Comparator
// usa o Comparator
System.out.println("size " + pq2.sizeO ) ; System.out.println("peek " + pq2.peekO ) ; System.out.println("size " + pq2.sizeO ) ; System.out.println("po11 " + pq2.po11 O ) ; System.out.println("size " + pq2.sizeO ) ; for(int x : ia) // revisa a fila System.out.print(pq2.po1l 1 I + " ") ;
JAVA
323
Esse c6digo
1356789
sj-ze peek
7
9
size
7
9
poll
exame.
capitulo; por agora, pense nela como significando "qualquer array que NAO seja um
DescriE6es
C-onvene um ar:ry em um List (e vincula um ao outro).
static int binarySearch (Object[ ],k"y) static int binarysearch (primiLive [ ] , key) static int binarySearch (T[ ], key, Comparator) static boolean equals (Object[ ], Objectt I ) static boolean equals (primitive[ ], primitive[ public staticvoid sort (Object[ ] ) public static void sort (primitive [ ] public staticvoid
)
Procuram em urn array classificado por um dado valor, retornam um indice ou ponto de insergio. Procura um valor em um array classificado com Comparator. Comparam dois arrap para determinar se os seus conteridos sio iguais. Classificam os elementos de um arrav por ordem natural.
Classifica os elementos de um array usando um
public static String tostring (Object[ ] ) public static String toString (primitive [
e Coniuntos
DescriE6es
Procuram em um List "classificado" por um valor, retornam um indice ou ponto de inserglo.
static int binarySearch (List, key) static int binarysearch (List, key, Comparator) static void reverse (List) static Comparator reverseOrder ( ) static Comparator reverseOrder (Comparator) static void Eort (List) static void sort (List, Comparator)
No
List
Set
Mop
DescriE6o
Adicionam um elemento. Para Lists, opcionalmente adicionam o elemento em um ponto indice.
Procuram em um conjunto por um objeto (ou, opcionalmente, por Maps com urna chave), retornam o resultado como um valor booleano. ObtAm um objeto de um conjuntq atrav6s de um indice ou uma chave-
boolean add (element) boolean add (index. element) boofean contains (object) boolean containsKey (object key) bool-ean containeValue (obj ect value)
object get (index) object get (key) int indexOf (object) Iterator iterator
(
)
Set keyset,
valor a um ldap.
Removem um elemento atrav6.s de um indice, do valor do elemento ou de uma chave. Retorna o nrimero de elementos de um coniunto. Retornam um arraycontendo os elementos do conluruo.
x
(1
peekO
Para o exame, os m6todos de PriorityQueue que vocA precisa entender sio of f er O (que 6 semelhante a add O ), (que obt6mo elementono iniciodafila, masnio o apaga) epo11( ) (que obt6m oprimeiro elementoe o remove da fila).
natural. O rcguinte
cddtgo lhe
qudm,l a entender
as
JAVA
325
String[] sa = {"tf f.", f<'i\, \,>f <,,, l,>FF<\\ }; / / est6. ordenado? PriorityQueue<String> tre3 = new Priorj-tyeueue<String> ( ) ; for(String s : sa)
\\>
na? nffarlc\
.
> f<
exane,
>FF<
Se uoc6 se /embrarque os espaEot sdo cobcados antes dos caracteres e qae at lehas
API
API
e as clatses de implenentagio.
nitodns
6.4 Desenuoluer aidigo qae use @mpriadanente os parhmehts de tipo en declaragdes de clasnsf intufacu, uaridueis dz insti.ncias, argamentos de e tips fu ntomol e esoa,vr mdtodas gmtfrns oa mdtodos qac usem tipos rtringas, e entender as sene/banpar e d{ewryat mhv essas daar abordagns.
Os arrays em Java sempre foram de tipo especifico - um array declarado como do tipo String (string t J ) nio 6 capaz de aceitar Integers (ou ints), Dogs, ou qualquer outra coisa que nio sejam Strings. Mas lembre-se de que, antes de Java 5, nlo havia nenhuma sintaxe para declarar um conjunto com esse mesmo comportamento. Para criar um Arraylist de Strings, voc6 usava:
);
havia nenhuma sintaxe que lhe permitisse especificar que mylist usaria Strings e somente Strings. E, nio havendo nenhuma maneira de especificar um tipo para o ArrayList, o compilador neo podia forg6Jo a colocar apenas coisas do tipo especificado na lista. A partir de Java 5, podemos usar os gen6ricos e, embora eles nlo sirvam apenas para criar coniuntos de tipo especifico, 6 s6 para isso que a maioria dos desenvolvedores usa os gen6ricos. Assim, embora os gen6ricos nio sirvam apenas para conjuntos, considere que os conjuntos 6 a principal razio e motivagio para os gen6ricos terem sido adicionados ) linguagem.
Nio
E essa nio foi uma decisio f6cil, nem foi uma adigio inteiramente bem-vinda. Isso porque, junto com capaci&de de se usar tipos especificos, os gen6ricos v6m com uma consider6vel bagagem - a maior pane vod nunca ver6 nem ter6 de se preocupar com ela, mas existem algumas quest6es que surgem de forma str4rreen&ntemente r6pida Abordaremos aquelas mais prov6veis de aparecer no seu pr6prio c6digo, que sio tamMm as questSes que vocA precisar6 conhecer para o exame.
O principal desafio para a Sun, ao adrcionar os gen6ricos ) linguagem (e o principal motivo pelo qual demoraram tento), foi como lidar com c6digos antigos escritos sem os gen6ricos. Os engenheiros Java da Sun obviamente neo queriam estragar todos os c6digos Java existentes, enteo, tiveram de encontrar uma maneira de as classes Java com tipo especifico (gen6ricas) e as sem tipo especifico (nXo-gen6ricas/pr6-Java 5) conseguirem funcionar juntas. A solugXo encontrada nlo foi a mais amig6vel, mas ela lhe permite usar c5digo antigo, nio-gen6rico, ao mesmo tempo usando c6digo gen6rico que trabalha juntamente com c6digo nio-gen6rico. Mas perceba que dissemos "trabalha", e nio que
"trabalha BEM".
Embora vocA possa integrar c6digo gen6rico Java 5 com c6digo antigo, nio-gen6rico, as conseqiiAncias podem ser desastrosas e, infelizmente, a maioria dos desastres ocorrem em tempo de execugio, e nio de compilagio. Felizmente, no entanto, a maioria dos compiladores geram avisos que lhe informam quando voc6 esti usando conjuntos nioseguros (significando nio-gen6ricos).
e vocA veri quest6es que esperam que voc6 entenda os complexos problemas que podem surgir quando mistura c6digo nio-gen6rico com gen6rico. E, como alguns dos outros t6picos deste livro, seria possivel escrever um livro inteiro se f6ssemos abordar
O exame Java 5 aborda conjuntos tanto no estilo pr6-Java 5 (nio-gen6rico) quanto no estilo Java 5,
e Coniuntos
todos os detalhes sobre os gen6ricos, mas o exame (e este livro) aborda mais do que a maioria dos desenvolvedores precisar| usar na prinica.
Eis uma revisio de um Arraylist pr6-Java 5 criado para armazenar Strings. (Dissemos "criado" porque isso era tudo o que voc6 podtafazer - criar o conjunto -, mas nada garantiaque o Arraylist iria armazenar apenas Strings).
List mylist
mrrT.i
= new
ArraylistO; //
/ /
mylist.add(new
Isso significava que era responsabilidade total do programador ser... Cuidadoso. Nlo ter nenhuma maneira de garantir o tipo do conjunto nio era muito amistoso para o programador em um linguagem tio rlgtda com relagXo aos tipos. Estamos tio acostumados com o compilador nos impedindo de, por exemplo, atribuir um a uma refer6ncia booleana ou uma String a uma refer6ncia Dogl rn?s' com os coniuntos, a hist6ria era "pode entrar! A porta esti sempre abena! Todos os objetos sio bem-vindos aqui a qualquer hora!"
int
E, uma vez que um conjunto podia armazcnar qualquer coisa, os m6todos que retiram objetos do conjunto s6 podiam ter uma esp6cie de tipo de retorno - java.lang.Object. Isso significava que, para retirarmos uma String da nossa lista que-devia-armazcnar-silStnngs, era preciso uma conversio:
(0)
E uma vez que nio era possivel garantir que o que estava saindo era realmente uma String (uma vez que era possivel colocar qualquer coisa na lista), a conversio podia falhar em tempo de execugio.
Assim, os gen6ricos cuidam dos dois extremos (inserir e retirar informag6es) ao forgar o uso de um tipo especifico nos seus conjuntos. Vamos atualizar a lista String:
List<String> mylist = new Arraylist<String> ( ) ; mylist . add ( "Fred" ) ; / / OK, armazena SLrings mylist.add(new Dog( ) ) ; / / erro de compilagSo !
!
E, e"ata-ente isso o que queriamos. Ao usar a sintaxe dos gen6ricos - o que significa colocar o tipo entre sinais de maior e menor ( String , estamos dizendo ao compilador que esse coniunto s6 poder6 armazenar ob.ietos String. O tipo declarado dentro dos sinais 6 conhecido como "tipo parametrizado", "parAmetro de tipo" ou, 6 claro, o nosso bom e velho "tipo". Neste capitulo, iremos nos referir a ele usando os dois novos termos tamb6m.
Perfeito.
Entio, agora que garantimos o tipo do que seri INSERIDO, voc6 pode tamb6m garantir o tipo do que ser6 RETIRADO, e isso significa que voc6 pode se livrar da conversio quando receber algo do conjunto. Em vez de:
/ era garantido
String
(0 ) ;
O compilador j6 sabe que mylist cont6m apenas coisas que podem ser atribuidas a uma refer6ncia String, entXo, nio 6 mais necessirio usar uma converslo. At6 aqui, tudo parece bem simples. E, com o novo loop for, 6 claro que
voc6 pode fazer iterag6es atrav6s da lista de Strings:
for (String s : myl,ist) { int x = s.lengtho; / / n6,o 6 preciso converter antes de chamar um m6todo string!
/ / compilador j6 sabia que \rs" era uma String vindo de Mylist ]
E, 6 claro, vocA pode declarar um parAmetro de tipo para um argumento de m6todo, que, enteo, transforma o argumento em uma referncia de tipo especifico.
JAVA
327
void t.akel,istOfStrings (List<String> strings) { strings. add ('.foo', ) ; / / adiedo de uma String
)
sem problemas
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 ( )
{
(
inserir
dogs
de retornar qualquer coisa que nio seja compativel com um Set(Dog) (embora essa questlo de o que 6 e o que nio 6 compativel ficari bem interessante logo a seguir). IJma vez que o compilador garanta que apenas um DogSet de tipo especifico ser6 retornado, os objetos que chamarem o m6todo nio precisario de uma conversio para retirar Dogs do Set:
O compilador o impedir6
Dog
d = getDoglist0.get(0); // fr
getDoglist ( ) seria
Dog
(A conversio neste exemplo aplica-se ao que vem do m6todo seL ( ) de Set; n6s nio estamos conveftendo o que retornado do m6todo getDoglist ( ) , que 6 um Set)
E quanto ao beneficio de um conjunto completamente heterogeneo? Em outras palavras, e se voc6 gostasse do fato de que, antes dos gen6ricos, era possivel criar um Arraylist que armazenasse qualquer tipo de objeto?
List mylist
Arraylist<Object> O; / / armazea
QUALQUER
tipo de objeto
Declarar um List com um parAmetro de tipo < Object > cria um conjunto que funciona quase da mesma forma que os conjuntos pr6-Java 5, nio-gen6ricos - 6 possivel colocar QUATQUER tipo de Object no conjunto. VocA veri mais adiante que os conjuntos nio-gen6ricos e os conjuntos de tipo < Object > nio sXo completamente similares, mas, na maior parte do tempo, as diferengas nio imponam.
se isso fosse o fim da hist6ria... Mas ain& existem algumas quest6es complicadas referentes a argumentos de rn6todos, polimorfismo e a integragio entre c6digo gen6rico e niogen6rico, de modo que estamos apenas nos aquecendo aqru.
Ah,
e Coniunlos
^r
c{- 1\ oL \ /
se
torna
Moleza. E se houver c6digo que usava a verseo nio-gen6rica e realizavauma conversao para obter coisas, isso nio vai e$ragar o c6digo de ningu6m:
Thf^d6t frrLc:jer fi /Tnranar\ \rrrLsvs!/
list.get(0li
// a conversSo ndo 6 mais necess5ria, / / mas deix6-1a aqui ndo causar6 problemas
uma
um
conjunto gen6rico
'imnnrf
public class Testlegacy { public static void main(String[] args) { List<Integer> myl,ist = new Arraylist<Integer>
|
)'
aenanifinn
esyve
// |
.^n"irlnl-^
vv.LJ
da
fLfyvinn
mylisr.add(4); myl,ist.add(6); Adder adder = new eddero; int total = adder.addall(myl,ist); // passado para System. out.println (tota1 ) ;
]
Eis a classe antiga, nio-gen6rica, que queremos usar:
'imnnrf i:rr: rrt- i'l *.
um argumento sem
tipo
class Adder { int addA]1(List list) { / / m6todo com um argumento List n5o-gen6rico, / / mas assume (sem garantia nenhuma) gue serSo Int.egfers Iterator it = 1ist. iterator ( ) ; int total = 0;
JAVA
329
))
intValue(
return total;
) Sim, fu-nciona sem problemas. E possivel misturar c6digo gen6rico correto com c6digos anrigos, nio-gen6ricos, e todos
ficam felizes.
( ) presumiu (confiou? torceu?) que a lista passada estava de fato restringida a Integers, mesmo que, quando o c6digo foi escrito, nio houvesse nenhuma gararfiia. Era responsabilidade do programador ser cuidadoso.
addAll ( ) nio estava fazendo nada, exceto obter o Integer (usando uma conversio) de uma lista e acessar o seu valor, nio houve problemas. Nesse exemplo, nio houve nenhum risco para o c6digo do chamador, mas o mtodo antigo poderia ter falhado caso a lista que foi passada contivesse qualquer coisa que nio fosse um Integer (o que teria causado uma ClassCastException).
Umavez que o m6todo
Mas, imagine agora que voc6 chame um m6todo antigo que Ser6 que vai funcionar?
nio
apenas leia
um valor, mas
adicione algo ao
Arraylistl
import java.util.*;
nrrl-r'l i a nl:c< rn6ciR^dT.6dA^1r s\4\4seYsvj I
L
myl-ist.add(6);
class Inserter { // m6todo com um argumento List nao-gen6rico void insert(List list) { list.add(new Integler(42)\; // adiciona d lista a ser recebida
) )
Ceftamente, esse c6digo funciona. Ele compila e executa. O m6todo insert ( ) coloca um Integer na lista que fora originalmente declarada como ( Integer ) , portanto, nlo h6 nenhum problema. Mas... E se modificarmos o m6todo
<anAa
]
Ser6,
que isso vai funcionar? Sim, infelizmente funciona! Isso compila e executa. Nenhuma exceglo de tempo de execugio. Ainda assim, algu6m acabou de colocar uma String em um Arraylist que deveria ser exclusivo do tipo
(Integer).
Lembre-se de que o c6digo antigo permitia que se colocasse qualquer coisa (exceto tipos primitivos) em um conjunto. E, para dar suporte aos c6digos antigos, Java 5 permite que os c6digos novos, com tipos especificos, usem c6digos antigos (a ultima coisa que a Sun queria era pedir que milh6es de desenvolvedores Java modificassem todos os seus c6digos existentes).
e Coniuntos
Assim, o compilador Java5 6 forgado a permitir que voc6 compile oseu c6digo novo mesmo que ele chame um sem tipo especifico, e faga deus-sabe-o-qu6 com ele. m6todo de ,tma classe antiga que usa rr-
Entretanro, s6 porque o compiladorJava 5 permite que esse c6digo compile, nio quer {ize1 que ele fique FELZ com isso. Na verdade, oiompilador iri thi advertir de qG est6 assumindo um grande, {ande risco ao enviar o seu excelente Arraylist ( Integer ) para um m6todo perigoso que pode inserir Floats, Strings ou at6 mesmo Dogs na sua
lrsta,
"rgorn"nto
(simplesmente Quando voc6 chamou o m6todo addall ( ) em um exempl_o anterior, ele nio inseriu nada nalista adiciorrou os valores dentro do conjunto), de forma que nio houve risco, para o chamador, de que a sua lista fosse modificada de alguma forma horrivel. O c6digo compilou e executou sem problemas. Mas, na segunda versXo, com o m6todo antigo insert ( ) que adiciona uma String, o compilador gerou um aviso:
NoLe: TestBadlegacy.java uses unchecked or unsafe operations. Note: Recompile with -Xfint:unchecked for details.
lrmbre-se de que os auisos do runpiladlrNAo sdo consifuradot un erm dr compikgdo. O compilador gerou um arquivo de classe perfeitamente v6lido a partir & compilagio, mas foi gentil o suficiente para lhe dizer o _equivalente a: ."Eu esPero ieriamente que voc6 saiba o que esta fazendo,porque este c6digo antigo NAO tem nenhum respeito (e nem conhecimento) do seu tipo especifico ( lnteger ) , e poderi fazer o que quiser com o seu precioso
Arraylist(Integer)".
OBSERVAQ6ESpeneOE)(AME
Certifqa*se
de saber a dfervnga entre "a compila4dofalha" e "conpila rem enos", e enhe
'bonpila
fardo
diferenga
Porin, quando
uoc| estiaer usando gendricot e misturando aldigo com e sem tipos especlfcos, ot auisos passam
afaryr difmnga.
De volta ao nosso exemplo com o c6digo antigo que fazuma inserglo, tenha em mente que, para AMBAS as vers6es do m6todo insert ( ) (uma que adiciona umlnteger e outra que adiciona uma String), o compilador emitir6 avisos. O compilador NAO sabe se o m6todo insert ( ) esti adicionando a coisa cena (Integer) ou a errada (String). A razlo pela qual o compilador produz um aviso 6 porque o m6todo esti ADICIONANDO algo ao conjunto! Em outras palavras, o compilador sabe que h6 uma chance de que o m6todo possa adicionar a coisa enada a um conjunto que o chamador pensa ser de tipo especifico.
OBSERVAQ6ESpRneOE)(AME
Para
os propdsitot
do exame, a ndo
se
vr
mtia,
niba
que a compi/agdo os
de
pmdu{ri,
ainda asim
se
trata
dz
una compilagdo
auins
NUI'JCA
considerada como
unafalba
nnpihEdo.
d
iri
I\{AO
quutdo
nmpilt
st'lcesso. Se a
pagunta
d.o exame
quivr
pnda{ni
"auisos".
palura
faryr con
EIJMII,{AR
induinl explcitamente a
At6 aqui, ji vimos como o compilador irS,gerar avisos caso perceba que h6 uma chance de que o seu conjunto de tipo especifico seja prejudicado por c6digos antigos, que nio usam tipo especifico. Mas, uma das perguntas que os delenvolvedores sempt. fazem 6.: "Ok, certo, o c6digo compila, mas, por que ele E)GCUTA? Por que o c6digo que insere a coisa errada na minha lista funciona no tempo de execuglo?" Em ouras palavras, por que a JVM permite que
o c6digo antigo insira uma String no seu Arraylist < Integer > , sem nenhum problema? Nenhuma excegXo, nada. . Apenas uma discreta violagio total da seguranga do tipo que voc6 poderia nio descobrir at6 o pior momento possivel.
H6 uma grande verdade que voc6 precisa saber para entender porque o c6digo roda sem problemas - aJVM nio tem id6ia de que o seu Arraylist devia armazenar apenas Integers. A informagio sobre os tipos nio existe em tempo de execugio! Todo o seu c6digo gen6rico serve apenas para o compilador. Por meio de um processo chamado de "apagamento de tipos", o compilador realizatodas as suas verificag6es no seu c6digo gen6rico e depois retira as informag6es de dpos do bytecode da classe. Em tempo de execugio, TODOS os c6digos referentes a conjuntos - tanto os antigos quanto os novos do Java 5 que voc6 escreve com gen6ricos - t6m exatamente a mesma apar6ncia, que 6 a da versio pr6gen6ricos dos conjuntos. Nada das suas informag6es de tipos existe em tempo de execugio. Em outras
palavras, que vocA tenha ESCRITO
);
JAVA Depois que o trabalho do compilador termina, aJVM vA o que ele sempre viu antes deJava 5 e dos gen6ricos:
33I
O;
para voc6
as convers6es
Pense nos gen6ricos como uma proteglo estritamente de tempo de compilaglo. O compilador usa informag6es de tipos, gen6ricos (o < tipo entre sinais de maior e menor) para ceftificar-se de que o seu c6digo nio colocar6 as coisas erradas em um conjunto, e de que voc6 nio atribuir6 o que receber de um conjunto ao tipo de refer6ncia errado. Mas NADA dessa protegio existe em tempo de execugio.
Isso 6 um pouco diferente dos arrays, que lhe fornecem protegeo TANTO em tempo de compilagio quanto em tempo de execuglo. Por que eles fizeram os gen6ricos assim? Por que nio existe informagio de tipo em tempo de execuglo? Para dar supofte a c6digos antigos. Em tempo de execufXo, os conjuntos slo similares ios conjuntos de antigamente- O que voc6 ganha ao usar os gen6ricos 6 uma protegio de tempo de compilagio o qual garante que voc6 nio colocari a coisa errada em uma colegio com tipo definido, e tamb6m elimina a necessidade de uma conversio ao se retirar algo, uma vez que o compilador ji sabe que, de uma lista Integer, s6 pode sair um Integer.
O fato 6 que voc6 nio PRECISA de protegio em tempo de execugio... At6 que comece a misturar c6digo gen6rico nio-gen6rico, como fizemos no exemplo anterior. Ai entlo voc6 pode ter desastres acontecendo em tempo de execugio. O 6nico conselho que podemos dar 6 prestar muita atenglo nestes avisos do compilador:
javac TestBadlegacy. java Note: Test.Badlegacy.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
Esse aviso
xlint : unchecked. Se o fizer, voc6 receber6 algo como isto: javac -X1j-nt :unchecked TestBadlegacy. java TestBadlegacy. java: 17 : warning: [unchecked] unchecked cafl- to add(E) as a member of the raw tl4)e java.util.l,ist list. add (new String (" 42" \ ) ;
1 warning
Quando voc6 compila com o flag compilador o trata como
lista.
se fosse
do compilador nio 6 muito descritivo, mas a segunda observagio sugere que voc6 recompile com
poderio fazer algo perigoso. Neste exemplo, uma vez que o argumento da lista nio foi declarado com um tipo, o
um c6digo antigo e assume que nio h6 risco
a
-Xlint
exame, voc6 precisar6 ser capaz de reconhecer quando est6 compilando c6digo que ir6 produzir avisos, mas, ainda assim, compilar. E qualquer c6digo que compile (mesmo com avisos) ir6 executar! Nenhuma violaqXo de tipo ser6 detectada em tempo de execugio pelaJW[, at6 que essas violag6es bag;uncem o seu c6digo de alguma outra forma. Em nlo vai falhar em tempo de execugio at6 que outras palavras, o ato de adicionar uma String a uma lista ( Integer voc6 tente tratar essa String-que-voc6-pensa-ser-um-Integer como um Integer.
No
Por exemplo, imagine que voc6 queira que o seu c6digo retire algo do seu (supostamente seguro) Arraylist (Integer), no qual um c6digo antigo inseriu uma String. Ele compila (com avisos). E executa... Ou pelo menos o c6digo que faz essa insergio de uma String executa. Mas quando voc6 retira a String-que-nXo-deveria-estar-16 da lista, e tenta atribui-la a uma refer6ncia Integer ou chamar um m6todo Integer, ter6 problemas.
Tenha em mente, enteo, que o problema de se colocar a coisa errada em um conjunto (gen6rico) de trpo especifico nio aparece no momento em que voc6 usa add ( ) no conjunto. Ele s6 aparece depois, quando voc6 tenta usar algo da lista e esse elemento nio bate com o que voc6 esperava. Antigamente (no tempo pr6-lava 5), vocA sempre assumia que poderia receber a coisa errada de um conjunto (uma vez que nenhum conjunto era de tipo especifico), entao voce tomava precaug6es defensivas no seu c6digo. O problema de se misturar c6digo gen6rico com nio-gen6rico 6 que voc nio estari esperando esses problemas, pois imagjnari que este protegido por um falso sentimento de seguranga por ter escrito c6digo com tipos especificos. Basta se lembrar que, assim que vocA repassa o seu conjunto de tipo especifico para nm c6digo antigo, que nio usa tipos especificos, a protegio j6fioi para o espago.
Novamente, preste muita atengio nos avisos do compilador, e esteja preparado para ver quest6es como
aParecendo no exame.
essas
e Coniuntos
oBSERVAQ6TS
Ao uur
pene O EXAME
eEedfn)
caidado comproblemas de unboxingl Se uocd declarar am conjanto ndo-gendico, o mitodo referlncia do tipo jaua.lang.Objut. Lznbre-se de que o uaboxing ndo i c@a7de conuerter um Objut erz un tipoprimitiuo, nem meimt se a referincia duse Objut apontarpara am Integer (oz algun outro tipoprinitiuo) no he@. O unboxing somente conuerte de una referincia a uma clatse wrapper (como um Integer au uru Lnng) para un tipo pinitiuo. conjuntot anlgos (sen tipo
get ( )
se
);
\
/n
/ 6 preciso converter
(
)'
int x2 = test2.qet(O);
Polimorfismo e os Gen6ricos
Os conjuntos gen6ricos lhe dio os mesmos beneficios da seguranga de tipos que voc6 sempre teve com os arrays, mas existem algumas diferengas cruciais que podem lhe pegar se voce nXo estiver preparado. A maioria delas tem a ver com o polimorfismo. Voc6
ji viu que o polimorfismo se aplica ao tipo "base" do conjunto: List<fnteqer> mylist = new Arraylist<Integer> ( ) ;
Arraylist.
Em outras palavras, podemos atribuir um Arraylist a uma refer6ncia List, porque List 6 um supeftipo de Nada especial ai - essa atribuigio polim6rfica funciona da maneira como sempre funcionou em Java, independentemente dos tipos gen6ricos.
Masequantoaisto?
cl-ass Parent { } class Child extends Parent { } List<Parent> mylist = new Arrayf,ist<Chi1d>
Pense nisso
por um minuto.
Continue pensando...
Nlo, isso nlo funciona. H6 uma regra bastante simples aqui - o tipo da declaragio davari|vel precisa bater com o tipo que vod passa ao tipo real do objeto. Se vod declarar List ( Foo ) foo, entio qualquer coisa que vod atribuir ) refer6ncia fooDEVEserdotipogen6rico (Foo>.Nioumsubtipode (Foo).NXoumzupertiposw (Foo).Apenas (Foo).
Estes estlo errados:
NAo!
NAOI
//
de Number
List<'JButton> myl,ist = new Arraylist<JButton>O; // sLm List<Object> mylist = new Arraylist<Object>O; / / sLm List<Integer> mylist = new Arraylist<Tnteger>O; // sim
At6 aqui, tudo bem. E s6 manter id6nticos o tipo gen6rico da refer6ncia e o tipo gen6rico do objeto ao qual ela se refere. Em outras palavras, o polimorfismo aqui se aplica apenas ao tipo "base'. E, por "base", queremos dizer o pr6prio tipo da classe do conjunto - a classe que pode ser personalizada com um tipo. Neste c6digo,
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.
NAO
333
import java.util.*;
nlacc Daranf I
l
class Child extends Parent { } public class Testpoly { public static void main(String[] argrs) { ParentlJ myarray = new childt3l; // sim
I
nio isro:
NAOI
Po1 que as regras para definigio de tipos em arrays sio diferentes das regras para definigio de tipos nos gen6ricos? Falaremos sobre isso em um minuto. Por agora, apenas memorize que o polimorfismo nio funiiona da mesma forma para gen6ricos como funciona para affays.
M6todos Gen6ricos
Se voc6 ainda nio estava familiarizado com os gen6ricos, poder6 e$ar se sentindo pouco ) vontade com as implicag6es da questlo nio-h6-atribuigio-polim6rfica-para-tipos-gen6ricos que apresentamos acima. Mas como 6 que poderia estar se sentido ) vontade? Um dos grandes beneficios do polimorfismo 6 que voc6 pode declarar, digamos, um argumento de m6todo de determinado dpo e, em tempo de execugio, poder fazer esse argumento referir-se a qualquer subtipo incluindo aqueles que voc6 nem sabia que existiam quando escreveu o m6todo com o argumento do supertipo.
Por exemplo, imagine um exemplo cllssico (simplificado) de polimorfismo, com uma classe representando um veterin6rio (AnimalDoctor) que possui um m6todo checkupQ. E neste momento, voce tem tr6s subtipos de Animal Dog, Cat e Bird - cada um implementando o m6todo abstrato checkupQ de Animal:
class Dog extends Animal- { public void checkupO { // implementa c6digo especifico de Dog System. out.println ( "Dog checkup" ) ;
)
class Cat extends Animal { public void checkupO { // implementa c6digo especifico de System. out.println ( "Cat checkup" ) ;
] ]
Cat
class Bird extends Animal { public void checkupO { // implementa c6digo especifico de Bird System. out . println ( "Bird checkup" ) ;
])
Esquecendo os conjuntos,/arrays por um momento, apenas imagine o que a classe AnimalDoctor precisa para poder ter um c6digo que tome qualquer tipo de Animal e chame o m6todo checkup ( ) de Animal. Tentar sobrecarregar a classe AnimalDoctor com m6todos checkup ( ) para cada tipo poss(vel de animal seria absurdo, e obviamente nioextensivel. VocA teria de modificar a classe AnimalDoctor a cada vez que algu6m adicionasse um novo subtipo de
Animal.
Assim, na classe AnimalDoctor, vocd provavelmente teria um m6todo polim6rfico:
public void
checkAnimal (Animal
a)
e Coniunlos o
a.checkup?; // n6o importa com qual subtipo de animal // m6todo checkupO sobrescrito de cada Animal execute
)
E, 6 claro, queremos que AnimalDoctor tamb6m tenha c6digo que possa tomar affays de Dogs, Cats ou Birds, para quando o veterinirio vier a uma exposigio de cies, gatos ou pissaros, resPectivamente.
Novamente, nio queremos m6todos sobrecarregados com a$ays paracada subtipo potencial de Animal, entXo
usaremos polimorfismo na classe AnimalDoctor:
j
Eis o exemplo inteiro, com o teste do polimorfismo do array que usa qualquer tipo de array de animais (Dos
car [ ], Bird[ ]). import j ava. utj-1 . *; abstract class Animal { public abstract voj-d checkupO;
]
],
class Dog extends Animal { public void checkupO { // implementa c6digo especifico de System. out . println ( "Dog checkup" ) ;
) )
Dog
class Cat extends Animal { public void checkupO { /,/ implementa c6digo especifico de Cat System. out . println ( "Cat checkup" ) ;
)
class Bird extends Animal i public void checkupO { // implementa c6digo especifico de Bird System. out.println ( "Bird checkup" ) ;
) )
public class AnimalDoctor { / / o m6Lodo usa um array de qualquer subtipo de animal public void checkanimals (Animal [] anj-mals) { for(Animal a : animals) {
a.checkupO;
] ]
public static void main(String[] args) t // faz o tesLe Dog[] dogs - {new DoSO , new DogO }; Cat[] cats = {newCatO, newCatO, newcat0}; Bird[] birds - {new Bird( ) };
AnimalDoctor doc = new AnimalDoctor ( ) ;
JAVA
335
Em outras palavras, um m6todo que use, digamos um Arraylist<Animal> NAO ser6 capazde aceitar um conjunto de qualquer subtipo de Animal! Isso significa que Arraylist ( Dog nio pode ser passado para um m6todo com um argumenb de Araylist<Animal), mesmo que, como n6s sabemos, isso bem com arrays simples.
firncione
essa diferenga entre arrays e Arraylist 6 condizente com as regras de atribuigio de polimorfismo que ji vimos - o fato de que voc6 nio pode atribuir um objeto do tipo Arraylist (JBunon ) a um List i Object > . Mas 6 aqui que voc6 comega a sentir a complicagio trazida pela disdngio entre arrays com tipos especificos e conjuntos com
Obviamente,
trpos especrtrcos. N6s sabemos que nio vai funcionar corretamente, mas vamos tentar modificar o c6digo de AnimalDoctor para usar I, generrcos emvez oe arrays:
public class AnimalDoctorGeneric { // modifica o argumento de Animal! I para Arraylist<Ani-rna1> public void checkAnimals (ArraylistcAnimal> animals) { for(Animal a : animals) {
a.checkupO;
] ]
public static void main(St.ring[] arqs) { / / cri,a Arraylist.s em vez de arrays para Dog, Cat, Bird
ListcDog> dog,s = new Arraylist<Dog>
dogs.add(new DogO
(
,'
);
ListcCat> cats = new Arraylist<Cat> ( ) ; cats.add(new CatO ); cats.add(new CatO ); List<Bird> birds = new Arraylist<eird> ( ) , birds. add (new Bird ( ) ) ; / / este c6digo 6 o mesmo que o da versdo com Array
Ani-malDoctorGeneric doc = new AnimafDoctorceneric / / isto funcionou quando usErmos arrays em vez de
(
Arraylists
doc.checlrrnLnals(dogs) i // anvLa un r,iat<Dog> doc.checklninals(cats) i ll enwi.a un r,ist<Cat> doc.checlrAninalg (birds) ; l l enwLa un t ist<Bird>
)
j ava
: 51
Anj-malDoctorGeneric. java
52
: checkAnimals ( java.util.
e Coniunlos
AnimalDoctorGeneric
j ava: 53
3 errors
O compilador nos interrompe com erros, e nXo avisos. Voc simplesmente NAO PODE atribuir os Arraylists individuaisdossubtiposdeAnimal(<Dog>, (Cat) ou <Bird>)aumArraylistdosupenipo (Animal),que6
o tipo declarado do argumento.
Essa 6 uma das quest6es mais complexas para programadores Java que esteo
funciona da maneira como voce esperaria. Assim, n6s temos duas quest6es na verdade: Por que isso nXo funciona?
tio
Voc nos odiaria, e a todos os engenheiros da Sun, se lhe diss6ssemos que nlohicomo faz&lo funcionar - ou seja, que voc6 teria de aceitar as coisas como slo e teria de escrever c6digos horrivelmente inflexiveis que tentam antecipar e codificar m6todos sobrecarregados para cada ( tipo ) especifico. Felizmente, existe uma forma de faz&lo funlionar. Mas, primeiramente, por que nio funciona, se funciona para os arrays? Por que nio 6 possivel passar um Arraylist ( Dog ) a um m6todo com um argumento de Arraylist ( Animal > ?
N6s chegaremos li, mas primeiramente vamos dar um passo atr6s por um minuto e considerar este cenirio, que 6 perfeitamente v6lido:
Animalf l animalq = nai^r Animal
f ?l
Assim, esta parte funciona tanto com arrays quanto com conjuntos gen6ricos - podemos adicionar uma instlncia de um subtipo em um $ray o! conjunto declarado com um supertipo. Vocd pode idicionar Dogs e Cats avmarray Animal (animal [ 1) ou a um conjunto Animal (Arraylist ( Animal >).
E, com arrays, isso se aplica ao que acontece dentro de um m6todo:
public void addAnimal(Animal[] animals) { animals [0] = new Dog ( ) ; / / sem problema, qualquer Animal funciona ,/ / em animal [ ]
)
se isso for verdadeiro, e voc6 puder colocar Dogs em um Arraylist ( Animal > , enteo por que voc6 usar o mesmo tipo de cenirio de m6todos? Por que nlo 6 possivel fazer isto?
Entio,
nio pode
public void
)
JAVA
337
Na verdade, voc6 PODE fazer isso sob ceftas condig6es. O c6digo acima IRA compilar com sucesso SE o que voc6 passar ao m6todo for tamb6m um Arraylist < Animal > . Essa 6 a parte onde isso difere dos arrays porque, na versXo dos arrays, voc6 PODIA passar um Dos [ ] ao m6todo que usa um Ani-ma1 [ ] .
A TINICA coisa que vocA pode passar a um argumento de m6todo de Arraylist ( Animal ) 6 um Arraylist < Animal ) ! (Assumindo que voc6 nio esteja tentando passar um subtipo de Arraylist, uma vez que, lembre-se, o tipo "base" pode ser polim6rfico.)
6 inv6lido para Arraylist, mas nio para arrays? Por que nlo6possivelpassarumArraylist(Dog) aumargumentodeArraylist<Animal)?Naverdade,oproblemaE
igualmente perigoso esteja voc6 usando arrays ou um conjunto gen6rico. Ocorre apenas que o compilador e aJVM se comportam de formas diferentes p^ra e para conjuntos gen6ricos.
^rr^ys um conjunto (array ou Arraylist) de um subtipo para um m6todo que use um conjunto de um supertipo 6 que voc6 poderia adicionar alguma coisa. E isso significa que voc6 poderia adicionar a coisa ERRADA! Isso provavelmente 6 muito 6bvio, mas, pelo sim pelo nio (e para reforgar o conceito), vamos
passar
public void addAnimal(Animal[] animals) { anj-malslO] = new DogO; // ok, qualquer subtipo de Animal funciona
)
Nenhum problema aqui. N6s passamos um Dog I J para o m6todo e adicionamos um Dog ao array (o que foi permitido porque o parimetro do m6todo era do tipo Animal [ ] , o qual pode armazenar qualquer subtipo de Animal). Mas e se modificdssemos o c6digo chamador para
public void foo ( ) t Cat.[] cats = {new CatO, new CatO}; addAnimal(cats); // sem problema, envia o Cat[ ] para o m6todo
)
e
public void addAnimal(Animal[] anj-mals) { animals[0] = new Dog(); // Oh, ndol Acabamos de col-ocar
//
)
um Dog
em rrm arrav
Cat!
O compilador pensa que 6 perfeitamente vilido adicionar um Dog a um array Animal [ ] , uma vez que um Dog pode ser atribuido a uma referAncia de Animal. O problema 6 que, se voce passasse um array de um subtipo de _ . Animal (Cat, Dog ou Bir$, o compilador nio saberia. O compilador nio percebe que, em algum lugar do heap, hi um arraydo tipo caat l, e nioanimal [ ], e voc6 est6prestes itenta. adicionarum Doga ele. Para o compilador, voc6 do tipo Animal, enteo ele nio tem como perceber o problema. p,rssou vm
^rray
ESSE 6 o cen6rio que estamos
tentando impedir, independentemente de se 6 um array ou um Arraylist. A diferenga nio com coniuntos gen6ricos.
para um m6todo que use um pela qual o compilador nio lhe permitir6 passar um Arraylist ( Dog ArrayliJtcAnimal> 6 que, dentro do m6todo, o parAmetro 6 do tipo Arraylist(Animal>, e isso significa que voc6 poderia colocar qualqueriipo de Animal dentro dele. Nio haveria como o compilador the impedir de colocar um -Dog mas que esti agora sendo referenciado a partir do em um List que fo.a originalrnente declarado como Cat
A razlo
),
parAmetro
<Animal).
Ainda temos duas perguntas... como se contorna essa problema e por que, afilal, o compilador permite que voc6 assuma esse risco para arrays mas neo para ArrayLists (ou qualquer outro conjunto gen6rico)? A, razio pela qual voc6 consegue compilar isso com arrays 6. que existe uma excegio de tempo de execugio (ArrayStbreEiception) que lhe impedirl de colocar o tipo errado de objeto em um array. Se vocA enviar um array Dog para o m6todo que usa um array Animal, e adicionar apenas Dogs (incluindo subtipos de Dog, 6 clarQ ao array ago1^ iendo referenciado por Animal, nioh|problemas. Mas se voc6 tentar adicionar um Cat ao objeto que nio verdade 6 tm array Dog, receber6 a excegio.
NAO hi uma excegio equivalente para gen6ricos, por-causa do apagamento dos tipos! Em outras palavras, em mas NAO sabe o tipo de um conjunto. Todas as informag6es de tempo de execugXo aJVM SABE o tipo dos ^rr^ys, tipoi gen6ricos sio removidas dtrante i compilaSo, de forma que, no momento em que ela chega )JVM, simplesmente nlo
Mas
338
Copiruf
o7:
Gen6ricos e Coniuntos
h6 como reconhecer o desastre de se colocar um Cat em um Arraylist ( Dog e vice-versa (e a coisa fica exatamente como os problemas que voc6 tem quando usa c6digo antigo, sem tipo especifico).
VAtnO:
)
public void
isto 6 sempre v61ido, uma vez que Dog pode ser atribuido a uma refer6ncia
de Animal
List<Animal> animals = new Arraylist<Animal> ( ) ; animals.add(new Dog( ) ) ; animals.add(new DoS( ) ) ; AnimalDoct.orGeneri-c doc = new AnimalDoctorGeneric ( ) ; doc.addAnimal(animals); // OK, uma vez que animals bate / / com o arsumento do m6todo
)
Desde que a:6rttca coisa que voc6 passe a addAnimals (List<Animal>) seja um Arraylist(Animal), o compilador ficaleliz - sabendo que qualquer subtipo de Animal que voc6 adicionar seri vilido (voc6 sempre pode adicionar um Dog a um conjunto Animal, etc e tal). Mas se voc6 tentar chamar addAnimal ( ) com um argumento de qualquer OUTRO tipo Arraylist, o compilador o impedir6, uma vez que, em tempo de execugio, aJVM nio teria nenhuma forma de impedir que voc6 adicionasse um Dog ao que foi criado com um conjunto Cat.
Dog
{
),
addAnimal
(),
public void
)
List<Dog> animal-s = new Arraylist<Dog> ( ) ; anj-mals.add(new Dog ( ) ) ; animals.add(new DoS( ) ) ; AnimalDoctorGeneric doc = new AnimalDoctorGeneric ( ) ; doc. addAnimal (animals ) ; / / 6 AQUI que surge o problema!
)
j ava
1 . Li s
AnimalDoctorGeneric
List<Dog>
t<Animal>
1 error
Repare que essa mensagem 6 praticamente a mesma que vocd receberia ao tentar chamar qualquer m6todo com o argumento errado. Esti dizendo que voc6 simplesmente nio pode chamar addAnimat (List<Animal>) usando algo cuja referAncia tenha sido declarada como List (Dog>. (E o tipo da refer6ncia, e nio o pr6prio tipo do objeto que importa, mas lembre-se: o tipo gen6rico de um objeto 6 SEMPRE o mesmo que o tipo gen6rico declarado na refer6ncia. List(Dog) po& se referir A?ENAS a conjuntos que sejam subtipos de List, mas que tenham sido instanciados como o tipo gen6rico < Dog > ) Maisumavez, lembre*e de queumavezdentro do mdtodo addAnimals ( ) , nrdo o queimporta6 otipo doparAmaro neste caso, List < Animal > . (N6t o modificamos de Arraylist para Lis para manter o nosso polimorfismo de tipo "base"
mais claro.)
JAVA
339
De volta I questio principal - como contornamos isso? Se o problema esti relacionado apenas ao perigo de se adicionar a coisa errada ao conjunto, e quanto ao m6todo checkup ( ) que usou o conjunto passado como de somente-leitura? Em outras palavras, e quanto aos m6todos que chamam m6todos de Animal para cada coisa do coniunto, o que iri funcionar independentemente de qual esp6cie de subtipo de Arraylist 6 passada?
Eisso6umadica! Om6todo add O 6que6oproblema,entio oqueprecisamos6deumaformade dizerao compilador'ei, estou usando o conjunto-passad6 apenas parachamir m6todos para os elementos - e prometo NAO
adicionar nada ao conjunto". E de fato EXISTE um mecanismo paradizer ao compilador que voc6 pode usar qualquer subtipo gen6rico do tipo do argumento declarado, porque nlo iricolocar nada no conjunto. E esse mecanismo 6 o coringa < ?>.
public void
Para
public void addAnimal(List<? extends Animal> animals) Ao usar < ? extends Animal>, estamos dizendo: "Eu posso receber um conjunto
Assim, 6 claro que o m6todo
esse
com o tipo definido de < Animal ) ou qualquer coisa que estenda Animal. Ah sim, e PROMETO que nio vou ADICIONAR nadaao coniunto". @xistem mais alguns detdhes, mas chegaremos li.)
addAnimal ( )
acima nXo vai compilar nem mesmo com a notagio do coringa, porque
public void
(List<? extends Animal> animals) { animal-s.add(new DosO) ; // NAol Nao se pode adicionar
addAnimal
se
VocA receberi um erro bastante estranho que poderi se parecer com isto:
AnimalDoctorGeneric. java:
38
l- error
que basicamente diz: "voc6 nio pode adicionar um Dog aqui". Se modificarmos o m6todo de forrna que ele adicione nada, passarl a funcionar. Mas eqpere
nio
no exame, com
- ainda tem mais. @ a prop6sito, tudo o que abordamos nesta sedo sobre ggn6ricos provavelmente ser6 te*ado ex@o do "apagamento de tipos", sobre o qual nlo 6 necessdrio que vod saiba quaisquer detalhes)
Primeiramente, <? extends Animal> significa que vocd pode usar qualquer subtipo de Animal; entretanto, esse subtipo pode ser OU uma subclasse de uma classe (abstrata ou concreta) OU um tipo que implemente a interface que vem depois da peJavra extends. Em outras palavras, a palavra-chave extends no contexto de um coringa representa tanto as subclasses quanto as implementag6es de interfaces. Nio h6 uma sintaxe <? implements SerializabLe>. Se voc6 quiser declarar um m6todo que use qualquer coisa que seja de um tipo que implemente Serializable, voc6 ainda usaria extends desta forma:
// //
Parece estranho porque vocA nunca usaria isso em uma declaraglo de classe, porque Serializable 6 uma interface,
uma classe. Mas a sintaxe 6 essa, entio memorize-a! Mais uma vez
subclasses.
- s6 existe llMA
.
essa palavra-chave 6
palavra-chave coringa que representa tanto implementag6es de interfaces qlranto extends. Por6m, quando a vir, pense em "E-LIM", no sentido de dgo que passa no
teste de
instanceof
a
Entretanto, hi outro cenirio ern que voc6 pode usar um coringa E aindaadicionar ao conjunto, mas de uma forma
segura
palavra-chave
super.
Dog>
Imagine, por exemplo, que voc6 tenha declarado o m6todo desta forma:
340 Copftulo
Z: Gen6ricos e Coniuntos
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
)
Dog> animals)
foi essencialmente: "Ei, compilador, por favor aceite qualquer List com um tipo gen6rico que
seia do tipo Dog, ou um supenipo de Dog. Nada mais baixo na irvore de heranga poder6 entrar, nus qualquer coisa mais alta do que Dog pode."
VocE provavelmente j6 entendeu por que isso funciona. Se voc6 passar um lista do tipo Animal, enteo 6 perfeitamente a ela. Se voc6 passar uma lista do tipo Dog, 6 perfeitamente v6lido adicionar um Dog a ela.E se voc6 passar uma lista io tipo Object,iINDA 6vilidordii;ott"t"rr- Dog a ela. Quando usa a sinraxe <z super . . . >, voc6 est6 dizendo ao compilador que pode aceitar o tipo que estA no hdo direito de super ou qualquer um dos seus supertipos, umayez que - e esta 6 parte principal do que faz isso funcionar - um conjunto declarado como qualquer supertipo de Dog seri capaz de aceitar um Dog como elemento. List < Object pode usar um Dog. List < Animal pode usar um Dog. E List ( Dog pode usar um Dog. Dessa forma, passar qualquer um desses ir6 funcionar. Assim, a palavra<have super na notaglo do coringa perrnite que vocA tenha umi forma restrita, mas ainda possivel, de adicionar a um conjunro.
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?
}
6?
Sim,EXISTEumagrandediferenga.List<?>,que6ocoringa<?>semaspalavras-chaveextends ousuper,
significa simplesmente "qualquer tipo". Assim, isso significa que qualquer tipo de List pode ser atribuido ao argtrmento. Poderia ser um List de ( Dog ) , ( Integer ) , (JButton ) , ( Socket ) , qualquer coisa. E usar o coringa sozinho, sem a palavra-chave super (r.g*d" de um tipo), significa que voc6 nio pode ADICIONAR nada i lista referida como List < ? >.
List<object.> 6 completamente diferente de List<?>. List<object> significa que o mdrodo SOMENTE pode usarum List<obj ect>. Nio um List.<Dog>, nem um List<Cat>. Significa, no entanto, que voc6 pode adicionar. i lista, uma vez que o compilador ji se certificou que voc6 est6 passando apenas um List < Object > v6lido
para o m6todo.
Com
imnnrf
public class testWildcards { public static void main(String[] argrs) { List<Integer> mylist = new Arraylist<Integer> Bar bar = new BarO;
bar . dofnsert (myl,ist ) ;
]
Se
O problemaestano m6todo list.add( ) dentro de dornsert ( ). O coringa<?> permite queumalistade QUALQUER tipo seja passada ao m6todo, mas o m6todo add ( ) nlo 6 v6lido, pelas raz5es que exploramos anteriormente (que voc6 podia colocar o tipo errado de coisas no conjunto). Assim, desta vez, a classe Test\Tildcards
JAVA
34]
a classe Bar nio compilar6, porque elarealizaum add ( ) em um m6todo que super). E se modificarmos o m6todo dotnsert ( ) para isto:
usar um
public class TestWildcards { public static void main(String[] args) { List<Integer> mylist = new Arraylist<fnteger> Bar bar = new Bar ( ) ;
bar. dof nsert
]
)
f
mwT,i st-
]
E agora,vai funcionar?
Se
nlo, por
quA?
Destavez,aclasseBar,comom6tododornsertO,compilasemsobressaltos.Oproblema6queoc6digo
Test\il/ildcards est6 tentando passar um List E narla mus pode substituir < Obiect > .
Integer
Object >
List< ? extends ob j ect.> e List< ?> slo absolutamente id6nticas! Ambas as instrug6es dizem: "Eu posso me referir a qualquer tipo de objeto". Mas, como voc6 pode ver, nenhuma delas 6 o mesmo que List < Object ) . Uma forma de se lembrar disso 6 qlue, se voc6 vir a notagio com coringa (um ponto de interrogagio ?), isso significa "muitas possibilidades". Se voc6 NAO vir o ponto de interrogagio, entio significa que deve ser usado o ( tipo ) especificado, e absolutamente NADA ALEM DELE. List ( Dog ) significa List ( Dog ) , e nio List ( Beagle ), List ( Poodle ) nem qualquer outro.subtipo de Dog. Mas List < ? extends Dog ) poderia significar List(Beagle), List(Poodle) e assim pordiante. E claro que List<?> poderia ser... Qualquer coisa.
A prop6sito,
Tenha em mente que os coringas s6 podem ser usados para declarag6es de referAncias (incluindo argumentos, variiveis, tipos de ietornos e assim por diante). Nio podem ser usados como o parAmetro de tipo quando voc6 cria um novo conjunto com tipo especifico. Pense nisso: enquanto uma refer6ncia pode ser abstrata e polim6rfica, o pr6prio objeto criado deve ser de um tipo especifico. VocA precisa definir o tipo quando cria o objeto usando new.
Como uma pequena revisio antes de seguirmos adiante com os gen6ricos, observe quais irio compilar:
as seguintes
instrug6es e descubra
1) List<?> list = new Arraylist<Dog>O; 2) List<? extends Animal> alist = new Arraylist<Dog>O; 3) List<?> foo = new Arraylist<? extends Animal>O; 4) List<? extends Dog> clist = new Arraylist<Tnteger> ( ) ; 5) List<? super Dog> blist = new Arraylist<Animal> ( ),' 6) List<? super Animaf> dlist = new Arraylist<Dog>O;
As respostas corretas (as instrug6es que compilario) sio As tr6s que nio
t,2
e 5.
Arraylist<? extends
I l
Instrugio:
List<? extends
Dogr>
cl,ist
new Arraylist<lnteger> ( ) ;
Problema: Nio 6 possivel atribuir uma lista de Integers a uma refer6ncia que aceita apenas um Dog (incluindo quaisquer subtipos de Dog, 6 claro).
lnstruglo:
O;
Problema:
Nlo
classe. Somente
Animal
ou
Obiect
e Coniuntos
Declarag6es Gen6ricas
At6 agora, falamos sobre como criar conjuntos com tipos especificos, e sobre como declarar vari6veis de referAncia
qne incLr"* argumentos e tipos de retorno usando a sintaxJgen6rica. Mas eis aqui algumas quest6es: como 6 que vamos saber se 6 permitido / requerido que n6s especifiquemos um tipo para essas classes de conjuntos? E a especificagio de tipos gen6ricos funcionJcom outias classes da API? E, finalmente, 6 possivel declararmos as nossas proprias il.sses co*o iipos gen6ricos? Em outras palavras, podemos criar uma classe (ue requeira que algu6m passe um tipo quando adeclararem e instanciarem?
Primeiro, exemplo,
A interface List estise comportando como um "modelo" (mais ou menos como os modelos do C+ +) e, ao escrever seu c6digo, voc6 o modifica de um List gen|rico puaum List < Dog ) ou List ( Integer ) , e assim por diante.
6 apenas uma convengio. Qualquer identificadorJava vilido funcionaria aqui, mas E significa "Elemento",e6usadoquandoomodelo6umconjunto.Aoutraconvengioprincipal 6T(significa"tipo"),usado
viu
declaragio dainterface para List, como imagina que seja o m6todo add
boolean add(E o)
Em outras palavras, o que quer que E seja quando voc6 declarar aList,
este c6digo:
imagine
= new ArraylistcAnimal> ( ) ; OEnaAPldeListderepentedeixadeserumabstrato (seutipoaqui> epassaaserumListdeAnimals.Esedum List de Animals, enteo o m6todo add ( ) de List obviamente deve se comportar desta forma: boolean add(Animal a)
List<Animal>
list
Quando consultar uma classe ou interface gentrica na API, escolha um parAmetro de tipo (Dog, JButton ou mesmo Object) e faga uma operaglo de busca e substituigXo mental para cada instAncia de E (ou qudquer identificador que esteja sendo usado como marcador para o parAmetro do tipo).
i qi- rant-a
l Dnn l
maxNumi
;
Agora imagine que voc6 quisesse criar uma subdasse de Rental que servisse apenas para o aluguel de carros. VocA POOena comegar com algo deste ttpo:
JAVA
343
O;
/a\
\el
System. /
out.println
/ provavelmente langa
)))
Mas quanto mais vocA olha, mais vocA percebe que:
1.
Voc6 ex6fazendo
sobrecarga)
do arg-umento de
2. VocA realmente
pr6pria verificagio de tipo no m6todo returnRental ( ) . Nio 6 possivel modificar o tipo returnRental ( ) para usar um Car, uma vez que se trara de uma sobrescrigio (e nio uma do m6todo & classe Rental. (Sobrecarregar acabaria com a sua flexibilidade polim6rfica com Rental).
a sua
nio quer criar zubclasses separadas para cada tipo possivel de coisas que podem ser alugadas (carros, computadores, sapatos de boliche,iriangas, e assim por diante).
Mas com a sua intelig6ncia natural (aumentada por este cenirio complicado), vocA rapidamente percebe que pode criar a classe Rental como um tipo gen6rico - um modelo para qudquer tipo de coisJque pode Jer aluga& -i irto resolve o seu problema. (N6s dissemos complicado... Uma vez que, na realidade, voc6 poderia muito bem querer ter diferentes comPortamentos para diferentes tipos de coisas que podem ser alugadas, mas at6 mesmo isso poderia ser resolvido de forma mais limpa atrav6sde algum tipo d.e composigio de componamento, em vez de com a [eranga (usando-se o padrio de projetos Estrat6gia, por exemplo). E nio, os padr6es de projetos nio caem no exame, mas ainda assim achamos que vocA deveria ler o nosso livro sobre padr6es de projetos). Assim, aqui est6 a sua nova e aprimorada classe gen6rica Rental:
/ // // //
/
"'t" significa o parAmetro do tipo Use o tipo da classe como o tipo de List
maxNum;
;
public T getRental0 { // bloqueia aL6 que haja algo disponivel return rentalPool. get (0) ;
)
// estamos alugando
urn T
// e o locador // retorna um T
class TestRental { public static void main (String[] args) t / /cria alguns Cars para o Pool Car c1 = new CarO; Car c2 = new CarO; List<Car> carlist = new Arraylist<Car> ( ) ; carlist . add ( c1 ) ; carlist . add ( c2 ) ;
Rentalceneric<Car> carRental = new Rentalceneric<Car> (2, carlist) ; / / reLira agora um car, e ndo serd necess6rio converter Car carToRent = carRental.getRentalO ; carRental . returnRental ( carToRent ) ,' / / ser6. que podemos colocar alguma outra coisa na carlist
original?
carlist.
l
"Fluffy"
));
Recebemos um erro:
kathy* javacl,. 5 RentalGeneric. java RentalGeneric. java:38: cannot find symbol strmbof : method add(Cat) location: interface j ava. util . List<Car> carl,ist. add(new Cat ( "Fluf fy" ) ) ; 1 error
Agora temos uma classe Rental que pode ter o tipo definido para qualquer coisa que o programador escolha, e o compilador forgarS. o uso desse tipo. Em outras palavras, funciona da mesma maneira como as classes de Coniuntos. Vejamos outroJ exemplos de sintaxe gen6rica qui voc6 poderia encontrar na API ou em c6digo-fonte. Eis uma outra
classe simples que usa o
tipo parametr:uado
{
//
da elasse
rF f I srl.drrqaeLL-t :nArr:rrAfTsr tJ
/ //
/
{
/ /
TestGenerics (T anlnstance)
)
rama
:rrrrmanl-n
rol-drno
return anfnstance;
J
Obviamente, esse 6 um uso absurdo dos gen6ricos e, na verdade, voce raramente veri gen6ricos fora de conjuntos. Mas voce precisa entender os di{erentes tipos de sintaxe gen6rica que poderi encontrar, de modo que continuaremos com esses exemplos at6 que os tenhamos abordado todos.
JAVA Voc6 pode usar mais de um tipo parametrizado em uma 6nica definigio de classe:
^,'Lll^ 1;uurre ^r^^^ urdb> rr^^ u>eTwO<T, X> {
345
T one; X two;
UseTwo(T
thiq
one, X two)
= ^na. LWU;
nna
]
T
teste, criando
com
<String, Integer>
{
new UseTwo<String,
/ / ralnrna
um
intt
) !_voc6 podg ular uma forma de notagio com coringa em uma definigio de classe, para especificar um intervalo (chamado de "limites") para o ripo que poderi ser usado para o parimetro do tipo:
/ use "T"
em vez
/ / .16 \\?"
// //
oK NAol
-*"*.*-**.
i:rz: rrli l
um
finn Lrvv
-trl-st<'I'>
-L f
sE.
= new Arrayl,ist<T>
);
list.add(t);
e Coniuntos
No c6digo.acima,
se
de
Dp&
/n6todo
se
componaria como
se tivesse
tido
esta aparAncia o
);
E, 6 claro,
se voce chamar o m6todo com um lnteger, o T ser6 substiruido por Integer (nio no bltecode, lembre-se descrevendo como ele aparenta se compott"r, e nlo como de fato acontece). estamos
tipo
A
de
coisa mais estranha a respeiro dos m6todos gen6ricos 6 que voc6 precisa declarar a vari6vel do tipo ANTES do
retorno do m6todo: um tiPo no argumento. VocA DEVE ser que ele seja especificado para a classe. Em CreateAnArraylist, a classe nio 6 h6 nenhum marcador de parAmetro de tipo que Possamos usar.
public <T> void makeArraylist (T t) O < T > antes de void simplesmente define o que T 6 antes que voc6 o,use como
declarar o tipo dessa forro", a
nio
gentrica,portanto, nio
VocA tem a opgio tamb6m de colocar limites sobre o lipo qu9 declarar;por exemplo, se q-uiser restringlr o m6todo makeArrayllst ( ) a apenas Number ou os selrs subiipos (Integer, Float e assim por diante), vocd usaria
Number>
void makeArraylist(T t)
pene o EXAME
NAO
eshi onde aocd declaroa a uariduel
de
pardnetro da
classe oa no
de pardwetro de tipo T. Para usar ama aaiduel de mitodo, antes do tipr de retuml. A linha abaixo podetl
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:
KEALMENTE
pardmetro do tipo:
class x { public
Sim, irofunciona. O
cada um dot asos de
<X> X(X
x) t }
Asin,
qae
X,
tipo <X>, qile' pzr sila ue7, ndo tem O conpi/ador convguefaryrpasing disso e hata
defonza independente.
ndo ocom nenbum conf/ito entre 0t fllmes das clares, dos narcadores dotpardmetms
tJm dos enganos mais cumafis qte ospmgramadores conetem ao criarvm classes ou mitodos geniricos i asar am <T>, 1E), e assin por diante. Este cddigo pode parecer con'eto, mat ndo i:
4?t
na intaxe do coringa
Number>
}
ete
NAO
i u,llido:
// //
NAOI
Sim
98o/o detudo o que voc6 provavelmente fari com os gen6ricos 6 simplesmente declarar e usar coniuntos com tiPo especificado, inituindo usilos (e pass6-los) como argumentos. Mas agora voc6 sabe muito mais (por6m, de forma alguma tudo) sobre a maneira como os gen6ricos funcionam.
JAVA
Se esse assunto
347
ficou claro e filctl paravocA, excelente. Se foi... Complicado, saiba que a adigio dos gen6ricos Fg""F:* J"yt chegou perto de cansat .tm" revolta entre alguns doi desenvolvedoies Java mais exp"erientes. A maioria dos criticos simplesmente estava descontente com a complexidade, ou nio estava convencida de que o beneficio de se ter coniuntos com tipos especificados. pena pelos milhares de regrinhas que voc6 tem de decorar agora. E " que, go.mlava 5, ficou mais dificil p5nder a linguagem. Mas icredite em n6s... Nunca vimos niigudm levar mais do que dois dias para entender os gen6ricos. Isso sio s6 48 horas consecutivas.
".tF*
:*l
gbjtt.) e do m6todo equals ( ) (siber se dois objetos sio tignrfcatiuanmte eqriaahtet). VocA conheceu a dewantagem de nio sobrescrever equals ( ) - pode n5o ser possivel enconirar o objetoem um conjunto. Discutimos.r* poi.t o como escrever um m6todo equals ( ) adequado - nio esquega de usar instanceof e referenciar os atrib-utos significativos do objeto. Revisamos os conrratos de sobrescr(io de eguals ( ) e hashCode ( ) . Conhecemos a teoria existente por tris dos c6digos de. ha;higg.e a difgre.lgg entre c6digos de hashing v6lidos, apropriados e eficientes. Tamb6m vimos que mesmo sendo muito ineficiente, 6 v6lido que um m6todo hashCode ( ) sempre rerorne o
mesmo valor.
4 :.gYit,
ryvislmop
finalidade do operador_
seguir passamos para os conjuntos, momento em que conhecemos os conjuntos Iist, Set e Map, e vimos a diferenga entre conjuntos ordenados e classificados. Aprendemos os atributos principais das classes comuns de conjuntos, equando us6-los.
Abordamos os detalhes sobre as classes Collections e Arrays: como classificar e como procurar nelas. Aprendemos sobre como converter arrays em Lists e de volta para affays. Finalmente, nos dedicamos aos gen6ricos. Os gen6ricos lhe permitem forgar a segrranga de tipos, em tempo & compilagXo, para conjuntos ou outras classes. Os gen6ricos aju&m agararnir que, quando voi6 receber um item de uma colegio, ele ser6.do tipo que voc6 espera, sem que seja necessirianenhuml conversio. VocA pode misturar c6digo antigo com c6digo que usa gen6ricos, mas isso pode causar exceg6es. As regras para o polimorfismo mudam g.ulndo voc6_ usa os gen6ricos, apesar de que, usando coringas, voc6 ainda pode criar conjuntos polim6rficos. Algumas declarag6es de gen6ricos permitem a leitura a panir de umionjunto, mas nio permitem a attahzagio do conjunio.
interessante.
Exercicios ripidos
Aqui estio alguns dos pontos principais do Capitulo
7.
Sobrescrevendo hashCode( ) e equals( ) (Objetivo 6.2) O equals( ),hashCode( ) e tostring( ) siopriblicos(finalize( ) 6protegido).
E E
O
println (
) ou ouuos
Use
Use
: :
( ) para determinar se dois objetos sio significativamente equivalentes. E Se voc6 nio sobrescrever equals ( ) , seus objetos nio serlo chaves riteis para tabelas/mapas de hashing. El Se voc6 nio sobrescrever equals ( ) , dois objetos diferentes nio serio considerados iguais. O Classes String e wrapper sobrescrevem equals ( ) e se tornam chaves adequadas paratabelx/mapas de hashing. tr Quando sobrescrever equals ( ) , use o operador instanceof para se certificar de que est6 avaliando uma classe
equals
apropriada.
D D
Quando sobrescrever
equals
),
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
resultado.
e Coniuntos
D Quando ser5, nub: se x nio for nu11, x. equals (nu1l) ser6 falso. D Sex.equals(y) forverdadeiro,x.hashCode( ) = = y.hashCode( ) deveser true E Se voc6 sobrescrever equals ( ) , sobrescreva hashCode ( ) '
As classes HashMap, HashSet, Hashtable, LinkedHashMap e LinkedFlashSet usam hashing. sobrescriglo vilida de hashCode sobrescriglo
E Uma E Uma
D
( ) ter6 que se ater ao contrato. eficiente de hashCode ( ) distribuir6 chaves de forma igualit6ria em v6rios dep6sitos. ( ) retorne o mesmo
hashCode
valor para todas
as instAncias
Para reiterar: se dois objetos forem iguais, seus c6digos de hashing tamb6m devem ser.
B E vilido
seia
(embora na pritica
muito ineficiente).
de hashCodeQ que foram realgados: chamadas a x.
E Aspectos do contrato E
Se
D E consistente: virias
(y)
x. equals (y) for true, x.hashCode ( ) == y.hashCod.e ( ) deve ser true O Se x. equals (y) for f a1se, x.hashCode ( ) -= y.hashCode ( ) podedser true ou false,
mas
false
D As vari6veis
transiente
( ) e hashCode (
).
E D E E
conjunto
List;
m6todos utilit6rios esteticos de conjuntos. ^rmazen As quatro uersdesbasicx dos conjuntos sio as L)stas, Conluntos, MEar e Filas:
E E E tr E
D D
repetigio
perruitida,
comum
indice,
nlo
Ordenado significa
estabelecida.
A classificagio pode
Atributos principais das classes comuns de coniuntos (Obietivo 6.1) [J Arraylist: iteragio e acesso aleat6rio r6pidos; fl Vector: Como um Arraylist um pouco mais lento, principalmente devido a seus m6todos sincronizados; O Linkedlist Adequado para ainsergilo de elementos ao final, ou seja, para pilhas e filas; E HashSet: Assegura a nio existAncia de duplicatas, nio fornece ordenamento; tr LinkedFlashSet: Sem duplicatas; iterapor ordem de insergio; D TreeSet: Sem duplicatas; itera na ordem classificada; E HashMap: atualizag6es mais ripidas (pares-chave/valor); permite uma chave nul1 e muitos valores nu1l; E Hashtable: Como um HashMap mais lento (semelhante a Vector, devido a seus m6todos sincronizados). Nenhum
valor ou chave
nu11
permitido;
E E tr
LinkedHashMap: iterag6es mais r6pidas; itera por ordem de insergio ou de rtltimo item acessado, permite uma chave nu1I e muitos valores nul1; TreeMap: Um mapa classificado. PriorityQueue: IJma lista de coisas a f.azer ordenada pela prioridade dos elementos.
JAVA
349
armazanar Objects, mas tipos primitivos podem ser usados com autoboxing.
com o loop
se
for
o & next ( ).
D hasNext ( ) determina
(
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.
()
E Implemente Comparable usando compareTo ( ); fornece apenas uma ordem de classificagio. E Crie v6rios Comparators para classi{icar uma classe de v6rias formas; implemente compare ( ) .
D
Para um List ser classificado e vasculhado, os seus elementos devem ser compar6veis. Para ser vasculhado, um array ou List deve ser classificado primeiro.
0
tr
java.util fornecem
(
tr Um
D Arrays
m6todo
sort
(
). classifica
D Um m6todo binarySearch ( ).
.
aslist ) cria um List a parrir de um array e vincula um ao outro. U Collections. reverse ( ) inverre a ordem dos elementos de um List.
que classifica ao contririo.
E Colf ections. reverseorder ( ) retorna um Comparator E Lists e Sets tAm um m6todo toArray ( ) para criar arrays.
tr Uq Arraylist
(subclasse
< Animal
se
>
pode aceitar refer6ncias do dpo Dog, Cat ou qualquer outro subtipo de Animal
ou,
tr
A.o usq conjuntos gen6ricos, nXo 6 necess6ria uma conversio para se obter elementos (de tipo declarado) a panir
List list = new Arraylist ( ) ; / / mais c6dioo cts-.I -^ ^ uLtrrre - -- -r r-i=a.get(0); String s = (String)list.get'(0) ;
tr
Voc6 pode passar um conjunto gen6rico para um m6todo que use um conjunto nio-gen6rico, mas os resultados podep ser desastrosos. O compilador.nXo poderi impedirque o m6todo insira o tipo errado no conjunto anteriormente seguro em relagio ao tipo.
Se
o compilador colseguir reconhecer que um c6digo de tipo inseguro esti potencialmenre colocando em perigo algo que voc6 originalmente declarou como de_dposeguro, voc6 riceber6 um aviso do compilador. Por eiemplo, se passar um List ( String ) para um m6todo declarado como
void foo(List
al,ist)
{ al,ist.add(anlnreger),.
o compilador emitiri um aviso, porque o m6todo add ( ) 6 potencialmente uma "operagio insegura".
Lembre-se de que "compila sem erros" nio 6 o mesmo que "compila sem avisos". No exame, um aviso de compilagio nio 6 considerado como erro ou falha de compilagio.
nXo existe no tempo de execudo
compila$o. Misturar gen6ricos com c6digo antigo pode criar um c6digo compilado que poder6 langar uma exce$o no
seguranp em tempo de
e Coniunlos
aplicam-se somente ao tipo-base, e
D As atribuig6es polim6rficas
nio
List<Animal> alist = new ArraylisL<Animal>O; Mas nio List<Animal> al,ist, = new ArraylistcDoS>O;
/ sim
n6'o
//
fl
se
aplica sempre que uma atribuigio puder ser feita. Os seguintes nia sio
baro t ]
//
ndo pode
retornar
um List<Dog>
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
<? exLends
Dog>,
QAoseusarumcoringa,
Q Ao
List<? extends
Dog>,oconjuntopodeseracessado,masniomodificado.
se usar um coringa, List<?>, qualquer tipo gen6rico pode ser atribuido e nXo para modificag6es.
QList<Object>refere-seapenasaumList<Object>,enquantoqueList<?>ouList<? obj ect> podem armazanar qudquer tipo de objeto, mas apenas para acesso. fl As conveng6es de declaraEio para gen6ricos usam T para o tipo e E para o elemento: public interface List<E> / / DecJ-araglo de API para List boolean add(E o) // Dec]-araqdo de List.addo
extends
tr O identificador de tipo dos gen6ricos pode ser usado em declarag6es de classes, m6todos class Foo<t> { } // vma classe T anrnstance; / / vma variiivel de instdncia Foo(T aRef) {} // o arqtmento de um construtor void bar(T aRef ) {} / / o argttmento de um m6t.odo T bazo {} // vm tiPo de retorno
O compilador fornecerS,o tipo propriamente dito.
variiveis:
public class
tr
UseTwo<T, X>
i i
nio definido
na classe:
public
<T>
void makelist(T t) {
T como o tipo de retorno. Esse m6todo tem um tipo & retorno void, mas para usar T dentro do argumento do m6todo voc6 deve declarar o < T ) , o que acontece antes do tipo de retorno.
ndo estivsando
Teste individual
l.
Dado:
import java.util.*; class Test { public static void main(String[] args) / / :.'nsira o c6digo aqui x.add("one";;
x.add("Lwo"1; x.add("TWO");
System.out,println(x.poll
)
O);
JAVA
)
35I
listcstring,> x = new Linkedlist<String> O ; B.TreeSet<String> x = new Treeset<String>O ; C.HashSet<String> x = new Hashset.<String> O ; D. Queue<Stringr> x = new Priorityeueue<Strinq> ( ) ; E.errayl,ist<String> x = new Araylist<String> ( ) ; F.f,inkedf,ist<String> x = new Lj,nkedlist<String>O
A.
2. Dado: public static void main(String[] args) { // INS]RA A DECLARAqAO AQUI for (int i = 0; j- <= 10; i++; { List<Integer> row = new Arraylist.<Integer> for (int j = 0; j <= 10; j++) row.add(i * j);
table.add(row)
)
();
Quais instrug6es poderiam ser inseridas em / compile e rode? (Marque todas as corretas)
TNSIRA
,.
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.
Quais das declarag6es abaixo s6o verdadeiras com relagao comparagdo de duas instincias da.mesma claslq, dado que os m6todos equals ) e halhcode ) foram apropriadamente
l.
E.rue.
o operador
o operador
::
=
de comparagXo de
de comparaSo de
hashCode
true.
D.
E.
Se
Se
o operador
true.
( ) retornar true, o m6todo equals ( ) pode retornar true. !: de comparagio de hashCode ( ) retornar true, o m6todo equals ( ) pode retornar
frashCode
4. Dado: import java.util.*; class Flubber { public sEatic void main(String[) args) { List<String> x - new Arraylist<String>O;
e Coniunlos
))
E
a saida:
xx
Xx
x
Qual c6digo, inserido em /
/ insira
o c6digo
;
as corretas)
,'
D.
Comparabl-e
c = Coflections.reverseOrderO
;
E, Comparator c = Collections.reverseorderO,'
Collections. sort (x, c) ;
5. Dado: 10. public static void main(String[] args) { 11. Queue<String> q = new Linkedlist<String> q. add ( "Veronica" ) ; 1,2 . q.add("Wa1lace"); 13. q.add("Duncan"); 14. 15. showAll (q) ; 16. ]
L1
.
(Queue
q)
42
Veronica
JAVA
353
navl-
l\
\
+ \\ $.|.
I I
before O exibir|12 B. O m6todo before <l exjbiritZl C. O m6todo bef ore ( ) exibir6 tr6s ndmeros, mas a ordem nio pode ser determinada. D. O m6todo before ( ) nio compilari. E. O m6todo before ( )langari uma excegio no tempo de execugio.
A. O m6todo
7. Dado:
.i n*^rts flrLlrur
i ar,L Jqvq.
,, F .i 1 . * . uLr! ,
String>O;
t2 = new ToDos ( "Monday,, ) ; ToDos t3 = new ToDos ( "Tuesday" ) ; m.put (t1, "dolaundry" ) ; m.put (t2, "payBi11s" ) ;
ToDos
m nrrl- /f? qr/ql-am ) nrrjrr^la^nAff nrinl-lnlm i^,,\. cizot\1.
A. Como
est6, o c6digo
nio compilar6.
produit|asuda2.
/,
asaidaser63.
8. Dado: 12. public class AccountManager { private Map accountTotals = new HashMap0; 13. private int retirementFund; 14.
15.
e Coniuntos
16. L7. 18. L9. 20, 2L. 23' 24. 25. 26. j
public int getBalance(Strj-ng accountName) { Integer total = (Integer) accountTotals.qet(accountName); if (totaI == nul1) total = Integer.valueof (0) ; ret.urn total-. intValue ( ) ;
)
Esta classe precisa ser atudizada para usar os tipos gen6ricos apropriados, sem modificag6es no comportamento (nem para melhor nem para pior). Quais destes passos poderiam ser realizados? @Iarque tr6s)
A. Substituir
linha
13
por
linha
13
por
(
linhas l7-20por
(accountName)
(accountName) i
(accountName)
));
9. Dado um array String devidamente preparado, contendo cinco elementos, qual faixa de resultados poderia ser produzida por uma chamada correta de Arrays.binarySearchQ? A.0a4
B.0a5
C. -La4 D. -1a5
E. -5a4
F. -5a5 G. -6a4
H. -6a5
JAVA
355
10. Dado:
interface Hungry<E> { void munch(E x); } interface Carnivore<E extends Animal> extends Hungry<E> {} interface Herbivore<E extends Plant> extends Hungry<E> {} abstract class Plant { } class Grass extends Plant { } abstract class Aninal { } class Sheep extends Animal implements Herbivore<Sheep> { public void munch(Sheep x) {}
)
esse
as
A. Modificar
a interface
Carnivore para
{}
Nio
modificaglo.
I l. Que classe de conjunto permitir6 que voc6 aumente ou diminua o tamanho e fornecer6 acesso indexado a seus elementos, nao tendo, por6m, m6todos sincronizados? (Marque todas as corretas)
A.
java.util . Hashset B. j ava. util . LinkedHashset C. java. util . List D. java.util .Anaylist E. java.util.vect,or F. java. util . Prioritl4ueue
e Coniuntos
{
g.add(new Person ( "Lotte" ) ) ; g.add(new Person( "Jane" ) ) ; g. add (new Person ( "Hans " ) ) ,'
g. add (new Person ( ".Tane" ) ) ;
in
hnnlaan
:AAfohiont-
nt
]
nla<q nri Parcnn rrafo
{
fi na l Cl-ri nd hana. }
public Person(String name) { this.name = name; public String toStringO { return name; }
]
Quais das seguintes coisas ocorrem pelo menos uma vez quando o c6digo 6 compilado e executado? corretas)
M*q*
todas as
A.Adding
C.
Hans
B.addingr Lotte
Adding ,fane
3
total: E. total:
D.
n 4r r
13. Dado:
'imnnrf i:rr: rrri'1 *.
class AlgaeDiesel { public static void main(String[] args) { String[] sa = {"foo", "bar", "baz" }; / / lnsira as chamadas de m6todos aqui
]
]
. Arrays e./ou j ava. util- . Collections voce poderia usar para converter as Quais m6todos de j ava. em um List e depois procurar no List pelo indice do elemento cujo vaTor 6 "f oo"? (Marque de um a tr& m6todos)
util
A.
B.
sort
()
asl,ist ( ) C. tor-ist ( )
()
D. search
E.
sortr,ist o
JAVA
F. G.
357
contains
binarySearch
()
import java.util.*; public cLass LongWordFinder { public static void main(String[] args) { StrinslJ array = { "123", "72345678", ListcString> list = Arrays. aslist (array) ; Collection<String> resultlist = getlongwords (1ist)
)
// INSTRA A
t
DECLARACAO AQUT
Collection<E> longwords = new Arraylist<E> ( ) ; for (E word : coll) if (word.lengthO > 6) longWords.add(word);
return
)
lonqWords,.
]
Quais declarag6es poderiam ser inseridas em compile e rode? (Ir4arque todas as corretas)
/,/
INSIRA A
A.public static
Collection<? extends
CharSequence>
public st.atic Collection<E extends CharSequence> getlongwords ( Col- lection<E> coll_ ) D. public static List<Charsequence>
C.
co 1 1 )
E.public static List<? extends CharSequence> getlongwords (Collection<? extends CharSequence> F. st.atic public <E extends CharSequence> Collection<E>
getlongwords (Collection<E> co11 )
G,
co11)
static public
getlongwords (Collection<E> co11 ) 15. Dado o c6digo a seguir, 12. Treeset map = new Treeset ( ) ; 13. map.add("one");
map.add("two");
juntos );
A. A compilaglo falha
one two three four C. four three two one D. four one three two E. one two three four one F. one four three two one
B. G.
I1 hngada uma excegio no
tempo de execuglo.
6. Dado um m6todo declarado como: public static <E extends Nudber> List<? super
deseja usar esse
Um programador
Quais pares de declarag6es poderiam ser colocados em / compilagio do c6digo? (Marque todas as corretas)
/ INSTRA As
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.
m6todopoll
nXo implementa Queue, e o instanciamento polim6rfico restringiria x a chamar apenas os m6todos declarados na interface List. B, C e E estio incorretas com base no exposto acima.
2. B est6 correta.
A est6 incorreta porque List 6 uma interface, de modo que vocd nio pode usar new List ( ) independentemente de quaisquer tipos gen6ricos. D, E e F estio incorretas porque List s6 usa um parimetro & tipo (um Map usaria dois, e nio um List). C |tentadora, mas incorreta. O argumento do tipo <List<rnteger>> deve ser o mesmo para os dois lados da atribuigio, embora o construtor new Arraylist ( ) do lador direito seja um subtipo do tipo
declarado de List
JAVA
359
3.
B e D. A resposta B 6 verdadeira porclue, freqiientemente, dois objetos diferentes podem retornar o mesmo valor paraoc6digodehashing. D6verdadeiraporquese acomparagiodehashCode( ) retornar: :, osdois
objetos podem ou nio ser iguais. As respostas A, C e E estio incorretas. C est6 incorreta porque o m6todo hashCode ( )6 muito flelvel em seus valores de retorno e, geralmente, dois objetos diferentes podem retornar o mesmo valor de hashing.
AeEnegamocontratodehashCode(
)e
equals
). (Objetivo
6.2)
4. E esth correta. O ordenamento natural produziria uma saida na seqii6ncia inversa da saida listada. O m6todo Collections . reverseorder ( ) usa um Comparator, e nio um Comparable, para reclassificar o conjunto.
A, B, C e D estio incorretas com
base no exposro acima.
(Objetivo 6.5)
5.
B esti correta.
compila
um aviso do compilador na linha 19 devido a uma atribuiglo nlo verificada, mas, fora isso, tudo erros. Embora tenha sido declarada originalmente como Queue<SLring>, em showAll O ela 6 passada como um Queue sem tipo especifico - nada no compilador ou naJVM nos impede de adicionar um Integer depois disso. O m6todo add ( ) coloca itens no final da fila, enquanto que remove ( ) os redra do inicio da lista, de forma que os itens sio exibidos na ordem em que foram colocados.
e executa sem
Hi
6.3)
6.
E est6 correta. Nio 6 possivel colocar Strings e ints no mesmo TreeSet. Sem os gen6ricos, o compilador nio tem como saber qual tipo 6 apropriado para o TreeSet em questeo, entio ele permite que tudo compile. No tempo de execugio, o TreeSet tentarS. classificar os elementos ) medida que eles sio adicionados, e, quando tentar comparar um Integer com uma String, langar6 uma ClassCastException. Observe que, embora o m6todo bef ore ( ) nio use gen6ricos, ele usa autoboxing. Tome cuidado com c6digo que use recursos novos e antigos misturados.
(Objetivo 6.5)
7. CeDestiocorretas.SehashCodeO nioforsobrescrito,entaocadaentradair|paraoseupr6priodep6sito,eo
equals ( ) nlo
hashCode
()
ter6 efeito no que diz respeito a determinar a equivalAncia. Se ( ) sobrescrito veri t1 e t2 como duplicatas.
8.
B. E e G estio corretas.
errada porque voc nlo pode usar um tipo primitivo como parAmetro de tipo. C est6 errada porque um Map usa dois parAmetros de tipo separados por uma virgula. D esti errada porque um int nio pode fazer autoboxing para um nu1 1, e F est6 errada porque um nu1 1 nio pode ser desencapsulado para um 0. H est6 errada porque voc6 nio pode fazer autoboxing de um tipo primitivo apenas tentando chamar um m6todo com ele. (Objetivo 6.4)
A esti
9. G esti correta.
Se uma correspond6ncia for encontrada, binarySearch ( )retornar6 o indice do elemento da corresponddncia. Se nio for encontrada, binarySearch ( ) retornar6 um nrimero negativo que, se invertido e depois diminuido, lhe informa o ponto de inserEio (indice do array) no qual o valor buscado deveri ser inserido no array para que a classificagio apropriada seja mantida.
6.5)
B est6 correta. O problema com o c6digo original 6 que Sheep tenta implementar Herbivore<Sheep> e Herbivore declara que o seu parametro de tipo E pode ser qualquer tipo que estenda Plant. Uma vez que um Sheep nio 6 um Plant, Herbivore<Sheep> nio faz sentido - o tipo Sheep est6 fora da faixa permitida do parimetro E de Herbivore. Apenas solug6es que ou alterem a definigio de um Sheep ou alterem a definigio de Herbivore poderlo conser[ar isso. Assim, A, E e F estio eliminadas. B funciona: modificar a definiqio de um Herbivore para permitir que possa devorar Sheep resolve o problema. C nio funciona porque um Herbivore<Plant> precisa ter um m6todo munch ( Plant ) , e nXo munch (Grass ) . D, finalmente, nio funciona porque, em D, fizemos 'Wolf a classe falha porque o seu m6todo munch ( Sheep ) nio atende mais ao Sheep estener Plant, e
^gora contrato de Carnivore. (Objetivo 6.4)
11.
D estl coffeta. Todas as classes de conjunto permitirlo que voc6 aumente ou diminua o tamanho de seu coniunto. O conjunto Arraylist fornece um indice para seus elementos. As classes de conjunto mais recentes tendem a nio ter m6todos sincronizados. O conjunto Vector 6 uma implementagio mais antiga da funcionalidade de
Aruayl,ist
Arrayl,ist.
As respostas A, B, C, E e F estlo incorretas com base na l6gica que esti descrita acima. Observag6es: uma interface e F, PriorityQueue nlo fornece acesso por indice. (Objetivo 6.2)
12.
C, List 6
( ) de Group - ele deveria ser add ( Person ) , uma vez que a Hashset<Person>. Assim, isso nlo compila. Teste ripido: o que aconteceria se voc6 consertasse essec6digo,modificandoadd(object) paraadd(Person)?Tenteexeantaroc6digoparaverseoresultadobate
e Coniunios
base
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 ( ).
contains ( ) retorna um booleano, e nio um indice. C, D e E estio incorretas porque m6todos nio estao definidos na interface List. (Objetivo 6.5)
perto, mas esti errada porque o valor de retorno
6
14.
F esti correta. A
chega
valorderetornoseiaCollectioncstring>,enioCollection<? extends CharSequence>.Best6 errada porque longWords foi declarado como Collection<E>, e isso nio pode ser implicitamente convertido em um List.<E> para bater com o valor de retorno declarado. @mbora n6s saibamos que longwords na verdade 6 um ArraylistcE>, o compilador s6 tem conhecimento daquilo que foi declarado) C, D e E estio erradas porque nio declaram uma variivel de tipo E (nio hi nenhum < > antes do valor de retorno), de modo que o corpo do m6todo getlongwords ( ) nio vai compilar. G est6 errada porque E super CharSequence nlo faz sentido - super poderia ser usada em conjunto com um coringa, mas nio com uma vari|vel de tipo como E.
(Objeaivo6.3)
15.
est6 correta. TreeSet assegura entradas sem repedgeo; al6m disso, se acessado,
afabdtica.
As respostas A, B, E, F, G e H estio incorretas com base nal6gica que este descrita acima. Observe que, embora voc6 nio seja mais obrigado a usar um Iterator emJava, pode faz6Jo se quiser. (Objetivo 6.5)
16.
B, E
e
F estio corretas.
O tipo de retorno do processo 6 declarado definitivamente como um List, e nio um Arraylist, de modo que A D estio erradas. C est6 errada porque o tipo de retorno resulta em um List<rnteger>, que nio pode ser atribuido a uma variivel do tipo l,istcNumber>. E claro que todas essas provavelmente causariam uma NullPointerException, uma vez que as varilveis ainda sio nulas - mas a questio s6 nos pediu parafazer o c6digo compilar.
Classes internas
individuol
desvantagens (pr6s e contras) das classes internas e o colocar|frenteaexemplos com os tipoi de sintaxe (geralmente de"apar6ncia.rtrirha)]ot qoais vocA ver6 no decorrer de todo o exame. Portanto' na verdade,voc|ter6 dbis objetivos neste capitulo: aprender o necess6rio para responder as perguntas que avaliarem seu conhecimento sobre classes internas, e aprender iomo ler e entender os c6digos de classes internas para que possa acompanhar corretamente o fluxo de perguntas que testarem seu conhecimento em outros tdpicos.
Este capitulo examinar6 asvantagens
e
Entio, por que todo o espalhafato relacionado is classes internas? Antes de entramos no assunto, temos que lhe avisar voc6 ji nio souber) que as classes internas tOm gerado debates apaixonados do tipo amor e 6dio desde que foram
introduzidas na nerslo
1.1 da
(se
linguagem. Pelo menos dessa vez, tentaremos ser reseryados em nossas opini6es e apenas para o exame. Ficar6 sob sua responsabilidade decidir como - e at6 q.t. ponto - deve us6-las em seu pr6prio desenvolvimento. E s6rio. Nem mesmo o toirr q.t. .ts"r-os revelar6 o que Jchamos realmente delas certo, c&o, vamos dizer entio! Achamos que elas tAm alguns empregos poderosos e eficientes
apresenraremos os fatos
em siruag6es muito especificas, incluindo c6digos que sejam mais f6ceiJde ler e de manutengio simples, mas tamb6m podem ser usadas de maneira excessiva e levar a um c6digo tlo claro quanto um labirinto em um milharal, gerando a
As classes internas permitirio que voc6 defina uma classe dentro de outra. Elas fornecerlo um tipo de escopo para suas classes j6 que voc6 poderifazer com que uma classe seja membro de outra. Da mesma forma que as classes Possuem variiveis e m6todos-m.*b.o, tamb6m poiem rer classes-rnembro. Elas v6m em virias vers6es,iependendo d. como e onde voc6 definir a classe interna, incluindo um tipo especial de classe interna conhecido como 'classe aninhada de nivel superior" (uma classe interna marcada com static), que tecnicamente nio 6 uma classe interna.Jique uma classe estitica aninhada nio deixa de ser uma classe definida dentro do escopo de outra classe, tamb6m a abordaremos neste capitulo sobre classes internas. Diferente do que ocorre nos outros capitulos deste livro, os objetivosparaaceftificagio sobre classes internas nio t6m nrimeros oficiais no exame, jiquef.azemparte de outros objetivos abordados em locais diferentes. Portanto, neste capitulo, os cabegalhos dos objetivos p ara a ceftifLcagio representario os quatro tdpicos sobre classes internas discutidos nele, em vez
de
I I I I
internas
an6nimas
At6 agora nio vimos nada incomum; afinal, 6 assim que se sup6e que sejam projetadas as classes do modelo OO. Como eEecia/istas. Por6m, o problema no cenirio do cliente de bate-papo 6 que o c6digo de manipulagio de eventos estA intimamente associado ao c6digo especifico desse cliente! Pense bem: quando o usu6rio pressionar um botio Enviar
JAVA
363
(indicando que q-uer que a mensagem que digitou sej a enviada para o servidor do bate-papo) , o c6digo do cliente de batepapo que enviar6 amensagem ter6 que ler em um campo de texto especifco.Em outras palavias, se o isuirio clicar no botio A, o programa ter6 que extrair o texto do objeto- TextF ieldB, de ama inttdncia espedfca fu ChatClienr Nlo em algu m otlho c1ynp9.de texto de um objeto dzferente,mas especificamente no campo de texto que determinada instAncia da cilse ChatClient referencia. Ponanto, o c6digo de manipulagio de eventos precisar6 de acesso aos membros do objeto ChatClienr, para que seja rltil como o c6digo "auxiliar" de uma instAncia especifica de ChatClient.
E se ChatClient for derivada de uma classe e o c6digo de manipulagio de eventos estender algu ma outraclasse? Voc6 nio Pode fazer.com que uma_classe seja derivada de v6rias classes, portanto, inserir todos os c6dig-os (o c6digo especifico do cliente de bate-papo e o de-manipulagio de eventos) na mesmi classe nlo funcionar6 nesse cio. Entio,6 qui voc6 p^oderiafazerseria se beneficiar da insergio de seu codigo de eventos em uma classe separada (melhor pr6tica no modelo OO, encapsulapglto e o recurso de estender uma classe diferente da estendida por ChatClient), mas,linda assim, concedendo a ele f6cil acesso aos membros da classe ChatClient.(para que o c6digo de manipulagio possa, por exemplo, atualizar xvari6veis de instAncia privadas de ChatClie nt).Y ocpotter; conseg,rii isso fazenio qrlr or rttembros de' ChatClient pudessem ser acessados pela classe de manipulagio ao torn6Jos, por exemplo, priblicos.'Contudo, essa tamb6m nlo 6 uma boa solugio.
.o-
Voc6 i6 sabe para onde estamos indo - um dos beneficios principais da classe interna 6 o "relacionamento especial" que a instdncia de uma classe intemacompanilha com uaa instincia da classe ex.tema. Esse "relacionamento especial" concede ao c6digo da classe interna acesso aos membros da classe que a estiver encapsulando (externa), como se a claise intemafryrseparte da extema.Naverdade, 6 exatamente isso que significa: a classe interna dumapane da classe externa. Nio s6 uma "parte', mas um nembm individual da classe externa. Sim, uma instAncia da classe interna teri acesso a todos os membros da ilasse externa, mgsTo aque/es marcados comopriuados- relaxe e lembre-se de que o objetivo era esse. Queremos que essa instAncia especifica da classe interna tenha um relacionamento intimo com a instAncia da classe externa, por6m, mantendo todo o resto separado. E, al6m disso, se voc6 escreveu a classe externa, enteo tamb6m criou a interna! Ponanto, nio est6 violando o
encapsulamento;voce
prljetlzz dessa
forma.
I I I
Estiticas
Locais de m6todo
An6nimas
No resto
desta seEio, no entanto) usaremos apenas otermo classe internaedescartaremos a palavra clmam quando passarmos para um.dos outros tr6s tipos da lista anterior, voc6 saber6. Defina a classe interna dentro das chaves da classe
a I
segurr:
class Mylnner {
)
isso,
Sjavac Myouter.java
terminar6 com /oziarquivos de classe: MfOuter.dass MlOuter$Mykrner.class
classe
acessar o
interna continua sendo uma classe separada, portanto, um arquivo de classe 6 gerado. Entretanto, voc6 nio poder6 arquivo da classe interna da maneira usual. Nio poder6, por exemplo, escrever:
*java MyOuter$MyInner esperando executar o m6todo main ( ) da classe interna, porque uma classe inte rna comam ndo possui declarag6es estiticas de nenhum ipo. A iinica maneira de uocd conseguir acessar a classe interna seni por meio de una instdncia afiua da c/are externalEm outras Palavras, s6 no tempo de execugio quando ji houver uma instAncia da classe externa a qual associar a instAncia da
classe
as classes:
nlacc
private int x =
/
7;
364 Cooitulo B:
Clqsses internos
O c6digo anterior
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
nlaec
Mrzf)rrt.ar
/ cria
uma
instdncia interna
a l a <<
Mr;Tnnar
Vod podever
no exemplo anterior que o c6digo de MyOutertrataMylnner exatamente como se fosse qualquer outraclasse que pudesse ser acessada - ele a instancia usando o nome da classe (new Myrnner )) e, em seguida, chama um
m6todonavari6veldereferdncia(in.seeouter(
)).Contudo,ainicarazloporqueessasintaxefunciona|queo
c6digo do m6todo de instAncia da classe externa est6 criando a instAncia. Em outras pal avras,ja existe tma inst1ncia da classe erterna- a instdncia qae estd execatando o mdtodomakelnner ( ) . Ponanto, como voc6 instanciari um objeto Mylnner de algum local fora da classe MyOuter? Isso 6 ao menos possivel? @em, j6 que teremos o trabalho de criar um novo subtitulo para esse assunto, como voc6 verA a seguir, o grande mist6rio nio ser6 resolvido aqui.) Uau! Esse 6 um grande quisermos criar uma instAncia da classe interna, 6 preciso ter uma instAncia da classe externa. Voc6 j6 sabe disso, mas pense nas implicag6es... Significa que, sem uma referbnciaauma instAncia da classe externa, nio poderi instanciar a classe interna a partir de um m6todo static da classe externa (porque, nio esquega, no c6digo static ndo hd a referdncia Lhis) ou de qualquer outro c6digo de alguma classe diferente. As instAncias de classes internas sempre recebem uma refer6ncia implicita ) classe externa. O compilador se encarrega disso, portanto, vocA nunca ver|nada,s6 o resultado final - o recurso que tem a classe interna de acessar membros da classe externa. O c6digo para criar uma instAncia de qualquer local fora do c6digo nio-static da classe externa 6 simples, mas voc6 deve memorizar isso para o exame!
O c6digo anterior
6o
mesmo, independente de o m6todo main ( ) estar dentro da classe MyOuter ou de algoma ouha outra classe tenha acesso a MyOuter, e ji que essa tem acesso padrXo, isso significa que o c6digo
JAVA
deve estar em uma classe do mesmo pacote de
365
MyOuter).
public static void main(String[1 args) MyOuter mo = new Myouter1; // vai comegar uma instAnciat I,Eouter.Mylilrer inner = ttro.new lrDrfnner ( ) t
1
anner-seeolrfer()
]
se estivesse chamando um m6todo na instAncia externa que, por acaso, fosse um m6todo de instanciagio especial da classe interna chamado com o uso da palavra-chave ner. e insttcilgio de uma classe interna 6 o ilnico cen6r.io no qual vocA chamar6 new emumainstincia, e nio para conshairvmainstAncia.
est6 um resumo ripido das. diferengas entre um c6digo de instanciaglo de classe interna que estej a dzntv da classe externa (por6m, sem ser est6tico) e um qu e exlafora daclasse externa:
Aqui
De dentro do c6digo da instAncia da classe externa, use o nome da classe interna normalmente:
public stat.ic void main (String[] args) { MyOuter.Mylnner inner = new MyOuterO.new MylnnerO;
inner.scootrfArl)'
)
r
e
De fora do c6digo dainstAncia da classe externa (incluindo o c6digo do m6todo est6tico da classe externa), o nome da classe interna agora deve incluir o da classe externa
MyOuter. Myfnner
para instanciar, vocA precisa usar uma referAncia
classe externa,
new MyOuter(
se i6
.new
this.
Revisio ripida de
this:
r
r I
A palavra-chave
c6digo
this static.
pode ser usada dentro do c6digo da instAncia. Melhor dizendo, nio pode ser usada dentro do
A referAncia
this apontariparao objeto que estiver sendo executado no momento. Em outras palavras, o objeto cuja refer6ncia foi usadapara chamar o m6todo que estiver sendo executado.
6 a maneira de um objeto passar uma refer6ncia dele pr6prio para algum outro c6digo, como argumento de um m6todo:
A refer6ncia thi s
{
;
passa uma
de um c6digo de classe interna, a referlncia thi s apontari para a instAncia da classe, como era de se esperar, j6 que this sempre referencia o objeto que est6 sendo executado. Por6m, e se o c6digo da classe interna precisar de uma referdncii explicita i instAncia da classe externa a qual a instAncia interna estiver associada? Em outras palivras , nmo uoc6 nimti am ponteiropara a "ryferncia Lhis extema"?Embora normalmente o c6digo da classe interna nio precise de uma refer6ncia classe externa, porque j6 ter6 uma implicita que estar6 usando para acessar os membros dessa classe, pode precisar da referAncia se tiver que pass6-la para algum outro c6digo como vemos a seguir:
nl:cc
MrzTnnor
public void seeouter ( ) t System.out.printlp(\tQqter x is " + x) ; System.out.println("fnner class ref is " + this); System. out.printl-n (\Outer cl-ass ref is \\ + Myouter. this)
366 Copitulo B:
Se
Closses inlernos
class MyOuter { Private int x = 7; public void makelnner ( ) { Myfnner in = new MyInner0;
in.seeOuterO;
]
class Mylnner { publj-c void seeOuterO { System.out.println("Outer x is " + x) ; System.out.println("Inner class ref is " + this); System.out.println("outer cfass ref is " + Myouter-this);
]
)
public scatic void main (String[] argrs) { MyOuter . MyInner inner = new MyOuter O . new MyInner
inner. seeOuter
) )
(
asaidaseri:
is Myouter$MyInner@113708 is MyOuter@33f1d7
pr6pria ou para a instancia externa do c6digo
dessa classe, use
sAo as
seguintes:
I I
pr6pria
"
thi
thi s
NomeDaClasseExterna.
this
(exemplo,
MyOuter . this).
A
classe
internas
externa, exatamente como os m6todos e variiveis de instAncia, portanto, os modificadores a seguir podem ser aplicados a umaclasse interna:
I I I I I I I
O escopo
de
um m6todo:
cl-ass Myouter2
JAVA
367
void doStuff O { cfass Mylnner { public voj_d seeOuter ( ) { System.out.println("Outer x is " + x); j / / fecha o m6todo da cfasse interna j / / fecha a definiqdo da classe interna / / fecha o m6todo doStuff0 da classe externa \ j // fecha aclasseexterna
Oc6digoanteriordeclaraumaclasse,Myouter2,comumm6todo,doStuff
outra classe, MyTrurer, 6 declarada com seu m6todo pr6prio, seeouter ( ) . O c6digo acima 6 completamente inritil, no entanto, p orqve ndo instancia a clase intemalS6 por que vo cE declarou a clxse, neo significa que criouuma insldncia dela. Ponanto, se quiser realmente llsara classelnterna (digamos, para chamar seus m6todos), entao, voce ter6 que criar uma instincia dela em algum loc al dentro fu ndtodo, mas abaixo da defnipdo da dasse intema. O c6digo abaixo mostra como instanciar e usar uma classe interna local de m6todo:
a'lacc MrrOrrfar? I
).Por6m, duttrodedoSLuff
( ),
private String x = "Outer2"; void doStuff O { class Mylnner { public void seeouterO { System.out.println("Outer x is " + x); j / / fecha o m6todo da classe interna
\ | / focha a dofininSo da classc interna
/ /
) I
) da classe externa
Pense bem. As
variiveis locais do m6todo residem na pilha e s6 existem conforme a duraglo do m6todo. VocA ji sabe que o variivel local 6 limitado ao m6todo em que foi declarada. Quando o m6todo 6 fin alizado, o quadro da pilha 6 eliminado e a vari6vel vira hist6ria. Contudo, mesmo depois que o m6todo 6 concluido, o objeto da classe interna criado denrro dele ainda pode estar ativo no heap se, por exemplo, uma referAncia_a ele tiver sido passada para algum outro c6digo
escopo de uma
e, em seguida,
arriazrnada em uma vari6vel de instAncia. J6 que.as vari6veis locais nio t6m_ garantia de continuarem ativas classe interna local de m6todo, esse objeto_nio pode usi-las. A menor qae as umiiueis locais vlan maridas cono f inal.'lO c6digo a seguir tenta acessar uma varilvel iocal de dentro de uma classe interna local de metoclo:
class MyOuter2
nri rra1-e Sfri
v!+vsev
{
r16J
x = "OUter2";
{
void doStuff O
al:qc M\/Tnhar
nr:int1n("Ogter
Svsfem-out-ni:int1n("Local
368 Copitulo B:
Closses inlernos
\ j \
/ fecha o m6todo da classe interna / / fecha a definigdo da classe interna / / fecha o m6todo doStuff ( ) da classe externa
/
//fechaaclasseexterna
realmente
preocupari o compilador:
com f
inal
corriglr.^ o problema:
Apenas um lembrete sobre os modificadores de um m6todo: as mesmas regras das declarag6es de vari6veis locais sio aplicadas )s classes internas locais de m6todo. VocA nio pode, por exemplo, marcar uma classe interna local de m6todo com public, private, protected, static, transient e algo semelhante. Os rinicos modificadores que vocpader,i aplicar a essa classe sio abstract e f inal - mas 6 claro que nunca os dois ao mesmo tempo como para qualquer outra classe ou m6todo.
oBSERVAQ6ES
terd acesn rlmente a membros da classe extenta, uma ue< que nenbuma instdncia associada da c/asse externa. S e uocd e#iuer em un ndtodo s t a t i ndo baueni a referdncia Lhis, portantl, a classe intema de um mdtodo s t a t i utd suleita as mesmas restipdes desse mdtodo. Em outras pa/arras, ndo tem ace$o a "uaidueis de
in$dncia".
hl-t
r. \,roleTtvo poro
r.f. o centttcocoo
Talvez sua tarefa mais importante aqui seja aprender a ndo se confundir quando se d.eparar com essa intaxe. O exame est6 repleto de c6digos com classes internas an6nimas. 56 para ter uma id6ia, voc6 poderi v6-los em perguntas sobre threads, wrappeobre, sobrescrigio, coleta de lixo, etc.
t
ln / rtnana^r^r, yvvuvrll \ /,
cl-ass Food
"anonlmous popcorn,' ) ;
JAVA
369
I;
)
r I I
Definimos duas
classes,
Popcorn e Food.
Food tem uma variivel de instAncia, declarada com o tipo Popcorn. Isso 6 tudo quanto m6todos.
i Food.
Essa classe
nattem
A variivel
de referAncia Popcorn ndo aponta para uma instAncia de Popcorn, mas para a instdncia de ana subclasse an6nina (ndo noneada) de Popcorn.
3. 4. 6. j;
Linha2
formato:
{
(
out.printl-n
"anonlzmous popcorn" ) ;
A linha 2
comega como uma declaragio de vari6vel de instAncia do tipo Popcorn. Mas, em vez de ter este
Popcorn
do ponto-e-virgula
"Declare uma variivel de referAncia, p, do tipo Popcorn. Em seguida, declare uma nova classe que nio tem nome, mas 6, uma sbclasse de Popcorn. E agora temos a chave que abre a definigio da classe..."
Linha
pop
( ) da superclasse
interna an6nima:
primeira instrugio dentro da definigio da nova classe. E o que ela Popcorn. Aqui este o ponto crucial da criagio de uma classe da saperclasse (ou implementar m6todos de uma interface, mas
a
4 Alinha46aprimeira (enesse casoailnica) instruglodom6todopop( ) novo. Nadaespecialaqui. Linha 5 A linha 5 cont6machave defechamento do m6todopop( ). Nadaespecial aquitamb6m. Linha 6 E aqui que vocA ter6 que prestar atengeo: a linha 6 inclui uma chauefechando a defnipdo da classe andnina (6 a
Linha
chave que acompanha a da linha 2), por6m, aindah| mais! Essa linha tamb6m tem 0 plnto- e-uirgula qaefnali7a a inshztgdo iniciada na linha 2, instruglo em que tudo comegou - a que declara e inicializa a vari6vel de referAncia Popcorn. Portanto, terminaremos com uma referAncia de Popcorn a uma instAncia rec6m-criada da novissima rubclasrc an6nima (sem nome) instantAnea de Popcorn.
ponto-e-uirgula
\ {
de
fechamento. Portanto,
uocd
conl
este n0 exame:
iar^r rrefv
rvyevlrr\/
Dnnnnrnf
^,,1-1
Puvrfe
4.
.i
p,ara
Voci precisard de um cuidado especia/ com a sintaxe qaando houuer classes internas enuoluidas, porqae o aidigo da linba 6 parece perfeitanente natural. Ndo estamos acostumadot a uer o ponto-e-uirgala depois de chaues (a ilnica oatra sitaagdo em qae isso ocorre t1 em atalhos na inicialirygdo de anay).
classes intemas an6nimas estlo envolvidas. kmbrese & q*, como no exemplo antarior de Popcorn, estamos usando o tipo da vari6vel de referAncia de uma superdasse para referenciar um objao da zubclasse. Quais sio as implicag6es? Vod s6 poder6 chamar os m6todos da refer6ncia de uma classe interna an6nima que forem definidos no tipo davaiilelde referAncia! Iso nlo 6 diferente de qualquer outra referAncia polim6r{ic4 por exemplo:
370 Copitulo B:
Clqsses internos
c]ass test { public static void main (String[] args) { Animalh=newHorseo; h.eatO; / / V61ido, a classe Animal tem r.m m6todo eato h.buckO; // Inv6lido! A classe Animal- nao tem buck()
] ]
classe interna an6nima que, em vez de sobrescrever um m6todo da superclasse, defina seu pr6prio m6todo novo. A definiglo do m6todo nlo 6 o problema, no entanto; o que impona realmente 6 como vocA chamari esse novo m6todo. O tipo da variivel de refer6ncia (a superclasse) nio terA nenhuma informagdo sobre esse mltodo (definido na subclasse an6nima), e o compilador reclamarA se voc6 tentar chamar qualquer m6todo na referAncia de uma classe interna an6nima que nXo esteja na definiglo de classes da superclasse.
{ )
;
out.println ( "popcorn"
cLass Food
^,,1-1 Puvffu
.i
{ {
t
(
"anonymous
sizzling popcorn"
);
"anonlmous popcorn" ) ;
];
public void poplt ( ) { p.pop O ; / / oK, Popcorn tem um m6todo pop o p. sizzle (l ; / / Inv6lido ! Popcorn ndo tem sizzfe
]
]
Popcorn
que 6 a maneira de o compilador dizer: "NXo consigo encontrar o m6todo seguido de: "Consiga uma pista".
JAVA
371
Mas, se Popcorn fosse um tipo de intefaa emvez de um tipo de classe, entAo a nova classe an6nima seria um inp le n e n tador da i n terface em v ez de uma s u b t las s e da c las s e, Examine o exemplo abaixo :
class Food {
Cookable c = new Cookableo
{
];
]
O c6digo anterior, como o exemplo de Popcorn, tamb6m cria a instAncia de uma classe interna an6nima, mas, dessa vez, a nova classe instantanea 6 um implementador da interface Cookable. E 6 bom ressaltar que essa ser6 a rinicavezqlre
voc6 ver6
a
sintaxe,
(
)
new Cookable
instanciar uma inteface,
emqueCookable 6umainterfanemvezdeumtipodeclassenioabstract.Porque,pensebem,
uoc6niopode
emboraparega que 6 isso que o c6drgo est|fazendo. Mas 6 claro que ele nio est6 instanciando um objeto Cookable, est6 criando a instAncia de um novo implementador an6nimo de Cookable. Portanto, voc6 pode ler a linhaabaixo,
Cookabfe
c = new Cookable0
Cookable
implementarainterfacecookable.Mas,ahsim,aindanio temotumaclassequeimplementeCookable,portanto,
cflaremos uma agora mesmo. Nio precisamos de um nome para a classe, mas ela seri uma classe que implementar6 Cookable, e essa chave iniciar6 a definigio da classe implementadora". Mais uma coisa
a memorizar sobre implementadores an6nimos de interface: eles podem implewentar sowefite uma inte(ace. Simplesmente, nlo h6 um rnecanismo que defina que sua classe interna an6nima ir6 implementar virias interfaces. Na verdade, uma classe interna an6nima nio pode nem estender uma classe e implementar uma interface ao mesmo tempo. A classe interna precisa da definiglo de se ir6 ser a subclasse de uma classe nomeada - e de maneira alguma ir6 implementar diretamente qualquer interface - az se implementari uma rinica interface. Por "diretamente", queremos dizer usando a palavra-chave implements como parte da declaragio da classe. Se a classe interna an6nima for uma subclasse do tipo de uma classe, ela se tornari automaticamente um implementador de qualquer interface criada pela superclasse.
oBSERVAQ6ESpeneOE)(AME
l,{60
se deixe enganar
por qaalquer tentatiua de instanciagdo de intefan que ndo s/a uma clase intema an6nima.
u,llida,
r = newRunnabl-el); // impossivel instanciar a interface enqaantl a qae re encontra abaixo d udlida, porque estui instanciando ua implementador da inteface Runnable
Runnable
iruplenentaqdo
(una
classe de
aninina): em
Runnable
vez de ponto-e-virqula
);
372 Copitulo B:
Closses internos
gostariamos de nos responsabilizar completamente pela confusio. Por6m, ficaremos felizes em compartilhar.
se voc chegou a essa sentenga presumiremos que voc6 compreendeu a segio anterior e adicionaremos apenas uma nova alteragio. Imagine oien6rio a seguir. Voc est6 digitando, tentando criar a classe perfeita, e .i.r.n. o c6digo que chama um m6todo em um objeto ear e usa um objeto do tipo Foo (uma interface).
Certo,
void foof O ;
]
nlo
ter-o
instanciar um, porque nem mesml tem umaclasse que implenenteFoo, o que dizer da instAncia dela. Assim, primeiro voc0 precisa de uma classe que implemente Foo e, em seguida, precisar6 de uma instAncia dessa classe que ser6 passada para o
m6tododoStuff
an6nima, dentro seu c6digo:
do argumenlo.
)daclasseBar.SendoumprogramadorJavaastuto,voc6simplesmentedefiniriumaclasseinterna Exatamente, logo onde voc6 menos esperaria encontrar uma classe. E aqui est6 o formato de
{ o {
/ \f^^f\r/
5.
6
r,^.i^
+^^f
q\tqfpm
arrt. nrinfln
j // final-izaom6todofoof 7. j) ; / / finaliza as instruq6es def, arg' e end da classe interna 8, j // finalizago(l 9. L0. j // final-iza a classe
11.
1,7. \
a agio comega na linha 4. Estamos chamando doStuf ) em um objeto Bar, mas o m6todo usa uma instAncia que E-Um Foo, em que Foo 6 uma interface. Ponanto, temos que criar tanto um a clxse de implementagdo quanto uma instdnciadessaclasse, tudo bem aqui no argumento de doStuf ) . EntXo,6 o que faremos. Escreveremos
f(
f(
new
FooO
para iniciar a nova definigio da classe an6nima que implementar6 aintertace Foo. Foo s6 tem um m6todo a implementar, f oof ( ) , portanto, nas linhas 5, 6 e 7 implementamos esse m6todo. Em seguida, na linha 8 - calma! - aparece mais uma sintaxe estranha. A primeira chave fecha a nova definiglo da classe an6nima. Mas, nio esquega que isso tudo ocorreu como parte do argumento de um m6todo, de modo que o par6ntese de fechamento ')' finaliza a chamada do m6todo, e ainda temos que encerrar a instruQio que comeqou na linha 4; assim, finalizaremos com um ponto-evirgula. Esiude essa sinta*ei YocE ueri classes internai an6nimas no exame e teri que ser muito cuidadoso com a
JAVA
373
maneira como sao fechadas. Se elas forem locais de argumento, terminario assim,
));
mas se forem classes an6nimas simples, entao, sereo finalizadas assim:
j;
De qualquer forma, a sintaxe nio 6, a que voc6 usar6 em praricamenre qualquer outra parre da linguagem Java, Poftanto, seja cuidadoso. IJma pergunta de alguma pane do exame pode envolver claises internas an6nimas constituindo o c6digo.
Iicil
tipo de gentilez
As ,r.zes, ouvimos falar de classes est6ticas aninhadas como classes aninhadas de nivel superior ou classes internas e$dticas, mas elas nio sio de maneira alguma classes internas, pela definigio padrio de uma classe interna. Enquanto uma classe interna (independente da versio) se beneficia do relacioianento especial com a classe externa (ou, emvez disso, poderiamos dizer qve as iilstdncias das duas classes compartilham um rilacionamento), uma classe estitica aninhada nio tem esse privil6gio. EIa simplesmente 6 uma cLsse nio-interna (tamb6m conhecida como "de nivel superior") cujo escopo se encontra dentio de outra classe. Ponanto, quando'se trata de classes estiticas, na verdade, a resolugio do nome-espago conta mais do que um relacionamento implicito entre as duas classes. IJma classe aninhada estatica 6 simplesmente
aqaela que d um merybro utdtico da classe encapsulatlora,
nesse caso,
classe propriamente dita nio 6 realmente "est6tica"l nio existem classes est6ticas. O modificador informa que a classe aninhada 6. um membro utitico da classe extema.Isso significa que ela pode ser acessada,
sem ter
static,
tma instdncia da
c/asse extema.
comum,
nl:qq
class Broom { static class 82 {void goB2( ) { System.out.println(..hi 2,,\; } } public static void main(String[ ] args) { Bigouter.Nest n = new Bigouter.Nest( ); // an,bos nomes de n.go( ); 82b2= new82( ); // acessa a classe interna b2.goB2( );
)
cl_asses
O que produz
hi
r]i2
374 Copitulo B:
Closses inlernos
is
aai,iueis de instdncjas
e m,itodos
ir
ndo-sLaLic
ndo-sEatic da c/asse, uma clasrc estdtica da claxe extema. Procare por c/asses aninhadas
static
con aldigo que se czmplfte tuml uma classe ndo+stdtica (intena regukr).
A seguir examinamos
de uma classe
Tamb6m examinamos o tipo de classe interna mais estranho de todos' a classe interna an6nima. Voc6 aprendeu que elas v6m em duas formas: simples e local de argumento. As classes internas an6nimas, digamos, normais, sio criadas como parte da atribuigio de umi vari6vel, enquanto as classes internas locais de argumento, na verdade, sio declaradas, definidas e automaticamente instanciadas dentro do argumento de um m6todo! Abordamos a maneira como as classes internas an6nimas podem ser uma subclasse do tipole classe nomeado ou um implementador da interface nomeada. Para concluir, examinambs como o polimorfismo 6 aplicado a classes internas an6nimas' voc6 s6 pode chamar na nova instAncia os m6todos definidos com o tipo de interface ou classe nomeada. Em outras palavras, mesmo se a classe interna an6nima definir seu novo m6todo, nenhum c6digo externo a ela poder6 chamar esse m6todo.
Como se j6 nio estiv6ssemos nos divertido o suficiente para um dia, passamos para as classes internas est6ticas, que, na verdade, nio sio classes internas. Conhecidas como classes aninhadas est6ticas, uma classe aninhada marcada com o modificador s tat i c 6 bem semelhante a qualquer outra classe nio interna, exceto pelo fat o de que pan acess6-la, o c6digo deve ter acesso tanto ) classe aninhada quanto ) classe encapsuladora. Vimos que como a classe 6 estitica, nenhuma instAncia da classe encapsuladora 6 necessiria e, portanto, a classe aninhada est6tica nlo compartilha um relacionamento especial com nenhumi instAncia da classe encapsuladora. kmbre-se de que as classes internas est6ticas nio sio capazes de acessar m6todos ou vari6veis de instincias.
Exercicios ripidos
Aqui estXo alguns dos pontos principais deste capitulo.
Classes internas E Uma classe interna "comu m" 6, declaradadentro das chaves
bloco de c6digo.
outro
(externa), portanto, pode ser marcada com um modificador de acesso, assim como com o modificador abstracL ou f inal (mas 6 claro que nunca com abstract e f inal ao mesmo tempo - lembre-se de que abstract significari que ela deve ter subclasses,
final
A instAncia da classe interna companilhari um relacionamento especial com uma instAncia da classe encapsuladora. Esse relacionamento concederi ) classe interna acesso a todos os membros da classe externa, incluindo os
marcados com
private.
fl E
Para instanciar uma classe interna, voc6 precisa ter uma refer6ncia
JAVA
375
A partir de um c6digo externo aos m6todos de instAncia da classe encapsuladorq vod pode instanciar a classe interna usando somente os nomes das classes interna e extema e uma referncia i classe extern4 como no c6digo abaixo:
Myouter mo = new MyOutero; Myouter.Myfnner inner = mo.new MylnnerO; A partir de um c6digo dentro da classe interna, a palavra-chave
instAncia da classe interna- Para apontar para a refer|ncia
classe externa a qual essa
classe externa
MrzOrri- ar
this pode armazenar uma refer6ncia i this .*t.rrr" (em outras palavras, a instAncia da esti associada) anteceda a palavra-charr. i5i" com o nome da
thi
D Uma classe interna local de m6todo 6 definida dentro de um m6todo da classe encapsuladora. D Para a classe interna ser usada, vocA precisa instanci6Ja, e essa instanciagio deve ocorrer dentro do mesmo
m6todo, por6m, ap6s o c6digo de definigio da classe.
E E
Uma classe interna local de m6todo.nio pode usar variiveis declaradas dentro do m6todo (incluindo parAmetros), a menos que essas variSveisie.lam marcadas com f inal.
Os rinicos modificadores que voc6 pode aplicar a uma classe interna local de m6todo sio f inal (nunca os dois ao mesmo rempo, no entanto).
abstracL
e seu
D Uma
pontoe-virgula em Java.
classe interna an6nima 6 sempre criada como pane de uma instruEio, portanto, nio esquega de fechar a instrugio, com uma chave, ap6s a definigXo da classe. Essa 6 uma d"s raras vezes em que voc6 ver6 uma clave seguida de um
D Por
causa do polimorfismo, os inicos m6todos que voc6 poder6 chamar em uma refer6ncia ) classe interna an6nima serio os delinidos na classe (ou interface) da variivel de referOncia, ainda que a classe an6nima seja, na verdade, uma subclasse ou um implementador do tipo da vari6vel de referAncia.
pode estender uma subclasse azr implementar uma interface. Diferente das classes nio. an6nimas (internas ou nio), uma classe interna an6nima nio pode fazer as duas coisas. Em outras palavras, nio pode e$ender uma classe e implementar uma interface, nem implemlntar mais de uma interface.
E Uma
interna de argumento local 6 declarada, definida e automaticamente instanciada como pane de uma chamada O importante a lembrar 6 que a classe estar6 sendo definida dentro do argumento de um m6todo, portanto, a sintaxe finalizariadefinigio da classe com uma chave, seguida de um par6ntese de feihamento para encerrar alhamada do m6todo, que ainda ser6 seguido por um ponto-e-virgula, o qual fechari a instruEio: ] ) ;
classe
de m6todo.
static.
E
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.
Instanciar uma classe aninhada estitica requer o uso tanto do nome da classe enerna quanto o da aninhada, como
vemos abaixo:
estitica nlo pode acessar membros nioest6ticos da classe extern4 ji que nio tem uma refer6ncia implicita nenhuma instAncia externa (em outras palavras, a instAncia da classe aninhada nio usa uma referAncia thi s orterna) .
Teste individual
As perguntas a seguir o ajudario a avaliar sua compreensio do material dinAmico e transcendente apresentado neste capitulo. Leia todas as opg6es com cuidado. Selecione todas as resposras corretas para cada pergunta. Nlo apresse. Relaxe.
se
376
Cooftulo
8:
Closses internos
que instruglo, se inserida em uma classe diferente de MyOuter ou Mylnner, criar6 uma instAncia da classe aninhada?
,{. Myouter.Mylnner m = new Myouter-Myfnner( ); B. uyouter.Mylnner mi = new Mylnner( ); C Myouter m = new uyouter( ); Myouter.MyInner mi = m.new Myouter.MyInner( ); D. Myrnner mi = new MyOuter.Mylnner( ); 2. Quais das declarag6es abaixo s6o verdadeiras com relagao
todas as corretas)
A
B.
Voc6 precisa ter uma referdncia ) instAncia da classe encapsuladora para instanci6-la. Ela nio tem acesso a membros
Suas
nlo-sLatic
da classe encapsuladora.
C
D. E.
variiveis
static.
e a classe
Se a classe
externa
chamar
Mlouter,
)
;
aninhada
se
chamar
Myrnner,
new
Myouter.Myfnner(
}
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)
= new eoo(24) { };
JAVA
377
4. class Test { 5. publj_c static void main (String [] args) 6. Foo f = new FooO;
7
.
]
/ / Trq; r:
n n,idi ^n =qui
8. 9.]
que instruglo, inserida na linha 7, criari uma instAncia de Bar? (l\4arque todas as corretas)
A. foo.Bar b = new Foo.Bar( ); B. Poo.Bar b = f .new ear( ); C. Bar b = new f .Bar( ); D.ear b = f .new Bar( ); E. P'oo.Bar b = new f .Bar( ); 6. Quais das declarag6es abaixo s6o verdadeiras com relagao a uma classe interna local de m6todo? (Marque todas :N correhs)
A C
D.
i-nal.
E.
7. O que 6 verdade com relagao ) classe interna an6nima? (Marque todas as correhs)
,4" Ela pode estender somente uma
classe e
B.
Ela pode estender somente uma classe e implementar v6rias interfaces. Ela pode estender somente uma classe ou implementar apenas uma interface. Pode implementar virias interfaces, independente de tamb6m estender uma classe. Pode implementar virias interfaces,
se
C
D.
E.
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<)
(new
]
BarO t]).goO;
378
Cop(tulo
B:
Closses internos
C. foobarhi
D.
barhi E. hi
9. Dado o c6digo a seguir, 1. public class TestObj { 2. public static void main (String [] argrs) t 3. Object o = new Object0 { publ j-c bool-ean equa]s (Obj ect obj ) t 4. return true; 5. 6. ) 7. ] System.out.println(o.equals("Fred") ) ; 8.
q]
10.)
qual ser6, o resultado?
de execugio.
L. ralse
D. A compilagio falhari por
causa de um erro na linha 3.
causa de
um erro na linha 4.
8.
0. Dado o c6digo a seguir, 1. public class HorseTest { 2. public static void main (String [] args) 3. class Horse { public String name; 4. public Horse(String s) { 5. 6. name = s; 7. ) B. ] 9. Object obj - new Horse("Zippo"); 10. Horse h - (Horse) obj; 1,1. System.out.printfn(h.name) ; t2. ]
1? ] qual serd o resultado?
E. A compilagdo
F. A compilaglo falharipor
I
l.
{
{
2. public static void main lsrrino [t aras] 3. class Horse { 4. public String name; 5. public Horse(String s) { 5. name = s,. t. ) 8. ] 9. Object obj = new Horse ( "Zippo,') ; 10. System.out.println(obj.name) ;
1.r.
12. j
C. A compilagdo falharipor
12. Dado o c6digo a seguir, publ-ic abstract cl-ass AbstractTest public int getNum0 {
return
)
45;
public static void main (String [] args) AbstractTest t = new AbstractTestO { public int getNum( ) { retwrn 22;
]
];
AbstractTest.Bar f = t.new BarO public int getNumo { return 57;
]
{
];
q\/c1-am arrlnrinf lnlf nal-\Trrmt\ + \'t\ + | dafT\Trrmf ]).
380 Copitulo B:
Closses internos
4.57
22
B. 43 s8
c.4s
57
E. A compilagio falhar6.
A. Mylnner
uma classe aninhada est6tica, portanto, deve ser instanciada com o uso do nome do escopo
6
completo que
MyOuter.Mylnner.
usa o nome da classe encapsuladora na instrugio new. C est6 errada porque usa a stnraxe ,rrcor.et". Quando voc6 instanciar uma classe aninhada. chamando a palavra-chave new .* ,rrn" instAncia da classe encapiuladora, nio teri que usar o nome dessa classe. A diferenEa entre A e C 6 que C est6 chamando new em uma instAncia da claise encapsulador^, ern uez de chamar a,palavra-chave iioladamente. D est6 incorreta porque nio usa o nome da classe encapsuladora na declaragio da variivel.
,)
B e D. A resposta B est6 correta porque uma classe aninhada estitica nio 6 associada a uma instAncia da classe or m.mbros nio-static da classe (da mesma forma que um m6todo encapsuladori e, porranto, nio podi
stalic
"cersar niopodeacessarosmimbrosnioesr6ticosdeumaclasse).Dusaasintaxecoffetaparainstanciagiodeuma
classes aninhadas est6ticas nio precisam (e nio podem usar) de uma referAncia ) instAncia da classe encapsulidoia. C esti errada porque as classes aninhadas est6ticas podem declarar e definir membros nio-estlticos. E estl iniorreta porque... Simplelmente est6. Nlo h6 uma regra que diga que uma classe interna ou aninhadatenha que estender algo.
estA correta. Ela define a instAncia de uma classe interna an6nima, o que tamb6m significa que ao mesmo tempo cria uma instAncia dessa nova classe an6nima. A classe an6nima 6 um implementador da interface Rur:nable, portanto, deve sobrescrever o m6todo run ) de Runnable.
3.
A resposta A
4. B e
),
portanto, viola
as regras da
incorreta.
est6 correta porque as classes internas an6nimas nio slo diferentes de nenhuma outra quando se trata de polimoifismo. Isso significa que vocA sempre poder6 declarar uma vari6vel de referniia do tipo da superclasse e ter essa vari|vel referenciando a instincia de um tipo da subclasse, que, nesse caso, 6 uma subclasse an6nima de Bar. Ji que Bar 6 uma subclasse de Boo, tudo funciona. C usa a sintaxe correta para a criaglo de uma instAncia de Boo.
C. A resposta B
classe
passa um tipo int para o constnrtor de Boo, e nio hi um construtor Boo. D est6 errada porque viola as regras do polimorfismo; voc6 nio pode referenciar um tipo da superclasse usando uma variivel de refer6ncia declarada com o tipo da subclasse. NXo 6 garantido que a superclasse tenha tudo que a subclasse possui. E usa a sintaxe incorreta.
na
classe
f,.
B est6 correta porque usa a sintaxe certa - emprega os dois nomes (das classes externa e interna) na declaraEio da refertncia, utilizando, em se gwda, uma referbncia ) classe ext erna para chamar new na classe interna.
As repostas A, C, D e E usam a sintaxe incorreta. A esti incorreu porque nio usa uma refer6ncia ) classe externa, e tamb6m porque inclui os dois nomes na instrugio new. C est|ercadaporque n5o usa o nome da classe externa na declaraglo da variivel de referAncia e porque a sintaxe de new nio esti correta. D est6 incorreta porque nio usa o nome da classe externa na declaragio da variivel de refer6ncia. E est6 errada porque a sintaxe de new est6 incorreta.
6.
BeE.ArepostaBesticorretaporqueumaclasseinternalocaldem6todopodeserabstract,emboraissosignifique
for usada (ponanto,6 improv6vel necessidade da criagio de uma subclasse da classe interna se a classe seja ritil). E est6 correta porque uma classe interna local de m6todo que uma classe interna local de m6todo funciona como qualquer outra classe interna - tem um relacionamento especial com uma instincia da classe externa, de modo que pode acessar todos os membros dessa classe.
a
abstract
abstract
A resposta A
seja
esse
viiido faz-lo). C e D esteo erradas porque uma classe interna local de m6todo nio pode ser public (embre-se de que voc6 nio pode marcar nenhuma variivel local com public) ou static.
a sintaxe de uma classe interna an6nima s6 permite um tipo nomeado depois de.new, tipo tem que ser apenas uma interface (caso no qual a classe an6nima implementari essa interface) ou vma inica classe (situag5o em que a classe an6nima estender6 essa classe).
e
est6
incorreta porque uma classe interna local de m6todo nio precisa ser declarada como f
inal
(embora
D e E estXo
JAVA
5 381
C.
8.
C esti correta pgrgue primeiro a instAncia de Foo 6 criada, o que significa que o consrnrtor de Foo foi executado e exibir6 foo. Aseguir, o m6todomakeBar( I 6 chamldo, o que criaumainstAnciade Bar, significando que o constnrtor de Bar foi executado e exibir6 barl e, para concluir,6. criadauma instAncia (de um subtipo an6nimo de Bar) partir da qual o m6todo go0 6 chamJdo. Repare que a linha (new Bar ( ) { ^ ] ) . so ( ) ; cria uma pequena classe interna an6nima, um subtipo de Bar.
As respostas A, B, D, E e F estXo incorretas com base na l6gica do programa que esd descrita acima.
com um ponto-e-virgula. Lembre-se de que a linha 3 6 uma linha 7 e, como instrugio, precisaria de um ponto-e-virgulicomo fechamento!
$ B, C, D, E e F estio incorretas com base nal6gica do programa descrita acima. Se o ponto-evirgula fosse adicionado i linha 7, entio a resposta B estaria correta - o programa exibiria true, o retbrno do
equals (
)
obj ect.
B. O c6digo da classe FlorseTest 6 perfeitamente v6lido. A linha 9 cria uma instAncia da classe interna local de m6todo Horse, usando uma variivel de refer6ncia declarada com o tipo Object. A linha 10 converte o objeto
Horse na vari|vel de refer6ncia Fforse, o que permitir6 que a linha 11 seja compilada. Se a linha 10 fosse removida, o c6digo de HorseTest nio seria compilado, porque a classe Object nio tem uma vari|vel name. As repostas A, C, D, E e F estio incorretas com base na l6gica do programa que est6 descrita acima.
11.
E. Esse c6digo 6 semelhante ao da pergunta L0, exceto pela instrugio de converslo ter sido removida. Se voc6 usar uma vari6vel de referncia do tipo obj ect, poderi acessar somente os membros definidos na classe
Obj
ect.
As repostas A, B, C e D estio incorretas com base na l6gica do programa que esd descrita acima.
12.
A. Voc0 pode definir uma classe interna como abstract, o que significa que s6 poderl instanciar subclasses concretas dessa classe. O objeto referenciado pela vari6vel t 6 a instAncia de uma subclasse concreta de AbstractTest, e a classe an6nima sobrescreve o m6todo getNum( ) para que retorne 22. Avariiryel
referenciada por f 6 a instAncia de uma subclasse an6nima de Bar, e essa subclasse tamb6m sobrescreve o m6todo getNum ( ) (para que retorne57). Lembre-se de que para criar uma instAncia de Bar, precisaremos de uma instAncia da classe externa AbstractTest, a fim de associ6-1a I nova instincia da classe interna Bar. AbstractTest nio pode ser instanciada porque 6 abstract, portanto, criamos uma subclasse an6nima (nioabstract) e, em seguida, usamos essa instAncia associando-a ) nova instAncia da subclasse de Bar. As repostas B, C, D, E e F estio incorretas com base na l6gica do programa que esd descrita acima.
382 Copitulo 8:
Clqsses internos
Threads
notifyfl ou noiifyAll0
Exercicios 16pidos
Teste Individuol
384
Copftulo 9: Threods
Imagine um aplicativo para corretores do mercado financeiro com virios comportamentos_complexos iniciados pelo usu6-"rio. Uma das aplicag6es seria"fazer o download das ultimas opg6es deprego das ag6es", a outra, "verificar avisos de pregos"; e uma terciira operagio, mais dem orada, seria"artalisar dados hist6ricos da emp resaY{Z" .
Em um ambiente de tempo de execugio de segmentaglo inica, essas.ag6es serio executadas uma ap6s a outra. A.pr6xima agio :d poder6o.orr., q.ra.rdo a anteiior tiveriido concluida. Se a anilise de um hist6rico levar meia hora e o usu6rio silecionat a e*ecugio d^o download seguido da pesquisa, o aviso de, digamos, compra ou venda de ag6es como resultado,
podevirtarde demais.
Acabamos de imaginar o tipo de aplicativo que precisa de virios threads. O ideal seria que o download ocorresse em segundo plano (isto 6, em outro thread). Delsa forma, outros processos poderiam ocorrer ao mesmo temPo para que' por e*implo,.rm arriso pudesse ser comunicado instantaneamente. Todo o tempo, o usuirio estaria interagindo com.outras panei do aplicativo. A an6lise tamb6m poderia ocorrer em um thread separado, para que o usu6rio pudesse trabalhar em outros lociis do aplicativo enquanto os resultados estivessem sendo calculados' Mas, o que exatamente i um thread? EmJava, "thread" significa duas coisas diferentes:
I I
Uma instAncia de Thread 6 apenas... IJm objeto. Como qualquer outro objeto emJava, ele tem vari6veis e m6todos, reside e 6 eliminado no heap. Mas um thread de exuapdo6 um processo individual (um processo "simples") que possui sua pr6pria pilha de chamadas. EmJava, hi an tbrcadporpilba de cbamadas - ou, considerando inversamente, anapilha de chanadaspor tbrcad.Mesmo se voc6 nio criar nenhum thread novo em seu programa, os threads estario li sendo executados em segundo plano.
O m6todo main ) , que di inicio a todo o processarnento, 6 um thread chamado (surpreendentemente) de thread principal. Se voc6 examinasse a pilha de chamadas principal (e 6 possivel, sempre que capturar um rastreamento de pilha de
algo que ocor ra dEois do m6todo principal ser iniciado, mas nlo dentro de outro thread), veria que main ) 6 o primeiro nouothread, uma nova pilha se m6todo da pilha - o m6todo na parte inferior dela. Por6m, logo que voc6 criar materializar|eos m6todos chamados a partir duythreadserio executados em uma pilha de chamadas separada da pilha de main ) . A execugio dessa segunda pilha de chamadas 6 considerada simultAnea a do thread principal, mas aperfeigoaremos essa noglo ao percorrermos este capitulo.
VocA pode achar confuso estarmos falando de c6digos sendo executados simultaneamenle
-, jh que voc6 sabe que hi somente uma CPU na maioria das miquinas que processam Java. Do que se trata entio? A JVM, que obt6m sua parcela da CPU independente do mecanismo de agendamento que o sistema operacional
usar, funciona como um mini-sistema operacional e agenda seus pr6prios threads, nlo imponando o sistema operacional subjacente. Em alguns JVMs, os threads java sio convertidos em threads nativos do sistema operacional, mas nio discutiremos isso arqui; os threads nativos nio estario no exame. Tamb6m nlo ser6 avaliada a compreensio de como os threads se comportam em ambientes de JVMs diferentes. Na verdade, o conceito mais importante a entender em todo este capirulo 6: Quando se trata de threads, h6 poucas garantias.
seja muito cuidadoso com a interpretagdo de algum comportamento com o qual voc6 se deparar em m6quina, como "a maneira do thread funcionar". Seri esperado no exame que voc6 saiba o que 6 ou nio um comporramento garantido, para que seja possivel projetar um programa de maneira que funcione independentemente da JVM subjacente. Issofaqpafte do conceito pincipal da linguagem Jaua.
Poftanto,
/./ma
AO TRABALHO
Nio
comela o erro
de
da
JL/M.
Camo
uocd aprenderd
posteionnente,
JW|IS
poden execatar tbreads de naneiras profundamente distintas. Por exempl0, um JIlM pade attryrar que todot as threads tenbam ttltt ue<caxl uma durapio ben distibuida, alocada para cada axt, nllm radi{o pefeito. Mas em outros JL/Ms, um tbread pode coille{ar a ser executada e, em seguida, sitzp/esrnente raubar a ftna, nunca dando ueTpara que os outros possam ter taa thance. Se uoc6 teslar sea aplicatiuo na JVM de "alocagdo adeqaada de tempo", e ndo soaber o que d ou ndo garantido em Jaua, entdo, poderdfcar assustado qaando executd-/o em an JWII com um mecanismo diferenle de agendamento de threads.
diferentes
As perguntas do exame sobre threads estio entre as mais dificeis. Na verdade, para a maioria das pessoas elas sla
JAVA
385
mais dificeis, e com qrxttro objaivos sobre threads voc6 terd que responder udriarpergontassobre eles. Se ainda os threa&, provavelmente ter6 que passar algum tempo fazendoieGs. Al6m disso, ai vai um aviso final de isen$o: Este t@ituk ndt i ama lentatiua fu lhe mstnmcomoprEehruru Elicatun con uirios tbrcatls fuJonna atleqaatla e segara bemos
realmente
tamb6m o que precisa para acertar as perguntas do exame sobre threads. Antes de conseguir escrever um c6digo adequado com v6rios tlrreads, no entanto, tera realmente que estudar mais sobre as complexidadesi sutilezas desse tipo de c6dilo.
(Observagio: O.t6pico de threads daemon nio cai no exame. Todos os threads discutidos neste capitulo sio threads "do usu6rio". Voc0 e o sistema operacional podem criar um segundo tipo de thread, chamado de thread daemon. A diferenga entre esses dois tipos (do usuiiio e daemon) 6 que a JVM16 finaliza um aplicativo quando todos os threads do usuirio tiverem finalizado - a JVM nio se importa em deixar os threads daemon fi.nalizarem, de forma que, uma vezfrnalizados todos os threads do usu6rio, aJVtrrt ir|fechar, independentemente do estado de quaisquer threads daemon. Mais uma vez, esse t6pico ndo cai no exame.)
Criando um thread
Um tlrread emJava comega como uma insAncia
os threads, o que de java-lang.Thread
e pausa-
No
exame,
vod
Vod encontra.ri m6todos na classe Thread para gerenciar ter6 que conhecer, pelo menos, os m6todos a sryin
) )
Toda a aglo comega no m6todo run ( ) . Considere o c6digo que voce quer executar em um thread diferente, como "o trabalho a ser feito". Melhor dizendo, vocA tem alguma tarefa que precisa ser executada, digamos, o download dos pregos de ag6es, em segundo plano, enquanto outras coisas estiverem acontecendo noprograma; portanto o que pretende realmente 6 que o trabalho seja executado em seu pr6prio thread. Entio, quando a tarefu executada for o trabolho citado, o executor (quem execut ari realmente o c6digo) ser6, o thread. E o trabalbo sempre comepa em um mdtodo run ( ) . como esti descrito abaixo:
acrui
Escrevasempre o c6digo queprecisaserexecutado nothreadseparadodeumm6todo ). O m6todorun ) chamar6 outros m6todos,6 claro, mas othreaddeexecu$o - anovapilhade chamadas - sempre comegarlchamando run ). Entlo, onde entrari o m6todo run ) ? Em uma das duas classes que vod pode usar para definir o trabalho de seu thread.
nn(
I I
VocA ter6 que conhecer as duas no exame, embora no mundo real seja muito mais provivel que implemente Runnable emvez de estender Thread. Estender a classe Thread 6 mais f6cil, mas, geralmente, nio 6 uma boa prhrica no modelo OO. Por qu6? Porque a criagio de subclasses deve ser reservada para classes que estendam uma classe j6 existente, por elas serem uma versio mais especializadada superclasse mais gen6rica. Portanto, a rinica situaglo em que realmente faz sentido (da perspectiva do modelo OO) estender Thread 6 quando temos uma verslo mais especializada de uma classe Thread. Em outras palavras, por que rucd tem um czntportamento de Thread mais espunliqado. No entanto, h6 chances de que o trabalho necessirio, na verdade, s6 possa ser executado por:ul;;' thread. Nesse caso, voc6 deve projetar uma classe que implemente a interface Runnable, o que deixar6 sua classe livre para estender alguma aatra classe.
Definindo um thread
Para definir um thread, voc6 precisa de um local para inserir seu m6todo run ( ) e, como acabamos de discutir, possivel fazer isso estendendo a classe Thread ou implementando a interface Runnable. Examinaremos as duas situag6es nesta segXo.
6
Estendendo java.lang.Thread
A maneira mais simples
de definir que um c6digo deve ser executado em um thread separado 6:
I I
run
O formato
386
Copftulo 9: Threods
dessa abordagem (al6m de ser uma opgio fraca para o projeto na maioria dos casos) 6 que se voc6 estender Thread, nio poderd utender nada mais. E nlo se trata de esse comportamento herdado da classe Thread ser exclusivamente necess6rio, porque para usar um thread voc6 teri que instanci6-lo de uma maneira ou de outra.
A limitagio
rurr
{
ir"n i. " + S);
].
]
Masesteja
classe Tbread espera um
a)ertaparaisso:omitodarun(String s) MbrecarregadoserdignoradopelaclasseTbreadamenosqueuoc6ochane.A milodo run ( ) um argumentos, e executari esse mdtodo para uoci ert una pi/lta de chamadas sQarada dEois que
a
otbreadtiuerseiniciad.o.Comumm6todorun(string s),aclasseThreadniochamar6om6todoparavocA,e,mesmo que voc6 chame o m6todo diretamente, a execugao nio ocorrer6 em um novo thread com uma pilha de chamadas s eparada.
Acontecer6 na mesma pilha que do c6digo de onde voc6 fez a chamada, como acontece com qualquer outra chamada a
m6todo normal.
I
mplementando java.lang.Runnable
de estender a classe que quiser, al6m de
6 esse:
A implement aElo dalntertace Runnable lhe proporcionari uma maneira comportamento que serA executado por um thread separado. O formato
definir o
-inh rrrrlnlpg
in
MyRUnnabfe,,);
]
)
Portanto, examinaremo
fancionarrealmente.
ser processado por um thread de execugio. habilitada para threads e, em seguida, veremos como fazer a coisa
Instanciando um thread
Nio run
Se
se esquega de que
) estar em uma subclasse de Thread ou em uma classe de objeto Thread parafazer t:udo funcionar.
voc6 estendesse a classe Thread,
a
&
classe de
implementagio
daquiapouco):
instanciagio serl um pouco menos simples. Para ter um c6digo executado por um thread,
uocdaindaprecinrideanainttdnciade-I'hread.Contudo,emvezdeinserirothreadeatarefu(oc6digodom6todorun( uma classe, voc6 teri que dividi-los em duas classes: a classe Thread para o aldigc espedfn do thread, e sua classe de
implementagio de Runnable para o c6digo da tarefa que seri executada pelo thread. (Uma outra forma comum de se
))em
considerarisso6pensandoqueThread6o"trabalhador",eRunnable6o"trabalho"aserfeito.)
de java.lang.Thread (algo tem que executar sua tarefa...) e passe para ela a tarefa!
JAVA
387
VocA s6 pode passar uma instAncia de Runnable para os virios objetos Thread, de modo que a mesma instAncia torne o destino de miltiplos threads, como vemos a seguir:
se
public cl-ass TestThreads { public static void main (String [] args) MyRunnable r = new MyRunnableO; Thread foo = new Thread(r); Thread bar = new Thread(r); Thread bat = new Thread(r);
l
Fornecer o mesmo destino para vlrios threads significa que mriltiplos threads de execugio estario executando mesma tarefa (e que a mesma tarefa seri feita diversas veies).
OBSERVAQ6TS
pene O EXAME
run
A pnipria classe Tbread inplementa Rtnnable (afna/, ela tern am adtodo poderia passar am Thread a 0ulr0 clnstrutzr de Tbread:
uocd
Thread
t = new Thread(new
MyThread(
) );
uocd sd
executado),
uma instAncia de Runnable (o destino, a instAncia que cont6m o trabalho na classe Thread. Os construtores relevantes para n6s seo:
I I I I
Thread(
Thread(String
name)
VocA ter6 que conhecer todos eles no exame! Posteriormente, discutiremos alguns dos outros construtores da lista anterior.
j6 criou uma instAncia de Thread e sabe qual m6todo run ( ) chamar. Mas ainda ndo hti nada anntecendo.I\esse momento, tudo o que temos 6 um objetoJava simples do tipo Thread. Ainda nio d un tbread de exuupio.Para obter um thread real - uma nova pilha de chamadas - ainda teremos qre iniciaro thread.
Entio, voc6
Quando um thread tiver sido instanciado, por6m, nio iniciado (em outras palavras, o m6todo ) nio foi chamado na instAncia de Thread), diz-se que ele est6 no estado novo. Nesse est6gio, o thread ainda nio 6 conside rado atiuo.
start (
Depoisqueom6todo start ( )6chamado,othread6considerado comoatiuo(emboraom6todorun( )possaainda nio ter comegado a rodar). Um thread 6 considerado como desativado (nio mais ativo) depois que o m6todo run ( ) finaLzaO m6todo i sAl ive ( ) 6 a melhor maneira de determinar se um thread foi iniciado, mas nio concluiu seu m6todo mn ( ) . (Observagio: o m6todo getstate ( ) 6 bastante ritil para a depuragio, mas voc6 nio precisar6 conhec6Jo para
oexame.l
Iniciando um thread
Voc6 criou um objeto Thread e ele sabe seu destino (a instAncia de Runnable que foi passada ou ele pr6prio se voc6 estendeu a classe Thread). Agora 6 hora de fazer toda essa est6ria de thread funcionar - iniciar uma nova pilha de chamadas. E tio simples que quase nao merece um subtitulo pr6prio:
t. start
Antes de start ( ) ser chamado em uma instAncia de Thread, diz-se que o thread (quando usarmos o t minrisculo, estaremos nos referindo ao tbread de exuacio, e nio a classe Thread) este no estado novo. como foi mencionado. O estado novo significa que voc6 tem um objeto Thread, mas ainda nio tem um thread rea/.Portanto, o que aconteceri depois que chamar start ( )? O que interessa:
388
Copitulo 9: Threoos
I r
O thread
run
) de seu
Certifique-se de memorizar o seguinte: a classe iniciada 6 Thread e nio Runnable. Chame instAncia de Thread ( ) e nXo de Runnable.
start ( ) em uma
OBSERVAQ6ES
aidigo que cbame o mdtodo rwn ) em uma c/asse Rannable (oa mesmo em ama ) serd executado em uru thread sQarado! Chamar instincia tle Thread), isso i pefeitanente udlida. Mas ndo stgntfca que o m,itodo run um milatlo ) drx)ninn tignfrco aPendr qile uoci estd cbamando am mitodo independente do thread qae estti sendo execatado, e ele entrard na pi/ha de chamadas ataal, em ueqde no inicio de ma noua pilba. O cddtgo a seguir ndo inicia um nouo thread de exuupdo:
nouo thread chamard. Portanto, se uoft se deparar com
pene EXAME Nno h,i natla especial na mitodo run ( ) da lingaagen laua. Cono main (
un
sinrylesmente
run (
Runnable
um
thread separado
definigio, instanciagXo
e
at6 agora:
inicializaEio de um thread:
class FooRunnable implements Runnable { public void runO { for(int x =1; x < 6; x++) t System. out . print.ln ( "Runnable running"
)
] ]
public class TestThreads { public static void main (String [] args) FooRunnable r = new FooRunnableO; Thread t = new Thread(r) ; t. start O ;
)
]
A execugio do c6digo anterior exibiri exatamente o esperado:
Entlo, o que aconteceri se iniciarmos v6rios threads? Veremos um exemplo simples em breve, mas primeiro, precisamos saber como exibir o thread que esti sendo executado. Podemos usar o m6todo getName ) da classe Thread e fazer com . O exemplo a seguir instancia um que cada objeto Runnable exiba o nome do thread que executar seu m6todo run ) thread, d6 a ele um nome e, em seguida, esse nome 6 exibido a partir do m6todo run ) :
n / \\\T:m6prrnn:l'r'l
(
o rrrrni
nn" I
System. out.
println
"Run
by
"
()
+ Thread.currentThread( ) .qetName ]
)
JAVA
nrthl ic ql-^l- id \z^id main (strind \ruLfrrv Il arfta\ LJ q!vr/
;
389
Ir
NameRunnable
) )
A execugio
desse c6digo
seguir:
? java
Run
NameThread
NameRunnable runninq
by Fred
Para obter o nome de um thread chame - quem adivinharia - getName ( ) na instAncia do thread. Mas, a instAncia Runnable de destino nem mesmo tem uma referAncia ) instAncia de Thread, de modo que primeiro chamamos o m6todo stat ic Thread. currentThread ( ) , que retorna uma referencia ao thread que estiver sendo executado e, em seguida, chamamos getName ( ) na refer6ncii retornada.
Mesmo
se
voc6 nio nomear explicitamente um thread, ele ter6 um nome. Examinemos o c6digo anterior, comentando a
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
java
NameThread
NameRunnable runninq
Run
by Thread-O
Ej6queestamosobtendoonomedothreadatualusandoom6todostatic
podemos at6 obter o nome do thread que est6 executando nosso c6digo principal,
Thread.currentThread( ),
nrinfln("thro^d
iS "
(
))
seri
%
java NameThreadTwo
thread is main
Certo, othreadprincipal j6temum nome inicializaeio de um thread.
-main
()
brincamos o bastante; passemos para a execugio real de aiiosthreads (mais de dois, na verdade). J6 temos dois threads, ( ) comega no seu pi6prio thread, e depois't. start ( ) iniciou um seganlo thread. O i6digo a seguir cria somente uma instAncia de Runnable e tr6s de Thread. Todas as tr6s instAncias de Thread t6m mesma instlncia de Runnable, e cad^ thread recebeu um nome exclusivo. Para concluir, todos os tres threads foram iniciados com uma chamada a start ( ) nas instAncias de Thread.
390
Coo(tulo 9: Threoqs
class NameRunnable implements Runnable public void runO t for (int x = 1; x < 3; x++) {
rJruvaLt.vuL.v!
q\rct-am
nrrj.
nrinl.
lnl"Rrrn r\urr \
krv
vJ
\'
public class
nrrlrl in
ManyNames {
rrnirl m:in /j- rino
\ v e! r44Y
c|.at'ir
Il
aros)
();
Thread one = new Thread(nr); one . setName ( "Fred" ) ; Thread two = new thread(nr);
two. setName ( "Lucy" ) ;
l-r^rn cf :rl|,hr^a
ar^r|.l\.
void main{SL:ing
I args)
r1
/ execuca
attm aAAl.d--"
*_ryI_-i
Pilha
/ / al
f--* *-.*--*
//em maino
methodl(r;
,r
I executa
ii
/ mais c6digro
i-..-'.."'-*J j
j
i
rtain
A
Pilha
i-----l
I-a{: Il;r B
pilha
(thread 3)
r**h"Ji I -l
t)
lniciolizoEdo de um threod
produzid
o seguinte:
Z java
ManyNames
Y r_S 1
JAVA
39I
by Fred, x is 2 Run by Fred, x is 3 Run by Lucy, x is 1 Run by Lucy, x i_s 2 Run by Lucy, x is 3 Run by Ricky, x is 1 Run by Ricky, x is 2
Run Run
by Ricky, x is
Bem, pelo menos 6 isso o que foi exibido quando executamos o c6digo - desta vez, na nossa miquina. Mas o comportamento que voc6 viu acima nio 6 garantido. Isso 6 tio crucial que voc teri que fazer uma pausa agora, respirar firndo e repetir comigo: "O comportamento nio 6 garantido". Vocd prlcisa saber, para usar fufliramente como programadorJava assim como no exame, que nio h6 nada na especi{icagloJava que informe que os threads comegario a ser executados na ordem em que foram iniciados (em outras palavras, a ordem na qual start ( ) foi chamado em cada thread). E nlohA garantias de que uma vez que um thread comece a ser executado, continue at6 sua conclusio. Ou que um loop ser6 concluido antes que outro thread comece. Nio, meu caro. Nada 6 garantido no c6digo anterior, exceto isro:
Cada tbread seni iniciado
e
exuutado ati a
eonclusdo.
as coisas acontecem em uma ordem previsivel. Mas as ag5es de diferentes threads podem se misnrar formas imprevisiveis. Se vocA executar o programa diversas vezes, ou em diversas miquinas, poderi ver saidas diferentes. Mesmo se nlo vir, voc6 precisa entender que o comportamento que est6 vendo nio 6 garantido-As vezes, uma pequena modificagio na maneira como o programa 6 executado fari uma diferenga emergir. Apenas por diversio, aumentamos a quantidade de iterag6es no c6digo do loop para que cada m6todo run ( ) o execute 400 vezes em vez de 3, e
eventualmente comegamos
public void runo { for (int x = L; x <= 400; x++) System.out .println ( "Run by " * ", X is " + x);
J
t
(
A execuglo do c6digo anterior, com cadathreadprocessando o m6todo run de szuloop 400 vezes, comegou bem, mas depois se tornou nio linear. Aqui esd apenas um trecho da saida de linha de comando da execuEio desse c6digo. Paratornar maisfacildistinguircadathread coloquei emit6lico asaidaqueincluiFred, eemnegrito adeLucy, deixando adeRicky
inakerada:
RunbyLucy,xis33T RunbyRicky,xis3l0
RunbyLury,xis338
RunbyRicky,xis3ll
RunbyLury,xis339
RunbyRidry,xis312
RunbyLuqy,xis340
RunbyRicky,xis313
RunbyLucy,xis34l
RunbyRidry,xis314
Runbylucy, xis342
RunbyRidry,xis3l5 Run by Fred, x is 346
Run by Lucy, x is 343
392
continua...
Repare que
h6 um padrio claro aqui. Se observarmos apenas a saida paraFred, vemos os nfmeros aumentando um de cada vez, como esperado:
nio
x is 345
is
347
E o mesmo acontece se observarmos apenas a saida de Lucy ou Ricky. Cada um deles est6 se compoffando, individualmente, de uma forma bem ordenada. Mas juntos - caos! No fragmento acima, vemos Fred, depois Lucy e depois Ricky (na mesma ordem em que originalmente iniciamos os threads), mas depois Lucy toma a vez de_Fred. Que falta de educagiol E depois Ricky e Lucy se alternam por alguns irutantes, at6 que Fred tenha outra opornrnidade. Eles se revezam dessa forma por t.mpo, depois disso. Finalmente (depois da parte mostrada acima) Fred finaliza, e depois Ricky, e "lgom entio Luryfinalizacomrlmalongaseqiidnciade saida. Assim, mesmo queRickytenhacomegado em terceiro, eleterminaem segundo. E, se executarmos novamente, obteremos um resultado diferente. Por qu6? Porque isso i decisdo do agendador, e nds ndo o contmlamorlO que faz surgir outro ponto principal que deve ser lembrado; stlporqae udrios tbreads sdo iniciador em uma ordem esperifca ndo ignfica qae wio executadot netsa ordem. Aordem nXo 6 garantida pelo agendador para nenhum grupo de threads iniciados. E a duragio tamb6m nlo. Nio sabemos, por exemplo, se um thread ser6 executado at6 a conclusio, antes que outros tenham uma chance de serem iniciados; se todos terio sua chance de serem processados ou se as duas coisas icontecerlo. H6 uma maneira, no entanto, de iniciar um thread sem que seja executado at6 que algum outro tenha sido concluido. VocA pode fazer isso com o m6todo j oin ) , o qual examinaremos posteriormente.
Um thread deixa
m6todo run
)6
concluido.
Quando um thread conclui seu m6todo run ( ) , deixa de ser um tread de execugio. A pilha desse tread se dissolve e ele 6 considerado inatiuo.floentanto,nlo6inativoeeliminado,apenasinatiuo..Pinda|urr'objetoThread,s6nio6.um/readde exuapdo.Ponarfio, se houver uma referOncia i instAncia de Thread, entio, mesmo quando essa instAncia nio for mais um tread de execugio, voc6 ainda poderi chamar m6todos nela, como em qualquer outro objeto Java. O que nio po derifazer, entretanto,6 chamar start ( ) novamente. Una ueqqae
Se o tread se tomar inatiuo, jamais podenl ser reiniciado!
voc6 tiver uma referAncia a um Thread, e chamar ) mais uma vez, isso ) , ele 6 iniciado. Se chamar causari uma excegio (uma IllegalThreadStateException, que 6 um tipo de RuntimeException, mas voc6 nio precisa se preocupar com o tipo exato). Isso ocorre independentemente de o m6todo run ) ter ou nXo finalizado em relagio ) primeira chamada a s ) . Apenas um novo thread pode ser iniciado, e apenas u mavez. Um thread que estiver rodando ou inativo nlo pode ser reinicializado.
start (
start (
tart (
capitulo.
O agendador de threads
O agendador de treads 4. a pane da JVM (embora a maioria das JVMs converca os treads Java diretamente em treads do sistema operacional subjacente) que decide qual tread deve ser executado em algum momento especifico, al6m de tirarteads do estado execut6vel. Presumindo a existAncia de somente uma m6quina processadora, apenas um tread pode ser executado por yez. Somente uma pilha pode ser processada de cada vez. E 6. o agendador de treads que decide qaaltread - de todos os qualificados - ser6 realmente processado. Qvando dizemos qaalifcado, na verdade, queremos dizer no e$ado exautiael.
Qualquer tread no estado execut'iuel pode ser selecionado pelo agendador como o rinico a ser ?rlcesradz. Se um tread nio estiver no estado executAvel, enteo, neo poderi ser selecionado como o que ser6 imediatamente executado. E, portanto, fica evidente aprecariedade de garantias aqui:
nio i garantida.
Embora o comportamento deflksela comum, ele nio 6 garantido. Comportamento de fila significa que quando um tread tiver concluido sua execugio, passari para o fim da fila do pool executlvel e aguardar6 at6 que finalmente chegue a ser o primeiro, quando poderA ser selecionado novamente. Na verdade, chamamos isso de pool executavel, em vez de fk executivel, para ajudar a reforgar o fato de que os trea& nio ficam todos alinhados numa ordem cena.
Apesar de
inflaenciar
nio
controlarrnot
o agendador de treads (nXo podemos, por exemplo, informar que um tread especifico
a seguir nos
oBSERVAQAO
tread
e
pene EXAME
exa
e
Espere porpergunlas n0
determinar
se
indeterrnin,l:uel.
JAVA5 393
Mdtodos da classe iava.lang.Thread Alguns dos m6todos que podem nos ajudar a influenciar o agendamento
de threads
sio
os seguintes:
public static void sleep(long millis) throws rnterruptedException public static void yieldo public final void joinO throws InterruptedException
nrrhrl ic final rrnid qe|-Priori 1-rr(int. uJ \ f rlL naurPrinri rlevv! r tv!
f
trr\ uf
public final void wait ( ) throws InterruptedException public final void notifyo public final void notifyAll ( ) O m6todo wait ( ) tem trAs vers6es sobrecarregadas (incluindo a listada
aqui).
Examinaremos o comportamento de cada um desses m6todos neste capitulo. Primeiro, no entanto, discutiremos os diferentes estados nos quais os treads podem se encontrar.
an
para 0utr0.
J6 vimos tr6s estados - nouo, executduele atiuo -, mas espere! Ainda h6 mais! A tarefado agendador 6 colocar e tirar os treads do esrado de execagdo. Embora ele possa passar um tread do estado de execugio novamente para o executAvel,
outros fatores podem fazer com que um tread saia do estado de execugio, por6m, tem vo\tar para o estado executavel. Um deles 6 quando seu m6todo run ( ) 6 concluido, situagio em que o tread passa do estado de execugio diretamente para o inativo. A seguir, examinaremos algumas das outras maneiras pelas quais um tread pode sair do estado de execugio e para onde ele ir6.
I Novo Esse 6 o estado em que o tread se enconrra depois que a instAncia de Thread foi criad4 mas o metodo start ( ) nlo foi chamado. Ele se torna um obieto Thread ativo, mas ainda nio 6 um tread de execucio. Nesse
momento. o tread 6 considerado
inatiuo.
Execut6vel Esse 6 o estado em que um tread se encontra quando est6 qualificado para ser executado, mas o agendador nlo o selecionou como o tread a ser processado. O tread entra pela primeira vez no e$ado executivel quando o m6todo ) 6 chamado, mas tamb6mpode retornar ao estado executivel depois de serprocessado ou ao retornar de um estado bloqueado, de espera ou de suspensio. Quando o tread est6 no estado execut6vel, 6 considerado
start (
atiut
ExecuFo
E o que interessa. O "grande momento". Onde acontece a aglo. Esse 6 o estado em que o tread se encontra quando o agendador o seleciona (no pool executivel) como o processo a ser executado imediatamente. IJm tread pode sair de um estado de execugio por v6rios motivos, inclusive pelo "agendador ter decidido assim". Examinaremos as outras raz6es em breve. Observe que n aFigtrag-2,h6 virias maneiras de se chegar ao estado executivel, mas s6 umo de entrar no estado de execugio: o agendador selecionar um tread no pool executivel.
Espera/bloqueio,/suspensio Este 6 o estado de um thread quando est6 qualificado para executar. Ceno, entio temos tr6s estados em um; mas todos possuem algo em comum: o tread ainda es6 ativo, por6m, nio esti qualificado para execngio. Em outras palavras, nio 6. exeuniwfmas pode rctomaraum estado execut6vel posteriormente, se um evento especifico ocorrer. Um tread pode ficar bkquead,t esperando por um recurso (como a E/S, ou o bloqueio de um objeto),
caso em que o evento que o retornar6 ao esado
executivel ser6
disponibilidarle do recuno
- por
recebidos dados atrav6s do fluxo de entrada que o c6digo do tread estiver lendo, ou se o bloqueio do objeto ficar disponivel. Um tread pode lrcar itlsPewr porque seu c6digo de execu$o o infomou paraficar inativo por algum tempo,
sinra$o em que ocorreri o retomo ao estado execut6vel devido ao periodo de suspensXo ter expirado. Ou o tread pode estar na erpcr4por W src6digo de exe cuglo a prouocou, caso em que o evento que o retorna rL para o estado
394
Copitulo 9: Threods
execut6vel ser6 outro tread enviando uma notificagio de que nio 6 mais preciso aguardar. O ponto imponante 6 que um tread nio inforrua ao outro que deve ficar bloqueado. Com alguns m6todos, pode pdrece,'que estea dizendo a outro threid para bloqueai, mas nlo estio. Se voc6 tiver uma referncia t a outro thread, pode escrever algo como:
t.sleep( );
ou
t.yield(
umavari6veldeinstAnciaparaacessarumm6todostatic
na classe Thread, que perrnite
a
-podecausarconfusio.H6umm6todo,suspend( ),
outro sualuspenslo; mas esse m6todo {oi reprovado e nio estari no exame (nem sua contrapartida, resume ( ) ). Hi ainda o m6todo stop ( ) , que tamb6m foi reprovado e nio ser6 avaliado. Tanto susp-end ( ) quanto stop ( ) se mostraram muito perigosos, ponanto, voc nlo deve us6-los e, nio esquega, porque foram reprovidos, nio aparecerio no exame. Nlo estude nada sobre eles, nio os use. Lembre-se
um tread informar
a
I Inativo
poderi ser ativado novamente (tipo aquela coisa: "eu vejo treads mortos"). Se voc chamar start ( ) em uma irstAncia inativa de Thread receber6 uma excegio de tempo de execuglo (e nio do compilador). E, provavelmente, nio
ser6
Um tread 6 considerado inativo quando seu m6todo run ( ) 6 concluido. Ele po& continuar sendo um objeto Thread utiliz6vel, mas nio seri mais um tread separado de execugXo. lJma vez que um tread estiver inativo, nunca
se
No que dizrespeito
ao exame, nXo estamospreocupados com o bloqueio de umtreadcausadoporE/a (digamos, aguardando algo chegar de um fluxo de entrada do servidor). Estamos falando do seguinte:
I I I
Suspensio
Suspensio
Espera
( ) 6 um mdtodo static da classe Thread. use-o em seu c6drgo para "desacelerar umtread entrar no modo de suspensio antes de retornar ao e$ado executivel (no qual ainda ter6 que aguardar para ser o ffead executado). Quando um tread 6 suspenso, vai para algum local e nio retornaao estado execut6vel at6 que seja
O m6todo sleep
forgandoo
a
despenado.
por achar que o treadex|percorrendo seu c6digo muito dar opomrnidades a outros, j6 que uma execuglo adequadamente agendada nilo 6 garantidanas especificag6esJava. Ou suponhamos um read executado em um loop, fazendo o download dos pregos mais recentes das ag6es e analisando-os. O download dos pregos um ap6s o outro se mostraria uma perda de tempo, j6 que a maioria seria semelhante, e o que 6 mais imponante - seria um consumo precioso de largura de banda. A maneira mais simples de resolver isso 6 fazer com que um tread entre em pausa (suspensio) por cinco minutos depois de cada download.
suspenso? Bem,
a
),
abaixo:
try
Thread.sleep(5*60*1000);
//
Suspenso
}
por 5 minutos
JAVA
395
de ocorrer n6s geralmente temos conhecimento, j6 que outro tread tem que faier ainterrupgio explicit"mente), Portanto' voc6 ser6 forgado a reconhecdJa manipulando ou declarando-a. Normalmente, ipln"r &."ps.tlamoi cada chamada de suspenslo em um bloco como no c6digo anterior.
tryliatch,
Vamos alterar o c6digo de Fred, Lucy e Ricky usando a suspenslo para tentdrforgar os treads a se alternarem, em vez de.permitir que um deles seja o dominante durante um periodo de timpo. Onde vocA acha que o m6todo sreep (
)
deveria entrar?
class NameRunnable implements Runnable public void run0 { for (int x = 1; x < 4i x++) { System.out.println ( "Run by "
+ Thread.currentThread( ) . getName
));
trv
/ Cria
um Runnable
NameRunnable
nr = new NameRunnableO;
Thread one = new Thread(nr); one. setName ( "Fred" ) ; Thread two = new Thread(nr);
two . setName ( "Lucy" ) ;
qi-arl-/\.
A execu$o
desse
by Lucy
P
rn h\/
^L\/
395
Copitulo 9: Threods
Apenas lembre-se de que o componamento da saida anterior tamb6m nlo 6 garantido. VocA nio teri como se ..rtifi."r de quanto tempo um tread serl executado antes de entrar em suspensio, portanto, nlo poder6 saber com certezase s6 um dos tr6i treads estari no estado executAvel quando o tread em execugeo entrar em suspensio. Em outras palavras, se houver dois treads ativos no pool execut6vel, voc6 nio ter6 como saber com certeza se o que nXo foi usado por riltimo ser6 o selecionado para execugio. Ainda asim, usar sLeep ( ) i a melhor maneira de tentarfaryr clm que todos osireads tenbam a chance de serent executados!Ou, pelo menos, de garantir que um tread nlo entre em execugio, e assim permanega atd sua conclusio. Quando vm tre^d encontrar uma chamada de suspensio, teri que ficar suspenso pelo menos durante o periodo especificado em milissegundos (a menos que seja interrompido antes de sua hora de deipertar, caso em que langari imediatamente a exceElo InterruptedException).
) ser,l o periodo quando um thread d despertado simplesmente retorna a0 estado executduel. Portanto, o tempo especifcado em sl-eep nfuimo durante o qua/ o lhread nio rcrd exuutado, mas nio seni operiodo tota/ durante o qua/ o thread ndo executari. De modo que uoc6
) sl-eep ) nno un tinerpfeitanma prcciso. Embom em naias @litatiws usm sl-eep ndo d amagarantia de que o thread comeganl a ser nmotimerselasr.{uimtenmteadequada,mdprvcisasaberqaeotenpoespafuadanestemdtodo
q*i
ptriodo ixpirar
eo
tiread dupertar.
se engane
NXo
se esquega de
que s l eep
)6
outronoeltadodeiuspensio.Vocpodeinseriroc6drgodesleep( )emqualquerlocal,j|quet0d0oc6digoser6
executado po r alguntread. Quando o c6digo que estiver sendo executado (o que significa o c6digo do tread que estiver sendo executado atualmente) chegar a uma chamada de s l eep ) , colocar6 o tread atual em suspensio.
Exercfcio 9-1
Criando um thread e colocando-o em suspenseo
Neste exercicio criaremos um tread de contagem simples. Ele contar6 at6I}},fazendo uma pausa de um segundo antes de cada nrimero. Al6m disso, continuando com o tema da contagem, ele exibir6uma st ingacadadeznimeros.
1. Crie uma classe e estenda Thread.
interface Runnable.
2. Sobrescreva o m6todo
run
3. Crie um loop for que seja executado 100 vezes. IJse a operagio de resto para verificar a exist6ncia de algum nrimero que seja o resto da divisio por 10. 4. Use o m6todo static os milissegundos.
Thread. sleep
AO TRABALHO
Nio tonfe en pioidadu quando projetar reu @licatiuo com u,irios tltreads. Jd qae o conrPortamentl das pioridadu para udrios tbreads nio garantido, ase-ar coml ama maneira de me/horara efcidncia de seuprograma, mas certfique-se de qae ele ndo dQenda desse comportamento
para
qae
/anrion( nrftlameflle.
O que tamb6m ndo 6. garantido 6 o comportamento quando os treads do pool t6m prioridade igual, ou o tread sendo executado tem a mesma prioridade dos treads do pool. Se todas as prioridades forem iguais, a implementagXo do agendador que a JVM usar poder6 fazer simplesmente o que quiser. Isso significa que um agendador pode executar uma das ag6es a seguir (entre outras coisas):
JAVA Selecionar a execugio de um tread mantendo-o assim at6 que seja bloqueado ou conclua seu m6todo o tempo dos treads do pool para dar a todos uma opoftunidade igual de execugio.
5
(
397
);
run
T dividir
public class TestThreads { pubfic static void main (String [] args) MyThread t = newMyThreado;
J
(),
ji
VocAtamb6mpodeconfiguraraprioridadedeumtreaddiretamentechamandoom6todosetpriority(
instAncia de Thread. como vemos abaixo:
)emuma
FooRunnable
r
'',;
= new FooRunnableO
ta
)
Thread
t
O
= new Thread(r);
rrr
t.start
As prioridades sio configuradas com o uso de um inteiro positivo, geralmente entre 1 e 10, e a JVM nunca alterar6 a prioridade de um tread. No entanto, valores de 1 a 10 nio sio garantidos. Alguns JVMs podem nio reconhecer dez valores distintos. Um JVM desses poderi a redtzir os valores de 1 a 10 para valores de I a 5, por exemplo; assim, se voc6 tiver, digamos, dez treads cada um com uma prioridade diferente e o aplicativo atual estiver sendo executado em um JVM que aloque um intervalo com somente cinco prioridades, entlo, dois ou mais treads podem ser mapeados para uma prioridade.
Embora apioridadepadrio t/a 5, a classe Thread possui trAs constantes (variiveis o intervalo das prioridades dos treads:
static
inal),
as quais
definem
Thread.MIN_PRIORITY (1)
Thread.NORM_PRIORITY
(
5)
)
O mdtodo yield(
pr6tica. O que
fim de permitir que outrostreadscomanermaprioridadetenhamsuaoportunidadedeserprocessados.Portanto,afinalidade6usaryield( parapromoverum agendamento sofisticado de opornrnidades entre treads de prioridades iguais. Na verdade, o m6todo
) fuuefazer
yield (
muito, na
)
|retornar
executivel,
yield (
) nlo garantefazer o que deveria, e mesmo se realmentefrzer com que um tread saia do estado de execugio retornando para o estado execut6vel, ndo hd gmantia deque o tread que ceder seu espago seja selecionado novamente entre todos os outros! De modo que, embora yieldQ possa - e geralmente o faz - fazer comque o tread sendo executado ceda seu espago para outro tread execut6vel com a mesma prioridade, nlo h6 garantias.
Um yield ( ) nunca faz um thread entrar no estado espera/bloqueio/suspensio. O miximo que pode acontecer 6 yield ( ) fazerumthread passar de executado para executivel, mas, novarnente, ele pode tamb6m nio ter efeito nenhum.
)daclasseThreadpermitequeumtread"sejaadicionadoaofinaldeoutrotread".Se
voc6 dver um tread B que nio puder executa r atarefa dele at6 que o tread A tenha conclui do a sua, entio, ser6 melhor "adicionar" o tread B ao A. Isso significa que o tread B nio se tornar6 execut6vel at6 que A tenha sido concluido (entrado no
inativo).
Threadt=newThread0;
t.start O ; t.joinO;
O c6digo anterior pega o tread que esti sendo executado (se ele estivesse no m6todo main ( ) , entio, seria o tread principal) e o adiciona ao final do tread referenciado por t. Isso impede que o thread atual se torne execut6vel antes que o threadreferenciado por t fique inativo. Emoutraspalavras, o c6digo t. join( )significa'me anexe (othreadatual) ao final de t, de forma que t precise finalizar antes que eu (o thread atual) possa executar novamente." Voc6 tamb6m pode chamar uma das vers6es sobrecarregadas do m6todo j oin ( ) que usa a duragio do tempo de espera, de modo que voc6 diga: "Espere at6 que o thread r seja concluido, mas se ele demorar mais de 5.000 milissegundos, interrompa a espera e se torne executivel assim mesmo". A Figura 9-3 mostra o efeito do m6todo j oin ( ) .
398
Copftulo 9: Threods
At6 agora, examinamos tr6s maneiras pelas quais um thread sendo executado pode sair do estado de execugio:
I
I
Garante f.azer comque o thread atual interrompa a execugio, ao menos durante o periodo especificado para a suspenslo (embora possa ser interompido antes do temPo especificado)'
Uma chamada
yield ( join(
Nio
garante muito, embora normalmente faga com que o thread sendo executado retorne ao estado executevel' a fim de que outro thread com a mesma prioridade possa ter uma chance.
Uma chamadaa
Garante f.azer com que o thread atual pare de ser executado at6 que o thread ao qual foi adicionado (em outras palavras, o thread no qual wait ( ) foi chamado) seja concluido. Se o thread no qual for adicionado estiver inativo, no entanto, o thread atual nio ter{ que retornar ao estado executevel.
Al6m
desses tr6s,
tamb6m temos os cen6rios a seguir, nos quais um thread pode sair do estado de execuglo:
I I I I
( ) do thread for concluido (6bvio). Com uma chamada a wait ( ) em um obieto (nio chamamos wait ( ) em um tbread, como veremos
Se
o m6todo
run
em
breve).
Quando um thread nio consegui r o bkq*eio do objeto cujo c6digo do m6todo estiver tentando executar.
passar
o thread
6
que outro thread tenha a chance de rodar. essas trocas da maneira que desejar. Saida
Nio
atual do estado executado paru execut|vel, para permitir preciso nenhum motivo - o agendador do thread pode fazer
A is running
n A ^ a a A A P R A R A A E ! R A n A R R R R R R R R A A A A I A l!r {D ic ic ic ic ic ic ic ic ie ic i+r ic ic i< ic ic ic ic ic ic ie ic ic ic ic ie ic ie ic ! urlrrlrv --.-'*i-rurllrug rrrnninn nrnnina rrrnnina rilnhihd rrrnrina nrnnind nrnninn vrrnninn rrrnninn rrrnhinn *,--i-r s4rf rrg rrlnhi-d rrrnrinn -,rrnina nrnhiaft nrnninc rirnnind rrrnninn firnhind rrrnnina rr:nnina rrrnninn rrrnni rrrnai n:nnina rrrnnira nrnninc rrrnnina .1,hnin^
start
Ot
Pilha
A esti
f-*--t r*-_:l t1 ti
;l
sendo executaca
I
//A-iilnfa-sc B //de ao finaf
il
aosturQ
i"l il
LI
a"ottero
Pilha
A estii
""';lo;u
Pilha B
rt
executaoa
ldood'e4l
i___,1
A
dostuf0
Pilha Aunida
'a ---,Ji
Pilha B
Figuro 9-3
O m6fodo join( )
utiticat
ou de instdncias de
JAVA
399
Voc consegue imaginar o problema que pode ocorrer quando dois threads diferentes com acesso ) mesma classe chamarem m6todos nesse objeto, e esses m6todos alterarem o estado do obieto? Em outras palavras, o que pode acontecer se doisthreads diferentes chamarem, digamos, um m6todo configurador no nermy objeto? Um cenirio como esse pode corromper o estado de um objeto (alterando os valores delua vari6vel de instAncia de maneira inconsistente) e se o seu estado compartilhar dados com outras parres do programa, bem, 6 horrivel demais at6 mesmo paravisualizar.
instincia de uma
Mas s6 porque gostamos de terror, examinaremos um exemplo do que pode acontecer. O c6digo a seguir demonstra o que aconteceria se dois threads diferentes estivessem acessando os mesmos dados de uma conta. Suponhamos que duas pessoas tenham um tallo de cheques cada uma, referente ) mesma conta (ou que duas pessoas tenham cart6es ATM, mas os dois cart6es estejam associados i mesma conta).
Nesse exemplo, temos uma classe chamada Account que representa uma conta de banco. Para que o c6digo nio fique extenso, essa conta comegari com um saldo igual a 50 e s6 poder6 ser usada para retiradas. A retirada ser6
aceita mesmo se nio houver bastante dinheiro na conta para cobri-la. da quantidade que voc6 quiser retirar:
^l ufa-D-^^ l^^^,,-! 6LLUUIrL r I
]
Agora 6 que vai ficar divenido. Imagine um casal, Fred e Lucy, os dois com acesso ) conta e querendo fazer retiradas. Mas eles nio querem exceder o saldo, portanto, antes de fazerem uma retirada, ele ou ela primeiro verifica o saldo, a fim de ter certeza de que hi o bastante como cobenura. Al6m disso, as retiradas slo sempre limitadas a uma quantia igual a 10, de modo que deve haver pelo menos esse valor no saldo da conta para que uma retirada seja feita. Parece simples. Mas 6 um processo de duas etapas: 1. Verificar o saldo:
2.
Se
houver o suficiente na conta (nesse exemplo, pelo menos um valor igual a L0),fazer a retirada.
se algo separar a etapa t da 2? Por exemplo, imagine o que aconteceria se Lucy verificasse o saldo e visse que h6 apenas o valor exato na conta, 10. Mas antes de elafaTer a retirada, Fred wifcasse o saldo e tambtim vire que h,l o bastante para a retirada. J6 que Lucy verificou o saldo, mas ainda nio f.ez sua retirada, Fred est6 vendo "dados inv6lidos". Ele est6 vendo o saldo da conta antes de Lucy debitar realmente a conta, mas a essa altura o d6bito 6 ceno de ocorrer. Agora, tanto Lucy quanto Fred acreditam que h6 o bastante paraf.azer suas retiradas. Poftanto, imagine agora que Lucy tenha {eito saa retirada e j5, nio tenha o bastante na conta para a retirada de Fred, mas ele acha que tem, )i que quando verificou, tinha! J6 veremos como o c6digo real da operagio no banco se pareceri, com Fred e Lucy representados por dois threads, cada um atuando no mesmo objeto Runnable e com esse objeto contendo uma refer6ncia a somente uma instincia da conta - poftanto, hi dois threads e uma conta.
O que aconteceri
A l6gica do c6digo
1.
uma conta.
2. Dois threads slo iniciados, representando Lucy e Fred, e cada um receber6 uma referAncia ao mesmo objeto Runnable (que cont6m uma referAncia i conta real). 3. O saldo inicial da conta 6 de 50, e cada retirada serA exatamente igual a 10.
4. No m6todo
run (
),
I I
se
antes
5. O m6todo
makewithdrawal (
se
) da classe de
I
T
hi
o bastante para
^retk^d^;
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;
400
Copitulo 9: Threoos
I I
quando sair da suspensio, concluirl a retirada e exibiri que ela foi feita;
se
nlo houver o basranre, exibir6 uma declaragio mostrando quem 6 vocA e o fato
de que
nio hi dinheiro
suficiente.
Porranto, o que esramos realmente tentando descobrir 6 se o seguinte 6 possivel: um s6cio verificar a conta e ver se hi o bastante, mas antes da retirada real ser feita, o outro s6cio verificar a conta e tambdmver que hi o suficiente. Quando o saldo da conta chegar a L0, se os dois s6cios o verificarem antes de fazer a retirada, ambos pensario que esti tudo certo e a conta ficar6 com menos 10!
Aqui
est6 o c6digo:
public class AccountDanger implements Runnabl-e private Account acct = new Account ( ) ; public static void main (String [] argrs) { AccountDanger r = new AccountDanger O ; Thread one = new Thread(r); Thread two = new fhread(r);
one. setName ( "Fred" ) ,' two . setName ( "Lucy" ) ;
");
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.
}
) )
1
Entio o que
aconteceu? E possivel que Lucy rcnha verificado o saldo, o thread tenha entrado em suspensao, Fred verificou o saldo,othreaddeLurydespeftoueconcluiu silaretirad^e,emseguida,Fredconcltiuasua,eelesacabaramportirarmaisdo
quepodiam? Veja
* i arra
1 l'rad
saida (numerada):
n: --**------rnger A--^rrnt.
ic aninf^ rrithArrt.r
JAVA
401
2. Lucy is going to withdraw 3. Fred completes the withdrawal 4. Fred is going to withdraw 5. Lucy completes the withdrawal 6. Lucy is going to withdraw 7. Fred completes the withdrawal 8. Fred is going to withdraw 9. Lucy completes the withdrawal 10. Lucy is goinq to withdraw 11. Fred completes the withdrawal 12. Not enough in account for Fred to 13. Not enough in account for Fred to 14. Lucy completes the withdrawal 15. account i-s overdrawn! 16. Not enough in account for Lucy to 17. account is overdrawnl 18. Not enough in account for Lucy to 19. account is overdrawnl
Embora a
withdraw withdraw
0 0
withdraw -10
withdraw -10
cada vez que voc6 executar esse c6digo a saida possa ser um pouco diferente, percorreremos esse exemplo especifico usando as linhas numeradas da saida. Nas primeiras quatro tentativas, tudo est6. correto. Fred verificou o saldo na linha 1 e viu que estava tudo bem. Na linha 2,Lucy verificou o saldo e viu que est6 tudo bem. Na linha 3,Predfez sua retirada. Nesse momento o saldo qtre Lury verificou (e acreditou qtre fosse preciso), na verdade, se
primeira rdrada. A
alterou depois da ihima vez qtre foi verificado. E agora Fred est6 verficando o saldo nouamente, antes de Lury concluir sua essa alrura, Fred tambdm est6 vendo um saldo potencialmente impreciso, porque sabemos que Lury vai concluir sua retirada. E posivel, 6 claro, que Fred conclua a sua antes de Lucy, mas nio foi iso qu aconteceu aqui.
Na linha 5, Lucy concluiu sua retirada e, em seguida, antes de Fred concluir a sua, Lucy verifica novamente a conta na linha 6. E isso continua assim at6 chegarmos i linha 8, onde Fred verifica o saldo e vA que 6 igual a 20. Na linha 9, Lucy conclui uma retirada (para qv^l ji tinha verificado o saldo anteriormente) e isso levou o saldo a um ^ valor igual a 10. Na linha 10, Lucy verificou novamente e viu que o saldo era 1.0, poftanto ela sabe que pode fazer
uma retirada. Mas nio sabe que Fred tambdn jti aeifcou o saldo na linha 8, dusaforma, ele acha que d segurofaqer a renradalNa linha 11, Fred conclui a retir^d^ para a qual verificou o saldo na linha 8. Isso levou o saldo a zero, mas Lucy ainda tem uma retirada pendente que aprovou na linha 10! Voc sabe o que acontecere.
Nas linhas !2 e 13, Fred verficou o saldo e viu que nlo havia o bastante na conta. Connrdo, na linh a I4,Lua7 concluiu sua retirada e BOOM! A conta agora esi estourada em 10 - algt que athamw qae seria euitada por meio de uma r,wficagdo anterior a uma ntirada
de tempo do que pode ocorrer quando dois threads acessam simuhaneamente o mesmo objeto.
Tempo Thread
A acessari Obleto 2
B acessari Obleto I
somente
Thread
e entio o Objeto 2
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?
4O2 Cooitulo
9: Threods
a rcr.trada - nunca fiquem separadas. Precisamos que Temos que garantir que as duas aapas da retbada - wrfiatr o saldo e como urna opera$o, mesmo quando o thread entrar em suqpensio entre as etapx I e2l Chamamos isso de "opera$o at6mica" (embora aqui a fisica esteja um porrco desatualizada, neste caso "at6mico" sigpfica "indivisivel") porque a operaSo, independente da quantidade de declara6es efetivas (ou insrug6es bytecode zubjacentes), serS concluida antesdo codigo de qudquer outro tlrread qtre attre sobre os mesmos dados.
Vocd ndo podz garantir que um tinico thread perrzanepa yndo execatado darante toda a operagdo atdmica. Entretanto, pode garantir que mesmo se o thread que estiver processando a opera$o at6mica entrar e sair do estado de execu$o, nenham oahn tbnad smda execatada prsa ahtm sobrc os mesmos dados. Em outras palavras, se o thread de Lury entrar em zuspensio depois de verificar o saldo, podemos i-pdit que Fred verifique o sddo anta de o thread de Lucy despenar e concluir sua retirada
jty
I I
private;
as
vari6veis.
lembrese de proteger
as variiveis de maneira normal usando um modificador de controle de acesso. E o codigo do moodo que voc6 precisa proteger, para qtre so um thread posa exe antA-lo por vez. Faga isso com a palavrachave slmchroni z ed .
makeWithdrawal ( ) com slmchronized, como vemos abaixo: private synchronized void makeWithdrawal(int amt) { if (acct.getBalanceO >= amt) {
Podemos resolver todos os problemas de Fred e Lucy adicionando uma palavra ao c6digo. Marcaremos o m6todo
trY
{
;
Thread.sleep(500) acct.wj-thdraw(amt);
System.
" completes the withdrawal"); ) else { System.out.println("Not enough in account for "
+ Thread. currentThread ( ) . getName
)
(
)
I java AccountDanger Frcd ic ooino 1-^ ldithdraw Fred completes the withdrawal Trrcw is ooinc to withdraw Lucy completes the withdrawal Fred is going to withdraw Fred completes the withdrawal Lucy is going to withdraw Lucy compl-etes the withdrawal Fred is going to wiLhdraw Fred completes the withdrawal Not enougfh in account for Lucy to withdraw Not enough in account for Fred to withdraw
0 0
JAVA
403
Not enough in account for Lucv to withdraw Not enough j-n account for Fred to withdraw Not enough in account for Lucy to withdraw
0 0
Observe que agora os threads, Lucy e Fred, sempre verificam o saldo da conta e concluem a retirada antes de o outro thread poder verificar o saldo.
SincronizasAo e bloqueios
a sincronizagio funciona? Com bloqueios. Todo objeto em Java possui um bloqueio interno que s6 surge quando o objeto tem um c6digo de m6todo sincronizado. Quando entrJmos em um m6todo sincronilado nio-est6tico, automaticamente adquirimos o bloqueio associado com a instAncia atual da classe cujo c6digo esramos erecutando (a instAncia this). A operaEio de adquirir um bloqueio para um objeto tamb6m e conheiida como obten$o do bloqueio, ou como bloquear o.objeto, on_ bloque ar no obj*o,ou sincronizar no objeto. Poderemos usar tamMm o termo monitor para nos referirmos ao objao cujo bloqueio estamos adquirindo. Tecnicamente, o bloqueio e o monitor slo duas coisas diferentes, mas a maioria das pessoas fala deles como se fossem a me$na cois4 e faremos o mesmo.
Como
J6 que s6 h6 um bloqueio por objeto, se um thread usar o bloqueio, nenhum outro poder6 acessar o c6digo sincronizado at6 que o bloqueio seja liberado. Isso significa que nenhum outro thread pode entrar no c6digo de sincronizagXo (o que significa que nio pode entrar em nenhum m6todo sincronizado desse objeto) at6 que o bloqueio tenha sido liberado. Normdmente, a liberagio de um bloqueio significa que o thread que o estA mantendo (em outras palavrx, o thread que est6 anulmente no m6todo sincronizado) sairi do m6todo sincronizado. Nesse momento, o bloqueio 6liberado at6 que algum outro thread entre em um m6todo sincronizado nesse objao.
I I I I
slmchronized,
as
variiveis, nio.
nio-slmchroni zed.
estiverem usando
slmchronized em uma classe, e ambos os threads m6todo. somente um thread poder6 executar o m6todo de cadavez.O outro teri de esperar at6 qu. o pri-.iro termine a sua chamada. Em outras piavras, quando um thread usar o bloqueio de um objeto, nenhum outro thread poderi acessar quaQaerdos m6todos sincronizados dessa classe (referentes a esse objeto).
Se
mesma instAncia
&
Seumaclassetivertantom6todosslmchronized quantonio-slmchronized, udriostbreahpodrrdoacessaros mitodos nlo-symchronized da classe! Se houver m6todos que nio acessem os dados que voc6 esti tentando proteger,
entXo, nio ser6 preciso marci-los como sincronizados. A sincronizaglo tem um impacto no dcsempenho (ou pode at6 cansar um impasse se usada incorretamente), ponanto, 6 melhor nio usi-la sem uma b oarozilo.
I I
St
o,
nio ot /ibera.
Othreadpodeasarmaisdearzbloqaeio.Porexemplo,othreadpodeacessarumm6todoslmchronized,obtendo assim um bloqueio e, em seguida, chamar imediatamente outro m6todo slmchronized em um objeto diferente, usando are bloqueio tamb6m. Com o desenrolar da pilha, os bloqueios serio liberados novamente. Al6m disso, se um thread adquirir um bloqueio e depois tentar chamar um m6todo sincronizado nesse mesmo objeto, nio haveri problemas. A JVM saberd que esse thread ji possui o bloqueio desse objeto, portanto, ele
poder6 chamar outros m6todos
synchronized
I li
Voed Pode
que a sincronizagio prejudica a concorrncia, 6 melhor nlo sincronizar nenhum outro c6digo al6m dos necess6rios para proteger seus dados. Portanto, se o escopo de um m6todo for maior do que deveria, voc6 poder6 reduzir o escopo da parte sincronizada para algo menor do que um m6todo completo - para apen s um bloqueio. Chamamos isso, por mais estranho que parega, de "bloco sincronizado", e seu formato 6 o seguinte:
nlacc Psvrrv q1m^rF6cf I
(
404
Cooitulo 9: Threods Quando o thread esti processando um c6digo a panir de um bloco slmchronized, inclusive o c6digo de qualquer m6todo desse bloco, diz-se que esse c6digo esta sendo executado em art clntexto sincroniTado. A pergunta que pode surgir 6.: sincroniqado com base em qud? O:u, sincroniqado com base no bkqueio dr qual objeto? Quando voc6 sincronizar umm6todo, o objeto usado para chamilo ser6 aquele cujo bloqueio tiver que ser obtido. Mas, quando sincronizar um bloco de c6digo, voc6 teri que especificar qual bloqueio de objeto ir6 usar; para tanto voc6 poder6, por exemplo., empregar alguniobjeto.de terceiroipara bloquear essi trecho de codigo.,kso lhe proporcronari o r.c.rr* de teimais de um bloqueio para a sincionizagio de c6digos dentro de um rinico obieto.
(ttris), como no c6digo acima. (Jma vez que 6 a mesma instAncia em bloqueiam, isso significa que voc6 pode sempre substituir um m6todo slmpor um nio-slmchr onized, que contenha um bloco slmchronized. Em outras palavras, isto: slmchronized
("
slmchronized" ) ;
esses m6todos t6m exatamente o mesmo efeito, na prhtica. Os bltecodes compilados poderlo nio ser exatamente os mesmos para os dois m6todos, mas poderiam ser - e quaisquer diferengas existentes nlo sio importantes. A primeira forma 6 mais curta e mais familiar para a maioria das pessoas, mas a segunda pode ser mais flexivel.
E quarrto aos metodos static? Eles podem ser slmchronized? Os m6todos static podem ser synchronized. 56 haveri uma copia dos dados static que vod tentar proteger, portanto, seri preciso apenas um bloqueio por classe para a sincronizaSo de m6todos estiticos - um bloqueio para tda a classe. Existe um bloqgeio assim; toda classe carregada em esa classe. E essa instincia de java.lang.Class cujo Java possui uma insrAncia correspondente de,iava.lang.Class bloqueio ser6 usado para proteger m6todos static da classe (se eles forem slmchronized). Nlo hi nada especial que sejapreciso fazer parasincronizar um m6todo static:
Novamente, isso poderia ser substituido por c6digo que use um bloco em uma classe chamada MyClass, o c6digo equivalente 6 o seguinte:
^'lh] PulrIL ;^ rf-f;^.int>LdUfL Irru zcd(MttCl noft-nrrnf VEuevurrL\/ aqq l\ nlacq\
J
slmchronized.
Se o
srmchrnni
IL
t"artt ,
)
count;
Espere, que hist6ria 6 essa de MyClass.class? Isso se chama literal de classe. Trata-se de um recurso especial da linguagem Java que diz ao compilador (que por sua vez diz ) JVM): 'encontre para mim a instAncia de Class que represente a classe chamada MyClass." Voc6 tamb6m pode fazer isso com o seguinte c6digo:
{
;
Entretanto,
essa verseo 6 mais longa, mais complexa e, o mais importante de tudo, nlo cai no exame SCJP. Mas f6cil e ripido usar um literal de classe - basta escrever o nome da classe e adicionar . class ao final. Nio 6 preciso usar aspas. Agora voc6 tem uma expressio para o objeto Class que precisa sincronizar.
JAVA
405
Exercfcio 9-2
Sincronizando um bloco de c6digo
Neste exercicio tentaremos sincronizar um bloco de c6digo. Dentro desse bloco obteremos o bloqueio de um objeto Para que outros threads nio possam altera-lo enquanto o bloco de c6digo estiver sendo executado. Criaremos tr6s threads, todos tentando manipular o mesmo objeto. Cada thread exibir6 a mesma letra 1OO vezes em seguida, a exibigio passar6 para a pr6xima letra. IJsaremos um objeto StringBuffer.
e,
Poderiamos executar a sincronizagio em um objeto String, mas as strings nio podem ser alteradas depois que sio criadas, Portanto, nio poderiamos passar para a pr6xima letra sem gerar um novo objeto String. A saida final deveriter 100 As, 100Bs e 100 Cs, tudo na mesma linha.
1. Crie a classe e estenda Thread. 2. Sobrescreva o m6todo run ( ) de Thread. E ai que entrarS,o bloco de c6digo slmchronized.. 3. Para que nossos tr6s threads companilhem o mesmo objeto, teremos que criar um constnrtor que aceite
objeto StringBuffer no argumento.
um
4. O bloco de c6digo slmchronized obter6 um bloqueio do objeto StringBuffer na etapa 3. 5. Dentro do bloco, exiba o objeto StringBuffer 100 vezes e, em seguida, passe para a letra seguinte. VocA pode
consultar o Capitulo 5 para verificar os m6todos de StringBuffer que ajudario aqui.
6.
Para concluir, no m6todo main ( ) , crie somente um objeto StringBuffer que use a letra A e, em seguida, gere tr6s instAncias de nossa classe e inicie todas elas.
O que acontecer6 se um thread nio puder obter o bloqueio? Quando um thread tentar acessar um m6todo slmchroni zed. e o bloqueio j6 estiver sendo usado, diz-se que ele foi inpedido de obter o bloqaeio de un objeto. Essencialmente, o thread entrari em um tipo de pool desse objeto especifco e ter|
que aguardar at6 que o bloqueio seja liberado e ele possa novamente passar para o estado executlvel/em execuEeo. s6 porque um bloqueio foi liberado nio significa que algum thread especifico iri usilo. Pode haver tr6s threads aguardando um rinico bloqueio, por exemplo, e nlo h6 garantias de que o thread que esteja esperando h6 mais tempo seri o primeiro a obter esse bloqueio.
No entanto,
Ao
se
considerar o impedimento, 6 importante prestar atengio a quais objetos estio sendo usados para o bloqueio.
r I I
Threads qtre chamam m6todos que nio sejam slmchronized. da mesma classe so bloquearto uns aos outros se forem chamados usandose a mesma insdncia. Isso ocorre porque cada um deles bloqueia na instAncia this, e, se forem chamados usandose duas irstAncias diferentes, eles receberXo dois bloqueios, qlre neo interferem um com o outro.
static
Threads que chamam m6todos static slmchroni zed da mesma classe sempre bloqueario uns aos outros - todos eles bloqueiam na mesma instAncia de Class.
Um m6todo
st,atic slmchronized e um que nio seja static slmchronized nunca bloqueario um ao outro, jamais. O m6todo static bloqueia em uma instincia de Class, enquanto que o m6todo niostatic bloqueia na instincia this - essas ag6es nXo interferem umas com as outras de forma nenhuma.
voc6 precisa observar exatamente qual obieto foi usado para o blogueio. (O que slmchronized?) Threads que sincronizem no mesmo objeto bloqueario umas )s outras. Threads que sincronizem em objetos diferentes nio o fard.o.
est6 dentro dos par6nteses, depois da palavra
9-1 lista os m6todos relacionados a threads e se o thread abre
A Tabela
Tobelo
mio
9-l
Mantm o bloqueio
notify ( ) (Embora
dessa chamada.
dobloqueio) inin/
I
sleep (
yield(
406
Copitulo 9: Threods
Entio, Quando Eu Preciso Sincronizar? A sincronizaglo pode ficar bem complicada, e voc6 pode estar se perguntando.pgr que iria.querer se dar a esse trabalho, ,r-i lrei q,re pode evitiJo. Mas lembre-se do exemplo antes de "condigio de corrida" , com Lucy e Fred fazendo r"qnei di conta deles. Quando usamos threads, normalmente precisamos usar alguma sincronizagio em algum lugar para nos certificarmos de que nossos m6todos nio ir6o interromper uns aos os nossos dados. Geralmente, sempre que mais de um thread estiver outros t" hor" "rr^i^,bag;ng""d" acessando dados mut{veis"(mbdificlveis), voc6 sincroniza p"ra prot.gir oJ dados, para cenificar-se de que dois threads nXo os estio modificando ao mesmo tempo (ou que um nio os estA modificando ao mesmo temPo em que o ourro os est6 lendo, o que tamb6m leva a cbnfusA,ei). ryao ( preciso se preocupar com variiveis locais -
cada thread recebe a sua pr6pria c6pia de uma vari6vel local. Dois threads que executem o mesmo m6todo ao mesmo tempo usario diferentes c6pias das vari6veis locais, e nio interferirio um com o outro. Entretanto, voc6 e nio-static, caso eles contenham dados que possam ser precisa se preocupar com campos
itatic
modificados.
Para dados modific6veis em um campo nlo-static, voc6 normalmente usar6 um m6todo nlo-static para acess6-los. Sincronizando o m6todo, voc6 garante que quaisquer threads que tentem executar esse mdtodo usando simultAneo. Mas um ihread que esteja trabalhando com uma a mesma instAncia serio impedidos de ter.m "cesso instAncia diferente nio serlifetado, porque esti adquirindo um bloqueio na outra instAncia. E isso o que queremos - que os threads trabalhanio .bm or mesrnos dados tenham de atuar um de cadavez, mas threads trabalhando iom dados diferentes possam simplesmente ignorar uns aos outros e executar semPre que quiserem; nio faz diferenga.
_
Para dados modific6veis, em um campo static, voc6 normalmente usa um m6todo est6tico para acess6-los. E novam ente, sincron)zando o m6todo, voc6 garante que quaisquer dois threads que tentem acessar os dados serio impedidos de ter acesso simultAneo, porque-ambos os threadsterlo de adquirir bloqueios no objeto Class para a classe em que o m6todo static est6 definido. Novamente, 6 isso o que queremos.
um campo
uma boa chance de elas nio funcionarem da maneira que voc6 deseja. Se voc6 tem um m6todo static acessando nio-static, e sincronizar o m6todo, voc adquire um bloqueio no objeto Class. Mas e se houver um outro m6todo.que tamb6m acesse nio-static, desta vez usando um m6todo nio.static? Ele provavelmente
9:ampg
Fica muito confuso tentar imaginar todas as coisas estranhas que podem acontecer aqui. Para manter a simplicidade: para tornar uma classe segura no que diz respeito a threads, os m6todos que acessam campos modificiveis precisam
ser
deue
slmchroni-zed.
deue
nrfeito apartir
s/an
dc mdtodw stat.ic slmchroni zed. O acesso a campos ndo-esL6ticos sLatic slmchronized. Por exemplo:
{
<i:l-iaFia]A.
.1 .
inf
n^nql- af i .E i al
JAVA
407
E se voc6 precisar acessar tanto campos static quanto nlo-static em um m6todo? Bem, existem maneiras de se fazer isso, mas esti.al6m do que voc6 precisa para o exame. Vocd viver6 uma vida mais longa e feliz se sinplesnente ndofryr isn. S6rio mesmo. N6s mentiriamos para voc6?
sincroniza$o)
Entretanto,_mesmo.quando uma classe for "segura", na maioria dos casos 6 perigoso confiar nessas classes para fornecer a protegio de thread que voc6 precisa. (Ora, o fato de usarmos repetidamente aspas em torno de "segura" tinha de significar algo, nlo?) Voc6 ainda precisa pensar com cuidado sobre como usar6 eisas classes. Como um exemplo,
considere a seguinte classe.
private List
names =
Collections.slmchronizedlist(
nar.r T.i nlra^r.i cf r \ ) ;
(0)
return nuI1;
) ( ) retorna um List cujos m6todos estao todos sincronizados e "seguros", de acordo com a documentagXo (como um Vector mas, uma vez que estamos no s6culo XXI, nXo iremos usar um Vector aqui). A questio 6, a classe Namelist pode ser usada de forma segura a partir de mriltiplos threads? E tentador pensar que sim; uma vez que os dados em names e$ao em um conjunto sincronizado, a classe Namelist tamb6m 6 "segura". Entretanto, nio 6 o caso - o m6todo removeFirst ( ) pode, is vezes, langar uma NoSuchElementException. Qual6 o problema? Ser6 que ele nio verifica corretamente o size ( ) dos nomes antes d remover algo, para ceftificar-se de que existe alguma coisa neles? Como ese c6digo poderia falhar? Vamos tentar usar
O m6todo
Collections. synchronizedlist
Namelist destaf.orma
class NameDropper extends Thread { public void runo t St.ring name = n1 .removeFirstO; System. out. println (name) ;
)
)
,-
408
Copitulo 9: Threoos
que.
poderia acontecer aqui seria.que um dos threads removeria um name e o exibiria, e depois o outro thread
tenrarra
Se
size ( ) e
names
Thread
get
t1 executa names . size ( ), que retorna 1. Thread t1 executanames . remove (0 ) , que retornaozlzmandias.
Threadt2 executanames. size ( ),queretorna Thread L2 nio chama remove ( o ) .
A saidaaqui
6
0.
Ozlzmandias
nu11
Entretanto,
se
Thread L1 executanames .
remove
(0),
que retorna
Ozymandias.
como aquela retornada por synchronizedlistQ, cada m6todo
essas duas
Threadt2 executanames.remove(0),quelangaumaexcegloporquealistaagoraest^vazia.
O que voc6 precisa perceber aqui 6 que, em uma
nada impede que
classe "segura"
individualestisinCronizado.Assim,narnes.sizeO est6slmchronized,enames.remove(0)tamb6m.Mas
outro thread
faga alguma
ocorrerproblemas.
em
Collections . slmchronizedlist
( ) . Emvez disso,
sincronize o c6digo
public class Namel,ist { private List names = new r-inkedl,ist ( ) ; pubfic synchronized void add(String name)
names.add(name); ]
Agoratodoom6todoremoveFirstO estisincronizado,edepoisqueumthreadoiniciarechamarnames.sizeO,o
outro thread nio poder6 mais interromper e roubar o ultimo name. O outro thread simplesmente teri primeiro finalize a sua operagXo com o m6todo removeFirst ( ) .
de esperar at6 que
A moral aqui 6 que, s6porqueest6descritacomo "seguraem rela$oatlveads",nioquer dizerqueuma classe 6 sempre segura. Se m6todos individuais estiverem sincronizados, isso pode nio ser o suficiente - pode seruma solugXo melhorcolocar a
sincronizaqio em um nivel mais alto (ou seja, colociJa no bloco ou m6todo que chama os outros m6todos). Depois que voc6 faz isso, a sincronizagio original (neste caso, aquela dentro do objeto retornado por collections . synctrronizedlist ( ) ) podeni se tornar redundante.
lmpasse em threads
O que talvez possa ocorrer de mais assustador a um programaJava 6 o impasse. O impasse ocorre quando dois threads ficam impedidos de obter um bloqueio, cada um esperando pelo bloqueio do outro. Nenhum deles poderl ser executado at6 que abram mXo do bloqueio, portanto, aguardario eternamente. Isso poder6 acontecer, por exemplo, quando o thread A chegar a um c6digo slmchroni zed, conseguir o bloqueio B e, em seguida, entrar em oaho m6todo (ainda dentro do c6digo slmchroni zed. parao qual possui o bloqueio) que tamb6m for slmchroni zed. Por6m, o thread A nlo poder4 obter o bloqueio par^ entr^r nesse c6digo slmchroni zed - o bloqueio C - porque outro thread, D, ji est6 com ele. Sendo assim, o thread A ir|, para o pool "de espera do bloqueio C", na esperanga de que o thread D
JAVA
seja breve e o libere (concluindo o m6todo
4O9
slmchronized). Mas o thread A ter6 que esperar realmente muito depois que o thread l-) obteve o bloqueio C,.ele entrou em um m6todb slmchronized que usa o l:mpo'.Pgrqle bloqueio^ B. E.:l?to que o thread D nio conseguiu o bloqueio B, uma vez que o thread ,{ 16 .rt"lr" com ele.'E esse thread nio vai liber6lo at6 que o thread D libere o bloqueio C.
Contudo,othreadDnioliberariobloqueioCantesdeobterobloqueioBedarprosseguimento.Eassim
permanecerio. O exemplo a seguir demonstra o impasse:
1. public cl-ass OeadlockRisk { private static class Resource { 2. public int value; 3. 4. ) private Resource resourceA = new Resource 5.
5nrirrate
ReSO111.Ce
();
7. B. 9. 10.
pubLic int read() { slmchronized(resourceA) { // Pode haver impasse slmchronized(resourceB) { return resourceB.vafue + resourceA.value;
)
) )
15. public void write(inr a, int b) { 16. synchronized(resourceB) t // Pode haver 1-'7 . slmchroni zed resourceA) { 18. resourceA.value = a; 19. resourceB.value = b; 20. ) 21. )
(
impasse aqui
))t
23.
Suponhamos que read ( ) tenha sido iniciado por um thread e write ( ) por outro. JA que temos dois threads diferentes que podem ler e gravar independentemente, exise o risco de impasse na linha 8 ou 15. O thread de leitura possui o recurso A, o de gravagio possui o recurso B e os dois ficario paralisados eternamente aguardando o outro desistir.
Um c6digo como esse quase nunca resulta em impasse porque a CPU tem que passar do thread de leitu ra para o de gravagXo em um ponto especifico e as chances de o impasse ocorrer sio muito pequenas. O aplicativo pode funcionar bem 99,9 por cento do tempo.
Esse 16 e 17 (ou nas
exemplo simples 6 f6cil de corrigir; apenas troque a ordem do bloqueio do thread de leitura ou de gravaEio nas linhas linhas 8 e 9). Situag6es mais complexas de impasse podem levar muito tempo para serem identificadas.
Independente de serem pequenas as chances de seu c6digo entrar em um impasse, a conclusio 6 t se yoc entrar em un impasse, fcaniparalivdo. H6 abordagens de projeto que podem ajudar a evitar impasses, incluindo estrat6gias de sempre obter bloqueios em uma ordem predeterminada. Deixaremos a seu cargo esse estudo que est6 al6m do escopo deste livro. Se voc aprender tudo que abordamos neste capitulo, no entanto, ainda saber6 mais sobre threads do que a maioria dos
programadoresJava.
notfi
ou
notfrAll.
entre si para comunicar - entre outras coisas
O fltimo item que precisamos examinar 6 como os threads podem interagir ostatusdeseusbloqueios.AclasseObjectpossuitr6sm6todos-wait(
),notify(
enotifyAll( )-que
ajudam os threads a obterem informag6es sobre o status de um evento importante para eles. Por exemplo, se a tarela de um thread for a distribuigio de correspondAncia, e a de outro for o processamento de corresponddncia,
410
Copitulo 9: Threods
este riltimo thread teri que verificar continuamente se hi alguma correspondOncia aprocessar. Usando o mecanismo de espera (l'"ir) . notificaglo (notify), ele poderia procurar a correspond6ncia, e se nio encontrasse ;Ora,'nlo vou perder-meu tempo proiurando-correspond6nciai a cada dois segundos. Vou ficar nenhuma dizerr por aqui, e quando o distribuidbr de correspond6niia colocaralgo nacaixa de correio, farei com que ele me avise' Assim, .n posso voltar ao estado execut ivel e f.azer meu trabalho". Em outras palavras, os m6todos wai t ( ) e notify ( ) permitem que um thread fique em uma "sala de espera" at6 que algom outro thread o avise (notifique) de que hi uma r^z1o para voltar ) atividade.
Um ponto
Os ndtodos
lembrar
(e
waiL
an
),
pode chamar
mdtodo
aait
notifi
Agora apresentaremos um exemplo de dois threads que dependem um do outro para dar prosseguimento a suas tarefas, e mosrraremos como usarwaiL ( ) e notify ( \ pirafazercom que interajamieguramente e no momento apropriado'
Considere uma m6quina controlada por computador que cone pedagos de tecido em formatos diferentes, e um aplicativo que permita que os usuS.rios especifiquem o formato do cone. A verslo atual do aplicativo possui somente um thread, o q"at pri-.iro solicita ao usuirio instrug6es e, em seguida, direciona o hardware para cortar no formato desejado, repetindo
ociclo&pois.
public void
/
run ( ) {
{
while (true)
/ Obt6m o formato do usu5ri-o // Calcula as etapas da m6quina para fazer o formato / / Envia as etapas para o hardware
Esse
'
projeto nlo
a
formatos
6 6timo porque o usuirio nio poder|fazer nada enquanto definir. Precisamos melhorar a situa$o.
houver outros
6 separar os processos em dois threads diferentes, um deles interagindo com o usuirio e outro gerenciando o hardware. O thread do usu6rio enviar6 as instrug5es para o thread do hardware e, em seguida ,voltarh a interagir com o usuirio imediatamente. O thread do hardware recebe as instrug6es do thread do usuirio e comega a instruir a miquina imediatamente. Os dois threads usam um objeto em comum para se comunicarem, o qual cont6m o projeto atual que est6 sendo processado.
esse
projeto:
/ ObL6m o formato do usu6rio / / CaIcuIa as etapas da n6quina para fazer o formato / / Modrfica objetos comuns com as novas etapas da m5quina
]
)
Oproblema agora|.fazer comque o threaddo hardware processe as etapas &miquinalogo que estiverem disponiveis. AlSm disso, o lhread do usuirionio deve alter6Jas at6 que todas tenharn sido enviidas paia o hardware. A solugio 6 usar wait ( ) enotify ( ), al6mdesincronizaralgunstiechosde c6digo.
um sinal (uma notificagio) desse objeio. Um thread pode entrar nessa lista com a execugio do m6todo wait ( ) do objeto de desdno. A partir desse momento, ele nio executarl nenhuma outra instrugio at6 que o m6todo noti fy ( ) do obieto de destino seia chamado. Se muitos threads e$iverem aguardando no mesmo objeto, somente um seri selecionado (sem uma ordem definida) para prosseguir com sua execugio. Se nio houver threads esperando, entao, nenhuma agio especifica seri tomada. Examinemos um c6digo real que mo$ra um objeto aguardando que outro o notifique (preste atenglo ji que 6 um pouco complexo):
Lembre-sedequeosm6todoswait( )
enotify(
) slom6todosdeinstAnciadeObiect.Damesmamaneiraque
de threads aguardando
JAVA
411
1. 2. 3. 4.
5.
class ThreadA { public static void main(String [] args) ThreadB b = new ThreadBo; b.start0;
slmchronized (b) i
. '7.
6
try
16. I7 .
1_8.
19. public void runO { 20. slmchronized(this) i 21_. for(int i=0;i<100;i++) 22. total += i; 23. ) 24. notifyo;
zo. l
27. j
programa condm dois obfetos com threads. ThreadA cont6m o rhread principal e ThreadB possui um thread oue calcula a soma de todos os ntmeros de 0 a 99. Logo que a linha 4 chamar o m6todo start ( ) , ihreadA passar6 p'ara a pf"ft"Jd* de c6digo de sua pr6pria classe, o qie si-gnifica.que pode chegar ) linha 12 antes que ThreadB concluaieu carcuro. r-ara rmpecur rsso, usamos o metodo wat-t ( ) na lrnha y.
Esse
precisa.do.bloque-iodeb.Paraqueumthreadchamewait(
bloqueio desse objeto,. Quando o thread estiver aguardando, liberar6 temporariamente o bloqueio para outros threads usarem, masprecisar6dele novamenteparadarpiossegurmento aexecugao. E comum enconirarmbsnm c6digo como o segumte:
)ounbtity[
) no objero, ThreadA
),.1.t.-queseroproprietiriodo
em
anotherObject
try
anotherobject.wait ( ) , // o thread libera o bloqueio e espera / / Para continuar, o thread precisa do bloqueio, / / enLdo poder6 ficar bloqueado at6 que o obtenha. ] catch(InterruptedException e) { }
)
fy
ect.
c6digo notificari qualquer outro que esteja aguardando o obieto this. O bloqueio pode ser obtido bem no inicio do c6digo, por eiemplo, no m6todo chamador. E bom ress;ltar que se o threid qui chamar wai t ( ) nio tiver o bloqueio, uma excegXo rllegalMonitorstateException seri langada. Eisa exceglo nio 6 verificada,
412
Copftulo 9: Threods
porranro, voc[ nlo precisa captari-la explicitament". E i*po.tante semPre deixar claro bloqueio de um ob.iito em um bloco de c6digo especifico.
se
um thread possui o
hi um bloco
maneiraqnl.
trylcatctr encapsulando o m6todo wait ( ) . Um thread em esPera n- thread em suspenslo, portanto, voca ter6 que manipular a
trY{
wai_t O ;
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:
t
L
I oarecE.lons;
etc.
E imponarrte que o thread do usuirio nlo altere as etapas da m6quina enquanto o thread do hardware ,rsando, portanio, essa leitura e gravagS,o devem ser sincronizadas.
as
estiver
esse
formato:
i class Machine extends fhread { operator operator; // assuma que isso seja iniciali-zado public void runO { while(true) {
slmchronized ( operator)
{
]
O thread da miquina, uma vez iniciado, entrar6 imediatamente no estado de espera, e aguardari pacientemente at6 que o operador envie iprimeira notificaESo. Nesse momento, ser6 o thread do operador que teri o bloqueig dessg o_bj91o, pbrtanto, o threJd do hard* are frcariparalisado por algum tempo. 56 depois que o thread do operador sair do bloco iincronizado 6que o thread do hardware poder6 realmente iniciar oprocessamento das etapas da m6quina.
JAVA
413
Enquanto um formato estiver sendo processado pelo hardware, o usu6rio poder6 interagir com o sistema e especificar outro_formato para ser cortalo. Quanio o usu6rio tiver terminado o formato-e for hora de con6-lo, o thread do operador rcntarl entrar no bloco s]ncronizado, podendo ser impedido at6 que a miquina .orr.l.r"-", o"p", anteriores. Quando o thread da m6q]rina tiver terminado, iepetir6 o loop, entrando ,rorr"m.rrt. no est"do d. .rp.ri (e, ponanto,.liberando o bloqueio). 56 entio o thread do operador podei6 entrar no bloco sincronizado esubstituir as
etapas da miquina pelas novas.
Ter dois threads 6 definitivamente uma melhoria sobre ter somente um, embora nessa implementagao ainda haja uma possibilidade de fa7.ey.9 ujuirio esperar. Uma melhoria adicional seria rer muitos forrn"to, em uma fila, ' reduzindo assim a possibilidade de ser necessirio solicitar ao usuirio que aguarde o hardware.
Tamb6m !6 yma. segunda versXo de wait ( ) que aceita alguns milissegundos como tempo miximo de espera. Se o thread nio for interrompido,_continuarA sua eiecuglo nor-malment. tJ*p.. que for notificado ou o que 6,.*po --r de espera especificado expirar. Essa continuagXo comum consiste em sair do eriado de espera, ,rr", p"rl d"i prosseguimento i execugio serl necess6rio obter o bloqueio do objeto:
slmchronized(a)
{ // O thread obt6m um bloquei-o em .a, a.wait(2000); // O thread libera o bloqueio e espera por notify, / I mas soment.e por dois seg,undos no miiximo, depois retorna para Runnable // O Lhread readquire o bloqueio / / ItIais inst.ruc6es acrui
j
oBSERVAQoES pene O E)GME
paando o mdtodo wa
imediatamente.
it(
| for chamado, isso nio txCnifta qae o thread abrird mdo de sea bloqueii na mesma bora. Se o thread ainda eftiuer concluindo o ctidigo sincroniqado, o bloqaeio ndo seni liberado atd que ele saia duse nidtgo. Portanto, sri porque
I\o
) for chanado em um objeto, o thread que e$iaer executando use aidigo abinl mdo de tea bloqueio
noLify (
no t
i fy (
foi
se
tornani disponiuel
nesse
mlmentl.
estarem
Na maioria dos cenarios, 6 preferivel notifi car todls osthreads que estiverem esperando por um objeto especifico. Se isso acontecer, voc6 poder6 usar notifyAll ( ) no objeto pira permitir que todosbs threadi saiam da lrea de espera e retornem ao estado execut6vel. Isso seri particularmente imponante se voc tiver threads aguardando um objeto, por6m, por diferentes raz6es, e quiser se cirtificar de que o thread certo serA notificado.
notifyAll (
);/
Todos os threads serio notificados e comegario a competir pela obtenglo do bloqueio. J6 que o bloqueio ser6 usado e liberado por cada thread, todos eles entrario em agio sem a necessidade de uma notificagioidicional.
Como mencionamos anteriormente, um objeto pode ter muitos threads esperando, e o uso de notify ( ) afetarit ym deles. Qual e*atamente nio ser6 especificado e depender6 da implementagio da JVM, porranro, voc6 nunca deve confiar que determinado thread ser6 notificado no lugar de outro.
aPenas
Nos
casos
noti fyAll (
Examinaremos isso em um c6digo. Nesse exemplo, h6 uma classe que a(ecuta um calculo e muitos threads de leitura que estio esperando para receber o c6lcrrlo concluido. Em algum momento, muitos *reads & leitura podedo estar esperando.
nrrl-r'l i c Raarlor
/l-: l nrrl
^f ^r
^il
^l
c = cafc,.
)
6.
7.
zaAlr\ I
j-rrr
eJ
Qrr<fpm v eurrL.
nrrl-
nrini-
ln/.'T^7^if vvqr \
Lf
ina rrv
fnr
nalnrrl:f
Lf
inn vrr.
r r
x\
/ ,
L2.
n rrr:ifl\.
414
Copitulo 9: Threods
l-3. ) catch (InterruptedException e) {i 1,4. ] l-5. System.out.println("Total is: " + c.total); I7' 18. public static void mai-n(String [] args) { t9 . Cal-cul-ator calculator = new Calculator ( ) ; 20. new Reader(calculator) .startO ; 2L. new Reader(calculator) .startO ; 22. new Reader (calculator) . start ( ) ; 23. calculator.startO; 24. ) 25. j
26.
27
. class Calculat.or ext.ends Thread { 28. int total; public void run0 { slmchronized (this ) { for(int i=0;i<100;i++) total += i;
]
29,
notifyAll
)
O;
)
)
(
programainida tr6s threads, todos esperando para receber o cilculo concluido (linhas 18-2a), e depois inicia a calcuiadJra e a sua tarefa. Observe qn. r. o m6todo run ( ) da linha 30 usasse notify ( ) em vez de notifyAll ) , somente um thread de leitura seria notificado, em vez de todos.
ambos,haviapelomenosumthreadchamandowaitO,eoutrothreadchamandonotifyO
ounotifyAllO.
notifyO
ounoLifyAllO.Masoqueacontecese,porexemplo,oCdculatorrodarprimeiroechamarnotifyo
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|-lonovamenteficario esperando para sempre. Isso provavelmente nXo 6 o que o programador queria que acontecesse. Quasl sempre, quandovoc6 queresperarporalgo, precisatamb6msercapazdevenficar se o wento j6ocorreu. Geralmente, a melhor maneira de resolver isso 6 colocar algum tipo de loop que verifique em algum tipo de express6es condicionais, e espere somente se o evento ainda nio tiver acontecido. Eis uma versio modificada, mais segura, do exemplo
e os Readers na espera
assume que
Machinefnstructions -iob
JAVA
415
calculateNewlnstructionsFor
machine. add,fob ( j ob)
;
shape ) ;
o loop para sempre, obtendo mais formatos dos usuirios, calorlando novas instn46es para esses enviando-os para a miquina. Mas agon al6grca para no t i fy ( ) foi movida para dentro do m6todo add,Job ( ) dadasseMachine:
O operador continuar6
e
formatos
List<Machinelnstructions> i obs = new Arrayl,ist<Machinefnstructions> public void addJob(Machinelnstructions job) { slmchronized (jobs) { jobs.add(job) ; jobs.notifyO;
1
I no l o
/ / aqnara veyvre
menos um
{
// Se chegarmos aqui, saberemos que jobs ndo est6 vazio Machinelnstructions instructions = jobs.remove(0),. / / Envia as instruq6es da miiquina para o hardware
A m6quina mant6m uma lista dos trabalhos agendados. Sempre que um operador adiciona um novo trabalho
lista, ele
chamaom6todoadd.rob O ef.azaadtgio.E'nquantoisso,om6iodorunO continuaoloop,procurandoportrabalhos na lista. Se nio houver nenhum, ele comega a esperar. Se for notificado, iri parar de esperar e irl verificar novamente a condigio do loop: a lista ainda est6 vazia? Na pi6tica, essa verificagio dupla provavelmente nio 6 necessiria, uma vez que o rtnico momento em que um noti fy ( ) 6 enviado 6 quando um novo trabalho acabou de ser adicionado i lista.
Entretanto, 6 uma bo; id6ia exigir que o thread verifique novamente
porque
6
noti fy
podeserreativadomesmoquenenhumc6di.gotenhachamadonotifyO ounotifyAllO.@elomenosnenhum i6Ag" de que voc tenha conhecimento. Als vezes aJW poderi chamar notify ( ) po1 raz6es que s6 ele sabe,_ou
Existe tamb6m uma situaglo possivel, chamada de reativagio espontenea, que pode existir em algumas situag6es - um thread
programar ilgumas outras chamadas de classes por raz6es desconhecidas) O que isso significa 6 que, quando o seu thread 6 reativado depois de um wai t O , voc6 nlo sabe com ceneza por que motivo ele foi reativado. Ao colocar o m6todo wai t o em um loop whi 1 e e veriiicar novamente a condigio que representa o evento pelo qual estivamos esperando, nos
cenificamosdeque,qualquerquesejaomotivo,voltaremosawaitO
se(esomentese) oeventoaindaniotiveracontecido.
Se estiver vazia, esperamos; se
Na classe Machine, o que e$avamos esperando era que a lista de trabalhos nio estivesse vazia.
esperamos.
Reparetamb6mquetanto o m6todo
run ( ) quantoo add.Tob ( ) sincronizamno mesmoobjeto-alistadetrabalhos. Tssoocorrepordoismotivos.Um6queestamoschamandowaitO enotifyO nestainstAncia,entiopfecisamos smcromzar para evlrar uma excegio IllegaiThreadState. O outro motivo 6 que os dados na lista de trabalhos sio
416
Copitulo 9: Threods modific6veis, e sio armazenados em um campo que 6 acessado por dois threads diferentes. Precisamos sincronizar para podermos acessar esses dadoi mbdificiveis de iorma segura. Felizmente, os mesmos blocos sincronizador qrr. ro, permitem esperar (wait ( )) e notificar (notify"( )) tamb6m fornecem a seguranga de thread requeridl para os nossos outros acessos a dados modificiveis. Na verdade, essa 6 a razio principal pe_la qual a sinironizagilo precisa usar wait ( ) e notify O - quase sempre, voc6 precisa companilhar alguns dados modificiveis entre v6rios threads ao mesmo tempo, e isso significa que voc6 precisa da sincronizagio. Repare que o bloco de sincronizaEio em addJob ( ) 6 grande o suficiente para incluir tamb6m a chamada a jobs. add(job) que modifica dados compartilhados. E o bloco sincronizado em run ( ) 6 grande o suficiente
_
paraincluirtodooloopwhile-queincluiachamadaajobs.isEmptyO,queacessadadoscompartilhados.
Amoraldahist6ria6que,quandousawaitO enotifyO ounotifyAll{),quasesemprevoc6deveterum loop while junto com wait ( ) para verificar uma condigio e forgar a continuagXo da espera at6 que a condigio seja atendida. E vod deve tamb6m usar o requerimento de sincroniza$o para as chamadas await O e notify O , para
proteger tarnb6m quaisquer outros dados que estiver compartilhando entre tfreads. Se vir c6digo que falhe em fazer isso, normalmente hi algo de errado com o c6digo mesmo se vod tiver dificuldacles em ver qual 6 exatamente o problema"
OBSERVAQ6BS
O:ndtodoswaiL( ),notify(
sdonitodotnmentedejaua.lang.Objut,endodejaua.lang.Tltreadou
e os de
jaua.lang.Rannable. Certfique-se de saber que mritodos sdo defnidu em Tbread, quais sdo en Objut
plftantqesseificil).DosrzitodosprincipaisdeThread,ceftifique-sedesaberquaissdosLaLic
quaisndosdo-join( )estart(
-s1eep( )eyield(
)-
listaosmdtodotprincipafuqueuocdprecisaniconltecernoexame,czmosnitodos
static
exibidw em itdlico.
ClasseThread
Interface Runnable
wait0
notdyQ
staft0 jeld(
tlttp(
run0
) )
notifyAll0
join0
que algu6m chame o m6todo start ( )do objeto Thread. Tamb6m examinamos como o m6todo sleep ) pode ser usado para fazer uma pausa em um thread, e vimos que quando um objeto entra em suspensio, mant6m todos os bloqueios que obteve antes de ficar suspenso.
Examinamos os cinco estados dos threads: novo, execut6vel, de execugio, bloqueado/em espera/suspenso e inativo. Voc6 aprendeu que quando um thread est6 inativo, nunca poderi ser restaurado mesmo se ainda lor um objeto vilido no heap. Vimos que s6 h6 uma maneira pela qual um thread pode passar para a execugio, que 6 a partir do e$ado execut6vel. No entanto, uma vez em execugXo, o thread pode se tornar inativo, entrar em suspensio, esperar que outro thread seja concluido, ser impedido de obter o bloqueio de um objeto, esperar por uma nbtificagio ou retornar ao estado exicut6vel.
VocA viu como dois threads atuando sobre os mesmos dados podem causar problemas s6rios (embra-se da conta banc6ria de Lury e Fred?). Vimos que, para permitir que um thread execute um m6todo, impedindo, por6m, que outros threads Processem o m6todo do mesmo objeto, usamos apalavra-chave slmchronized. Para coordenar iatividade entre
threadsdiferentes,useosm6todoswait
( ),notify(
enotifyAll (
).
Exercicios ripidos
Aqui estio alguns
dos pontos principais de cada objetivo para a certificagio deste Capinrlo. Tire uma c6pia embaixo de seutravesseiro para completar a absorgio.
e
0 B
).
Os objetos dos threads tamb6m podem ser criados com uma chamada ao construtor de Thread que usa um obieto Runnable como argumento. Diz-se que o objeto Runnable 6, o tlestino do thread.
JAVA
417
de
Voc6 pode chamar start ( ) em um objeto Thread somente uma vez. Se start vmavez em um objeto Thread, uma excegio RuntimeException seri langada.
E
u
tr
D QuandoumobjaoThreadforcriado,eleniosetomarawntlmaddemug'wxiq:eseum6todostart(
Quando um objeto Thread existe, mas nio foi iniciado, est6 no estado
nouo
E E D tr tr
Uma vez que um novo thread for iniciado, ele sempre entrari no estado execut6vel.
O agendador
de threads pode
e de
execugio.
Para uma m6quina tipica, de apenas um processador, s6 um thread pode ser executado estar no estado execut6vel.
Nio hi Nio
garantia de que
h6 garantia de que os threads terio a chance de ser executados de maneira justa. Isso 6 responsabilidade do agendador, como determinado pela implementagio especifica da miquina virnral. Se voc0 quiser garantir que seus threads terio sua execugio alternada, independente daJVM subjacente, deve usar o m6todo sleep ). Isso impedir6 que up thread domine.o processo sendo executado enquanto o outro estiver aguardando. (No entanto, na maioria dos casos, ) funciona bem o suficiente para encorajar os seus threads a
yield (
E
D
Umthreadsendoexecutadopodeentraremumestadobloqueado/deesperaporumachamadaawait(
oujoin(
),s1eep(
de
).
espera, porque
sincronizado.
E tr E E
D
se tornar disponivel, o thread s6 poder6 entrar novamente no e$ado executivel. Ele ir6 diretamente da espera para a execuglo (bem, tudo por raz6es pr6ticas).
Um thread em suspenslo ficari inativo por pelo menos o tempo especificado no argumento do m6todo s leep ( ) (a menos que seja interrompido), mas nio h6 garantias de quando o thread rec6mdesperto retornar6 realmente ) execugio.
O m6todo sleep ( ) 6 um m6todo staEic que suspende o thread que estiver sendo executado. Um thread nio pode informar a outro que deve ficar suspenso. O m6todo
e 10 (alto), embora
) 6 usado em objetos Thread para dar aos threads um n(vel de prioridade entre 1 Saixo) prioridades nio sejam garantidas e nem todos osJVMs usem um intervalo de prioridades de 1 a 10 - alguns niveis podem ser tratados como efetivamente iguais.
as
fl E
O
setpriority (
Se
yield ( ) pode fazer com que um thread em execuglo se.ja interrompido se houver threads execut6veis com a mesmaprioridade. Nio h6garantias de que isso ocorreri e de que quando o threadfor interrompido umthreaddiferente ser6selecionado paraexeorSo. Umthreadpode serinterrompido e reentrarimediatamente no esado deexean$o.
O m6todo
de uma garantia serA que, em qualquer momento em que um thread estiver sendo executado, ele geralmente nio ter6 uma prioridade menor do que a de algum outro thread do estado executivel. Se um thread de prioridade menor estiver sendo executado quando um thread de prioridade alta entrar no estado executrvel, a JVM geralmente interromperA o thread de prioridade menor e comegar6 a executar o de
tr
prioridade alta.
Quando um thread chamar o m6todo j oin ( ) de outro thread, aquele que estiver sendo executado esperar6 at6 que o thread ao qual foi adicionado seja concluido. Considere o m6todo j oin ( ) como se dissesse: "Ei thread, quero ser acrescentado ao seu final. Deixe-me saber quando voc6 tiver encerrado sua execugio para que eu possa entrar no estado execut6vel.
Problemas do acesso simultaneo e threads sincronizados (Obietivo 4.3) E Os m6todos slmchronized impedem que mais de um thread acesse o c6digo de um m6todo critico
objeto simultaneamente.
do
tr
slmchronized
c6digo sincronizado.
4l I
Copitulo 9: Threods
E E
Para sincronizar um bloco de c6digo (melhor dizendo, um escopo menor do que o m6todo inteiro), voc6 ter6 que especificar um argumento que seja o objeto em cujo bloqueio quiser basear a sincronizaglo. Embora s6 um thread possa acessar o c6digo sincronizado de uma instAncia especifica, virios threads podem acessar o mesmo c6digo nio sincronizado do objeto.
E Quando um objeto entra em suspensio, seus bloqueios estario indisponiveis para outros threads. E Osm6todosstatic podemserslmchronized comousodobloqueiodainstAnciadejava.lang.Classque
representar essa classe.
Comunicando-se com os objetos atrav6s da espera e notificagno (Objetivo 4.4) E O m6todo wait ( ) permite que um thread diga: "Nio hi nada que eu possa fazer aqui, portanto, coloque-me em seu pool de espera e me avise quando acontecer algo que me interesse". Basicamente, uma chamada await ( )
significa "espere-me em seu pool", ou "quero ser inserido em sua lista de espera".
O m6todo no t i f y
pool
E O m6todo noti fy ( ) ndo pode especificar qual thread em espera deveri ser notificado. E Om6todonotifyAll ( ) funcionadamesmamaneiraquenotify( ),s6queenviaosinalparatodosos
threads que estiverem aguardando no objeto.
fl
Todosostrsm6todos-wait(
que tenha o bloqueio desse objeto.
)/notify( )/notifyall(
) -devemserchamadosdedentrodeum
especifico, e seri necessirio
I
D
execugio do thread
bloqueios sejam
impasse pode ocorrer quando um objeto bloqueado tentar acessar outro objeto bloqueado, que por sua vez esteja tentando acessar o primeiro objeto citado. Em outras palavras, os dois threads estio esperando a liberagio do bloqueio um do outro; ou se.ia, os bloqueios nunca serlo liberados!
tr
O impasse
inadequado.
Nio
tente cri6lo.
Teste individual
Asperguntas
dificil, nio
se
a seguir o ajudarXo a avaliar sua compreensXo sobre o material apresentado nese capinrlo. Se inicialmente achar culpe. Seja otimista. Algumas destas quest6es sio longas e intrincadas, espere ver quest6es longas e intrincadas
no exametamb6m!
l.
Dado:
public class Messager implements Runnable { public static void main(St.ring11 args)
new Thread(new Messager("Wallace") )
private String name; public Messag:er(String name) { this.name = name; } public void runO {
moqc:aol1 ).
message(2);
)
419
corretas)
C Wallace-1 Gromi-t-1 Gromit.-2 Wallace-2 D. cromit-1 cromit-2 E. Gromit-2 Wall-ace-1 Gromit-l Wal-lace-2 H Oc6digoniocompila. G Ocorre umeffo no tempo de execu$o.
2. Dado: public class Letters extends Thread {
nri rral- o Qf ri r
i-
----.19f nalne;
arc lQf rina n:mol t
L
nrrLrl i c T.of
this.name =
name;
public void writeO { System. out.print (name) ; System. out . print (name ) ;
]
public st.atic void main(String[] args) new Letters ( "X" ) .start ( ),. new Letters ("Y") .start( ) ;
)
Qtreremosnoscenficardequeasaidasejaou)O(YYouYY)O!masnuncaXYXYnemqualqueroutracombinaSo.
Quaisdas
void runo { writel;; i synchronized void runO { writeO; } static slmchronized void runO { wriLeO; } void run0 { stmchronized(this) { writeO; } } void runO { stmchronized(Letters.class) { writeO; } i void runO { slmchronized(System.out) { writeo; } } void runO { stmchronized(System.out.class) { writeO; }
3. O seguinte bloco de c6digo cria um Thread usando um alvo Runnable: Runnable target = new MyRunnableO; Thread myThread = new Thread(target);
Quais das seguintes classes podem ser usadas para criar esse alvo , de forma que o c6dtgo arterior compile corretamente?
MyRunnable extend.s Runnable{public void runo {}} MyRunnable extend.s object{public void. runo{}} MyRunnable implements Runnable{public void runO{}} MyRunnable implements Runnabl-e{void runO {}} MyRunnable implements Runnabfe{public void startO{}}
420
Copitulo 9: Threods
4. Dado: 2. class MyThread extends thread { public static voj-d main(String [] args) 3. 4. MyThread t = new MyThread|; 5. t.srarto; 6. System.out.print("one. "); 't . t. start O ; 8. System.out.prj-nt("two. "); 9. ) public void runo { 10. 11. System.out.print("Thread "); 72. ) l-3. )
Qual6 o resultado
desse c6digo?
A
B.
Acompilagofalha.
Ocorre uma exce$o no tempo de execu$o.
3. 4. 5. 6.
t1
public static void main(String [] args) MyThread t = new l'tyThreado; Thread x = new Thread(t); x.startO;
8.
public voi-d run O { . 10. for(int i=0;i<3;++i) { 11. System.out.print(i + ".."); 1.2. )
9
1?
l
)
14.
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.
3. 4.
JAVA
421
s.
; 8. 9. 10. 11. L2.
1?
I
lines)
Thread.currentThreadO.sleep(1000);
o m6todo stat.ic Thread. currentfhread ( ) retornar| uma referencia ao objeto Thread que estiver sendo executado no momento. Qual seri o resultado desse c5digo?
A. Seri exibida cada String das linhas do array, com uma pausa de 1 segundo. B. Ser6 exibida cada String das knhas do array, sem pausa entre elas porque esse m6todo nio
Elt
6 executado em
um objeto
r nread.
C. Seri exibida D.
Esse c6digo
currentThread ( )
nio
thread.
7. Suponhamos que voce tivesse uma classe com duas varieveis private: a e b. Quais dos pares a seguir Podem impedir problemas de acesso simultAneo nessa classe (selecione todos que forem aplic6veis)? '4" public int read(int a, int b) {return a+b}
public B. public public C public public D. public public E. public public H public public
void set(int a, int b) {this.a=a;this.b=b} synchronized int read(int a, int b) {return a+b} slmchronized void set(int a, int b) {this.a=a;this.b=b} int read(int a, int b) {synchronized(a) {return a+b}} void set(int a, int b) {slmchronized(a) {this.a=a;this.b=b}} int read(int a, int b) {s}mchronized(a) {return a+b} } void set(int a, int b) {slmchronized(b) {this.a=a;this.b=bi} synchronized(this) int read(int a, int b) {return a+b} slmchronized(this) void set (int a, int b) {this .a=a; this.b=b} int read(int a, int b) {slmchronized(this) {return a+b} } void set(int a, int b) {synchronized(this) {this.a=aithis.b=b}}
8. Quais dos m6todos abaixo s6o da classe Object. (Marque todas as corretasx
,d notify( );
notifyAll ( ); C isfnterrupted( r;
B. D. slmchronized( );
!.
E.
4rf
int-arrrrni-/ ue!rqvu
I I
\'
422
Copitulo 9: Threods
3. System.out.print("1 "); 4. slmchronized(args) { 5. System.out.print("2 "); 6. try { '7. args.wait0; B. ) 9. catch(InterruptedException e) {} 10. ] 1l-. System. out.print. ( "3 " ) ; L2. ] 13. i
qual seri o resultado
se
tentarmos compilar
,{, SuacompilagXofalhar6porqueaexcegaorllegalMonitorstateExceptiondewait(
nalinhaT.
)nio6manipulada
B. 1.23
c13
D.L
E
2
E. Notempodeexecuglo,elelangar6umaexcegiolllegalMonitor StateExceptionquandotentarentrarno
estado de espera.
Sua
ele
this.
10. Suponhamos que o m6todo a seguir tenha sido apropriadamente sincronizado e chamado por um thread A no objeto B: wait (2000) ;
Depois que
PelaCPI-llr
esse
se
tornar6 candidato
A
B.
Depois que o thread A for notificado, ou ap6s dois segundos. Depois que o bloqueio de B for liberado, ou ap6s dois segundos. Dois segundos ap6s o thread A ser notificado.
segundos ap6s o bloqueio de B ser liberado.
C
I
D. Dois
l. Quais das declarag6es abaixo sio verdadeiras? (Marque todas A O m6todo notify ( ) deve ser charnado em um contexto sincronizado. B. Para chamar wai E ( ) , um objeto deve possuir o bloqueio do thread. C O m6todo notify ( ) 6 definido na classe java.lang.Thread.
as corretas)
D. Quando um thread esdver aguardando como resultado de waitQ, liberari seus bloqueios. E. O m6todo not.i fy ( ) faz com que um thread libere imediatamente seus bloqueios.
Adiferengaentre
12. Dado o cen6rio: Esta classe dever6 permitir que os usu6rios escrevam uma s6rie de mensagens, de forma que cada mensagem seja identificada com a hora e a data, d6m do nome do thread que escreveu a mensagem: public class Logger {
private StringBuilder contents = new StringBuilderO; public void log(String messaqe) { contents . append ( System. currentTimeMillis ( ) ) ; contents.append(" : ") ;
JAVA
423
contents . append (Thread. currentThread ( ) . getName contents . append (message ) ; contents . append
]
("
());
\n" ) ;
poderio
StringBuffer tornar6
E. Sincronizando
F.
13. Dado:
public static slmchronized void main(String[] args) throws InterruptedException { Thread t = new Thread0; t. start O ; Syslem. out.print ( "X" ) ; t.wait(l-0000); System. out.print ( "Y" ) ;
,I
Qual6 o resrltado
desse c6digo?
A
C
Exibexefinaliza.
B. Exibex enuncafinaliza.
ExibexY efinalizaquaseimediatamente.
atraso de 10 segundos entre
D. Exibe xY comum
Y.
E
G
n
Oc6digoniocompila.
4t
E langada uma
' ex@o
no tempo de exeor$o.
{
.
System. out.
print ( "
My'Ihread" ) ;
);
424
Copiiulo 9: Threods
f !rurl!
nfl
n l $ fnn" \
); t.start
)
qual ser6 o resultado?
A. foo
B. MyThread foo
C Mythread bar D. foo bar E. foo bar baz E bar foo G Acompila$oQallariL H E langada uma excegio no tempo de execugio.
15. Dado
public class
ThreadDemo
slmchronized void aO { act.Busy0; i static slmchronized void bO { actBusy0; static void actBusyO {
try
Thread.sleep(1000)
]
) catch (fnterruptedException e) t) public static void main(String[] args) { finaf ThreadDemo x = new fhreadDemoO; final- ThreadDemo y = new ThreadDemoo; Runnable runnable = new Runnable0 { public void runo { j-nt option = (int) (Math.random1 * 4l; switch (option) { case 0: x.ao,' break; case 1: x.b0; break; case 2: y.ao; break; case 3: y.bO; break,'
)
j;
O O
; ;
JAVA
425
as
Quais dos seguintes pares de chamadas a m6todos nunca poderiam ser executadas ao mesmo tempo? (l4arque todas corretas)
threadl, and x.ao em threadl , and x.b0 em thread.l , and y.ao em threadl , and y. b O em threadl , and x.ao em threadl-, and x.bo em Lhreadl, and y.ao em Lhread.l , and y.bo
em
6. Dado o c6digo a seguir, 1. public class Test { 2. public static void maj-n (String [] args) 3. final Foo f = new Foo O ; 4. Thread t = new Thread(new Runnable0 { publ-ic void run ( ) { 5. 6. f.doStuffo; t. ] B. )); 9. Thread g = new ThreadO { public void runo { 10. 11. f.doStuffo;
1
'>
1,4. t. start ( ) ; g. start O ; l-5 . 16. ] 17. ) 1. class Foo { 2. int x = 5,' 3. public void doStuff ( ) { 4. if (x<10) { 5. // nada a fazer 6. try { 7. wait.O; 8. ] catch(InterruptedException ex) { 9. ) else { 10. System.out.println("x is " + x++); 11. if (x >= 1-0 ) t 12. notifyQ;
1?
]
)
]-4.
1s.
16.
)
A. O c6digo
linha
12 da classe
Foo.
426
Copitulo 9: Threods
causa de um erro na linha 7 da classe Foo. causa de um erro na linha 4 da classe Test'
D. O c6digo nio
F.xis5 xis6
17. Dado:
public class TwoThreads { static Thread laurel, hardy; public static void main(String[] args) laurel = new Thread0 { public void run0 { System. out.println ( "A" ) ; try {
hardy.sleep(1000); ) catch (Exception e)
System.
{
(
out.println
. v!
"B" ) ;
:
i
q\rcfam rf e uqrr. nrrlvuu
nrint-ln rarLrlr
I irf-")
);
hardy = new rhread0 { public void run0 i
vJpeurrr.vuu.Pif.rL4
q\rcfam
nrrl-
nrint-ln
l"Tl/)
trY
corretas)
,4. a
B.e
Cc
D.p E.e
Ep
G
A resposta nio pode
ser
Oc6digonSocompila.
JAVA
427
C
e
Gromit-1
est6 correta. Ambos os threads exibirio duas mensagens cada. wallace-1 deve vir antes de wallace-2, deve vir antes de Gromit-2. Fora isso, as mensagens Wallace e Gromit podem vir em
base
qualquer ordem.
E e F estio corretas. Tanto E como F fazem ambos os threads bloquearem no mesmo objeto, o que impedir6 g|! os threads rodem simultaneamente, e garantir|xxYY ou YYx*. E um ponco incomum bloquear em um objeto como system. out, mas 6 perfeitamente vilido, e ambos os threads estio bloqueando no mesmo objeto.
A nio pode garantir nada, uma vez que nio tem sincronizagio. B e D sincronizam em uma instincia da classe Letters - mas como existem duas instincias diferentes no m6todo main ( ) , os dois threads nlo bloqueiam um ao outro e podem rodar simultaneamente,. resultando em saidas como XYXY. C nio vai compilar, pbrque esti tentando sobrescrever run ( ) com um m6todo static, e tamb6m est6 chamando um m6todo nio-stitic a partir de um m6todo estitico. G nio vai compilar porque System. out . class nio existe. Um literal de classe deve comegar com um nome de classe. System. out 6 um campo, e nio uma classe, de forma que System. out. class nio 6 um literal de classe vilido. (Objetivo a.3)
run ( ) v6lido.
um m6todo
sio implementadas,
nlo
publ ic.
4.
se tenta usar o m6todo start ( ) pela segunda vez em um mesmo objeto Thread, o lang*i uma IllegalThreadStateException. @mbora esse componamenro esteja especificado na API, alguns JVMs nio langam uma excegio consistentemente neise caso.) Mesmo se o thread tiver terminado de rodar, ainda 6 invilido chamar start ( ) novamente. A est6 incorreta porque a compilagio teri sucesso. No geral, o compilador Java s6 verifica se existem erros de sintaxe, emyez de erros na l6gica especifica de cada classe. C e D estio incorretas com base na l6gica exposta
acima. (Objetivo4.1)
J.
resposta A est6 incorreta porque a classe Thread implementa a interface Runnable; portanto, na linha 5, Thread pode usar um objeto do tipo Thread como argumento no construtor. B e C estio erradas porque a vari6vel i do loop for comega com um valor igual a 0 e termina com2. E esti incorreta por causa da l6gica do programa que esti desffita acima. (obj +.1) 6.
rnterruptedException. A resposta E est6 incorreta, mas estaria correta se a excegio rnterrupetdException tivesse sido tratada (A 6 precisa demais). B est6 errada (mesmo se a excegio rnterruptedException fosse manipulada)
)
deve declarar que langar6 a excegio
ou o m6todo
printAll
porquetodo c6digoJava, inclusive o m6todomain( ),6 executado emthreads. C est6incorreta. O m6todo sleep ( ) 6 suatic, portanto, mesmo se for chamado em uma instincia, continuari a{etando o thread que estiver sendo executado. (Objetivo 4.2)
7. B e F estio corretas. Se os m6todos forem marcados com slmchronized, os threads obterio o bloqueio do objeto antes de prosseguir. 56 um thread estar6 configurando ou lendo em determinado momento, o que assegura que read ) sempre retorne a soma de um par v6lido.
this
A resposta A
pelo m6todo
read
( ) pertengam ao mesmo
nio foi sincronizada; portanto, ni,o h6 garantias de que os valores somados par. C e D estio erradas; somente objetos podem ser usados na
sincronizagio. E falha; nio 6 possivel selecionar outros objetos (nem mesmo quando um m6todo for declarado com slmchronized. (Objetivo 4.3)
thi
de threads em espera
no objeto especificado.
AsrepostasCrE"GeHestioincorretas. Osm6todos
instAncia
9.
isrnterrupted( ) e interrupt ( ) slom6todosde eyield( ) siom6todosstatic deThread.Dest6erradaporque &Thread.Osm6todossleep( ) synchroni z ed 6 uma palavra<have e a estrutura slmchroni z ed ( ) faz parte da linguagem Java. (Objetivo 4.2) D est6 correta . t e 2 rerio eibidos, mas nio haver6 retorno da chamada a wai t porque nenhum outro thread
nodficar6 o thread principal, portanto,
3
A resposta A
est6
incorreta;
rllegalMonitorstateException
jl
que esse programa
rllegalMonitorStateExceptionnuncaser6langadaj6quewait( ) serifinalizadoemargrdentrodeum
428
Cooitulo 9: Threqqs bloco de c6digo sincronizado pelos argumentos. F est6 errada porque qualquer objeto pode ser usado na sincronizaglo e, al6m disso, this e static nio combinam. (Objetivo 4.4)
10.
se
torne candidato
a ser executado
novamente'
resposta B est6 incorreta porque um thread em espera nio retornar6 para o estado exectt6vel quando o bloqueio for liberado, a menos que uma notificagio ocorra. C est6 errada porque o thread se tornar6 candidato imediatamente ap6s a notificagio. D tamb6m est6 incorreta potqne Jm thread nio sair6 de um pool de espera s6
))devesemPre
A resposta B est6 incorreta porque para chamar wait ( ) , o thread deve possuir o bloqueio do objeto em que waiC ( ) est6 sendo chamido,i nio o contr6rio. C esti erradaporque notify( ) 6 definido em java.lang.object.Eest6erradaporquenotify( ) niofar6comqueumthreadlibereseusbloqueios.O
thread s6 poderi liberi-los saindo do c6Agb sincronizado. F est6 incorreta porque notifyAll ( ) notificar6 rodos os threads que estiverem aguardando um objeto bloqueado especifico e nio todos os threads que estiverem aguardando em qaaQaer objeto. (Objetivo 4.4)
12.
estit,
correta. Sincronizar os m6todos priblicos 6 suficiente paru tornar a classe segura, en6o F 6 falsa. Esta nio ser que algum tipo de sincronizaglo proteja os dados sendo modificados.
B nio est6 correta porque, embora um StringiBuf fer seja sincronizado internamente, podemos chamar append ( ) diversas vezes, e nada impediria que duas chamadas simultAneas a log ( ) misturassem as suas mensagens. C e D nio esteo corretas porque se um m6todo permanecer dessincronizado, ele poderi executar enquanto o outro esti rodando, o que poderia resultar na leitura do conterido enquanto uma das mensagens ainda est6 incompleta, ou em algo pior. (VocA nio vai querer chamar getstring ( ) para o StringBuf ter enquanto ele est6 modificando o tamanho do seu array de caracteres interno.) (Objetivo 4.3)
13.
Illega1Thread.StateException.
a espera fosse
colocada dentro de
t antesde chamar t.waitO, entio elelangauma O m6todo est6 sincronizado, mas nio em L, entlo a excegio ser6langada. um bloco slmchronized (t ) , entAo a resposta correta seriaD.
base na
Se
A resposta B est6 correta. Na primeira linha de main estamos construindo a instAncia de uma classe interna an6nima, estendendo MyThread. Poftanto, o construtor de MyThread ser6 executado e exibiri MyThread. A pr6xima instruEeo de main chama start ( ) na nova instAncia do thread, o que far6 com que o m6todo run ( ) sobrescrito (o m6todo run ( ) definido na classe interna an6nima) seja chamado.
As respostas A, C, D, E, F e G esteo todas incorretas por causa dal6gca do programa que estA descrita acima. (Objetivo4.1)
15. A, F
H. A est6 correta porque os m6todos chamados para a mesma instAncia bloqueiam uns aos outros. F e poderiam acontecer porque m6todos static synctrroni zed da mesma classe bloqueiam uns aos outros, independentemente de qual instAncia foi usada para chamar os m6todos. (I.{1o 6 obrigat6rio que uma instAncia chame m6todos stat.ic; apenas a classe est6 su.ieita a esse requerimento.)
e
H nio
C poderia acontecer porque os m6todos slmchronized chamados para diferentes instincias nio bloqueiam uns aos outros. B, D, E e G poderiam acontecer, porque os m6todos de instAncias e os m6todos static bloqueiam em diferentes objetos, e nio bloqueiam uns aos outros. (Objetivo 4.3)
16.
A resposta E est6 correta porque o thread nio possui o bloqueio do objeto em que chama wai
m6todo fosse sincronizado, o c6digo seria executado sem langar uma excegio.
t(
) . Se
o
a
As respostas A, B, C e D estio incorretas porque o c6digo ser6 compilado sem erros. F esti errada porque
excegXo ser6 langada antes que haja alguma saida. (Objetivo 4.4)
17 .
atual, que 6 ]aurel (embora o m6todo seja chamado usando-se uma refer6ncia a hardy). Isso 6 enganador, por6m, perfeitamente v6lido, e o Thread 1aure1 poderi entrar em suspensio sem exceg6es, exibindo A e C (depois de um atraso de 1 segundo). Enquanto isso, hardy tenta chamar laurel .wait ( ) - mas hardy nio sincronizou em 1aure1, de modo que chamar laurel .wait ( ) causa imediatamente uma IllegalThreadstateException, e assim hardy exibe D, E e F. Embora a ordem da saida seja mais ou menos indeterminada (nio temos como saber se A ser6 exibido antes de D, por exemplo), 6 garrntido que A, C, D, E e F serio exibidos, em alguma ordem - enteo G est6 incorreta.
A, C, D, E e F estlo corretas. Poderia parecer que 1aurel e hardy estio brigando para f.azer o outro s leep O ou wait O mas nio 6 o caso. LJma vez que sleep O 6 um m6todo static, ele afeta o thread
JAVA
429
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)
)
{}
1. 2.
?
class Ins)mc extends Thread { StringBuffer letter; public Inslmc(StringBuffer letter) this.letter = letter;
)
{
4. 5. 6.
'7.
letter.setCharAt(0, temp);
)
20.
2L. public static void main(String [] args) t 22. StringBuffer sb = new StringrBuffer ( "A" ) ; 23 . new Inslmc ( sb) . start O ; 24. new fnslmc (sb) . start ( ) ; 25 . new Ins)mc (sb) . start ( ) ; 26- )
430
Copitulo 9: Threods
.:;
i.
t0
*
.,
,tiir
Desenvolvimento
rt
I
I I a/
P&R
C6digo
Exercicios r6pidos
Teste
lndividuol
'ir,.,
,i
432
Cooftulo
l0:
Desenvolvimento
Voc6 deseia manter as suas classes organizadas. Voc6 precisa ter recursos poderosos pafa as suas classes enconffarem umas as outras. Voc6 quer certificar-se de que, quando estivet procuando por determinada classe, encontari a qlue esti procurando, e n6o outra que por acaso tenha o mesmo nome. Neste capinrlo, iremos explorar alguns dos recursos avangados dos comandos java eiavac.Iremos rever o uso de pacotes emJava, e veremos como procurar por classes que residem em
pacotes.
un cen,lio,
de
pacotet e in$ntgdu
l:;::r::t
7.5 Dado o nome completamente qualifcado de uma classe dbtribuida dentro e oufora dr an arquiao JAR, con$ruir a estrutura de **riadapara essa classe. Dado am exempk de aidigo e um classpath, detenninar se o classpath permitirtl que o cddigo compile con
At6. agora neste livro, n6s provavelmente j5, falamos sobre chamat os comandos agora iremos dar uma olhada mais aprofundada neles.
j avac e j ava
um milhio de vezes;
Compilando com -d
Por padrio, o compilador coloca um arquivo . class no mesmo diret6rio que o arquivo-fonte . j ava. Isso funciona bem para pequenos projetos, mas, quando vocd estiver trabalhando em projetos maiores, ir6 querer manter seus arquivos . j ava separados dos . class (isso aiuda no controle das vers6es, nos testes, no depuramento...). A opgio -d lhe
permitedizeraocompiladoremquediret6rioeledevericolocaro(s)arquivo(s).cl-assquegerar(d
Digamos que voc6 tenha a seguinte estrutura de diret6rios:
significadestino).
myProj
I
ect
| --cdllFFA
I
I
-- MyClass. java
- classes
I
t-O sguinte comandqernitidonodiretoriomyProj ect,iticompilarMyClass . j ava ecolocaroarquivolvblass . cLass resultanre nodiretorio classes. (Obsena$o:istoassumequeMlClassniotenhaumainstrugopadcage;filarernos sobrepacoteseminstantes.)
JAVA5 433
^/l ftrrDT^'i 6^i
j ava
package
com.
wickedlysmart
}
ect
| - - <arrraa
ll
I
I
--com
|-
-wickedlysmart
|
--MyClass.java
| - -ur4DDED ^1 -^^^^ |
ll
|
|
--com
I
|-
-wickedlysmart
|
|
Se
voc6 estivesse
- (Myclass . class vem para c6) no diret6rio source, compilaria MyClass . j ava e colocaria o arquivo MyClass . cf ass
-
resultante
no diret6rio
lido como: "Pata de{inir o diret6rio de destino,volte para o ditet6rio myProj ect e depois v6 para o diret6rio cl-asses, o qual ser6 o seu destino. Entio, compile o arquivo chamado MyClass . j ava. Finalmente, ponha o arquivo MyC 1 a s s . c 1 a s s resultante dentro da estrutura de diret6rios que bata com o seu pacote, neste caso classes,/com/wickedlysmart." Pelo fato de MyClass . j ava estar em um pacote, o compilador sabia que devia colocar o arquivo . class resultante no diret6rio cf asses/com/wickedlysmart.
Esse comando poderia ser
j avac
package
com.
wickedlysmart
ect
I
I - -cnrrrna
--com
I
|-
-wickedlysmart
I
l--uyclass.java
434
Cooitulo
l0:
Desenvolvimento
|
--classes
/classes com/wickedlysmart/t"tyClass. java Neste caso, o compilador criar6 dois diret6rios, chamados com e com/wickedlysmart, nessa ordem, para colocar o arquivo MyClass . class resultante no dirct6io coneto do pacote (com/wickedlysmart,/), o qual o compilador cria dentro do diret6rio.. . /classes existente. javac -d
.
. 6 que, se o diret6rio de destino que vocd especificar nio existit, voc6 receber6 um erro de compilagdo. Se, no exemplo anterior, o diret6rio classes NAO existisse, o compilador diria algo como:
(No
sioopcionais,epodemambastermultiplosvalores.
Vocd deve especiftcar exatamente um arquivo de classe para ser executadq e o comando j ava assume que voc esti falando de um arquivo . cf ass, entao nao especifique a extensio . cl-ass nalinha de comando. Eis um exemplo:
1 e
Deixando os detalhes para depois, esse comando pode ser lido como "crie umapropriedade de sistema chamada myProp defina o seu valor como myValue. Em seguida, abra o arquivo chamado MyCIass . cl-ass e envie para ele dois argumentos String cuios valores seiam x e 1". Vamos dar uma olhada com mais detalhes nas propriedades de sistema e nos argumentos de linha de comando.
Usando as Propriedades de Sistema Java 5 tem uma classe chamada j ava . util . Properties,
seguinte c6digo:
que pode ser usada para se acessarinformag6es persistentes de um sistema, tais como as versdes atuais do sistema operacional, do compiladotJava ou da m6quina virtualJava. Al6m de forneceresse tipo de informagdo pa&iq voc6 podetambdmadicionare obteras suas pr6prias propriedades. Observe o
import java.util.*; public class TestProps { public static void main(StringlJ args) i Properties P = System.getProperties O ; p. setProperty ( "myProp" , "myVa]ue" ) ; p. Iist (System.out) ;
]
Se esse
java
-DcmdProp=cmdval TestProps
os.name=Mac OS
mYProP=myvalug
user. language=en
JAVA
435
java.version=1.5.0
cmdProp=cmdVal
02
retic6ncias (. . .) representam diversos outros pares de nome = valor. (O nome e o valor sio, ds vezes, chamados de Duas propriedades norne = valor foram adicionadas is propriedades do sistema: myProp=myValue foi adicionada atavds do mEtodo setProperty, e cmdProp=cmdVal foi adicionada arraves
opgio -D
a
na linha de comando.
- D, se o seu
Ao usar
forma:
opgio
valor contiver espagos em branco, entlo todo o valor deve ser colocado entre aspas, desta
getProperty ( ) 6 usado para se obter uma fnica propriedade. Pode ser chamado com run s6 argumento (uma String que represente o norne, ou chave), ou pode ser chamado com dois argumentos (uma String que represente o nome, ou chave, e um valor String padrio para set usado como a propriedade caso esta ainda nao exista), Em ambos os casos, getProperty ( ) retotna a propriedade como uma String.
O m6todo
public class CmdArgs { public static void main(StringlJ args) { int x = 0; for(String s : args) System.out.println(x++ + " element = " + s);
)
compilado
java
CmdArgs
a saida ser6
0 element = x 1 element = 1
Como todos os arrays, o indice de args comega no zero. Os argumentos na linha de comando seguem diretamente o nome
daclasse.Oprimeiroargumento6atribufdoaargs[0],osegundoargumento6atribuidoaargs[1],eassimpor
diante, Hnalmente, existe alguma flexibilidade na declaragio do m6todo ma i n ( ) usado Eara se iniciar um aplicativoJava- A ordem dos
modificadoresdemainO podeseralteradaumpoucqoaffrydeStringsnnoprecisasechamarargs
pode ser declarado usando-se
a sinta:<e dos
e,apartirdoJava5,ometodo
vilidas para ma
in
():
static public void main(StringlJ args) public static void main(String... x) static public void main(String bang_a_gongI
teracessoajava.util .HasMap,entioocomandojavaamb6mprecisat6encontrarjava.util.HashMap. Tanto j ava quanto j avac usam o mesmo algoritrno bisico de busca:
436
Copitulo I 0: Desenvolvimento
1. Eles t6m ambos a mesma lista de lugares (diret6rios) onde procuram por classes. 2. Ambos procuram nessa lista de ditet6rios na mesma ordem. 3. Assim que encontram a classe que estavam procurando, eles interrompem a busca por essa classe. 4. 5. 6. 7.
O ptimeiro lugar onde eles procuram
6
No caso de as listas de
busca conterem dois ou mais arquivos com o mesmo nome, o ptimeiro arquivo encontrado ser6 usado. nos diret6rios que contem as classes que v6m com oJ2SE.
Classpaths significam "caminhos de busca de classes". Eles sdo listas de diret6rios nos quais podem ser encontradas
Um classpath pode ser declarado como umavari6vel de ambiente de sistema. O classpath declarado aqui 6 usado por padrio sempre que j ava ou j avac sio chamados.
Ou entlo, o classpath pode ser declarado como uma opg6o de linha de comando paraj ava ou j avac. Classpaths declarados como opg6es de linha de comando substituem o classpath declatado como vari6vel de ambiente, mas s6 persistem durante o tempo que durar a chamadz.
-classpath
foo
especifica dois diret6rios nos quais poder6o ser encontradas classes: / com/ f oo / acct e / com/ f oo. Em ambos os casos, esses diret6rios ficam absolutamente ligados h.ruz do sistema de arquivos, que 6 especificada pela barra inicial. E importante se lembrar que, quando especifica um subdiret6rio, vocd NAO est6 especificando os diret6rios acima dele. Por exemplq na d eclaragdo acima, o ditet6rio / com NAO ser6 usado na busca.
(\)
e o caracter
conuengdes do Unix. Se uocdfor usadio do l%indowq os seus diretrjrios rcparador serd o ponto-e-uirgala 0. M^, nluamente, uod NAO precisani ter
Uma situagio bastante comum ocorre quando j ava ou j avac reclama que nio consegue encontrar um arquivo de classe, e mesmo assim vocd pode ver que o arquivo SE ENCONTP-{ no diret6rio ataal! Ao procurar pot arqwvos de classe, os comandos j ava e j avac nio procuram no diret6rio atual por padrio. Voc6 precisa instrui-los aproctttar ar. A maneira de drzet a j ava ou j avac para procurar no diret6rio atual 6 adicionando um ponto (.) ao classpath:
-classpath
Esse classpath
/com/foo : .
6 idntico ao antettor, EXCETO pelo fato de que o ponto (.) ao final da declangd.o instrui j ava ou j avac a procurar por arquivos de classe tamb6m no diret6rio atual. (Lembte-se de que estamos falando de arquivos de classes quando voc6 est6 dizendo a j avac qual arquivo . j ava compilat, j avac procura no diret6rio atual por padrio.)
Tamb6m
6 imPortante lembrar que os classpaths determinam a busca da esquerdzpara a diteita. Portanto, em uma situagio em que existam classes com nomes duplicados localizadas em diferentes diret6rios nos seguintes classpaths, diferentes resultados irSo oconer:
-classpath
. : / foo : f com
Finalmente, o comando j ava lhe permite abreviar - cf as spath como - cp. A documentagdoJzvz 6 inconsistente sobre se o comando j avac permite ou nio - cp. Na maioria das m6quinas ele permite, mas nao h6 garanias. ^ ^brevi^tnra
Pacotes e a Procura
Quando voc6 comega a colocar classes dentro de pacotes, e depois comega a usar classpaths para encontrar essas classes, as coisas podem se complicar. Os criadores do exame sabiam disso, e tentaram criar um conjunto especialmente diab6lico de quest6es relativas a pacotes / classpath especialmente para confundir voc6. Vamos comegar revisando os pacotes. No seguinte c6digo:
package com.foo;
hj-
O { } i
JAVA
5 437
estamos dizendo que MyClass 6 um membro do pacote com. f oo. Isso significa que o nome totalmente qualificado da classe agota6 com. f oo . MyClass. Depois que uma classe 6 colocada em rrm pa.ote ,^p^rtedo nome totalrnente qualificado referente ao pacote se torna at6mica - ela nunca pode ser dividida. Vocd nio pode-dividi-la na linha de comandq e tamb6m nio pode dividi-la em uma insrrugio import. Vejamos agora como podemos usar com. f oo
.
MyClass
em outra classe:
package com.foo;
import
i mn^rf
com.
d^fi
foo.MyClass;
f^^ * .
/,/ qualquer
funcionarS
mz.hiO; i
)
E f6cil se confundir quando vocd usa instrug6es import. O c6digo acima 6 peffeitamente vdlido. A instrugio import 6 como um nome-c6digo Para o nome totalmente qualificado da classe. Voc define o nome totalmente qualificado da classe com uma instrugio import (ou com um coringa em uma instrugio import do pacote). Ap6s ter definido o nome totalmente qualificado, voc pode usar o "nome-c6digo" no seu caidigo - mas o nome-c6digo est6 sempre se referindo ao nome totalmente qualifi cado. Agora que j6 demos uma revisada nos pacotes, vejamos como eles funcionam em coniunto com classpaths e linhas de comando. Primekamente, comegaremos com a id6ia de que, quando voc est6 procutando por uma classe usando o seu nome totalmente qualificado, esse nome se relaciona intimamente com runa estrutura de diret6rios especifica. Por exemplq em relagdo ao seu diret6rio at:s^J., a classe cujo c6digo-fonte seja
package com.foo;
locdtzada aqui:
.
com/ f oo / MyClass
class
Para poder encontrar uma classe em um pacote, vocC precisa ter um diret6rio em seu classpath que tenha a entrada mais esquerda do pacote (a"raiz" do pacote) como um subdiret6rio. Esse 6 um conceito importante, entao velamos um outro
exemplo:
import com. wickedlysmart . Utils ; class TestClass { void doStuff O { Utils u = new UtilsO; u.doX("argt", "arg2" ) i com.wickedlysmart.Date d =
new com.wickedlysmart.Date O ; d. getMonth ( "Oct" ;
,
nome simples
//
nome completo
wickedlysmart.
importamosonometotalmentequalificadoparaaclasseUtils,enioofizemosparaaclasseDate.Afnicadtfercnga6 que, por termos listado Ut i l- s em uma instrugio import, nio tivemos de digitar o seu nome totalmente qualificado denffo da classe. Em ambos os casos, o pacote 6 com. wickedlysmart. Quando chegar a hora de compilar ou executar
TestCl-ass,
438
Cooftulo
l0:
Desenvolvimento
I I
1.
wickedlysmart
wickedlysmart
chamados
Utils
Finalmente, o diret6rio que tiver todos esses atributos precisa ainda estat acessivel (via um classpath) de uma das duas
seguintes maneiras:
e neo a
2.
(raj_zl
|-
-dire
|-
-aire
|
-airc
-cp dirB:dirB/dirc
Neste exemplo, dirB e dirB/dirC sio caminhos relativos (eles nio comegam com uma barra /). Ambos esses caminhos relativos s6 tem sentido quando o diret6rio atual 6 dirA. Teste ripido! Se o diret6rio atual for dirA, e voc6 estiver procurando por arquivos de classes, e usar o classpath descrito acima, em quais diret6rios ser6 feita a busca?
dirC?
F6cil demais? E quanto i mesma pergunta, mas com o diret6rio atual sendo a ruz (/)? Quando o dttet6tio ataal 6 dttA, enteo dirB e serio usados na busca, mas nio dirA (embre-se, n6s nio especificamos o ditet6rio atual adicionando um ponto O ao classpath). Quando o diret6rio atual6 a raiz, ewmavez que dirB n6o 6 um subdiret6rio diteto da raiz, nio ser6 feita busca em nenhum diret6rio. Ceno, e se o diret6do atual fosse dirB? Novamente, nio serd feita busca em nenhum diret6rio! Isso ocorre porque nio tem um subdiret6rio chamada dirB. Em outras
dirB
dirB.
/ (raiz)
I
--dirA
I
|-
-dirB
|
-airc
JAVAs 439
subditet6rio direto da niz,entdo nunca seri feita busca em dirB. E, repetindo mais uma vez,lm^vez que o ponto (.) nZo foi colocado no classpath, o diret6rio atual s6 entrari na busca se por acaso ele fot descrito em algum outro lugar no classpath (neste caso, dirC).
de
ama
classe
distribuida dentro
ua exenplo
oufora de un arquiao JAk, canstruir a estr*tara de perrnitinl que o aidigo compile con
ArquivosfAReaProcura
Depois que voce criou e testou o seu aplicativo, voc6 poder6 dese)ar "empacot6-lo" para facilitar a sua distribuigio e instalagSo por outas pessoas. Um mecanismo queJava fornece para esse prop6sito 6 o arquivoJAR.JAR significaJava Archive ('ArquivoJava'). Os arquivosJAR sio usados para comprimir dados (de forma semelhante
arquivar dados.
a
Digamos que voc6 tenha um aplicativo que use muitas classes diferentes,localtzadas em diversos pacotes diferentes. Eis uma 6rvore de diret6rios parcial:
faql-
| |
--UseStuff.java
--ws
||
--mYAPP
|-
-uti1s
I
I
I
l--Dates.class
|
(pacote myApp.utits;)
-Conversions. clags
il
|-
-engl-ne
j
|
-r.a.. class
(pacote
myApp. engine,'
--minmax.class
Vocpode cnarumrinico arquivoJARquecontern todos os anquhos de dasses demyApp, emantdrnaestruturade diret6rios de myApp. Umarcz criado essearquiroJAR, elepode sertransferidoparaoutros diret6rios e outros computadores, e todas as dasses no
precise descompactar o arquivoJAR Embora voc
alquvoJARpodedo seracessadasatrav6sdedasspathseusadaspor j ava e j avac.Tirdoissopodeacontecersemquevocd jamais nio precise saber como criar arquivosJAR para o exame, r'amos passar para o diretotio
e em seguida cnat
ws,
j ar:
cd
ws
myApp
OcomandoiarcriaumarquivoJARchamadoMyJar.ia4oqu;zliriconterodiret6riomyApp etodaairvorede
subdiret6rios e todos os arquivos de myApp. Voc6 poder6 examinar o conterido do arquivoJAR com o comando seguinte (isso tamb6m rti.o ca no exame):
ar -tf Myilar. j ar
META_INF/
META- INF/MANIFEST. MF
440
Copitulo
I0:
Desenvolvimento
mvApp/
myApp/
.lr5 score
myApp/uti1s/
myApp/ut i 1slDaLes . clas s
myAPp,/ut i1 s/ Convers ions
.
class
myApp/engine/ myApp/engine/rete
.
class
.c
1as s
Certo, voltemos agora aos assuntos do exame. O processo de se encontrar um arquivoJAR atrav6s do classpath 6 semelhante ao de encontrar um arquivo de pacote em um classpath. A diferenga 6 que, quando voc especifica um caminho para urn arquivo JAR, precisa incluir o nome do arquivo ao final do caminho. Digamos que voc queira compilar
UseStuff.javanodiret6riotest,eUseStuff.javapreciseteracessoaumaclassecontidaemmyApp.jar. Para compilar UseStuf f . j ava, voc6 usaria cd test javac -classpath ws/myApp. jar Usestuff . java
Compare o uso do arquivoJAR ao uso de uma classe em um pacote. Se UseStuf
diret6rio myApp
utiIs,
f . j ava precisasse
usar classes do
e a classe
n6o estivesse em
umJA\
vocd usaria
r./s Usestuf
f . java
Lembre-se de que, ao usar run classpath, o ultimo diret6rio no caminho deve ser o super-diret6rio daruz do pacote. Q'{o exemplo anterior, myApp 6 o dfuet6rio-raiz do pacote myApp . ut i 1 s.) Repare que myApp pode ser o dret6io raiz para mais de um pacote (myApp. utils e myApp. engine), e os comandos j ava e j avac podem, dessa forma, encontrat o que precisarem em diversos pacotes relacionados. Em ouffas palavras, se wg estiver no classpath, e ws for o super-diret6rio de myApp, entao as classes presentes tanto em myApp . ut i l- s quanto em myApp . eng ine serao
encontradas.
o mesmo
niltiplos pacotet
A tituk d.e infomagdq uoci n6o pode usar import, j ava lembre+e, uma inshvgdo inlprrt xd i capa<dz inportar un rinico pacote.
importar
Nio
deJava.
queforne(am //m
nome-cridigo
uendo.
JAVA
5 44I
in$rapdet
Observag6o: No Capinrlo 1, n6s abordamos a maior parte do que estd definido neste obietq mas deixamos as importag6es
lmportag6es Est6ticas
N6s vimos usando instug6es import ao longo de todo o livro. No fim das contas, o finico valor que as instrug6es import tm 6 que elas economizam dtgtagdo e podem tarr' r o seu c6digo mais f6cllde ler. EmJava 5, a instrugio imporf foi aprimoradapan fotnecer capacidades ainda maiores de economia de digitagio... Emtora algumas pessoas argumentem que isso prejudicou a legibilidade. Esse novo recurso 6 conhecido como importagio estitica. As importag5es
est6ticaspodemserusadasquandovoc6desejausarosmembrosstatic deumaclasse.ffo.6podeusaresserecursoem classes da API e nas suas pr6prias.) Eis um exemplo do tipo "antes e depois":
Antes das importag6es est6ticas:
public cl-ass Teststatic { public static void main(StringlJ args) t System. out . print]n ( Integer.lvl,i\X_VALUE ) ; System. out. . println ( Integer. toHexStrj-ng (42) ) ;
1
i
Depois das importag6es est6ticas:
import stat.ic java. lang. System.out; import static java. 1ang. Integer. *;
.i hl'1^'1 rU^ I/UUf LrdDD ^'l --^ r^^n.qf rf i nTmnnrt ICDLOLdLIUTTTLIJUT L I I {
// t // 2
public static void main(String[] args) out.printl-n (MAX VALUE) ; out . prj-ntln (toHexst.ring (42) ) ;
)
//
l t
Ambas as classes produzem 2747 483647
a
mesma saida:
Vamos ver o que est6 acontecendo no c6digo que usa o recurso das importag6es est6ticas:
1.
Embora o recurso seja normalmente chamado de 'lmportagio estitica", a sintaxe DE\IE ser import static segu.ida pelo nome totalmente qualificado do membro stat i c que voc6 deseja importar, ou enteo um coringa. Neste caso, estamos fazendo uma importagio estitica no obieto out da classe System.
2. Nestecaso,poderiamosquererusatdiversosmembrosstaticdaclassejava.lang.Integer.EstainstruEio import stat ic usa o coringa para dtzer"eu quero fazer importagio est6tica de TODOS os membros stat i c
desta classe".
3. 4.
Agora finalmente estamos vendo o beneficio do recurso! Ndo tivemos de digitar System in System.out.prindn! Uau! Em segundo lugar, nio tivemos de digitat o Int.eger em Integer. MAX_VALUE. Assim, nessa linha de c6digo, pudemos usar um atilho para um m6todo static Epanuma constante.
FinaLmente, fazemos mais um atalho, desta vez
p^r
um m6todo da classe
Integer.
esse recurso, mas nio somos os rinicos. Ainda nio estamos convencidos de que a economia de muito pouca digitagd.o valha a pena diante da possibilidade de se tofnaf o c6digo um pouco mais dificil de ler. Entretanto, esse recurso foi pedido por muitos desenvolvedores, de modo que acabou sendo adicionado i linguagem.
442
Cooitulo
l0:
Desenvolvimento
I I
import sEaLic; static import est6incorreto. Cuidado com membros static com nomes ambiguos. Pot exemplo, se fizer uma importagdo est|icapafaa classe Integer e para a classe Long, uma referdncia a MAX-VALUE causar6 um erro de compilaglo' uma l'ez que tanto Integer quanto Long possuem uma constante MAX-VALUE , eJava nio poder6 saber a qual
MAX_VALUE vocd est6 se referindo.
Epossivelfazerwma'tmportagdoest6ticaemrefernciasaobjetosstatic,constaotes(embre-sequeelassio
static
final-).
m6todos
static.
N6s comegamos explorando o comando j avac com mais profundidade. A opgio - d lhe permite colocar arquivos de classes gerados pela compilagio em qualquer diret6rio que quiser. A op96o - d lhe permite especificat o destho dos arquivos
de classes rec6m-criados.
Em segrida, falamos sobre algumas das opg6es disponiveis atrav6s do iniciador de aplicativos j ava. Discutimos a otdem dos argumentos que j ava plde usar, iniluindo [opq6esJ class largument.os] . N6s aprendemos como consultar e afi^liz rptopriedades de sistema no c6digo e na linha de comando, usando a opgio -D.
O t6pico seguinte referiu-se ao tratamento dos argumentos de linha de comando. Os principais conceitos sio que esses colocados em um arcay deStrings, e que o primeiro argumento vai para o elemento 0 do arr y, o segundo ".go-..rtoJriopara o elemento 1 e assim por diante. argumento vai
Passamos para o importante t6pico referente a como j ava e j avac Procuram por outros arquivos de classes quando precisam deler, .oho ambos bs comandos usam o mesmo algoritmo para encontrar essas classes. Existem locais de busca " pr6-definidos pela Sun, e outros locais de busca, chamados classpaths, que sio definidos pelo usu6rio. A sintaxe para ilasspaths no Uni* 6 diferente da sintaxe para classpaths do Windows, e o exame tende a usat a sintaxe do Unix'
O t6pico sobre pacotes veio em seguida. Lembre-se de que, depois que vocd colocar uma classe em um pacote, o seu nome se torna at6mico - em outras palavras, n6o pode ser dividido. Existe um relacionamento intimo entre o nome de pacote totaknente qualificado de uma classe e a estrutura de diret6rios na qual a classe reside.
Os arquivosJAR foram discutidos em seguida. Os arquivosJAR sio usados para comprimir e arquivar dados. Eles podem ser usados para arquivar estruturas arb6reas de diret6rios inteiras em um tinico arquivoJAR. Os arquivosJARpodem ser vasculhados pot j ava e pot j avac.
as
deconvenincia,quereduzanecessidadedesedigitarnomeslongospa:amernbtosstatic
dasclassesquevoc6usar
Exercicios Raipidos
Eis aqui os pontos principais deste capinrlo.
Usando javac e java (Objetivo 7.2) E Use - d para modificar o destino de um arquivo de classe quando
j avac.
o-ruz do pacote i6
E
fl tr
Aopgio
exisa.
java
quandoquisetdefinirumapropriedadedesistema.
As propriedades de sistema consistem de pares de nome = valor que devem ser anexados diretamente ap6s -D, por
j ava -Dmyproperty=myvalus.
tr
16
Procurando com java e javac (Objetivo 7.5) E j ava e j avac usam ambos o mesmo algoritmo P^t^procurat por classes. E A busca comega pelos locais que cont6m as classes que vm com oJ2SE. D Os usu6rios podem definirlocais de busca secund6rios usando classpaths. 0 Padr6es de Classpaths podem ser definidos usando-se vari6veis de ambiente do SO.
JAVA
5 443
E
O
Um mesmo classpath pode definir muitos locais de busca diferentes. Em classpaths do Unix, sio usadas batas (/)
usadas barras invertidas
0 E
D
El
p^x
sepzu:^r
(\).
Em Unix, sio usados dois-pontos (:) panseparar os caminhos dentro de um classpath. No Windows, sio usados
pontos-e-virgulas (r.
Em um classpath, para especificar o diret6rio atual como local de busca, use um ponto Em um classpath , uma vez encontrada uma classe, busca 6 importante.
a busca 6
(.)
E E D
colocada dentro de um pacote, deve ser usado o seu nome totaLnente qualificado.
import
Para que uma classe possa ser localizada, o seu nome estrurura do diret6rio onde ela reside.
El Um classpath pode conter tanto caminhos relativos quanto absolutos. 0 Um caminho absoluto comega com uma / ou uma \. D Apenas o diret6rio final de um dado caminho ser6 vasculhado.
Arquivos fAR (Objetivo 7.5) Q E possivelatmazenar toda uma estrutura atb6rcade diret6rios em um mesmo arquivoJAR. 0 E possivel procurar em arquivosJAR usando-se j ava e j avac. 0 Quando voc6 inclui um arquivoJAR em um classpath, deve incluir nZo somente o diret6rio no qual se localiza o
arquivoJA\
mas o nome desse arquivo tamb6m.
em - . . /
jre/l-ib/
da drvore
lmportag6es Estiticas (Objetivo 7. | ) B Voc6 deve comegar uma instrugio de importagdo estitica desta forma: import static E Vocpodeusarimportagdesestiticasparaciaratalhosparamembrosstatic (vari6veis,constantesem6todos statie) de qualquer classe.
Teste Individual l.
Dadas estas cl:Fses de diferentes arquivos: package xcom,'
import xcom.*; class Needy3 { public static void main(Srringll args) xcom.Useful u = new xcom.UsefulO; System.out.println(u. increment (5) ) ;
)
// linha
{
l"
// Iin}ra
Asaida60.
B. Asaida65.
444
Copitulo
l0:
Desenvolvimento
C. Asafda66. D. Acompilagtrofdha.
E.
estrutura de diret6rios:
| -- Robot.cl-ass
I
I -- .*
|
I
-- Pet.class
-- 'hv
|
-- oos.class
|
1
E o seguinte arquivo-fonte:
^1 ^-^ urdss ^"--^1 ^-^ rYryvrdsE
Robot r;
Dats ^.
Dog d;
)
Qual(is) instrugio(6es) deve(m) ser adiciona(s) para que o arquivo-fonte possa compilar? (1\4arque todas as corretas)
A. package org,. B. j-mport or9.* ; C. package or9.*; D. package org.ex; E. import org. ex. * E package org.ex.why;
,.
3. Dado: 1,. // insira o c6digo aqui 2. class StatTest { 3. public static void main(String[] args) 4. System.out.println(Integer.I4AX_VALUE) 5. l
-1 b.
J
{
;
A. import static java.lang; B. import static java. lang. Integer; C. import static java. 1-ang. Integer. * ; D. import stat.ic j ava. 1ang. Integer. *_VALUE,' E import static java.lang, Integer.MAX_VALUE; E Nenhuma das instrug6es acima usa sintaxe de importagio vilida. 4. Dado: import static java. lang.
System. *
JAVA
445
or
int
x=0
++x
g += _A_V_[xl;
" _A_v_.length;
out.println($);
) )
linha de comando:
java_-A
Qual 6 o resultado?
A- -A B. A. C. -1. D. -A.
E. _-A.
E
G.
Acompilagdofalha.
E langada uma excegio no tempo de execugio.
foo
I
xcom
|
package xcom;
publicclassA{
package xcom;
public class B extends A { } Qual opglo permite que B . j ava compile? $4arque todas as corretas)
,{.
Definir o diret6do atual como xcom
i arr: n Il
'i elra e
depois chamat
B. Definir
B.java
e
depois chamar
xcom/B. java
E. Definir o diret6rio arual como Eest e depois javac -classpath xcom:. B.java
446
public class Stuff i public static final int MY-CONSTANT = 5; public static int doSt.uff(int x) i return (x++)*x;
)
a*
B.
25 30 36
c.
E
D. Acompilagdofalha.
E langada uma exceg6o no tempo de execugio.
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;
package xcom;
class TestXcom { public static void main(Stringll args) g b = new BO; b.doBO; b.goO;
JAVA
5 447
l
Qual opgdq se inserida em / todas as coretas)
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
correas)
.d
B. D. E.
/foo/bar
foo/bar /baz
em /
/bing
/foo/bar/baz
E esta linha de comando fot chamada a parat de / t oo
j avac?
O resultado nlo
previsivel.
I l. Quais afirmativas sio verdadeiras? (Marque todas as corretas) .d O comando j ava pode acessar classes de mais de um pacote, a partir de run mesmo arquivoJAR.
B.
Os atquivos JAR podem ser usados com o comando dtvore de diret6rios J2SE.
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.
public class xit i nrrl-r-lia crrina gluelt (String a, String b) { return a+b;
z
import pkg.*;
c-Lass useKltr t
l^ ELduru -yoid main(String[] args) { -,,L1 vq!f,ru ^r^r:^ String s = new Kit O .gluelt (args [1] , args [2J ) ; System. out.println (s) ;
)
)
a seguinte
estrutura de subdiret6rios:
t--
|
I
--useK].f'.cIass
com
l--Kr-t.uar.lar
Se o
ditet6rio atual for test, e o arquivo pkg/Kit . cl-ass estiver em produzirS,a saida bc? O4arque todas as corretas)
UseKit b c UseKit a b
-cl-asspath com UseKit b c -classpath com:. UseKit b c -classpat,h com/Kit,Jar. jar UseKit b c -classpaLh com/KitJar.jar UseKit a b c -classpath com/Kit,far.jar:. UseKit b c
B,EeFsSoexigidas.AfnicamanekadeseacessaraclasseDog6atrav6sdeF,que6umainstrugiopack^ge,IJmavez que voc6 s6 pode ter uma instrugio package em u1n arquivo-fonte, ter6 de obter acesso is classes Robot e Pet usando instrug6es import. A opgio B acessa Robot, e a opgio E acessa Pet. A, C, D e G est6o incotretas com base no exposto acima. Al6m disso, C
e G usam sintaxe
3.
C e E usam sintaxe correta para importag6es estedcas. A linha 4 nlo est6 usando importag6es esteticas, de modo que o
4 4.
B, D
B est6 correta. Esta questdo estd usando identificadores v6lidos (mas inapropriados e esquisitos), importag6es est6ticas, var-args em main ( ) e l6gica de pr6-incrementagio.
JAVA5 449
A, C, D, E, F
5. eG
Cesticorreta.ParaqueB.javapossacompilar,primeiroocompiladorprecisasercapazdeencontrarB.java.
Depois de encontr6-lo, precisa encontrar tamb6m A. cl-ass. Pelo fato de A. class estar no pacote xcom, o compilador ndo a encontrat| se for chamado a partir do diret6rio xcom. Lembre-se de que - c las spath nio est6 procurando por B . j ava, esta procurando por quaisquer classes de que B . j ava precise (neste caso, A. class). A, B, and D esteo incorretas com base no exposto acima. E esti incorreta porque o compilador nio consegue enconffar
B. j ava. (Objetivo
7.2)
a
6.
A, B, C
7.
um flagde compi-lagio,
eo
B, C
8.
est6 correta. O modificador de acesso publ ic 6 o 6nico que permite que c6digo de fora de um pacote acesse m6todos em tun pacote - independentemente da heranga.
A
9.
get Property
A, B, D, E
e
10. D est6 cotret^. Um - clas spath incluido com uma chamada a j avac substitui o classpath do sistema. Quando j avac esti usando um classpath, ele 16 o classpath da esquerda para a direita e usa a primeira corresponddncia que encontrat.
A, B, C
11.
tambdm pode usar arquivosJAR. C est6 incorreta porqueJARs podem estar mas eles tambEm podem ser acessados se residirem em outros locais. E esti incorreta, os arquivosJARmantm estruturas de diret6rios. (Obietivo 7.5)
j avac
72. Hest6,coteta.
A,C,EeGestioincorretaspeiosimplesfatodequeargsI
J comegaporzero.B,DeFestaoincorretasporquejava
precisa de um classpath que especifique dois diret6rios, um para o arquivo da classe (o diret6rio . ) e um para o arquivo JAR (o diret6rio com). Lembre-se de que para encontrar um arquivoJAR, o classpath deve incluir o nome do arquivo JAR, nio apenas o seu diret6rio (Objetivo 7.5)
450
Copftulo
l0:
Desenvolvimento
,it!,i
Ap6ndice A
Sobre os stqulvos
..
:":
ij: "
452 Ap6ndice A
arquivos disponiveis para donwload, no site wwrv.altabooks.com.br, vdm com o MasterExam (todos os arquivos estZo em ingl6s). O software 6 ficil de instalar em qualquer computadorWindows 98/NT/2000, e para que os recursos do MasterExam possam ser acessados ele precisa ser instalado. Para registrar-se para um segundo MasterExam, basta clicar no link Bonus Material da pigrna principal e seguir as instrug6es para acessar o registro online.
Os
Requisitos do sistema
O software requer o \X/indows 98 ou superior, o Internet Explorer 5.0 ou superior instalagio completa.
e 20
MasterExam
O MasterExam the fornecer6 uma simulag6o do exame real. A quantidade e os tipos de perguntas al6m do tempo permitido foram definidos para ser uma representagio precisa do ambiente do exarne. Voc ter6 a opgdo de fazer um exame com o livto aberto, incluindo dicas, referncias e respostas; um exame com o livro fechado; ou a simulaqio MasterExam com tempo definido, Quando voc6 iniciar o MasterExame, um rel6gio.ligrtal apatecer|no canto superiot esquerdo da sua tela. O rel6gio contjnuat6,acontagem tegressivaatzero a menos que voc6 selecione terminato exame antes que o tempo expire. Pata se registar a fim de teceber outro MasterExam, simplesmente clique no link Bonus MateialdapAgjna principal e siga as instrugdes para o rcg1svo on-l.ine graruiro.
Aiuda
Um atquivo de ajuda 6 fornecido por meio do botio Help que se encontra no canto inferior esquerdo da p6gina principal. Os recutsos de ajuda individual tamb6m est6o disponfveis no MasterExam e no treinamento on-line da LearnKey.
Removendo instalag6es
O MasterExam ser6 instalado em sua unidade de disco rigrdo. A fim de obtet melhores resultados no que diz respeito remogio de programas, use as opg6es Iniciar I Programas I LearnKey I Desinstalar para remover o MasterExam.
Se quiser remover o Real Player, use o icone Adicionar/Remover Programas de seu painel de controle. Voc tamb6m pode remover os pfogramas de treinamento da LearnKey nesse local.
Suporte t6cnico
Para enviar perguntas relacionadas ao
contefdo t6cnico do livro elet6nico ou do MasterBxam, visite o site www.osborne.com ou mande uma mensagem (em ingls) de correio eletr6nico para customer.sewice@macgraw-hill.com. Clientes fora dos Estados Unidos, devem enviar a mensagem para international-cs@mcgraw-hill.com.
JAVA2 453
Este livro foi impresso nas o{icinas gr6ficas da Editora Vozes Ltda., Rua Frei Luis, 100
Pet6polis, RJ,